open Giraffe open Microsoft.AspNetCore.Http open Microsoft.AspNetCore.Builder open Microsoft.Extensions.DependencyInjection open Microsoft.Extensions.Hosting open Thoth.Json type QueryFilter = | Equal of string * string | GreaterThan of string * float | LessThan of string * float type QueryDSL = { Select : string list Filters : QueryFilter list Sort : (string * string) list // Field and direction } let parseQuery (body: string) = // Example JSON parsing (using FSharp.Data or similar) // Example query JSON: // { "select": ["name", "age"], "filters": [{"field": "age", "op": "gt", "value": 30}], "sort": [["name", "asc"]] } try let query = Decode.Auto.fromString body // let parsed = FSharp.Data.JsonValue.Parse(body) //let selectFields = parsed.["select"].AsArray() |> Array.map string |> List.ofArray //let filters = // parsed.["filters"].AsArray() // |> Array.map (fun filter -> // match filter.["op"].AsString() with // | "eq" -> Equal(filter.["field"].AsString(), filter.["value"].AsString()) // | "gt" -> GreaterThan(filter.["field"].AsString(), filter.["value"].AsFloat()) // | "lt" -> LessThan(filter.["field"].AsString(), filter.["value"].AsFloat()) // | _ -> failwith "Unsupported filter") // |> List.ofArray //let sort = // parsed.["sort"].AsArray() // |> Array.map (fun s -> s.[0].AsString(), s.[1].AsString()) // |> List.ofArray //{ Select = selectFields; Filters = filters; Sort = sort } query with | ex -> failwithf "Failed to parse query: %s" ex.Message let fetchData (queryDsl: QueryDSL) = // Mock database query (replace with actual DB logic) let mockData = [ {| name = "Alice"; age = 30 |} {| name = "Bob"; age = 25 |} {| name = "Charlie"; age = 35 |} ] // Filter and transform the data based on the DSL mockData |> List.filter (fun row -> queryDsl.Filters |> List.forall (function | Equal(field, value) -> row.[field] = value | GreaterThan(field, num) -> row.[field] |> float > num | LessThan(field, num) -> row.[field] |> float < num)) |> List.map (fun row -> queryDsl.Select |> List.map (fun field -> field, row.[field]) |> dict) |> fun result -> result let queryHandler (next: HttpFunc) (ctx: HttpContext) = task { let! body = ctx.ReadBodyAsStringAsync() let queryDsl = parseQuery body let data = fetchData queryDsl return! json data next ctx } let webApp = choose [ POST "/query" >=> queryHandler RequestErrors.notFound "Not Found" ] let configureApp (app: IApplicationBuilder) = app.UseGiraffe webApp let configureServices (services: IServiceCollection) = services.AddGiraffe() |> ignore [] let main args = Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(fun webBuilder -> webBuilder //.Configure(configureApp) .ConfigureServices(configureServices) |> ignore) .Build() .Run() 0