rooibos 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c2eb32007ddd93c0a653829b44492878ca229fef1f90c84516d474d3f324132
4
- data.tar.gz: f52b7a94243bd9582b7229cf48b3834d3f9ae6abaf9f9d6c622625f1d3951a8a
3
+ metadata.gz: 16b78b8c6fabd42cda3c443da5f6487f043f33190ac7bb8d2190add134d154be
4
+ data.tar.gz: 790da4bb69ca1f711fe3ae5dc41c09f18d88db4986258716db7b6db6060e21a3
5
5
  SHA512:
6
- metadata.gz: 2d5dc50320f2b8026cbb4f33d4c94b2a18beb6930bbdda45a0d38f14013c7015ecb5fce740d2003e6ba19cf48c901dc21e65034d2a66cc6ab6e6c7a3615688e0
7
- data.tar.gz: 17a5f9bd24f5c9075fbe333a542a094ec40aa9063bd93d0265a5c4c264ead213d9c5030691c62cfd40c3c731570b5c30da0665dc67dbb1ff2a57545e729404f4
6
+ metadata.gz: d306617ae1c2532c8bd105941beea50d4715840c0a087ec0199863e5ea089f7db1cdb9e9dea2a1921dec4b783c9f953963fe89f2a41d981101cc751b0ac518bf
7
+ data.tar.gz: 483be60cb25f8025bf222d8e63ba5d784695678aac93d883a0fa9ac83ba53832103e4f3c6be5b3908509d3b6b1f0d3572afa83de77e30398a12e7a56a9b25497
data/.builds/ruby-3.2.yml CHANGED
@@ -16,7 +16,7 @@ packages:
16
16
  - clang
17
17
  - git
18
18
  artifacts:
19
- - rooibos/pkg/rooibos-0.6.0.gem
19
+ - rooibos/pkg/rooibos-0.6.1.gem
20
20
  sources:
21
21
  - https://git.sr.ht/~kerrick/rooibos
22
22
  tasks:
data/.builds/ruby-3.3.yml CHANGED
@@ -16,7 +16,7 @@ packages:
16
16
  - clang
17
17
  - git
18
18
  artifacts:
19
- - rooibos/pkg/rooibos-0.6.0.gem
19
+ - rooibos/pkg/rooibos-0.6.1.gem
20
20
  sources:
21
21
  - https://git.sr.ht/~kerrick/rooibos
22
22
  tasks:
data/.builds/ruby-3.4.yml CHANGED
@@ -16,7 +16,7 @@ packages:
16
16
  - clang
17
17
  - git
18
18
  artifacts:
19
- - rooibos/pkg/rooibos-0.6.0.gem
19
+ - rooibos/pkg/rooibos-0.6.1.gem
20
20
  sources:
21
21
  - https://git.sr.ht/~kerrick/rooibos
22
22
  tasks:
@@ -16,7 +16,7 @@ packages:
16
16
  - clang
17
17
  - git
18
18
  artifacts:
19
- - rooibos/pkg/rooibos-0.6.0.gem
19
+ - rooibos/pkg/rooibos-0.6.1.gem
20
20
  sources:
21
21
  - https://git.sr.ht/~kerrick/rooibos
22
22
  tasks:
data/CHANGELOG.md CHANGED
@@ -21,6 +21,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
21
21
 
22
22
  ### Removed
23
23
 
24
+ ## [0.6.1] - 2026-01-26
25
+
26
+ ### Added
27
+
28
+ ### Changed
29
+
30
+ ### Fixed
31
+
32
+ ### Removed
33
+
24
34
  ## [0.6.0] - 2026-01-25
25
35
 
26
36
  ### Added
@@ -250,6 +260,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
250
260
  - **First Release**: Empty release of `rooibos`, a Ruby implementation of The Elm Architecture (TEA) for `ratatui_ruby`. Scaffolding generated by `ratatui_ruby-devtools`.
251
261
 
252
262
  [Unreleased]: https://git.sr.ht/~kerrick/rooibos/refs/HEAD
