Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Made Schema optional params as structs
  • Loading branch information
xperiandri committed Sep 19, 2026
commit a3911d7a9cb8a67bb0a3607f6a60be076e15f641
8 changes: 4 additions & 4 deletions src/FSharp.Data.GraphQL.Server/Execution.fs
Original file line number Diff line number Diff line change
Expand Up @@ -754,13 +754,13 @@ let internal executeOperation (ctx : ExecutionContext) : AsyncVal<GQLExecutionRe
| Query -> executeQueryOrMutation resultSet ctx ctx.Schema.Query ctx.RootValue
| Mutation ->
match ctx.Schema.Mutation with
| Some m -> executeQueryOrMutation resultSet ctx m ctx.RootValue
| None -> raise(InvalidOperationException("Attempted to make a mutation but no mutation schema was present!"))
| ValueSome m -> executeQueryOrMutation resultSet ctx m ctx.RootValue
| ValueNone -> raise(InvalidOperationException("Attempted to make a mutation but no mutation schema was present!"))
| Subscription ->
match ctx.Schema.Subscription with
| Some s ->
| ValueSome s ->
match executeSubscription resultSet ctx.GetInputContext ctx s ctx.RootValue with
| Ok data -> AsyncVal.wrap(GQLExecutionResult.Stream(ctx.ExecutionPlan.DocumentId, data, ctx.Metadata))
| Error errs -> asyncVal { return GQLExecutionResult.Error(ctx.ExecutionPlan.DocumentId, errs, ctx.Metadata) }

| None -> raise(InvalidOperationException("Attempted to make a subscription but no subscription schema was present!"))
| ValueNone -> raise(InvalidOperationException("Attempted to make a subscription but no subscription schema was present!"))
8 changes: 4 additions & 4 deletions src/FSharp.Data.GraphQL.Server/Executor.fs
Original file line number Diff line number Diff line change
Expand Up @@ -146,15 +146,15 @@ type Executor<'Root>(schema: ISchema<'Root>, middlewares : IExecutorMiddleware s
| Query -> Ok schema.Query
| Mutation ->
match schema.Mutation with
| Some m -> Ok m
| None -> Error <| [ GQLProblemDetails.CreateWithKind (
| ValueSome m -> Ok m
| ValueNone -> Error <| [ GQLProblemDetails.CreateWithKind (
"Operation to be executed is of type mutation, but no mutation root object was defined in current schema",
ErrorKind.Validation
)]
| Subscription ->
match schema.Subscription with
| Some s -> Ok <| upcast s
| None -> Error <| [ GQLProblemDetails.CreateWithKind (
| ValueSome s -> Ok <| upcast s
| ValueNone -> Error <| [ GQLProblemDetails.CreateWithKind (
"Operation to be executed is of type subscription, but no subscription root object was defined in the current schema",
ErrorKind.Validation
)]
Expand Down
8 changes: 4 additions & 4 deletions src/FSharp.Data.GraphQL.Server/Planning.fs
Original file line number Diff line number Diff line change
Expand Up @@ -403,31 +403,31 @@ let internal planOperation (ctx: PlanningContext) : ExecutionPlan =
Metadata = ctx.Metadata }
| Mutation ->
match ctx.Schema.Mutation with
| Some mutationDef ->
| ValueSome mutationDef ->
{ DocumentId = ctx.DocumentId
Operation = ctx.Operation
RootDef = mutationDef
Fields = fields
Variables = variables
Strategy = Sequential
Metadata = ctx.Metadata }
| None ->
| ValueNone ->
Debug.Fail "Must be prevented by validation"
raise (
MalformedGQLQueryException
"Operation to be executed is of type mutation, but no mutation root object was defined in current schema"
)
| Subscription ->
match ctx.Schema.Subscription with
| Some subscriptionDef ->
| ValueSome subscriptionDef ->
{ DocumentId = ctx.DocumentId
Operation = ctx.Operation
RootDef = subscriptionDef
Fields = fields
Variables = variables
Strategy = Sequential
Metadata = ctx.Metadata }
| None ->
| ValueNone ->
Debug.Fail "Must be prevented by validation"
raise (
MalformedGQLQueryException
Expand Down
15 changes: 7 additions & 8 deletions src/FSharp.Data.GraphQL.Server/Schema.fs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ type SchemaConfig =
Directives = [ IncludeDirective; SkipDirective; DeferDirective; streamDirective; LiveDirective ] }

/// GraphQL server schema. Defines the complete type system to be used by GraphQL queries.
type Schema<'Root> (query: ObjectDef<'Root>, ?mutation: ObjectDef<'Root>, ?subscription: SubscriptionObjectDef<'Root>, ?config: SchemaConfig) =
type Schema<'Root> (query: ObjectDef<'Root>, [<Struct>] ?mutation: ObjectDef<'Root>, [<Struct>] ?subscription: SubscriptionObjectDef<'Root>, ?config: SchemaConfig) =

let schemaConfig =
match config with
Expand All @@ -191,8 +191,8 @@ type Schema<'Root> (query: ObjectDef<'Root>, ?mutation: ObjectDef<'Root>, ?subsc
__Schema
query ]

