-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Run 'tmp' processes in integration tests
--   
--   <tt>tmp-proc</tt> runs services in docker containers for use in
--   integration tests. It aims to make using these services become like
--   accessing <i>tmp</i> processes, similar to how <i>tmp</i> file or
--   directories are used. It aspires to provide a user-friendly API, while
--   including useful features such as
--   
--   <ul>
--   <li>launch of multiple services on docker during test setup</li>
--   <li>delayed test execution until the launched services are
--   available</li>
--   <li>simplified use of connections to the services from a <a>WAI</a>
--   server under test</li>
--   <li>good integration with haskell testing frameworks like <a>hspec</a>
--   and <a>tasty</a></li>
--   </ul>
@package tmp-proc
@version 0.7.2.1


-- | Defines type-level combinators for performing a merge sort of
--   type-level lists.
--   
--   <a>SortSymbols</a> sorts type-level lists of <tt>Symbols</tt>.
--   
--   The other exported combinators make it easy to implement type-level
--   merge sort for similar type-level lists.
--   
--   This is an internal module that provides type-level functions used in
--   various constraints in <a>System.TmpProc.Docker</a>.
module System.TmpProc.TypeLevel.Sort

-- | Sort a list of type-level <tt>symbols</tt> using merge sort.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; :kind! SortSymbols '["xyz", "def", "abc"]
--   SortSymbols '["xyz", "def", "abc"] :: [Symbol]
--   = '["abc", "def", "xyz"]
--   </pre>
type family SortSymbols (xs :: [Symbol]) :: [Symbol]

-- | Takes 1 element at a time from a list until the desired length is
--   reached.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; :kind! Take '["a", "b", "c", "d"] 2
--   Take '["a", "b", "c", "d"] 2 :: [Symbol]
--   = '["a", "b"]
--   </pre>
type family Take (xs :: [k]) (n :: Nat) :: [k]

-- | Drops 1 element at a time until the the dropped target is reached.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; :kind! Drop '["a", "b", "c", "d"] 2
--   Drop '["a", "b", "c", "d"] 2 :: [Symbol]
--   = '["c", "d"]
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; :kind! Drop '["a"] 2
--   Drop '["a"] 2 :: [Symbol]
--   = '[]
--   </pre>
type family Drop (xs :: [k]) (n :: Nat) :: [k]

