11module Node.ChildProcess
22 ( Handle ()
3- , Spawn ()
4- , Stdin ()
5- , Stdout ()
6- , Stderr ()
73 , ChildProcess ()
8- , SpawnOptions ()
4+ , CHILD_PROCESS ()
5+ , stderr
6+ , stdout
7+ , stdin
8+ , pid
9+ , connected
10+ , kill
11+ , send
12+ , disconnect
913 , ChildProcessError ()
1014 , onExit
1115 , onClose
1216 , onDisconnect
1317 , onMessage
1418 , onError
1519 , spawn
20+ , SpawnOptions ()
1621 , defaultSpawnOptions
1722 ) where
1823
1924import Prelude
2025
2126import Control.Monad.Eff (Eff ())
2227
23- import Data.Function (Fn0 (), Fn1 (), Fn2 ())
28+ import Data.StrMap (StrMap ())
29+ import Data.Function (Fn2 (), runFn2 )
30+ import Data.Nullable (Nullable (), toNullable )
2431import Data.Maybe (Maybe (..))
2532import Data.Foreign (Foreign ())
2633
34+ import Node.Buffer (Buffer ())
2735import Node.Stream (Readable (), Writable ())
2836import Node.ChildProcess.Signal (Signal (..))
2937
38+ -- | A handle for inter-process communication (IPC).
3039foreign import data Handle :: *
31- foreign import data Spawn :: !
32- foreign import data Stdin :: !
33- foreign import data Stdout :: !
34- foreign import data Stderr :: !
35-
36- type ChildProcess =
37- { stderr :: forall eff . Readable () (stderr :: Stderr | eff ) String
38- , stdin :: forall eff . Writable () (stdin :: Stdin | eff ) String
39- , stdout :: forall eff . Readable () (stdout :: Stdout | eff ) String
40- , pid :: Number
40+
41+ -- | The effect for creating and interacting with child processes.
42+ foreign import data CHILD_PROCESS :: !
43+
44+ newtype ChildProcess = ChildProcess ChildProcessRec
45+
46+ runChildProcess :: ChildProcess -> ChildProcessRec
47+ runChildProcess (ChildProcess r) = r
48+
49+ -- | Note: some of these types are lies, and so it is unsafe to access some of
50+ -- | these record fields directly.
51+ type ChildProcessRec =
52+ { stderr :: forall eff . Readable () (cp :: CHILD_PROCESS | eff ) Buffer
53+ , stdin :: forall eff . Writable () (cp :: CHILD_PROCESS | eff ) Buffer
54+ , stdout :: forall eff . Readable () (cp :: CHILD_PROCESS | eff ) Buffer
55+ , pid :: Int
4156 , connected :: Boolean
42- , kill :: forall eff . Fn1 Signal Boolean
43- , send :: forall eff r . Fn2 { | r } Handle ( Eff eff Unit )
44- , disconnect :: forall eff . Fn0 ( Eff eff Unit )
57+ , kill :: Signal -> Boolean
58+ , send :: forall r . Fn2 { | r } Handle Boolean
59+ , disconnect :: forall eff . Eff eff Unit
4560 }
4661
62+ -- | The standard error stream of a child process. Note that this is only
63+ -- | available if the process was spawned with the stderr option set to "pipe".
64+ stderr :: forall eff . ChildProcess -> Readable () (cp :: CHILD_PROCESS | eff ) Buffer
65+ stderr = _.stderr <<< runChildProcess
66+
67+ -- | The standard output stream of a child process. Note that this is only
68+ -- | available if the process was spawned with the stdout option set to "pipe".
69+ stdout :: forall eff . ChildProcess -> Readable () (cp :: CHILD_PROCESS | eff ) Buffer
70+ stdout = _.stdout <<< runChildProcess
71+
72+ -- | The standard input stream of a child process. Note that this is only
73+ -- | available if the process was spawned with the stdin option set to "pipe".
74+ stdin :: forall eff . ChildProcess -> Writable () (cp :: CHILD_PROCESS | eff ) Buffer
75+ stdin = _.stdin <<< runChildProcess
76+
77+ -- | The process ID of a child process. Note that if the process has already
78+ -- | exited, another process may have taken the same ID, so be careful!
79+ pid :: ChildProcess -> Int
80+ pid = _.pid <<< runChildProcess
81+
82+ connected :: forall eff . ChildProcess -> Eff (cp :: CHILD_PROCESS | eff ) Boolean
83+ connected = pure <<< _.connected <<< runChildProcess
84+
85+ send :: forall eff props . { | props } -> Handle -> ChildProcess -> Eff (cp :: CHILD_PROCESS | eff ) Boolean
86+ send msg handle (ChildProcess cp) = pure (runFn2 cp.send msg handle)
87+
88+ disconnect :: forall eff . ChildProcess -> Eff (cp :: CHILD_PROCESS | eff ) Unit
89+ disconnect = _.disconnect <<< runChildProcess
90+
91+ -- | Send a signal to a child process. It's an unfortunate historical decision
92+ -- | that this function is called "kill", as sending a signal to a child
93+ -- | process won't necessarily kill it.
94+ kill :: forall eff . Signal -> ChildProcess -> Eff (cp :: CHILD_PROCESS | eff ) Boolean
95+ kill sig (ChildProcess cp) = pure (cp.kill sig)
96+
4797type SpawnOptions =
4898 { cwd :: String
4999 , stdio :: Array String
50- , env :: forall r . { | r }
100+ , env :: Nullable ( StrMap String )
51101 , detached :: Boolean
52- , uid :: Number
53- , gid :: Number
102+ , uid :: Int
103+ , gid :: Int
54104 }
55105
56- onExit :: forall eff . ChildProcess -> (Maybe Number -> Maybe Signal -> Eff eff Unit ) -> Eff eff Unit
106+ onExit :: forall eff . ChildProcess -> (Maybe Int -> Maybe Signal -> Eff eff Unit ) -> Eff eff Unit
57107onExit = mkOnExit Nothing Just Signal
58108
59- onClose :: forall eff . ChildProcess -> (Maybe Number -> Maybe Signal -> Eff eff Unit ) -> Eff eff Unit
109+ onClose :: forall eff . ChildProcess -> (Maybe Int -> Maybe Signal -> Eff eff Unit ) -> Eff eff Unit
60110onClose = mkOnClose Nothing Just Signal
61111
62112onMessage :: forall eff . ChildProcess -> (Foreign -> Maybe Handle -> Eff eff Unit ) -> Eff eff Unit
@@ -65,13 +115,13 @@ onMessage = mkOnMessage Nothing Just
65115foreign import onDisconnect :: forall eff . ChildProcess -> Eff eff Unit -> Eff eff Unit
66116foreign import onError :: forall eff . ChildProcess -> (ChildProcessError -> Eff eff Unit ) -> Eff eff Unit
67117
68- foreign import spawn :: forall eff . String -> Array String -> SpawnOptions -> Eff (spawn :: Spawn | eff ) ChildProcess
118+ foreign import spawn :: forall eff . String -> Array String -> SpawnOptions -> Eff (cp :: CHILD_PROCESS | eff ) ChildProcess
69119
70120defaultSpawnOptions :: SpawnOptions
71121defaultSpawnOptions =
72122 { cwd: undefined
73123 , stdio: [" pipe" , " pipe" , " pipe" ]
74- , env: process.env
124+ , env: toNullable Nothing
75125 , detached: false
76126 , uid: undefined
77127 , gid: undefined
@@ -85,14 +135,13 @@ type ChildProcessError =
85135
86136foreign import mkOnExit :: forall a eff .
87137 Maybe a -> (a -> Maybe a ) -> (String -> Signal ) ->
88- ChildProcess -> (Maybe Number -> Maybe Signal -> Eff eff Unit ) -> Eff eff Unit
138+ ChildProcess -> (Maybe Int -> Maybe Signal -> Eff eff Unit ) -> Eff eff Unit
89139foreign import mkOnMessage :: forall a eff .
90140 Maybe a -> (a -> Maybe a ) ->
91141 ChildProcess -> (Foreign -> Maybe Handle -> Eff eff Unit ) -> Eff eff Unit
92142foreign import mkOnClose :: forall a eff .
93143 Maybe a -> (a -> Maybe a ) -> (String -> Signal ) ->
94- ChildProcess -> (Maybe Number -> Maybe Signal -> Eff eff Unit ) -> Eff eff Unit
144+ ChildProcess -> (Maybe Int -> Maybe Signal -> Eff eff Unit ) -> Eff eff Unit
95145
96146-- There's gotta be a better way.
97147foreign import undefined :: forall a . a
98- foreign import process :: forall r . { env :: { | r } }
0 commit comments