263
+ [0.6.1]: https://git.sr.ht/~kerrick/rooibos/refs/v0.6.1
253
264
  [0.6.0]: https://git.sr.ht/~kerrick/rooibos/refs/v0.6.0
254
265
  [0.5.0]: https://git.sr.ht/~kerrick/rooibos/refs/v0.5.0
255
266
  [0.4.0]: https://git.sr.ht/~kerrick/rooibos/refs/v0.4.0
@@ -0,0 +1,17 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
+ -->
5
+
6
+ # For Rails Developers
7
+
8
+
9
+ By the end of this guide, you will:
10
+
11
+ - Understand how MVC is similar to and different from MVU
12
+ - Understand why TUIs run a continuous loop instead of request/response
13
+ - Explain how Commands handle async work off the main thread
14
+ - Translate "thinking in resources" to "thinking in state transitions"
15
+ - See side-by-side comparisons of Rails patterns and their Rooibos equivalents
16
+
17
+ > ⚠️ **This page is a stub.** Help us write it! See the [Documentation Plan](../contributors/documentation_plan.md) and [Style Guide](../contributors/documentation_style.md).
@@ -0,0 +1,17 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
+ -->
5
+
6
+ # For RatatuiRuby Developers
7
+
8
+
9
+ By the end of this guide, you will:
10
+
11
+ - Understand what Rooibos adds on top of RatatuiRuby
12
+ - Organize growing codebases with fragments instead of large case statements
13
+ - Migrate imperative draw calls to a declarative View function
14
+ - Convert poll_event handling to message-driven Update
15
+ - Use the same RatatuiRuby widgets, layouts, and styles you already know
16
+
17
+ > ⚠️ **This page is a stub.** Help us write it! See the [Documentation Plan](../contributors/documentation_plan.md) and [Style Guide](../contributors/documentation_style.md).
@@ -7,22 +7,63 @@
7
7
 
8
8
  module Rooibos
9
9
  module Command
10
- # An aggregating parallel command.
11
- All = Data.define(:envelope, :commands, :nested) do
10
+ # Aggregates parallel commands and returns all results together.
11
+ #
12
+ # Dashboards load user profiles, settings, and stats before rendering.
13
+ # Fetching sequentially is slow. Fire-and-forget batches lose correlation
14
+ # between commands and their results.
15
+ #
16
+ # This command runs children in parallel and collects their results into
17
+ # a single <tt>Message::All</tt> response. Pattern-match on the envelope
18
+ # to correlate results. Each result appears in the same order as commands.
19
+ #
20
+ # Use it for coordinated fetches where you need all results before proceeding.
21
+ #
22
+ # Prefer the <tt>Command.all</tt> factory method for convenience.
23
+ #
24
+ # === Example
25
+ #
26
+ # # Using the factory method (recommended)
27
+ # Command.all(:dashboard,
28
+ # Command.http(:get, "/users", :_),
29
+ # Command.http(:get, "/stats", :_),
30
+ # )
31
+ #
32
+ # # Using the class directly
33
+ # All.new(:dashboard,
34
+ # Command.http(:get, "/users", :_),
35
+ # Command.http(:get, "/stats", :_),
36
+ # )
37
+ #
38
+ # # Pattern-match on the aggregated result
39
+ # def update(message, model)
40
+ # case message
41
+ # in { type: :all, envelope: :dashboard, results: [users, stats] }
42
+ # model.with(users:, stats:, loading: false)
43
+ # end
44
+ # end
45
+ class All < Data.define(:envelope, :commands, :nested)
12
46
  include Custom
13
47
 
14
48
  class << self
15
49
  undef_method :new
16
50
 
51
+ # Creates an aggregating parallel command.
52
+ #
53
+ # [tag] Symbol to tag the result message.
54
+ # [args] Commands to run in parallel. Pass as multiple arguments
55
+ # or a single array.
56
+ #
57
+ # === Example
58
+ #
59
+ # All.new(:dashboard,
60
+ # Command.http(:get, "/users", :_),
61
+ # Command.http(:get, "/stats", :_),
62
+ # )
17
63
  def new(tag, *args)
