-
Notifications
You must be signed in to change notification settings - Fork 730
/
ApolloCodegenOptions.swift
219 lines (192 loc) · 8.57 KB
/
ApolloCodegenOptions.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
import Foundation
/// An object to hold all the various options for running codegen
public struct ApolloCodegenOptions {
/// Enum to select how you want to export your API files.
public enum OutputFormat {
/// Outputs everything into a single file at the given URL.
/// NOTE: URL must be a file URL
case singleFile(atFileURL: URL)
/// Outputs everything into individual files in a folder a the given URL
/// NOTE: URL must be a folder URL
case multipleFiles(inFolderAtURL: URL)
}
/// Enum to select which code generation you wish to use
public enum CodeGenerationEngine: Equatable {
/// The default, tried and true code generation engine
case typescript
/// The VERY WORK IN PROGRESS Swift code generation engine. Use at your own risk!
case swiftExperimental
/// The current default for the code generation engine.
public static var `default`: CodeGenerationEngine {
.typescript
}
var targetForApolloTools: String {
switch self {
case .typescript:
return "swift"
case .swiftExperimental:
return "json-modern"
}
}
}
/// The possible access modifiers for code generated by this tool.
public enum AccessModifier {
case `public`
case `internal`
case `none`
/// The prefix which should be used for classes, enums, and structs generated by this tool.
public var prefixValue: String {
switch self {
case .public: return "public "
case .internal: return "internal "
case .none: return ""
}
}
}
/// Enum to select how to handle properties using a custom scalar from the schema.
public enum CustomScalarFormat: Equatable {
/// Uses a default type instead of a custom scalar.
case none
/// Use your own types for custom scalars.
case passthrough
/// Use your own types for custom scalars with a prefix.
case passthroughWithPrefix(String)
}
let codegenEngine: CodeGenerationEngine
let additionalInflectionRules: [InflectionRule]
let includes: String
let mergeInFieldsFromFragmentSpreads: Bool
let namespace: String?
let modifier: AccessModifier
let only: URL?
let omitDeprecatedEnumCases: Bool
let operationIDsURL: URL?
let outputFormat: OutputFormat
let customScalarFormat: CustomScalarFormat
let suppressSwiftMultilineStringLiterals: Bool
let urlToSchemaFile: URL
let downloadTimeout: Double
/// Designated initializer.
///
/// - Parameters:
/// - codegenEngine: The code generation engine to use. Defaults to `CodeGenerationEngine.default`
/// - includes: Glob of files to search for GraphQL operations. This should be used to find queries *and* any client schema extensions. Defaults to `./**/*.graphql`, which will search for `.graphql` files throughout all subfolders of the folder where the script is run.
/// - mergeInFieldsFromFragmentSpreads: Set true to merge fragment fields onto its enclosing type. Defaults to true.
/// - modifier: [EXPERIMENTAL SWIFT CODEGEN ONLY] - The access modifier to use on everything created by this tool. Defaults to `.public`.
/// - namespace: [optional] The namespace to emit generated code into. Defaults to nil.
/// - omitDeprecatedEnumCases: Whether deprecated enum cases should be omitted from generated code. Defaults to false.
/// - only: [optional] Parse all input files, but only output generated code for the file at this URL if non-nil. Defaults to nil.
/// - operationIDsURL: [optional] Path to an operation id JSON map file. If specified, also stores the operation ids (hashes) as properties on operation types. Defaults to nil.
/// - outputFormat: The `OutputFormat` enum option to use to output generated code.
/// - customScalarFormat: How to handle properties using a custom scalar from the schema.
/// - suppressSwiftMultilineStringLiterals: Don't use multi-line string literals when generating code. Defaults to false.
/// - urlToSchemaFile: The URL to your schema file.
/// - downloadTimeout: The maximum time to wait before indicating that the download timed out, in seconds. Defaults to 30 seconds.
/// - additionalInflectionRules: [EXPERIMENTAL SWIFT CODEGEN ONLY] - Any non-default rules for pluralization or singularization you wish to include. Defaults to an empty array.
public init(codegenEngine: CodeGenerationEngine = .default,
additionalInflectionRules: [InflectionRule] = [],
includes: String = "./**/*.graphql",
mergeInFieldsFromFragmentSpreads: Bool = true,
modifier: AccessModifier = .public,
namespace: String? = nil,
omitDeprecatedEnumCases: Bool = false,
only: URL? = nil,
operationIDsURL: URL? = nil,
outputFormat: OutputFormat,
customScalarFormat: CustomScalarFormat = .none,
suppressSwiftMultilineStringLiterals: Bool = false,
urlToSchemaFile: URL,
downloadTimeout: Double = 30.0) {
self.codegenEngine = codegenEngine
self.additionalInflectionRules = additionalInflectionRules
self.includes = includes
self.mergeInFieldsFromFragmentSpreads = mergeInFieldsFromFragmentSpreads
self.modifier = modifier
self.namespace = namespace
self.omitDeprecatedEnumCases = omitDeprecatedEnumCases
self.only = only
self.operationIDsURL = operationIDsURL
self.outputFormat = outputFormat
self.customScalarFormat = customScalarFormat
self.suppressSwiftMultilineStringLiterals = suppressSwiftMultilineStringLiterals
self.urlToSchemaFile = urlToSchemaFile
self.downloadTimeout = downloadTimeout
}
/// Convenience initializer that takes the root folder of a target and generates
/// code with some default assumptions.
/// Makes the following assumptions:
/// - Schema is at [folder]/schema.json
/// - Output is a single file to [folder]/API.swift
/// - You want operation IDs generated and output to [folder]/operationIDs.json
///
/// - Parameters:
/// - folder: The root of the target.
/// - codegenEngine: The code generation engine to use. Defaults to `CodeGenerationEngine.default`
/// - downloadTimeout: The maximum time to wait before indicating that the download timed out, in seconds. Defaults to 30 seconds
public init(targetRootURL folder: URL,
codegenEngine: CodeGenerationEngine = .default,
downloadTimeout: Double = 30.0) {
let schema = folder.appendingPathComponent("schema.json")
let outputFileURL: URL
switch codegenEngine {
case .typescript:
outputFileURL = folder.appendingPathComponent("API.swift")
case .swiftExperimental:
outputFileURL = folder.appendingPathComponent("API.json")
}
let operationIDsURL = folder.appendingPathComponent("operationIDs.json")
self.init(codegenEngine: codegenEngine,
operationIDsURL: operationIDsURL,
outputFormat: .singleFile(atFileURL: outputFileURL),
urlToSchemaFile: schema,
downloadTimeout: downloadTimeout)
}
var arguments: [String] {
var arguments = [
"codegen:generate",
"--target=\(self.codegenEngine.targetForApolloTools)",
"--addTypename",
"--includes='\(self.includes)'",
"--localSchemaFile='\(self.urlToSchemaFile.path)'"
]
if let namespace = self.namespace {
arguments.append("--namespace=\(namespace)")
}
if let only = only {
arguments.append("--only='\(only.path)'")
}
if let idsURL = self.operationIDsURL {
arguments.append("--operationIdsPath='\(idsURL.path)'")
}
if self.omitDeprecatedEnumCases {
arguments.append("--omitDeprecatedEnumCases")
}
switch customScalarFormat {
case .none:
break
case .passthrough:
arguments.append("--passthroughCustomScalars")
case .passthroughWithPrefix(let prefix):
arguments.append("--passthroughCustomScalars")
arguments.append("--customScalarsPrefix='\(prefix)'")
}
if self.mergeInFieldsFromFragmentSpreads {
arguments.append("--mergeInFieldsFromFragmentSpreads")
}
if self.suppressSwiftMultilineStringLiterals {
arguments.append("--suppressSwiftMultilineStringLiterals")
}
switch self.outputFormat {
case .singleFile(let fileURL):
arguments.append("'\(fileURL.path)'")
case .multipleFiles(let folderURL):
arguments.append("'\(folderURL.path)'")
}
return arguments
}
}
extension ApolloCodegenOptions: CustomDebugStringConvertible {
public var debugDescription: String {
self.arguments.joined(separator: "\n")
}
}