A Clojure(Script) qraphql query client library. Generate valid graphql queries with Clojure data structures.
Venia is originally supposed to be used in Clojurescript apps, but can be used as well in Clojure, as the coreis written in CLJC. The sole purpose of this library is graphql query string generation from Clojure data,so that strings concatenations and manipulations could be avoided when using grapqhl.It is up to developers to hook it up to frontend apps. However, at least some sort of re-frame-graphql-fx libraryis on a roadmap.
The easiest way to start with venia, is simple's query generation.
(ns my.project
(:require [venia.core :as v]))
(v/graphql-query {:venia/queries [[:employee {:id 1 :active true} [:name :address [:friends [:name :email]]]]]})
=> "{employee(id:1,active:true){name,address,friends{name,email}}}"
Obviously, If we would like to fetch employees and projects within the same simple query, we would do it this way:
(v/graphql-query {:venia/queries [[:employee {:id 1 :active true} [:name :address [:friends [:name :email]]]]
[:projects {:active true} [:customer :price]]]})
=> "{employee(active:true){name,address},project(active:true){customer,price}}"
In the example above, :employee
and :projects
fields have arguments {:id 1 :active true}
and {:id 1 :active true}
respectively.
We can add arguments to other fields easily by wrapping field name and its arguments to vector [:customer {:id 2}]
:
(v/graphql-query {:venia/queries [[:projects {:active true} [[:customer {:id 2}] :price]]]})
=> "{project(active:true){customer(id:2),price}}"
Now, if we need to have an alias for query, it can be easily achieved by using venia's query-with-data map
(v/graphql-query {:venia/queries [{:query/data [:employee {:id 1 :active true} [:name :address [:friends [:name :email]]]]
:query/alias :workhorse}
{:query/data [:employee {:id 2 :active true} [:name :address [:friends [:name :email]]]]
:query/alias :boss}]})
=> prettified:
{
workhorse: employee(id: 1, active: true) {
name
address
},
boss: employee(id: 2, active: true) {
name
address
}
}
In the query above, we use :query/data
key for query definition and :query/alias
for query's alias definition.
What about fragments? Just add :venia/fragments
vector with fragments definitions
(v/graphql-query {:venia/queries [{:query/data [:employee {:id 1 :active true} :fragment/comparisonFields]
:query/alias :workhorse}
{:query/data [:employee {:id 2 :active true} :fragment/comparisonFields]
:query/alias :boss}]
:venia/fragments [{:fragment/name "comparisonFields"
:fragment/type :Worker
:fragment/fields [:name :address]}]})
=> prettified:
{
workhorse: employee(id: 1, active: true) {
...comparisonFields
}
boss: employee(id: 2, active: true) {
...comparisonFields
}
}
fragment comparisonFields on Worker {
name
address
}
Now you can generate really complex queries with variables as well. In order to define variables, we need to definean operation type and name.
(v/graphql-query {:venia/operation {:operation/type :query
:operation/name "employeeQuery"}
:venia/variables [{:variable/name "id"
:variable/type :Int
:variable/default 1}
{:variable/name "name"
:variable/type :String}]
:venia/queries [{:query/data [:employee {:id :$id
:active true
:name :$name}
:fragment/comparisonFields]
:query/alias :workhorse}
{:query/data [:employee {:id :$id
:active false}
:fragment/comparisonFields]
:query/alias :boss}]
:venia/fragments [{:fragment/name "comparisonFields"
:fragment/type :Worker
:fragment/fields [:name :address [:friends [:name :email]]]}]})
=> prettified:
query employeeQuery($id: Int = 1, $name: String) {
workhorse: employee(id: $id, active: true, name: $name) {
...comparisonFields
}
boss: employee(id: $id, active: false) {
...comparisonFields
}
}
fragment comparisonFields on Worker {
name
address
friends {
name
email
}
}
Mutations are also supported, just use :mutation
operation type:
(v/graphql-query {:venia/operation {:operation/type :mutation
:operation/name "AddProjectToEmployee"}
:venia/variables [{:variable/name "id"
:variable/type :Int!}
{:variable/name "project"
:variable/type :ProjectNameInput!}]
:venia/queries [[:addProject {:employeeId :$id
:project :$project}
[:allocation :name]]]})
=> prettified:
mutation AddProjectToEmployee($id:Int!,$project:ProjectNameInput!) {
addProject(employeeId:$id, project:$project) {
allocation,
name
}
}
Venia will verify that you don't use undefined variables or fragments.
For example, the following v/graphql-query
calls will throw exceptions:
(v/graphql-query {:venia/queries [[:employee {:id 1 :active true} :fragment/undefined]]}
(v/graphql-query {:venia/queries [[:employee {:id 1 :active :$undefined} [:name]]]}))
because fragment and variable are never defined.
You can use graphql's __typename
meta field anywhere inside of your query.For example:
(v/graphql-query {:venia/queries [[:employee [:meta/typename :name :address]]}
=> prettified:
{
employee {
__typename,
name,
address
}
}
Copyright © 2017 Vincit
Distributed under the Eclipse Public License, the same as Clojure.
<script> defer 和 async 有什么区别? 相同点: <script> 标签必须有 src 属性,不能是内联脚本 加载是异步的 脚本中不能调用 document.write() 不同点: defer 在 HTML 4 中被定义,async 在 HTML 5 中定义 defer 使脚本在 HTML 解析完且触发 DOMContentLoaded 之前按照声明顺序执行,async 则是
我们把项目查看模式切换成Android,所有的文件会通过类型进行归类,这个并不是实际在电脑中的文件结构哦,如果想看实际的物理结构请切换到Project. 切换成Android可以查看所有的Gradle Script: 每个文件后面都有一个灰色字体描述: 1.build.gradle: Project构建文件 2.build.gradle: Module构建文件 3.gradle.propertie
SCRIPT FLUSH 清除所有 Lua 脚本缓存。 关于使用 Redis 对 Lua 脚本进行求值的更多信息,请参见 EVAL 命令。 可用版本: >= 2.6.0 复杂度: O(N) , N 为缓存中脚本的数量。 返回值: 总是返回 OK redis> SCRIPT FLUSH OK
SCRIPT KILL 杀死当前正在运行的 Lua 脚本,当且仅当这个脚本没有执行过任何写操作时,这个命令才生效。 这个命令主要用于终止运行时间过长的脚本,比如一个因为 BUG 而发生无限 loop 的脚本,诸如此类。 SCRIPT KILL 执行之后,当前正在运行的脚本会被杀死,执行这个脚本的客户端会从 EVAL 命令的阻塞当中退出,并收到一个错误作为返回值。 另一方面,假如当前正在运行的脚本已
SCRIPT EXISTS script [script ...] 给定一个或多个脚本的 SHA1 校验和,返回一个包含 0 和 1 的列表,表示校验和所指定的脚本是否已经被保存在缓存当中。 关于使用 Redis 对 Lua 脚本进行求值的更多信息,请参见 EVAL 命令。 可用版本: >= 2.6.0 时间复杂度: O(N) , N 为给定的 SHA1 校验和的数量。 返回值: 一个列表,包含
SCRIPT LOAD script 将脚本 script 添加到脚本缓存中,但并不立即执行这个脚本。 EVAL 命令也会将脚本添加到脚本缓存中,但是它会立即对输入的脚本进行求值。 如果给定的脚本已经在缓存里面了,那么不做动作。 在脚本被加入到缓存之后,通过 EVALSHA 命令,可以使用脚本的 SHA1 校验和来调用这个脚本。 脚本可以在缓存中保留无限长的时间,直到执行 SCRIPT FLUSH
1. 前言 前面一系列动态 SQL 小节的学习中,我们都是在 xml 中书写 SQL 的。注解无法发挥 MyBatis 动态 SQL 的真正威力,但是 if、choose、bind、where 等标签还是可以在注解中使用的。 MyBatis 官方文档对于此的介绍只有寥寥一句话和一个简单的例子,在实际的应用中也几乎没有人这样去做,因为它确实不太美观,但是考虑到这个知识点并不复杂,也极有可能成为一个刁
Notepad++ 的 CS-Script 工具 CS-Script tools suite 是 NotePad++的轻量级扩展工具集。可以利用它有效的进行 C# 的编写/执行开发,而无须像传统的开发工具那样需要额外的开销。同时它也提供了一个完整的 IDE 的众多功能特性。但是它并不打算取代任何一个 IDE,只是作为一个成熟 IDE 和普通的文本编辑器之间的补充而存在。 CS-Script too