18
- # DWIM: detect nested vs splatted based on call-site arity
19
- if args.size == 1 && args.first.is_a?(Array)
20
- commands = args.first
21
- nested = true
22
- else
23
- commands = args
24
- nested = false
25
- end
64
+ # DWIM: flatten single-array arg to support both call patterns
65
+ nested = args.size == 1 && args.first.is_a?(Array)
66
+ commands = [args].flatten(2)
26
67
 
27
68
  if RatatuiRuby::Debug.enabled?
28
69
  commands.each do |cmd|
@@ -40,11 +81,18 @@ module Rooibos
40
81
  end
41
82
  end
42
83
 
43
- # Executes the command, running all children in parallel.
84
+ # Executes all child commands in parallel and aggregates results.
85
+ #
86
+ # Sends <tt>Message::All</tt> when all children complete. Results appear
87
+ # in the same order as commands. If canceled, sends <tt>Message::Canceled</tt>.
88
+ #
89
+ # [out] Outlet for sending messages.
90
+ # [token] Cancellation token from the runtime.
44
91
  def call(out, token)
45
92
  # Early return for empty commands - prevents hang from zip_futures([])
46
93
  if commands.empty?
47
- response = Message::All.new(envelope:, results: [].freeze, nested:)
94
+ results = [] #: Array[Object]
95
+ response = Message::All.new(envelope:, results: results.freeze, nested:)
48
96
  out.put(Ractor.make_shareable(response))
49
97
  return
50
98
  end
@@ -20,18 +20,29 @@ module Rooibos
20
20
  # Use it for parallel fetches, concurrent refreshes, or any work that
21
21
  # does not need coordinated results.
22
22
  #
23
+ # Prefer the <tt>Command.batch</tt> factory method for convenience.
24
+ #
23
25
  # === Example
24
26
  #
27
+ # # Using the factory method (recommended)
28
+ # Command.batch(
29
+ # Command.http(:get, "/users", :users),
30
+ # Command.http(:get, "/stats", :stats),
31
+ # )
32
+ #
33
+ # # Using the class directly
34
+ # Batch.new(
35
+ # Command.http(:get, "/users", :users),
36
+ # Command.http(:get, "/stats", :stats),
37
+ # )
38
+ #
39
+ # # Handle each response independently
25
40
  # def update(msg, model)
26
41
  # case msg
27
- # in :refresh_all
28
- # batch = Command.batch(
29
- # Command.http(:get, "/users", :users),
30
- # Command.http(:get, "/stats", :stats),
31
- # )
32
- # [model.with(loading: true), batch]
33
- # in :users | :stats
34
- # [model.with(msg => data), nil]
42
+ # in { type: :http, envelope: :users, body: }
43
+ # model.with(users: JSON.parse(body))
44
+ # in { type: :http, envelope: :stats, body: }
45
+ # model.with(stats: JSON.parse(body))
35
46
  # end
36
47
  # end
37
48
  class Batch < Data.define(:commands) do
@@ -40,7 +51,15 @@ module Rooibos
40
51
  class << self
41
52
  undef_method :new
42
53
 
43
- # Initialize
54
+ # Creates a parallel batch command.
55
+ #
56
+ # [args] Commands to run in parallel. Pass as multiple arguments
57
+ # or a single array.
58
+ #
59
+ # === Example
60
+ #
61
+ # Batch.new(cmd1, cmd2, cmd3)
62
+ # Batch.new([cmd1, cmd2, cmd3])
44
63
  def new(*args)
45
64
  # DWIM: accept (cmd1, cmd2) or ([cmd1, cmd2])
46
65
  commands = (args.size == 1 && args.first.is_a?(Array)) ? args.first : args
@@ -61,7 +80,14 @@ module Rooibos
61
80
  end
62
81
  end
63
82
 
64
- # Call it
83
+ # Executes all child commands in parallel.
84
+ #
85
+ # Each child sends its results independently via the runtime.
86
+ # When all complete, sends <tt>Message::Batch</tt>. If canceled,
87
+ # sends <tt>Message::Canceled</tt> instead.
88
+ #
89
+ # [out] Outlet for sending messages.
90
+ # [token] Cancellation token from the runtime.
65
91
  def call(out, token)
