Skip to content

Commit

Permalink
[Docs] Refresh tutorials (#478)
Browse files Browse the repository at this point in the history
### Motivation

Our tutorials were originally written for SOAR 0.1.0, so we need to
update them to reflect the best practices as of SOAR 1.0 instead.

### Modifications

- Adapted to the new Examples structure (most importantly, point to
cloning the Vapor hello world project when writing the client, instead
of the GreetingService.)
- Added a mention of the shorthand APIs as an alternative to the
exhaustive handling. (Still show exhaustive handling first though, as we
want to make sure adopters consider that first and even prefer it.)
- More minor polish and updates.

### Result

Tutorials ready for 1.0 (sans versions, those are changed in #472)

### Test Plan

Previewed locally, actually went through all the tutorials and verified
they all work.
  • Loading branch information
czechboy0 authored Dec 12, 2023
1 parent 14927ee commit ce18524
Show file tree
Hide file tree
Showing 31 changed files with 134 additions and 181 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ As an alternative to invoking the CLI manually, you can also use the package com
Set up the `openapi.yaml` and `openapi-generator-config.yaml` files the same way as you would for the build plugin, and then run:

```console
% swift package plugin generate-code-from-openapi --target GreetingServiceClient
% swift package plugin generate-code-from-openapi --target HelloWorldURLSessionClient
```

This will generate files into the `GreetingServiceClient` target's Sources directory, in a directory called GeneratedSources, which you can then check into your repository.
This will generate files into the `HelloWorldURLSessionClient` target's Sources directory, in a directory called `GeneratedSources`, which you can then check into your repository.

You can also invoke the command from the Xcode UI by control-clicking on a target in the Project Navigator, and selecting the command.
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
Additionally, you can host an HTML page that renders the OpenAPI document as interactive documentation that you can use from the browser, for example using [swagger-ui](https://github.com/swagger-api/swagger-ui).

In this tutorial we'll add both endpoints to our Vapor server.
> Tip: The [OpenAPIEndpointsServer example package](https://github.com/apple/swift-openapi-generator/tree/main/Examples/OpenAPIEndpointsServer) contains the configured Vapor server, in case you want to see the result of this tutorial.

> Tip: The [swagger-ui-endpoint-example package](https://github.com/apple/swift-openapi-generator/tree/main/Examples/swagger-ui-endpoint-example) contains the result of this tutorial, in case you're looking for a working example.
}

@Section(title: "Add an /openapi.yaml endpoint") {
Expand All @@ -17,7 +17,7 @@

@Steps {
@Step {
Create a `Public/` directory for serving static content.
In the server package, create a `Public/` directory for serving static content.

@Code(name: "console", file: server-openapi-endpoints.console.0.txt, reset: true)
}
Expand All @@ -44,11 +44,11 @@
}
}
@Section(title: "Add a Swagger UI endpoint") {
Now we'll add a static `openapi.html` page that serves Swagger UI and add a redirect to this page from `/` for discoverability.
Now we'll add a static `openapi.html` page that serves Swagger UI and add a redirect to this page from `/openapi` for discoverability.

@Steps {
@Step {
Create the file `Public/openapi.html` with the swagger-ui JavaScript.
Create the file `Public/openapi.html` with the HTML contents as shown on the right.

By placing it in the public directory, it is already reachable at `/openapi.html`.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
The API for the service is defined using OpenAPI and you'll create a Swift client for this service, from scratch!

Your Swift package will make use of the Swift OpenAPI Generator plugin to generate the code you'll use to call this API.

> Tip: The [hello-world-urlsession-client-example package](https://github.com/apple/swift-openapi-generator/tree/main/Examples/hello-world-urlsession-client-example) contains the result of this tutorial, in case you're looking for a working example.
}

@Section(title: "(Optional) Downloading and running the server locally for testing") {

In the next section of the guide we will create a client for this service. In order to execute requests, you can download the example server implementation and run it locally.
In the next section of the guide we will create a client for this service. In order to execute requests, you can download an example server implementation and run it locally.

@Steps {
@Step {
Expand Down Expand Up @@ -164,4 +166,21 @@
}
}
}

@Section(title: "Unwrapping the response using the shorthand API") {
If you don't need to handle all the response codes and content types, you can also use the shorthand API on the response and body enums, providing you with throwing getters for unwrapping each value.

These conveniences will throw an error if the received response or content type doesn't match the one you're requesting.

@Steps {
@Step {
Remove the switch statement and replace it with chained access to the `ok` response, to its `body`, to the `json` content type of the body, and finally to the `message` property of the received greeting.
@Code(name: "main.swift", file: client.main.7.swift, previousFile: client.main.6.swift)
}
@Step {
You can now compile and run the executable again and see the response in the console.
@Code(name: "console", file: client.console.4.0.txt)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@
The API for the service is defined using OpenAPI and you'll create a Swift client for this service, from scratch!

Your Xcode project will make use of the Swift OpenAPI Generator plugin to generate the code you'll use to call this API from your existing app.

Note: If you don't already have an existing app project, first create a new SwiftUI-based iOS app Xcode project before continuing.

> Tip: The [HelloWorldiOSClientAppExample package](https://github.com/apple/swift-openapi-generator/tree/main/Examples/HelloWorldiOSClientAppExample) contains the result of this tutorial, in case you're looking for a working example.
}

@Section(title: "(Optional) Downloading and running the server locally for testing") {

In the next section of the guide we will create a client for this service. In order to execute requests, you can download the example server implementation and run it locally.
In the next section of the guide we will create a client for this service. In order to execute requests, you can download an example server implementation and run it locally.

@Steps {
@Step {
Expand All @@ -35,7 +39,7 @@
}
}
}

@Section(title: "Configuring your target to use the Swift OpenAPI Generator plugin") {

Let's extend this app to call our `GreetingService` API.
Expand Down Expand Up @@ -63,25 +67,23 @@
@Step {
With the configuration files in place, we will add the following three package dependencies: the build plugin, the Runtime library, and a concrete client transport that uses URLSession to send HTTP requests.

Select the project in the Project Navigator again, select the project in the Project Editor, and go to Package Dependencies.
Select the project in the Project Navigator, select the project in the Project Editor, and go to Package Dependencies.
}
@Step {
Under Packages, click the plus button to add a new package dependency.
}
@Step {
Find the `swift-openapi-generator` package in an existing collection, or type in the full URL to the search field at the top: `https://github.com/apple/swift-openapi-generator`.

Change the dependency rule to `Up to Next Minor Version`.
}
@Step {
Since the package provides a build plugin that we will integrate later, do not check any products on the next Choose Package Products screen.
Since the package provides a build plugin that we will integrate later, make sure that on the Choose Package Products screen, the "Add to Target" value is "None" for all products listed.

Click Add Package.
}
@Step {
Repeat the same steps two more times, with the packages `https://github.com/apple/swift-openapi-runtime` and `https://github.com/apple/swift-openapi-urlsession`.

This time, do check the library products to be added to the **GreetingServiceClient target**. Note, this might not be the default target Xcode offers to add the libraries to.
This time, ensure the library products are added to the **GreetingServiceClient target**. Note, this might not be the default target Xcode offers to add the libraries to.
}
@Step {
To finish configuring the build plugin in your target, navigate to the Build Phases tab of the GreetingServiceClient in the Project Editor, and expand the Run Build Tool Plug-ins section.
Expand Down Expand Up @@ -110,7 +112,7 @@
@Code(name: "GreetingClient.swift", file: client.xcode.0.swift, reset: true)
}
@Step {
Define a new struct called `GreetingClient` with an initializer and an empty method that will fetch cats using the generated client.
Define a new struct called `GreetingClient` with an initializer and an empty method that will fetch the greeting using the generated client.

@Code(name: "GreetingClient.swift", file: client.xcode.1.swift)
}
Expand Down Expand Up @@ -145,6 +147,13 @@

@Code(name: "GreetingClient.swift", file: client.xcode.6.swift)
}
@Step {
Alternatively, if you don't need to handle all the responses and content types exhaustively, you can use the shorthand API to unwrap the received body value.

Note that if the actual received response or content type is different to your requested one, the unwrapping getters will thrown an error.

@Code(name: "GreetingClient.swift", file: client.xcode.6.2.swift)
}
@Step {
Finally, in your app target, integrate the client to fetch the personalized greeting, for example to show it in the UI.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
The API for the service is defined using OpenAPI and you'll create a Swift server for this service, from scratch!

Your Swift package will make use of the Swift OpenAPI Generator plugin to generate the code you'll use to implement this API.

> Tip: The [hello-world-vapor-server-example package](https://github.com/apple/swift-openapi-generator/tree/main/Examples/hello-world-vapor-server-example) contains the result of this tutorial, in case you're looking for a working example.
}

@Section(title: "Creating a new Swift package") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,7 @@ import PackageDescription

let package = Package(
name: "GreetingServiceClient",
platforms: [
.macOS(.v10_15),
.iOS(.v13),
.tvOS(.v13),
.watchOS(.v6),
],
platforms: [.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6), .visionOS(.v1)],
targets: [
.executableTarget(
name: "GreetingServiceClient"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,7 @@ import PackageDescription

let package = Package(
name: "GreetingServiceClient",
platforms: [
.macOS(.v10_15),
.iOS(.v13),
.tvOS(.v13),
.watchOS(.v6),
],
platforms: [.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6), .visionOS(.v1)],
dependencies: [
.package(url: "https://github.com/apple/swift-openapi-generator", exact: "1.0.0-alpha.1"),
.package(url: "https://github.com/apple/swift-openapi-runtime", exact: "1.0.0-alpha.1"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,7 @@ import PackageDescription

let package = Package(
name: "GreetingServiceClient",
platforms: [
.macOS(.v10_15),
.iOS(.v13),
.tvOS(.v13),
.watchOS(.v6),
],
platforms: [.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6), .visionOS(.v1)],
dependencies: [
.package(url: "https://github.com/apple/swift-openapi-generator", exact: "1.0.0-alpha.1"),
.package(url: "https://github.com/apple/swift-openapi-runtime", exact: "1.0.0-alpha.1"),
Expand All @@ -18,10 +13,7 @@ let package = Package(
.executableTarget(
name: "GreetingServiceClient",
plugins: [
.plugin(
name: "OpenAPIGenerator",
package: "swift-openapi-generator"
)
.plugin(name: "OpenAPIGenerator", package: "swift-openapi-generator"),
]
)
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,7 @@ import PackageDescription

let package = Package(
name: "GreetingServiceClient",
platforms: [
.macOS(.v10_15),
.iOS(.v13),
.tvOS(.v13),
.watchOS(.v6),
],
platforms: [.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6), .visionOS(.v1)],
dependencies: [
.package(url: "https://github.com/apple/swift-openapi-generator", exact: "1.0.0-alpha.1"),
.package(url: "https://github.com/apple/swift-openapi-runtime", exact: "1.0.0-alpha.1"),
Expand All @@ -18,20 +13,11 @@ let package = Package(
.executableTarget(
name: "GreetingServiceClient",
dependencies: [
.product(
name: "OpenAPIRuntime",
package: "swift-openapi-runtime"
),
.product(
name: "OpenAPIURLSession",
package: "swift-openapi-urlsession"
),
.product(name: "OpenAPIRuntime", package: "swift-openapi-runtime"),
.product(name: "OpenAPIURLSession", package: "swift-openapi-urlsession"),
],
plugins: [
.plugin(
name: "OpenAPIGenerator",
package: "swift-openapi-generator"
)
.plugin(name: "OpenAPIGenerator", package: "swift-openapi-generator"),
]
)
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,7 @@ import PackageDescription

let package = Package(
name: "GreetingServiceClient",
platforms: [
.macOS(.v10_15),
.iOS(.v13),
.tvOS(.v13),
.watchOS(.v6),
],
platforms: [.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6), .visionOS(.v1)],
dependencies: [
.package(url: "https://github.com/apple/swift-openapi-generator", exact: "1.0.0-alpha.1"),
.package(url: "https://github.com/apple/swift-openapi-runtime", exact: "1.0.0-alpha.1"),
Expand All @@ -18,20 +13,11 @@ let package = Package(
.executableTarget(
name: "GreetingServiceClient",
dependencies: [
.product(
name: "OpenAPIRuntime",
package: "swift-openapi-runtime"
),
.product(
name: "OpenAPIURLSession",
package: "swift-openapi-urlsession"
),
.product(name: "OpenAPIRuntime", package: "swift-openapi-runtime"),
.product(name: "OpenAPIURLSession", package: "swift-openapi-urlsession"),
],
plugins: [
.plugin(
name: "OpenAPIGenerator",
package: "swift-openapi-generator"
)
.plugin(name: "OpenAPIGenerator", package: "swift-openapi-generator"),
]
)
]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
% git clone https://github.com/apple/swift-openapi-generator
% cd swift-openapi-generator/Examples/GreetingService
% cd swift-openapi-generator/Examples/hello-world-vapor-server-example
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
% git clone https://github.com/apple/swift-openapi-generator
% cd swift-openapi-generator/Examples/GreetingService
% cd swift-openapi-generator/Examples/hello-world-vapor-server-example

% swift run GreetingService
% swift run HelloWorldVaporServer
..
Build complete! (37.91s)
2023-06-01T10:36:58+0200 notice codes.vapor.application : [Vapor] Server starting on http://127.0.0.1:8080
2023-12-12T09:06:32+0100 notice codes.vapor.application : [Vapor] Server starting on http://127.0.0.1:8080
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
% git clone https://github.com/apple/swift-openapi-generator
% cd swift-openapi-generator/Examples/GreetingService
% cd swift-openapi-generator/Examples/hello-world-vapor-server-example

% swift run GreetingService
% swift run HelloWorldVaporServer
..
Build complete! (37.91s)
2023-06-01T10:36:58+0200 notice codes.vapor.application : [Vapor] Server starting on http://127.0.0.1:8080
2023-12-12T09:06:32+0100 notice codes.vapor.application : [Vapor] Server starting on http://127.0.0.1:8080

% curl 'localhost:8080/api/greet?name=Jane'
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
// The Swift Programming Language
// https://docs.swift.org/swift-book

print("Hello, world!")
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,5 @@ let client = Client(
transport: URLSessionTransport()
)

let response = try await client.getGreeting(
.init(
query: .init(name: "CLI")
)
)
let response = try await client.getGreeting(query: .init(name: "CLI"))
print(response)
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ let client = Client(
transport: URLSessionTransport()
)

let response = try await client.getGreeting(
.init(
query: .init(name: "CLI")
)
)
let response = try await client.getGreeting(query: .init(name: "CLI"))
switch response {
case .ok(let okResponse):
print(okResponse)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ let client = Client(
transport: URLSessionTransport()
)

let response = try await client.getGreeting(
.init(
query: .init(name: "CLI")
)
)
let response = try await client.getGreeting(query: .init(name: "CLI"))
switch response {
case .ok(let okResponse):
print(okResponse)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ let client = Client(
transport: URLSessionTransport()
)

let response = try await client.getGreeting(
.init(
query: .init(name: "CLI")
)
)
let response = try await client.getGreeting(query: .init(name: "CLI"))
switch response {
case .ok(let okResponse):
switch okResponse.body {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import OpenAPIRuntime
import OpenAPIURLSession

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

let response = try await client.getGreeting(query: .init(name: "CLI"))
print(try response.ok.body.json.message)
Loading

0 comments on commit ce18524

Please sign in to comment.