From 552ea0ea151abfe8e6495dcb713bff86dbbb47e9 Mon Sep 17 00:00:00 2001 From: Joseph Roorda Date: Fri, 3 Sep 2021 14:22:42 -0400 Subject: [PATCH] Add abstraction for ASP.NET initialization, Add AutoOpen to several common submodules --- src/Dash.NET/DashApp.fs | 63 ++++++++++++++++++- src/Dash.NET/DashComponents/ComponentBase.fs | 1 + .../DashComponents/HTMLComponents/Html.fs | 2 + src/Dash.NET/DashConfig.fs | 34 +++++++++- src/Dash.NET/Operators.fs | 1 + 5 files changed, 98 insertions(+), 3 deletions(-) diff --git a/src/Dash.NET/DashApp.fs b/src/Dash.NET/DashApp.fs index d3d1d38..3d64a0b 100644 --- a/src/Dash.NET/DashApp.fs +++ b/src/Dash.NET/DashApp.fs @@ -5,8 +5,17 @@ open Giraffe.ViewEngine open Views open Plotly.NET open System -open System.Collections.Generic -open System.Runtime.InteropServices +open System.IO + +open Microsoft.AspNetCore.Builder +open Microsoft.AspNetCore.Cors.Infrastructure +open Microsoft.AspNetCore.Hosting +open Microsoft.Extensions.Hosting +open Microsoft.Extensions.Logging +open Microsoft.Extensions.DependencyInjection + +[] +do () type DashApp = { @@ -153,3 +162,53 @@ type DashApp = ] setStatusCode 404 >=> text "Not Found" ] + + static member run (args: string []) (app: DashApp) = + //TODO: make this customizable + let errorHandler (ex : Exception) (logger : ILogger) = + logger.LogError(ex, "An unhandled exception has occurred while executing the request.") + clearResponse >=> setStatusCode 500 >=> (app.Config.ErrorHandler ex) + + let configureCors (builder : CorsPolicyBuilder) = + builder.WithOrigins(sprintf "http://%s:8080" app.Config.HostName) + .AllowAnyMethod() + .AllowAnyHeader() + |> ignore + + let configureApp (appBuilder : IApplicationBuilder) = + let env = appBuilder.ApplicationServices.GetService() + (match env.EnvironmentName with + | "Development" -> appBuilder.UseDeveloperExceptionPage() + | _ -> appBuilder.UseGiraffeErrorHandler(errorHandler)) + .UseHttpsRedirection() + .UseCors(configureCors) + .UseStaticFiles() + .UseGiraffe(DashApp.toHttpHandler app) + + let configureServices (services : IServiceCollection) = + services.AddCors() |> ignore + services.AddGiraffe() |> ignore + + let configureLogging (builder : ILoggingBuilder) = + builder.AddFilter(fun l -> l.Equals app.Config.LogLevel) + .AddConsole() + .AddDebug() |> ignore + + // This folder has to be "/WebRoot" for the way generated component javascript injection currently works + let contentRoot = Reflection.Assembly.GetExecutingAssembly().Location |> Path.GetDirectoryName + let webRoot = Path.Combine(contentRoot, "WebRoot") + + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults( + fun webHostBuilder -> + webHostBuilder + .UseContentRoot(contentRoot) + .UseWebRoot(webRoot) + .Configure(Action configureApp) + .ConfigureServices(configureServices) + .ConfigureLogging(configureLogging) + |> ignore) + .Build() + .Run() + + 0 diff --git a/src/Dash.NET/DashComponents/ComponentBase.fs b/src/Dash.NET/DashComponents/ComponentBase.fs index 0a11afa..790c309 100644 --- a/src/Dash.NET/DashComponents/ComponentBase.fs +++ b/src/Dash.NET/DashComponents/ComponentBase.fs @@ -33,6 +33,7 @@ type DashComponentStyle() = inherit DynamicObj() type DashComponentProps() = inherit DynamicObj() +[] module ComponentPropTypes = type InputType = diff --git a/src/Dash.NET/DashComponents/HTMLComponents/Html.fs b/src/Dash.NET/DashComponents/HTMLComponents/Html.fs index 2f76b92..845a955 100644 --- a/src/Dash.NET/DashComponents/HTMLComponents/Html.fs +++ b/src/Dash.NET/DashComponents/HTMLComponents/Html.fs @@ -7,6 +7,7 @@ open Plotly.NET /// https://github.com/alfonsogarciacaro/Feliz.Engine /// and are available under the Dash.NET.Html module. +[] module Css = type Style = StyleProperty of string * obj @@ -14,6 +15,7 @@ module Css = let Css = Feliz.CssEngine(fun k v -> StyleProperty(k, v)) +[] module Html = open Css diff --git a/src/Dash.NET/DashConfig.fs b/src/Dash.NET/DashConfig.fs index 2f1a66d..aa4b4bd 100644 --- a/src/Dash.NET/DashConfig.fs +++ b/src/Dash.NET/DashConfig.fs @@ -3,6 +3,10 @@ open Newtonsoft.Json open Plotly.NET +open System +open Giraffe +open Microsoft.Extensions.Logging + type HotReloadSettings = { [] @@ -14,6 +18,7 @@ type HotReloadSettings = //todo: use standard casing and add serialization flags instead. type DashConfig = { + //Dash Specific [] UrlBasePathname: string Option [] @@ -30,6 +35,14 @@ type DashConfig = SuppressCallbackExceptions: bool [] UpdateTitle: string + + //Giraffe, Logging and ASP.NET specific + [] + HostName: string + [] + LogLevel: LogLevel + [] + ErrorHandler: Exception -> HttpHandler } static member create urlBasePathname @@ -40,6 +53,10 @@ type DashConfig = showUndoRedo suppressCallbackExceptions updateTitle + + hostName + logLevel + errorHandler = { UrlBasePathname = urlBasePathname @@ -51,9 +68,24 @@ type DashConfig = SuppressCallbackExceptions = suppressCallbackExceptions UpdateTitle = updateTitle //hot_reload = {Intervall = 3000; MaxRetry = 8} + + HostName = hostName + LogLevel = logLevel + ErrorHandler = errorHandler } static member initDefault() = - DashConfig.create None "/" false true true false false "Updating..." + DashConfig.create + None + "/" + false + true + true + false + false + "Updating..." + "localhost" + LogLevel.Debug + ((fun ex -> ex.Message) >> text) static member initDefaultWith(initializer: DashConfig -> DashConfig) = DashConfig.initDefault () |> initializer diff --git a/src/Dash.NET/Operators.fs b/src/Dash.NET/Operators.fs index 6833ebd..bfbe17d 100644 --- a/src/Dash.NET/Operators.fs +++ b/src/Dash.NET/Operators.fs @@ -1,5 +1,6 @@ namespace Dash.NET +[] module Operators = /// Shorthand for creation of a dependency (binding of the property of a component)