Skip to content

Commit 9cb8f9c

Browse files
authored
Add scalar type (#4)
1 parent 06a8678 commit 9cb8f9c

File tree

8 files changed

+327
-76
lines changed

8 files changed

+327
-76
lines changed

Sources/Graphiti/Schema/Schema.swift

Lines changed: 133 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import GraphQL
22

3-
public final class SchemaBuilder<Root> {
3+
public final class SchemaBuilder<Root, Context> {
44
var graphQLTypeMap: [AnyType: GraphQLType] = [
55
AnyType(Int.self): GraphQLInt,
66
AnyType(Double.self): GraphQLFloat,
@@ -17,8 +17,8 @@ public final class SchemaBuilder<Root> {
1717

1818
init() {}
1919

20-
public func query(name: String = "Query", build: (ObjectTypeBuilder<Root, Root>) throws -> Void) throws {
21-
let builder = ObjectTypeBuilder<Root, Root>(schema: self)
20+
public func query(name: String = "Query", build: (ObjectTypeBuilder<Root, Context, Root>) throws -> Void) throws {
21+
let builder = ObjectTypeBuilder<Root, Context, Root>(schema: self)
2222
try build(builder)
2323

2424
query = try GraphQLObjectType(
@@ -29,8 +29,8 @@ public final class SchemaBuilder<Root> {
2929
)
3030
}
3131

32-
public func mutation(name: String = "Mutation", build: (ObjectTypeBuilder<Root, Root>) throws -> Void) throws {
33-
let builder = ObjectTypeBuilder<Root, Root>(schema: self)
32+
public func mutation(name: String = "Mutation", build: (ObjectTypeBuilder<Root, Context, Root>) throws -> Void) throws {
33+
let builder = ObjectTypeBuilder<Root, Context, Root>(schema: self)
3434
try build(builder)
3535

3636
mutation = try GraphQLObjectType(
@@ -41,8 +41,8 @@ public final class SchemaBuilder<Root> {
4141
)
4242
}
4343

44-
public func subscription(name: String = "Subscription", build: (ObjectTypeBuilder<Root, Root>) throws -> Void) throws {
45-
let builder = ObjectTypeBuilder<Root, Root>(schema: self)
44+
public func subscription(name: String = "Subscription", build: (ObjectTypeBuilder<Root, Context, Root>) throws -> Void) throws {
45+
let builder = ObjectTypeBuilder<Root, Context, Root>(schema: self)
4646
try build(builder)
4747

4848
subscription = try GraphQLObjectType(
@@ -56,7 +56,7 @@ public final class SchemaBuilder<Root> {
5656
public func object<Type>(
5757
type: Type.Type,
5858
interfaces: Any.Type...,
59-
build: (ObjectTypeBuilder<Root, Type>) throws -> Void
59+
build: (ObjectTypeBuilder<Root, Context, Type>) throws -> Void
6060
) throws {
6161
let name = fixName(String(describing: Type.self))
6262
try `object`(name: name, type: type, interfaces: interfaces, build: build)
@@ -66,7 +66,7 @@ public final class SchemaBuilder<Root> {
6666
type: Type.Type,
6767
name: String,
6868
interfaces: Any.Type...,
69-
build: (ObjectTypeBuilder<Root, Type>) throws -> Void
69+
build: (ObjectTypeBuilder<Root, Context, Type>) throws -> Void
7070
) throws {
7171
try `object`(name: name, type: type, interfaces: interfaces, build: build)
7272
}
@@ -75,9 +75,9 @@ public final class SchemaBuilder<Root> {
7575
name: String,
7676
type: Type.Type,
7777
interfaces: [Any.Type],
78-
build: (ObjectTypeBuilder<Root, Type>) throws -> Void
78+
build: (ObjectTypeBuilder<Root, Context, Type>) throws -> Void
7979
) throws {
80-
let builder = ObjectTypeBuilder<Root, Type>(schema: self)
80+
let builder = ObjectTypeBuilder<Root, Context, Type>(schema: self)
8181
try builder.addAllFields()
8282
try build(builder)
8383

@@ -94,7 +94,7 @@ public final class SchemaBuilder<Root> {
9494

9595
public func interface<Type>(
9696
type: Type.Type,
97-
build: (InterfaceTypeBuilder<Root, Type>) throws -> Void
97+
build: (InterfaceTypeBuilder<Root, Context, Type>) throws -> Void
9898
) throws {
9999
let name = fixName(String(describing: Type.self))
100100
try interface(name: name, type: type, build: build)
@@ -103,9 +103,9 @@ public final class SchemaBuilder<Root> {
103103
public func interface<Type>(
104104
name: String,
105105
type: Type.Type,
106-
build: (InterfaceTypeBuilder<Root, Type>) throws -> Void
106+
build: (InterfaceTypeBuilder<Root, Context, Type>) throws -> Void
107107
) throws {
108-
let builder = InterfaceTypeBuilder<Root, Type>(schema: self)
108+
let builder = InterfaceTypeBuilder<Root, Context, Type>(schema: self)
109109
try build(builder)
110110

111111
let interfaceType = try GraphQLInterfaceType(
@@ -118,15 +118,15 @@ public final class SchemaBuilder<Root> {
118118
map(Type.self, to: interfaceType)
119119
}
120120

121-
public func `enum`<Type>(
121+
public func `enum`<Type : OutputType>(
122122
type: Type.Type,
123123
build: (EnumTypeBuilder<Type>) throws -> Void
124124
) throws {
125125
let name = fixName(String(describing: Type.self))
126126
try `enum`(name: name, type: type, build: build)
127127
}
128128

129-
public func `enum`<Type>(
129+
public func `enum`<Type : OutputType>(
130130
name: String,
131131
type: Type.Type,
132132
build: (EnumTypeBuilder<Type>) throws -> Void
@@ -142,6 +142,55 @@ public final class SchemaBuilder<Root> {
142142

143143
map(Type.self, to: enumType)
144144
}
145+
146+
public func scalar<Type : OutputType>(
147+
type: Type.Type,
148+
build: (ScalarTypeBuilder<Type>) throws -> Void
149+
) throws {
150+
let name = fixName(String(describing: Type.self))
151+
try scalar(name: name, type: type, build: build)
152+
}
153+
154+
public func scalar<Type : OutputType>(
155+
name: String,
156+
type: Type.Type,
157+
build: (ScalarTypeBuilder<Type>) throws -> Void
158+
) throws {
159+
let builder = ScalarTypeBuilder<Type>()
160+
try build(builder)
161+
162+
if builder.parseValue != nil && builder.parseLiteral == nil {
163+
throw GraphQLError(
164+
message: "parseLiteral function is required."
165+
)
166+
}
167+
168+
if builder.parseValue == nil && builder.parseLiteral != nil {
169+
throw GraphQLError(
170+
message: "parseValue function is required."
171+
)
172+
}
173+
174+
let scalarType: GraphQLScalarType
175+
176+
if let parseValue = builder.parseValue, let parseLiteral = builder.parseLiteral {
177+
scalarType = try GraphQLScalarType(
178+
name: name,
179+
description: builder.description,
180+
serialize: builder.serialize,
181+
parseValue: parseValue,
182+
parseLiteral: parseLiteral
183+
)
184+
} else {
185+
scalarType = try GraphQLScalarType(
186+
name: name,
187+
description: builder.description,
188+
serialize: builder.serialize
189+
)
190+
}
191+
192+
map(Type.self, to: scalarType)
193+
}
145194
}
146195

147196
extension SchemaBuilder {
@@ -355,7 +404,7 @@ extension SchemaBuilder {
355404
let argument = GraphQLArgument(
356405
type: try getInputType(from: propertyType, field: field),
357406
description: argumentsType.descriptions[property.key],
358-
defaultValue: argumentsType.defaultValues[property.key]?.map
407+
defaultValue: try argumentsType.defaultValues[property.key]?.asMap()
359408
)
360409

361410
arguments[property.key] = argument
@@ -366,11 +415,14 @@ extension SchemaBuilder {
366415
}
367416
}
368417

369-
public struct Schema<Root> {
418+
public typealias NoRoot = Void
419+
public typealias NoContext = Void
420+
421+
public struct Schema<Root, Context> {
370422
let schema: GraphQLSchema
371423

372-
public init(_ build: (SchemaBuilder<Root>) throws -> Void) throws {
373-
let builder = SchemaBuilder<Root>()
424+
public init(_ build: (SchemaBuilder<Root, Context>) throws -> Void) throws {
425+
let builder = SchemaBuilder<Root, Context>()
374426
try build(builder)
375427

376428
guard let query = builder.query else {
@@ -387,35 +439,86 @@ public struct Schema<Root> {
387439
directives: builder.directives
388440
)
389441
}
442+
public func execute(
443+
request: String,
444+
variables: [String: Map] = [:],
445+
operationName: String? = nil
446+
) throws -> Map {
447+
guard Root.self is Void.Type else {
448+
throw GraphQLError(
449+
message: "Root value is required."
450+
)
451+
}
452+
453+
guard Context.self is Void.Type else {
454+
throw GraphQLError(
455+
message: "Context value is required."
456+
)
457+
}
458+
459+
return try graphql(
460+
schema: schema,
461+
request: request,
462+
variableValues: variables,
463+
operationName: operationName
464+
)
465+
}
390466

391467
public func execute(
392468
request: String,
393-
contextValue: Any = Void(),
394-
variableValues: [String: Map] = [:],
469+
rootValue: Root,
470+
variables: [String: Map] = [:],
395471
operationName: String? = nil
396-
) throws -> Map {
472+
) throws -> Map {
473+
guard Context.self is Void.Type else {
474+
throw GraphQLError(
475+
message: "Context value is required."
476+
)
477+
}
478+
479+
return try graphql(
480+
schema: schema,
481+
request: request,
482+
rootValue: rootValue,
483+
variableValues: variables,
484+
operationName: operationName
485+
)
486+
}
487+
488+
public func execute(
489+
request: String,
490+
context: Context,
491+
variables: [String: Map] = [:],
492+
operationName: String? = nil
493+
) throws -> Map {
494+
guard Root.self is Void.Type else {
495+
throw GraphQLError(
496+
message: "Root value is required."
497+
)
498+
}
499+
397500
return try graphql(
398501
schema: schema,
399502
request: request,
400-
contextValue: contextValue,
401-
variableValues: variableValues,
503+
contextValue: context,
504+
variableValues: variables,
402505
operationName: operationName
403506
)
404507
}
405508

406509
public func execute(
407510
request: String,
408511
rootValue: Root,
409-
contextValue: Any = Void(),
410-
variableValues: [String: Map] = [:],
512+
context: Context,
513+
variables: [String: Map] = [:],
411514
operationName: String? = nil
412-
) throws -> Map {
515+
) throws -> Map {
413516
return try graphql(
414517
schema: schema,
415518
request: request,
416519
rootValue: rootValue,
417-
contextValue: contextValue,
418-
variableValues: variableValues,
520+
contextValue: context,
521+
variableValues: variables,
419522
operationName: operationName
420523
)
421524
}

0 commit comments

Comments
 (0)