Giter Site home page Giter Site logo

apple / swift-openapi-generator Goto Github PK

View Code? Open in Web Editor NEW
1.2K 111.0 87.0 1.42 MB

Generate Swift client and server code from an OpenAPI document.

Home Page: https://swiftpackageindex.com/apple/swift-openapi-generator/documentation

License: Apache License 2.0

Swift 98.58% Dockerfile 0.05% Shell 1.32% HTML 0.04%
ios-swift openapi server-side-swift swift plugin swiftpm

swift-openapi-generator's Introduction

Swift OpenAPI Generator

Generate Swift client and server code from an OpenAPI document.

Overview

OpenAPI is a specification for documenting HTTP services. An OpenAPI document is written in either YAML or JSON, and can be read by tools to help automate workflows, such as generating the necessary code to send and receive HTTP requests.

Swift OpenAPI Generator is a Swift package plugin that can generate the ceremony code required to make API calls, or implement API servers.

The code is generated at build-time, so it's always in sync with the OpenAPI document and doesn't need to be committed to your source repository.

Features

  • Works with OpenAPI Specification versions 3.0 and 3.1.
  • Streaming request and response bodies enabling use cases such as JSON event streams, and large payloads without buffering.
  • Support for JSON, multipart, URL-encoded form, base64, plain text, and raw bytes, represented as value types with type-safe properties.
  • Client, server, and middleware abstractions, decoupling the generated code from the HTTP client library and web framework.

To see these features in action, check out the list of example projects.

Usage

Swift OpenAPI Generator can be used to generate API clients and server stubs.

Below you can see some example code, or you can follow one of the step-by-step tutorials.

Using a generated API client

The generated Client type provides a method for each HTTP operation defined in the OpenAPI document1 and can be used with any HTTP library that provides an implementation of ClientTransport.

import OpenAPIURLSession
import Foundation

let client = Client(
    serverURL: URL(string: "http://localhost:8080/api")!,
    transport: URLSessionTransport()
)
let response = try await client.getGreeting()
print(try response.ok.body.json.message)

Using generated API server stubs

To implement a server, define a type that conforms to the generated APIProtocol, providing a method for each HTTP operation defined in the OpenAPI document1.

The server can be used with any web framework that provides an implementation of ServerTransport, which allows you to register your API handlers with the HTTP server.

import OpenAPIRuntime
import OpenAPIVapor
import Vapor

struct Handler: APIProtocol {
    func getGreeting(_ input: Operations.getGreeting.Input) async throws -> Operations.getGreeting.Output {
        let name = input.query.name ?? "Stranger"
        return .ok(.init(body: .json(.init(message: "Hello, \(name)!"))))
    }
}

@main struct HelloWorldVaporServer {
    static func main() async throws {
        let app = Vapor.Application()
        let transport = VaporTransport(routesBuilder: app)
        let handler = Handler()
        try handler.registerHandlers(on: transport, serverURL: URL(string: "/api")!)
        try await app.execute()
    }
}

Package ecosystem

The Swift OpenAPI Generator project is split across multiple repositories to enable extensibility and minimize dependencies in your project.

Repository Description
apple/swift-openapi-generator Swift package plugin and CLI
apple/swift-openapi-runtime Runtime library used by the generated code
apple/swift-openapi-urlsession ClientTransport using URLSession
swift-server/swift-openapi-async-http-client ClientTransport using AsyncHTTPClient
swift-server/swift-openapi-vapor ServerTransport using Vapor
swift-server/swift-openapi-hummingbird ServerTransport using Hummingbird
swift-server/swift-openapi-lambda ServerTransport using AWS Lambda

Requirements and supported features

Generator versions Supported OpenAPI versions Minimum Swift version
1.0.0 ... main 3.0, 3.1 5.9

See also Supported OpenAPI features.

Supported platforms and minimum versions

The generator is used during development and is supported on macOS and Linux.

