Skip to content

Commit 7f91fbe

Browse files
feat: Adds throwing/await support to @graphQLResolver
1 parent 79e9849 commit 7f91fbe

3 files changed

Lines changed: 139 additions & 1 deletion

File tree

Sources/GraphQLGeneratorMacros/GraphQLGeneratorMacros.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@
1818
/// // With name - uses custom GraphQL field name
1919
/// @graphQLResolver(name: "fullName")
2020
/// let name: String
21+
///
22+
/// // Async throwing computed property - automatically adds 'try await'
23+
/// @graphQLResolver
24+
/// var userId: String {
25+
/// get async throws {
26+
/// try await user.fetchID()
27+
/// }
28+
/// }
2129
/// }
2230
/// ```
2331
///
@@ -31,6 +39,10 @@
3139
/// func fullName(context: GraphQLContext, info: GraphQLResolveInfo) async throws -> String {
3240
/// return name
3341
/// }
42+
///
43+
/// func userId(context: GraphQLContext, info: GraphQLResolveInfo) async throws -> String {
44+
/// return try await userId
45+
/// }
3446
/// ```
3547
///
3648
/// ## Requirements

Sources/GraphQLGeneratorMacrosBackend/GraphQLResolverMacro.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ public struct GraphQLResolverMacro: PeerMacro {
3535
let propertyName = identifier.text
3636
let propertyType = type.trimmedDescription
3737

38+
// Check if the property has a throwing getter
39+
let hasThrows = binding.accessorBlock?.accessors.as(AccessorDeclListSyntax.self)?.contains { accessor in
40+
accessor.accessorSpecifier.tokenKind == .keyword(.get) && accessor.effectSpecifiers?.throwsClause != nil
41+
} ?? false
42+
43+
// Check if the property has an async getter
44+
let hasAsync = binding.accessorBlock?.accessors.as(AccessorDeclListSyntax.self)?.contains { accessor in
45+
accessor.accessorSpecifier.tokenKind == .keyword(.get) && accessor.effectSpecifiers?.asyncSpecifier != nil
46+
} ?? false
47+
3848
// Set argument defaults
3949
var graphQLFieldName = propertyName
4050

@@ -55,7 +65,7 @@ public struct GraphQLResolverMacro: PeerMacro {
5565
// Generate the resolver method
5666
let resolverMethod: DeclSyntax = """
5767
func \(raw: graphQLFieldName)(context: GraphQLContext, info: GraphQLResolveInfo) async throws -> \(raw: propertyType) {
58-
return \(raw: propertyName)
68+
return \(raw: hasThrows ? "try " : "")\(raw: hasAsync ? "await " : "")\(raw: propertyName)
5969
}
6070
"""
6171

Tests/GraphQLGeneratorMacrosTests/GraphQLResolverMacroTests.swift

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,4 +264,120 @@ final class GraphQLResolverMacroTests: XCTestCase {
264264
macros: testMacros
265265
)
266266
}
267+
268+
func testComputedProperty() {
269+
assertMacroExpansion(
270+
"""
271+
struct User {
272+
@graphQLResolver
273+
var name: String {
274+
get {
275+
return "Test"
276+
}
277+
}
278+
}
279+
""",
280+
expandedSource: """
281+
struct User {
282+
var name: String {
283+
get {
284+
return "Test"
285+
}
286+
}
287+
288+
func name(context: GraphQLContext, info: GraphQLResolveInfo) async throws -> String {
289+
return name
290+
}
291+
}
292+
""",
293+
macros: testMacros
294+
)
295+
}
296+
297+
func testThrowingComputedProperty() {
298+
assertMacroExpansion(
299+
"""
300+
struct User {
301+
@graphQLResolver
302+
var id: String {
303+
get throws {
304+
try property.getID()
305+
}
306+
}
307+
}
308+
""",
309+
expandedSource: """
310+
struct User {
311+
var id: String {
312+
get throws {
313+
try property.getID()
314+
}
315+
}
316+
317+
func id(context: GraphQLContext, info: GraphQLResolveInfo) async throws -> String {
318+
return try id
319+
}
320+
}
321+
""",
322+
macros: testMacros
323+
)
324+
}
325+
326+
func testAsyncComputedProperty() {
327+
assertMacroExpansion(
328+
"""
329+
struct User {
330+
@graphQLResolver
331+
var id: String {
332+
get async {
333+
await property.getID()
334+
}
335+
}
336+
}
337+
""",
338+
expandedSource: """
339+
struct User {
340+
var id: String {
341+
get async {
342+
await property.getID()
343+
}
344+
}
345+
346+
func id(context: GraphQLContext, info: GraphQLResolveInfo) async throws -> String {
347+
return await id
348+
}
349+
}
350+
""",
351+
macros: testMacros
352+
)
353+
}
354+
355+
func testThrowingAsyncComputedProperty() {
356+
assertMacroExpansion(
357+
"""
358+
struct User {
359+
@graphQLResolver
360+
var id: String {
361+
get async throws {
362+
try await property.getID()
363+
}
364+
}
365+
}
366+
""",
367+
expandedSource: """
368+
struct User {
369+
var id: String {
370+
get async throws {
371+
try await property.getID()
372+
}
373+
}
374+
375+
func id(context: GraphQLContext, info: GraphQLResolveInfo) async throws -> String {
376+
return try await id
377+
}
378+
}
379+
""",
380+
macros: testMacros
381+
)
382+
}
267383
}

0 commit comments

Comments
 (0)