66
92
  handles = commands.map { |cmd| out.standing(cmd, token) }
67
93
  out.wait(*handles, token:)
@@ -14,13 +14,64 @@ module Rooibos
14
14
  # New code should use Rooibos::Message::HttpResponse.
15
15
  HttpResponse = Message::HttpResponse
16
16
 
17
- # An HTTP request command.
18
- Http = Data.define(:method, :url, :envelope, :headers, :body, :timeout, :parser) do
17
+ # Performs HTTP requests and sends the response as a message.
18
+ #
19
+ # Applications fetch data from APIs. Users expect responsive interfaces
20
+ # while requests complete. Managing HTTP connections, timeouts, and
21
+ # threading manually is error-prone.
22
+ #
23
+ # This command executes HTTP requests off the main thread. The runtime
24
+ # dispatches it and routes the response back to your update function
25
+ # as a <tt>Message::HttpResponse</tt>.
26
+ #
27
+ # Use it to fetch API data, post forms, or interact with web services.
28
+ #
29
+ # Prefer the <tt>Command.http</tt> factory method for convenience.
30
+ # The constructor supports flexible DWIM (Do What I Mean) arity.
31
+ #
32
+ # === Example
33
+ #
34
+ # # Using the factory method (recommended)
35
+ # Command.http(:get, "/api/users", :users)
36
+ # Command.http(get: "/api/users", envelope: :users)
37
+ # Command.http(:post, "/api/users", '{"name":"Jo"}', :created)
38
+ #
39
+ # # Using the class directly
40
+ # Http.new(:get, "/api/users", :users)
41
+ #
42
+ # # Pattern-match on the response
43
+ # def update(message, model)
44
+ # case message
45
+ # in { type: :http, envelope: :users, status: 200, body: }
46
+ # model.with(users: JSON.parse(body))
47
+ # in { type: :http, envelope: :users, error: }
48
+ # model.with(error:)
49
+ # end
50
+ # end
51
+ class Http < Data.define(:method, :url, :envelope, :headers, :body, :timeout, :parser)
19
52
  include Custom
20
53
 
21
54
  class << self
22
55
  undef_method :new
23
56
 
57
+ # Creates an HTTP request command.
58
+ #
59
+ # Supports flexible DWIM arity for convenience:
60
+ # <tt>Http.new("url")</tt>:: GET, URL as envelope
61
+ # <tt>Http.new("url", :tag)</tt>:: GET, custom envelope
62
+ # <tt>Http.new(:post, "url")</tt>:: POST, URL as envelope
63
+ # <tt>Http.new(:post, "url", :tag)</tt>:: POST, custom envelope
64
+ # <tt>Http.new(:post, "url", "body", :tag)</tt>:: POST with body
65
+ # <tt>Http.new(get: "url")</tt>:: keyword shortcut
66
+ #
67
+ # [method] HTTP method symbol: <tt>:get</tt>, <tt>:post</tt>,
68
+ # <tt>:put</tt>, <tt>:patch</tt>, or <tt>:delete</tt>.
69
+ # [url] Request URL (String).
70
+ # [envelope] Symbol to tag the response message.
71
+ # [headers] Optional hash of HTTP headers.
72
+ # [body] Optional request body (String).
73
+ # [timeout] Optional timeout in seconds (default 10).
74
+ # [parser] Optional callable to transform response body.
24
75
  def new(*args, method: nil, url: nil, envelope: nil, headers: nil, body: nil, timeout: nil, parser: nil,
25
76
  get: nil, post: nil, put: nil, patch: nil, delete: nil
26
77
  )
@@ -134,6 +185,17 @@ module Rooibos
134
185
  end
135
186
  private_class_method :parse_dwim_args
136
187
 
188
+ # Executes the HTTP request and sends the response.
189
+ #
190
+ # Sends <tt>Message::HttpResponse</tt> with status, body, and headers.
191
+ # On network errors, sends the same message type with <tt>error</tt>
192
+ # populated instead.
193
+ #
194
+ # Note: Ruby's <tt>Net::HTTP</tt> blocks until completion. Cancellation
195
+ # cannot interrupt a request in progress. The grace period is 0.
196
+ #
197
+ # [out] Outlet for sending messages.
198
+ # [token] Cancellation token from the runtime.
137
199
  def call(out, token)
