All Projects → walmartlabs → Lacinia

walmartlabs / Lacinia

Licence: other
GraphQL implementation in pure Clojure

Programming Languages

clojure
4091 projects
ANTLR
299 projects
r
7636 projects

Labels

Projects that are alternatives of or similar to Lacinia

Odatatoentity
OData .net core
Stars: ✭ 117 (-92.9%)
Mutual labels:  graphql
Wp Graphql Yoast Seo
This is an extension to the WPGraphQL plugin for Yoast SEO
Stars: ✭ 120 (-92.72%)
Mutual labels:  graphql
Deploy Strapi On Aws
Deploying a Strapi API on AWS (EC2 & RDS & S3)
Stars: ✭ 121 (-92.66%)
Mutual labels:  graphql
Searchobjectgraphql
GraphQL plugin for SearchObject gem
Stars: ✭ 118 (-92.84%)
Mutual labels:  graphql
Shio
✨ :dna: Shio CMS - Model Content, Use GraphQL and Create Site using Javascript with Native Cache and Search.
Stars: ✭ 119 (-92.78%)
Mutual labels:  graphql
Hypergraphql
GraphQL interface for querying and serving linked data on the Web.
Stars: ✭ 120 (-92.72%)
Mutual labels:  graphql
Angular Enterprise Example
Scalable / Large Angular application structure example
Stars: ✭ 117 (-92.9%)
Mutual labels:  graphql
Gql
Libraries supporting GraphQL in Dart
Stars: ✭ 122 (-92.6%)
Mutual labels:  graphql
Graphene Gae
GraphQL Support for Google AppEngine [DEPRECATED - Looking for maintainers]
Stars: ✭ 119 (-92.78%)
Mutual labels:  graphql
React Graphql Github Apollo
🚀 A React + Apollo + GraphQL GitHub Client. Your opportunity to learn about these technologies in a real world application.
Stars: ✭ 1,563 (-5.22%)
Mutual labels:  graphql
Server
Framework NodeJS for GraphQl
Stars: ✭ 118 (-92.84%)
Mutual labels:  graphql
Client Side Graphql
Stars: ✭ 119 (-92.78%)
Mutual labels:  graphql
Graphql Mode
An Emacs mode for GraphQL
Stars: ✭ 120 (-92.72%)
Mutual labels:  graphql
Universal React Apollo Example
Universal React Apollo App (GraphQL) consuming: https://github.com/WeLikeGraphQL/wordpress-graphql-api-example!
Stars: ✭ 117 (-92.9%)
Mutual labels:  graphql
Springboot Restful Angular
springBoot,restful,jwt,angular4 搭建的前后端分离后台管理系统
Stars: ✭ 121 (-92.66%)
Mutual labels:  graphql
Autograph
A GraphQL Client in Swift
Stars: ✭ 117 (-92.9%)
Mutual labels:  graphql
Graphql Directive Auth
GraphQL directive for handling auth
Stars: ✭ 120 (-92.72%)
Mutual labels:  graphql
Onesubscribe
ss ssr v2ray 订阅管理 node 后端
Stars: ✭ 122 (-92.6%)
Mutual labels:  graphql
Graphql Typed Document Node
An improved version of `DocumentNode` for seamless TypeScript integration for GraphQL.
Stars: ✭ 122 (-92.6%)
Mutual labels:  graphql
Netcoreblockly
.NET Core API to Blockly - generate from WebAPI, Swagger, OData, GraphQL =>
Stars: ✭ 121 (-92.66%)
Mutual labels:  graphql

Lacinia

Clojars Project

CircleCI

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.

  • 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 exposed types.

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 {:primary_functions {:type (list String)}
            :id {:type Int}
            :name {:type String}
            :appears_in {:type (list :episode)}}}

  :human
  {:fields {:id {:type Int}
            :name {:type String}
            :home_planet {:type String}
            :appears_in {:type (list :episode)}}}}

 :queries
 {:hero {:type (non-null :human)
         :args {:episode {:type :episode}}
         :resolve :get-hero}
  :droid {:type :droid
          :args {:id {:type String :default-value "2001"}}
          :resolve :get-droid}}}

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, provided by the :resolve key inside fields such as the :hero and :droid query.

The values here, :get-hero and :get-droid, are placeholders; the startup code of the application will use com.walmartlabs.lacinia.util/attach-resolvers to attach the actual field resolver function.

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. If it's a scalar type, it should return a value that conforms to the defined type in the schema. If not, it's a type error.

The field resolver is totally responsible for obtaining the data from whatever external store you use: whether it is a database, a web service, or something else.

It's important to understand that every field has a field resolver, even if you don't define it explicitly. If you don't supply a field resolver, Lacinia provides a default field resolver, customized to the field.

Here's what the get-hero field resolver might look like:

(defn get-hero [context arguments value]
  (let [{:keys [episode]} arguments]
    (if (= episode :NEWHOPE)
      {:id 1000
       :name "Luke"
       :home_planet "Tatooine"
       :appears_in ["NEWHOPE" "EMPIRE" "JEDI"]}
      {:id 2000
       :name "Lando Calrissian"
       :home_planet "Socorro"
       :appears_in ["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 attaching resolvers, it is necessary to compile the schema; this step performs validations, provide 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 [attach-resolvers]]
         '[com.walmartlabs.lacinia.schema :as schema])

(def star-wars-schema
  (-> "schema.edn"
      slurp
      edn/read-string
      (attach-resolvers {:get-hero get-hero
                         :get-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: appears_in
  }
}
{: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-2021 WalmartLabs

Distributed under the Apache License, Version 2.0.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].