Skip to content

Commit

Permalink
Merge branch 'feature/clojure-sdk' into feature/strings-api
Browse files Browse the repository at this point in the history
  • Loading branch information
cap10morgan committed Apr 20, 2023
2 parents 2418301 + f0d42bb commit 3e11f79
Show file tree
Hide file tree
Showing 8 changed files with 866 additions and 254 deletions.
1 change: 1 addition & 0 deletions src/fluree/db/db/json_ld.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@
(-iri [this subject-id compact-fn] (iri this subject-id compact-fn))
(-search [this fparts] (query-range/search this fparts))
(-query [this query-map] (fql/query this query-map))
(-query [this query-map opts] (fql/query this query-map opts))
(-stage [db json-ld] (jld-transact/stage db json-ld nil))
(-stage [db json-ld opts] (jld-transact/stage db json-ld opts))
(-index-update [db commit-index] (index-update db commit-index))
Expand Down
2 changes: 1 addition & 1 deletion src/fluree/db/json_ld/api.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
- defaults:
- did - (optional) DiD information to use, if storing blocks as verifiable credentials,
or issuing queries against a permissioned database.
- context - (optional) Default @context map to use for ledgers formed with this connection."
- @context - (optional) Default @context map to use for ledgers formed with this connection."
[{:strs [method parallelism] :as opts}]
;; TODO - do some validation
(promise-wrap
Expand Down
308 changes: 153 additions & 155 deletions src/fluree/db/json_ld/transact.cljc

Large diffs are not rendered by default.

49 changes: 42 additions & 7 deletions src/fluree/db/query/fql/syntax.cljc
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
(ns fluree.db.query.fql.syntax
(:require [clojure.string :as str]
[clojure.walk :as walk]
[fluree.db.util.core :as util :refer [pred-ident?]]
[fluree.db.util.log :as log]
[fluree.db.constants :as const]
[fluree.json-ld :as json-ld]
[malli.core :as m]
[fluree.db.util.validation :as v]
[malli.transform :as mt]))
Expand Down Expand Up @@ -63,14 +65,38 @@
(defn encode-query-key
[k]
(if (string? k)
(do
(log/debug "encoding query key:" k)
(let [kebab-k (->kebab-case k)]
(if (str/starts-with? kebab-k "@")
(-> kebab-k (subs 1) keyword)
(keyword kebab-k))))
(let [kebab-k (->kebab-case k)]
(if (str/starts-with? kebab-k "@")
(-> kebab-k (subs 1) keyword)
(keyword kebab-k)))
k))

(defn decode-query
[q]
(log/debug "decoding query:" q)
;; TODO: Replace this with a :map-with schema once this lands upstream:
;; https://github.com/metosin/malli/issues/881
(walk/postwalk
(fn [v]
(cond
(qualified-keyword? v) (str (namespace v) ":" (name v))
(= v :context) "@context"
(keyword? v) (name v)
:else v))
q))

(defn analytical-query-results-transformer
[context]
;; TODO: Replace this with a :map-with schema once this lands upstream:
;; https://github.com/metosin/malli/issues/881
(let [kw-context (util/keywordize-keys context)]
(mt/transformer
{:encoders
{:string (fn [s]
(if-let [expanded (json-ld/expand-iri s context)]
(json-ld/compact expanded kw-context)
s))}})))

(def registry
(merge
(m/predicate-schemas)
Expand Down Expand Up @@ -199,7 +225,7 @@
["where" ::where]
["values" {:optional true} ::values]]
::context ::v/context
::analytical-query [:map
::analytical-query [:map {:decode/fluree decode-query}
["where" ::where]
["t" {:optional true} ::t]
["@context" {:optional true} ::context]
Expand Down Expand Up @@ -247,6 +273,15 @@
(m/encoder ::query {:registry registry}
(mt/key-transformer {:encode encode-query-key})))

(def coerce-analytical-query
(m/coercer ::analytical-query v/fluree-transformer {:registry registry}))

(defn analytical-query-results-encoder
[context]
(m/encoder ::analytical-query-results
{:registry registry}
(analytical-query-results-transformer context)))

(def valid-query?
(m/validator ::query {:registry registry}))

Expand Down
70 changes: 58 additions & 12 deletions src/fluree/db/util/validation.cljc
Original file line number Diff line number Diff line change
@@ -1,18 +1,64 @@
(ns fluree.db.util.validation
(:require [malli.core :as m]))
(:require [malli.core :as m]
[malli.transform :as mt]))

(def value? (complement coll?))

(defn decode-iri
[v]
(cond
(qualified-keyword? v) (str (namespace v) ":" (name v))
(keyword? v) (name v)
:else v))

(def registry
(merge
(m/base-schemas)
(m/type-schemas)
(m/comparator-schemas)
(m/predicate-schemas)
{::iri :string
::val [:fn value?]
::context [:orn
[:sequence [:sequential [:orn
[:string :string]
[:map map?]]]]
[:map map?]]}))
(m/base-schemas)
(m/type-schemas)
(m/comparator-schemas)
(m/predicate-schemas)
{::iri [:string {:decode/fluree decode-iri}]
::val [:fn value?]
::string-key [:string {:decode/fluree name
:encode/fluree keyword}]
::context-map [:map-of ::iri ::iri]
::context [:orn
[:sequence [:sequential [:orn
[:string :string]
[:map ::context-map]]]]
[:map ::context-map]]
::context-key [:= {:decode/fluree #(if (= % :context)
"@context" %)}
"@context"]
::did [:orn
[:id :string]
[:map [:and
[:map-of ::string-key :any]
[:map
["id" :string]
["public" :string]
["private" :string]]]]]
::connect-defaults [:map
[:did {:optional true} ::did]
[::m/default [:map-of {:max 1} ::context-key ::context]]]
::connect-opts [:and
[:map-of ::string-key :any]
[:map
["method" {:decode/fluree name} :string]
["defaults" {:optional true} ::connect-defaults]]]
::create-opts [:maybe
[:and
[:map-of ::string-key :any]
[:map
["defaults" {:optional true}
[:map-of {:max 1} ::context-key ::context]]]]]
::create-response [:map-of ::string-key :any]}))

