<commit_before>﻿module FSDN.Program

open System.IO
open System.Net
open Suave
open Suave.Web
open Suave.Logging
open Suave.Operators
open Suave.Filters
open Suave.Files
open Argu
open FSharpApiSearch

type Args =
  | Port of Sockets.Port
  | Home_Directory of string
  | Log_Level of string
with
  interface IArgParserTemplate with
    member this.Usage =
      match this with
      | Port _ -> "specify a primary port."
      | Home_Directory _ -> "specify a home or root diretory."
      | Log_Level _ -> "specify log level."

let configAndApp database homeDir (args: ParseResults<Args>) : (SuaveConfig * WebPart) =

  let homeDir = DirectoryInfo(homeDir).FullName
  let logger =
    match args.TryPostProcessResult(<@ Log_Level @>, LogLevel.FromString) with
    | Some l -> l
    | None -> LogLevel.Warn
    |> Loggers.ConsoleWindowLogger
 
  let notFound ctx = asyncOption {
    let! ctx = browseFile homeDir "404.html" ctx
    return { ctx with response = { ctx.response with status = HTTP_404 } }
  }
  
  let app =
    choose [
      log logger logFormat >=> never
      GET >=> choose [
        path "/" >=> browseFile homeDir "index.html"
        pathScan "/%s.html" (fun name -> tryThen (name |> sprintf "%s.html" |> browseFile homeDir) notFound)
        pathScan "/%s.js" (browseFile homeDir << sprintf "%s.js")
        pathScan "/%s.js.map" (browseFile homeDir << sprintf "%s.js.map")
      ]
      Api.app database logger
    ]

  let serverConfig = {
    defaultConfig with
      bindings = [ HttpBinding.mk HTTP IPAddress.Loopback (args.GetResult(<@ Port @>, 8083us)) ]
      homeFolder =
        args.TryGetResult(<@ Home_Directory @>)
        |> Option.map (fun d -> DirectoryInfo(d).FullName)
      logger = logger
  }

  (serverConfig, app)

let parser = ArgumentParser.Create<Args>()

[<EntryPoint>]
let main args =
  let args = parser.Parse(args)
  let homeDir = args.GetResult(<@ Home_Directory @>, ".")
  let database =
    Path.Combine(homeDir, ApiLoader.databaseName)
    |> ApiLoader.loadFromFile
  startWebServer <|| configAndApp database homeDir args
  0<commit_msg>split functions<commit_after>﻿module FSDN.Program

open System.IO
open System.Net
open Suave
open Suave.Web
open Suave.Logging
open Suave.Operators
open Suave.Filters
open Suave.Files
open Argu
open FSharpApiSearch

type Args =
  | Port of Sockets.Port
  | Home_Directory of string
  | Log_Level of string
with
  interface IArgParserTemplate with
    member this.Usage =
      match this with
      | Port _ -> "specify a primary port."
      | Home_Directory _ -> "specify a home or root diretory."
      | Log_Level _ -> "specify log level."

let logger (args: ParseResults<Args>) =
  match args.TryPostProcessResult(<@ Log_Level @>, LogLevel.FromString) with
  | Some l -> l
  | None -> LogLevel.Warn
  |> Loggers.ConsoleWindowLogger

let app database homeDir logger : WebPart =

  let notFound ctx = asyncOption {
    let! ctx = browseFile homeDir "404.html" ctx
    return { ctx with response = { ctx.response with status = HTTP_404 } }
  }

  choose [
    log logger logFormat >=> never
    GET >=> choose [
      path "/" >=> browseFile homeDir "index.html"
      pathScan "/%s.html" (fun name -> tryThen (name |> sprintf "%s.html" |> browseFile homeDir) notFound)
      pathScan "/%s.js" (browseFile homeDir << sprintf "%s.js")
      pathScan "/%s.js.map" (browseFile homeDir << sprintf "%s.js.map")
    ]
    Api.app database logger
  ]

let serverConfig port homeDir logger = {
  defaultConfig with
    bindings = [ HttpBinding.mk HTTP IPAddress.Loopback port ]
    homeFolder = Some homeDir
    logger = logger
}

let parser = ArgumentParser.Create<Args>()

[<EntryPoint>]
let main args =
  let args = parser.Parse(args)
  let homeDir = DirectoryInfo(args.GetResult(<@ Home_Directory @>, ".")).FullName
  let logger = logger args
  let port = args.GetResult(<@ Port @>, 8083us)
  let config = serverConfig port homeDir logger
  let database =
    Path.Combine(homeDir, ApiLoader.databaseName)
    |> ApiLoader.loadFromFile
  let app = app database homeDir logger
  startWebServer config app
  0
{'fraction_non_alphanumeric': 0.10729090465740064, 'fraction_numerical': 0.0053645452328700315, 'mean_word_length': 3.1857142857142855, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 50, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3263733', 'n_tokens_mistral': 1324, 'n_tokens_neox': 1288, 'n_words': 382}