The generated code, runtime library, and transports are supported on more platforms, listed below.

Component macOS Linux iOS tvOS watchOS visionOS
Generator plugin and CLI ✅ 10.15+ ✖️ ✖️ ✖️ ✖️
Generated code and runtime library ✅ 10.15+ ✅ 13+ ✅ 13+ ✅ 6+ ✅ 1+

Documentation and example projects

To get started, check out the documentation, which contains step-by-step tutorials.

You can also experiment with example projects that use Swift OpenAPI Generator and integrate with other packages in the ecosystem.

Or if you prefer to watch a video, check out Meet Swift OpenAPI Generator from WWDC23.

Footnotes

  1. Example OpenAPI document (click to expand)
    openapi: '3.1.0'
    info:
      title: GreetingService
      version: 1.0.0
    servers:
      - url: https://example.com/api
        description: Example service deployment.
    paths:
      /greet:
        get:
          operationId: getGreeting
          parameters:
            - name: name
              required: false
              in: query
              description: The name used in the returned greeting.
              schema:
                type: string
          responses:
            '200':
              description: A success response with a greeting.
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Greeting'
    components:
      schemas:
        Greeting:
          type: object
          description: A value with the greeting contents.
          properties:
            message:
              type: string
              description: The string representation of the greeting.
          required:
            - message
    
    2

swift-openapi-generator's People

Contributors

andrewse02 avatar arthurcro avatar bfrearson avatar czechboy0 avatar denil-ct avatar dpasirst avatar gjcairo avatar glbrntt avatar kyle-ye avatar lennartkerkvliet avatar macblazer avatar mahdibm avatar mbrandonw avatar michalsrutek avatar miguel-arrf avatar mt-hodaka avatar paraipan9 avatar rnro avatar sajjon avatar simonjbeaumont avatar takeshi-1000 avatar tib avatar yanniks avatar yim-lee avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swift-openapi-generator's Issues

Include the user-provided operation description in the generated doc comment

My openapi.yaml looks like this:

openapi: '3.0.3'

paths:
  /:
    get:
      description: Returns metadata about the API, including version.
      operationId: getRoot
      parameters:
      responses:
        '200':
          description: A success response with information about the API.

When I generate docs in Xcode, I get some, but “Instance Method getRoot(_:)” has this blurb: “Operation getRoot performs GET on /”.

As I understand it, description: can be Markdown, so I’m not sure of the best way to incorporate it into DocC, but I feel like that’s an important thing to support.

Support multiple request body content types

Similar to #6 but for request content.

Should be simpler, as it doesn't require the integration with the Accept header. It'll just be an extension of the existing N=1 media types into N>1. The generated type is already an enum though, so shouldn't require structural changes, just handling all the supported media types instead of picking the first "best" one (like the generator does today).

Support OpenAPI 3.1

Today, we assume OpenAPI 3.0.x, but we should explore how we can also support 3.1, and continue to support both in parallel for some time, as 3.0.x is still the most adopted one out in the wild.

Consider the Client being generic over Transport/Middlewares

Might result in better performance as it'd avoid existentials in the transport and middlewares properties.

However, we also should keep in mind the use case where the exact transport and set of middlewares used at runtime is not known at build time (e.g. by adding a middleware dynamically based on an environment variable, choosing a transport based on an env var - testing vs live, etc).

Consider flattening allOf + 1 subschema as a way to add descriptions to properties

OpenAPI 3.0.x doesn't support adding descriptions to object properties, only to schemas.

That's not a problem when the schema is an inline one, as the description of the inline schema simply becomes the description of the property (works today).

However, when the property references a schema in #/components/schemas/..., there's no room to put a description on the property.

For example, consider:

components:
  schemas:
    Route:
      type: object
      properties:
        from:
          $ref: '#components/schemas/Location'
        to:
          $ref: '#components/schemas/Location'
      required:
        - from
        - to

