shadow-cljs
shadow-cljs copied to clipboard
Expose shadow-remote endpoint over nREPL
Most editors have a working nREPL implementation so it makes sense to tunnel shadow-remote over nREPL. As of 2.17.3
there are 3 new related nREPL ops to get full access to shadow-remote. If editors aren't interested in these they can just be ignored, all existing operations are unaffected.
The intent is that an editor that is interested sends a message once to initiate a "connection". The init message must contain a :data-type
with either edn
or transit
. Depending on what is chosen there all following shadow-remote-msg
messages are expected to have a :data
string value encoded in the chosen type.
{:op "shadow-remote-init" :data-type "edn"}
;; or
{:op "shadow-remote-init" :data-type "transit"}
After the init the "connection" is open and the editor will start receiving messages from the shadow-remote relay. The editor may also send further messages by wrapping the actual message in a nREPL envelope.
;; messages from either the editor or the relay
{:op "shadow-remote-msg" :data "encoded string"}
Further details on shadow-remote can be found in this post. If any editor implementors have any interest in this I'll expand that document to include all currently available messages and their use. As of now it powers everything in the shadow-cljs UI as well as any existing REPL implementation. So even nREPL eval
is already using it under the hood, just not exposed in fine detail.
Please reach out if you attempt to work on this on the editor side. Happy to help out with protocol questions.
A note on nREPL session management. The editor may clone a new session for this but all shadow-remote
related messages must then use that session. If a shadow-remote-msg
is received before shadow-remote-init
it'll be rejected and just send an :err
. I also don't know how any existing nREPL middleware may interfere with this.