package sihl

  1. Overview
  2. Docs
The modular functional web framework

Install

Dune Dependency

Authors

Maintainers

Sources

sihl-0.1.2.tbz
sha256=69705a3a35f204acfdda62f61056e3f0ec3ef5bcd1df1508be65b066a0b1df9c
sha512=1987d211f56d0261eefbae978065a4e6781d60ad94b08597875307e5cf6e5a1b79787d9c79f784f5a9f77c35203cfd0b488841a07adfd87b0710d6fd65422b94

doc/sihl.data/Data/index.html

Module DataSource

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

Sourcemodule Db : sig ... end

The database service allows you to interact with relational databases.

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
      ...
      )
Sourcemodule Repo : sig ... end

The repository service deals with cleaning repositories. This is useful for integration tests.

Sourcemodule Migration : sig ... end

Use the migration service to implement, register and run migrations.

Sourcemodule Ql : sig ... end

A simple query language that can be used for HTTP queries that get passed into repositories. It currently supports filtering, sorting and pagination.

Sourcemodule View : sig ... end

Modules and helpers to handle paginated collections, which is a partial view on a list of things.

Sourcemodule Id : sig ... end

Encode and decode entity identifiers as UUIDs.

OCaml

Innovation. Community. Security.