Above, one might reasonably want to document the from and to properties differently, but can't in OpenAPI 3.0 (however, it is possible to add descriptions to $ref schemas in OpenAPI 3.1).

A commonly used workaround, even recommended by the JSON schema contributors, is to wrap the reference in an allOf inline schema, and add the property there, making it:

components:
  schemas:
    Route:
      type: object
      properties:
        from:
          description: The location from which the traveler departs.
          allOf:
            - $ref: '#components/schemas/Location'
        to:
          description: The location to which the traveler arrives.
          allOf:
            - $ref: '#components/schemas/Location'
      required:
        - from
        - to

Today, the generator produces a struct for the allOf, meaning that all access to the nested schema is with an extra property access.

Since this is an officially recommended workaround for a design issue in OpenAPI, we could have the generator flatten that allOf level when it only contains a single child schema, and only use the description from the all of, resulting in being able to add a comment on a property that references a reusable type.

The main question here is:

  1. Should it be default behavior?
  2. Should it be possible to opt-out of this shortcut?
  3. Should it be opt-in only?

Choose the serialization method based on content type

Currently, the generator chooses the serialization method (JSON, text-based, or raw data) based on the type used in the request/response body. Most of the time, that works correctly, but there are some corner cases, such as:

  • content type: application/json, the body is a fragment string (as opposed to a JSON container, like an object or an array).

In this case, we today serialize it using LosslessStringConvertible, and end up without the quotes. That's only correct if the content type is text/plain (and in fact was just fixed in apple/swift-openapi-runtime#9).

Action: add logic for choosing the serialization method based on the content type, instead of trying to deduce it from the Swift type.

Whilst implementing this change, I think that we may want to revisit the encoding logic, since I think the knowledge of whether to encode a value as binary data, JSON, or plain text, is at the place where the content-type is set, but we'll defer that to a subsequent PR.

From: apple/swift-openapi-runtime#10

Document the release process

Should probably be another docc article in the Contributing section.

Should include how to correctly stage changes to the runtime library, optionally to transports, and at which point the generator can update its dependencies and how to pick the next version (major/minor/patch).

Consider moving constants from the generator to the runtime

Currently we have symbols defined in the runtime package that the generator needs to generate code for.

In order to facilitate this, the generator package contains a Constants file where some of the symbol names are declared as strings.

There are quite a number of such symbols. These are found in Constants.swift.

These could be colocated along with the symbol itself to make it super clear. For example, if we defined an underscored @_spi(Generator) enum SymbolNames {} in runtime and then whenever we are declaring something in runtime that we'll need to generate by name, we can colocate the symbol like this:

+ extension SymbolNames {
+     public static let APIProtocol = "APIProtocol"
+ }
  public protocol APIProtocol { ... }

Some things to consider:

  • this would introduce a build-time dependency from the generator CLI/plugin on the runtime library, which doesn't exist today (the generator package depends on the runtime package for tests, and as a way to communicate which versions work together)
  • the runtime library would expand scope from only being used by the generated code, to also being used by the generator code

Emit errors processing .yaml files that Xcode can display

I got the following error in the build transcript:

Showing All Messages
Error: dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid YAML.", underlyingError: Optional(19:3: error: scanner: while scanning for the next token in line 19, column 3
found character that cannot start any token:
  	post:
  ^)))

It would be great if this were something Xcode could parse and show as an error in the error navigator.

Emit JSON path reference in comments for all generated types

This already works for many types and properties, but not for all.

We should ensure that all content from the OpenAPI doc generated in Swift includes a comment linking it back to its original JSON path in the OpenAPI doc.

For example:

/// - Remark: Generated from `#/paths/\/pets\/{petId}/patch/requestBody/content/application\/json/schema`.

Support external JSON references

Support external JSON references to allow breaking up a large doc into smaller ones.

"External" can mean either:

  1. another file on local disk
  2. a remote file

