I asked about the API before and I got an function which I can use to send my code to runtime from my own code,
(shadow.cljs.devtools.api/repl :build-id)
It was based on Socket REPL. Actually I'm a little confused about the history about Socket REPL and nREPL. But I know that Socket REPL returns me only strings and nREPL returns me data in a structure.
So actually nREPL is the useful one I think. Now I want to send my code with nREPL. Is there any API I can use too?
Besides there was an option in my template shadow-cljs.edn which I think should pick me a random port, not sure if it's still working today...
:socket-repl {:port 0}
but it's obviously sure that nREPL is running when I start the watch server..
shadow-cljs - nREPL server started on port 54004
Are the roles of Socket REPL and nREPL just different in the case of shadow-cljs?
nREPL provides a way to eval code remotely among other things. That is pretty much the only thing it has in common with the Socket REPL. nREPL uses a completely different protocol so it can't really be compared with the Socket REPL. It is much more complex. I can't explain nREPL easily since I barely understand it myself.
See https://github.com/nrepl/nrepl
:socket-repl is only used to configure the Socket REPL, :nrepl configures nREPL. They are independent and don't affect each other.
Thanks.. but is there an API like this for nREPL?
(shadow.cljs.devtools.api/repl :build-id)
The shadow-cljs API doesn't change and remains exactly the same.
(shadow.cljs.devtools.api/repl :build-id)
So there might be something wrong... I have a shadow-cljs instance running:
=>> yarn watch
yarn run v1.13.0
$ shadow-cljs watch client
shadow-cljs - config: /Users/chen/repo/erigeron/composer-todolist/shadow-cljs.edn cli version: 2.8.12 node: v11.6.0
shadow-cljs - updating dependencies
shadow-cljs - dependencies updated
[2019-03-03 12:23:58.917 - WARNING] TCP Port 9630 in use.
[2019-03-03 12:24:01.584 - WARNING] TCP Port 7000 in use.
shadow-cljs - HTTP server available at http://localhost:7001
shadow-cljs - server version: 2.8.12 running at http://localhost:9631
shadow-cljs - nREPL server started on port 49259
shadow-cljs - watching build :client
[:client] Configuring build.
[:client] Compiling ...
[:client] Build completed. (199 files, 27 compiled, 0 warnings, 7.52s)
And I got a nrepl-client running:
client = require('nrepl-client').connect port: 49259
client
.once 'connect', () ->
expr = '(shadow.cljs.devtools.api/repl :client)';
client.eval expr, (err, result) ->
console.log '%s => ', expr, err or result
# client.end()
setTimeout ->
client.eval '(println (range 100))', (err, result) ->
console.log 'result', err, result
client.eval '(exists? js/window)', (err, result) ->
console.log 'result', err, result
, 1000
And it prints:
=>> coffee client.coffee
(shadow.cljs.devtools.api/repl :client) => [ { id: 'D27994C7-657B-451F-BE73-142F055B1AF8',
out: 'To quit, type: :cljs/quit\n',
session: '155cb6f5-d95b-464f-b9f2-97ab112f2558' },
{ id: 'D27994C7-657B-451F-BE73-142F055B1AF8',
ns: 'cljs.user',
session: '155cb6f5-d95b-464f-b9f2-97ab112f2558',
value: '[:selected :client]' },
{ id: 'D27994C7-657B-451F-BE73-142F055B1AF8',
session: '155cb6f5-d95b-464f-b9f2-97ab112f2558',
status: [ 'done' ] } ]
result null [ { err:
'Syntax error compiling at (REPL:1:1).\nUnable to resolve symbol: exists? in this context\n',
id: '8914D014-2566-462F-AAF6-7C97EEFD024A',
session: 'eaf13e73-4993-48bc-a1bf-b54e1efd3a95' },
{ ex: 'class clojure.lang.Compiler$CompilerException',
id: '8914D014-2566-462F-AAF6-7C97EEFD024A',
'root-ex': 'class clojure.lang.Compiler$CompilerException',
session: 'eaf13e73-4993-48bc-a1bf-b54e1efd3a95',
status: [ 'eval-error' ] } ]
result null [ { err:
'Syntax error compiling at (REPL:1:1).\nUnable to resolve symbol: exists? in this context\n',
id: '8914D014-2566-462F-AAF6-7C97EEFD024A',
session: 'eaf13e73-4993-48bc-a1bf-b54e1efd3a95' },
{ ex: 'class clojure.lang.Compiler$CompilerException',
id: '8914D014-2566-462F-AAF6-7C97EEFD024A',
'root-ex': 'class clojure.lang.Compiler$CompilerException',
session: 'eaf13e73-4993-48bc-a1bf-b54e1efd3a95',
status: [ 'eval-error' ] },
{ id: '8914D014-2566-462F-AAF6-7C97EEFD024A',
session: 'eaf13e73-4993-48bc-a1bf-b54e1efd3a95',
status: [ 'done' ] } ]
result null [ { id: '8A3B2892-6845-4CA4-8CFC-2EC6421B3AB2',
out:
'(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99)\n',
session: 'fdfa1917-86cb-4168-a485-4f74910231f6' },
{ id: '8A3B2892-6845-4CA4-8CFC-2EC6421B3AB2',
ns: 'shadow.user',
session: 'fdfa1917-86cb-4168-a485-4f74910231f6',
value: 'nil' },
{ id: '8A3B2892-6845-4CA4-8CFC-2EC6421B3AB2',
session: 'fdfa1917-86cb-4168-a485-4f74910231f6',
status: [ 'done' ] } ]
So the code I sent via nREPL is not running in the context of the webpage I was debugging. I must have misunderstood your APIs.
You misunderstood nREPL.
I don't know the exact client API but you are supposed to create a session (maybe via :clone?) and re-use that session for the following commands. Note how your example uses a couple different session ids? There should only be one, or maybe 2 in the beginning. Once you call (shadow.cljs.devtools.api/repl :foo) that session will be switched to CLJS and only that session. So if the client just creates a new session it will be in CLJ mode again and can't eval CLJS.
Turned out there are several steps required before I can call that API. The step involved:
nrepl-client module.client.clone (err, result) -> to create a new session. also client.lsSessions (err, result) -> is the API to list sessions. Turned out the session used by API could be a temporary one. So we need to create one by ourselves.(shadow.cljs.devtools.api/repl :foo) in the created session with a namespace cljs.user.app.main in my code...Details of APIs in node-nrepl-client could be found on its README.