A Clojure library for spec-driven interop with GraalVM Polyglot runtime.
[org.clojars.zharinov/graal-spec-tools "0.1.1"]
Disclaimer: consider it alpha-quality until 1.0.0
(require '[graal-spec-tools.core :as gst])
;; Only for samples below
(def context
(-> (org.graalvm.polyglot.Context/newBuilder
(into-array String ["js"]))
(.build)))
(def bindings (.getBindings context "js"))
(require '[spec-tools.data-spec :as ds])
(def spec
(ds/spec
{:name ::person
:spec {:id integer?
:boss boolean?
(ds/req :name) string?
(ds/opt :description) string?
:aliases [(ds/or {:maps {:alias string?}
:strings string?})]
:orders [{:id int?
:description string?}]
:languages #{keyword?}
:address (ds/maybe
{:street string?
:zip string?})}}))
(def value {:id 42
:boss true
:name "Liisa"
:description "Liisa is a valid boss"
:aliases [{:alias "Lissu"} "Liisu"]
:orders [{:id 1, :description "cola"}
{:id 2, :description "kebab"}]
:languages #{:clj :cljs}
:address {:street "Amurinkatu 2"
:zip "33210"}})
(gst/encode spec value)
;; => #graal-proxy[{:id 42, ...}]
(.putMember bindings "value" (gst/encode spec value))
(= value
(gst/decode spec
(.eval context "js"
"const x = JSON.stringify(global.value, null, 2)
console.log(x)
JSON.parse(x)")))
;; => true
(require '[clojure.spec.alpha :as s])
(require '[spec-tools.spec :as spec])
(def args-spec
(s/cat
:x spec/integer?
:y spec/string?))
(def ret-spec boolean?)
(def fn-spec
(gst/fspec
{:name ::sample-fn
:args args-spec
:ret ret-spec}))
(def context
(-> (org.graalvm.polyglot.Context/newBuilder
(into-array String ["js"]))
(.build)))
(.putMember bindings "fn"
(gst/encode fn-spec
(fn [x y] (= (str x) y))))
(.eval context "js" "fn(42, '42')")
;; => #graal[true]
(let [fn-js "(x, y) => x == y"
fn-graal (.eval context "js" fn-js)
fn-clj (gst/decode fn-spec fn-graal)]
(fn-clj 42 "foo"))
;; => false
(defn set-timeout [callback timeout-ms]
(Thread/sleep timeout-ms)
(callback))
(.putMember bindings "setTimeout"
(gst/encode
(gst/fspec
{:name ::set-timeout
:args (s/cat
:callback (gst/fspec
{:name ::callback})
:timeout-ms (s/or
:zero spec/zero?
:pos spec/pos-int?))})
set-timeout))
(.eval context "js" "setTimeout(() => { console.log('hello') }, 1000)")
;; After 1 second, will print 'hello' somewhere
:args
spec in graal-spec-tools/fdef
will cause "Argument error" exception. Please use predicates defined by spec-tools instead.Copyright © 2019 Sergei Zharinov
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close