Skip to content

Commit aedadce

Browse files
committed
Bump version to 3.1.1 and add tests for reserved scalar names handling
1 parent 05ef9fc commit aedadce

8 files changed

Lines changed: 246 additions & 12 deletions

File tree

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
</PropertyGroup>
1212

1313
<PropertyGroup Label="NuGet">
14-
<Version>3.1.0</Version>
14+
<Version>3.1.1</Version>
1515
</PropertyGroup>
1616

1717
</Project>

RELEASE_NOTES.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
### 3.1.1 - 2026-04-03
2+
* Fixed GraphQL client provider handling for schema types that reuse reserved scalar names such as `Date`, so introspection kind now takes precedence over built-in scalar mappings.
3+
14
#### 0.0.1-beta - 2016-04-19
25
* Initial release
36

@@ -242,4 +245,4 @@
242245

243246
### 3.1.1 - Unreleased
244247

245-
* Fixed planning phase crash when inline fragments reference types not included in union or interface definitions
248+
* Fixed planning phase crash when inline fragments reference types not included in union or interface definitions

src/FSharp.Data.GraphQL.Client.DesignTime/ProvidedTypesHelper.fs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -297,10 +297,6 @@ module internal ProvidedOperation =
297297
tdef.AddXmlDoc("Represents a GraphQL operation on the server.")
298298
tdef.AddMembersDelayed(fun _ ->
299299
let operationResultDef = ProvidedOperationResult.makeProvidedType(operationType)
300-
let isScalar (typeName: string) =
301-
match schemaTypes.TryFind typeName with
302-
| Some introspectionType -> introspectionType.Kind = TypeKind.SCALAR
303-
| None -> false
304300
let variables =
305301
let rec mapVariable (variableName : string) (variableType : InputType) =
306302
match variableType with
@@ -309,9 +305,9 @@ module internal ProvidedOperation =
309305
| Some uploadInputTypeName when typeName = uploadInputTypeName ->
310306
struct (variableName, typeName, TypeMapping.makeOption typeof<Upload>)
311307
| _ ->
312-
match TypeMapping.scalar.TryFind(typeName) with
308+
match TypeMapping.tryFindScalarType schemaTypes typeName with
313309
| Some t -> struct (variableName,typeName, TypeMapping.makeOption t)
314-
| None when isScalar typeName -> struct (variableName, typeName, typeof<string option>)
310+
| None when TypeMapping.isScalarTypeName schemaTypes typeName -> struct (variableName, typeName, typeof<string option>)
315311
| None ->
316312
match schemaProvidedTypes.TryFind(typeName) with
317313
| Some t -> struct (variableName, typeName, TypeMapping.makeOption t)
@@ -381,7 +377,7 @@ module internal ProvidedOperation =
381377
tdef.DeclaredProperties |> Seq.exists ((fun p -> p.PropertyType) >> existsUploadType)
382378
variables |> Seq.exists (fun struct (_, _, t) -> existsUploadType t)
383379
|| variables
384-
|> Seq.where (fun struct (_, typeName, _) -> TypeMapping.scalar.TryGetValue typeName |> fst |> not)
380+
|> Seq.where (fun struct (_, typeName, _) -> not (TypeMapping.isScalarTypeName schemaTypes typeName))
385381
|> Seq.choose (fun struct (_, typeName, _) -> schemaProvidedTypes |> Map.tryFind typeName)
386382
|> Seq.exists existsUploadTypeDefinition
387383
let runMethodOverloads : MemberInfo list =

src/FSharp.Data.GraphQL.Client/BaseTypes.fs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,19 @@ module internal TypeMapping =
169169
"URI", typeof<Uri> |]
170170
|> Map.ofArray
171171

