package sihl
Install
Dune Dependency
Authors
Maintainers
Sources
sha256=49fe887d05083b37523cd6e7ca35239822c561fe7109dd383c30aeb4259a7b98
sha512=4135ad42a75fb9adc3e853a466b696d9ee6d7a9d8acf0cee9fd5f5485679a517f524ce704e2d153df4a7c4f1d14df9f94ab2a8fbe5b36e744b505daab1d40f3d
doc/sihl.data/Data/index.html
Module Data
Source
Use this module to query the database, implement and run migrations, clean repositories, turn HTTP queries into SQL queries or for sane entity identifier handling.
Installation
The database service uses https://github.com/paurkedal/ocaml-caqti under the hood. Caqti can dynamically load the correct driver based on the DATABASE_URL
(postgresql://).
Caqti supports following databases (caqti drivers):
- PostgreSQL (caqti-driver-postgresql)
- MariaDB (caqti-driver-mariadb)
- SQLite (caqti-driver-sqlite)
module Log = Sihl.Log.Service.Make ()
module Config = Sihl.Config.Service.Make (Log)
module Db = Sihl.Data.Db.Service.Make (Config) (Log)
Install one of the drivers listed above.
opam install caqti-driver-postgresql
Add the driver to your done
file:
caqti-driver-postgresql
Usage
Register the database middleware, so other services can query the database with the context that contains the database pool.
module DbMiddleware = Sihl.Web.Middleware.Db.Make (Service.Db)
let middlewares = [
DbMiddleware.m();
]
The database service should be used mostly in repositories and not in services themselves.
pizza_order_repo.ml:
module MakePostgreSql
(DbService: Sihl.Data.Db.Service.Sig.SERVICE) : Pizza_order_sig.REPO =
struct
let find_request =
Caqti_request.find_opt Caqti_type.string Model.t
{sql|
SELECT
uuid,
customer,
pizza,
amount,
status,
confirmed,
created_at,
updated_at
FROM pizza_orders
WHERE pizza_orders.uuid = ?::uuid
|sql}
let find ctx ~id =
DbService.query ctx (fun connection ->
let module Connection = (val connection : Caqti_lwt.CONNECTION) in
Connection.find_opt get_request id
|> Lwt_result.map_err Caqti_error.show)
end
pizza_order_service.ml:
module Make
(Repo: Pizza_order_sig.REPO) : Pizza_order_sig.SERVICE = struct
let find ctx ~id = Repo.find ctx ~id
end
Then you can use the service:
module PizzaOrderRepo = Pizza_order_repo.MakePostgreSql (Service.Db)
module PizzaOrderService = Pizza_order_service.Make (PizzaOrderRepo)
let get_pizza_order =
Sihl.Web.Route.get "/pizza-orders/:id" (fun ctx ->
Sihl.Web.Res.(html |> set_body "Hello!") |> Lwt.return)
let get_pizza_order =
Sihl.Web.Route.get "/pizza-orders/:id" (fun ctx ->
let id = Sihl.Web.Req.param ctx "id" in
let pizza = PizzaOrderService.find ctx ~id in
...
)
The repository service deals with cleaning repositories. This is useful for integration tests.
Use the migration service to implement, register and run migrations.
A simple query language that can be used for HTTP queries that get passed into repositories. It currently supports filtering, sorting and pagination.
Modules and helpers to handle paginated collections, which is a partial view on a list of things.