138
200
  return if token.canceled?
139
201
 
@@ -16,24 +16,31 @@ module Rooibos
16
16
  # platform-specific commands.
17
17
  #
18
18
  # This command detects the platform and runs the appropriate opener:
19
- # +open+ on macOS, +xdg-open+ on Linux, +start+ on Windows.
19
+ # <tt>open</tt> on macOS, <tt>xdg-open</tt> on Linux, <tt>start</tt> on Windows.
20
20
  #
21
- # On success (exit 0), sends +Message::Open+.
22
- # On failure (non-zero), sends +Message::Error+.
21
+ # On success (exit 0), sends <tt>Message::Open</tt>.
22
+ # On failure (non-zero), sends <tt>Message::Error</tt>.
23
+ #
24
+ # Prefer the <tt>Command.open</tt> factory method for convenience.
23
25
  #
24
26
  # === Example
25
27
  #
28
+ # # Using the factory method (recommended)
29
+ # Command.open(model.selected_file)
30
+ # Command.open("https://rooibos.run")
31
+ #
32
+ # # Using the class directly
33
+ # Open.new(path: model.selected_file, envelope: model.selected_file)
34
+ #
35
+ # # Pattern-match on the response
26
36
  # def update(msg, model)
27
37
  # case msg
28
- # in :view_clicked
29
- # [model, Command.open(model.selected_file)]
30
38
  # in { type: :open, envelope: path }
31
39
  # model.with(status: "Opened #{path}")
32
40
  # in { type: :error, envelope: path }
33
41
  # model.with(error: "Could not open #{path}")
34
42
  # end
35
43
  # end
36
- #
37
44
  class Open < Data.define(:path, :envelope)
38
45
  include Custom
39
46
 
@@ -20,6 +20,9 @@ module Rooibos
20
20
  #
21
21
  # Use it for delayed actions, debounced inputs, or animation loops.
22
22
  #
23
+ # Prefer the <tt>Command.wait</tt> or <tt>Command.tick</tt> factory
24
+ # methods for convenience. Both are aliases for the same behavior.
25
+ #
23
26
  # === Example: Notification dismissal
24
27
  #
25
28
  # def update(msg, model)
@@ -44,7 +47,7 @@ module Rooibos
44
47
  # [model.with(frame:), Command.tick(0.1, :animate)]
45
48
  # end
46
49
  # end
47
- Wait = Data.define(:seconds, :envelope) do
50
+ class Wait < Data.define(:seconds, :envelope)
48
51
  include Custom
49
52
 
50
53
  # Cooperative cancellation needs no grace period.
@@ -36,9 +36,21 @@ module Rooibos
36
36
  # # No side effect
37
37
  # [model, nil]
38
38
  module Command
39
- # Sentinel value for application termination.
39
+ # Terminates the application.
40
40
  #
41
- # The runtime detects this before dispatching. It breaks the loop immediately.
41
+ # Users press a key or click a button to quit. The update function returns
42
+ # a command, and the runtime executes it. Termination is special: the
43
+ # runtime detects this sentinel before dispatching and breaks the loop.
44
+ #
45
+ # Prefer the <tt>Command.exit</tt> factory method for convenience.
46
+ #
47
+ # === Example
48
+ #
49
+ # # Using the factory method (recommended)
50
+ # [model, Command.exit]
51
+ #
52
+ # # Using the class directly
53
+ # [model, Exit.new]
42
54
  class Exit < Data.define
43
55
  include Custom
44
56
 
@@ -85,14 +97,25 @@ module Rooibos
85
97
  cancellation
86
98
  end
87
99
 
88
- # Sentinel value for command cancellation.
100
+ # Cancels a running command.
101
+ #
102
+ # Long-running commands (WebSocket listeners, database pollers) run until
103
+ # stopped. Stopping them requires signaling from outside the command. The
104
+ # runtime tracks active commands by their object identity and routes cancel
105
+ # requests.
106
+ #
107
+ # This type carries the handle (command object) to cancel. The runtime
108
+ # pattern-matches on <tt>Command::Cancel</tt> and signals the token.
109
+ #
110
+ # Prefer the <tt>Command.cancel</tt> factory method for convenience.
111
+ #
112
+ # === Example
89
113
  #
