Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/publish-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
env:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
DOTNET_NOLOGO: true
DOTNET_SDK_VERSION: 10.0.202
DOTNET_SDK_VERSION: 10.0.300

jobs:
publish:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ env:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
DOTNET_NOLOGO: true
SLEEP_DURATION: 60
DOTNET_SDK_VERSION: 10.0.202
DOTNET_SDK_VERSION: 10.0.300

jobs:
publish:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-22.04, windows-latest, macOS-latest]
dotnet: [10.0.202]
dotnet: [10.0.300]
runs-on: ${{ matrix.os }}

steps:
Expand Down
5 changes: 5 additions & 0 deletions FSharp.Data.GraphQL.Integration.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
<Platform Name="x64" />
<Platform Name="x86" />
</Configurations>
<Folder Name="/samples/">
<Project Path="samples/star-wars-api/star-wars-api.fsproj" />
</Folder>
<Folder Name="/Solution Items/">
<File Path="Directory.Build.props" />
<File Path="Directory.Build.targets" />
Expand All @@ -12,7 +15,9 @@
<Folder Name="/src/">
<Project Path="src/FSharp.Data.GraphQL.Server.AspNetCore/FSharp.Data.GraphQL.Server.AspNetCore.fsproj" />
<Project Path="src/FSharp.Data.GraphQL.Server.Giraffe/FSharp.Data.GraphQL.Server.Giraffe.fsproj" />
<Project Path="src/FSharp.Data.GraphQL.Server.Middleware/FSharp.Data.GraphQL.Server.Middleware.fsproj" />
<Project Path="src/FSharp.Data.GraphQL.Server.Oxpecker/FSharp.Data.GraphQL.Server.Oxpecker.fsproj" />
<Project Path="src/FSharp.Data.GraphQL.Server.Relay/FSharp.Data.GraphQL.Server.Relay.fsproj" />
<Project Path="src/FSharp.Data.GraphQL.Server/FSharp.Data.GraphQL.Server.fsproj" />
<Project Path="src/FSharp.Data.GraphQL.Shared/FSharp.Data.GraphQL.Shared.fsproj" />
</Folder>
Expand Down
1 change: 1 addition & 0 deletions Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
<PackageReference Update="GraphQL.Server.Ui.Voyager" Version="8.*" />
<PackageReference Update="HotChocolate.AspNetCore" Version="15.*" />
<PackageReference Update="Iced" Version="1.17.*" />
<PackageReference Update="Microsoft.AspNetCore.Mvc.Testing" Version="$(AspNetCoreVersion)" />
<PackageReference Update="Microsoft.Azure.Cosmos" Version="3.*" />
<PackageReference Update="Microsoft.CodeCoverage" Version="17.3.*" />
<PackageReference Update="Microsoft.Data.Sqlite" Version="$(MicrosoftExtensionsVersion)" />
Expand Down
74 changes: 12 additions & 62 deletions build/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ module Program

open System
open System.IO
open System.Net.Http
open System.Text.Json

open Fake.Core
open Fake.Core.TargetOperators
Expand Down Expand Up @@ -32,7 +30,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 "10.0.202" }
let setVersion (o : DotNet.Options) = { o with Version = Some "10.0.300" }
let setRestoreOptions (o : DotNet.RestoreOptions) = o.WithCommon setVersion

let configurationString = Environment.environVarOrDefault "CONFIGURATION" "Release"
Expand Down Expand Up @@ -123,26 +121,6 @@ let runTests (project : string) (args : string) =
|> _.WithCommon(DotNetCli.setVersion))
project

let starWarsServerStream = StreamRef.Empty

let [<Literal>] StartStarWarsServerTarget = "StartStarWarsServer"
Target.create StartStarWarsServerTarget <| fun _ ->
Target.activateFinal "StopStarWarsServer"

let project =
"samples"
</> "star-wars-api"
</> "star-wars-api.fsproj"

startGraphQLServer project 8086 starWarsServerStream

let [<Literal>] StopStarWarsServerTarget = "StopStarWarsServer"
Target.createFinal StopStarWarsServerTarget <| fun _ ->
try
starWarsServerStream.Value.Write ([| 0uy |], 0, 1)
with e ->
printfn "%s" e.Message

let integrationTestServerProjectPath =
"tests"
</> "FSharp.Data.GraphQL.IntegrationTests.Server"
Expand Down Expand Up @@ -179,58 +157,35 @@ Target.createFinal StopIntegrationServerTarget <| fun _ ->
with e ->
printfn "%s" e.Message