-- | Counts a list, 1 element at a time.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; :kind! CmpNat 4 (LengthOf '[1, 2, 3, 4])
--   CmpNat 4 (LengthOf '[1, 2, 3, 4]) :: Ordering
--   = 'EQ
--   </pre>
type family LengthOf (xs :: [k]) :: Nat

-- | Computes the midpoint of a number.
--   
--   N.B: maximum value that this works for depends on the reduction limit
--   of the type-checker.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; :kind! CmpNat 49 (HalfOf 99)
--   CmpNat 49 (HalfOf 99) :: Ordering
--   = 'EQ
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; :kind! CmpNat 50 (HalfOf 100)
--   CmpNat 50 (HalfOf 100) :: Ordering
--   = 'EQ
--   </pre>
type family HalfOf (n :: Nat) :: Nat


-- | Defines type-level data structures and combinators used by
--   <a>System.TmpProc.Docker</a> and <a>System.TmpProc.Warp</a>.
--   
--   <a>HList</a> implements a heterogenous list used to define types that
--   represent multiple concurrent <tt>tmp procs</tt>.
--   
--   <a>KV</a> is intended for internal use within the <tt>tmp-proc</tt>
--   package. It allows indexing and sorting of lists of tmp procs.
module System.TmpProc.TypeLevel

-- | Defines a Heterogenous list.
data HList :: [Type] -> Type
[HNil] :: HList '[]
[HCons] :: anyTy -> HList manyTys -> HList (anyTy : manyTys)
infixr 5 `HCons`

-- | An infix alias for <a>HCons</a>.
(&:) :: x -> HList xs -> HList (x : xs)
infixr 5 &:

-- | Construct a singleton HList
only :: x -> HList '[x]

-- | An infix alias for <a>both</a>.
(&:&) :: x -> y -> HList '[x, y]
infixr 6 &:&

-- | Construct a two-item HList.
both :: x -> y -> HList '[x, y]
infixr 6 `both`

-- | Obtain the first element of a <a>HList</a>.
hHead :: HList (a : as) -> a

-- | Get an item in an <a>HList</a> given its type.
hOf :: forall y xs. IsInProof y xs => Proxy y -> HList xs -> y

-- | Allows reordering of similar <tt><a>HList</a>s</tt>.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; hReorder @_ @'[Bool, Int] ('c' &amp;: (3 :: Int) &amp;: True &amp;: (3.1 :: Double) &amp;: HNil)
--   True &amp;: 3 &amp;: HNil
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; hReorder @_ @'[Double, Bool, Int] ('c' &amp;: (3 :: Int) &amp;: True &amp;: (3.1 :: Double) &amp;: HNil)
--   3.1 &amp;: True &amp;: 3 &amp;: HNil
--   </pre>
class ReorderH xs ys
hReorder :: ReorderH xs ys => HList xs -> HList ys

-- | Use a type-level symbol as <i>key</i> type that indexes a <i>value</i>
--   type.
data KV :: Symbol -> Type -> Type
[V] :: a -> KV s a

-- | Select an item from an <a>HList</a> of <tt><a>KV</a>s</tt> by
--   <i>key</i>.
--   
--   <i>N.B</i> Returns the first item. It assumes the keys in the KV HList
--   are unique. <i>TODO:</i> enforce this rule using a constraint.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; select @"d" @Double  @'[KV "b" Bool, KV "d" Double] (V True &amp;:  V (3.1 :: Double) &amp;: HNil)
--   3.1
--   </pre>
select :: forall k t xs. MemberKV k t xs => HList xs -> t

-- | Select items with specified keys from an <tt><a>HList</a></tt> of
--   <tt><a>KV</a>s</tt> by <i>key</i>.
--   
--   <i>N.B.</i> this this is an internal function.
--   
--   The keys must be provided in the same order as they occur in the
--   HList, any other order will likely result in an compiler error.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; selectMany @'["b"] @'[Bool] @'[KV "b" Bool, KV "d" Double] (V True &amp;:  V (3.1 :: Double) &amp;: HNil)
--   True &amp;: HNil
--   </pre>
selectMany :: forall ks ts xs. ManyMemberKV ks ts xs => HList xs -> HList ts

-- | Proves a symbol and its type occur as entry in a list of
--   <tt><a>KV</a></tt> types.
data LookupKV (k :: Symbol) t (xs :: [Type])
[AtHead] :: LookupKV k t (KV k t : kvs)
[OtherKeys] :: LookupKV k t kvs -> LookupKV k t (KV ok ot : kvs)

-- | Generate proof instances of <a>LookupKV</a>.
class MemberKV (k :: Symbol) (t :: Type) (xs :: [Type])
lookupProof :: MemberKV k t xs => LookupKV k t xs

-- | Generate proof instances of <a>LookupMany</a>.
class ManyMemberKV (ks :: [Symbol]) (ts :: [Type]) (kvs :: [Type])
manyProof :: ManyMemberKV ks ts kvs => LookupMany ks ts kvs

-- | A constraint that confirms that a type is not present in a type-level
--   list.
type family IsAbsent e r :: Constraint

-- | Generate proof instances of <a>IsIn</a>.
class IsInProof t (tys :: [Type])
instance (System.TmpProc.TypeLevel.IsInProof y xs, System.TmpProc.TypeLevel.ReorderH xs ys) => System.TmpProc.TypeLevel.ReorderH xs (y : ys)
instance System.TmpProc.TypeLevel.IsInProof t (t : tys)
instance System.TmpProc.TypeLevel.IsInProof t tys => System.TmpProc.TypeLevel.IsInProof t (a : tys)
instance System.TmpProc.TypeLevel.ReorderH xs '[]
instance System.TmpProc.TypeLevel.ManyMemberKV '[k] '[t] (System.TmpProc.TypeLevel.KV k t : ks)
instance System.TmpProc.TypeLevel.ManyMemberKV ks ts kvs => System.TmpProc.TypeLevel.ManyMemberKV (k : ks) (t : ts) (System.TmpProc.TypeLevel.KV k t : kvs)
instance System.TmpProc.TypeLevel.ManyMemberKV ks ts kvs => System.TmpProc.TypeLevel.ManyMemberKV ks ts (System.TmpProc.TypeLevel.KV ok ot : kvs)
instance System.TmpProc.TypeLevel.MemberKV k t '[System.TmpProc.TypeLevel.KV k t]
instance System.TmpProc.TypeLevel.MemberKV k t (System.TmpProc.TypeLevel.KV k t : kvs)
instance System.TmpProc.TypeLevel.MemberKV k t kvs => System.TmpProc.TypeLevel.MemberKV k t (System.TmpProc.TypeLevel.KV ok ot : kvs)
instance GHC.Show.Show (System.TmpProc.TypeLevel.HList '[])
instance (GHC.Show.Show x, GHC.Show.Show (System.TmpProc.TypeLevel.HList xs)) => GHC.Show.Show (System.TmpProc.TypeLevel.HList (x : xs))
instance GHC.Classes.Eq (System.TmpProc.TypeLevel.HList '[])
instance (GHC.Classes.Eq x, GHC.Classes.Eq (System.TmpProc.TypeLevel.HList xs)) => GHC.Classes.Eq (System.TmpProc.TypeLevel.HList (x : xs))


-- | Provides the core datatypes and combinators used to launch temporary
--   <i>(tmp)</i> processes <i>(procs)</i> using docker.
--   
--   <tt>tmp-proc</tt> helps launch services used by integration tests on
--   docker. It aims to simplify writing those kind of tests, by providing
--   combinators that
--   
--   <ul>
--   <li>launch services on docker</li>
--   <li>provide references to the launched services</li>
--   <li>clean up these services after the test completes</li>
--   </ul>
--   
--   It achieves this through its typeclasses, datatypes and combinators:
--   
--   <ul>
--   <li>A datatype implements the <a>Proc</a> typeclass to specify a
--   docker image that provides a service</li>
--   <li><a>startup</a> starts a <tt>Proc</tt>; using a <tt>docker run</tt>
--   command generated from metadata encoded in the <tt>Proc</tt>'s
--   implementation</li>
--   <li>Additionally, a <tt>Proc</tt> datatype may implement the
--   <a>ToRunCmd</a> typeclass to customize the arguments of the <tt>docker
--   run</tt> command that launches the service.</li>
--   <li>Invoking <a>startup</a> constructs a <a>ProcHandle</a> on
--   successful launch of a service specifed by a <a>Proc</a><ul><li>It
--   provides combinators for accessing the service, and for eventually
--   shutting it down</li></ul></li>
--   <li>Multiple services are launched by specifying distinct
--   <tt>Procs</tt> in an <a>HList</a><ul><li><a>startupAll</a> constructs
--   an <a>HList</a> of the corresponding <tt>ProcHandle</tt> on successful
--   launch of the specified services.</li></ul></li>
--   </ul>
--   
--   Support for additional features that might prove useful in integration
--   tests is available by implementing additional supporting typeclasses:
--   
--   <ul>
--   <li><i><a>Connectable</a></i></li>
--   <li><i><a>Preparer</a></i></li>
--   </ul>
--   
--   Use <a>Connectable</a> when there is a specific <i>Connection</i>
--   datatype used to access a service. It provides a combinator to
--   construct an instance of that datatype that accesses the launched
--   service
--   
--   Use <a>Preparer</a> to allow customization and cleanup of the docker
--   container used to launch the service
--   
--   <ul>
--   <li><tt><a>Preparer</a></tt> allows resources used by a docker
--   container to be set up before invoking the <tt>docker run</tt> command
--   that starts a service, and enables these to be cleaned up
--   afterwards</li>
--   <li>It works with <tt><a>ToRunCmd</a></tt> to allow refererences to
--   the resources to be specified in the <tt>docker run</tt> command</li>
--   </ul>
module System.TmpProc.Docker

-- | Specifies how to launch a temporary process using Docker.
class (KnownSymbol (Image a), KnownSymbol (Name a)) => Proc a where {
    
    -- | The image name of the docker image, e.g, <i>postgres:10.6</i>
    type Image a :: Symbol;
    
    -- | A label used to refer to the running tmp proc created from this image,
    --   e.g, <i>a-postgres-db</i>
    type Name a = (labelName :: Symbol) | labelName -> a;
}

-- | Additional arguments to the docker command that launches the tmp proc.
runArgs :: Proc a => [Text]

-- | Determines the service URI of the tmp proc, when applicable.
uriOf :: Proc a => HostIpAddress -> SvcURI

-- | Resets some state in a tmp proc service.
reset :: Proc a => ProcHandle a -> IO ()

-- | Checks if the tmp proc started correctly.
ping :: Proc a => ProcHandle a -> IO Pinged

-- | Maximum number of pings to perform during startup.
pingCount :: Proc a => Natural

-- | Number of milliseconds between pings.
pingGap :: Proc a => Natural

-- | Starts a <a>Proc</a>.
--   
--   It uses <a>ping</a> to determine if the <a>Proc</a> started up ok, and
--   will fail by throwing an exception if it did not.
--   
--   Returns the <a>ProcHandle</a> used to access and control the
--   <a>Proc</a> once a ping has succeeded.
startup :: ProcPlus a prepared => a -> IO (ProcHandle a)

-- | Name of a process.
nameOf :: forall a. Proc a => a -> Text

-- | Simplifies use of <a>uriOf</a>.
uriOf' :: forall a. Proc a => a -> HostIpAddress -> SvcURI

-- | Simplifies use of <a>runArgs</a>.
runArgs' :: forall a. Proc a => a -> [Text]

-- | Indicates the result of pinging a <a>Proc</a>.
--   
--   If the ping succeeds, <a>ping</a> should return <a>OK</a>.
--   
--   <a>ping</a> should catch any exceptions that are expected when the
--   <tt><a>Proc</a>s</tt> service is not available and return
--   <a>NotOK</a>.
--   
--   <a>startupAll</a> uses <a>PingFailed</a> to report any unexpected
--   exceptions that escape <a>ping</a>.
data Pinged

-- | The service is running OK.
OK :: Pinged

-- | The service is not running.
NotOK :: Pinged

-- | Contact to the service failed unexpectedly.
PingFailed :: Text -> Pinged

-- | Use an action that might throw an exception as a ping.
toPinged :: forall e a. Exception e => Proxy e -> IO a -> IO Pinged

-- | Declares a proof that a list of types only contains
--   <tt><a>Proc</a>s</tt>.
class AreProcs as

-- | Allow customization of the docker command that launches a
--   <tt><a>Proc</a></tt>
--   
--   The docker launch command is `docker run -d <i>optional-args</i>
--   --name $(name a) $(imageText a)`
--   
--   A <tt>Proc</tt> datatype should declare an instance of
--   <tt>ToRunCmd</tt> to control <i>optional-args</i>
--   
--   This module provides an <tt>Overlappable</tt> fallback instance with
--   default behaviour that matches all <tt><a>Proc</a></tt>, so this
--   typeclass is only needed when a <tt><a>Proc</a></tt> datatypes
--   actually needs additional arguments
class (Preparer a prepared) => ToRunCmd a prepared
toRunCmd :: ToRunCmd a prepared => a -> prepared -> [Text]

-- | Prepare resources for use by a <tt><a>Proc</a></tt>
--   
--   Preparation occurs before the docker container is a launched; once the
--   resources are set up, they are located using the <tt>prepared</tt>
--   datatype.
--   
--   Usually, this means it will be used by <a>toRunCmd</a> to provide
--   additional arguments to the <tt>docker run</tt> command
--   
--   This module provides an <tt>Overlappable</tt> fallback instance that
--   matches all <tt><a>Proc</a></tt>, so this typeclass is only needed
--   when a <tt><a>Proc</a></tt> datatype actually requires preparatory
--   setup.
--   
--   The first argument to <a>prepare</a> is a <tt>[<a>SlimHandle</a>]</tt>
--   that gives access to other <tt>tmp-procs</tt> previously launched in
--   the same test, to allow <a>prepare</a> to setup links to them when
--   necessary
class Preparer a prepared | a -> prepared

-- | Generate a <tt>prepared</tt> before the docker container is started
prepare :: Preparer a prepared => [SlimHandle] -> a -> IO prepared

-- | Clean up any resources associated with <tt>prepared</tt>
tidy :: Preparer a prepared => a -> prepared -> IO ()

-- | A <tt>Constraint</tt> that combines <tt><a>Proc</a></tt> and its
--   supporting typeclasses
type ProcPlus a prepared = (Proc a, ToRunCmd a prepared, Preparer a prepared)

-- | Start up processes for each <a>Proc</a> type
--   
--   the processes' are able to communicate via a docker network with a
--   unique generated name
startupAll :: AreProcs procs => HList procs -> IO (HandlesOf procs)

-- | Terminate all processes owned by some <tt><a>ProcHandle</a>s</tt>.
terminateAll :: AreProcs procs => HandlesOf procs -> IO ()

-- | Set up some <tt><a>Proc</a>s</tt>, run an action that uses them, then
--   terminate them.
withTmpProcs :: AreProcs procs => HList procs -> (HandlesOf procs -> IO b) -> IO b

-- | Start up processes for each <a>Proc</a> type.

-- | <i>Deprecated: since v0.7 this is no longer needed and will be
--   removed, use startupAll instead; it always generates a named docker
--   network</i>
startupAll' :: AreProcs procs => Maybe Text -> HList procs -> IO (NetworkHandlesOf procs)

-- | Like <a>terminateAll</a>, but also removes the docker network
--   connecting the processes.

-- | <i>Deprecated: since v0.7 this is no longer needed and will be
--   removed, use terminateAll instead</i>
netwTerminateAll :: AreProcs procs => NetworkHandlesOf procs -> IO ()

-- | Like <a>startupAll</a>, but reveals the generated network name via the
--   deprecated <a>NetworkHandlesOf</a>

-- | <i>Deprecated: since v0.7 this is no longer needed and will be
--   removed, use startupAll instead</i>
netwStartupAll :: AreProcs procs => HList procs -> IO (NetworkHandlesOf procs)

-- | Provides access to a <a>Proc</a> that has been started.
data ProcHandle a

-- | A <tt>pattern</tt> constructor the provides selectors for the
--   <tt>ProcHandle</tt> fields
--   
--   The selectors are readonly, i.e they only match in a pattern context
--   since <tt>ProcHandle</tt>s cannot be constructed directly; they are
--   constructed by invoking <a>startupAll</a> or <a>startup</a>
pattern ProcHandle :: a -> String -> SvcURI -> HostIpAddress -> ProcHandle a

-- | Obtain the handle matching the given type from a <tt><a>HList</a></tt>
--   of <tt><a>ProcHandle</a></tt>.
handleOf :: HandleOf a procs b => Proxy a -> HandlesOf procs -> ProcHandle b

-- | Provides an untyped view of the data in a <a>ProcHandle</a>
data SlimHandle
SlimHandle :: Text -> HostIpAddress -> String -> SvcURI -> SlimHandle
[shName] :: SlimHandle -> Text
[shIpAddress] :: SlimHandle -> HostIpAddress
[shPid] :: SlimHandle -> String
[shUri] :: SlimHandle -> SvcURI

-- | Obtain the <a>SlimHandle</a>.
slim :: Proc a => ProcHandle a -> SlimHandle

-- | Converts list of types to the corresponding <tt><a>ProcHandle</a></tt>
--   types.
type family Proc2Handle (as :: [Type]) = (handleTys :: [Type]) | handleTys -> as

-- | Constraint alias used to constrain types where proxy of a <a>Proc</a>
--   type looks up a value in an <a>HList</a> of <a>ProcHandle</a>.
type HasHandle aProc procs = (Proc aProc, AreProcs procs, IsInProof (ProcHandle aProc) (Proc2Handle procs))

-- | Constraint alias used to constrain types where a <a>Name</a> looks up
--   a type in an <a>HList</a> of <a>ProcHandle</a>.
type HasNamedHandle name a procs = (name ~ Name a, Proc a, AreProcs procs, MemberKV name (ProcHandle a) (Handle2KV (Proc2Handle procs)))

-- | A list of <tt><a>ProcHandle</a></tt> values.
type HandlesOf procs = HList (Proc2Handle procs)

-- | Resets the handle whose index is specified by the proxy type.
ixReset :: IxReset a procs => Proxy a -> HandlesOf procs -> IO ()

-- | Pings the handle whose index is specified by the proxy type.
ixPing :: IxPing a procs => Proxy a -> HandlesOf procs -> IO Pinged

-- | Obtains the service URI of the handle whose index is specified by the
--   proxy type.
ixUriOf :: IxUriOf a procs => Proxy a -> HandlesOf procs -> SvcURI

-- | Select the named <tt><a>ProcHandle</a>s</tt> from an <a>HList</a> of
--   <tt><a>ProcHandle</a></tt>.
manyNamed :: SomeNamedHandles names namedProcs someProcs sortedProcs => Proxy names -> HandlesOf someProcs -> HandlesOf namedProcs

-- | Obtain the <a>SlimHandle</a> of several <tt><a>Proc</a>s</tt>
mapSlim :: AreProcs procs => HandlesOf procs -> [SlimHandle]

-- | Constraint alias when several <tt><a>Name</a>s</tt> are used to find
--   matching types in an <a>HList</a> of <a>ProcHandle</a>.
type SomeNamedHandles names procs someProcs sortedProcs = (names ~ Proc2Name procs, ManyMemberKV (SortSymbols names) (SortHandles (Proc2Handle procs)) (Handle2KV (Proc2Handle sortedProcs)), ReorderH (SortHandles (Proc2Handle procs)) (Proc2Handle procs), ReorderH (Proc2Handle someProcs) (Proc2Handle sortedProcs), AreProcs sortedProcs, SortHandles (Proc2Handle someProcs) ~ Proc2Handle sortedProcs)

-- | A list of <tt><a>ProcHandle</a></tt> values of different types with
--   the name of the docker network connecting their processes

-- | <i>Deprecated: since v0.7 this is no longer necessary and will be
--   removed</i>
type NetworkHandlesOf procs = (Text, HandlesOf procs)

-- | Specifies how to construct a connection datatype for accessing the
--   launched service specified by a <a>Proc</a>.
class (Proc a) => Connectable a where {
    
    -- | The connection type.
    type Conn a = (conn :: Type) | conn -> a;
}

-- | Get a connection to the Proc via its <a>ProcHandle</a>.
openConn :: Connectable a => ProcHandle a -> IO (Conn a)

-- | Close a connection to a <a>Proc</a>.
closeConn :: Connectable a => Conn a -> IO ()

-- | Run an action on a <a>Connectable</a> handle as a callback on its
--   <a>Conn</a>
withTmpConn :: Connectable a => ProcHandle a -> (Conn a -> IO b) -> IO b

-- | Open all the <a>Connectable</a> types to corresponding <a>Conn</a>
--   types.
openAll :: Connectables xs => HandlesOf xs -> IO (HList (ConnsOf xs))

-- | Close some <a>Connectable</a> types.
closeAll :: Connectables procs => HList (ConnsOf procs) -> IO ()

-- | Open some connections, use them in an action; close them.
withConns :: Connectables procs => HandlesOf procs -> (HList (ConnsOf procs) -> IO b) -> IO b

-- | Builds on <a>handleOf</a>; gives the <a>Conn</a> of the
--   <a>ProcHandle</a> to a callback.
withConnOf :: (HandleOf idx procs namedConn, Connectable namedConn) => Proxy idx -> HandlesOf procs -> (Conn namedConn -> IO b) -> IO b

-- | Open all known connections; use them in an action; close them.
withKnownConns :: (AreProcs someProcs, Connectables conns, ReorderH (Proc2Handle someProcs) (Proc2Handle conns)) => HandlesOf someProcs -> (HList (ConnsOf conns) -> IO b) -> IO b

-- | Open the named connections; use them in an action; close them.
withNamedConns :: (SomeNamedHandles names namedConns someProcs sortedProcs, Connectables namedConns) => Proxy names -> HandlesOf someProcs -> (HList (ConnsOf namedConns) -> IO b) -> IO b

-- | Declares a proof that a list of types only contains
--   <tt><a>Connectable</a>s</tt>.
class Connectables as

-- | Determine if the docker daemon is accessible.
hasDocker :: IO Bool

-- | generate a random network name

-- | <i>Deprecated: since v0.7 this is no longer needs to be exported and
--   will be hidden in later releases</i>
genNetworkName :: IO Text

-- | The IP address of the docker host.
type HostIpAddress = Text

-- | A connection string used to access the service once its running.
type SvcURI = ByteString

-- | Sort a list of type-level <tt>symbols</tt> using merge sort.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; :kind! SortSymbols '["xyz", "def", "abc"]
--   SortSymbols '["xyz", "def", "abc"] :: [Symbol]
--   = '["abc", "def", "xyz"]
--   </pre>
type family SortSymbols (xs :: [Symbol]) :: [Symbol]

-- | Computes the midpoint of a number.
--   
--   N.B: maximum value that this works for depends on the reduction limit
--   of the type-checker.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; :kind! CmpNat 49 (HalfOf 99)
--   CmpNat 49 (HalfOf 99) :: Ordering
--   = 'EQ
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; :kind! CmpNat 50 (HalfOf 100)
--   CmpNat 50 (HalfOf 100) :: Ordering
--   = 'EQ
--   </pre>
type family HalfOf (n :: Nat) :: Nat

-- | Counts a list, 1 element at a time.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; :kind! CmpNat 4 (LengthOf '[1, 2, 3, 4])
--   CmpNat 4 (LengthOf '[1, 2, 3, 4]) :: Ordering
--   = 'EQ
--   </pre>
type family LengthOf (xs :: [k]) :: Nat

-- | Drops 1 element at a time until the the dropped target is reached.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; :kind! Drop '["a", "b", "c", "d"] 2
--   Drop '["a", "b", "c", "d"] 2 :: [Symbol]
--   = '["c", "d"]
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; :kind! Drop '["a"] 2
--   Drop '["a"] 2 :: [Symbol]
--   = '[]
--   </pre>
type family Drop (xs :: [k]) (n :: Nat) :: [k]

-- | Takes 1 element at a time from a list until the desired length is
--   reached.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; :kind! Take '["a", "b", "c", "d"] 2
--   Take '["a", "b", "c", "d"] 2 :: [Symbol]
--   = '["a", "b"]
--   </pre>
type family Take (xs :: [k]) (n :: Nat) :: [k]

-- | Generate proof instances of <a>IsIn</a>.
class IsInProof t (tys :: [Type])

-- | Allows reordering of similar <tt><a>HList</a>s</tt>.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; hReorder @_ @'[Bool, Int] ('c' &amp;: (3 :: Int) &amp;: True &amp;: (3.1 :: Double) &amp;: HNil)
--   True &amp;: 3 &amp;: HNil
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; hReorder @_ @'[Double, Bool, Int] ('c' &amp;: (3 :: Int) &amp;: True &amp;: (3.1 :: Double) &amp;: HNil)
--   3.1 &amp;: True &amp;: 3 &amp;: HNil
--   </pre>
class ReorderH xs ys
hReorder :: ReorderH xs ys => HList xs -> HList ys

-- | Generate proof instances of <a>LookupMany</a>.
class ManyMemberKV (ks :: [Symbol]) (ts :: [Type]) (kvs :: [Type])

-- | Generate proof instances of <a>LookupKV</a>.
class MemberKV (k :: Symbol) (t :: Type) (xs :: [Type])

-- | A constraint that confirms that a type is not present in a type-level
--   list.
type family IsAbsent e r :: Constraint

-- | Use a type-level symbol as <i>key</i> type that indexes a <i>value</i>
--   type.
data KV :: Symbol -> Type -> Type
[V] :: a -> KV s a

-- | Defines a Heterogenous list.
data HList :: [Type] -> Type
[HNil] :: HList '[]
[HCons] :: anyTy -> HList manyTys -> HList (anyTy : manyTys)
infixr 5 `HCons`

-- | Obtain the first element of a <a>HList</a>.
hHead :: HList (a : as) -> a

-- | Get an item in an <a>HList</a> given its type.
hOf :: forall y xs. IsInProof y xs => Proxy y -> HList xs -> y

-- | An infix alias for <a>HCons</a>.
(&:) :: x -> HList xs -> HList (x : xs)
infixr 5 &:

-- | Construct a two-item HList.
both :: x -> y -> HList '[x, y]
infixr 6 `both`

-- | An infix alias for <a>both</a>.
(&:&) :: x -> y -> HList '[x, y]
infixr 6 &:&

-- | Construct a singleton HList
only :: x -> HList '[x]

-- | Select an item from an <a>HList</a> of <tt><a>KV</a>s</tt> by
--   <i>key</i>.
--   
--   <i>N.B</i> Returns the first item. It assumes the keys in the KV HList
--   are unique. <i>TODO:</i> enforce this rule using a constraint.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; select @"d" @Double  @'[KV "b" Bool, KV "d" Double] (V True &amp;:  V (3.1 :: Double) &amp;: HNil)
--   3.1
--   </pre>
select :: forall k t xs. MemberKV k t xs => HList xs -> t

-- | Select items with specified keys from an <tt><a>HList</a></tt> of
--   <tt><a>KV</a>s</tt> by <i>key</i>.
--   
--   <i>N.B.</i> this this is an internal function.
--   
--   The keys must be provided in the same order as they occur in the
--   HList, any other order will likely result in an compiler error.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; selectMany @'["b"] @'[Bool] @'[KV "b" Bool, KV "d" Double] (V True &amp;:  V (3.1 :: Double) &amp;: HNil)
--   True &amp;: HNil
--   </pre>
selectMany :: forall ks ts xs. ManyMemberKV ks ts xs => HList xs -> HList ts
instance GHC.Show.Show System.TmpProc.Docker.Pinged
instance GHC.Classes.Eq System.TmpProc.Docker.Pinged
instance GHC.Show.Show System.TmpProc.Docker.SlimHandle
instance GHC.Classes.Eq System.TmpProc.Docker.SlimHandle
instance System.TmpProc.Docker.Connectables '[]
instance (System.TmpProc.Docker.Connectable a, System.TmpProc.Docker.Connectables as, System.TmpProc.TypeLevel.IsAbsent a as) => System.TmpProc.Docker.Connectables (a : as)
instance System.TmpProc.Docker.HasHandle p procs => System.TmpProc.Docker.HandleOf p procs p
instance System.TmpProc.Docker.HasHandle p procs => System.TmpProc.Docker.IxReset p procs
instance System.TmpProc.Docker.HasHandle p procs => System.TmpProc.Docker.IxPing p procs
instance System.TmpProc.Docker.HasHandle p procs => System.TmpProc.Docker.IxUriOf p procs
instance System.TmpProc.Docker.HasNamedHandle name p procs => System.TmpProc.Docker.HandleOf name procs p
instance System.TmpProc.Docker.HasNamedHandle name a procs => System.TmpProc.Docker.IxReset name procs
instance System.TmpProc.Docker.HasNamedHandle name a procs => System.TmpProc.Docker.IxPing name procs
instance System.TmpProc.Docker.HasNamedHandle name a procs => System.TmpProc.Docker.IxUriOf name procs
instance System.TmpProc.Docker.AreProcs '[]
instance (System.TmpProc.Docker.ProcPlus a prepared, System.TmpProc.Docker.AreProcs as, System.TmpProc.TypeLevel.IsAbsent a as) => System.TmpProc.Docker.AreProcs (a : as)
instance (a GHC.Types.~ a', System.TmpProc.Docker.Proc a) => System.TmpProc.Docker.Preparer a a'
instance (a GHC.Types.~ a', System.TmpProc.Docker.Proc a) => System.TmpProc.Docker.ToRunCmd a a'


-- | Provides functions that make it easy to run <i><a>Application</a>s</i>
--   that access services running as <tt>tmp</tt> <tt>procs</tt> in
--   integration tests.
module System.TmpProc.Warp

-- | Set up some <tt>ProcHandles</tt> then run an <a>Application</a> that
--   uses them on a free port.
--   
--   Allows the app to configure itself using the <tt>tmp procs</tt>, then
--   provides a callback with access to the handles.
--   
--   The <tt>tmp procs</tt> are shut down when the application is shut
--   down.
testWithApplication :: AreProcs procs => HList procs -> (HandlesOf procs -> IO Application) -> ((HandlesOf procs, Port) -> IO a) -> IO a

-- | Set up some <tt>ProcHandles</tt> then run an <a>Application</a> that
--   uses them on a free port.
--   
--   Allows the app to configure itself using the <tt>tmp procs</tt>, then
--   provides a callback with access to the handles.
--   
--   Also runs a <tt>ready</tt> action that to determine if the application
--   started correctly.
--   
--   The <tt>tmp procs</tt> are shut down when the application is shut
--   down.
testWithReadyApplication :: AreProcs procs => (Port -> IO ()) -> HList procs -> (HandlesOf procs -> IO Application) -> ((HandlesOf procs, Port) -> IO a) -> IO a

-- | Like <a>testWithApplication</a>, but the port is secured using a
--   'Warp.TLSSettings. '
testWithTLSApplication :: AreProcs procs => TLSSettings -> HList procs -> (HandlesOf procs -> IO Application) -> ((HandlesOf procs, Port) -> IO a) -> IO a

-- | Like <a>testWithReadyApplication</a>; the port is secured with
--   <a>TLSSettings</a>.
testWithReadyTLSApplication :: AreProcs procs => TLSSettings -> (Port -> IO ()) -> HList procs -> (HandlesOf procs -> IO Application) -> ((HandlesOf procs, Port) -> IO a) -> IO a

-- | Represents a started Warp application and any <a>AreProcs</a>
--   dependencies.
data ServerHandle procs

-- | The <a>Port</a> on which the <a>ServerHandle</a>s server is running.
serverPort :: ServerHandle procs -> Port

-- | The <tt><a>ServerHandle</a>s</tt> <tt>ProcHandles</tt>.
handles :: AreProcs procs => ServerHandle procs -> HandlesOf procs

-- | Shuts down the <a>ServerHandle</a> server and its <tt>tmp proc</tt>
--   dependencies.
shutdown :: AreProcs procs => ServerHandle procs -> IO ()

-- | Runs an <a>Application</a> with <tt>ProcHandle</tt> dependencies on a
--   free port.
runServer :: AreProcs procs => HList procs -> (HandlesOf procs -> IO Application) -> IO (ServerHandle procs)

-- | Like <a>runServer</a>; with an additional <tt>ready</tt> that
--   determines if the server is ready.'.
runReadyServer :: AreProcs procs => (Port -> IO ()) -> HList procs -> (HandlesOf procs -> IO Application) -> IO (ServerHandle procs)

-- | Like <a>runServer</a>; the port is secured with <a>TLSSettings</a>.
runTLSServer :: AreProcs procs => TLSSettings -> HList procs -> (HandlesOf procs -> IO Application) -> IO (ServerHandle procs)

-- | Like <a>runReadyServer</a>; the port is secured with
--   <a>TLSSettings</a>.
runReadyTLSServer :: AreProcs procs => TLSSettings -> (Port -> IO ()) -> HList procs -> (HandlesOf procs -> IO Application) -> IO (ServerHandle procs)

-- | Simplifies writing the health checks used by <tt>ready</tt> variants
--   of this module.
checkHealth :: Int -> IO (Either a b) -> IO ()


-- | Exports all tmp-proc behaviour.
--   
--   <tt>tmp-proc</tt> is a package that aims to simplify writing
--   integration tests that use dockerizable services.
--   
--   The package has the following structure:
--   
--   <ul>
--   <li><b><a>System.TmpProc.Docker</a>:</b> definition of core data
--   types, <tt>Proc</tt> and <tt>ProcHandle</tt>, and their
--   combinators.</li>
--   <li><b><a>System.TmpProc.Warp</a>:</b> functions that make it easy to
--   test a WAI <tt>application</tt> that accesses <tt>tmp</tt>
--   <tt>procs</tt></li>
--   </ul>
module System.TmpProc