<commit_before>namespace FSharp.Data.GraphQL.Server.Middlewares

open FSharp.Data.GraphQL
open FSharp.Data.GraphQL.Types.Patterns
open FSharp.Data.GraphQL.Types
open FSharp.Data.GraphQL.Execution

type internal QueryWeightMiddleware(threshold : float, reportToMetadata : bool) =
    let middleware (threshold : float) (ctx : ExecutionContext) (next : ExecutionContext -> AsyncVal<GQLResponse>) =
        let measureThreshold (threshold : float) (fields : ExecutionInfo list) =
            let getWeight f =
                if f.ParentDef = upcast ctx.ExecutionPlan.RootDef 
                then 0.0
                else
                    match f.Definition.Metadata.TryFind<float>("queryWeight") with
                    | Some w -> w
                    | None -> 0.0
            let rec checkThreshold acc fields =
                match fields with
                | [] -> (true, acc)
                | x :: xs ->
                    let current = acc + (getWeight x)
                    if current > threshold then (false, current)
                    else match x.Kind with
                         | SelectFields fields ->
                            let (pass, current) = checkThreshold current fields
                            if pass then checkThreshold current xs else (false, current)
                         | ResolveCollection field ->
                            let (pass, current) = checkThreshold acc [ field ]
                            if pass then checkThreshold current xs else (false, current)
                         | ResolveAbstraction typeFields ->
                            let fields = typeFields |> Map.toList |> List.collect (fun (_, v) -> v)
                            let (pass, current) = checkThreshold current fields
                            if pass then checkThreshold current xs else (false, current)
                         | _ ->
                            checkThreshold current xs
            checkThreshold 0.0 fields
        // let directFields = ctx.ExecutionPlan.Fields
        // let fields = directFields
        let error (ctx : ExecutionContext) =
            GQLResponse.ErrorAsync("Query complexity exceeds maximum threshold. Please reduce query complexity and try again.", ctx.Metadata)
        let (pass, totalWeight) = measureThreshold threshold ctx.ExecutionPlan.Fields
        let ctx =
            match reportToMetadata with
            | true -> { ctx with Metadata = ctx.Metadata.Add("queryWeightThreshold", threshold).Add("queryWeight", totalWeight) }
            | false -> ctx
        if pass
        then next ctx
        else error ctx
    interface IExecutorMiddleware with
        member __.CompileSchema = None
        member __.PostCompileSchema = None
        member __.PlanOperation = None
        member __.ExecuteOperationAsync = Some (middleware threshold)

type internal ObjectListFilterMiddleware<'ObjectType, 'ListType>(reportToMetadata : bool) =<commit_msg>Fix issue with QueryCostMiddleware + deferred<commit_after>namespace FSharp.Data.GraphQL.Server.Middlewares

open FSharp.Data.GraphQL
open FSharp.Data.GraphQL.Types.Patterns
open FSharp.Data.GraphQL.Types
open FSharp.Data.GraphQL.Execution

type internal QueryWeightMiddleware(threshold : float, reportToMetadata : bool) =
    let middleware (threshold : float) (ctx : ExecutionContext) (next : ExecutionContext -> AsyncVal<GQLResponse>) =
        let measureThreshold (threshold : float) (fields : ExecutionInfo list) =
            let getWeight f =
                if f.ParentDef = upcast ctx.ExecutionPlan.RootDef 
                then 0.0
                else
                    match f.Definition.Metadata.TryFind<float>("queryWeight") with
                    | Some w -> w
                    | None -> 0.0
            // let rec getFields = function
            //     | ResolveValue -> []
            //     | SelectFields fields -> fields
            //     | ResolveCollection field -> [ field ]
            //     | ResolveAbstraction typeFields -> typeFields |> Map.toList |> List.collect snd
            //     | ResolveDeferred info -> getFields info.Kind
            //     | ResolveStreamed (info, _) -> getFields info.Kind
            //     | ResolveLive info -> getFields info.Kind
            let rec checkThreshold acc fields =
                match fields with
                | [] -> (true, acc)
                | x :: xs ->
                    let current = acc + (getWeight x)
                    if current > threshold then (false, current)
                    else match x.Kind with
                         | ResolveValue -> checkThreshold current xs
                         | SelectFields fields ->
                            let (pass, current) = checkThreshold current fields
                            if pass then checkThreshold current xs else (false, current)
                         | ResolveCollection field ->
                            let (pass, current) = checkThreshold acc [ field ]
                            if pass then checkThreshold current xs else (false, current)
                         | ResolveAbstraction typeFields ->
                            let fields = typeFields |> Map.toList |> List.collect (fun (_, v) -> v)
                            let (pass, current) = checkThreshold current fields
                            if pass then checkThreshold current xs else (false, current)
                         | ResolveDeferred info -> checkThreshold current (info :: xs)
                         | ResolveStreamed (info, _) -> checkThreshold current (info :: xs)
                         | ResolveLive info -> checkThreshold current (info :: xs)
            checkThreshold 0.0 fields
        let error (ctx : ExecutionContext) =
            GQLResponse.ErrorAsync("Query complexity exceeds maximum threshold. Please reduce query complexity and try again.", ctx.Metadata)
        let (pass, totalWeight) = measureThreshold threshold ctx.ExecutionPlan.Fields
        let ctx =
            match reportToMetadata with
            | true -> { ctx with Metadata = ctx.Metadata.Add("queryWeightThreshold", threshold).Add("queryWeight", totalWeight) }
            | false -> ctx
        if pass
        then next ctx
        else error ctx
    interface IExecutorMiddleware with
        member __.CompileSchema = None
        member __.PostCompileSchema = None
        member __.PlanOperation = None
        member __.ExecuteOperationAsync = Some (middleware threshold)

type internal ObjectListFilterMiddleware<'ObjectType, 'ListType>(reportToMetadata : bool) =
{'fraction_non_alphanumeric': 0.07472226449551057, 'fraction_numerical': 0.0018262060569167555, 'mean_word_length': 1.71345995045417, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '982151', 'n_tokens_mistral': 1533, 'n_tokens_neox': 1468, 'n_words': 476}