• Stars
    star
    1,798
  • Rank 24,801 (Top 0.6 %)
  • Language
    Clojure
  • License
    Other
  • Created about 7 years ago
  • Updated 20 days ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

GraphQL implementation in pure Clojure

Lacinia

Clojars Project CI

Lacinia Manual | Lacinia Tutorial | API Documentation

This library is a full implementation of Facebook's GraphQL specification.

Lacinia should be viewed as roughly analogous to the official reference JavaScript implementation. In other words, it is a backend-agnostic GraphQL query execution engine. Lacinia is not an Object Relational Mapper ... it's simply the implementation of a contract sitting between the GraphQL client and your data.

Lacinia features:

  • An EDN-based schema language, or use GraphQL's Interface Definition Language.

  • High performance parser for GraphQL queries, built on Antlr4.

  • Efficient and asynchronous query execution.

  • Full support for GraphQL types, interfaces, unions, enums, input objects, and custom scalars.

  • Full support for GraphQL subscriptions.

  • Full support of inline and named query fragments.

  • Full support for GraphQL Schema Introspection.

Lacinia has been developed with a set of core philosophies:

  • Prefer data over macros and other tricks: Compose your schema in whatever mix of data and code works for you.

  • Embrace Clojure: Use EDN data, keywords, functions, and persistent data structures.

  • Keep it simple: You provide the schema and a handful of functions to resolve data, and Lacinia does the rest.

  • Do the right thing: apply reasonable defaults without a lot of "magic".

This library can be plugged into any Clojure HTTP pipeline. The companion library lacinia-pedestal provides full HTTP support, including GraphQL subscriptions, for Pedestal.

An externally developed library, duct-lacinia, provides similar capability for Duct.

Getting Started

For more detailed documentation, read the manual.

GraphQL starts with a schema definition of types that can be queried.

A schema starts as an EDN file; the example below demonstrates a small subset of the available options:

{:enums
 {:Episode
  {:description "The episodes of the original Star Wars trilogy."
   :values [:NEWHOPE :EMPIRE :JEDI]}}

 :objects
 {:Droid
  {:fields {:id {:type Int}
            :primaryFunctions {:type (list String)}
            :name {:type String}
            :appearsIn {:type (list :Episode)}}}

  :Human
  {:fields {:id {:type Int}
            :name {:type String}
            :homePlanet {:type String}
            :appearsIn {:type (list :Episode)}}}
  :Query
  {:fields {:hero {:type (non-null :Human)
                   :args {:episode {:type :Episode}}}
            :droid {:type :Droid
                    :args {:id {:type String 
                                :default-value "2001"}}}}}}}

The fields of the special Query object define the query operations available; with this schema, a client can find the Human hero of an episode, or find a Droid by its id.

A schema alone describes what data is available to clients, but doesn't identify where the data comes from; that's the job of a field resolver.

A field resolver is just a function which is passed the application context, a map of arguments values, and a resolved value from a parent field. The field resolver returns a value consistent with the type of the field; most field resolvers return a Clojure map or record, or a list of those. Lacinia then uses the GraphQL query to select fields of that value to return in the response.

Here's what a very opinionated get-hero field resolver might look like:

(defn get-hero 
  [context arguments value]
  (let [{:keys [episode]} arguments]
    (if (= episode :NEWHOPE)
      {:id 1000
       :name "Luke"
       :homePlanet "Tatooine"
       :appearsIn ["NEWHOPE" "EMPIRE" "JEDI"]}
      {:id 2000
       :name "Lando Calrissian"
       :homePlanet "Socorro"
       :appearsIn ["EMPIRE" "JEDI"]})))

In this greatly simplified example, the field resolver can simply return the resolved value. Field resolvers that return multiple values return a list, vector, or set of values.

In real applications, a field resolver might execute a query against a database, or send a request to another web service.

After injecting resolvers, it is necessary to compile the schema; this step performs validations, provides defaults, and organizes the schema for efficient execution of queries.

This needs only be done once, in application startup code:

