Skip to content

Commit 36c16c6

Browse files
feat: Adds default value support
1 parent bd23d6c commit 36c16c6

5 files changed

Lines changed: 108 additions & 63 deletions

File tree

Examples/HelloWorldServer/Sources/HelloWorldServer/schema.graphql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ input UserInfo {
1414
name: String!
1515
email: EmailAddress!
1616
age: Int
17-
role: Role
17+
role: Role = USER
1818
}
1919

2020
"""

Examples/HelloWorldServer/Tests/HelloWorldServerTests/HelloWorldServerTests.swift

Lines changed: 55 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -11,45 +11,45 @@ struct HelloWorldServerTests {
1111
users: ["1" : .init(id: "1", name: "John", email: "john@example.com", age: 18, role: .user)],
1212
posts: ["1" : .init(id: "1", title: "Foo", content: "bar", authorId: "1")]
1313
)
14-
#expect(
15-
try await graphql(
16-
schema: schema,
17-
request: """
18-
{
19-
posts {
14+
let actual = try await graphql(
15+
schema: schema,
16+
request: """
17+
{
18+
posts {
19+
id
20+
title
21+
content
22+
author {
2023
id
21-
title
22-
content
23-
author {
24-
id
25-
name
26-
email
27-
age
28-
role
29-
}
24+
name
25+
email
26+
age
27+
role
3028
}
3129
}
32-
""",
33-
context: context
34-
) == .init(
35-
data: [
36-
"posts": [
37-
[
30+
}
31+
""",
32+
context: context
33+
)
34+
let expected = GraphQLResult(
35+
data: [
36+
"posts": [
37+
[
38+
"id": "1",
39+
"title": "Foo",
40+
"content": "bar",
41+
"author": [
3842
"id": "1",
39-
"title": "Foo",
40-
"content": "bar",
41-
"author": [
42-
"id": "1",
43-
"name": "John",
44-
"email": "john@example.com",
45-
"age": 18,
46-
"role": "USER"
47-
]
43+
"name": "John",
44+
"email": "john@example.com",
45+
"age": 18,
46+
"role": "USER"
4847
]
4948
]
5049
]
51-
)
50+
]
5251
)
52+
#expect(actual == expected)
5353
}
5454

5555
@Test func mutation() async throws {
@@ -58,32 +58,32 @@ struct HelloWorldServerTests {
5858
users: [:],
5959
posts: [:]
6060
)
61-
#expect(
62-
try await graphql(
63-
schema: schema,
64-
request: """
65-
mutation {
66-
upsertUser(userInfo: {id: "2", name: "Jane", email: "jane@example.com"}) {
67-
id
68-
name
69-
email
70-
age
71-
role
72-
}
61+
let actual = try await graphql(
62+
schema: schema,
63+
request: """
64+
mutation {
65+
upsertUser(userInfo: {id: "2", name: "Jane", email: "jane@example.com"}) {
66+
id
67+
name
68+
email
69+
age
70+
role
7371
}
74-
""",
75-
context: context
76-
) == .init(
77-
data: [
78-
"upsertUser": [
79-
"id": "2",
80-
"name": "Jane",
81-
"email": "jane@example.com",
82-
"age": nil,
83-
"role": nil
84-
]
72+
}
73+
""",
74+
context: context
75+
)
76+
let expected = GraphQLResult(
77+
data: [
78+
"upsertUser": [
79+
"id": "2",
80+
"name": "Jane",
81+
"email": "jane@example.com",
82+
"age": nil,
83+
"role": "USER"
8584
]
86-
)
85+
]
8786
)
87+
#expect(actual == expected)
8888
}
8989
}

README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -217,12 +217,11 @@ public struct EmailAddress: Scalar {
217217

218218
## Development Roadmap
219219

220-
1. Default values: Default values are currently ignored
221-
2. Directives: Directives are currently not supported
222-
3. Subscription: Subscription definitions are currently ignored
223-
4. Improved testing: Generator tests should cover much more of the functionality
224-
5. Additional examples: Ideally large ones that cover significant GraphQL features
225-
6. 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.
220+
1. Directives: Directives are currently not supported
221+
2. Subscription: Subscription definitions are currently ignored
222+
3. Improved testing: Generator tests should cover much more of the functionality
223+
4. Additional examples: Ideally large ones that cover significant GraphQL features
224+
5. 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.
226225

227226
## Contributing
228227

Sources/GraphQLGeneratorCore/Generator/SchemaGenerator.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,12 @@ package struct SchemaGenerator {
285285
type: \(try graphQLTypeReference(for: field.type)),
286286
"""
287287

288-
// TODO: Default value support
288+
if let defaultValue = field.defaultValue {
289+
output += """
290+
291+
defaultValue: \(mapToSwiftCode(defaultValue)),
292+
"""
293+
}
289294

290295
if let description = field.description {
291296
output += """
@@ -660,6 +665,13 @@ package struct SchemaGenerator {
660665
"""
661666
}
662667

668+
if let defaultValue = arg.defaultValue {
669+
output += """
670+
,
671+
defaultValue: \(mapToSwiftCode(defaultValue))
672+
"""
673+
}
674+
663675
output += """
664676
665677
),

Sources/GraphQLGeneratorCore/Utilities/swiftTypeName.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,37 @@ func mapScalarType(_ graphQLType: String, nameGenerator: SafeNameGenerator) -> S
8181
return nameGenerator.swiftTypeName(for: graphQLType)
8282
}
8383
}
84+
85+
/// Converts a Map value to valid Swift code representation
86+
func mapToSwiftCode(_ map: Map) -> String {
87+
switch map {
88+
case .undefined:
89+
return ".undefined"
90+
case .null:
91+
return ".null"
92+
case .bool(let value):
93+
return ".bool(\(value))"
94+
case .number(let value):
95+
return ".number(Number(\(value)))"
96+
case .string(let value):
97+
// Escape special characters for Swift string literal
98+
let escaped = value
99+
.replacingOccurrences(of: "\\", with: "\\\\")
100+
.replacingOccurrences(of: "\"", with: "\\\"")
101+
.replacingOccurrences(of: "\n", with: "\\n")
102+
.replacingOccurrences(of: "\r", with: "\\r")
103+
.replacingOccurrences(of: "\t", with: "\\t")
104+
return ".string(\"\(escaped)\")"
105+
case .array(let values):
106+
let elements = values.map { mapToSwiftCode($0) }.joined(separator: ", ")
107+
return ".array([\(elements)])"
108+
case .dictionary(let dict):
109+
let pairs = dict.map { key, value in
110+
let escapedKey = key
111+
.replacingOccurrences(of: "\\", with: "\\\\")
112+
.replacingOccurrences(of: "\"", with: "\\\"")
113+
return "\"\(escapedKey)\": \(mapToSwiftCode(value))"
114+
}.joined(separator: ", ")
115+
return ".dictionary([\(pairs)])"
116+
}
117+
}

0 commit comments

Comments
 (0)