homebaseio / datalog-console

Administration UI for Datascript, Datahike, and other Datalog databases
https://homebaseio.github.io/datalog-console/
MIT License
55 stars 8 forks source link

Upload to NPM? #29

Open lidorcg opened 2 years ago

lidorcg commented 2 years ago

I would like to use this tool from js (without homebase) but I can't seem to find it on npm. Is there an easy way of integration from js (without homebase) that I'm missing?

becomingbabyman commented 2 years ago

We're working on it. At the moment the datalog-console is designed to be used in the chrome extension almost exclusively. You can also grab it off clojars if you're using Clojurescript, but we haven't exposed all the requisite APIs to make it work outside of the chrome extension.

Are you just trying to connect it to a datascript DB?

lidorcg commented 2 years ago

yeah, from the js api. That is, I'm not going through cljs atm so it would be a serious hustle to integrate it using cljs, that is why I looked for a js integration.

I'm planning to use it with chrome so that's a non-issue. The only issue is that I can't call:

(datalog-console/enable! {:conn conn})

from js (so far as I know...)

lidorcg commented 2 years ago

So I was able to make it work but... img

  1. First I needed to compile it to esm (because I work with vite which uses esm for dev) so I added this to shadow-cljs.edn:

    :npm {:target :esm
      :output-dir "dist/js"
      :modules {:datalog-console {:exports {enable datalog-console.integrations.datascript/enable-js}}}}
  2. Then I found that for some reason (I still haven't discovered why) conn that was created through datascript's js interop wasn't passed to datalog-console as legit conn but as some weird object (although in datascript it seems that it is passed as a normal conn, all the methods there depends on it). Anyway I ended up passing a function that serializes the conn:

    // from js
    enable(() => datascript.serializable(datascript.db(conn)));
  3. And I needed to deserialize it on the cljs end, I also discovered that datalog-console doesn't work well with string keys in the schema and attributes so I had to override the from-serializable functions (:thaw-fn and :thaw-kw) to make up for that:

    
    (ns datalog-console.integrations.datascript
    (:require [goog.object :as gobj]
            [cljs.reader]
            [datascript.core :as d]
            [datalog-console.lib.version :as dc]
            [datascript.serialize :as ds]))

(defn- thaw-fn [s] (-> (cljs.reader/read-string s) (clj->js) (js->clj :keywordize-keys true)))

(defn get-db [conn-fn] (-> (conn-fn) (ds/from-serializable {:thaw-fn thaw-fn :thaw-kw keyword})))

(defn transact-from-devtool! [conn transact-str] (try (d/transact conn (cljs.reader/read-string transact-str)) {:datalog-console.client.response/transact! :success} (catch js/Error e {:error (goog.object/get e "message")})))

(defn enable! "Takes a datascript database connection atom. Adds message handlers for a remote datalog-console process to communicate with. E.g. the datalog-console browser extension." [{:keys [conn]}] (try (js/document.documentElement.setAttribute "datalog-console-remote-installed" true) (.addEventListener js/window "message" (fn [event] (when-let [devtool-message (gobj/getValueByKeys event "data" ":datalog-console.client/devtool-message")] (let [msg-type (:type (cljs.reader/read-string devtool-message))] (case msg-type

                           :datalog-console.client/request-whole-database-as-string
                           (.postMessage js/window #js {":datalog-console.remote/remote-message" (pr-str (get-db conn))} "*")

                           :datalog-console.client/transact!
                           (let [transact-result (transact-from-devtool! conn (:data (cljs.reader/read-string devtool-message)))]
                             (.postMessage js/window #js {":datalog-console.remote/remote-message" (pr-str transact-result)} "*"))

                           :datalog-console.client/request-integration-version
                           (.postMessage js/window #js {":datalog-console.remote/remote-message" (pr-str {:version dc/version})})
                           nil)))))
(catch js/Error _e nil)))

(defn ^:export enable-js [conn] (enable! {:conn conn}))



And finally I could go to the chrome extension and load my db :)!
Hopes it will help other people.