90
- # Long-running commands (WebSocket listeners, database pollers) run until stopped.
91
- # Stopping them requires signaling from outside the command. The runtime tracks
92
- # active commands by their object identity and routes cancel requests.
114
+ # # Using the factory method (recommended)
115
+ # [model, Command.cancel(model.active_fetch)]
93
116
  #
94
- # This type carries the handle (command object) to cancel. The runtime pattern-matches
95
- # on <tt>Command::Cancel</tt> and signals the token.
117
+ # # Using the class directly
118
+ # [model, Cancel.new(handle: model.active_fetch)]
96
119
  class Cancel < Data.define(:handle)
97
120
  include Custom
98
121
  include Message::Predicates
@@ -133,20 +156,29 @@ module Rooibos
133
156
  #
134
157
  # Use it to run builds, lint files, execute scripts, or invoke any CLI tool.
135
158
  #
159
+ # Prefer the <tt>Command.system</tt> factory method for convenience.
160
+ #
136
161
  # === Batch Mode (default)
137
162
  #
138
163
  # A single message arrives when the command finishes:
139
- # <tt>[tag, {stdout:, stderr:, status:}]</tt>
164
+ # <tt>Message::System::Batch</tt> with <tt>stdout</tt>, <tt>stderr</tt>, <tt>status</tt>.
140
165
  #
141
166
  # === Streaming Mode
142
167
  #
143
- # Messages arrive incrementally:
144
- # - <tt>[tag, :stdout, line]</tt> for each stdout line
145
- # - <tt>[tag, :stderr, line]</tt> for each stderr line
146
- # - <tt>[tag, :complete, {status:}]</tt> when the command finishes
147
- # - <tt>[tag, :error, {message:}]</tt> if the command cannot start
168
+ # <tt>Message::System::Stream</tt> messages arrive incrementally:
169
+ # <tt>stream: :stdout</tt>:: for each stdout chunk
170
+ # <tt>stream: :stderr</tt>:: for each stderr chunk
171
+ # <tt>stream: :complete</tt>:: when the command finishes
172
+ # <tt>stream: :error</tt>:: if the command cannot start
173
+ #
174
+ # === Example
148
175
  #
149
- # The <tt>status</tt> is the integer exit code (0 = success).
176
+ # # Using the factory method (recommended)
177
+ # Command.system("ls -la", :got_files)
178
+ # Command.system("tail -f log.txt", :log, stream: true)
179
+ #
180
+ # # Using the class directly
181
+ # System.new(command: "ls -la", envelope: :got_files, stream: false)
150
182
  class System < Data.define(:command, :envelope, :stream)
151
183
  include Custom
152
184
 
@@ -314,6 +346,16 @@ module Rooibos
314
346
  # adds its routing prefix. Clean separation. No coupling.
315
347
  #
316
348
  # Use it to compose child fragments that return their own commands.
349
+ #
350
+ # Prefer the <tt>Command.map</tt> factory method for convenience.
351
+ #
352
+ # === Example
353
+ #
354
+ # # Using the factory method (recommended)
355
+ # Command.map(child_command) { |msg| [:sidebar, msg] }
356
+ #
357
+ # # Using the class directly
358
+ # Mapped.new(inner_command: child_command, mapper: ->(msg) { [:sidebar, msg] })
317
359
  class Mapped < Data.define(:inner_command, :mapper)
318
360
  include Custom
319
361
 
@@ -8,5 +8,5 @@
8
8
  module Rooibos
9
9
  # The version of this gem.
10
10
  # See https://semver.org/spec/v2.0.0.html
11
- VERSION = "0.6.0"
11
+ VERSION = "0.6.1"
12
12
  end
data/sig/concurrent.rbs CHANGED
@@ -31,6 +31,7 @@ module Concurrent
31
31
  def rejected?: () -> bool
32
32
  def wait: (?Numeric? timeout) -> self
