Skip to content

Commit bd23d6c

Browse files
docs: Adds design details for each type
1 parent 1944d7a commit bd23d6c

1 file changed

Lines changed: 53 additions & 4 deletions

File tree

README.md

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
***WARNING***: This package is in beta. It's API is still evolving and is subject to breaking changes.
2+
13
# GraphQL Generator for Swift
24

35
A Swift package plugin that generates server-side GraphQL API code from GraphQL schema files, inspired by [GraphQL Tools' makeExecutableSchema](https://the-guild.dev/graphql/tools/docs/generate-schema).
@@ -57,7 +59,7 @@ type Query {
5759

5860
When you build, the plugin will automatically generate Swift code:
5961
- `Types.swift` - Swift protocols for your GraphQL types
60-
- `Schema.swift` - Schema
62+
- `Schema.swift` - Defines `buildGraphQLSchema` function that builds an executable schema
6163

6264
### 3. Create required types
6365

@@ -118,11 +120,58 @@ let result = try await graphql(schema: schema, request: "{ users { name email }
118120
print(result)
119121
```
120122

121-
## Detailed Usage
123+
## Design
124+
125+
### Root Types
126+
Root types (Query, Mutation, and Subscription) are modeled as Swift protocols with static method requirements for each field. The user must implement these types and provide them to the `buildGraphQLSchema` function.
127+
128+
### Object Types
129+
Object types are modeled as Swift protocols with instance method requirements for each field. This is to enable maximum implementation flexibility. Internally, GraphQL passes result objects directly through to subsequent resolvers. By only specifying the interface, we allow the backing types to be incredibly dynamic - they can be simple codable structs or complex stateful actors, reference or values types, or any other type configuration.
130+
131+
Furthermore, by only referencing protocols, we can have multiple Swift types back a particular GraphQL type, and can easily mock portions of the schema. As an example, consider the following schema snippet:
132+
```graphql
133+
type A {
134+
foo: String
135+
}
136+
```
137+
138+
This would result in the following protocol:
139+
```swift
140+
public protocol AProtocol: Sendable {
141+
func foo(context: Context, info: GraphQLResolveInfo) async throws -> String
142+
}
143+
```
144+
145+
You could define two conforming types. To use `ATest` in tests, simply return it from the relevant resolvers.
146+
```swift
147+
struct A: AProtocol {
148+
let foo: String
149+
func foo(context: Context, info: GraphQLResolveInfo) async throws -> String {
150+
return foo
151+
}
152+
}
153+
struct ATest: AProtocol {
154+
func foo(context: Context, info: GraphQLResolveInfo) async throws -> String {
155+
return "test"
156+
}
157+
}
158+
```
159+
160+
161+
### Interface Types
162+
Interfaces are modeled as a protocol with required methods for each relevant field. Implementing objects and interfaces are marked as requiring conformance to the interface protocol.
163+
164+
### Union Types
165+
Union types are modeled as a marker protocol, with no required properties or functions. Related objects are marked as requiring conformance to the union protocol.
166+
167+
### Input Object Types
168+
Input object types are modeled as a deterministic Codable struct with the declared fields. If more complex objects must be created from the codable struct, this can be done in the resolver itself, since input objects only relevant for their associated resolver (they are not passed to downstream resolvers).
122169

123-
### Scalars
170+
### Enum Types
171+
Enum types are modeled as a deterministic String enum with values matching the declared fields and associated representations. If you need different values or more complex implementations, simply convert to/from a different representation inside your resolvers.
124172

125-
Scalar types must be provided for each GraphQL scalar. Since GraphQL uses a different serialization system than Swift, you must conform the type to Swift's `Codable` and GraphQL's `Scalar`, and have them agree on a representation.
173+
### Scalar Types
174+
Scalar types are not modeled by the generator. They are simply referenced using the Scalar's name, and you are expected to implement the required type. Since GraphQL uses a different serialization system than Swift, you must conform the type to Swift's `Codable` and GraphQL's `Scalar`, and have them agree on a representation.
126175

127176
Below is an example that represents a scalar struct as a raw String:
128177

0 commit comments

Comments
 (0)