(require '[clojure.edn :as edn]
         '[com.walmartlabs.lacinia.util :refer [inject-resolvers]]
         '[com.walmartlabs.lacinia.schema :as schema])

(def star-wars-schema
  (-> "schema.edn"
      slurp
      edn/read-string
      (inject-resolvers {:Query/hero get-hero
                         :Query/droid (constantly {})})
      schema/compile))

With the compiled application available, it can be used to execute requests; this typically occurs inside a Ring handler function:

(require '[com.walmartlabs.lacinia :refer [execute]]
         '[clojure.data.json :as json])

(defn handler [request]
  {:status 200
   :headers {"Content-Type" "application/json"}
   :body (let [query (get-in request [:query-params :query])
               result (execute star-wars-schema query nil nil)]
           (json/write-str result))})

Lacinia doesn't know about the web tier at all, it just knows about parsing and executing queries against a compiled schema. A companion library, lacinia-pedestal, is one way to expose your schema on the web.

Clients will typically send a JSON POST request, with a query key containing the GraphQL query document:

{
  hero {
    id
    name
  }
}

The execute function returns EDN data that can be easily converted to JSON. The :data key contains the value requested for the hero query in the request.

{:data
  {:hero {:id 2000
          :name "Lando Calrissian"}}}

This example request has no errors, and contained only a single query. GraphQL supports multiple queries in a single request. There may be errors executing the query, Lacinia will process as much as it can, and will report errors in the :errors key.

One of the benefits of GraphQL is that the client has the power to rename fields in the response:

{
  hero(episode: NEWHOPE) {
    movies: appearsIn
  }
}
{:data {:hero {:movies [:NEWHOPE :EMPIRE :JEDI]}}}

This is just an overview, far more detail is available in the manual.

Status

This library has been used in production at Walmart since 2017, going through a very long beta period as it evolved; we transitioned to a 1.0 release on 9 Oct 2021.

To use this library with Clojure 1.8, you must include a dependency on clojure-future-spec.

More details are in the manual.

License

Copyright ยฉ 2017-2023 WalmartLabs

Distributed under the Apache License, Version 2.0.

More Repositories

1

thorax

Strengthening your Backbone
JavaScript
1,324
star
2

react-ssr-optimization

React.js server-side rendering optimization with component memoization and templatization
JavaScript
821
star
3

electrode

Electrode - Application Platform on React/Node.js powering Walmart.com
446
star
4

little-loader

A lightweight, IE8+ JavaScript loader
JavaScript
371
star
5

json-to-simple-graphql-schema

Transforms JSON input into a GraphQL schema
JavaScript
279
star
6

eslint-config-defaults

A composable set of ESLint defaults
JavaScript
229
star
7

lumbar

Modular javascript build tool
JavaScript
226
star
8

datascope

Visualization of Clojure data structures using Graphviz
Clojure
206
star
9

lacinia-pedestal

Expose Lacinia GraphQL as Pedestal endpoints
Clojure
197
star
10

bigben

BigBen - a generic, multi-tenant, time-based event scheduler and cron scheduling framework
Kotlin
196
star
11

concord

Concord - workflow orchestration and continuous deployment management
Java
195
star
12

kubeman

The Hero that Kubernetes deserves
TypeScript
164
star
13

system-viz

Graphviz visualization of a component system
Clojure
159
star
14

react-native-orientation-listener

A react-native library for obtaining current device orientation
Java
151
star
15

thorax-seed

JavaScript
131
star
16

vizdeps

Visualize Leiningen dependencies using Graphviz
Clojure
130
star
17

mupd8

Muppet
Scala
126
star
18

active-status

Present status of mulitple 'jobs' in a command line tool, using terminal capability codes
Clojure
118
star
19

schematic

Combine configuration with building a Component system
Clojure
104
star
20

easy-fix

easy-fix: run integration tests like unit tests
JavaScript
101
star
21

dyn-edn

Dynamic properties in EDN content
Clojure
94
star
22

fruit-loops

Server-side jQuery API renderer.
JavaScript
89
star
23

generator-thorax

Thorax yeoman generator
JavaScript
87
star
24

walmart-cla

Walmart Contributor License Agreement Information
85
star
25

react-native-cropping

Cropping components for react-native
JavaScript
68
star
26

curved-carousel

An infinitely scrolling carousel with configurable curvature
JavaScript
64
star
27

walmart-api

API wrapper for the public Walmart Labs API
JavaScript
62
star
28

gozer

Open source library to parse various X12 file formats for retail/supply chain
Java
60
star
29

cookie-cutter

An opinionated micro-services framework for TypeScript
TypeScript
57
star
30

mock-server

SPA application debug proxy server
JavaScript
56
star
31

test-reporting

Tiny library to assist with reporting some context when a test fails
Clojure
53
star
32

container-query

A responsive layout helper based on the width of the container
JavaScript
52
star
33

react-native-platform-visible

A very simple component visibility switch based on Platform
JavaScript
49
star
34

eslint-config-walmart

A set of default eslint configurations, Walmart Labs style.
JavaScript
48
star
35

clojure-game-geek

Example source code for the Lacinia tutorial
Clojure
47
star
36

babel-plugin-react-cssmoduleify

Babel plugin to transform traditional React element classNames to CSS Modules
JavaScript
45
star
37

generator-release

Yeoman generator for handling Bower/NPM releases.
JavaScript
45
star
38

costanza

Frontend error tracking toolkit: Own your own domain
JavaScript
35
star
39

zFAM

z/OS-based File Access Manager
Assembly
35
star
40

nightcall

Automated Enumeration Script for Pentesting
Python
34
star
41

cond-let

A useful merge of cond and let
Clojure
30
star
42

static

JavaScript
26
star
43

bolt

[DEPRECATED] an opinionated meta task runner for components.
JavaScript
24
star
44

shared-deps

Leiningen plugin to allow sub-modules to more easily share common dependencies
Clojure
24
star
45

ridicule

Mocking everything
JavaScript
22
star
46

linearroad

Walmart version of the Linear Road streaming benchmark.
Java
22
star
47

backbone-historytracker

Backbone plugin for navigation direction tracking
JavaScript
22
star
48

zECS

z/OS-based Enterprise Cache Service
COBOL
21
star
49

pulsar

Text-based dashboard for Elixir CLIs
Elixir
20
star
50

react-native-image-progressbar

An image based progress bar
JavaScript
20
star
51

layout

A simple responsive layout helper
CSS
17
star
52

zUID

z/OS-based Unique Identifier generator
Assembly
16
star
53

showcase-template

A starter template for a showcase of React components
CSS
16
star
54

grunt-release-component

Grunt release helper for bower components
JavaScript
15
star
55

anomaly-detection-walmart

Python
14
star
56

partnerapi_sdk_dotnet

Walmart Partner API SDK for .NET
C#
14
star
57

circus

External Webpack Component Plugin
JavaScript
13
star
58

concord-website

Documentation website source code for Concord
JavaScript
13
star
59

concord-plugins

Java
12
star
60

strati-functional

A lightweight collection of functional classes used to complement core Java.
Java
12
star
61

thorax-boilerplate

A boilerplate project for Thoroax
JavaScript
11
star
62

nocktor

nocktor - your nock doctor
JavaScript
11
star
63

getting-started

How to get started with the WalmartLabs API and tooling
9
star
64

LinearGenerator

Reworked data generator for LinearRoad streaming benchmark that no longer needs mitsim or any database.
Java
9
star
65

json-patchwork

JavaScript
9
star
66

object-diff

A Go library implementing object wise diff and patch.
Go
8
star
67

small-world-graph

Graphing as in Data
C++
8
star
68

chai-shallowly

A chai assertion plugin for enzyme.
JavaScript
8
star
69

typeahead.js-legacy

typeahead.js is a fast and fully-featured autocomplete library
JavaScript
8
star
70

child-pool

child_process pool implementation
JavaScript
7
star
71

thorax-todos

JavaScript
6
star
72

hula-hoop

Server-side rendering components for Thorax + Hapi stacks.
JavaScript
6
star
73

apache-http-client

A Clojure ring compatible http interface for Apache HttpClient
Clojure
5
star
74

lumbar-loader

JavaScript
5
star
75

krabby

JavaScript
4
star
76

js-conceptualizer

JS Conceptualizer is a bit of client-side Javascript that parses out concepts, particularly proper nouns, from HTML on a web page.
JavaScript
4
star
77

babel-plugin-i18n-id-hashing

Namespace the ID of React-Intl keys
JavaScript
4
star
78

express-example

A crazy simple example of using the Walmart API with express
JavaScript
4
star
79

wml-coding-std

A module for keeping consistent JS coding standards at WML
JavaScript
3
star
80

nativedriver

native driver for UI automation
Objective-C
3
star
81

was

Go
3
star
82

thorax-rails

Ruby
3
star
83

hapi-example

A crazy simple example of using the Walmart API with hapi
JavaScript
3
star
84

lumbar-long-expires

Long expires cache buster plugin for Lumbar
JavaScript
3
star
85

component-scan

A component scanner for React
JavaScript
3
star
86

scanomatic-server

Scan-O-Matic Node Server
JavaScript
3
star
87

hadoop-openstack-swifta

hadoop-openstack-swifta
Java
3
star
88

SDJSBridge

Native/Hybrid Javascript Bridge
Objective-C
2
star
89

cordova-starter-kit

A starter kit for using Cordova and the Walmart API
JavaScript
2
star
90

priorityY

Priority Based Connected Components
Python
2
star
91

bolt-standard-flux

electrode bolt standard configs and tasks for flux architecture.
JavaScript
1
star
92

github-util

Github utility methods.
JavaScript
1
star
93

lumbar-tester

Unit testing plugin for Lumbar
JavaScript
1
star
94

apidocs

HTML
1
star
95

circus-stylus

Stylus linker for Circus components
JavaScript
1
star
96

SDUserActivity

An simplified interface for NSUserActivity for apps that want to participate in handoff.
Objective-C
1
star
97

walmartlabs.github.io

Helper to redirect to code.walmartlabs.com
HTML
1
star
98

BurpSuiteDynamicSessionTracker

BurpSuite extension for tracking and manipulating dynamic session cookies
Java
1
star
99

bolt-cli

[DEPRECATED] bolt command line interface.
JavaScript
1
star
100

phoenix-build

Common build libraries for Phoenix projects
JavaScript
1
star