and fix the module header in THSpec.hs
Ross MacLeod authored
f64bbbdf
Name Last commit Last update
composite-aeson-refined add prism generation via TH as well as improve flexibility of lens TH generation, add DefaultJsonFormat for Fixed
composite-aeson add prism generation via TH as well as improve flexibility of lens TH generation, add DefaultJsonFormat for Fixed
composite-base and fix the module header in THSpec.hs
composite-ekg add prism generation via TH as well as improve flexibility of lens TH generation, add DefaultJsonFormat for Fixed
composite-opaleye add prism generation via TH as well as improve flexibility of lens TH generation, add DefaultJsonFormat for Fixed
composite-reflex add prism generation via TH as well as improve flexibility of lens TH generation, add DefaultJsonFormat for Fixed
example remove Frames as a dependency, pulling in :-> to Composite.Record
.gitignore initial commit extracted from PoC
LICENSE Tweak to LICENSE to correct legal corporate name
Makefile update update-build to be way better
README.md remove Frames as a dependency, pulling in :-> to Composite.Record
default.nix add default.nix to make nix builds which use multiple composite libraries more simple
stack.yaml add corecords, reflex utilities, refined support for aeson, and some other utilities
update-build-shell.nix update update-build to be way better
update-build.sh update update-build to be way better

composite

Composite is a group of libraries focusing on practical uses of composite records, in particular Vinyl, such as querying records from a database and converting them to JSON. These libraries are based on the excellent Frames style use of Vinyl records, though composite implements its own derived from Frames to make for a smaller dependency graph, as Frames is a full CSV parsing/printing and data manipulation library.

composite-aeson

composite-aeson provides JSON formatting facilities for records. JSON formats can be derived automatically when default formats are available, explicitly assembled, combined, or a mix. Aeson's use of FromJSON/ToJSON type classes is mostly avoided to make using JSON formats first-class while still convenient.

Example:

import qualified Data.Aeson as Aeson
import Composite.Aeson (RecJsonFormat, defaultJsonFormatRec, recFormatJson)
import Composite.Record (Record, (:->), pattern (:*:), pattern Nil)

type FId   = "id"   :-> Int
type FName = "name" :-> Text
type User = '[FId, FName]

userFormat :: RecJsonFormat e User
userFormat = recFormatJson defaultJsonFormatRec

alice :: Record '[User]
alice = 1 :*: "Alice" :*: Nil

aliceJson :: Aeson.Value
aliceJson = toJsonWithFormat userFormat alice

composite-base

Definitions shared by the other composite libraries or generally useful when using Vinyl/Frames records.

composite-opaleye

composite-opaleye provides the necessary instances to use a Frames record with the opaleye library, letting you use records for query expressions as well as result rows.

Example:

import Composite.Opaleye (defaultRecTable)
import Composite.Record (Record, (:->))
import Composite.TH (withLensesAndProxies)
import Control.Lens (view)
import Data.Proxy (Proxy(Proxy))
import Frames ((:->), Record, rlens)
import Opaleye (Column, PGInt8, PGText, Query, Table, (./=), asc, constant, orderBy, queryTable, restrict)

-- For each field type defined with, withLensesAndProxies will expand to the type, a record lens for the type,
-- and a proxy for the type, so for example FId is the type, fId is a lens which accesses the "id" field of any
-- record which contains that field, and fId_ is a proxy for the field type in case it's needed.
withLensesAndProxies [d|
  type FId   = "id"   :-> Int64
  type CId   = "id"   :-> Column PGInt8
  type FName = "name" :-> Text
  type CName = "name" :-> Column PGText
  |]

type User     = '[FId, FName]
type UserCols = '[CId, CName]

userTable :: Table (Record UserCols) (Record UserCols)
userTable = Table "users" defaultRecTable

userQuery :: Query (Record User)
userQuery =
  orderBy (asc $ view cName) $ proc () -> do
    user@(view cId -> recId) <- queryTable userTable -< ()
    restrict -< recId ./= constant 1
    returnA -< user

example

A small servant based server which uses composite-opaleye to pull records from the database, reshape the record to an API type, and send the records out to the client as JSON via composite-aeson.

Contributing

Contributions and feedback welcome! File and issue or make a PR.

Chat

Asa (@asa) and Ross (@dridus) hang out on fpchat.