(def fluree-transformer
(mt/transformer {:name :fluree}))

(def coerce-connect-opts
(m/coercer ::connect-opts fluree-transformer {:registry registry}))

(def coerce-create-opts
(m/coercer ::create-opts fluree-transformer {:registry registry}))
102 changes: 102 additions & 0 deletions src/fluree/sdk/clojure.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
(ns fluree.sdk.clojure
(:require [fluree.db.json-ld.api :as api]
[fluree.db.json-ld.transact :as ftx]
[fluree.db.util.log :as log]
[fluree.db.util.validation :as v]
[fluree.db.query.fql.syntax :as fql]
[fluree.db.query.fql.parse :as fqp]
[fluree.json-ld :as json-ld])
(:refer-clojure :exclude [load]))

(defn connect
"Forms connection to ledger, enabling automatic pulls of new updates, event
services, index service.
Multiple connections to same endpoint will share underlying network connection.
Options include:
- :defaults - (optional) with any of the following values:
- :did - (optional) DiD information to use, if storing blocks as verifiable
credentials, or issuing queries against a permissioned database.
- :context - (optional) Default @context map to use for ledgers formed with
this connection."
[opts]
(let [opts* (v/coerce-connect-opts opts)]
(log/debug "connect opts:" opts*)
(api/connect opts*)))

(defn create
"Creates a new json-ld ledger. A connection (conn) must always be supplied.
Ledger-alias (optional) is a friendly name that is used for:
- When publishing to a naming service that allows multiple pointers for the
same namespace (e.g. IPNS), this becomes a sub-directory off the namespace.
For multiple directories deep, use '/' for a
e.g. the ledgers movies/popular, books/authors, books/best-sellers could
use the same IPNS id (in this example using IPNS DNSLink):
fluree:ipns://my.dns.com/books/authors
fluree:ipns://my.dns.com/books/best-sellers
fluree:ipns://my.dns.com/movies/top-rated
- When combining multiple ledgers, each ledger becomes an individual named
graph which can be referenced by name.
Options map (opts) can include:
- :defaults
- :did - DiD information to use, if storing blocks as verifiable credentials
- :context - Default @context map to use for ledgers formed with this connection"
([conn] (create conn nil nil))
([conn ledger-alias] (create conn ledger-alias nil))
([conn ledger-alias opts]
(let [opts* (v/coerce-create-opts opts)]
(api/create conn ledger-alias opts*))))

(defn load
"Loads an existing ledger by its alias (which will be converted to a
connection-specific address first)."
[conn ledger-alias]
(api/load conn ledger-alias))

(defn exists?
"Returns a promise with true if the ledger alias or address exists, false
otherwise."
[conn ledger-alias-or-address]
(api/exists? conn ledger-alias-or-address))

(defn stage
"Performs a transaction and queues change if valid (does not commit)"
([db json-ld] (stage db json-ld nil))
([db json-ld opts]
(let [json-ld* (ftx/coerce-txn json-ld)]
(api/stage db json-ld* opts))))

(defn commit!
([ledger db] (commit! ledger db nil))
([ledger db opts] (api/commit! ledger db opts)))

(defn db
"Retrieves latest db, or optionally a db at a moment in time
and/or permissioned to a specific identity."
([ledger] (db ledger nil))
([ledger opts] (api/db ledger opts)))

(defn query
[db query]
(let [context (json-ld/parse-context (fqp/parse-context query db))
results-encoder (fql/analytical-query-results-encoder context)]
(future
(->> query
fql/coerce-analytical-query
(api/query db)
deref
(log/debug->>val "pre-encoded query results:")
results-encoder))))

(comment
;; TODO: Finish these
(defn multi-query
[db query]
(api/multi-query db query))

(defn history
[ledger query]
(api/history ledger query)))
Loading

0 comments on commit 3e11f79

Please sign in to comment.