33
33
  def value: () -> T?
34
+ def value!: () -> T
34
35
  def reason: () -> Exception?
35
36
  end
36
37
 
@@ -18,6 +18,10 @@ module Rooibos
18
18
  # Grace period for cooperative cancellation (seconds).
19
19
  # Runtime waits this long before force-killing the thread.
20
20
  def rooibos_cancellation_grace_period: () -> Float
21
+
22
+ # Runtime type checking (from Kernel).
23
+ # Required for DWIM nested detection in All.new.
24
+ def is_a?: (Module | Class module_or_class) -> bool
21
25
  end
22
26
 
23
27
  # Sentinel value for application termination.
@@ -114,9 +118,9 @@ module Rooibos
114
118
  include Custom
115
119
 
116
120
  attr_reader seconds: Float
117
- attr_reader tag: Symbol
121
+ attr_reader envelope: Symbol
118
122
 
119
- def self.new: (seconds: Float, tag: Symbol) -> instance
123
+ def self.new: (seconds: Float, envelope: Symbol) -> instance
120
124
 
121
125
  # Execute the timer with cooperative cancellation.
122
126
  def call: (Outlet out, Concurrent::Cancellation token) -> void
@@ -210,7 +214,7 @@ module Rooibos
210
214
  attr_reader live: Lifecycle
211
215
 
212
216
  # Sends a message to the runtime.
213
- def put: (*Object args) -> void
217
+ def put: (*message args) -> void
214
218
 
215
219
  # Runs a child command synchronously, returning its result.
216
220
  def source: (_Callable command, Concurrent::Cancellation token, ?timeout: Float) -> Object?
@@ -242,17 +246,17 @@ module Rooibos
242
246
  class All
243
247
  include Custom
244
248
 
245
- attr_reader tag: Symbol
246
- attr_reader commands: Array[Custom]
249
+ attr_reader envelope: Symbol
250
+ attr_reader commands: Array[_Command]
247
251
  attr_reader nested: bool
248
252
 
249
- def self.new: (Symbol tag, *Custom | Array[Custom]) -> instance
253
+ def self.new: (Symbol envelope, *_Command | Array[_Command]) -> instance
250
254
 
251
255
  def call: (Outlet outlet, Concurrent::Cancellation token) -> void
252
256
  end
253
257
 
254
258
  # Creates an aggregating parallel command.
255
- def self.all: (Symbol tag, *Custom | Array[Custom]) -> All
259
+ def self.all: (Symbol envelope, *_Command | Array[_Command]) -> All
256
260
 
257
261
  # HTTP response shapes for pattern matching
258
262
  type http_success_shape = { type: :http, envelope: Symbol, status: Integer, body: String, headers: Hash[String, String] }
@@ -4,6 +4,10 @@
4
4
  #++
5
5
 
6
6
  module Rooibos
7
+ # Any value passed through Outlet#put to the runtime.
8
+ # Commands may produce any type; Predicates mixin is optional.
9
+ type message = Object
10
+
7
11
  # Messages sent from commands to update functions.
8
12
  module Message
9
13
  # Fallback predicate mixin.
@@ -127,12 +131,12 @@ module Rooibos
127
131
  include Predicates
128
132
 
129
133
  attr_reader envelope: Symbol
130
- attr_reader results: Array[untyped]
134
+ attr_reader results: Array[message]
131
135
  attr_reader nested: bool
132
136
 
133
137
  def initialize: (
134
138
  envelope: Symbol,
135
- results: Array[untyped],
139
+ results: Array[message],
136
140
  nested: bool
137
141
  ) -> void
138
142
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rooibos
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kerrick Long
@@ -306,6 +306,8 @@ files:
306
306
  - doc/essentials/views.md
307
307
  - doc/getting_started/for_go_developers.md
308
308
  - doc/getting_started/for_python_developers.md
309
+ - doc/getting_started/for_rails_developers.md
310
+ - doc/getting_started/for_ratatui_ruby_developers.md
309
311
  - doc/getting_started/for_react_developers.md
310
312
  - doc/getting_started/index.md
311
313
  - doc/getting_started/install.md