fix(client): read a duplex channel's directions from the operations that speak them - #108
Open
juicycleff wants to merge 5 commits into
Open
juicycleff wants to merge 5 commits into
juicycleff wants to merge 5 commits into
Conversation
…hat speak them Both AsyncAPI readers stamped every message on a channel with each operation's action and took the last-sorted payload for the direction's schema. On forge's own live-query channel, where the receive operation sorts first, that named the send direction nothing, named receive by its key, and put the send payload in the receive schema. The URL reader also appended one endpoint per operation, so a duplex channel reached through a URL source never carried both schemas and never became a duplex binding. One fold now serves both readers: an operation contributes only the messages it references (all of them when it lists none), the first message per direction claims that direction's schema, and the messages metadata is keyed by message name so the generated binding says `send: 'SendMessage'`.
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
Conventional Commits ValidationPR Title: valid |
…hannel `cache.live` is typed as the structural LiveBinding, and 1.11.0 declared it without `raw`, so an application's stream helper had to cast to the binder class to reach the one method the duplex work added. The interface now carries `raw` with the same signature as StreamBinder.raw; the type import is erased, so the REST-only bundle does not grow.
Contributor
Conventional Commits ValidationPR Title: valid |
Contributor
Conventional Commits ValidationPR Title: valid |
Contributor
Conventional Commits ValidationPR Title: valid |
…hannel An operation that lists `messages` and resolves none of them to the channel fell back to speaking every message the channel declares, and then both operations did, and the fold labelled each name with whichever action came last. That is the empty send direction this PR exists to remove, arriving by a different road and without a word of warning. AsyncAPI 3 says those refs point at the channel's own messages and forge's router writes them that way, but other generators write #/components/messages/send and leave the channel to carry the definition. The trailing segment of the ref is the channel's key there, so try it when the strict read comes back with nothing. It has to be a key the channel actually declares, so this can only narrow the fallback, never invent a message. When the fallback still engages for an operation that did list refs, the spec now carries a warning naming the operation and the channel. applyOperationMessages takes the spec and the operation id to do it, which both readers already had in hand. And a name claimed by one direction is no longer relabelled by the other, so two operations that legitimately speak the whole channel stop taking the names back from each other and the result no longer depends on operation-id sort order.
…raw takes The interface typed the handler as (message: unknown) => void while the class takes a FrameHandler, which is (message, channel). Method bivariance means the narrow spelling compiles and the runtime is unaffected: the channel arrives either way. The caller is what breaks. Anyone reaching the socket through cache.live, which is the reason this interface exists at all, receives the channel a frame came on and cannot see it in the type, so on a socket multiplexing more than one channel they either cast or guess.
Contributor
Conventional Commits ValidationPR Title: valid |
…ment The second resolution pass took the last path segment of any operation message reference as a key on this channel. A reference into another channel's messages shares the key vocabulary, so it bound a direction to the wrong message with no warning. The pass now applies to #/components/messages/ references only; anything else that resolves nothing takes the whole-channel fallback and its warning.
Contributor
Conventional Commits ValidationPR Title: valid |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #107, two gaps the first real duplex channel exposed.
The generator named forge's own live-query socket as
send: '',receive: 'receive', and the two payload schemas were swapped. Both AsyncAPI readers did the same thing: for each operation they walked every message on the channel, stamped it with that operation's action, and let the last-sorted payload win the direction's schema. With the receive operation sorting first, the send direction was never named and the receive schema held the send payload. The URL reader also appended one endpoint per operation, so through a URL source neither half ever carried both schemas and the channel never became a duplex binding at all.One fold now serves both readers. An operation contributes only the messages it references, or all of them when it lists none, which is what every older document relied on. The first message per direction claims that direction's schema. The messages metadata is keyed by message name, so you get
send: 'SendMessage'in the generated table instead of an empty string. Tests drive the fix through both entry points,ParseFileandextractFromAsyncAPI, with the live-query document as forge's router emits it. Against the real twinos document the generated entry is now:One visible consequence for URL sources: a channel with several operations used to produce one endpoint per operation, each named after its operation id. It now produces one endpoint, named after the first operation id in sorted order (
query.live.wsReceivefor the live-query channel). That is what the file reader always did, so the two readers now agree, but if you generated a client from a URL and relied on the per-operation names for a multi-operation channel, the identifier changes.The second gap is in client-core.
cache.liveis typed as the structuralLiveBinding, and 1.11.0 declared it withoutraw, so an application's stream helper had to cast toStreamBinderto reach the one method the duplex work added. The interface now carriesraw. The type import is erased, so the REST-only bundle does not grow; the size budgets are unchanged.