172+
let isBuiltInScalarTypeName (name : string) =
173+
scalar |> Map.containsKey name
174+
175+
let isScalarTypeName (schemaTypes : Map<TypeName, IntrospectionType>) (name : string) =
176+
match schemaTypes.TryFind name with
177+
| Some schemaType -> schemaType.Kind = TypeKind.SCALAR
178+
| None -> isBuiltInScalarTypeName name
179+
180+
let tryFindScalarType (schemaTypes : Map<TypeName, IntrospectionType>) (name : string) =
181+
if isScalarTypeName schemaTypes name
182+
then scalar |> Map.tryFind name
183+
else None
184+
172185
let getSchemaTypes (introspection : IntrospectionSchema) =
173186
let schemaTypeNames =
174187
[| "__TypeKind"
@@ -179,13 +192,11 @@ module internal TypeMapping =
179192
"__EnumValue"
180193
"__Directive"
181194
"__Schema" |]
182-
let isScalarType (name : string) =
183-
scalar |> Map.containsKey name
184195
let isIntrospectionType (name : string) =
185196
schemaTypeNames |> Array.contains name
186197
introspection.Types
187198
|> Array.choose (fun t ->
188-
if not (isIntrospectionType t.Name) && not (isScalarType t.Name)
199+
if not (isIntrospectionType t.Name) && not (t.Kind = TypeKind.SCALAR && isBuiltInScalarTypeName t.Name)
189200
then Some(t.Name, t)
190201
else None)
191202
|> Map.ofArray

tests/FSharp.Data.GraphQL.IntegrationTests/FSharp.Data.GraphQL.IntegrationTests.fsproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,14 @@
1717

