generated from tpl/purs
docs: add docs
This commit is contained in:
parent
1e0f06d176
commit
c0ec6dec53
@ -18,15 +18,43 @@ import Effect.Class (liftEffect)
|
||||
import Effect.Exception (Error)
|
||||
import Prim.Row (class Union)
|
||||
|
||||
type PoolT :: forall k. (k -> Type) -> k -> Type
|
||||
type PoolT = ReaderT Pool
|
||||
-- | Monad handling pool resource acquisition & release
|
||||
-- |
|
||||
-- | ```
|
||||
-- | runPostgres
|
||||
-- | {connectionString: "postgresql://postgres:postgres@localhost:5432"}
|
||||
-- | $ session do
|
||||
-- | exec_ "create table foo (bar int);"
|
||||
-- | exec_ "insert into foo values (1);"
|
||||
-- | res <- query "select * from foo"
|
||||
-- | pure $ res == 1
|
||||
-- | ```
|
||||
-- |
|
||||
-- | Is equivalent to:
|
||||
-- | ```
|
||||
-- | do
|
||||
-- | pool <- liftEffect $ Pool.make {connectionString: "postgresql://postgres:postgres@localhost:5432"}
|
||||
-- | finally (Pool.end pool) do
|
||||
-- | client <- Pool.connect pool
|
||||
-- | finally (liftEffect $ Pool.release pool client) do
|
||||
-- | Client.exec_ "create table foo (bar int);" client
|
||||
-- | Client.exec_ "insert into foo values (1);" client
|
||||
-- | res <- Client.query "select * from foo" client
|
||||
-- | pure $ res == 1
|
||||
-- | ```
|
||||
type PostgresT :: forall k. (k -> Type) -> k -> Type
|
||||
type PostgresT = ReaderT Pool
|
||||
|
||||
type SessionT :: forall k. (k -> Type) -> k -> Type
|
||||
type SessionT = ReaderT Client
|
||||
|
||||
-- | A monad representing a connected session to a database
|
||||
class (MonadBracket Error Fiber m, MonadAff m, MonadReader Client m) <= MonadSession m where
|
||||
-- | Executes a query and unmarshals the result into `r`
|
||||
query :: forall q r. AsQuery q => FromRows r => q -> m r
|
||||
-- | Executes a query and returns the number of rows affected
|
||||
exec :: forall q. AsQuery q => q -> m Int
|
||||
-- | Executes a query and discards the result
|
||||
exec_ :: forall q. AsQuery q => q -> m Unit
|
||||
|
||||
instance (MonadBracket Error Fiber m, MonadAff m, MonadReader Client m) => MonadSession m where
|
||||
@ -38,7 +66,9 @@ instance (MonadBracket Error Fiber m, MonadAff m, MonadReader Client m) => Monad
|
||||
liftAff $ Client.exec q client
|
||||
exec_ = void <<< exec
|
||||
|
||||
session :: forall m a. MonadBracket Error Fiber m => MonadAff m => MonadSession (SessionT m) => SessionT m a -> PoolT m a
|
||||
-- | Lifts a session to `PostgresT`, releasing the client to the pool
|
||||
-- | after execution.
|
||||
session :: forall m a. MonadBracket Error Fiber m => MonadAff m => MonadSession (SessionT m) => SessionT m a -> PostgresT m a
|
||||
session m = do
|
||||
pool <- ask
|
||||
let
|
||||
@ -46,7 +76,12 @@ session m = do
|
||||
rel _ c = liftEffect $ Pool.release pool c
|
||||
lift $ bracket acq rel (runReaderT m)
|
||||
|
||||
transaction :: forall m a. MonadBracket Error Fiber m => MonadAff m => MonadSession (SessionT m) => SessionT m a -> PoolT m a
|
||||
-- | Lifts a session to `PostgresT`, running the session
|
||||
-- | in a transaction.
|
||||
-- |
|
||||
-- | If the session throws an error, the transaction will be
|
||||
-- | rolled back and the error rethrown.
|
||||
transaction :: forall m a. MonadBracket Error Fiber m => MonadAff m => MonadSession (SessionT m) => SessionT m a -> PostgresT m a
|
||||
transaction m =
|
||||
let
|
||||
begin = void $ exec "begin;"
|
||||
@ -55,10 +90,11 @@ transaction m =
|
||||
in
|
||||
session $ begin *> catchError commit rollback
|
||||
|
||||
runPool :: forall m a missing trash r e f. MonadBracket e f m => MonadAff m => Union r missing (Pool.Config trash) => Record r -> PoolT m a -> m a
|
||||
runPool cfg m =
|
||||
-- | Runs a `PostgresT` with a pool created with the provided config, invoking `Pool.end` afterwards.
|
||||
runPostgres :: forall m a missing trash r e f. MonadBracket e f m => MonadAff m => Union r missing (Pool.Config trash) => Record r -> PostgresT m a -> m a
|
||||
runPostgres cfg m =
|
||||
let
|
||||
acq = liftEffect $ Pool.make @r @missing @trash cfg
|
||||
rel _ p = liftAff $ Pool.end p
|
||||
in
|
||||
bracket acq rel (runReaderT m)
|
||||
bracket acq rel $ runReaderT m
|
||||
|
@ -6,14 +6,17 @@ import Data.Either (Either(..))
|
||||
import Data.String.Regex (Regex)
|
||||
import Data.String.Regex as Regex
|
||||
import Data.String.Regex.Flags (RegexFlags(..))
|
||||
import Data.Tuple.Nested (type (/\), (/\))
|
||||
import Effect (Effect)
|
||||
import Effect.Aff (Aff, bracket)
|
||||
import Effect.Aff (Aff, bracket, makeAff)
|
||||
import Effect.Aff.Postgres.Client (Client)
|
||||
import Effect.Aff.Postgres.Client as Client
|
||||
import Effect.Aff.Postgres.Pool (Pool)
|
||||
import Effect.Aff.Postgres.Pool as Pool
|
||||
import Effect.Class (liftEffect)
|
||||
import Effect.Unsafe (unsafePerformEffect)
|
||||
import Node.EventEmitter (EventHandle(..))
|
||||
import Node.EventEmitter as EE
|
||||
import Node.Path as Path
|
||||
import Node.Process (cwd)
|
||||
import Partial.Unsafe (unsafePartial)
|
||||
@ -54,3 +57,21 @@ unsafeFromRight e = unsafePartial $ case e of Right b -> b
|
||||
|
||||
re :: String -> RegexFlags -> Regex
|
||||
re s f = unsafeFromRight $ Regex.regex s f
|
||||
|
||||
class Curried a b | a -> b where
|
||||
curried :: (b -> Effect Unit) -> a
|
||||
|
||||
instance Curried (Effect Unit) Unit where
|
||||
curried f = f unit
|
||||
|
||||
instance Curried (a -> Effect Unit) a where
|
||||
curried = identity
|
||||
|
||||
instance Curried (a -> b -> Effect Unit) (a /\ b) where
|
||||
curried f = \a b -> f $ a /\ b
|
||||
|
||||
instance Curried (a -> b -> c -> Effect Unit) (a /\ b /\ c) where
|
||||
curried f = \a b c -> f $ a /\ b /\ c
|
||||
|
||||
onceAff :: forall psCb jsCb emitter r. Curried psCb r => EventHandle emitter psCb jsCb -> emitter -> Aff r
|
||||
onceAff ev em = makeAff \res -> mempty <* EE.once ev (curried (res <<< Right)) em
|
||||
|
@ -4,7 +4,7 @@ import Prelude
|
||||
|
||||
import Control.Monad.Error.Class (throwError)
|
||||
import Control.Monad.Fork.Class (class MonadBracket, bracket)
|
||||
import Control.Monad.Postgres (PoolT, exec_, query, runPool, session, transaction)
|
||||
import Control.Monad.Postgres (PostgresT, exec_, query, runPostgres, session, transaction)
|
||||
import Data.Array as Array
|
||||
import Data.Array.NonEmpty as Array.NonEmpty
|
||||
import Data.Maybe (fromJust, maybe)
|
||||
@ -18,7 +18,7 @@ import Test.Common (re, withConfig)
|
||||
import Test.Spec (Spec, around, describe, it)
|
||||
import Test.Spec.Assertions (expectError, shouldEqual)
|
||||
|
||||
withTable :: forall a m. MonadBracket Error Fiber m => MonadAff m => String -> PoolT m a -> PoolT m a
|
||||
withTable :: forall a m. MonadBracket Error Fiber m => MonadAff m => String -> PostgresT m a -> PostgresT m a
|
||||
withTable s m =
|
||||
let
|
||||
tabname = unsafePartial fromJust $ join $ Array.index (maybe [] Array.NonEmpty.toArray $ Regex.match (re "create table (\\w+)" Regex.Flag.ignoreCase) s) 1
|
||||
@ -28,21 +28,21 @@ withTable s m =
|
||||
spec :: Spec Unit
|
||||
spec =
|
||||
around withConfig $ describe "Control.Monad.Postgres" do
|
||||
it "empty works" \cfg -> runPool cfg $ pure unit
|
||||
it "connects" \cfg -> runPool cfg do
|
||||
it "empty works" \cfg -> runPostgres cfg $ pure unit
|
||||
it "connects" \cfg -> runPostgres cfg do
|
||||
act <- session $ query "select 1"
|
||||
act `shouldEqual` 1
|
||||
it "connects multiple" \cfg -> runPool cfg do
|
||||
it "connects multiple" \cfg -> runPostgres cfg do
|
||||
a <- session $ query "select 1"
|
||||
b <- session $ query "select 2"
|
||||
a `shouldEqual` 1
|
||||
b `shouldEqual` 2
|
||||
it "transaction commits" \cfg -> runPool cfg do
|
||||
it "transaction commits" \cfg -> runPostgres cfg do
|
||||
withTable "create table test_txn_commits (id int);" do
|
||||
transaction $ exec_ "insert into test_txn_commits values (1);"
|
||||
act <- session $ query "select * from test_txn_commits"
|
||||
act `shouldEqual` [ 1 ]
|
||||
it "transaction rolls back" \cfg -> runPool cfg do
|
||||
it "transaction rolls back" \cfg -> runPostgres cfg do
|
||||
withTable "create table test_txn_rolls_back (id int);" do
|
||||
expectError $ transaction do
|
||||
exec_ "insert into test_txn_rolls_back values (1);"
|
||||
|
@ -12,8 +12,7 @@ import Effect.Aff (forkAff, joinFiber)
|
||||
import Effect.Aff.Postgres.Client (query)
|
||||
import Effect.Aff.Postgres.Client as Client
|
||||
import Effect.Exception as Error
|
||||
import Test.Common (withClient)
|
||||
import Test.Event (onceAff)
|
||||
import Test.Common (onceAff, withClient)
|
||||
import Test.Spec (Spec, around, describe, it)
|
||||
import Test.Spec.Assertions (shouldEqual)
|
||||
|
||||
@ -60,4 +59,4 @@ spec =
|
||||
describe "json" do
|
||||
it "unmarshals" \c -> shouldEqual (JSON { foo: "bar" }) =<< query "select '{\"foo\": \"bar\"}' :: json" c
|
||||
it "is string" \c -> shouldEqual "{\"foo\": \"bar\"}" =<< query "select '{\"foo\": \"bar\"}' :: json" c
|
||||
it "array is string" \c -> shouldEqual [ [ "{\"foo\": \"bar\"}" ] ] =<< query "select array['{\"foo\": \"bar\"}' :: json]" c
|
||||
it "array is string" \c -> shouldEqual [["{\"foo\": \"bar\"}"]] =<< query "select array['{\"foo\": \"bar\"}' :: json]" c
|
||||
|
@ -7,8 +7,7 @@ import Effect.Aff (finally, forkAff, joinFiber)
|
||||
import Effect.Aff.Postgres.Client as Client
|
||||
import Effect.Aff.Postgres.Pool as Pool
|
||||
import Effect.Class (liftEffect)
|
||||
import Test.Common (config, withPool)
|
||||
import Test.Event (onceAff)
|
||||
import Test.Common (config, onceAff, withPool)
|
||||
import Test.Spec (Spec, around, describe, it)
|
||||
import Test.Spec.Assertions (expectError, shouldEqual)
|
||||
|
||||
|
@ -1,29 +0,0 @@
|
||||
module Test.Event where
|
||||
|
||||
import Prelude
|
||||
|
||||
import Data.Either (Either(..))
|
||||
import Data.Profunctor (lcmap)
|
||||
import Data.Tuple.Nested (type (/\), uncurry2, (/\))
|
||||
import Effect (Effect)
|
||||
import Effect.Aff (Aff, makeAff)
|
||||
import Node.EventEmitter (EventHandle(..))
|
||||
import Node.EventEmitter as EE
|
||||
|
||||
class Curried a b | a -> b where
|
||||
curried :: (b -> Effect Unit) -> a
|
||||
|
||||
instance Curried (Effect Unit) Unit where
|
||||
curried f = f unit
|
||||
|
||||
instance Curried (a -> Effect Unit) a where
|
||||
curried = identity
|
||||
|
||||
instance Curried (a -> b -> Effect Unit) (a /\ b) where
|
||||
curried f = \a b -> f $ a /\ b
|
||||
|
||||
instance Curried (a -> b -> c -> Effect Unit) (a /\ b /\ c) where
|
||||
curried f = \a b c -> f $ a /\ b /\ c
|
||||
|
||||
onceAff :: forall psCb jsCb emitter r. Curried psCb r => EventHandle emitter psCb jsCb -> emitter -> Aff r
|
||||
onceAff ev em = makeAff \res -> mempty <* EE.once ev (curried (res <<< Right)) em
|
Loading…
Reference in New Issue
Block a user