Commit d4923553 authored by Ivar Refsdal's avatar Ivar Refsdal

Lacinia generated pull for Datomic POC

parents
/target
/classes
/checkouts
pom.xml
pom.xml.asc
*.jar
*.class
/.lein-*
/.nrepl-port
.hgignore
.hg/
*.iml
.idea/
\ No newline at end of file
This diff is collapsed.
# lacinia-datomic-pull
A Clojure library designed to ... well, that part is up to you.
## Usage
FIXME
## License
Copyright © 2018 FIXME
Distributed under the Eclipse Public License either version 1.0 or (at
your option) any later version.
(defproject lacinia-datomic-pull "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.9.0"]
[com.walmartlabs/lacinia "0.30.0"]
[com.datomic/datomic-pro "0.9.5703"]
[dato-schema "0.1.3"]
[walmartlabs/datascope "0.1.1"]])
{:enums {:mood
{:values [:good :bad]}}
:objects
{:human {:fields {:id {:type String}
:name {:type String}
:age {:type Int}
:mood {:type :mood}
:moods {:type (list :mood)}
:liste {:type (list String)}
:address {:type :address}
:visited_countries {:type (list :country)}}}
:address {:fields {:street {:type String}
:city {:type String}
:country {:type :country}}}
:country {:fields {:id {:type String}
:name {:type String}}}}
:queries {:human {:type (non-null :human)
:args {:id {:type ID}}
:resolve :human}}}
(ns lacinia-datomic-pull.core
(:require [clojure.edn :as edn]
[com.walmartlabs.lacinia :refer [execute]]
[com.walmartlabs.lacinia.util :refer [attach-resolvers]]
[com.walmartlabs.lacinia.schema :as schema]
[com.walmartlabs.datascope :as ds]
[lacinia-datomic-pull.pattern :as pattern]
[lacinia-datomic-pull.lift-enums :as enums]
[datomic.api :as d]
[clojure.pprint :refer [pprint]]
[dato-schema.core]
[clojure.java.io :as io])
(:import (java.util UUID)))
(defn create-empty-in-memory-db []
(let [uri "datomic:mem://woof"]
(d/delete-database uri)
(d/create-database uri)
(let [conn (d/connect uri)]
conn)))
(def conn (create-empty-in-memory-db))
(def schema
#d/schema[[:human/id :one :uuid :unique]
[:human/name :one :string]
[:human/age :one :long]
[:human/address :one :ref :component]
[:human/mood :one :ref]
[:human/moods :many :ref]
[:human/liste :many :ref]
[:human/visited_countries :many :ref]
[:mood/good :enum]
[:mood/bad :enum]
[:address/street :one :string]
[:address/city :one :string]
[:address/country :one :ref]
[:country/id :one :string :unique]
[:country/name :one :string]])
@(d/transact conn schema)
(def human-id #uuid"5bbb36ea-4e3a-4e21-a7d6-bed3450a5d34")
@(d/transact conn [{:db/id "NO"
:country/id "no"
:country/name "Noreg"}
{:db/id "SE"
:country/id "SE"
:country/name "Sverige"}
{:human/id human-id
:human/name "Ola"
:human/age 40
:human/mood :mood/good
:human/moods #{:mood/good :mood/bad}
:human/visited_countries #{"NO" "SE"}
:human/address {:address/street "Asdf"
:address/city "Bergen"
:address/country "NO"}}])
(defn get-human [context arguments value]
(let [pattern (pattern/context->pull-pattern context)
ent (d/pull (d/db conn)
pattern
[:human/id (UUID/fromString (:id arguments))])]
(println "pull pattern is:")
(pprint pattern)
(enums/lift-enums context ent)))
(def star-wars-schema
(-> "schema.edn"
io/resource
slurp
edn/read-string
(attach-resolvers {:human get-human})
schema/compile))
(pprint (execute star-wars-schema
"query { human(id: \"5bbb36ea-4e3a-4e21-a7d6-bed3450a5d34\") {
id
name
mood
moods
visited_countries {
name
}
address {
street
city
country {
id
name
}
}
}}"
nil nil))
\ No newline at end of file
(ns lacinia-datomic-pull.lift-enums
(:require [lacinia-datomic-pull.pattern :refer [enum?]]))
(defn selections->enum-paths [schema selections & [path]]
(let [path (or path [])]
(reduce (fn [o {:keys [leaf? field selections] :as selection}]
(let [newpath (conj path field)]
(cond (enum? schema selection) (conj o newpath)
leaf? o
:else (into o (selections->enum-paths schema selections newpath)))))
[]
selections)))
(defn set-path [m paths cb]
(let [path (first paths)
v (get m path ::none)]
(cond (= ::none v)
m
(= 1 (count paths))
(assoc m path (if (vector? v)
(mapv cb v)
(cb v)))
(vector? v)
(assoc m path (mapv #(set-path % (rest paths) cb) v))
:else (assoc m path (set-path v (rest paths) cb)))))
(defn lift-enums
[context ent]
(reduce (fn [o path] (set-path o path (fn [x] (keyword (name (:db/ident x))))))
ent
(selections->enum-paths (:com.walmartlabs.lacinia.constants/schema context)
(:selections (:com.walmartlabs.lacinia/selection context)))))
(ns lacinia-datomic-pull.pattern)
(defn field-def->inner-type [fdef]
(let [typ (get fdef :type)]
(cond (keyword? typ) typ
(nil? typ) (throw (ex-info "Could not get final type" {:fdef fdef}))
:else (field-def->inner-type typ))))
(defn enum? [schema {:keys [field-definition] :as selection}]
(and (:leaf? selection)
(= :enum (:category (get schema (field-def->inner-type field-definition))))))
(defn list-selection? [schema selection]
(= :list (->> selection :field-definition :type :kind)))
(defn selection->pull [schema type {:keys [leaf? field selections field-definition] :as selection}]
(let [fqn (keyword (name type) (name field))
list-default (when (list-selection? schema selection) [:default []])]
(cond (enum? schema selection) {(into [fqn :as field] list-default) [:db/ident]}
leaf? (into [fqn :as field] list-default)
:else {(into [fqn :as field] list-default) (mapv #(selection->pull schema (field-def->inner-type field-definition) %) selections)})))
(defn context->pull-pattern
[context]
(let [schema (:com.walmartlabs.lacinia.constants/schema context)
selections (:selections (:com.walmartlabs.lacinia/selection context))
root-type (field-def->inner-type (->> context
:com.walmartlabs.lacinia.constants/parsed-query
:selections
first
:field-definition))]
(mapv (partial selection->pull schema root-type) selections)))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment