Skip to content

Commit

Permalink
refact: moving websockets code to .Shared to prepare for client impl. (
Browse files Browse the repository at this point in the history
…#504)

* refact: moving websockets code to .Shared to prepare for client impl.

  We intend to implement the client part now. It's useful to share
contract-related code between client and server implementations.

* `IDictionary<string, obj>` -> `Output` (changing back)

* Applied suggestions of @xperiandrii

* moved NameValueLookup to Output.fs

  according to @xperiandrii's suggestion

* Use of deprecated GraphQLPlayground was causing the build to fail

  According to the failure message, one should use GraphiQL instead

* correction: reintroduced escape character for new line

Co-authored-by: Andrii Chebukin <XperiAndri@Outlook.com>

* removed deprecated GraphQL playground

---------

Co-authored-by: Andrii Chebukin <XperiAndri@Outlook.com>
  • Loading branch information
valbers and xperiandri authored Dec 7, 2024
1 parent 51c665b commit 891e36d
Show file tree
Hide file tree
Showing 46 changed files with 194 additions and 193 deletions.
1 change: 0 additions & 1 deletion Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@
<PackageReference Update="FsToolkit.ErrorHandling" Version="4.15.3" />
<PackageReference Update="GraphQL.Server.Ui.Altair" Version="8.*" />
<PackageReference Update="GraphQL.Server.Ui.GraphiQL" Version="8.*" />
<PackageReference Update="GraphQL.Server.Ui.Playground" Version="8.*" />
<PackageReference Update="GraphQL.Server.Ui.Voyager" Version="8.*" />
<PackageReference Update="HotChocolate.AspNetCore" Version="14.*" />
<PackageReference Update="Iced" Version="1.17.*" />
Expand Down
1 change: 0 additions & 1 deletion samples/chat-app/server/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ let main args =
if app.Environment.IsDevelopment () then
app.UseGraphQLAltair "/altair" |> ignore
app.UseGraphQLGraphiQL "/graphiql" |> ignore
app.UseGraphQLPlayground "/playground" |> ignore
app.UseGraphQLVoyager "/voyager" |> ignore
app.UseRouting () |> ignore
app.UseEndpoints (fun endpoints -> endpoints.MapNitroApp (PathString "/nitro") |> ignore)
Expand Down
1 change: 0 additions & 1 deletion samples/chat-app/server/chat-app.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
<PackageReference Include="FsToolkit.ErrorHandling.TaskResult" />
<PackageReference Include="GraphQL.Server.Ui.Altair" />
<PackageReference Include="GraphQL.Server.Ui.GraphiQL" />
<PackageReference Include="GraphQL.Server.Ui.Playground" />
<PackageReference Include="GraphQL.Server.Ui.Voyager" />
<PackageReference Include="HotChocolate.AspNetCore" />
</ItemGroup>
Expand Down
1 change: 0 additions & 1 deletion samples/relay-book-store/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ let main argv =
if app.Environment.IsDevelopment () then
app.UseGraphQLAltair "/altair" |> ignore
app.UseGraphQLGraphiQL "/graphiql" |> ignore
app.UseGraphQLPlayground "/playground" |> ignore
app.UseGraphQLVoyager "/voyager" |> ignore
app.UseRouting () |> ignore
app.UseEndpoints (fun endpoints -> endpoints.MapNitroApp (PathString "/nitro") |> ignore)
Expand Down
1 change: 0 additions & 1 deletion samples/relay-book-store/relay-book-store.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
<PackageReference Include="Giraffe" />
<PackageReference Include="GraphQL.Server.Ui.Altair" />
<PackageReference Include="GraphQL.Server.Ui.GraphiQL" />
<PackageReference Include="GraphQL.Server.Ui.Playground" />
<PackageReference Include="GraphQL.Server.Ui.Voyager" />
<PackageReference Include="HotChocolate.AspNetCore" />
<PackageReference Include="Microsoft.Data.Sqlite" />
Expand Down
1 change: 0 additions & 1 deletion samples/star-wars-api/Startup.fs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ type Startup private () =
if env.IsDevelopment () then
app.UseGraphQLAltair "/altair" |> ignore
app.UseGraphQLGraphiQL "/graphiql" |> ignore
app.UseGraphQLPlayground "/playground" |> ignore
app.UseGraphQLVoyager "/voyager" |> ignore
app.UseRouting () |> ignore
app.UseEndpoints (fun endpoints -> endpoints.MapNitroApp (PathString "/nitro") |> ignore)
Expand Down
1 change: 0 additions & 1 deletion samples/star-wars-api/star-wars-api.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
<PackageReference Include="FsToolkit.ErrorHandling.TaskResult" />
<PackageReference Include="GraphQL.Server.Ui.Altair" />
<PackageReference Include="GraphQL.Server.Ui.GraphiQL" />
<PackageReference Include="GraphQL.Server.Ui.Playground" />
<PackageReference Include="GraphQL.Server.Ui.Voyager" />
<PackageReference Include="HotChocolate.AspNetCore" />
</ItemGroup>
Expand Down
4 changes: 0 additions & 4 deletions src/FSharp.Data.GraphQL.Server.AspNetCore/Exceptions.fs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@

<ItemGroup>
<Compile Include="Helpers.fs" />
<Compile Include="Exceptions.fs" />
<Compile Include="GQLRequest.fs" />
<Compile Include="Messages.fs" />
<Compile Include="Serialization/JsonConverters.fs" />
<Compile Include="Serialization\JSON.fs" />
<Compile Include="GraphQLOptions.fs" />
<Compile Include="GraphQLSubscriptionsManagement.fs" />
<Compile Include="GraphQLWebsocketMiddleware.fs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ open FSharp.Data.GraphQL
open FsToolkit.ErrorHandling

open FSharp.Data.GraphQL.Server
open FSharp.Data.GraphQL.Shared

type DefaultGraphQLRequestHandler<'Root> (
httpContextAccessor : IHttpContextAccessor,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module internal FSharp.Data.GraphQL.Server.AspNetCore.GraphQLSubscriptionsManagement

open FSharp.Data.GraphQL.Server.AspNetCore.WebSockets
open FSharp.Data.GraphQL.Shared.WebSockets

let addSubscription
(id : SubscriptionId, unsubscriber : SubscriptionUnsubscriber, onUnsubscribe : OnUnsubscribeAction)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ open FsToolkit.ErrorHandling

open FSharp.Data.GraphQL
open FSharp.Data.GraphQL.Execution
open FSharp.Data.GraphQL.Server.AspNetCore.WebSockets
open FSharp.Data.GraphQL.Shared.WebSockets

type GraphQLWebSocketMiddleware<'Root>
(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ module ServiceCollectionExtensions =
SchemaExecutor = executor
RootFactory = rootFactory
ReadBufferSize = GraphQLOptionsDefaults.ReadBufferSize
SerializerOptions = Json.getWSSerializerOptions additionalConverters
SerializerOptions = Shared.Json.getWSSerializerOptions additionalConverters
WebsocketOptions = {
EndpointUrl = endpointUrl
ConnectionInitTimeout = TimeSpan.FromMilliseconds (GraphQLOptionsDefaults.WebSocketConnectionInitTimeoutInMs)
Expand Down Expand Up @@ -67,7 +67,7 @@ module ServiceCollectionExtensions =
// Use if you want to return HTTP responses using minmal APIs IResult interface
.Configure<HttpClientJsonOptions>(
Action<HttpClientJsonOptions>(fun o ->
Json.configureDefaultSerializerOptions additionalConverters o.SerializerOptions
Shared.Json.configureDefaultSerializerOptions additionalConverters o.SerializerOptions
)
)
.AddSingleton<IOptionsFactory<GraphQLOptions<'Root>>>(
Expand Down
142 changes: 1 addition & 141 deletions src/FSharp.Data.GraphQL.Server/Execution.fs
Original file line number Diff line number Diff line change
Expand Up @@ -13,158 +13,18 @@ open FSharp.Data.GraphQL.Ast
open FSharp.Data.GraphQL.Errors
open FSharp.Data.GraphQL.Extensions
open FSharp.Data.GraphQL.Helpers
open FSharp.Data.GraphQL.Shared
open FSharp.Data.GraphQL.Types
open FSharp.Data.GraphQL.Types.Patterns
open FSharp.Data.GraphQL

type Output = IDictionary<string, obj>

let (|RequestError|Direct|Deferred|Stream|) (response : GQLExecutionResult) =
match response.Content with
| RequestError errs -> RequestError errs
| Direct (data, errors) -> Direct (data, errors)
| Deferred (data, errors, deferred) -> Deferred (data, errors, deferred)
| Stream data -> Stream data


/// Name value lookup used as output to be serialized into JSON.
/// It has a form of a dictionary with fixed set of keys. Values under keys
/// can be set, but no new entry can be added or removed, once lookup
/// has been initialized.
/// This dictionary implements structural equality.
type NameValueLookup(keyValues: KeyValuePair<string, obj> []) =

let kvals = keyValues |> Array.distinctBy (fun kv -> kv.Key)

let setValue key value =
let mutable i = 0
while i < kvals.Length do
if kvals.[i].Key = key then
kvals.[i] <- KeyValuePair<string, obj>(key, value)
i <- Int32.MaxValue
else i <- i+1
let getValue key = (kvals |> Array.find (fun kv -> kv.Key = key)).Value

let (|BoxedSeq|_|) (xs : obj) =
match xs with
| (:? System.Collections.IEnumerable as enumerable) -> Some (Seq.cast<obj> enumerable)
| _ -> None

let rec structEq (x: NameValueLookup) (y: NameValueLookup) =
if Object.ReferenceEquals(x, y) then true
elif Object.ReferenceEquals(y, null) then false
elif Object.ReferenceEquals(x, null) then false
elif x.Count <> y.Count then false
else
x.Buffer
|> Array.forall2 (fun (a: KeyValuePair<string, obj>) (b: KeyValuePair<string, obj>) ->
if a.Key <> b.Key then false
else
match a.Value, b.Value with
| (:? NameValueLookup as x), (:? NameValueLookup as y) -> structEq x y
| (BoxedSeq x), (BoxedSeq y) ->
if Seq.length x <> Seq.length y then false else Seq.forall2 (=) x y
| a1, b1 -> a1 = b1) y.Buffer

let pad (sb: System.Text.StringBuilder) times =
for _ in 0..times do sb.Append("\t") |> ignore

let rec stringify (sb: System.Text.StringBuilder) deep (o:obj) =
match o with
| :? NameValueLookup as lookup ->
if lookup.Count > 0 then
sb.Append("{ ") |> ignore
lookup.Buffer
|> Array.iter (fun kv ->
sb.Append(kv.Key).Append(": ") |> ignore
stringify sb (deep+1) kv.Value
sb.Append(",\r\n") |> ignore
pad sb deep)
sb.Remove(sb.Length - 4 - deep, 4 + deep).Append(" }") |> ignore
| :? string as s ->
sb.Append("\"").Append(s).Append("\"") |> ignore
| :? System.Collections.IEnumerable as s ->
sb.Append("[") |> ignore
for i in s do
stringify sb (deep + 1) i
sb.Append(", ") |> ignore
sb.Append("]") |> ignore
| other ->
if isNull other |> not
then sb.Append(other.ToString()) |> ignore
else sb.Append("null") |> ignore
()
/// Returns raw content of the current lookup.
member _.Buffer : KeyValuePair<string, obj> [] = kvals

/// Return a number of entries stored in current lookup. It's fixed size.
member _.Count = kvals.Length

/// Updates an entry's value under given key. It will throw an exception
/// if provided key cannot be found in provided lookup.
member _.Update key value = setValue key value

override x.Equals(other) =
match other with
| :? NameValueLookup as lookup -> structEq x lookup
| _ -> false

override _.GetHashCode() =
let mutable hash = 0
for kv in kvals do
hash <- (hash*397) ^^^ (kv.Key.GetHashCode()) ^^^ (if isNull kv.Value then 0 else kv.Value.GetHashCode())
hash

override x.ToString() =
let sb = Text.StringBuilder()
stringify sb 1 x
sb.ToString()

interface IEquatable<NameValueLookup> with
member x.Equals(other) = structEq x other

interface System.Collections.IEnumerable with
member _.GetEnumerator() = (kvals :> System.Collections.IEnumerable).GetEnumerator()

interface IEnumerable<KeyValuePair<string, obj>> with
member _.GetEnumerator() = (kvals :> IEnumerable<KeyValuePair<string, obj>>).GetEnumerator()

interface IDictionary<string, obj> with
member _.Add(_, _) = raise (NotSupportedException "NameValueLookup doesn't allow to add/remove entries")
member _.Add(_) = raise (NotSupportedException "NameValueLookup doesn't allow to add/remove entries")
member _.Clear() = raise (NotSupportedException "NameValueLookup doesn't allow to add/remove entries")
member _.Contains(item) = kvals |> Array.exists ((=) item)
member _.ContainsKey(key) = kvals |> Array.exists (fun kv -> kv.Key = key)
member _.CopyTo(array, arrayIndex) = kvals.CopyTo(array, arrayIndex)
member x.Count = x.Count
member _.IsReadOnly = true
member _.Item
with get (key) = getValue key
and set (key) v = setValue key v
member _.Keys = upcast (kvals |> Array.map (fun kv -> kv.Key))
member _.Values = upcast (kvals |> Array.map (fun kv -> kv.Value))
member _.Remove(_:string) =
raise (NotSupportedException "NameValueLookup doesn't allow to add/remove entries")
false
member _.Remove(_:KeyValuePair<string,obj>) =
raise (NotSupportedException "NameValueLookup doesn't allow to add/remove entries")
false
member _.TryGetValue(key, value) =
match kvals |> Array.tryFind (fun kv -> kv.Key = key) with
| Some kv -> value <- kv.Value; true
| None -> value <- null; false

new(t: (string * obj) list) =
NameValueLookup(t |> List.map (fun (k, v) -> KeyValuePair<string,obj>(k, v)) |> List.toArray)

new(t: string []) =
NameValueLookup(t |> Array.map (fun k -> KeyValuePair<string,obj>(k, null)))

module NameValueLookup =
/// Create new NameValueLookup from given list of key-value tuples.
let ofList (l: (string * obj) list) = NameValueLookup(l)


let private collectDefaultArgValue acc (argdef: InputFieldDef) =
match argdef.DefaultValue with
| Some defVal -> Map.add argdef.Name defVal acc
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
</ItemGroup>

<ItemGroup>
<Compile Include="Output.fs" />
<Compile Include="Helpers\Diagnostics.fs" />
<Compile Include="Helpers\ObjAndStructConversions.fs" />
<Compile Include="Helpers\Extensions.fs" />
Expand All @@ -58,6 +59,10 @@
<Compile Include="Validation.fs" />
<Compile Include="ValidationResultCache.fs" />
<Compile Include="Parser.fs" />
<Compile Include="GQLRequest.fs" />
<Compile Include="WebSockets.fs" />
<Compile Include="Serialization/JsonConverters.fs" />
<Compile Include="Serialization/JSON.fs" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace FSharp.Data.GraphQL.Server.AspNetCore
namespace FSharp.Data.GraphQL.Shared

open System.Collections.Immutable
open System.Text.Json
Expand Down
Loading

0 comments on commit 891e36d

Please sign in to comment.