let [<Literal>] UpdateIntrospectionFileTarget = "UpdateIntrospectionFile"
Target.create UpdateIntrospectionFileTarget <| fun _ ->
let client = new HttpClient ()
(task {
let! result = client.GetAsync ("http://localhost:8086")
let! contentStream = result.Content.ReadAsStreamAsync ()
let! jsonDocument = JsonDocument.ParseAsync contentStream
let file =
new FileStream ("tests/FSharp.Data.GraphQL.IntegrationTests/introspection.json", FileMode.Create, FileAccess.Write, FileShare.None)
let encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
let jsonWriterOptions = JsonWriterOptions (Indented = true, Encoder = encoder)
let writer = new Utf8JsonWriter (file, jsonWriterOptions)
jsonDocument.WriteTo writer
do! writer.FlushAsync ()
do! writer.DisposeAsync ()
do! file.DisposeAsync ()
result.Dispose ()
})
.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 [<Literal>] BuildIntegrationTestsTarget = "BuildIntegrationTests"
Target.create BuildIntegrationTestsTarget <| fun _ ->
let [<Literal>] UpdateIntrospectionFileTarget = "UpdateIntrospectionFile"
Target.create UpdateIntrospectionFileTarget <| fun _ ->
integrationTestsProjectPath
|> DotNet.build (fun options -> {
|> DotNet.test (fun options -> {
options with
Framework = Some DotNetMoniker
Configuration = configuration
Common = { DotNetCli.setVersion options.Common with CustomParams = Some "--filter FullyQualifiedName~IntrospectionUpdateTests" }
MSBuildParams = {
options.MSBuildParams with
DisableInternalBinLog = true
Verbosity = Some Normal
}
Common = DotNetCli.setVersion options.Common
})

let unitTestsProjectPath =
"tests"
</> "FSharp.Data.GraphQL.Tests"
</> "FSharp.Data.GraphQL.Tests.fsproj"

let [<Literal>] RunUnitTestsTarget = "RunUnitTests"
Target.create RunUnitTestsTarget <| fun _ ->
runTests unitTestsProjectPath ""

let [<Literal>] RunIntegrationTestsTarget = "RunIntegrationTests"
Target.create RunIntegrationTestsTarget <| fun _ ->
runTests integrationTestsProjectPath "" //"--filter Execution=Sync"

let prepareDocGen () =
Shell.rm "docs/release-notes.md"
Shell.cp "RELEASE_NOTES.md" "docs/RELEASE_NOTES.md"
Expand Down Expand Up @@ -406,12 +361,7 @@ Target.create "PackAndPush" ignore
==> RestoreTarget
==> BuildTarget
==> RunUnitTestsTarget
==> StartStarWarsServerTarget
==> BuildIntegrationTestServerTarget
==> StartIntegrationServerTarget
==> UpdateIntrospectionFileTarget
==> BuildIntegrationTestsTarget
==> RunIntegrationTestsTarget
==> "All"
=?> (GenerateDocsTarget, Environment.environVar "GITHUB_ACTIONS" = "True")
|> ignore
Expand Down
6 changes: 6 additions & 0 deletions samples/star-wars-fabulous-client/StarWars.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@
<Project Path="StarWars.Android/StarWars.Android.fsproj">
<BuildType Solution="Ad-Hoc|*" Project="Release" />
<BuildType Solution="AppStore|*" Project="Release" />
<Build Solution="*|Any CPU" Project="false" />
<Build Solution="*|ARM" Project="false" />
<Build Solution="*|iPhone" Project="false" />
<Build Solution="*|iPhoneSimulator" Project="false" />
<Build Solution="*|x64" Project="false" />
<Build Solution="*|x86" Project="false" />
<Deploy Solution="Debug|Any CPU" />
<Deploy Solution="Release|Any CPU" />
</Project>
Expand Down
5 changes: 4 additions & 1 deletion samples/star-wars-fabulous-client/StarWars/Common.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ open FSharp.Data.GraphQL

module Commands =

type GraphQLApi = GraphQLProvider<"http://localhost:8086">
[<Literal>]
let IntrospectionPath = "../../../tests/FSharp.Data.GraphQL.IntegrationTests/introspection.json"

type GraphQLApi = GraphQLProvider<IntrospectionPath>
let GetCharactersData = GraphQLApi.Operation<"queries/FetchCharacters.graphql">()

type Character = GraphQLApi.Operations.FetchCharacters.Types.CharactersFields.Character
20 changes: 10 additions & 10 deletions samples/star-wars-fabulous-client/StarWars/StarWars.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<EnableDefaultEmbeddedResourceItems>false</EnableDefaultEmbeddedResourceItems>
</PropertyGroup>
<ItemGroup>
<PackageReference Update="FSharp.Core" Version="4.5.2" />
<PackageReference Update="FSharp.Core" VersionOverride="4.5.2" />
<!-- workaround for VSMac bug https://github.com/mono/monodevelop/pull/5137 -->
</ItemGroup>
<ItemGroup>
Expand All @@ -18,16 +18,16 @@
<Compile Include="Style.fs" />
<Compile Include="Common.fs" />
<None Include="queries\FetchCharacters.graphql" />
<PackageReference Include="Xamarin.Forms" Version="4.0.0.425677" />
<PackageReference Include="Xamarin.Essentials" Version="1.0.0" />
<PackageReference Include="Fabulous.Core" Version="0.35.0" />
<PackageReference Include="Fabulous.CustomControls" Version="0.35.0" />
<PackageReference Include="Fabulous.LiveUpdate" Version="0.35.0" />
<PackageReference Include="FSharp.Core" Version="4.6.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="FSharp.Data.GraphQL.Client" Version="1.0.1" />
<PackageReference Include="Xamarin.Forms" VersionOverride="4.0.0.425677" />
<PackageReference Include="Xamarin.Essentials" VersionOverride="1.0.0" />
<PackageReference Include="Fabulous.Core" VersionOverride="0.35.0" />
<PackageReference Include="Fabulous.CustomControls" VersionOverride="0.35.0" />
<PackageReference Include="Fabulous.LiveUpdate" VersionOverride="0.35.0" />
<PackageReference Include="FSharp.Core" VersionOverride="4.6.2" />
<PackageReference Include="Newtonsoft.Json" VersionOverride="13.0.1" />
<PackageReference Include="FSharp.Data.GraphQL.Client" VersionOverride="1.0.1" />
<Compile Include="CharacterDetailPage.fs" />
<Compile Include="MainPage.fs" />
<Compile Include="StarWars.fs" />
</ItemGroup>
</Project>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<ExcludeAssets>contentFiles;runtime</ExcludeAssets>
</PackageReference>
<PackageReference Include="FSharp.TypeProviders.SDK" VersionOverride="8.1.0" />
<PackageReference Include="FSharp.SystemTextJson" />
<PackageReference Include="FsToolkit.ErrorHandling" />
<PackageReference Include="FParsec" />
<PackageReference Include="Microsoft.Extensions.Http">
Expand All @@ -29,8 +30,6 @@

<ItemGroup>
<Compile Include="..\FSharp.Data.GraphQL.Client\MimeTypes.fs" />
<Compile Include="..\FSharp.Data.GraphQL.Client\TextConversions.fs" />
<Compile Include="..\FSharp.Data.GraphQL.Client\JsonValue.fs" />
<Compile Include="..\FSharp.Data.GraphQL.Client\Extensions.fs" />
<Compile Include="..\FSharp.Data.GraphQL.Client\Schema.fs" />
<Compile Include="..\FSharp.Data.GraphQL.Client\ReflectionPatterns.fs" />
Expand Down
26 changes: 16 additions & 10 deletions src/FSharp.Data.GraphQL.Client.DesignTime/ProvidedTypesHelper.fs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ open System.Collections
open System.Collections.Generic
open System.Net.Http
open System.Reflection
open System.Text.Json
open System.Text.Json.Serialization
open FSharp.Core
open FSharp.Data.GraphQL
Expand Down Expand Up @@ -333,7 +334,7 @@ module internal ProvidedOperation =
let serverUrl = info.ServerUrl
let headerNames = info.HttpHeaders |> Seq.map fst |> Array.ofSeq
let headerValues = info.HttpHeaders |> Seq.map snd |> Array.ofSeq
<@@ { ServerUrl = serverUrl; HttpHeaders = Array.zip headerNames headerValues; Connection = new GraphQLClientConnection() } @@>
<@@ { ServerUrl = serverUrl; HttpHeaders = Array.zip headerNames headerValues; Connection = new GraphQLClientConnection(); JsonSerializerOptions = Serialization.defaultSerializerOptions.Value } @@>
| None -> <@@ Unchecked.defaultof<GraphQLProviderRuntimeContext> @@>
// We need to use the combination strategy to generate overloads for variables in the Run/AsyncRun methods.
// The strategy follows the same principle with ProvidedRecord constructor overloads,
Expand Down Expand Up @@ -403,16 +404,16 @@ module internal ProvidedOperation =
HttpHeaders = context.HttpHeaders
OperationName = Option.ofObj operationName
Query = actualQuery
Variables = %%variables }
Variables = %%variables
JsonSerializerOptions = context.JsonSerializerOptions }
let response =
if shouldUseMultipartRequest
then Tracer.runAndMeasureExecutionTime "Ran a multipart GraphQL query request" (fun _ -> GraphQLClient.sendMultipartRequest context.Connection request)
else Tracer.runAndMeasureExecutionTime "Ran a GraphQL query request" (fun _ -> GraphQLClient.sendRequest context.Connection request)
let responseString = response.Content.ReadAsStringAsync().GetAwaiter().GetResult()
let responseJson = Tracer.runAndMeasureExecutionTime "Parsed a GraphQL response to a JsonValue" (fun _ -> JsonValue.Parse responseString)
// If the user does not provide a context, we should dispose the default one after running the query
if isDefaultContext then (context :> IDisposable).Dispose()
OperationResultBase(response, responseJson, %%operationFieldsExpr, operationTypeName) @@>
new OperationResultBase(response, responseString, %%operationFieldsExpr, operationTypeName) @@>
let methodParameters = overloadParameters |> List.map (fun struct (name, _, t) -> ProvidedParameter(name, t, ?optionalValue = if isOption t then Some null else None))
let methodDef = ProvidedMethod("Run", methodParameters, operationResultDef, invoker)
methodDef.AddXmlDoc("Executes the operation on the server and fetch its results.")
Expand Down Expand Up @@ -449,25 +450,25 @@ module internal ProvidedOperation =
HttpHeaders = context.HttpHeaders
OperationName = Option.ofObj operationName
Query = actualQuery
Variables = %%variables }
Variables = %%variables
JsonSerializerOptions = context.JsonSerializerOptions }
async {
let! ct = Async.CancellationToken
let! response =
if shouldUseMultipartRequest
then Tracer.asyncRunAndMeasureExecutionTime "Ran a multipart GraphQL query request asynchronously" (fun _ -> GraphQLClient.sendMultipartRequestAsync ct context.Connection request |> Async.AwaitTask)
else Tracer.asyncRunAndMeasureExecutionTime "Ran a GraphQL query request asynchronously" (fun _ -> GraphQLClient.sendRequestAsync ct context.Connection request |> Async.AwaitTask)
let! responseString = response.Content.ReadAsStringAsync() |> Async.AwaitTask
let responseJson = Tracer.runAndMeasureExecutionTime "Parsed a GraphQL response to a JsonValue" (fun _ -> JsonValue.Parse responseString)
// If the user does not provide a context, we should dispose the default one after running the query
if isDefaultContext then (context :> IDisposable).Dispose()
return OperationResultBase(response, responseJson, %%operationFieldsExpr, operationTypeName)
return new OperationResultBase(response, responseString, %%operationFieldsExpr, operationTypeName)
} @@>
let methodParameters = overloadParameters |> List.map (fun struct (name, _, t) -> ProvidedParameter(name, t, ?optionalValue = if isOption t then Some null else None))
let methodDef = ProvidedMethod("AsyncRun", methodParameters, TypeMapping.makeAsync operationResultDef, invoker)
methodDef.AddXmlDoc("Executes the operation asynchronously on the server and fetch its results.")
upcast methodDef)
let parseResultDef =
let invoker (args : Expr list) = <@@ OperationResultBase(%%args.[1], JsonValue.Parse %%args.[2], %%operationFieldsExpr, operationTypeName) @@>
let invoker (args : Expr list) = <@@ new OperationResultBase(%%args.[1], %%args.[2], %%operationFieldsExpr, operationTypeName) @@>
let parameters = [
ProvidedParameter("rawResponse", typeof<HttpResponseMessage>)
ProvidedParameter("responseJson", typeof<string>)
Expand Down Expand Up @@ -753,7 +754,8 @@ module internal Provider =
| _ -> ProvidedParameter("serverUrl", typeof<string>)
let httpHeaders = ProvidedParameter("httpHeaders", typeof<seq<string * string>>, optionalValue = null)
let connectionFactory = ProvidedParameter("connectionFactory", typeof<unit -> GraphQLClientConnection>, optionalValue = null)
[serverUrl; httpHeaders; connectionFactory]
let jsonSerializerOptions = ProvidedParameter("jsonSerializerOptions", typeof<JsonSerializerOptions>, optionalValue = null)
[serverUrl; httpHeaders; connectionFactory; jsonSerializerOptions]
let defaultHttpHeadersExpr =
let names = httpHeaders |> Seq.map fst |> Array.ofSeq
let values = httpHeaders |> Seq.map snd |> Array.ofSeq
Expand All @@ -768,7 +770,11 @@ module internal Provider =
match %%args.[2] : unit -> GraphQLClientConnection with
| argHeaders when obj.Equals(argHeaders, null) -> fun () -> new GraphQLClientConnection()
| argHeaders -> argHeaders
{ ServerUrl = %%serverUrl; HttpHeaders = httpHeaders; Connection = connectionFactory() } @@>
let jsonOptions =
match %%args.[3] : JsonSerializerOptions with
| null -> Serialization.defaultSerializerOptions.Value
| opts -> opts
{ ServerUrl = %%serverUrl; HttpHeaders = httpHeaders; Connection = connectionFactory(); JsonSerializerOptions = jsonOptions } @@>
ProvidedMethod("GetContext", methodParameters, typeof<GraphQLProviderRuntimeContext>, invoker, isStatic = true)
let operationMethodDef =
let staticParams =
Expand Down
Loading
Loading