Skip to content

Commit 9ba2457

Browse files
examples: Flesh out Makefile-based example (#489)
### Motivation We have an example project showing ahead-of-time generation using the `swift-openapi-generator` CLI directly, driven by a Makefile. This PR polishes it up a bit and makes it more flexible. Additionally, the generated code had not been updated since we switched the default access modifier from package to internal. ### Modifications - Allow overriding a bunch of things when calling `make`. - Prompt for confirmation before blowing away the output directory. - Regenerate sources to pick up the new access modifier. - Add a `help` target. ### Result More extensive example. E.g. running the following command: ```console % make help Run make with one of the following targets: help: Display this help. generate: Generate the sources using swift-openapi-generator. build: Runs swift build. clean: Delete the output directory used for generated sources. clean-all: Clean everything, including the checkout of swift-openapi-generator. dump: Dump all derived values used by the Makefile. The following options can be overriden on the command line: SWIFT_OPENAPI_GENERATOR_GIT_URL (e.g. https://github.com/apple/swift-openapi-generator) SWIFT_OPENAPI_GENERATOR_GIT_TAG (e.g. 1.0.0) SWIFT_OPENAPI_GENERATOR_CLONE_DIR (e.g. .swift-openapi-generator) SWIFT_OPENAPI_GENERATOR_BUILD_CONFIGURATION (e.g. release) OPENAPI_YAML_PATH (e.g. openapi.yaml) OPENAPI_GENERATOR_CONFIG_PATH (e.g. openapi-generator-config.yaml) OUTPUT_DIRECTORY (e.g. Sources/ManualGeneratorInvocationClient/Generated) ``` ### Test Plan CI should still build the package.
1 parent 11f1629 commit 9ba2457

File tree

4 files changed

+123
-57
lines changed

4 files changed

+123
-57
lines changed

Examples/manual-generation-generator-cli-example/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ DerivedData/
99
/Package.resolved
1010
.ci/
1111
.docc-build/
12+
.swift-openapi-generator/
Lines changed: 81 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,86 @@
1-
REPO_URL = https://github.com/apple/swift-openapi-generator
2-
VERSION = 1.0.0
3-
TMP_DIR = /tmp
4-
REPO_DIR = $(TMP_DIR)/swift-openapi-generator
5-
CLI_EXECUTABLE = $(REPO_DIR)/.build/release/swift-openapi-generator
1+
# To see how to drive this makefile use:
2+
#
3+
# % make help
64

7-
$(REPO_DIR):
8-
git clone --branch $(VERSION) --depth 1 $(REPO_URL) $(REPO_DIR)
5+
# The following values can be changed here, or passed on the command line.
6+
SWIFT_OPENAPI_GENERATOR_GIT_URL ?= https://github.com/apple/swift-openapi-generator
7+
SWIFT_OPENAPI_GENERATOR_GIT_TAG ?= 1.0.0
8+
SWIFT_OPENAPI_GENERATOR_CLONE_DIR ?= $(CURRENT_MAKEFILE_DIR)/.swift-openapi-generator
9+
SWIFT_OPENAPI_GENERATOR_BUILD_CONFIGURATION ?= debug
10+
OPENAPI_YAML_PATH ?= $(CURRENT_MAKEFILE_DIR)/openapi.yaml
11+
OPENAPI_GENERATOR_CONFIG_PATH ?= $(CURRENT_MAKEFILE_DIR)/openapi-generator-config.yaml
12+
OUTPUT_DIRECTORY ?= $(CURRENT_MAKEFILE_DIR)/Sources/ManualGeneratorInvocationClient/Generated
913

10-
$(CLI_EXECUTABLE): $(REPO_DIR)
11-
cd $(REPO_DIR) && swift build -c release --package-path $(REPO_DIR)
14+
# Derived values (don't change these).
15+
CURRENT_MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
16+
CURRENT_MAKEFILE_DIR := $(patsubst %/,%,$(dir $(CURRENT_MAKEFILE_PATH)))
17+
SWIFT_OPENAPI_GENERATOR_BIN := $(SWIFT_OPENAPI_GENERATOR_CLONE_DIR)/.build/$(SWIFT_OPENAPI_GENERATOR_BUILD_CONFIGURATION)/swift-openapi-generator
1218

13-
all: $(CLI_EXECUTABLE)
19+
# If no target is specified, display help
20+
.DEFAULT_GOAL := help
1421

15-
generate: $(CLI_EXECUTABLE)
16-
$(CLI_EXECUTABLE) generate ./openapi.yaml \
17-
--output-directory ./Sources/ManualGeneratorInvocationClient/Generated \
18-
--config ./openapi-generator-config.yaml
22+
help: # Display this help.
23+
@-+echo "Run make with one of the following targets:"
24+
@-+echo
25+
@-+grep -Eh "^[a-z-]+:.*#" $(CURRENT_MAKEFILE_PATH) | sed -E 's/^(.*:)(.*#+)(.*)/ \1 @@@ \3 /' | column -t -s "@@@"
26+
@-+echo
27+
@-+echo "The following options can be overriden on the command line:"
28+
@-+echo
29+
@-+echo " SWIFT_OPENAPI_GENERATOR_GIT_URL (e.g. https://github.com/apple/swift-openapi-generator)"
30+
@-+echo " SWIFT_OPENAPI_GENERATOR_GIT_TAG (e.g. 1.0.0)"
31+
@-+echo " SWIFT_OPENAPI_GENERATOR_CLONE_DIR (e.g. .swift-openapi-generator)"
32+
@-+echo " SWIFT_OPENAPI_GENERATOR_BUILD_CONFIGURATION (e.g. release)"
33+
@-+echo " OPENAPI_YAML_PATH (e.g. openapi.yaml)"
34+
@-+echo " OPENAPI_GENERATOR_CONFIG_PATH (e.g. openapi-generator-config.yaml)"
35+
@-+echo " OUTPUT_DIRECTORY (e.g. Sources/ManualGeneratorInvocationClient/Generated)"
1936

20-
clean-generator:
21-
rm -rf $(REPO_DIR)
37+
generate: $(SWIFT_OPENAPI_GENERATOR_BIN) $(OPENAPI_YAML_PATH) $(OPENAPI_GENERATOR_CONFIG_PATH) $(OUTPUT_DIRECTORY) # Generate the sources using swift-openapi-generator.
38+
$< generate \
39+
--config "$(OPENAPI_GENERATOR_CONFIG_PATH)" \
40+
--output-directory "$(OUTPUT_DIRECTORY)" \
41+
"$(OPENAPI_YAML_PATH)"
42+
43+
build: # Runs swift build.
44+
swift build
45+
46+
clean: # Delete the output directory used for generated sources.
47+
@echo 'Delete entire directory: $(OUTPUT_DIRECTORY)? [y/N] ' && read ans && [ $${ans:-N} = y ] || (echo "Aborted"; exit 1)
48+
rm -rf "$(OUTPUT_DIRECTORY)"
49+
50+
clean-all: clean # Clean everything, including the checkout of swift-openapi-generator.
51+
@echo 'Delete checkout of swift-openapi-generator $(SWIFT_OPENAPI_GENERATOR_CLONE_DIR)? [y/N] ' && read ans && [ $${ans:-N} = y ] || (echo "Aborted"; exit 1)
52+
rm -rf "$(SWIFT_OPENAPI_GENERATOR_CLONE_DIR)"
53+
54+
55+
dump: # Dump all derived values used by the Makefile.
56+
@echo "CURRENT_MAKEFILE_PATH = $(CURRENT_MAKEFILE_PATH)"
57+
@echo "CURRENT_MAKEFILE_DIR = $(CURRENT_MAKEFILE_DIR)"
58+
@echo "SWIFT_OPENAPI_GENERATOR_GIT_URL = $(SWIFT_OPENAPI_GENERATOR_GIT_URL)"
59+
@echo "SWIFT_OPENAPI_GENERATOR_GIT_TAG = $(SWIFT_OPENAPI_GENERATOR_GIT_TAG)"
60+
@echo "SWIFT_OPENAPI_GENERATOR_CLONE_DIR = $(SWIFT_OPENAPI_GENERATOR_CLONE_DIR)"
61+
@echo "SWIFT_OPENAPI_GENERATOR_BUILD_CONFIGURATION = $(SWIFT_OPENAPI_GENERATOR_BUILD_CONFIGURATION)"
62+
@echo "SWIFT_OPENAPI_GENERATOR_BIN = $(SWIFT_OPENAPI_GENERATOR_BIN)"
63+
@echo "OPENAPI_YAML_PATH = $(OPENAPI_YAML_PATH)"
64+
@echo "OPENAPI_GENERATOR_CONFIG_PATH = $(OPENAPI_GENERATOR_CONFIG_PATH)"
65+
@echo "OUTPUT_DIRECTORY = $(OUTPUT_DIRECTORY)"
66+
67+
$(SWIFT_OPENAPI_GENERATOR_CLONE_DIR):
68+
git \
69+
-c advice.detachedHead=false \
70+
clone \
71+
--branch "$(SWIFT_OPENAPI_GENERATOR_GIT_TAG)" \
72+
--depth 1 \
73+
"$(SWIFT_OPENAPI_GENERATOR_GIT_URL)" \
74+
$@
75+
76+
$(SWIFT_OPENAPI_GENERATOR_BIN): $(SWIFT_OPENAPI_GENERATOR_CLONE_DIR)
77+
swift \
78+
build \
79+
--package-path "$(SWIFT_OPENAPI_GENERATOR_CLONE_DIR)" \
80+
--configuration "$(SWIFT_OPENAPI_GENERATOR_BUILD_CONFIGURATION)" \
81+
--product swift-openapi-generator
82+
83+
$(OUTPUT_DIRECTORY):
84+
mkdir -p "$@"
85+
86+
.PHONY: help generate build clean clean-all dump

Examples/manual-generation-generator-cli-example/Sources/ManualGeneratorInvocationClient/Generated/Client.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import struct Foundation.Data
1010
import struct Foundation.Date
1111
#endif
1212
import HTTPTypes
13-
package struct Client: APIProtocol {
13+
internal struct Client: APIProtocol {
1414
/// The underlying HTTP client.
1515
private let client: UniversalClient
1616
/// Creates a new client.
@@ -21,7 +21,7 @@ package struct Client: APIProtocol {
2121
/// - configuration: A set of configuration values for the client.
2222
/// - transport: A transport that performs HTTP operations.
2323
/// - middlewares: A list of middlewares to call before the transport.
24-
package init(
24+
internal init(
2525
serverURL: Foundation.URL,
2626
configuration: Configuration = .init(),
2727
transport: any ClientTransport,
@@ -39,7 +39,7 @@ package struct Client: APIProtocol {
3939
}
4040
/// - Remark: HTTP `GET /greet`.
4141
/// - Remark: Generated from `#/paths//greet/get(getGreeting)`.
42-
package func getGreeting(_ input: Operations.getGreeting.Input) async throws -> Operations.getGreeting.Output {
42+
internal func getGreeting(_ input: Operations.getGreeting.Input) async throws -> Operations.getGreeting.Output {
4343
try await client.send(
4444
input: input,
4545
forOperation: Operations.getGreeting.id,

Examples/manual-generation-generator-cli-example/Sources/ManualGeneratorInvocationClient/Generated/Types.swift

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import struct Foundation.Data
1010
import struct Foundation.Date
1111
#endif
1212
/// A type that performs HTTP operations defined by the OpenAPI document.
13-
package protocol APIProtocol: Sendable {
13+
internal protocol APIProtocol: Sendable {
1414
/// - Remark: HTTP `GET /greet`.
1515
/// - Remark: Generated from `#/paths//greet/get(getGreeting)`.
1616
func getGreeting(_ input: Operations.getGreeting.Input) async throws -> Operations.getGreeting.Output
@@ -20,7 +20,7 @@ package protocol APIProtocol: Sendable {
2020
extension APIProtocol {
2121
/// - Remark: HTTP `GET /greet`.
2222
/// - Remark: Generated from `#/paths//greet/get(getGreeting)`.
23-
package func getGreeting(
23+
internal func getGreeting(
2424
query: Operations.getGreeting.Input.Query = .init(),
2525
headers: Operations.getGreeting.Input.Headers = .init()
2626
) async throws -> Operations.getGreeting.Output {
@@ -32,9 +32,9 @@ extension APIProtocol {
3232
}
3333

3434
/// Server URLs defined in the OpenAPI document.
35-
package enum Servers {
35+
internal enum Servers {
3636
/// Example service deployment.
37-
package static func server1() throws -> Foundation.URL {
37+
internal static func server1() throws -> Foundation.URL {
3838
try Foundation.URL(
3939
validatingOpenAPIServerURL: "https://example.com/api",
4040
variables: []
@@ -43,97 +43,97 @@ package enum Servers {
4343
}
4444

4545
/// Types generated from the components section of the OpenAPI document.
46-
package enum Components {
46+
internal enum Components {
4747
/// Types generated from the `#/components/schemas` section of the OpenAPI document.
48-
package enum Schemas {
48+
internal enum Schemas {
4949
/// A value with the greeting contents.
5050
///
5151
/// - Remark: Generated from `#/components/schemas/Greeting`.
52-
package struct Greeting: Codable, Hashable, Sendable {
52+
internal struct Greeting: Codable, Hashable, Sendable {
5353
/// The string representation of the greeting.
5454
///
5555
/// - Remark: Generated from `#/components/schemas/Greeting/message`.
56-
package var message: Swift.String
56+
internal var message: Swift.String
5757
/// Creates a new `Greeting`.
5858
///
5959
/// - Parameters:
6060
/// - message: The string representation of the greeting.
61-
package init(message: Swift.String) {
61+
internal init(message: Swift.String) {
6262
self.message = message
6363
}
64-
package enum CodingKeys: String, CodingKey {
64+
internal enum CodingKeys: String, CodingKey {
6565
case message
6666
}
6767
}
6868
}
6969
/// Types generated from the `#/components/parameters` section of the OpenAPI document.
70-
package enum Parameters {}
70+
internal enum Parameters {}
7171
/// Types generated from the `#/components/requestBodies` section of the OpenAPI document.
72-
package enum RequestBodies {}
72+
internal enum RequestBodies {}
7373
/// Types generated from the `#/components/responses` section of the OpenAPI document.
74-
package enum Responses {}
74+
internal enum Responses {}
7575
/// Types generated from the `#/components/headers` section of the OpenAPI document.
76-
package enum Headers {}
76+
internal enum Headers {}
7777
}
7878

7979
/// API operations, with input and output types, generated from `#/paths` in the OpenAPI document.
80-
package enum Operations {
80+
internal enum Operations {
8181
/// - Remark: HTTP `GET /greet`.
8282
/// - Remark: Generated from `#/paths//greet/get(getGreeting)`.
83-
package enum getGreeting {
84-
package static let id: Swift.String = "getGreeting"
85-
package struct Input: Sendable, Hashable {
83+
internal enum getGreeting {
84+
internal static let id: Swift.String = "getGreeting"
85+
internal struct Input: Sendable, Hashable {
8686
/// - Remark: Generated from `#/paths/greet/GET/query`.
87-
package struct Query: Sendable, Hashable {
87+
internal struct Query: Sendable, Hashable {
8888
/// The name used in the returned greeting.
8989
///
9090
/// - Remark: Generated from `#/paths/greet/GET/query/name`.
91-
package var name: Swift.String?
91+
internal var name: Swift.String?
9292
/// Creates a new `Query`.
9393
///
9494
/// - Parameters:
9595
/// - name: The name used in the returned greeting.
96-
package init(name: Swift.String? = nil) {
96+
internal init(name: Swift.String? = nil) {
9797
self.name = name
9898
}
9999
}
100-
package var query: Operations.getGreeting.Input.Query
100+
internal var query: Operations.getGreeting.Input.Query
101101
/// - Remark: Generated from `#/paths/greet/GET/header`.
102-
package struct Headers: Sendable, Hashable {
103-
package var accept: [OpenAPIRuntime.AcceptHeaderContentType<Operations.getGreeting.AcceptableContentType>]
102+
internal struct Headers: Sendable, Hashable {
103+
internal var accept: [OpenAPIRuntime.AcceptHeaderContentType<Operations.getGreeting.AcceptableContentType>]
104104
/// Creates a new `Headers`.
105105
///
106106
/// - Parameters:
107107
/// - accept:
108-
package init(accept: [OpenAPIRuntime.AcceptHeaderContentType<Operations.getGreeting.AcceptableContentType>] = .defaultValues()) {
108+
internal init(accept: [OpenAPIRuntime.AcceptHeaderContentType<Operations.getGreeting.AcceptableContentType>] = .defaultValues()) {
109109
self.accept = accept
110110
}
111111
}
112-
package var headers: Operations.getGreeting.Input.Headers
112+
internal var headers: Operations.getGreeting.Input.Headers
113113
/// Creates a new `Input`.
114114
///
115115
/// - Parameters:
116116
/// - query:
117117
/// - headers:
118-
package init(
118+
internal init(
119119
query: Operations.getGreeting.Input.Query = .init(),
120120
headers: Operations.getGreeting.Input.Headers = .init()
121121
) {
122122
self.query = query
123123
self.headers = headers
124124
}
125125
}
126-
@frozen package enum Output: Sendable, Hashable {
127-
package struct Ok: Sendable, Hashable {
126+
@frozen internal enum Output: Sendable, Hashable {
127+
internal struct Ok: Sendable, Hashable {
128128
/// - Remark: Generated from `#/paths/greet/GET/responses/200/content`.
129-
@frozen package enum Body: Sendable, Hashable {
129+
@frozen internal enum Body: Sendable, Hashable {
130130
/// - Remark: Generated from `#/paths/greet/GET/responses/200/content/application\/json`.
131131
case json(Components.Schemas.Greeting)
132132
/// The associated value of the enum case if `self` is `.json`.
133133
///
134134
/// - Throws: An error if `self` is not `.json`.
135135
/// - SeeAlso: `.json`.
136-
package var json: Components.Schemas.Greeting {
136+
internal var json: Components.Schemas.Greeting {
137137
get throws {
138138
switch self {
139139
case let .json(body):
@@ -143,12 +143,12 @@ package enum Operations {
143143
}
144144
}
145145
/// Received HTTP response body
146-
package var body: Operations.getGreeting.Output.Ok.Body
146+
internal var body: Operations.getGreeting.Output.Ok.Body
147147
/// Creates a new `Ok`.
148148
///
149149
/// - Parameters:
150150
/// - body: Received HTTP response body
151-
package init(body: Operations.getGreeting.Output.Ok.Body) {
151+
internal init(body: Operations.getGreeting.Output.Ok.Body) {
152152
self.body = body
153153
}
154154
}
@@ -162,7 +162,7 @@ package enum Operations {
162162
///
163163
/// - Throws: An error if `self` is not `.ok`.
164164
/// - SeeAlso: `.ok`.
165-
package var ok: Operations.getGreeting.Output.Ok {
165+
internal var ok: Operations.getGreeting.Output.Ok {
166166
get throws {
167167
switch self {
168168
case let .ok(response):
@@ -180,26 +180,26 @@ package enum Operations {
180180
/// A response with a code that is not documented in the OpenAPI document.
181181
case undocumented(statusCode: Swift.Int, OpenAPIRuntime.UndocumentedPayload)
182182
}
183-
@frozen package enum AcceptableContentType: AcceptableProtocol {
183+
@frozen internal enum AcceptableContentType: AcceptableProtocol {
184184
case json
185185
case other(Swift.String)
186-
package init?(rawValue: Swift.String) {
186+
internal init?(rawValue: Swift.String) {
187187
switch rawValue.lowercased() {
188188
case "application/json":
189189
self = .json
190190
default:
191191
self = .other(rawValue)
192192
}
193193
}
194-
package var rawValue: Swift.String {
194+
internal var rawValue: Swift.String {
195195
switch self {
196196
case let .other(string):
197197
return string
198198
case .json:
199199
return "application/json"
200200
}
201201
}
202-
package static var allCases: [Self] {
202+
internal static var allCases: [Self] {
203203
[
204204
.json
205205
]

0 commit comments

Comments
 (0)