Current section

19 Versions

Jump to

Compare versions

8 files changed
+31 additions
-17 deletions
  @@ -11,6 +11,16 @@ not in lockstep yet; entries note which surface they affect.
11 11
12 12 ## [Unreleased]
13 13
14 + ## [0.5.0] — 2026-05-27
15 +
16 + ### Changed
17 +
18 + - Command replies are now returned in native Elixir shape (atom keys,
19 + structs, atom values), symmetric with `render/1`; `Musubi.Wire.to_wire/1`
20 + moves to the transport egress (#59). Revises #57. Client wire contract
21 + unchanged. **Breaking** (Elixir API): tests asserting wire-shaped replies
22 + from `dispatch_command/3` / `command/4` must switch to native shape.
23 +
14 24 ## [0.4.0] — 2026-05-26
15 25
16 26 ### Changed
  @@ -122,7 +132,8 @@ Initial public release of the Musubi runtime (then `Arbor`):
122 132 - TypeScript client and React adapter that materialize the diff stream
123 133 into immutable snapshots.
124 134
125 - [Unreleased]: https://github.com/fahchen/musubi/compare/v0.4.0...HEAD
135 + [Unreleased]: https://github.com/fahchen/musubi/compare/v0.5.0...HEAD
136 + [0.5.0]: https://github.com/fahchen/musubi/compare/v0.4.0...v0.5.0
126 137 [0.4.0]: https://github.com/fahchen/musubi/compare/v0.3.0...v0.4.0
127 138 [0.3.0]: https://github.com/fahchen/musubi/compare/v0.2.0...v0.3.0
128 139 [0.2.0]: https://github.com/fahchen/musubi/compare/v0.1.0...v0.2.0
  @@ -34,7 +34,7 @@ Add Musubi to your Phoenix application:
34 34 ```elixir
35 35 def deps do
36 36 [
37 - {:musubi, "~> 0.4.0"}
37 + {:musubi, "~> 0.5.0"}
38 38 ]
39 39 end
40 40 ```
  @@ -10,7 +10,7 @@ In the Phoenix app:
10 10 ```elixir
11 11 def deps do
12 12 [
13 - {:musubi, "~> 0.4.0"}
13 + {:musubi, "~> 0.5.0"}
14 14 ]
15 15 end
16 16 ```
  @@ -1,6 +1,6 @@
1 1 {<<"links">>,[{<<"GitHub">>,<<"https://github.com/fahchen/musubi">>}]}.
2 2 {<<"name">>,<<"musubi">>}.
3 - {<<"version">>,<<"0.4.0">>}.
3 + {<<"version">>,<<"0.5.0">>}.
4 4 {<<"description">>,
5 5 <<"Server-authoritative, page-scoped runtime library for Elixir/Phoenix applications.">>}.
6 6 {<<"elixir">>,<<"~> 1.18">>}.
  @@ -43,7 +43,6 @@ defmodule Musubi.Page.Server do
43 43 alias Musubi.Stream
44 44 alias Musubi.Telemetry
45 45 alias Musubi.Upload
46 - alias Musubi.Wire
47 46
48 47 @type transport_opts() :: map()
49 48 @type start_arg() ::
  @@ -666,13 +665,15 @@ defmodule Musubi.Page.Server do
666 665 # Command pipeline + render
667 666 # ---------------------------------------------------------------------------
668 667
669 - # Single client-bound reply seam. The handler reply and any
670 - # `:before_command` halt reply are normalized through `Musubi.Wire` here
671 - # so the client receives the same wire form as rendered state. The raw,
672 - # un-wired reply is what observability sees: handler replies pass through
673 - # `:after_command` hooks; halt replies surface only in the
674 - # `[:musubi, :auth, :deny]` telemetry inside `run_command_pipeline` — so
675 - # user hooks and operators still see the handler's original Elixir term.
668 + # Command replies leave the runtime in native Elixir shape (atom keys,
669 + # structs, atom values) — symmetric with `render/1` output. The wire-form
670 + # transformation (`Musubi.Wire.to_wire/1`) happens at the transport egress
671 + # (`Musubi.Transport.Channel` / `Musubi.Transport.ConnectionChannel`), the
672 + # same boundary that serializes patch envelopes. So `command/4`,
673 + # `command_by_name/4`, and `Musubi.Testing.dispatch_command/3` all expose
674 + # the native reply. Reply-schema validation still runs against the wire
675 + # form: `Musubi.Hooks.ValidateReplySchema` wires internally for validation
676 + # only and leaves the returned reply untouched.
676 677 @spec run_command_with_render(store_id(), atom(), command_payload(), State.t()) ::
677 678 {:ok | :halted, command_reply(), State.t(), PatchEnvelope.t() | nil}
678 679 defp run_command_with_render(store_id, command_name, payload, %State{} = state) do
  @@ -682,10 +683,10 @@ defmodule Musubi.Page.Server do
682 683 case pipeline_status do
683 684 :ok ->
684 685 {next_state, envelope} = render_and_envelope(state)
685 - {:ok, Wire.to_wire(reply), next_state, envelope}
686 + {:ok, reply, next_state, envelope}
686 687
687 688 :halted ->
688 - {:halted, Wire.to_wire(reply), state, nil}
689 + {:halted, reply, state, nil}
689 690 end
690 691 end
Loading more files…