{"id":35078652,"url":"https://github.com/bnert-land/graphql.kit","last_synced_at":"2026-04-25T01:38:50.708Z","repository":{"id":215801592,"uuid":"739788472","full_name":"bnert-land/graphql.kit","owner":"bnert-land","description":"Clojure GraphQL Toolkit","archived":false,"fork":false,"pushed_at":"2024-02-20T11:35:03.000Z","size":118,"stargazers_count":0,"open_issues_count":4,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-02-21T11:55:35.004Z","etag":null,"topics":["clojure","clojure-graphql","graphql","graphql-clojure"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bnert-land.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"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}},"created_at":"2024-01-06T14:49:23.000Z","updated_at":"2024-01-14T19:46:39.000Z","dependencies_parsed_at":"2024-02-20T11:49:57.666Z","dependency_job_id":"86c3e99c-a4a4-4aee-97cb-ec3e98084ee1","html_url":"https://github.com/bnert-land/graphql.kit","commit_stats":null,"previous_names":["bnert-land/graphql.kit"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bnert-land/graphql.kit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bnert-land%2Fgraphql.kit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bnert-land%2Fgraphql.kit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bnert-land%2Fgraphql.kit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bnert-land%2Fgraphql.kit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bnert-land","download_url":"https://codeload.github.com/bnert-land/graphql.kit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bnert-land%2Fgraphql.kit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28078608,"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","status":"online","status_checked_at":"2025-12-27T02:00:05.897Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","clojure-graphql","graphql","graphql-clojure"],"created_at":"2025-12-27T12:35:48.887Z","updated_at":"2025-12-27T12:35:49.320Z","avatar_url":"https://github.com/bnert-land.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg style=\"border-radius: 8px;\" src=\"./assets/graphql.kit.png\" align=\"center\"\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n    GraphQL for Clojure Ring Implementations\n\u003c/p\u003e\n\n## Motivation\n\nFor those who don't want to use pedestal, or merely prefer other web servers,\nthis one's for you :cheers:.\n\nThis README is still a todo, there is a bit to document.\nBut between what is here and the [examples](./examples), is enough to work off of for the curious.\n\n\n## Quick Start\n\n### Install\nOnce there is more rigor (i.e. test suite) applied to the code in this repo,\na clojars release will be supported. Until then, if you're a trail blazer:\n```clojure\nland.bnert/graphql.kit {:git/url \"https://github.com/bnert-land/graphql.kit\"\n                        :git/sha \"...\"}\n```\n\n### Write Your App (Service/Easy)\nIf you're starting a new GraphQL project, and don't need to hook into an\nexisting web stack, you can choose to use the prebuilt \"service\" interface:\n```clojure\n(ns app.core\n  (:require\n    [graphql.kit :as kit]))\n\n\n(defn -main [\u0026 _args]\n  (kit/service!\n    {:graphiql {:enabled?        true\n                :url             \"http://localhost:9109/graphql\"\n                :subscriptionUrl \"ws://localhost:9109/graphql/subscribe\"}\n     :endpoints {:graphiql  \"/graphiql\"\n                 :http      \"/graphql\"\n                 :websocket \"/graphql/subscribe\"}\n     ; There is a default \"middleware chain\". The main responsibility\n     ; is to parse query params and json as well as negotiate resposne content/format.\n     ;\n     ; Therefore, the resulting middleware execution will look like:\n     ;\n     ; logger -\u003e parsing -\u003e  logger -\u003e health-check -\u003e root-handler\n     ;\n     :middleware {:prepend [(logger \"PREPEND\u003e\")]\n                  :append  [(logger \"APPEND\u003e\") (health-check \"/health\")]}\n     :scalars   {:UUID {:parse     #(when (string? %) (parse-uuid %))\n                        :serialize str}}\n     :resolvers {:query\n                 ; Assuming each of these functions map to a resolver fn\n                 {:Mutation/addDroid add-droid\n                  :Mutation/addHuman add-human\n                  :Query/droid       droid\n                  :Query/droids      droids\n                  :Query/human       human\n                  :Query/humans      humans\n                  :Query/hero        hero\n                  :Query/heros       heros}\n                 :subscription\n                 {:Subscription/eventsevents}}\n     :server    {:port 9109}\n     ; Assuming an 'edn' schema is a resource on the classpath\n     :schema    {:resource \"graphql/schema/star-wars.edn\"}}))\n\n```\nSee [the \"easy\" example](./examples/easy/), which implements the above.\n\n### Write Your App (Piecemeal)\nThe below app example is assuming you're definig your schema as edn as a resource:\n```clojure\n(ns app.core\n  (:require\n    [aleph.http :as http]\n    [graphql.kit.engines.lacinia :as kit.engine]\n    [graphql.kit.loaders.edn :as kit.loader]\n    [graphql.kit.servers.aleph.ws :as kit.ws]\n    [graphql.kit.servers.ring.http :as kit.http]\n    [graphql.kit.servers.ring.graphiql :as kit.graphiql]\n    [ring.middleware.keyword-params :as mw.keyword-params]\n    [ring.middleware.params :as mw.params]\n    [ring.middleware.json :as mw.json]))\n\n(def port 9109)\n\n(def kit-config\n  {:graphql.kit/engine (kit.engine/engine!)\n   :graphql.kit/loader (kit.loader/loader!)\n\n   ; Every config option w/o a :graphql.kit namespace is passed to\n   ; the underlying graphql engine\n   ;\n\n   ; The `:options` are passed as options to Lacinia.\n   ; You could use a manifold executor instead of the default\n   ; thread pool.\n   :options  {#_#_:executor (manifold.executor/execute-pool)}\n\n   ; Schema can be\n   ;   1. A map w/ `:resource` key. The path of the `:resource` key will be loaded using `:graphql.kit/loader`.\n   ;   2. A map w/ `:path` key. The path will load a file using `:graphql.kit/loader`\n   ;   3. A map w/o a `:path` or `:resource` key will be treated as a schema\n   ;   4. A string, which signals that the schema is in SDL format.\n   :schema   {:resource \"graphql/schema.edn\"}\n\n   ; Resolvers have some extra structure, will go into more detail about the specifics of the lacinia\n   ; engine at a later point in the docs.\n   :resolvers\n   {:query        {:Query/thing resolve-thing}\n    :subscription {:Subscription/events subscribe-to-events}}\n\n(def http-handler\n  (kit.http/handler kit-config))\n\n(def ws-handler\n  (kit.ws/handler kit-config))\n\n(def graphiql-handler\n  (kit.graphiql/handler\n    {:enabled? true ; defaults to false\n     :url             \"http://localhost:9109/graphql\"\n     :subscriptionUrl \"ws://localhost:9109/graphql/subscribe\"}))\n\n(defn app [{:keys [request-method uri] :as req}]\n  (case [request-method uri]\n    [:get \"/graphql\"]\n      (http-handler req)\n    [:post \"/graphql\"]\n      (http-handler req)\n    [:get \"/graphql/subscribe\"]\n      (ws-handler req)\n    [:get \"/graphiql\"]\n      (graphiql-handler req)\n    #_default\n      {:status 404}))\n\n(defn -main [\u0026 args]\n  (println (format \"Starting server @ http://localhost:%s\" port))\n  (http/start-server\n    (-\u003e app\n        (mw.json/wrap-json-response)\n        (mw.keyword-params/wrap-keyword-params)\n        (mw.params/wrap-params)\n        (mw.json/wrap-json-params))\n    {:port port}))\n```\n\n## Examples\n\n- [Aleph w/ Lacinia Engine, GraphiQL](./examples/aleph/)\n- [Ring Jetty w/ Lacinia Engine, GraphiQL](./examples/ring-jetty)\n- [Service/Easy API](./examples/easy)\n- [Service/Easy API Using GraphQL Schema SDL](./examples/easy-sdl)\n- **TODO** Fullstack using the two above w/ Apollo Client\n- **TODO** TodoMVC\n- **TODO** Chat app\n\n\n## Concepts\n### Engines\n\nIn the context of `graphql.kit`, an \"engine\" is responsible for compiling a GraphQL schema\nand executing queries, subscriptions, and coorindating resolving values.\n\nCurrent engine implementations:\n| Name                                              | Compliant w/ GraphQL Spec | Compliant w/ Apollo Federation |\n|:--------------------------------------------------|:--------------------------|:-------------------------------|\n| [Lacinia](https://github.com/walmartlabs/lacinia) | yes                       | yes, only w/ SDL               |\n\n\nIn order to provide a well featured library, and given this library is in early stages,\nthe focus is on integrating [Lacinia](https://github.com/walmartlabs/lacinia).\n\nOther Clojure or Java based GraphQL engines may be integrated, however, that is\nnot the focus at this time.\n\nThere is an [engine protocol](https://github.com/bnert-land/graphql.kit/blob/main/src/graphql/kit/protos/engine.clj), which when satistfied can plug into `graphql.kit`.\n\n\n### Loaders\n\nA \"loader\" is responsible for loading a GraphQL schema. The current loaders are:\n\n- [Default](https://github.com/bnert-land/graphql.kit/blob/main/src/graphql/kit/loaders/default.clj), which simply reads a file from either a file path or resource.\n- [EDN](https://github.com/bnert-land/graphql.kit/blob/main/src/graphql/kit/loaders/edn.clj), which reads file content from either the path or resource and parses the file into Clojure data structure.\n- [Aero](https://github.com/bnert-land/graphql.kit/blob/main/src/graphql/kit/loaders/aero.clj) does everything that the EDN loader does, but also provides all the functionality exposed by Aero when reading configuration.\n  - ~~The Aero loader requires a peer dependency of [`juxt/aero`](https://github.com/juxt/aero)~~ `aero` is currently included. It will be \"unbundled\" when a first release is cut.\n\nIf none of the above are satisfactory, there is a [loader protocol](https://github.com/bnert-land/graphql.kit/blob/main/src/graphql/kit/protos/loader.clj) which can be implemented and plugged into `graphql.kit`.\n\n\n### Handlers\n\nA \"handler\" is higher order function which takes a configuration map and produces a\nring compliant handler.\n\nCurrent handler implementaions:\n- GraphQL over HTTP\n  - Ring Compliant Servers\n- [GraphQL over WebSocket](#one)\n  - Aleph\n  - Ring Compliant Servers, as of [1.11.0 spec](#two)\n- [Graphql over SSE](#three)\n  - None right now\n\n\n## References\n\n- \u003ca id=\"one\"\u003e[1]:\u003c/a\u003e [GraphQL over WebSocket Spec](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md)\n- \u003ca id=\"two\"\u003e[2]:\u003c/a\u003e [Ring 1.11.0 WebSocket Spec](https://github.com/ring-clojure/ring/blob/master/SPEC.md#3-websockets)\n- \u003ca id=\"three\"\u003e[3]:\u003c/a\u003e [GraphQL over Server-Sent Events Spec](https://github.com/enisdenjo/graphql-sse/blob/master/PROTOCOL.md)\n\n\n---\n\nCopyright (c) Brent Soles. All rights reserved.\n\nSee [LICENSE](./LICENSE) for license information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbnert-land%2Fgraphql.kit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbnert-land%2Fgraphql.kit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbnert-land%2Fgraphql.kit/lists"}