{"id":13499541,"url":"https://github.com/walmartlabs/lacinia","last_synced_at":"2025-05-14T02:00:26.655Z","repository":{"id":18710638,"uuid":"85124920","full_name":"walmartlabs/lacinia","owner":"walmartlabs","description":"GraphQL implementation in pure Clojure","archived":false,"fork":false,"pushed_at":"2025-02-08T17:51:06.000Z","size":3642,"stargazers_count":1832,"open_issues_count":21,"forks_count":163,"subscribers_count":61,"default_branch":"master","last_synced_at":"2025-04-10T16:59:30.317Z","etag":null,"topics":["clojure","graphql"],"latest_commit_sha":null,"homepage":"http://lacinia.readthedocs.io/en/latest/","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/walmartlabs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":"docs/contributing.rst","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-03-15T21:59:45.000Z","updated_at":"2025-04-03T22:41:00.000Z","dependencies_parsed_at":"2023-02-18T12:19:28.397Z","dependency_job_id":"a5b28d70-80af-4e87-b3bc-a8a3c61464cb","html_url":"https://github.com/walmartlabs/lacinia","commit_stats":{"total_commits":1091,"total_committers":65,"mean_commits":"16.784615384615385","dds":"0.40238313473877174","last_synced_commit":"3d744f2dd771729e513829b489ed33ccf3fd4a61"},"previous_names":[],"tags_count":98,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/walmartlabs%2Flacinia","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/walmartlabs%2Flacinia/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/walmartlabs%2Flacinia/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/walmartlabs%2Flacinia/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/walmartlabs","download_url":"https://codeload.github.com/walmartlabs/lacinia/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254052658,"owners_count":22006716,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clojure","graphql"],"created_at":"2024-07-31T22:00:34.550Z","updated_at":"2025-05-14T02:00:26.520Z","avatar_url":"https://github.com/walmartlabs.png","language":"Clojure","funding_links":[],"categories":["Libraries","Clojure","Implementations","\u003ca name=\"Clojure\"\u003e\u003c/a\u003eClojure"],"sub_categories":["Clojure Libraries","Clojure"],"readme":"# Lacinia\n\n\n[![Clojars Project](https://img.shields.io/clojars/v/com.walmartlabs/lacinia.svg)](https://clojars.org/com.walmartlabs/lacinia)\n[![CI](https://github.com/walmartlabs/lacinia/actions/workflows/config.yml/badge.svg)](https://github.com/walmartlabs/lacinia/actions/workflows/config.yml)\n\n[Lacinia Manual](http://lacinia.readthedocs.io/en/latest/) |\n[Lacinia Tutorial](http://lacinia.readthedocs.io/en/latest/tutorial) |\n[API Documentation](http://walmartlabs.github.io/apidocs/lacinia/)\n\nThis library is a full implementation of\nFacebook's [GraphQL specification](https://facebook.github.io/graphql).\n\nLacinia should be viewed as roughly analogous to the\n[official reference JavaScript implementation](https://github.com/graphql/graphql-js/).\nIn other words, it is a backend-agnostic GraphQL query execution engine.\nLacinia is not an Object Relational Mapper ... it's simply the implementation of a contract\nsitting between the GraphQL client and your data.\n\nLacinia features:\n\n- An [EDN](https://github.com/edn-format/edn)-based schema language, or use\n  GraphQL's [Interface Definition Language](http://spec.graphql.org/June2018/#sec-Type-System).\n\n- High performance parser for GraphQL queries, built on [Antlr4](http://www.antlr.org/).\n\n- Efficient and asynchronous query execution.\n\n- Full support for GraphQL types, interfaces, unions, enums, input objects, and custom scalars.\n\n- Full support for GraphQL subscriptions.\n\n- Full support of inline and named query fragments.\n\n- Full support for GraphQL Schema Introspection.\n\nLacinia has been developed with a set of core philosophies:\n\n- Prefer data over macros and other tricks: Compose your schema in whatever mix of data and code works for you.\n\n- Embrace Clojure: Use EDN data, keywords, functions, and persistent data structures.\n\n- Keep it simple: You provide the schema and a handful of functions to resolve data, and Lacinia does the rest.\n\n- Do the right thing: apply reasonable defaults without a lot of \"magic\".\n\nThis library can be plugged into any Clojure HTTP pipeline.\nThe companion library [lacinia-pedestal](https://github.com/walmartlabs/lacinia-pedestal) provides\nfull HTTP support, including GraphQL subscriptions, for [Pedestal](https://github.com/pedestal/pedestal).\n\nAn externally developed library, [duct-lacinia](https://github.com/kakao/duct-lacinia), provides similar capability\nfor [Duct](https://github.com/duct-framework/duct).\n\n## Getting Started\n\nFor more detailed documentation, [read the manual](http://lacinia.readthedocs.io/en/latest/).\n\nGraphQL starts with a schema definition of types that can be queried.\n\nA schema starts as an EDN file; the example below demonstrates a small subset\nof the available options:\n\n```clojure\n{:enums\n {:Episode\n  {:description \"The episodes of the original Star Wars trilogy.\"\n   :values [:NEWHOPE :EMPIRE :JEDI]}}\n\n :objects\n {:Droid\n  {:fields {:id {:type Int}\n            :primaryFunctions {:type (list String)}\n            :name {:type String}\n            :appearsIn {:type (list :Episode)}}}\n\n  :Human\n  {:fields {:id {:type Int}\n            :name {:type String}\n            :homePlanet {:type String}\n            :appearsIn {:type (list :Episode)}}}\n  :Query\n  {:fields {:hero {:type (non-null :Human)\n                   :args {:episode {:type :Episode}}}\n            :droid {:type :Droid\n                    :args {:id {:type String \n                                :default-value \"2001\"}}}}}}}\n```\nThe fields of the special Query object define the query operations available; with this schema,\na client can find the Human `hero` of an episode, or find a `Droid` by its id.\n\nA schema alone describes what data is available to clients, but doesn't identify where\nthe data comes from; that's the job of a field resolver.\n\nA field resolver is just a function which is passed the application context,\na map of arguments values, and a resolved value from a\nparent field.\nThe field resolver returns a value consistent with the type of the field; most field resolvers\nreturn a Clojure map or record, or a list of those.  Lacinia then uses the GraphQL query to \nselect fields of that value to return in the response.\n\nHere's what a very opinionated `get-hero` field resolver might look like:\n\n```clojure\n(defn get-hero \n  [context arguments value]\n  (let [{:keys [episode]} arguments]\n    (if (= episode :NEWHOPE)\n      {:id 1000\n       :name \"Luke\"\n       :homePlanet \"Tatooine\"\n       :appearsIn [\"NEWHOPE\" \"EMPIRE\" \"JEDI\"]}\n      {:id 2000\n       :name \"Lando Calrissian\"\n       :homePlanet \"Socorro\"\n       :appearsIn [\"EMPIRE\" \"JEDI\"]})))\n```\n\nIn this greatly simplified example, the field resolver can simply return the resolved value.\nField resolvers that return multiple values return a list, vector, or set of values.\n\nIn real applications, a field resolver might execute a query against a database,\nor send a request to another web service.\n\nAfter injecting resolvers, it is necessary to compile the schema; this\nstep performs validations, provides defaults, and organizes the schema\nfor efficient execution of queries.\n\nThis needs only be done once, in application startup code:\n\n\n```clojure\n(require '[clojure.edn :as edn]\n         '[com.walmartlabs.lacinia.util :refer [inject-resolvers]]\n         '[com.walmartlabs.lacinia.schema :as schema])\n\n(def star-wars-schema\n  (-\u003e \"schema.edn\"\n      slurp\n      edn/read-string\n      (inject-resolvers {:Query/hero get-hero\n                         :Query/droid (constantly {})})\n      schema/compile))\n```\n\nWith the compiled application available, it can be used to execute\nrequests; this typically occurs inside a Ring handler function:\n\n```clojure\n(require '[com.walmartlabs.lacinia :refer [execute]]\n         '[clojure.data.json :as json])\n\n(defn handler [request]\n  {:status 200\n   :headers {\"Content-Type\" \"application/json\"}\n   :body (let [query (get-in request [:query-params :query])\n               result (execute star-wars-schema query nil nil)]\n           (json/write-str result))})\n```\n\nLacinia doesn't know about the web tier at all, it just knows about\nparsing and executing queries against a compiled schema.\nA companion library, [lacinia-pedestal](https://github.com/walmartlabs/lacinia-pedestal),\nis one way to expose your schema on the web.\n\nClients will typically send a JSON POST request, with a `query` key containing the GraphQL query document:\n\n```\n{\n  hero {\n    id\n    name\n  }\n}\n```\n\n\nThe `execute` function returns EDN data that can be easily converted to JSON.\nThe :data key contains the value requested for the `hero` query in the request.\n\n```clojure\n{:data\n  {:hero {:id 2000\n          :name \"Lando Calrissian\"}}}\n```\n\nThis example request has no errors, and contained only a single query.\nGraphQL supports multiple queries in a single request.\nThere may be errors executing the query, Lacinia will process as much as\nit can, and will report errors in the :errors key.\n\nOne of the benefits of GraphQL is that the client has the power to rename\nfields in the response:\n\n```\n{\n  hero(episode: NEWHOPE) {\n    movies: appearsIn\n  }\n}\n```\n\n```clojure\n{:data {:hero {:movies [:NEWHOPE :EMPIRE :JEDI]}}}\n```\n\nThis is just an overview, far more detail is available\nin [the manual](http://lacinia.readthedocs.io/en/latest/).\n\n## Status\n\nThis library has been used in production at Walmart since 2017, going through a very long\nbeta period as it evolved; we transitioned to a 1.0 release on 9 Oct 2021.\n\nTo use this library with Clojure 1.8, you must include \na dependency on [clojure-future-spec](https://github.com/tonsky/clojure-future-spec).\n\nMore details are [in the manual](http://lacinia.readthedocs.io/en/latest/clojure.html).\n\n## License\n\nCopyright © 2017-2023 WalmartLabs\n\nDistributed under the Apache License, Version 2.0.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwalmartlabs%2Flacinia","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwalmartlabs%2Flacinia","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwalmartlabs%2Flacinia/lists"}