diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml
index 0b747b8c..eb4054de 100644
--- a/.github/workflows/copilot-setup-steps.yml
+++ b/.github/workflows/copilot-setup-steps.yml
@@ -33,5 +33,5 @@ jobs:
with:
global-json-file: global.json
dotnet-version: |
- 9.x
+ 10.x
8.x
diff --git a/.github/workflows/publish-ci.yml b/.github/workflows/publish-ci.yml
index a6b76300..f31487b5 100644
--- a/.github/workflows/publish-ci.yml
+++ b/.github/workflows/publish-ci.yml
@@ -8,7 +8,7 @@ on:
env:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
DOTNET_NOLOGO: true
- DOTNET_SDK_VERSION: 9.0.307
+ DOTNET_SDK_VERSION: 10.0.202
jobs:
publish:
diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml
index 849de8d2..d4df8454 100644
--- a/.github/workflows/publish-release.yml
+++ b/.github/workflows/publish-release.yml
@@ -9,7 +9,7 @@ env:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
DOTNET_NOLOGO: true
SLEEP_DURATION: 60
- DOTNET_SDK_VERSION: 9.0.307
+ DOTNET_SDK_VERSION: 10.0.202
jobs:
publish:
diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml
index 9333d342..07356a39 100644
--- a/.github/workflows/pull-request.yml
+++ b/.github/workflows/pull-request.yml
@@ -21,7 +21,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-22.04, windows-latest, macOS-latest]
- dotnet: [9.0.307]
+ dotnet: [10.0.202]
runs-on: ${{ matrix.os }}
steps:
diff --git a/Directory.Build.props b/Directory.Build.props
index 37bb94b2..aff702c9 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,9 +1,9 @@
- net8.0
- 9.0
- 9.0.*
+ net10.0
+ 10.0
+ 10.0.*
true
true
$(NoWarn);NU1504;NU1701
@@ -11,7 +11,7 @@
- 3.1.1
+ 4.0.0
diff --git a/Packages.props b/Packages.props
index e2860d90..8d49347e 100644
--- a/Packages.props
+++ b/Packages.props
@@ -1,10 +1,10 @@
- 8.0.*
- 8.0.*
- 8.0.*
- 9.0.202
+ 10.0.*
+ 10.0.*
+ 10.0.*
+ 10.1.202
4.17.*
2.9.3
6.*
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index e4a2d805..948a801c 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,7 +1,9 @@
#### 0.0.1-beta - 2016-04-19
+
* Initial release
#### 0.0.2-beta - 2016-09-01
+
* Introduced intermediate representation of GraphQL operation execution.
* Introduced ability to convert GraphQL query to LINQ.
* Replaced current asynchronous API resolver internals.
@@ -9,11 +11,13 @@
* Minor bugfixes and performance optimizations.
### 0.0.3-beta - 2018-03-22
+
* Introduced a sample for GraphQL over WebSocket Protocol
* Introduced support for Stream and Defer directives
* Minor bugfixes.
### 0.0.4-beta - 2018-05-31
+
* Introduced support for middlewares in the execution pipeline.
* Introduced new package, named FSharp.Data.GraphQL.Server.Middleware, with generic, built-in middlewares.
* Introduced QueryWeightMiddleware, a generic execution middleware to measure query complexity and optionally block query execution with a threshold.
@@ -26,9 +30,11 @@
* Added support for nested deferred and streamed results (currently does have a maximum degree of two nested operations).
### 0.0.4-beta01 - 2018-05-31
+
* Fix package dependency versions
### 0.0.5-beta - 2018-08-10
+
* Upgraded dependencies on Newtonsoft.Json to the latest version.
* Changing subscription field definitions to have a generic output type - the output is not required to be a GraphQL type anymore.
* Implemented experimental support for @live directive, through a subscription system.
@@ -36,86 +42,108 @@
* Added support for asynchronous subscription field definitions.
### 0.0.6-beta - 2018-08-10
+
* Fixes for introspection query
* Use string identifier to publish to subscription
### 0.0.7-beta - 2018-09-17
+
* **Breaking Change:** Async Pub/Sub methods for subscription and live directive handler interfaces
* Add Long Scalar definition
### 0.0.8-beta - 2018-10-27
+
* Add subscription field to introspection schema
### 0.0.8-beta01 - 2018-10-28
+
* Add subscription field to introspection schema
### 0.0.9 - 2018-11-02
+
* Fixed a bug where output def of a subscription field was not reachable for introspection.
### 0.0.10-beta - 2018-11-13
+
* Deferred and Streamed results now return their fields in the direct result as well. The value of those fields will be an empty list or null.
* Live results now send the immediate result in the direct result, instead of the deferred result.
### 0.0.11-beta - 2018-11-21
+
* Deferred and Streamed results fixes for GQL interfaces.
### 0.0.12-beta - 2018-11-21
+
* Deferred and Streamed results fixes for GQL interfaces when at the top-level of query.
### 0.0.16-beta - 2019-01-03
+
* **Breaking Change** The `ISubscriptionProvider` interface now has additional methods to publish to subscriptions by tag.
* **Breaking Change** Renamed interface methods in `ISubscriptionProvider` from XxAsync to AsyncXx to reserve the former for TPL extensions.
* Fixes for stream and defer execution.
### 0.0.17-beta - 2019-01-11
+
* Execute deferred results in parallel.
### 0.0.18-beta - 2019-01-16
+
* Fix dispose of deferred/stream responses.
### 1.0.0-beta - 2019-04-27
+
* **Breaking Change** New type provider API! see samples/client-provider for details.
* Fixes for #216 enum as a variable.
* Upgraded paket and dependencies.
### 1.0.0-beta2 - 2019-04-27
+
* **Breaking Change** GraphQLProvider now makes Nullable GraphQL inputs optional method arguments instead of options
* **Breaking Change** GraphQLProvider uses the operation name as the generated operation type's names. if no operation name is specified it uses "Operation" + the query string's hash
* Make the type provider cross-targeting
* **Breaking Change** Add postcompile phase to middleware interface
### 1.0.0-beta3 - 2019-05-10
+
* **Breaking Change** GraphQLProvider record types constructors now receive option arguments as optional arguments
* Revision on scalar types parsing - fixed some wrong behaviors such as parsing ints as floats
### 1.0.0-beta4 - 2019-05-13
+
* Fixing a bug when converting variable types to variables json in a query
### 1.0.0-beta5 - 2019-05-13
+
* Fixing a bug when parsing json objects with no fields in serialization
### 1.0.0-beta6 - 2019-05-17
+
* Changing constructors of provided types to have overloads instead of optional parameters (needed because of a limitation of the Type Provider SDK)
* Adding support for field aliases
* Operation result errors and custom data now are provided as their respective types instead of options (`Operation Error []` and `Map`)
### 1.0.0-beta7 - 2019-05-17
+
* Minor bug fixes
* Fixing an error on overload constructor definition
### 1.0.0-beta8 - 2019-05-22
+
* Performance improvements
### 1.0.0-beta9 - 2019-05-22
+
* Fixing dependency issue on Server component
### 1.0.0-beta90 - 2019-05-29
+
* Fixing a wrong cast for System.Uri type
* Adding support for file uploads through [GraphQL Multipart Request Spec](https://github.com/jaydenseric/graphql-multipart-request-spec)
* Changing variable parameters of Run/AsyncRun methods to work as overloaded methods instead of one having optional parameters
* Minor bug fixes
### 1.0.0 - 2019-07-04
+
* Changing the internal client of the Type provider (`System.Net.Http.HttpClient`)
* Fixing several minor bugs of the file upload system in the client provider
* Limiting the upload type of the client provider to be a scalar type (provider fails if it is not)
@@ -129,34 +157,40 @@
* **Breaking Change** Renaming `FSharp.Data.GraphQL.Server.Middlewares` package to `FSharp.Data.GraphQL.Server.Middleware`
### 1.0.1 - 2019-07-05
+
* Adjusting package dependencies (`FParsec`, `System.Net.Http`, and `FSharp.Data.GraphQL.Server` are not locked anymore)
### 1.0.2 - 2019-08-19
+
* fixed false positive validation errors related to variable usage.
### 1.0.3 - 2020-03-03
+
* Correct printing of queries without names
* Correct printing of ListValue and ObjectValue
* Traverse list values in argument lists
* Added test cases for object inputs for GraphQL functions
-
### 1.0.4 - 2020-03-22
+
* TypeProvider now treats custom scalars as strings
* The Guid scalar was mapped to a DateTime
-
### 1.0.5 - 2020-03-23
+
* Support opening static classes
* Add additional case in client to support failed requests that don't return a path.
### 1.0.6 - 2020-12-15
+
* TypeProvider accepts IHttpClientFactory as input
### 1.0.7 - 2020-12-30
+
* Add static TypeProvider parameter `explicitOptionalParameters`.
### 1.0.8 - 2021-04-18
+
* Remove Desktop build
* Update documentation and build tools
* Upgrade build scripts
@@ -166,6 +200,7 @@
* Fix parser bug. Thanks to @njlr
### 2.0.0 - 2024-03-24
+
* **Breaking Change** Migrated to .NET 6/7 and F# 7
* **Breaking Change** Implemented GraphQL error handling using `IGQLError` interface instead of exceptions
* **Breaking Change** Implemented parsing variables as `JsonElement`
@@ -186,17 +221,21 @@
* Fixed various introspection and default value encoding issues
### 2.1.0 - 2024-04-13
+
* Improved server exception logging by including exception in log message
* Documentation and README improvements
### 2.2.0 - 2024-05-08
+
* Improved `AddGraphQLOptions`
* Added Altair and GraphiQL to sample projects
### 2.2.1 - 2024-06-16
+
* Fixed `JsonSerializerOptions` read-only instance error
### 3.0.0 - 2025-11-30
+
* **Breaking Change** Migrated to .NET 8 and F# 9.0 with `FSharp.Core` 9.0.x
* **Breaking Change** Updated scalar `CoerceOutput` signature to `objnull -> 'Primitive option`
* **Breaking Change** Moved GraphQL error extensions to standard `extensions` field according to specification
@@ -244,3 +283,9 @@
* Fixed planning phase crash when inline fragments reference types not included in union or interface definitions
* 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.
+
+### 4.0.0 - Unreleased
+
+* **Breaking Change** Migrated to .NET 10
+* **Breaking Change** Made Relay `Edge` a read-only struct
+* Improved Relay XML documentation comments
diff --git a/build/Program.fs b/build/Program.fs
index e1cd7d83..22bbb133 100644
--- a/build/Program.fs
+++ b/build/Program.fs
@@ -32,7 +32,7 @@ let ctx = Context.forceFakeContext ()
let embedAll = ctx.Arguments |> List.exists (fun arg -> arg = BuildArguments.EmbedAll)
module DotNetCli =
- let setVersion (o : DotNet.Options) = { o with Version = Some "9.0.307" }
+ let setVersion (o : DotNet.Options) = { o with Version = Some "10.0.202" }
let setRestoreOptions (o : DotNet.RestoreOptions) = o.WithCommon setVersion
let configurationString = Environment.environVarOrDefault "CONFIGURATION" "Release"
@@ -50,7 +50,7 @@ let configuration =
// - for documentation, you also need to edit info in "docs/tools/generate.fsx"
[]
-let DotNetMoniker = "net8.0"
+let DotNetMoniker = "net10.0"
let project = "FSharp.Data.GraphQL"
let release = ReleaseNotes.load "RELEASE_NOTES.md"
@@ -77,6 +77,7 @@ Target.create BuildTarget <| fun _ ->
"FSharp.Data.GraphQL.slnx"
|> DotNet.build (fun options -> {
options with
+ Common = options.Common.WithRedirectOutput true |> DotNetCli.setVersion
Configuration = configuration
MSBuildParams = {
options.MSBuildParams with
@@ -90,8 +91,10 @@ Target.create BuildTarget <| fun _ ->
})
let startGraphQLServer (project : string) port (streamRef : DataRef) =
- CreateProcess.fromRawCommandLine "dotnet" $"run --project {project} --no-build --configuration {configurationString} --urls=http://localhost:%i{port}/"
+ CreateProcess.fromRawCommandLine "dotnet" $"run --project {project} --no-build --no-launch-profile --configuration {configurationString} --urls=http://localhost:%i{port}/"
|> CreateProcess.withStandardInput (CreatePipe streamRef)
+ |> CreateProcess.redirectOutput
+ |> CreateProcess.withOutputEventsNotNull Trace.trace Trace.traceError
|> Proc.start
|> ignore
@@ -116,8 +119,8 @@ let runTests (project : string) (args : string) =
]
}
}
- .WithCommon
- DotNetCli.setVersion)
+ |> _.WithRedirectOutput(true)
+ |> _.WithCommon(DotNetCli.setVersion))
project
let starWarsServerStream = StreamRef.Empty
@@ -156,7 +159,7 @@ Target.create BuildIntegrationTestServerTarget <| fun _ ->
options.MSBuildParams with
DisableInternalBinLog = true
}
- Common = { options.Common with CustomParams = Some "--no-dependencies" }
+ Common = { DotNetCli.setVersion options.Common with CustomParams = Some "--no-dependencies" }
})
@@ -197,13 +200,36 @@ Target.create UpdateIntrospectionFileTarget <| fun _ ->
.Wait ()
client.Dispose ()
+let unitTestsProjectPath =
+ "tests"
+ > "FSharp.Data.GraphQL.Tests"
+ > "FSharp.Data.GraphQL.Tests.fsproj"
+
+let integrationTestsProjectPath =
+ "tests"
+ > "FSharp.Data.GraphQL.IntegrationTests"
+ > "FSharp.Data.GraphQL.IntegrationTests.fsproj"
+
+let [] BuildIntegrationTestsTarget = "BuildIntegrationTests"
+Target.create BuildIntegrationTestsTarget <| fun _ ->
+ integrationTestsProjectPath
+ |> DotNet.build (fun options -> {
+ options with
+ Configuration = configuration
+ MSBuildParams = {
+ options.MSBuildParams with
+ DisableInternalBinLog = true
+ }
+ Common = DotNetCli.setVersion options.Common
+ })
+
let [] RunUnitTestsTarget = "RunUnitTests"
Target.create RunUnitTestsTarget <| fun _ ->
- runTests "tests/FSharp.Data.GraphQL.Tests/FSharp.Data.GraphQL.Tests.fsproj" ""
+ runTests unitTestsProjectPath ""
let [] RunIntegrationTestsTarget = "RunIntegrationTests"
Target.create RunIntegrationTestsTarget <| fun _ ->
- runTests "tests/FSharp.Data.GraphQL.IntegrationTests/FSharp.Data.GraphQL.IntegrationTests.fsproj" "" //"--filter Execution=Sync"
+ runTests integrationTestsProjectPath "" //"--filter Execution=Sync"
let prepareDocGen () =
Shell.rm "docs/release-notes.md"
@@ -219,12 +245,18 @@ let prepareDocGen () =
let [] GenerateDocsTarget = "GenerateDocs"
Target.create GenerateDocsTarget <| fun _ ->
prepareDocGen ()
- DotNet.exec DotNetCli.setVersion "fsdocs" "build --clean" |> ignore
+ let result = DotNet.exec DotNetCli.setVersion "fsdocs" "build --clean"
+ if not result.OK then
+ result.Errors |> Seq.iter (Trace.traceError)
+ failwithf "fsdocs build failed with exit code %d" result.ExitCode
let [] GenerateDocsWatchTarget = "GenerateDocsWatch"
Target.create GenerateDocsWatchTarget <| fun _ ->
prepareDocGen ()
- DotNet.exec DotNetCli.setVersion "fsdocs" "watch --clean" |> ignore
+ let result = DotNet.exec DotNetCli.setVersion "fsdocs" "watch --clean"
+ if not result.OK then
+ result.Errors |> Seq.iter (Trace.traceError)
+ failwithf "fsdocs watch failed with exit code %d" result.ExitCode
System.Console.ReadKey () |> ignore
let [] ReleaseDocsTarget = "ReleaseDocs"
@@ -378,6 +410,7 @@ Target.create "PackAndPush" ignore
==> BuildIntegrationTestServerTarget
==> StartIntegrationServerTarget
==> UpdateIntrospectionFileTarget
+==> BuildIntegrationTestsTarget
==> RunIntegrationTestsTarget
==> "All"
=?> (GenerateDocsTarget, Environment.environVar "GITHUB_ACTIONS" = "True")
diff --git a/samples/relay-book-store/relay-book-store.fsproj b/samples/relay-book-store/relay-book-store.fsproj
index 8ab45f6d..492a31de 100644
--- a/samples/relay-book-store/relay-book-store.fsproj
+++ b/samples/relay-book-store/relay-book-store.fsproj
@@ -15,8 +15,6 @@
-
-
diff --git a/samples/star-wars-api/Program.fs b/samples/star-wars-api/Program.fs
index e5132664..d2e8600b 100644
--- a/samples/star-wars-api/Program.fs
+++ b/samples/star-wars-api/Program.fs
@@ -1,8 +1,9 @@
module FSharp.Data.GraphQL.Samples.StarWarsApi.Program
-open Microsoft.AspNetCore
+open Microsoft.AspNetCore.Builder
open Microsoft.AspNetCore.Hosting
open Microsoft.Extensions.Configuration
+open Microsoft.Extensions.Hosting
let exitCode = 0
@@ -29,11 +30,14 @@ let buildWebHost (args : string array) =
.AddJsonFile("appsettings.json", false, true)
.AddJsonFile($"appsettings.{envName}.json", true) |> ignore
- WebHost
+ Host
.CreateDefaultBuilder(args)
- .UseConfiguration(config)
- .ConfigureAppConfiguration(configureAppConfiguration)
- .UseStartup()
+ .ConfigureWebHostDefaults(fun webBuilder ->
+ webBuilder
+ .UseConfiguration(config)
+ .ConfigureAppConfiguration(configureAppConfiguration)
+ .UseStartup()
+ |> ignore)
[]
let main args =
diff --git a/samples/star-wars-api/star-wars-api.fsproj b/samples/star-wars-api/star-wars-api.fsproj
index 0e566d7a..1937930c 100644
--- a/samples/star-wars-api/star-wars-api.fsproj
+++ b/samples/star-wars-api/star-wars-api.fsproj
@@ -7,7 +7,6 @@
-
diff --git a/src/FSharp.Data.GraphQL.Client.DesignTime/ProvidedTypesHelper.fs b/src/FSharp.Data.GraphQL.Client.DesignTime/ProvidedTypesHelper.fs
index 621c5b2c..504207bb 100644
--- a/src/FSharp.Data.GraphQL.Client.DesignTime/ProvidedTypesHelper.fs
+++ b/src/FSharp.Data.GraphQL.Client.DesignTime/ProvidedTypesHelper.fs
@@ -322,16 +322,7 @@ module internal ProvidedOperation =
let buildVariablesExprFromArgs (varNames : string list) (args : Expr list) =
let mapVariableExpr (name : string) (value : Expr) =
let value = Expr.Coerce(value, typeof)
- <@@ let rec mapVariableValue (value : obj) =
- match value with
- | null -> null
- | :? string -> value // We need this because strings are enumerables, and we don't want to enumerate them recursively as an object
- | :? EnumBase as v -> v.GetValue() |> box
- | :? RecordBase as v -> v.ToDictionary() |> box
- | OptionValue v -> v |> Option.map mapVariableValue |> box
- | EnumerableValue v -> v |> Array.map mapVariableValue |> box
- | v -> v
- (name, mapVariableValue %%value) @@>
+ <@@ (name, VariableMapping.mapVariableValue %%value) @@>
let args =
let varArgs = List.skip (args.Length - variables.Length) args
(varNames, varArgs) ||> List.map2 mapVariableExpr
diff --git a/src/FSharp.Data.GraphQL.Client/BaseTypes.fs b/src/FSharp.Data.GraphQL.Client/BaseTypes.fs
index e981d83c..5bc66444 100644
--- a/src/FSharp.Data.GraphQL.Client/BaseTypes.fs
+++ b/src/FSharp.Data.GraphQL.Client/BaseTypes.fs
@@ -459,3 +459,17 @@ type OperationResultBase (rawResponse: HttpResponseMessage, responseJson : JsonV
type OperationBase (query : string) =
/// Gets the query string of the operation.
member _.Query = query
+
+module VariableMapping =
+
+ open FSharp.Data.GraphQL.Client.ReflectionPatterns
+
+ let rec mapVariableValue (value : obj) =
+ match value with
+ | null -> null
+ | :? string -> value
+ | :? EnumBase as v -> v.GetValue() |> box
+ | :? RecordBase as v -> v.ToDictionary() |> box
+ | OptionValue v -> v |> Option.map mapVariableValue |> box
+ | EnumerableValue v -> v |> Array.map mapVariableValue |> box
+ | v -> v
diff --git a/src/FSharp.Data.GraphQL.Server.Relay/Connections.fs b/src/FSharp.Data.GraphQL.Server.Relay/Connections.fs
index 5938b63c..369d6d3c 100644
--- a/src/FSharp.Data.GraphQL.Server.Relay/Connections.fs
+++ b/src/FSharp.Data.GraphQL.Server.Relay/Connections.fs
@@ -3,6 +3,7 @@
namespace FSharp.Data.GraphQL.Server.Relay
+open System.Runtime.CompilerServices
open FSharp.Data.GraphQL.Types
open FSharp.Data.GraphQL.Types.Patterns
@@ -11,6 +12,7 @@ open FSharp.Data.GraphQL.Types.Patterns
/// Edges are used to traverse connections in Relay pagination.
///
/// The type of the node at the end of this edge.
+[]
type Edge<'Node> = {
/// Opaque cursor string used to identify this node's position in the connection.
Cursor : string
diff --git a/tests/FSharp.Data.GraphQL.IntegrationTests.Server/FSharp.Data.GraphQL.IntegrationTests.Server.fsproj b/tests/FSharp.Data.GraphQL.IntegrationTests.Server/FSharp.Data.GraphQL.IntegrationTests.Server.fsproj
index 359157c7..6a4a691b 100644
--- a/tests/FSharp.Data.GraphQL.IntegrationTests.Server/FSharp.Data.GraphQL.IntegrationTests.Server.fsproj
+++ b/tests/FSharp.Data.GraphQL.IntegrationTests.Server/FSharp.Data.GraphQL.IntegrationTests.Server.fsproj
@@ -10,7 +10,6 @@
-
diff --git a/tests/FSharp.Data.GraphQL.IntegrationTests.Server/Program.fs b/tests/FSharp.Data.GraphQL.IntegrationTests.Server/Program.fs
index 857bbf95..46fec9b6 100644
--- a/tests/FSharp.Data.GraphQL.IntegrationTests.Server/Program.fs
+++ b/tests/FSharp.Data.GraphQL.IntegrationTests.Server/Program.fs
@@ -1,17 +1,18 @@
namespace FSharp.Data.GraphQL.IntegrationTests.Server
-open Microsoft.AspNetCore
+open Microsoft.Extensions.Hosting
open Microsoft.AspNetCore.Hosting
module Program =
let exitCode = 0
- let buildWebHost args =
- WebHost
+ let buildHost args =
+ Host
.CreateDefaultBuilder(args)
- .UseStartup()
+ .ConfigureWebHostDefaults(fun webBuilder ->
+ webBuilder.UseStartup() |> ignore)
[]
let main args =
- buildWebHost(args).Build().Run()
+ buildHost(args).Build().Run()
exitCode
diff --git a/tests/FSharp.Data.GraphQL.IntegrationTests/FSharp.Data.GraphQL.IntegrationTests.fsproj b/tests/FSharp.Data.GraphQL.IntegrationTests/FSharp.Data.GraphQL.IntegrationTests.fsproj
index 5ef03404..44bc1d17 100644
--- a/tests/FSharp.Data.GraphQL.IntegrationTests/FSharp.Data.GraphQL.IntegrationTests.fsproj
+++ b/tests/FSharp.Data.GraphQL.IntegrationTests/FSharp.Data.GraphQL.IntegrationTests.fsproj
@@ -9,8 +9,6 @@
-
-