git.iko.soy/purestack-dev/todomvc
on master help sign in
runMsg
commita4c41d985ead56d991e869662997229bd028078b authoriko <mail@iko.soy> dateFri 4 Jul 2025, 20:52 (1 year ago) parentc8f9b92
3 files changed+48−18
flake.nix+2 src/Frontend.purs+9−5 src/Plum.purs+37−13
flake.nix+2
@@ -38,6 +38,8 @@
3838 project-m36.command = "${
3939 project-m36-rest.packages.${system}.default
4040 }/bin/project-m36-rest";
41+ proxy.command =
42+ "${pkgs.reproxy}/bin/reproxy -l=localhost:3001 --static.enabled --static.rule='*,^/api/(.*),http://localhost:3000/$1' --assets.location=. --assets.spa";
4143 };
4244 });
4345 in {
src/Frontend.purs+9−5
@@ -19,14 +19,18 @@ type Model = { newTodo :: String, todos :: Array String }
1919data Msg
2020 = UpdateNewTodo String
2121 | AddNewTodo
22+ | TodoAdded
2223
2324main :: Effect Unit
2425main = do
2526 Plum.run @Model @Msg "plum"
26− { init: pure { newTodo: "", todos: [] }
27− , update: \msg model -> case msg of
27+ { init: \_runMsg -> pure { newTodo: "", todos: [] }
28+ , update: \runMsg msg model -> case msg of
2829 UpdateNewTodo newTodo -> pure model { newTodo = newTodo }
29− AddNewTodo -> pure model { newTodo = "", todos = model.newTodo : model.todos }
30+ AddNewTodo -> do
31+ runMsg $ api.createTodo (TodoItem { text: model.newTodo, done: false }) $> TodoAdded
32+ pure model { newTodo = "", todos = model.newTodo : model.todos }
33+ TodoAdded -> pure model
3034 , view: \model -> column do
3135 font "sans-serif"
3236
@@ -46,9 +50,9 @@ main = do
4650 text todo mempty
4751 }
4852
49−url = case URL.fromString "localhost" of
53+url = case URL.fromString "http://localhost" of
5054 Just x -> x
5155 Nothing -> unsafeCoerce unit
5256
53−x = client @API url
57+api = client @API url
5458
src/Plum.purs+37−13
@@ -5,12 +5,15 @@ import Prelude
55import Data.Array as Array
66import Data.Maybe (Maybe(..))
77import Effect (Effect)
8+import Effect.Aff (Aff, launchAff_)
9+import Effect.Class (liftEffect)
810import Effect.Console (log)
911import Effect.Ref as Ref
1012import Foreign.Object as Object
1113import Literals.Undefined (undefined)
1214import Plum.View (GenericUI(..), UI, grow)
1315import Snabbdom as Snabbdom
16+import Unsafe.Coerce (unsafeCoerce)
1417import Untagged.Union (asOneOf)
1518import Web.DOM.NonElementParentNode (getElementById) as Web
1619import Web.HTML (window) as Web
@@ -18,8 +21,8 @@ import Web.HTML.HTMLDocument (toNonElementParentNode) as Web
1821import Web.HTML.Window (document) as Web
1922
2023type Plum msg model =
21− { init :: Effect model
22− , update :: msg -> model -> Effect model
24+ { init :: (Aff msg -> Effect Unit) -> Effect model
25+ , update :: (Aff msg -> Effect Unit) -> msg -> model -> Effect model
2326 , view :: model -> UI msg Unit
2427 }
2528
@@ -28,25 +31,36 @@ run id plum = do
2831 Web.window >>= Web.document >>= Web.getElementById id <<< Web.toNonElementParentNode >>= case _ of
2932 Just element -> do
3033 let node = Snabbdom.toVNode element
34+ modelRef <- Ref.new { model: unsafeCoerce undefined, lastNode: node }
3135 patch <- Snabbdom.init
32− initModel <- plum.init
33− modelRef <- Ref.new { model: initModel, lastNode: node }
3436 let
37+ fire =
38+ ( \msg -> do
39+ log "in"
40+ { model: m, lastNode } <- Ref.read modelRef
41+ m_ <- plum.update
42+ ( \aff ->
43+ launchAff_
44+ ( do
45+ msg' <- aff
46+ liftEffect $ fire msg'
47+ pure unit
48+ )
49+ )
50+ msg
51+ m
52+ node' <- view m_
53+ newNode <- patch lastNode node'
54+ Ref.write { model: m_, lastNode: newNode } modelRef
55+ pure unit
56+ )
3557 view model = do
3658 let UI { children } _ = plum.view model
3759 case Array.uncons children of
3860 Just { head: child } -> do
3961 let
4062 { node, style } = grow
41− ( \msg -> do
42− log "in"
43− { model: m, lastNode } <- Ref.read modelRef
44− m_ <- plum.update msg m
45− node <- view m_
46− newNode <- patch lastNode node
47− Ref.write { model: m_, lastNode: newNode } modelRef
48− pure unit
49− )
63+ fire
5064 child
5165 pure $
5266 Snabbdom.h "div"
@@ -75,6 +89,15 @@ run id plum = do
7589 }
7690 []
7791 (asOneOf undefined)
92+ initModel <- plum.init
93+ ( \aff ->
94+ launchAff_
95+ ( do
96+ msg' <- aff
97+ liftEffect $ fire msg'
98+ pure unit
99+ )
100+ )
78101 newNode <- view initModel
79102 newNode_ <- patch node newNode
80103 log "patched"
@@ -84,3 +107,4 @@ run id plum = do
84107
85108outerStyle :: String
86109outerStyle = "html,body{height:100%;padding:0;margin:0;}"
110+