let m = mutation |> function Some (Named n) -> [n] | _ -> []
let s = subscription |> function Some (Named n) -> [n] | _ -> []
let m = mutation |> function ValueSome (Named n) -> [n] | _ -> []
let s = subscription |> function ValueSome (Named n) -> [n] | _ -> []
seq { initialTypes; s; m; schemaConfig.Types } |> Seq.collect id |> TypeMap.FromSeq

let getImplementations (typeMap : TypeMap) =
Expand Down Expand Up @@ -349,9 +349,8 @@ type Schema<'Root> (query: ObjectDef<'Root>, ?mutation: ObjectDef<'Root>, ?subsc
|> List.map (introspectDirective inamed)
|> List.toArray
{ QueryType = Map.find query.Name inamed
// TODO: `mutation`/`subscription` are still `'T option` (Schema's constructor is out of scope for this change) - convert here until that follow-up moves Schema to [<Struct>] ?.
MutationType = mutation |> ValueOption.ofOption |> ValueOption.map (fun m -> Map.find m.Name inamed)
SubscriptionType = subscription |> ValueOption.ofOption |> ValueOption.map(fun s -> Map.find s.Name inamed)
MutationType = mutation |> ValueOption.map (fun m -> Map.find m.Name inamed)
SubscriptionType = subscription |> ValueOption.map (fun s -> Map.find s.Name inamed)
Types = itypes
Directives = idirectives }

Expand Down Expand Up @@ -382,8 +381,8 @@ type Schema<'Root> (query: ObjectDef<'Root>, ?mutation: ObjectDef<'Root>, ?subsc
member _.Directives = schemaConfig.Directives |> List.toArray
member _.Introspected = introspected.Force()
member _.Query = upcast query
member _.Mutation = mutation |> Option.map (fun x -> upcast x)
member _.Subscription = subscription |> Option.map (fun x -> upcast x)
member _.Mutation = mutation |> ValueOption.map (fun x -> upcast x)
member _.Subscription = subscription |> ValueOption.map (fun x -> upcast x)
member _.TryFindType typeName = typeMap.TryFind(typeName, includeDefaultTypes = true)
member _.GetPossibleTypes typedef = getPossibleTypes typedef
member _.ParseError path exn = schemaConfig.ParseError path exn
Expand Down
8 changes: 4 additions & 4 deletions src/FSharp.Data.GraphQL.Shared/TypeSystem.fs
Original file line number Diff line number Diff line change
Expand Up @@ -428,11 +428,11 @@ and ISchema =

/// A mutation root object. Defines all top level operations,
/// that can be performed from GraphQL mutations.
abstract Mutation : ObjectDef option
abstract Mutation : ObjectDef voption

// A subscription root object. Defines all top level operations,
// that can be performed from GraphQL subscriptions.
abstract Subscription : SubscriptionObjectDef option
abstract Subscription : SubscriptionObjectDef voption

