From 8775860fdd67e2406b80d9818ab44d2c2bcc3bd5 Mon Sep 17 00:00:00 2001 From: enzotar Date: Thu, 26 Feb 2026 09:04:22 -0800 Subject: [PATCH] feat: 4-app signal composition demo with explicit outputs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add 3 new streaming apps with explicit output declarations: - streaming-clock.ds: output hours, minutes, seconds (tick private) - streaming-stats.ds: output total, average, max (sum private) - streaming-mood.ds: output mood, energy, color (clicks private) Add compose-dashboard.ds that receives all 4 streams via unique relay channels (/stream/default, /stream/clock, /stream/stats, /stream/mood) into a single dashboard view. Each app demonstrates selective signal registration — only declared outputs are streamed, internal state remains private. --- examples/compose-dashboard.ds | 53 +++++++++++++++++++++++++++++++++++ examples/streaming-clock.ds | 25 +++++++++++++++++ examples/streaming-mood.ds | 50 +++++++++++++++++++++++++++++++++ examples/streaming-stats.ds | 44 +++++++++++++++++++++++++++++ 4 files changed, 172 insertions(+) create mode 100644 examples/compose-dashboard.ds create mode 100644 examples/streaming-clock.ds create mode 100644 examples/streaming-mood.ds create mode 100644 examples/streaming-stats.ds diff --git a/examples/compose-dashboard.ds b/examples/compose-dashboard.ds new file mode 100644 index 0000000..45a19cc --- /dev/null +++ b/examples/compose-dashboard.ds @@ -0,0 +1,53 @@ +-- DreamStack 4-App Composition Dashboard +-- Composes signals from 4 independent streaming apps. +-- Each app has explicit output declarations: +-- counter: count, doubled (NOT message) +-- clock: hours, minutes, seconds (NOT tick) +-- stats: total, average, max (NOT sum, last_sample) +-- mood: mood, energy, color (NOT clicks) +-- +-- Run with: +-- Tab 1: cargo run -p ds-stream +-- Tab 2: dreamstack stream examples/streaming-counter.ds --port 3000 +-- Tab 3: dreamstack stream examples/streaming-clock.ds --port 3002 +-- Tab 4: dreamstack stream examples/streaming-stats.ds --port 3003 +-- Tab 5: dreamstack stream examples/streaming-mood.ds --port 3004 +-- Tab 6: dreamstack build examples/compose-dashboard.ds +-- +-- Open the built file in a browser. + +let counter = stream from "ws://localhost:9100/stream/default" +let clock = stream from "ws://localhost:9100/stream/clock" +let stats = stream from "ws://localhost:9100/stream/stats" +let mood = stream from "ws://localhost:9100/stream/mood" + +view main = + column [ + text "🎛️ DreamStack Signal Composition" + text "4 apps → 1 dashboard" + row [ + column [ + text "── 🔢 Counter ──" + text "Count: {counter.count}" + text "Doubled: {counter.doubled}" + ] + column [ + text "── 🕐 Clock ──" + text "{clock.hours}:{clock.minutes}:{clock.seconds}" + ] + ] + row [ + column [ + text "── 📊 Stats ──" + text "Samples: {stats.total}" + text "Average: {stats.average}" + text "Max: {stats.max}" + ] + column [ + text "── 😊 Mood ──" + text "Mood: {mood.mood}" + text "Energy: {mood.energy}%" + text "Color: {mood.color}" + ] + ] + ] diff --git a/examples/streaming-clock.ds b/examples/streaming-clock.ds new file mode 100644 index 0000000..2df4bde --- /dev/null +++ b/examples/streaming-clock.ds @@ -0,0 +1,25 @@ +-- DreamStack Streaming Clock +-- Streams time signals every second. +-- Only hours, minutes, seconds are exposed (tick is internal). +-- +-- Run with: +-- dreamstack stream examples/streaming-clock.ds --port 3002 + +let tick = 0 +let seconds = tick % 60 +let minutes = (tick / 60) % 60 +let hours = (tick / 3600) % 24 + +stream clock on "ws://localhost:9100/peer/clock" { + mode: signal, + output: hours, minutes, seconds +} + +every 1000 -> tick += 1 + +view clock = + column [ + text "🕐 Streaming Clock" + text "{hours}:{minutes}:{seconds}" + text "tick: {tick}" + ] diff --git a/examples/streaming-mood.ds b/examples/streaming-mood.ds new file mode 100644 index 0000000..d1d027a --- /dev/null +++ b/examples/streaming-mood.ds @@ -0,0 +1,50 @@ +-- DreamStack Streaming Mood +-- Interactive mood and energy tracker. +-- Only mood, energy, color are exposed (clicks is internal). +-- +-- Run with: +-- dreamstack stream examples/streaming-mood.ds --port 3004 --relay ws://localhost:9100/source/mood + +let mood = "neutral" +let energy = 50 +let color = "gray" +let clicks = 0 + +stream mood_tracker on "ws://localhost:9100/peer/mood" { + mode: signal, + output: mood, energy, color +} + +view mood_tracker = + column [ + text "😊 Mood Tracker" + text "Mood: {mood}" + text "Energy: {energy}%" + text "Color: {color}" + row [ + button "😄 Happy" { + click: mood = "happy" + click: color = "green" + click: energy = energy + 10 + } + button "😐 Neutral" { + click: mood = "neutral" + click: color = "gray" + } + button "😤 Angry" { + click: mood = "angry" + click: color = "red" + click: energy = energy - 10 + } + ] + row [ + button "☕ Caffeine" { + click: energy = energy + 25 + click: clicks += 1 + } + button "😴 Rest" { + click: energy = energy - 15 + click: clicks += 1 + } + ] + ] diff --git a/examples/streaming-stats.ds b/examples/streaming-stats.ds new file mode 100644 index 0000000..ba5ab58 --- /dev/null +++ b/examples/streaming-stats.ds @@ -0,0 +1,44 @@ +-- DreamStack Streaming Stats +-- Tracks button presses and computes statistics. +-- Only total, average, max are exposed (sum and last_sample are internal). +-- +-- Run with: +-- dreamstack stream examples/streaming-stats.ds --port 3003 + +let total = 0 +let max = 0 +let sum = 0 +let average = sum / (total + 1) + +stream stats on "ws://localhost:9100/peer/stats" { + mode: signal, + output: total, average, max +} + +view stats = + column [ + text "📊 Streaming Stats" + text "Samples: {total}" + text "Average: {average}" + text "Max: {max}" + row [ + button "+5" { + click: total += 1 + click: sum += 5 + } + button "+10" { + click: total += 1 + click: sum += 10 + } + button "+25" { + click: total += 1 + click: sum += 25 + click: max = 25 + } + button "+50" { + click: total += 1 + click: sum += 50 + click: max = 50 + } + ] + ]