-
Notifications
You must be signed in to change notification settings - Fork 1
/
core.clj
157 lines (129 loc) · 7.39 KB
/
core.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
(ns stillsuit.core
"Main public API for stillsuit.
For more details, see the [user manual](http://docs.workframe.com/stillsuit/current/manual/).
Note that this namespace constitutes the entirety of the public API; all the other
namespaces in stillsuit can be considered to be implementation details and may change
over time."
(:require [stillsuit.lacinia.queries :as sq]
[stillsuit.lacinia.scalars :as ss]
[stillsuit.lacinia.resolvers :as sr]
[stillsuit.lacinia.enums :as se]
[stillsuit.lib.util :as slu]
[datomic.api :as d]
[com.walmartlabs.lacinia :as lacinia]
[com.walmartlabs.lacinia.schema :as schema]
[clojure.tools.logging :as log]
[com.walmartlabs.lacinia.util :as util]))
(defn- datomic-connect
[db-uri]
(if-not db-uri
(log/error "No datomic URL defined in config or schema!")
(let [conn (d/connect db-uri)]
(log/infof "Connecting to datomic at %s..." db-uri)
conn)))
(defn- make-app-context
"Return an app-context map suitable for handing to (lacinia/execute-query)."
[base-context schema connection enum-map entity-filters config]
(let [context-conn (or connection (datomic-connect (or (:catchpocket/datomic-uri config)
(:stillsuit/datomic-uri schema))))]
(merge {:stillsuit/connection context-conn
:stillsuit/enum-map enum-map
:stillsuit/config config
:stillsuit/entity-filters entity-filters}
base-context)))
(defn- decorate-resolver-map
[resolver-map config]
(merge resolver-map
(sr/resolver-map config)
(sq/resolver-map config)))
(def ^:private base-schema
(delay (slu/load-edn-resource "stillsuit/base-schema.edn")))
(def ^:private default-config-schema
(delay (slu/load-edn-resource "stillsuit/config-defaults.edn")))
(defn datomic-enum
"Given a stillsuit-decorated app context and a keyword representing a lacinia enum which has
been described in the stillsuit config, return the keyword corresponding to the datomic value
for that keyword.
Parameters:
- `app-context`: the lacinia application context (first argument to a resolver function)
- `lacinia-type`: the keyword corresponding to a lacinia `:enum` definition
- `lacinia-enum-keyword`: a keyword representing the value we're trying to convert to
its datomic equivalent
For more information, see [the user manual](http://docs.workframe.com/stillsuit/current/manual/#_stillsuit_enums)."
[app-context lacinia-type lacinia-enum-keyword]
(let [value (get-in app-context [:stillsuit/enum-map lacinia-type :stillsuit/lacinia-to-datomic lacinia-enum-keyword])]
(when (nil? value)
(log/infof "Unable to find datomic enum equivalent for lacinia enum value %s!" lacinia-enum-keyword))
value))
(defn connection
"Given a stillsuit-decorated app context, return the datomic connection object that was associated with the
context at the time `(stillsuit/decorate)` was called.
Parameters:
- `app-context`: the lacinia application context (first argument to a resolver function)
For more information, see [the user manual](http://docs.workframe.com/stillsuit/current/manual/#_stillsuit_enums)."
[app-context]
(:stillsuit/connection app-context))
(defn db
"Given a stillsuit-decorated app context, get the most recent datomic db value from its datomic connection.
Parameters:
- `app-context`: the lacinia application context (first argument to a resolver function)
For more information, see [the user manual](http://docs.workframe.com/stillsuit/current/manual/#_stillsuit_enums)."
[app-context]
(some-> app-context :stillsuit/connection d/db))
(defn decorate
"Main interface to stillsuit. Accepts a map containing various parameters as input; returns
a map with an app context and a schema. The map can be passed to [[execute]] in order to
invoke lacinia with its configuration.
The single argument to `(decorate)` should be a map with the following keys:
- `:stillsuit/schema`: a normal
[lacinia schema definition](http://lacinia.readthedocs.io/en/latest/tutorial/init-schema.html#schema-edn-file).
- `:stillsuit/connection`: a datomic [connection object]().
- `:stillsuit/resolvers`: a map of keywords to resolver function objects, identical to the
map you'd pass to
[`(lacinia.util/attach-resolvers)`](http://lacinia.readthedocs.io/en/latest/resolve/attach.html).
- `:stillsuit/config` (optional): a map of
[configuration options](http://docs.workframe.com/stillsuit/current/manual/#_compiling_a_schema)
for stillsuit.
- `:stillsuit/context` (optional): a map containing any custom information your resolvers need,
identical to the `context` argument you'd pass to `(lacinia/execute)`.
- `:stillsuit/transformers` (optional): a map of keywords to scalar transformer function objects,
identical to the map you'd pass to
[`(lacinia.util/attach-scalar-transformers)`](http://lacinia.readthedocs.io/en/latest/custom-scalars.html#attaching-scalar-transformers).
- `:stillsuit/entity-filters` (optional): a map of keywords to entity filter functions, which are
used to filter the results of :stillsuit/ref resolvers.
The return value of this function is a map with two keys:
- `:stillsuit/schema`: the compiled, transformed schema definition
- `:stillsuit/app-context`: an application context object
These two data structures can be passed to `(lacinia/execute)` directly, or there is a
simple wrapper function [[execute]] that will invoke lacinia for you.
For more information, see [the user manual](http://docs.workframe.com/stillsuit/current/manual/)."
[{:stillsuit/keys [schema config resolvers transformers context connection entity-filters]}]
(let [opts (merge @default-config-schema (:stillsuit/config schema) config)
uncompiled (-> @base-schema
(slu/deep-map-merge schema)
(sq/attach-queries opts)
(sr/attach-resolvers opts)
(util/attach-resolvers (decorate-resolver-map resolvers opts))
(util/attach-scalar-transformers (ss/transformer-map transformers opts)))
compile-opts (when-not (:stillsuit/no-default-resolver? opts)
{:default-field-resolver sr/default-resolver})
enum-map (se/make-enum-map opts uncompiled)
compiled (if (:stillsuit/compile? opts)
(schema/compile uncompiled compile-opts)
uncompiled)]
(when (:stillsuit/trace? opts)
(log/spy :trace uncompiled))
{:stillsuit/schema compiled
:stillsuit/app-context (make-app-context context schema connection
enum-map entity-filters opts)}))
(defn execute
"Convenience function to take the result of [[decorate]] and execute a query against it.
The `query` and `variables` parameters are the same ones that would be passed to
`(lacinia.core/execute)`.
For more information, see [the user manual](http://docs.workframe.com/stillsuit/current/manual/#__code_stillsuit_execute_code)."
([stillsuit-result query]
(execute stillsuit-result query nil))
([stillsuit-result query variables]
(let [schema (:stillsuit/schema stillsuit-result)
context (:stillsuit/app-context stillsuit-result)]
(lacinia/execute schema query variables context))))