/// List of all directives supported by the current schema.
abstract Directives : DirectiveDef[]
Expand Down Expand Up @@ -472,8 +472,8 @@ and ISchema<'Root> =
interface
inherit ISchema
abstract Query : ObjectDef<'Root>
abstract Mutation : ObjectDef<'Root> option
abstract Subscription : SubscriptionObjectDef<'Root> option
abstract Mutation : ObjectDef<'Root> voption
abstract Subscription : SubscriptionObjectDef<'Root> voption
end

/// A type alias for a field execute compiler function.
Expand Down
26 changes: 13 additions & 13 deletions src/FSharp.Data.GraphQL.Shared/Validation.fs
Original file line number Diff line number Diff line change
Expand Up @@ -904,8 +904,8 @@ module Ast =
=
let visitCount =
visited
|> List.filter (fun x -> x = fragName)
|> List.length
|> Seq.filter (fun x -> x = fragName)
|> Seq.length
if visitCount > 1 then
AstError.AsResult $"Fragment '%s{fragName}' is making a cyclic reference."
else
Expand Down Expand Up @@ -961,7 +961,7 @@ module Ast =
|> getFragmentAndParentTypes
|> ValidationResult.collect (checkFragmentSpreadIsPossibleInSelection))

let private checkInputValue (schemaInfo : SchemaInfo) (variables : VariableDefinition list option) (selection : SelectionInfo) =
let private checkInputValue (schemaInfo : SchemaInfo) (variables : VariableDefinition list voption) (selection : SelectionInfo) =
let rec checkIsCoercible (tref : IntrospectionTypeRef) (argName : string) (value : InputValue) =
let canNotCoerce =
AstError.AsResult (
Expand Down Expand Up @@ -1045,15 +1045,15 @@ module Ast =
| VariableName varName ->
let variableDefinition =
variables
|> Option.defaultValue []
|> List.tryPick (fun v ->
|> ValueOption.defaultValue []
|> List.vtryPick (fun v ->
if v.VariableName = varName then
Some (v, schemaInfo.TryGetInputType (v.Type))
ValueSome (v, schemaInfo.TryGetInputType (v.Type))
else
None)
ValueNone)
match variableDefinition with
| Some (vdef, Some vtype) when vdef.DefaultValue.IsSome -> checkIsCoercible vtype argName vdef.DefaultValue.Value
| Some (vdef, None) when vdef.DefaultValue.IsSome -> canNotCoerce
| ValueSome (vdef, Some vtype) when vdef.DefaultValue.IsSome -> checkIsCoercible vtype argName vdef.DefaultValue.Value
| ValueSome (vdef, None) when vdef.DefaultValue.IsSome -> canNotCoerce
| _ -> Success
selection.Field.Arguments
|> ValidationResult.collect (fun arg ->
Expand All @@ -1067,10 +1067,10 @@ module Ast =
let internal validateInputValues (ctx : ValidationContext) =
ctx.Definitions
|> ValidationResult.collect (fun def ->
let (vars, selectionSet) =
let struct (vars, selectionSet) =
match def with
| OperationDefinitionInfo odef -> (Some odef.Definition.VariableDefinitions, odef.SelectionSet)
| FragmentDefinitionInfo fdef -> (None, fdef.SelectionSet)
| OperationDefinitionInfo odef -> struct (ValueSome odef.Definition.VariableDefinitions, odef.SelectionSet)
| FragmentDefinitionInfo fdef -> struct (ValueNone, fdef.SelectionSet)
selectionSet
|> ValidationResult.collect (checkInputValue ctx.Schema vars))

Expand All @@ -1096,7 +1096,7 @@ module Ast =
let selectionSetDirectives =
frag.SelectionSet
|> List.collect (getDistinctDirectiveNamesInSelection path)
fragDirectives |> List.append selectionSetDirectives
fragDirectives @ selectionSetDirectives

let internal validateDirectivesDefined (ctx : ValidationContext) =
ctx.Definitions
Expand Down
Loading