Skip to content

Commit

Permalink
stoplight
Browse files Browse the repository at this point in the history
  • Loading branch information
dankinsoid committed May 4, 2024
1 parent 12584ae commit 05c809a
Show file tree
Hide file tree
Showing 14 changed files with 88 additions and 18 deletions.
2 changes: 1 addition & 1 deletion Example/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ let package = Package(
],
dependencies: [
.package(url: "https://github.com/vapor/vapor.git", from: "4.70.0"),
.package(url: "https://github.com/dankinsoid/VaporToOpenAPI.git", from: "4.4.1"),
.package(path: "../")
],
targets: [
.target(
Expand Down
9 changes: 7 additions & 2 deletions Example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ run project
swift run
```

and open `http://127.0.0.1:8080/swagger/` (don't miss the last `/`)
if you run project through XCode you need to set the working directory to the project root directory.
Edit Scheme -> Options -> Use custom working directory

and open:
- Swagger: `http://127.0.0.1:8080/swagger/` (don't miss the trailing `/`)
- Stoplight: `http://127.0.0.1:8080/doc`

## Requirements 📝

- Language: Swift 5.7+
- Language: Swift 5.9+
- Toolkit: [Vapor](https://docs.vapor.codes/) 4.70.0
4 changes: 2 additions & 2 deletions Example/Sources/App/Controllers/OpenAPIController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ struct OpenAPIController: RouteCollection {
)
}
.excludeFromOpenAPI()
routes.grouped("docs").registerOpenAPIElements(path: "/swagger/swagger.json")

routes.stoplightDocumentation("docs", openAPIPath: "/swagger/swagger.json")
}
}
2 changes: 1 addition & 1 deletion Example/Sources/App/Models/Address.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import SwiftOpenAPI
import VaporToOpenAPI

/// Address
@OpenAPIAutoDescriptable
@OpenAPIDescriptable
public struct Address: Codable, WithExample {

/// Street address
Expand Down
2 changes: 1 addition & 1 deletion Example/Sources/App/Models/ApiResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Vapor
import VaporToOpenAPI

/// Api response body
@OpenAPIAutoDescriptable
@OpenAPIDescriptable
public struct ApiResponse: Codable, Content, WithExample {

/// Response code
Expand Down
2 changes: 1 addition & 1 deletion Example/Sources/App/Models/Category.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Foundation
import SwiftOpenAPI
import VaporToOpenAPI

@OpenAPIAutoDescriptable
@OpenAPIDescriptable
/// Category
public struct Category: Codable, Identifiable, WithExample {

Expand Down
2 changes: 1 addition & 1 deletion Example/Sources/App/Models/Customer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Foundation
import SwiftOpenAPI
import VaporToOpenAPI

@OpenAPIAutoDescriptable
@OpenAPIDescriptable
/// Customer
public struct Customer: Codable, Identifiable, WithExample {

Expand Down
2 changes: 1 addition & 1 deletion Example/Sources/App/Models/LoginQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Foundation
import SwiftOpenAPI
import VaporToOpenAPI

@OpenAPIAutoDescriptable
@OpenAPIDescriptable
/// Login query
public struct LoginQuery: Codable, WithExample {

Expand Down
2 changes: 1 addition & 1 deletion Example/Sources/App/Models/Order.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import SwiftOpenAPI
import Vapor
import VaporToOpenAPI

@OpenAPIAutoDescriptable
@OpenAPIDescriptable
/// Order
public struct Order: Codable, Equatable, Content, WithExample {

Expand Down
2 changes: 1 addition & 1 deletion Example/Sources/App/Models/UpdatePetQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Foundation
import SwiftOpenAPI
import VaporToOpenAPI

@OpenAPIAutoDescriptable
@OpenAPIDescriptable
public struct UpdatePetQuery: Codable, Equatable, WithExample {

/// Updated name of the pet
Expand Down
2 changes: 1 addition & 1 deletion Example/Sources/App/Models/UploadImageQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Foundation
import SwiftOpenAPI
import VaporToOpenAPI

@OpenAPIAutoDescriptable
@OpenAPIDescriptable
public struct UploadImageQuery: Codable, Equatable, WithExample {

/// Additional data to pass to server
Expand Down
2 changes: 1 addition & 1 deletion Example/Sources/App/Models/User.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import SwiftOpenAPI
import Vapor
import VaporToOpenAPI

@OpenAPIAutoDescriptable
@OpenAPIDescriptable
/// User model
public struct User: Codable, Content, Identifiable, WithExample {

Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ let routes = app.routes.groupedOpenAPI(auth: .apiKey())
- `openAPINoAuth`: This method is used to specify that an operation does not require any authentication.

- `openAPI(custom:)`: These methods are used to customize a specific aspect of the OpenAPI metadata for a Vapor route, such as a specific security scheme or callback.


- `stoplightDocumentation(openAPI:)`: These methods are used to generate a [Stoplight documentation](https://stoplight.io/) from your Vapor routes.

- `operationID` and `operationRef`: These properties are used to generate unique identifiers for OpenAPI operations and to create references to them in other parts of the specification.

#### Customizing OpenAPI schemas and parameters
Expand Down
69 changes: 66 additions & 3 deletions Sources/VaporToOpenAPI/Elements.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,71 @@
import Vapor

extension RoutesBuilder {
public func registerOpenAPIElements(path: String, title: String = "OpenAPI Documentation") {
get("") { req in

/// Registers an OpenAPI documentation page using the [Stoplight Elements API](https://stoplight.io/).
/// - Parameters:
/// - path: The path to the stoplight documentation.
/// - title: The title of the OpenAPI documentation page.
/// - openAPI: A closure that returns the OpenAPI documentation.
@discardableResult
public func stoplightDocumentation(
_ path: PathComponent...,
title: String = "OpenAPI Documentation",
openAPI: @escaping (Routes) throws -> OpenAPIObject
) -> Route {
stoplightDocumentation(path, title: title, openAPI: openAPI)
}

/// Registers an OpenAPI documentation page using the [Stoplight Elements API](https://stoplight.io/).
/// - Parameters:
/// - path: The path to the stoplight documentation.
/// - title: The title of the OpenAPI documentation page.
/// - openAPI: A closure that returns the OpenAPI documentation.
@discardableResult
public func stoplightDocumentation(
_ path: [PathComponent],
title: String = "OpenAPI Documentation",
openAPI: @escaping (Routes) throws -> OpenAPIObject
) -> Route {
let jsonPath = path + ["openapi.json"]
get(jsonPath) { req in
try openAPI(req.application.routes)
}
.excludeFromOpenAPI()

return stoplightDocumentation(
path,
openAPIPath: "/" + jsonPath.string,
title: title
)
}

/// Registers an OpenAPI documentation page using the [Stoplight Elements API](https://stoplight.io/).
/// - Parameters:
/// - path: The path to the stoplight documentation.
/// - openAPIPath: The path to the OpenAPI documentation.
/// - title: The title of the OpenAPI documentation page.
@discardableResult
public func stoplightDocumentation(
_ path: PathComponent...,
openAPIPath: String,
title: String = "OpenAPI Documentation"
) -> Route {
stoplightDocumentation(path, openAPIPath: openAPIPath, title: title)
}

/// Registers an OpenAPI documentation page using the [Stoplight Elements API](https://stoplight.io/).
/// - Parameters:
/// - path: The path to the stoplight documentation.
/// - openAPIPath: The path to the OpenAPI documentation.
/// - title: The title of the OpenAPI documentation page.
@discardableResult
public func stoplightDocumentation(
_ path: [PathComponent],
openAPIPath: String,
title: String = "OpenAPI Documentation"
) -> Route {
get(path) { req in
var headers = HTTPHeaders()
headers.contentType = .html

Expand All @@ -23,7 +86,7 @@ extension RoutesBuilder {
</head>
<body>
<elements-api apiDescriptionUrl="\(path)" router="hash" />
<elements-api apiDescriptionUrl="\(openAPIPath)" router="hash" />
</body>
</html>
Expand Down

0 comments on commit 05c809a

Please sign in to comment.