Skip to content

Commit 084f18e

Browse files
feat!: In-place setting of Schema Resolvers
This builds the schema at runtime by parsing the SDL and setting the field resolvers in place, as opposed to generated an entire equivalent schema. The previous way could resulted in longer files that caused long compile times, and was more complex and brittle. Compile time improvements have been validated on the large GitHub schema. This approach does require that we make a change to the GraphQL package that makes field resolvers mutable.
1 parent aab0eb9 commit 084f18e

12 files changed

Lines changed: 166 additions & 1288 deletions

File tree

Examples/GraphQLDotOrg/Package.resolved

Lines changed: 3 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Examples/GraphQLDotOrg/Package.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ let package = Package(
1515
],
1616
dependencies: [
1717
.package(name: "graphql-generator", path: "../.."),
18-
.package(url: "https://github.com/GraphQLSwift/GraphQL.git", from: "4.0.0"),
18+
// TODO: Mainline when merged: https://github.com/GraphQLSwift/GraphQL/pull/174
19+
.package(url: "https://github.com/NeedleInAJayStack/GraphQL.git", revision: "30873303575b92f2395a900869ec8f253efad1b2"),
1920
],
2021
targets: [
2122
.target(

Examples/HelloWorldServer/Package.resolved

Lines changed: 3 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Examples/HelloWorldServer/Package.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ let package = Package(
99
],
1010
dependencies: [
1111
.package(name: "graphql-generator", path: "../.."),
12-
.package(url: "https://github.com/GraphQLSwift/GraphQL.git", from: "4.0.0"),
12+
// TODO: Mainline when merged: https://github.com/GraphQLSwift/GraphQL/pull/174
13+
.package(url: "https://github.com/NeedleInAJayStack/GraphQL.git", revision: "30873303575b92f2395a900869ec8f253efad1b2"),
1314
],
1415
targets: [
1516
.target(

Plugins/GraphQLGeneratorPlugin.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ struct GraphQLGeneratorPlugin: BuildToolPlugin {
2929
let outputFiles = [
3030
outputDirectory.appendingPathComponent("Types.swift"),
3131
outputDirectory.appendingPathComponent("Schema.swift"),
32+
outputDirectory.appendingPathComponent("SDL.swift"),
3233
]
3334

3435
let arguments = schemaInputs.flatMap { ["\($0.path)"] } + [

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,6 @@ public struct EmailAddress: Scalar {
218218
## Development Roadmap
219219

220220
1. Directives: Directives are currently not supported
221-
2. Executable Schema: To work around the immutability of some Schema components, we generate Swift code to fully recreate the defined schema. Instead, we could just add resolver logic to the schema parsed from the `.graphql` file SDL.
222221

223222
## Contributing
224223

Sources/GraphQLGenerator/main.swift

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,21 +42,20 @@ struct GraphQLGeneratorCommand: ParsableCommand {
4242
print("Parsing schema files...")
4343
}
4444

45-
// Parse schema files
46-
let parser = SchemaParser()
47-
let schema = try parser.parseSchemaFiles(schemaFiles)
48-
49-
if verbose {
50-
print("Schema parsed successfully")
51-
print("Generating Swift code...")
45+
/// Read GraphQL schema files and combine them into a single schema
46+
var combinedSource = ""
47+
for filePath in schemaFiles {
48+
let url = URL(fileURLWithPath: filePath)
49+
let content = try String(contentsOf: url, encoding: .utf8)
50+
combinedSource += content + "\n"
5251
}
5352

5453
// Generate code
5554
let generator = CodeGenerator()
56-
let generatedFiles = try generator.generate(schema: schema)
55+
let files = try generator.generate(source: combinedSource)
5756

5857
// Write generated files
59-
for (filename, content) in generatedFiles {
58+
for (filename, content) in files {
6059
let fileURL = outputURL.appendingPathComponent(filename)
6160
try content.write(to: fileURL, atomically: true, encoding: .utf8)
6261

Sources/GraphQLGeneratorCore/Generator/CodeGenerator.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ package struct CodeGenerator {
77

88
/// Generate all Swift files from the schema
99
/// Returns a dictionary of filename -> file content
10-
package func generate(schema: GraphQLSchema) throws -> [String: String] {
10+
package func generate(source: String) throws -> [String: String] {
11+
let schema = try GraphQL.buildSchema(source: source)
12+
1113
var files: [String: String] = [:]
1214

1315
// Generate Types.swift
@@ -18,6 +20,10 @@ package struct CodeGenerator {
1820
let schemaGenerator = SchemaGenerator()
1921
files["Schema.swift"] = try schemaGenerator.generate(schema: schema)
2022

23+
// Generate SDL.swift
24+
let sdlGenerator = SDLGenerator()
25+
files["SDL.swift"] = try sdlGenerator.generate(source: source)
26+
2127
return files
2228
}
2329
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import Foundation
2+
import GraphQL
3+
4+
/// Generates a file that simply wraps the SDL so that its available at runtime without moving files.
5+
package struct SDLGenerator {
6+
package func generate(source: String) throws -> String {
7+
return """
8+
// Generated by GraphQL Generator
9+
// DO NOT EDIT - This file is automatically generated
10+
11+
let graphQLRawSDL = #\"\"\"
12+
\(source)
13+
\"\"\"#
14+
"""
15+
}
16+
}

0 commit comments

Comments
 (0)