2020-01-02 12:24:00 +01:00
module Db
open FSharp.Data.Sql
[<Literal>]
let ConnectionString = "Server=127.0.0.1; Database=todo_api_db; User Id=suave; Password=1234;"
type Sql = SqlDataProvider<ConnectionString=ConnectionString, DatabaseVendor=Common.DatabaseProviderTypes.POSTGRESQL, CaseSensitivityChange=Common.CaseSensitivityChange.ORIGINAL>
2020-01-02 12:48:35 +01:00
module Context =
type DbContext = Sql.dataContext
2020-01-02 12:24:00 +01:00
2020-01-02 12:48:35 +01:00
let getContext() = Sql.GetDataContext()
module Types =
open Context
2020-01-02 15:51:22 +01:00
open Chiron
2020-01-02 13:24:11 +01:00
type DbTodo = DbContext.``public.todosEntity``
type Todo =
2020-01-02 15:51:22 +01:00
{ id: int
2020-01-02 13:24:11 +01:00
description: string
name: string }
2020-01-02 15:51:22 +01:00
static member ToJson(todo: Todo) =
json {
do! Json.write "name" todo.name
do! Json.write "description" todo.description
do! Json.write "id" todo.id
}
static member FromJson(_: Todo) =
json {
let! name = Json.read "name"
let! description = Json.read "description"
let! id = Json.read "id"
return { name = name
description = description
id = id }
}
2020-01-02 13:24:11 +01:00
2020-01-02 14:37:47 +01:00
type TodoDetails =
2020-01-02 15:51:22 +01:00
{ description: string
2020-01-02 14:37:47 +01:00
name: string }
2020-01-02 15:51:22 +01:00
static member FromJson(_: TodoDetails) =
json {
let! name = Json.read "name"
let! description = Json.read "description"
return { name = name
description = description }
}
2020-01-02 14:37:47 +01:00
2020-01-02 16:24:57 +01:00
type PartialTodoDetails =
{ description: string option
name: string option }
static member FromJson(_: PartialTodoDetails) =
json {
let! name = Json.tryRead "name"
let! description = Json.tryRead "description"
return { name = name
description = description }
}
2020-01-02 12:48:35 +01:00
module Queries =
open Context
open Types
2020-01-02 14:37:47 +01:00
let getTodosById id (ctx: DbContext): DbTodo option =
2020-01-02 12:48:35 +01:00
query {
for todo in ctx.Public.Todos do
where (todo.Id = id)
select todo
}
|> Seq.tryHead
2020-01-02 14:37:47 +01:00
2020-01-02 16:50:27 +01:00
let getAllTodos (ctx: DbContext): DbTodo list =
query {
for todo in ctx.Public.Todos do
select todo
}
|> Seq.toList
2020-01-02 14:37:47 +01:00
2020-01-02 17:13:31 +01:00
let updateTodo (todo: DbTodo) (details: TodoDetails) (ctx: DbContext) =
2020-01-02 14:37:47 +01:00
todo.Name <- details.name
todo.Description <- details.description
ctx.SubmitUpdatesAsync()
2020-01-02 16:24:57 +01:00
2020-01-02 17:13:31 +01:00
let patchTodo (todo: DbTodo) (details: PartialTodoDetails) (ctx: DbContext) =
2020-01-02 16:24:57 +01:00
Option.iter (fun name -> todo.Name <- name) details.name
Option.iter (fun description -> todo.Description <- description) details.description
if Option.orElse details.name details.description |> Option.isSome
then ctx.SubmitUpdatesAsync()
else Async.result()
2020-01-02 16:32:16 +01:00
2020-01-02 17:13:31 +01:00
let deleteTodo (todo: DbTodo) (ctx: DbContext) =
2020-01-02 16:32:16 +01:00
todo.Delete()
ctx.SubmitUpdatesAsync()
2020-01-02 17:11:49 +01:00
let createTodo (details: TodoDetails) (ctx: DbContext) =
async {
let todo = ctx.Public.Todos.Create()
2020-01-02 17:13:31 +01:00
do! updateTodo todo details ctx
2020-01-02 17:11:49 +01:00
return todo
}