To start, let's consider other local files first, as remote files might have other implications (security, privacy, etc).

Generate convenience initializers that flatten some nested scopes

Creating input types is quite verbose because they contain multiple nested enums. (e.g. .ok(.init(headers: .init(), body: .json(...)))).

It may be useful to generate static helper functions on the output type so it's possible to write .ok(body: .json(...)) instead, or even .ok(...) directly.

We have to be careful here, though, as it's possible to go very far and generate a ton of conveniences, that end up making the API more difficult to understand. So will require a well thought-out proposal first, describing which high-value conveniences we should generate, and how we evaluate further requests.

We also need to keep in mind that the generator complexity shouldn't be significantly increased with this work, as per https://github.com/apple/swift-openapi-generator/blob/main/Sources/swift-openapi-generator/Documentation.docc/Articles/Project-scope-and-goals.md#principle-reduce-complexity-of-the-generator-implementation

Empty string enum value breaks the generator

We've seen a string enum definition like:

type: string
enum:
  - ""
  - foo
  - bar

Note the empty string as the first case.

Currently, the generator breaks on it, but we should be able to handle it. Somewhat related to #21.

Use a swift-syntax based renderer

The generator currently uses a string-based renderer, but we should switch over to using swift-syntax under the hood to render the generated Swift code.

swift-syntax is already in the dependency graph, brought in by swift-format.

The work should be very self-contained, the renderer is a protocol that the new swift-syntax-based renderer type would adopt.

Replace dynamic type checks with generic overloads

A recent PR to the runtime library was fixing an issue for the transcoding of types that have an additional protocol conformance. This was done with a dynamic as? type check and an as! force cast.

In a comment, we discussed a better way: using a specialization and letting the compiler do the work: apple/swift-openapi-runtime#9 (comment).

We approved the PR as-was because it matched the pattern we were using in the rest of the code base and was a targeted fix for an issue.

This issue is to track revisiting the dynamic type checking pattern in all the places its used in the runtime library and adopting the pattern in the linked PR comment.

Revisit server1/server2 and case1/case2 and value1/value2 naming in Servers, oneOf, allOf/anyOf

Revisit server1/server2 and case1/case2 and value1/value2 naming in Servers, oneOf, allOf/anyOf.

We don't like the names, we should derive better unique names, e.g. based on:

  • Swift type
  • JSON path
  • user-provided description
  • something else inherent

We just have to keep in mind that in many cases (e.g. inline schemas), we don't have a unique name to use, and might need to derive one - there we need to watch out for potential naming conflicts.

Dry run option on the CLI

Since the CLI overwrites existing files in --output-path, we could have a --dry-run option that just prints what it would have done.

Make request/response bodies an async sequence of bytes

For simplicity, initially the type holding the raw request and response body data is Foundation.Data, but that prevents use cases where large amounts of data need to be sent/received if the memory limit of the process is low.

What should be possible: a uploading/downloading large (multi-GB) files without buffering them into memory on either client/server ends.

Support recursive types

Currently the package does not support recursive types. Should this be possible? Maybe I'm doing something wrong. otherwise, I would propose to add this constraint in the docs. I have this use case due to Server Driven UI. This results in components or actions that can be embedded in each other.

Errors:

  • Value type 'x' cannot have a stored property that recursively contains it
  • Value type 'x' has infinite size

Issue with paths ending with a slash

Context:
Hi! I was testing creating a Client with the following openapi.yaml file:

openapi: 3.0.2
info:
  title: FastAPI
  description: Example app
  version: 0.1.0
servers:
  - url: http://127.0.0.1:8000
    description: Localhost deployment.