1818
<ItemGroup>
1919
<Content Include="introspection.json" />
20+
<Content Include="reserved_scalar_input_date_introspection.json" />
21+
<Content Include="reserved_scalar_object_date_introspection.json" />
2022
<None Include="operation.graphql">
2123
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
2224
</None>
2325
<Content Include="xunit.runner.json" CopyToOutputDirectory="PreserveNewest" />
2426
<Compile Include="Helpers.fs" />
27+
<Compile Include="ReservedScalarNameProviderTests.fs" />
2528
<Compile Include="LocalProviderTests.fs" />
2629
<Compile Include="LocalProviderWithOptionalParametersOnlyTests.fs" />
2730
<Compile Include="SwapiLocalProviderTests.fs" />
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
module FSharp.Data.GraphQL.IntegrationTests.ReservedScalarNameProviderTests
2+
3+
open Xunit
4+
open Helpers
5+
open FSharp.Data.GraphQL
6+
7+
type ObjectDateProvider = GraphQLProvider<"reserved_scalar_object_date_introspection.json">
8+
type InputDateProvider = GraphQLProvider<"reserved_scalar_input_date_introspection.json">
9+
10+
module ObjectDateSchema =
11+
type SchemaDate = ObjectDateProvider.Types.Date
12+
13+
let operation =
14+
ObjectDateProvider.Operation<"""query Q {
15+
dateInfo {
16+
value
17+
category
18+
}
19+
}""">()
20+
21+
let compileSmoke () =
22+
let schemaDate = SchemaDate(value = "2026-04-03", category = "default")
23+
let operationInstance : ObjectDateProvider.Operations.Q = operation
24+
schemaDate |> ignore
25+
operationInstance |> ignore
26+
27+
module InputDateSchema =
28+
type SchemaDate = InputDateProvider.Types.Date
29+
30+
let operation =
31+
InputDateProvider.Operation<"""query Q($input: Date) {
32+
echoDate(input: $input)
33+
}""">()
34+
35+
let compileSmoke () =
36+
let schemaDate = SchemaDate(value = "2026-04-03", category = "default")
37+
let deferredRun : unit -> _ =
38+
fun () -> operation.Run(Unchecked.defaultof<GraphQLProviderRuntimeContext>, schemaDate)
39+
schemaDate |> ignore
40+
deferredRun |> ignore
41+
42+
[<Fact>]
43+
let ``Should allow object types that reuse reserved scalar names`` () =
44+
ObjectDateSchema.compileSmoke ()
45+
true |> equals true
46+
47+
[<Fact>]
48+
let ``Should allow input object types that reuse reserved scalar names`` () =
49+
InputDateSchema.compileSmoke ()
50+
true |> equals true
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
{
2+
"data": {
3+
"__schema": {
4+
"queryType": {
5+
"name": "Query"
6+
},
7+
"mutationType": null,
8+
"subscriptionType": null,
9+
"types": [
10+
{
11+
"kind": "SCALAR",
12+
"name": "String",
13+
"description": null,
14+
"fields": null,
15+
"inputFields": null,
16+
"interfaces": null,
17+
"enumValues": null,
18+
"possibleTypes": null
19+
},
20+
{
21+
"kind": "OBJECT",
22+
"name": "Query",
23+
"description": null,
24+
"fields": [
25+
{
26+
"name": "echoDate",
27+
"description": null,
28+
"args": [
29+
{
30+
"name": "input",
31+
"description": null,
32+
"type": {
33+
"kind": "INPUT_OBJECT",
34+
"name": "Date",
35+
"ofType": null
36+
},
37+
"defaultValue": null
38+
}
39+
],
40+
"type": {
41+
"kind": "SCALAR",
42+
"name": "String",
43+
"ofType": null
44+
},
45+
"isDeprecated": false,
46+
"deprecationReason": null
47+
}
48+
],
49+
"inputFields": null,
50+
"interfaces": [],
51+
"enumValues": null,
52+
"possibleTypes": null
53+
},
54+
{
55+
"kind": "INPUT_OBJECT",
56+
"name": "Date",
57+
"description": null,
58+
"fields": null,
59+
"inputFields": [
60+
{
61+
"name": "value",
62+
"description": null,
63+
"type": {
64+
"kind": "SCALAR",
65+
"name": "String",
66+
"ofType": null
67+
},
68+
"defaultValue": null
69+
},
70+
{
71+
"name": "category",
72+
"description": null,
73+
"type": {
74+
"kind": "SCALAR",
75+
"name": "String",
76+
"ofType": null
77+
},
78+
"defaultValue": null
79+
}
80+
],
81+
"interfaces": null,
82+
"enumValues": null,
83+
"possibleTypes": null
84+
}
85+
],
86+
"directives": []
87+
}
88+
}
89+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
{
2+
"data": {
3+
"__schema": {
4+
"queryType": {
5+
"name": "Query"
6+
},
7+
"mutationType": null,
8+
"subscriptionType": null,
9+
"types": [
10+
{
11+
"kind": "SCALAR",
12+
"name": "String",
13+
"description": null,
14+
"fields": null,
15+
"inputFields": null,
16+
"interfaces": null,
17+
"enumValues": null,
18+
"possibleTypes": null
19+
},
20+
{
21+
"kind": "OBJECT",
22+
"name": "Query",
23+
"description": null,
24+
"fields": [
25+
{
26+
"name": "dateInfo",
27+
"description": null,
28+
"args": [],
29+
"type": {
30+
"kind": "OBJECT",
31+
"name": "Date",
32+
"ofType": null
33+
},
34+
"isDeprecated": false,
35+
"deprecationReason": null
36+
}
37+
],
38+
"inputFields": null,
39+
"interfaces": [],
40+
"enumValues": null,
41+
"possibleTypes": null
42+
},
43+
{
44+
"kind": "OBJECT",
45+
"name": "Date",
46+
"description": null,
47+
"fields": [
48+
{
49+
"name": "value",
50+
"description": null,
51+
"args": [],
52+
"type": {
53+
"kind": "SCALAR",
54+
"name": "String",
55+
"ofType": null
56+
},
57+
"isDeprecated": false,
58+
"deprecationReason": null
59+
},
60+
{
61+
"name": "category",
62+
"description": null,
63+
"args": [],
64+
"type": {
65+
"kind": "SCALAR",
66+
"name": "String",
67+
"ofType": null
68+
},
69+
"isDeprecated": false,
70+
"deprecationReason": null
71+
}
72+
],
73+
"inputFields": null,
74+
"interfaces": [],
75+
"enumValues": null,
76+
"possibleTypes": null
77+
}
78+
],
79+
"directives": []
80+
}
81+
}
82+
}

0 commit comments

Comments
 (0)