Skip to content

Commit daa556a

Browse files
Merge pull request #118 from NeedleInAJayStack/feature/scalar-extensions
Scalar customizations
2 parents f80bd13 + a6708b7 commit daa556a

File tree

1 file changed

+47
-16
lines changed

1 file changed

+47
-16
lines changed

Sources/Graphiti/Scalar/Scalar.swift

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ import OrderedCollections
44
/// Represents a scalar type in the schema.
55
///
66
/// It is **highly** recommended that you do not subclass this type.
7-
/// Instead, modify the encoding/decoding behavior through the `MapEncoder`/`MapDecoder` options available through
8-
/// `Coders` or a custom encoding/decoding on the `ScalarType` itself.
7+
/// Encoding/decoding behavior can be modified through the `MapEncoder`/`MapDecoder` options available through
8+
/// `Coders` or a custom encoding/decoding on the `ScalarType` itself. If you need very custom serialization controls,
9+
/// you may provide your own serialize, parseValue, and parseLiteral implementations.
910
open class Scalar<Resolver, Context, ScalarType: Codable>: TypeComponent<Resolver, Context> {
1011
// TODO: Change this no longer be an open class
1112

@@ -14,22 +15,34 @@ open class Scalar<Resolver, Context, ScalarType: Codable>: TypeComponent<Resolve
1415
name: name,
1516
description: description,
1617
serialize: { value in
17-
guard let scalar = value as? ScalarType else {
18-
throw GraphQLError(
19-
message: "Serialize expected type \(ScalarType.self) but got \(type(of: value))"
20-
)
18+
if let serialize = self.serialize {
19+
return try serialize(value, coders)
20+
} else {
21+
guard let scalar = value as? ScalarType else {
22+
throw GraphQLError(
23+
message: "Serialize expected type \(ScalarType.self) but got \(type(of: value))"
24+
)
25+
}
26+
27+
return try self.serialize(scalar: scalar, encoder: coders.encoder)
2128
}
22-
23-
return try self.serialize(scalar: scalar, encoder: coders.encoder)
2429
},
2530
parseValue: { map in
26-
let scalar = try self.parse(map: map, decoder: coders.decoder)
27-
return try self.serialize(scalar: scalar, encoder: coders.encoder)
31+
if let parseValue = self.parseValue {
32+
return try parseValue(map, coders)
33+
} else {
34+
let scalar = try self.parse(map: map, decoder: coders.decoder)
35+
return try self.serialize(scalar: scalar, encoder: coders.encoder)
36+
}
2837
},
2938
parseLiteral: { value in
30-
let map = value.map
31-
let scalar = try self.parse(map: map, decoder: coders.decoder)
32-
return try self.serialize(scalar: scalar, encoder: coders.encoder)
39+
if let parseLiteral = self.parseLiteral {
40+
return try parseLiteral(value, coders)
41+
} else {
42+
let map = value.map
43+
let scalar = try self.parse(map: map, decoder: coders.decoder)
44+
return try self.serialize(scalar: scalar, encoder: coders.encoder)
45+
}
3346
}
3447
)
3548

@@ -40,18 +53,30 @@ open class Scalar<Resolver, Context, ScalarType: Codable>: TypeComponent<Resolve
4053
try typeProvider.mapName(ScalarType.self, to: name)
4154
}
4255

56+
// TODO: Remove open func, instead relying on a passed closure
4357
open func serialize(scalar: ScalarType, encoder: MapEncoder) throws -> Map {
4458
try encoder.encode(scalar)
4559
}
4660

61+
// TODO: Remove open func, instead relying on a passed closure
4762
open func parse(map: Map, decoder: MapDecoder) throws -> ScalarType {
4863
try decoder.decode(ScalarType.self, from: map)
4964
}
5065

66+
let serialize: ((Any, Coders) throws -> Map)?
67+
let parseValue: ((Map, Coders) throws -> Map)?
68+
let parseLiteral: ((GraphQL.Value, Coders) throws -> Map)?
69+
5170
init(
5271
type _: ScalarType.Type,
53-
name: String?
72+
name: String?,
73+
serialize: ((Any, Coders) throws -> Map)? = nil,
74+
parseValue: ((Map, Coders) throws -> Map)? = nil,
75+
parseLiteral: ((GraphQL.Value, Coders) throws -> Map)? = nil
5476
) {
77+
self.serialize = serialize
78+
self.parseValue = parseValue
79+
self.parseLiteral = parseLiteral
5580
super.init(
5681
name: name ?? Reflection.name(for: ScalarType.self),
5782
type: .scalar
@@ -62,11 +87,17 @@ open class Scalar<Resolver, Context, ScalarType: Codable>: TypeComponent<Resolve
6287
public extension Scalar {
6388
convenience init(
6489
_ type: ScalarType.Type,
65-
as name: String? = nil
90+
as name: String? = nil,
91+
serialize: ((Any, Coders) throws -> Map)? = nil,
92+
parseValue: ((Map, Coders) throws -> Map)? = nil,
93+
parseLiteral: ((GraphQL.Value, Coders) throws -> Map)? = nil
6694
) {
6795
self.init(
6896
type: type,
69-
name: name
97+
name: name,
98+
serialize: serialize,
99+
parseValue: parseValue,
100+
parseLiteral: parseLiteral
70101
)
71102
}
72103
}

0 commit comments

Comments
 (0)