paths:
  /items/:
    get:
      tags:
        - Items
      summary: Read Items
      operationId: read_items_items__get
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                title: Response Read Items Items  Get
                type: array
                items:
                  $ref: "#/components/schemas/Item"
    post:
      tags:
        - Items
      summary: Create Item
      operationId: create_item_items__post
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Item"
        required: true
      responses:
        "200":
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Item"
        "422":
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HTTPValidationError"
components:
  schemas:
    HTTPValidationError:
      title: HTTPValidationError
      type: object
      properties:
        detail:
          title: Detail
          type: array
          items:
            $ref: "#/components/schemas/ValidationError"
    Item:
      title: Item
      required:
        - name
        - price
      type: object
      properties:
        name:
          title: Name
          type: string
        description:
          title: Description
          type: string
        price:
          title: Price
          type: number
        tax:
          title: Tax
          type: number
        tags:
          title: Tags
          type: array
          items:
            type: string
          default: []
    ValidationError:
      title: ValidationError
      required:
        - loc
        - msg
        - type
      type: object
      properties:
        loc:
          title: Location
          type: array
          items:
            anyOf:
              - type: string
              - type: integer
        msg:
          title: Message
          type: string
        type:
          title: Error Type
          type: string

Here's my main.swift (this is for a Swift Package):

import OpenAPIRuntime
import OpenAPIURLSession

let client = Client(
    serverURL: try Servers.server1(),
    transport: URLSessionTransport()
)

let response = try await client.read_items_items__get(
    .init()
)


switch response {
case .ok(let okResponse):
    switch okResponse.body {
    case .json(let greeting):
        print(greeting)
    }
case .undocumented(statusCode: let statusCode, _):
    print("🥺 undocumented response: \(statusCode)")
}

If I inspect the generated file for the Client, here's part of the code:

public func read_items_items__get(_ input: Operations.read_items_items__get.Input) async throws
        -> Operations.read_items_items__get.Output
    {
        try await client.send(
            input: input,
            forOperation: Operations.read_items_items__get.id,
            serializer: { input in
                var request: OpenAPIRuntime.Request = .init(path: "/items", method: .get)
(...)

Shouldn't the path be /items/ instead of /items?

In my specific use case, my server is a FastAPI server, and this is what I get when I run the package (with command: swift run --package-path Swift-With-FastAPI-Package):

127.0.0.1:63403 - "GET /items HTTP/1.1" 307 Temporary Redirect
INFO:     127.0.0.1:63403 - "GET /items/ HTTP/1.1" 200 OK

The output of the swift run (...) command is the expected, however I would like to avoid the redirect in the Server. Is this the expected behaviour?


$ swift --version
swift-driver version: 1.75.2 Apple Swift version 5.8 (swiftlang-5.8.0.124.2 clang-1403.0.22.11.100)
Target: arm64-apple-macosx13.0

Operating system: macOS 13.2

$ uname -a
Darwin XPQFF7Q9JC 22.3.0 Darwin Kernel Version 22.3.0: Thu Jan 5 20:50:21 PST 2023; root:xnu-8792.81.2~2/RELEASE_ARM64_T8112 arm64

Support variable generation and template expansion in serverURL

We should support variable expansion in the Server Object: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#server-variable-object

The generated Servers enum already uses static methods to prepare for this:

enum Servers {
  static func server1() throws -> URL
}

Supporting variables would mean generating e.g.

enum Servers {
  static func server2(environment: String, foo: Int, bar: Components.Schemas.Something) throws -> URL
}

Server should validate Content-Type header

Currently, a generated server does not validate the content-type header before it tries to parse the request body contents, which means that if incorrect request body data is sent, the error message will be thrown by e.g. the JSONDecoder, and might be a bit cryptic, versus a clear error thrown by a method like validateContentTypeIfPresent does for responses bodies.

Converting strings into Swift safe names can lead to conflicts

An example of a schema that today the generator produces non-compiling Swift code for, as both enum cases are named _1.

type: string
enum:
  - "+1"
  - "-1"

Some ideas of solving this:

  • word-ify common symbols, so instead of turning + into _, turn it into plus, ending up with plus1 and minus1 here

It's likely that no solution will completely solve this problem, as it's always going to be possible to create a conflict, as not all characters that are valid as an OpenAPI name are valid as Swift identifiers, so some mapping is necessary.

Support default values for schema properties

The generator skips the default values for Components.Schemas. It would be nice to have a default value for the property itself and in the initializer. I made an example:

Spec example:
Screenshot 2023-06-13 at 20 22 25

Current:
Screenshot 2023-06-13 at 20 20 58

Desired:
Screenshot 2023-06-13 at 20 21 52

Support deprecated annotations

Support for generating deprecated annotations for things deprecated in the OpenAPI document.

This will allow OpenAPI doc authors to deprecate types and properties in the OpenAPI doc, and the generated Swift code will emit warnings for them.

Failed to reproduce "Generating a client in an Xcode project" example

Commit hash: 37255b7

Context: I just wanted to try example, but build fails.

Steps to reproduce:

  1. Create new Xcode project (iOS app, Swift, SwiftUI)
  2. Follow steps from tutorial including Section 1 and Section 2
  3. Build fails on Step 3 of Section 3

XCode Version 14.3 (14E222b)

$ swift --version
swift-driver version: 1.75.2 Apple Swift version 5.8 (swiftlang-5.8.0.124.2 clang-1403.0.22.11.100)
Target: arm64-apple-macosx13.0
$uname -a
Darwin MacBook-Pro-Aleksej.local 22.5.0 Darwin Kernel Version 22.5.0: Mon Apr 24 20:52:24 PDT 2023; root:xnu-8796.121.2~5/RELEASE_ARM64_T6000 arm64

Consider adding typealiases for Operations.*.Input.* types for referenced types

When all types are inline, you get consistent names for all operations:

  • Operations.<operationID>.Input.Path
  • Operations.<operationID>.Input.Query
  • Operations.<operationID>.Input.Headers
  • Operations.<operationID>.Input.Cookies
  • Operations.<operationID>.Input.Body

And similar for Operations.<operationID>.Output.

When using reusable types for requestBody, parameter, and response, however, these can point directly to e.g. Components.RequestBodies.Foo, etc, which breaks the symmetry.

Consider emitting a typealias here that would make all the names predictable, e.g.

enum Operations {
  enum <operationId> {
    struct Input {
      typealias Body = Components.RequestBodies.Foo
    }  
  }
}

Support object schemas in query items

We should support encoding non-primitive values as query items, which is prescribed by OpenAPI.

        - name: fields
          in: query
          description: Pairs of field=value to filter results
          required: true
          schema:
            type: object
            additionalProperties:
              type: string

The above example also uses additionalProperties, but I think that shouldn't change the story around serializing object structs into query items.

Somewhat related to #18.

This issue was also encountered in #83.

Recurse when calculating whether an init param is required

Having even one optional header means we have to explicitly provide them when constructing a response - that's not great.

For example:

return .ok(.init(body: .json(.init(foo: "bar"))))

Now, even when we don't want to provide any headers, we'll have to provide the param.

This should only happen when there is at least one required header.

Make Input/Output (and nested) types Equatable/Hashable

We should make the generated operation-specific Input/Output (and nested) types Equatable.

A few drivers:

  • easier testing
  • easier caching of hash(Input) -> cached Output
  • more consistent with most of the other generated types

Create an Unresolved* typealias for all supported OpenAPI types

For easier handling of potentially referenceable OpenAPI types in the generator, e.g. Either<JSONReference<JSONSchema>, JSONSchema>?, we should create a typealias called Unresolved* (e.g. UnresolvedSchema). This is already present for some of the types, but not all.

The full list right now is:

  • schemas
  • parameters
  • (response) headers
  • request bodies
  • responses

Attach more context information to errors thrown in middlewares

Currently, when errors are thrown in a transport, we attach as much context as we have at that point (the Input value, operationId, etc). But when an error is thrown in a middleware, we don't attach some info that we could, so let's fix that. Will make debugging errors thrown by middlewares quicker, if all the right context is already attached and logged.

Support base64 encoded data (type: string + format: byte)

Currently, only type: string + format: binary is supported, and represents raw data (an octet stream).

OpenAPI also supports base64-encoded data, represented as the following JSON schema:

type: string
format: byte

The generated type for it should also be Foundation.Data (same as for format: binary), but as part of serialization/deserialization, the extra step of base64 coding needs to be added.

Testing: verify that both a whole request/response body being application/json with the contents of a base64-encoded string (use case 1), but also as a nested field in a JSON object (use case 2), both are pretty common.

Revisit structure at runtime of allOf/oneOf/anyOf

Structure at runtime of allOf/oneOf/anyOf - today, we use nesting of structs to represent the nested schemas.

Could be represented as a single flattened struct that conforms to multiple protocols, one for each nested type, or some other way.

Things to keep in mind:

  • lack of nested protocols in Swift
  • cost of using existentials vs concrete types

Feature "Unexploded query params" is not supported.

Using an Open API file that has a parameter with explode: false results in a warning of

Feature "Unexploded query params" is not supported, skipping [context: foundIn=Operations.launcher_list.Input.Query (#/paths/2.2.0/launcher/GET/query)/launcher_config__ids]

false values appear to be listed as unsupported in the documentation.
image

  /launcher/:
    get:
      operationId: launcher_list
      parameters:
        - in: query
          name: launcher_config__ids
          schema:
            type: array
            items:
              type: integer
          description: Comma-separated launcher config IDs.
          explode: false
          style: form
      responses:
        "200":
          description: A success response with a greeting.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Greeting"

I am open to creating a PR, but this is my first time using Open API and would need guidance.

Build Error: Command PhaseScriptExecution failed with a nonzero exit code

Issue: Build Error
Fault Code: Command PhaseScriptExecution failed with a nonzero exit code
Environment: Xcode 15 beta (15A5160n)
OpenAPI Spec: https://github.com/meraki/openapi/blob/master/openapi/spec3.json

Summary:
Build error occurs when generating Cisco Meraki API spec using plugin.

Swift OpenAPI Generator configuration:

  • OpenAPI document path: */openapi.yaml
  • Configuration path: */openapi-generator-config.yaml
  • Generator modes: types, client
  • Output file names: Types.swift, Client.swift
  • Output directory: */SourcePackages/plugins/TestingOpenAPI.output/TestingOpenAPI/OpenAPIGenerator/GeneratedSources
  • Diagnostics output path: <none - logs to stderr>
  • Current directory: */TestingOpenAPI
  • Is plugin invocation: true
  • Additional imports:

Plugin Version:

swift-openapi-generator: 0.1.1
swift-openapi-runtime: 0.1.2
swift-openapi-urlsession: 0.1.0

Error:

12592:3: expected name in member access
Command PhaseScriptExecution failed with a nonzero exit code

Context:

12563 : /// Parsed a raw value that was not defined in the OpenAPI document.
12564 : case undocumented(String)
12565 : public init? ( rawValue : String ) {
12566 : switch rawValue {
12567 : case "":
12568 : self = .
12569 : case "full":
12570 : self = .full
12571 : case "half":
12572 : self = .half
12573 : default:
12574 : self = .undocumented(rawValue)
12575 : }
12576 : }
12577 : public var rawValue: String
12578 : {
12579 : switch self {
12580 : case let .undocumented(string):
12581 : return string
12582 : case .:
12583 : return ""
12584 : case .full:
12585 : return "full"
12586 : case .half:
12587 : return "half"
12588 : }
12589 : }
12590 : public static var allCases: [duplexPayload]
12591 : {
12592 : [., .full, .half]
12593 : }
12594 : }

Notes:

  • Many "similar" errors when generating the Netbox 3.5 OpenAPI spec. Will attach as another comment once documented.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.