You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Apollo Client for iOS enables you to use Swift scripting to perform certain operations that otherwise require the command line. This document guides you through setting up a Swift Package Manager executable and then using it to:
9
7
10
8
- Download a schema
11
9
- Generate Swift code for your model object based on your schema and operations
12
10
11
+
## Conceptual background
12
+
13
+
Apollo's code generation requires both of the following to run:
14
+
15
+
* Your **schema**, which defines what it's *possible* for you to request from or send to your server
16
+
* One or more **operations**, which define what you are *actually* requesting from the server
17
+
18
+
If you're missing either of these, codegen can't run. If you define operations but no schema, the operations can't be validated. If you define a schema but no operations, there's nothing to validate or generate code for.
19
+
20
+
Or, more succinctly:
21
+
22
+
```
23
+
schema + operations = code
24
+
```
25
+
26
+
Each operation you define can be one of the following:
27
+
28
+
- A **query**, which is a one-time request for specific data
29
+
- A **mutation**, which changes data on the server and then receives updated data back
30
+
- A **subscription**, which allows you to listen for changes to a particular object or type of object
31
+
32
+
Code generation takes your operations and compares them to the schema to confirm that they're valid. If an operation _isn't_ valid, the whole process errors out. If all operations are valid, codegen generates Swift code that gives you end-to-end type safety for each operation.
33
+
34
+
The rest of this guide will help you set up a Swift Package Manager executable that will live alongside your main `xcodeproj` and which can be used either from your main `xcodeproj` or on its own to download a schema, generate code, or both.
35
+
13
36
## Setup
14
37
15
38
To begin, let's set up a Swift Package Manager executable:
@@ -63,7 +86,7 @@ To begin, let's set up a Swift Package Manager executable:
You can use this to get the URL of the folder you plan to download the CLI to:
127
150
128
151
```swift:title=main.swift
129
152
let cliFolderURL = sourceRootURL
130
-
.appendingPathComponent("Codegen")
131
-
.appendingPathComponent("ApolloCLI")
153
+
.apollo.childFolderURL(folderName: "Codegen")
154
+
.apollo.childFolderURL(folderName: "ApolloCLI")
132
155
```
133
156
134
157
This would put the folder to download the CLI here in your filesystem:
@@ -187,10 +210,10 @@ One of the convenience wrappers available to you in the target is `ApolloSchemaD
187
210
188
211
```swift:title=main.swift
189
212
let output = sourceRootURL
190
-
.appendingPathComponent("MyProject")
213
+
.apollo.childFolderURL(folderName:"MyProject")
191
214
```
192
215
193
-
You might want to make sure the folder exists before proceeding:
216
+
Note that particularly if you're not just downloading the schema into your target's folder, you will want to make sure the folder exists before proceeding:
194
217
195
218
```swift:title=main.swift
196
219
try FileManager
@@ -201,8 +224,8 @@ One of the convenience wrappers available to you in the target is `ApolloSchemaD
201
224
3. Set up your `ApolloSchemaOptions` object. In this case, we'll use the [default arguments for all the constructor parameters that take them](./api/ApolloCodegenLib/structs/ApolloSchemaOptions#methods), and only pass in the endpoint to download from and the folder to put the downloaded file into:
@@ -231,28 +254,7 @@ One of the convenience wrappers available to you in the target is `ApolloSchemaD
231
254
232
255
Note the warning: This isn't relevant for schema downloading, but it *is* relevant for generating code: In order to generate code, you need both the schema and some kind of operation.
233
256
234
-
## Using codegen to create a `.graphql` file with an operation
235
-
236
-
Code generation requires both of the following to run:
237
-
238
-
* Your **schema**, which defines what it's *possible*for you to request from or send to your server
239
-
* One or more **operations**, which define what you are *actually* requesting from the server
240
-
241
-
If you're missing either of these, codegen can't run. If you define operations but no schema, the operations can't be validated. If you define a schema but no operations, there's nothing to validate or generate code for.
242
-
243
-
Or, more succinctly:
244
-
245
-
```
246
-
schema + operations = code
247
-
```
248
-
249
-
Each operation you define can be one of the following:
250
-
251
-
- A **query**, which is a one-time request for specific data
252
-
- A **mutation**, which changes data on the server and then receives updated data back
253
-
- A **subscription**, which allows you to listen for changes to a particular object or type of object
254
-
255
-
Code generation takes your operations and compares them to the schema to confirm that they're valid. If an operation _isn't_ valid, the whole process errors out. If all operations are valid, codegen generates Swift code that gives you end-to-end type safety foreach operation.
257
+
## Creating a `.graphql` file with an operation
256
258
257
259
Because you've already [downloaded a schema](#downloading-a-schema), you can now proceed to creating an operation. The easiest and most common type of operation to create is a Query.
258
260
@@ -295,15 +297,15 @@ Here, for example, is what this looks like in a file for one of the queries in o
295
297
296
298
<img alt="Launch list file" src="screenshot/graphql_file_launchlist.png" class="screenshot"/>
297
299
298
-
## Generating code for a target
300
+
## Generating Swift code for a target
299
301
300
-
>**Before you start**: Remember, you need to have a locally downloaded copyof your schema and at least one `.graphql` file containing an operation in your file tree. If you don't have **both**of these, code generation will fail. [Read the section above](#using-codegen-to-create-a-graphql-file-with-an-operation) if you don't have an operation set up!
302
+
>**Before you start**: Remember, you need to have a locally downloaded copyof your schema and at least one `.graphql` file containing an operation in your file tree. If you don't have **both**of these, code generation will fail. [Read the section above](#creating-a-graphql-file-with-an-operation) if you don't have an operation set up!
301
303
302
304
1. Specify the URL for the root of the target you're generating code for:
303
305
304
306
```swift:title=main.swift
305
307
let targetURL = sourceRootURL
306
-
.appendingPathComponent("MyProject")
308
+
.apollo.childFolderURL(folderName: "MyProject")
307
309
```
308
310
309
311
Again, you might want to make sure the folder exists before proceeding:
@@ -317,7 +319,7 @@ Here, for example, is what this looks like in a file for one of the queries in o
317
319
2. Set up your `ApolloCodegenOptions` object. In this case, we'll use the constructor that [sets defaults for you automatically](./api/ApolloCodegenLib/structs/ApolloCodegenOptions#methods):
This creates a single file called `API.swift` in the target's root folder.
@@ -328,7 +330,7 @@ Here, for example, is what this looks like in a file for one of the queries in o
328
330
do {
329
331
try ApolloCodegen.run(from: targetURL,
330
332
with: cliFolderURL,
331
-
options: options)
333
+
options: codegenOptions)
332
334
} catch {
333
335
exit(1)
334
336
}
@@ -367,6 +369,71 @@ Now, you're able to generate code from a debuggable Swift Package Manager execut
367
369
4. Build your target.
368
370
369
371
Now, every time you build your project, this script gets called. Because Swift knows not to recompile everything unless something's changed, it should not have a significant impact on your build time.
372
+
373
+
## Full Script Example
374
+
375
+
Here's an example of a full `main.swift` file for your `Codegen` project which follows the file structure outlined above, and both downloads the schema and uses it to run the codegen:
376
+
377
+
```swift:title=main.swift
378
+
import Foundation
379
+
import ApolloCodegenLib
380
+
381
+
// Grab the parent folder of this file on the filesystem
382
+
let parentFolderOfScriptFile = FileFinder.findParentFolder()
383
+
384
+
// Use that to calculate the source root of both the
385
+
let sourceRootURL = parentFolderOfScriptFile
386
+
.apollo.parentFolderURL() // Sources
387
+
.apollo.parentFolderURL() // Codegen
388
+
.apollo.parentFolderURL() // MyProject
389
+
390
+
// From the source root, figure out where your target
391
+
// root is within your main project
392
+
let targetRootURL = sourceRootURL
393
+
.apollo.childFolderURL(folderName: "MyProject")
394
+
395
+
// Set up the URL you want to use to download the project
396
+
let endpoint =URL(string: "http://localhost:8080/graphql")!
397
+
398
+
// Create an options object for downloading the schema
399
+
let schemaDownloadOptions =ApolloSchemaOptions(endpointURL: endpoint,
400
+
outputFolderURL: targetRootURL)
401
+
402
+
// Calculate where you want to create the folder where the CLI will
403
+
// be downloaded by the ApolloCodegenLib framework.
// This makes the error message in Xcode a lot more legible,
414
+
// and prevents the script from continuing to try to generate
415
+
// code if the schema download failed.
416
+
exit(1)
417
+
}
418
+
419
+
// Create the default Codegen options object (assumes schema.json
420
+
// is in the target root folder, all queries are in some kind
421
+
// of subfolder of the target folder and will output as a
422
+
// single file to API.swift in the target folder)
423
+
let codegenOptions =ApolloCodegenOptions(targetRootURL: targetRootURL)
424
+
425
+
do {
426
+
// Actually attempt to generate code.
427
+
try ApolloCodegen.run(from: targetRootURL,
428
+
with: cliFolderURL,
429
+
options: codegenOptions)
430
+
} catch {
431
+
// This makes the error message in Xcode a lot more legible.
432
+
exit(1)
433
+
}
434
+
```
435
+
436
+
Note that in practice, you will probably want to break the codegen and schema download into separate files, since you'll need to run the code generation considerably more frequently.
Copy file name to clipboardExpand all lines: scripts/run-bundled-codegen.sh
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@
4
4
set -euo pipefail
5
5
6
6
# Advertisement!
7
-
echo"Have you tried our new Swift Package Manager wrapper around codegen? It's now available in beta! See docs at https://www.apollographql.com/docs/ios/swift-scripting/. Note that when this comes out of beta, this Bash script will be deprecated, so give it a try today!"
7
+
echo"Have you tried our new Swift Package Manager wrapper around codegen? It's now out of beta and ready to go! See docs at https://www.apollographql.com/docs/ios/swift-scripting/. This Bash script will be deprecated soon, so give it a try today!"
0 commit comments