Path module

Before we move on to defining views for the rest of the application, let's introduce one more file - Path.fs and insert it before View.fs (follow same steps as when we added View.fs):

Path.fs

   1: 
   2: 
   3: 
   4: 
   5: 
   6: 
   7: 
   8: 
   9: 
  10: 
module SuaveMusicStore.Path type IntPath = PrintfFormat<(int -> string),unit,string,string,int> let home = "/" module Store = let overview = "/store" let browse = "/store/browse" let details : IntPath = "/store/details/%d"

The module will contain all valid routes in our application. We'll keep them here in one place, in order to be able to reuse both in App and View modules. Thanks to that, we will minimize the risk of a typo in our View module. We defined a submodule called Store in order to group routes related to one functionality - later in the tutorial we'll have a few more submodules, each of them reflecting a specific set of functionality of the application.

The IntPath type alias that we declared will let us use our routes in conjunction with static-typed Suave routes (pathScan in App module). We don't need to fully understand the signature of this type, for now we can think of it as a route parametrized with integer value. And indeed, we annotated the details route with this type, so that the compiler treats this value specially. We'll see in a moment how we can use details in App and View modules, with the advantage of static typing.

Let's use the routes from Path module in our App:

App.fs

  16: 
  17: 
  18: 
  19: 
  20: 
  21: 
  22: 
  23: 
let webPart = choose [ path Path.home >=> (OK View.index) path Path.Store.overview >=> (OK "Store") path Path.Store.browse >=> browse pathScan Path.Store.details (fun id -> OK (sprintf "Details %d" id)) ]

as well as in our View for aHref to home:

View.fs

  12: 
  13: 
  14: 
  15: 
  16: 
div ["id", "header"] [ tag "h1" [] [ a Path.home [] [Text "F# Suave Music Store"] ] ]

Note, that in App module we still benefit from the static typed routes feature that Suave gives us - the id parameter is inferred by the compiler to be of integer type. If you're not familiar with type inference mechanism, you can follow up this link.

type IntPath = PrintfFormat<(int -> string),unit,string,string,int>

Full name: SuaveMusicStore.Path.IntPath
Multiple items
type PrintfFormat<'Printer,'State,'Residue,'Result> =
new : value:string -> PrintfFormat<'Printer,'State,'Residue,'Result>
member Value : string

Full name: Microsoft.FSharp.Core.PrintfFormat<_,_,_,_>

--------------------
type PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple> =
inherit PrintfFormat<'Printer,'State,'Residue,'Result>
new : value:string -> PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple>

Full name: Microsoft.FSharp.Core.PrintfFormat<_,_,_,_,_>

--------------------
new : value:string -> PrintfFormat<'Printer,'State,'Residue,'Result>

--------------------
new : value:string -> PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple>
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = System.String

Full name: Microsoft.FSharp.Core.string
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
val home : string

Full name: SuaveMusicStore.Path.home
module Store

from SuaveMusicStore.Path
val overview : string

Full name: SuaveMusicStore.Path.Store.overview
val browse : string

Full name: SuaveMusicStore.Path.Store.browse
val details : IntPath

Full name: SuaveMusicStore.Path.Store.details
namespace Suave
module Html

from Suave
val index : string

Full name: SuaveMusicStore.View.index
val html : (Attribute list -> Node list -> Node)

Full name: Suave.Html.html
val head : (Attribute list -> Node list -> Node)

Full name: Suave.Html.head
val title : attr:Attribute list -> s:string -> Node

Full name: Suave.Html.title
val body : (Attribute list -> Node list -> Node)

Full name: Suave.Html.body
val div : (Attribute list -> Node list -> Node)

Full name: Suave.Html.div
val tag : tag:string -> attr:Attribute list -> contents:Node list -> Node

Full name: Suave.Html.tag
val a : href:string -> attr:Attribute list -> (Node list -> Node)

Full name: Suave.Html.a
module Path

from SuaveMusicStore
union case Node.Text: string -> Node
val htmlToString : node:Node -> string

Full name: Suave.Html.htmlToString
module App

from SuaveMusicStore
module Filters

from Suave
module Operators

from Suave
module RequestErrors

from Suave
module Successful

from Suave
module Web

from Suave
val browse : (HttpContext -> Async<HttpContext option>)

Full name: SuaveMusicStore.App.browse
val request : apply:(HttpRequest -> HttpContext -> 'a) -> context:HttpContext -> 'a

Full name: Suave.Http.request
val r : HttpRequest
member HttpRequest.queryParam : key:string -> Choice<string,string>
union case Choice.Choice1Of2: 'T1 -> Choice<'T1,'T2>
val genre : string
val OK : body:string -> WebPart

Full name: Suave.Successful.OK
val sprintf : format:Printf.StringFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
union case Choice.Choice2Of2: 'T2 -> Choice<'T1,'T2>
val msg : string
val BAD_REQUEST : body:string -> WebPart

Full name: Suave.RequestErrors.BAD_REQUEST
val webPart : WebPart<HttpContext>

Full name: SuaveMusicStore.App.webPart
val choose : options:WebPart<'a> list -> WebPart<'a>

Full name: Suave.WebPart.choose
val path : pathAfterDomain:string -> WebPart

Full name: Suave.Filters.path
module View

from SuaveMusicStore
val pathScan : pf:PrintfFormat<'a,'b,'c,'d,'t> -> h:('t -> WebPart) -> WebPart

Full name: Suave.Filters.pathScan
val details : Path.IntPath

Full name: SuaveMusicStore.Path.Store.details
val id : int
val startWebServer : config:SuaveConfig -> webpart:WebPart -> unit

Full name: Suave.Web.startWebServer
val defaultConfig : SuaveConfig

Full name: Suave.Web.defaultConfig

Show code from this section on GitHub

results matching ""

    No results matching ""