diff --git a/README.md b/README.md index 4163590cb..88104a01f 100644 --- a/README.md +++ b/README.md @@ -8,60 +8,171 @@ Generate Swift client and server code from an OpenAPI document. ## Overview -[OpenAPI][openapi] is an open specification for documenting HTTP APIs. +[OpenAPI][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. -## Repository organization +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. -The Swift OpenAPI Generator project is split across multiple repositories to enable extensibility and minimize dependencies in your project. +## 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][examples-generator]. + +## 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][tutorials-generator]. + +### Using a generated API client + +The generated `Client` type provides a method for each HTTP operation defined in the OpenAPI document[^example-openapi-yaml] and can be used with any HTTP library that provides an implementation of `ClientTransport`. + +```swift +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) +``` -**swift-openapi-generator** ([source][repo-generator], [docs][docs-generator]) provides the plugin. +### Using generated API server stubs -**swift-openapi-runtime** ([source][repo-runtime], [docs][docs-runtime]) provides a library with common types and abstractions used by the generated code. +To implement a server, define a type that conforms to the generated `APIProtocol`, providing a method for each HTTP operation defined in the OpenAPI document[^example-openapi-yaml]. -> See the generator in action in [Meet Swift OpenAPI Generator](https://developer.apple.com/wwdc23/10171) from WWDC23. +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. -Choose one of the transports listed below, or create your own by adopting the `ClientTransport` or `ServerTransport` protocol: +```swift +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][repo-generator] | Swift package plugin and CLI | +| [apple/swift-openapi-runtime][repo-runtime] | Runtime library used by the generated code | +| [apple/swift-openapi-urlsession][repo-urlsession] | `ClientTransport` using [URLSession][urlsession] | +| [swift-server/swift-openapi-async-http-client][repo-ahc] | `ClientTransport` using [AsyncHTTPClient][ahc] | +| [swift-server/swift-openapi-vapor][repo-vapor] | `ServerTransport` using [Vapor][vapor] | +| [swift-server/swift-openapi-hummingbird][repo-hummingbird] | `ServerTransport` using [Hummingbird][hummingbird] | -| Repository | Type | Description | -| ---------- | ---- | ----------- | -| [apple/swift-openapi-urlsession][repo-urlsession] | Client | Uses `URLSession` from [Foundation][foundation]. | -| [swift-server/swift-openapi-async-http-client][repo-ahc] | Client | Uses `HTTPClient` from [AsyncHTTPClient][ahc]. | -| [swift-server/swift-openapi-vapor][repo-vapor] | Server | Uses [Vapor][vapor]. | -| [swift-server/swift-openapi-hummingbird][repo-hummingbird] | Server | Uses [Hummingbird][hummingbird]. | ## Requirements and supported features | Generator versions | Supported OpenAPI versions | Minimum Swift version | -| -------- | ------- | ----- | -| `1.0.0` ... `main` | 3.0, 3.1 | 5.9 | +| ------------------ | -------------------------- | --------------------- | +| `1.0.0` ... `main` | 3.0, 3.1 | 5.9 | + +See also [Supported OpenAPI features][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. +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 -| Component | macOS | Linux | iOS | tvOS | watchOS | visionOS | -| -: | :-: | :-: | :-: | :-: | :-: | :-: | -| Generator plugin and CLI | ✅ 10.15+ | ✅ | ❌ | ❌ | ❌ | ❌ | -| Generated code, runtime, transports | ✅ 10.15+ | ✅ | ✅ 13+ | ✅ 13+ | ✅ 6+ | ✅ 1+ | +To get started, check out the [documentation][docs-generator], which contains +[step-by-step tutorials][tutorials-generator]. -## Documentation +You can also experiment with [example projects][examples-generator] that use +Swift OpenAPI Generator and integrate with other packages in the ecosystem. -To get started, check out the full [documentation][docs-generator], which contains step-by-step tutorials! +Or if you prefer to watch a video, check out [Meet Swift OpenAPI +Generator](https://developer.apple.com/wwdc23/10171) from WWDC23. [openapi]: https://openapis.org [repo-generator]: https://github.com/apple/swift-openapi-generator [docs-generator]: https://swiftpackageindex.com/apple/swift-openapi-generator/documentation +[tutorials-generator]: https://swiftpackageindex.com/apple/swift-openapi-generator/tutorials/swift-openapi-generator +[supported-openapi-features]: https://swiftpackageindex.com/apple/swift-openapi-generator/documentation/swift-openapi-generator/supported-openapi-features +[examples-generator]: https://github.com/apple/swift-openapi-generator/blob/main/Examples/README.md [repo-runtime]: https://github.com/apple/swift-openapi-runtime [docs-runtime]: https://swiftpackageindex.com/apple/swift-openapi-runtime/documentation [repo-urlsession]: https://github.com/apple/swift-openapi-urlsession -[foundation]: https://developer.apple.com/documentation/foundation +[urlsession]: https://developer.apple.com/documentation/foundation/urlsession [repo-ahc]: https://github.com/swift-server/swift-openapi-async-http-client [ahc]: https://github.com/swift-server/async-http-client [repo-vapor]: https://github.com/swift-server/swift-openapi-vapor [vapor]: https://github.com/vapor/vapor [repo-hummingbird]: https://github.com/swift-server/swift-openapi-hummingbird [hummingbird]: https://github.com/hummingbird-project/hummingbird +[^example-openapi-yaml]:
Example OpenAPI document (click to expand) + + ```yaml + 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 + ``` +
diff --git a/Sources/swift-openapi-generator/Documentation.docc/Swift-OpenAPI-Generator.md b/Sources/swift-openapi-generator/Documentation.docc/Swift-OpenAPI-Generator.md index b125907b1..3d7a82347 100644 --- a/Sources/swift-openapi-generator/Documentation.docc/Swift-OpenAPI-Generator.md +++ b/Sources/swift-openapi-generator/Documentation.docc/Swift-OpenAPI-Generator.md @@ -8,49 +8,90 @@ Generate Swift client and server code from an OpenAPI document. ## Overview -[OpenAPI][openapi] is an open specification for documenting HTTP APIs. An OpenAPI document is written in either YAML or JSON. These machine-readable formats can be read by tools to automate workflows. OpenAPI has an large, existing [ecosystem of tooling][tools]. +[OpenAPI][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. -### Getting started +## Features -> Tip: In a rush? Get started quickly by . +- 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. -Alternatively, to integrate Swift OpenAPI Generator into your existing project, or to create a new one, follow one of our _getting started_ guides: -- -- -- +To see these features in action, see . -### Repository organization +## Usage -The Swift OpenAPI Generator project is split across multiple repositories to enable extensibility and minimize dependencies in your project. +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 tutorials. + +### Using a generated API client + +The generated `Client` type provides a method for each HTTP operation defined in the [OpenAPI document](#Example-OpenAPI-document) and can be used with any HTTP library that provides an implementation of `ClientTransport`. -**swift-openapi-generator** ([source][repo-generator], [docs][docs-generator]) provides the plugin. +```swift +import OpenAPIURLSession +import Foundation -**swift-openapi-runtime** ([source][repo-runtime], [docs][docs-runtime]) provides a library with common types and abstractions used by the generated code. +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) +``` -> Tip: See the generator in action in [Meet Swift OpenAPI Generator](https://developer.apple.com/wwdc23/10171) from WWDC23. +### Using generated API server stubs -The generated code isn't tied to a specific HTTP client library or web server framework, allowing adopters to use simple input and output data types for API operations. For making and serving HTTP requests, the generated code requires a type that confoms to one of the protocol abstractions, `ClientTransport` or `ServerTransport`, which the user chooses when creating the client or server. +To implement a server, define a type that conforms to the generated `APIProtocol`, providing a method for each HTTP operation defined in the [OpenAPI document](#Example-OpenAPI-document). -Choose one of the transports listed below, or create your own by adopting the `ClientTransport` or `ServerTransport` protocol: +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. -| Repository | Type | Description | -| ---------- | ---- | ----------- | -| [apple/swift-openapi-urlsession][repo-urlsession] | Client | Uses `URLSession` from [Foundation][foundation]. | -| [swift-server/swift-openapi-async-http-client][repo-ahc] | Client | Uses `HTTPClient` from [AsyncHTTPClient][ahc]. | -| [swift-server/swift-openapi-vapor][repo-vapor] | Server | Uses [Vapor][vapor]. | -| [swift-server/swift-openapi-hummingbird][repo-hummingbird] | Server | Uses [Hummingbird][hummingbird]. | +```swift +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. -> Tip: Factor out common logic, for example, for authentication, logging, and retrying, into a _middleware_, by providing a type that adopts [`ClientMiddleware`](https://swiftpackageindex.com/apple/swift-openapi-runtime/documentation/openapiruntime/clientmiddleware) or [`ServerMiddleware`](https://swiftpackageindex.com/apple/swift-openapi-runtime/documentation/openapiruntime/servermiddleware). Like transports, middlewares can be used with other projects that use Swift OpenAPI Generator. +| Repository | Description | +| ---------- | ----------- | +| [apple/swift-openapi-generator][repo-generator] | Swift package plugin and CLI | +| [apple/swift-openapi-runtime][repo-runtime] | Runtime library used by the generated code | +| [apple/swift-openapi-urlsession][repo-urlsession] | `ClientTransport` using [URLSession][urlsession] | +| [swift-server/swift-openapi-async-http-client][repo-ahc] | `ClientTransport` using [AsyncHTTPClient][ahc] | +| [swift-server/swift-openapi-vapor][repo-vapor] | `ServerTransport` using [Vapor][vapor] | +| [swift-server/swift-openapi-hummingbird][repo-hummingbird] | `ServerTransport` using [Hummingbird][hummingbird] | ### Requirements and supported features | Generator versions | Supported OpenAPI versions | Minimum Swift version | -| -------- | ------- | ----- | -| `1.0.0` ... `main` | 3.0, 3.1 | 5.9 | +| ------------------ | -------------------------- | --------------------- | +| `1.0.0` ... `main` | 3.0, 3.1 | 5.9 | See also . @@ -60,10 +101,61 @@ 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, runtime, transports | ✅ 10.15+ | ✅ | ✅ 13+ | ✅ 13+ | ✅ 6+ | ✅ 1+ | +| 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 topics below, or one of the tutorials. + +You can also experiment with one of the examples in 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](https://developer.apple.com/wwdc23/10171) from WWDC23. + +### Example OpenAPI document + +```yaml +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 +``` ## Topics @@ -103,6 +195,7 @@ The generated code, runtime library, and transports are supported on more platfo [docs-runtime]: https://swiftpackageindex.com/apple/swift-openapi-runtime/documentation [repo-urlsession]: https://github.com/apple/swift-openapi-urlsession [foundation]: https://developer.apple.com/documentation/foundation +[urlsession]: https://developer.apple.com/documentation/foundation/urlsession [repo-ahc]: https://github.com/swift-server/swift-openapi-async-http-client [ahc]: https://github.com/swift-server/async-http-client [repo-vapor]: https://github.com/swift-server/swift-openapi-vapor