djblue / portal

A clojure tool to navigate through your data.

Home Page:https://djblue.github.io/portal/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Feature request: Standalone/Server mode

davidpham87 opened this issue · comments

Hello,

Thanks a lot, portal is a great addition to the Clojure ecosystem.

I wonder if that was possible to create a standalone server mode, and clients could connect to it by sending request to the server. In my mind , you could start a server portal with babashka in a a given port (say 1664), then any client (clj/CLJS) could send edn data to the server through http request. Optimally, a tap register function would be provided so that user just have to provide the port of the server.

This would disentangle portal from the client process and ease the integration with other tools (such as emacs) and shadow-CLJS/hot reloading) and ithe workflow would then resemble to the nrepl/socket repl.

An example of such implementation is the shadow-CLJS inspect server.

Best regards,
David

Hi @davidpham87, thanks for the kind words!

Portal could provide a client API but it would provide less functionality since it wouldn't have access to runtime objects. I added 0d39d47 as an example of what could be done currently with portal. Is this kind of what you were thinking?

Hi @djblue,

Thanks a lot for the swift answer! Yes, this is what I have been thinking about!

As for your comment, I might be using clojure in the wrong way, but I try to code as much as possible with data, and if I need to introspect an object, I try to convert it to a hash-map before I tap it.

In terms of ergonomics, I wish we could have a flag to portal.main such that we could invoke portal standalone this way:

bb -cp `clojure -Spath -M:portal/cli` -m portal.main --standalone --port 1664

(or have the usual shortcut -s and -p).

As for the client, it would be great if this is included directly inside the portal api, so that we could have it on both Clojure and ClojureScript. But as it is now, I can already use it!

I am going to try to incorporate portal with my clomacs configuration :-)

Best regards,
David

@djblue thanks for this, portal keeps surprising me with how easy it is to set up in different environments! This time tap>-ing from Cloudflare workers :) (In the worker I wasn't able to start the server since the runtime doesn't allow what's happening in require-string in the node sever.)

Here's a plain/standalone ClojureScript client if anyone needs one:

(ns cljs-cloudflare.portal
  (:require
    [cognitect.transit :as transit]))

(defn- transit-write
  [value]
  (transit/write
    (transit/writer :json {:transform transit/write-meta})
    value))

(defn send!
  ([value] (send! nil value))
  ([{:keys [encoding port host]
     :or   {encoding :transit
            host     "localhost"
            port     1664}}
    value]
   (-> (js/fetch
         (str "http://" host ":" port)
         (clj->js
           {:method "POST"
            :headers
            {"content-type"
             (case encoding
               :json    "application/json"
               :transit "application/transit+json"
               :edn     "application/edn")}
            :body
            (case encoding
              :json    (js/JSON.stringify value)
              :transit (transit-write value)
              :edn     (pr-str value))}))
       (.then #(js/console.log "send! result" %)))))

@martinklepsch Thanks a lot for the code snippet, we should totally find a way to merge this into the library. @djblue Would you welcome a pull request?

@martinklepsch thanks for the ClojureScript client example!

@davidpham87 I would definitely welcome a pull request! Since you've opened this issues, I've been thinking a lot about how a remote API would enable a bunch of useful workflows. https://github.com/djblue/portal/tree/client-api is what I have done so far but it could use more work.

I'm thinking the clients could live under portal.client.<platform>, for example:

  • portal.client.jvm
  • portal.client.web
  • portal.client.node
  • portal.client.clr
  • portal.client.erlang

I recently added b7cf00b. So I'm hoping in the future, you will be able to pipe all tap>s to a single portal and quickly determine which runtime they came from 👌

@davidpham87 the changes have been merged to master and will be part of the next release. I made the following updates:

Rename client fns from send! to submit

  • Use submit to more closely match portal.api/submit
  • Default to edn for transport as it provides the highest level of serialization fidelity.
  • Include metadata when printing edn
  • Default to tagged literals when reading edn

Thanks again for this awesome contribution!