{"id":15641631,"url":"https://github.com/oliyh/lacinia-gen","last_synced_at":"2025-04-13T12:25:13.630Z","repository":{"id":62433276,"uuid":"123464383","full_name":"oliyh/lacinia-gen","owner":"oliyh","description":"Generators for GraphQL","archived":false,"fork":false,"pushed_at":"2018-09-23T10:54:09.000Z","size":27,"stargazers_count":70,"open_issues_count":5,"forks_count":5,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-27T03:22:47.521Z","etag":null,"topics":["clojure","clojurescript","generative","graphql","lacinia"],"latest_commit_sha":null,"homepage":null,"language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oliyh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-03-01T16:53:12.000Z","updated_at":"2024-05-31T07:50:24.000Z","dependencies_parsed_at":"2022-11-01T21:15:31.210Z","dependency_job_id":null,"html_url":"https://github.com/oliyh/lacinia-gen","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oliyh%2Flacinia-gen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oliyh%2Flacinia-gen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oliyh%2Flacinia-gen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oliyh%2Flacinia-gen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oliyh","download_url":"https://codeload.github.com/oliyh/lacinia-gen/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246162090,"owners_count":20733350,"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","clojurescript","generative","graphql","lacinia"],"created_at":"2024-10-03T11:44:03.059Z","updated_at":"2025-03-29T08:31:35.349Z","avatar_url":"https://github.com/oliyh.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# lacinia-gen\n\n`lacinia-gen` lets you generate GraphQL responses using your [lacinia](https://github.com/walmartlabs/lacinia) schema\nand GraphQL queries, allowing you to make your tests more rigorous in both Clojure and Clojurescript.\n\n[![Clojars Project](https://img.shields.io/clojars/v/lacinia-gen.svg)](https://clojars.org/lacinia-gen)\n\n## Usage\n\nThere are two main ways to use `lacinia-gen`:\n - [Full graph](#full-graph) generates the entire graph from any entry point\n - [Query result](#query-result) generates a response for a particular query\n\n### Full graph\n\nYou can create a generator for a full graph from any root by using the `generator` function in\n`lacinia-gen.core`. This resolves all reachable nodes in the graph up to the desired recursion depth.\n\n```clojure\n(require '[lacinia-gen.core :as lgen])\n(require '[clojure.test.check.generators :as g])\n\n(let [schema {:enums {:position {:values [:goalkeeper :defence :attack]}}\n              :objects {:team {:fields {:wins {:type 'Int}\n                                        :losses {:type 'Int}\n                                        :players {:type '(list :player)}}}\n                        :player {:fields {:name {:type 'String}\n                                          :age {:type 'Int}\n                                          :position {:type :position}}}}}]\n\n  (let [gen (lgen/generator schema)]\n\n    (g/sample (gen :position) 5)\n    ;; =\u003e (:defence :goalkeeper :defence :goalkeeper :goalkeeper)\n\n    (g/sample (gen :player) 5)\n    ;; =\u003e ({:name \"\", :age 0, :position :attack}\n           {:name \"\", :age 0, :position :attack}\n           {:name \"\", :age 1, :position :attack}\n           {:name \"m\", :age -2, :position :defence}\n           {:name \"¤\", :age 4, :position :defence})\n\n    (g/sample (gen :team) 5)\n    ;; =\u003e ({:wins 0, :losses 0, :players ()}\n           {:wins 1,\n            :losses 1,\n            :players ({:name \"\u001b\", :age -1, :position :defence})}\n           {:wins 1,\n            :losses 2,\n            :players\n            ({:name \"\", :age 1, :position :attack}\n             {:name \"q\", :age -2, :position :attack})}\n           {:wins -3, :losses 1, :players ()}\n           {:wins 0,\n            :losses -3,\n            :players\n            ({:name \"ßéÅ\", :age 3, :position :attack}\n             {:name \"\", :age -4, :position :defence})})))\n```\n\nIt supports recursive graphs, so the following works too:\n\n```clojure\n(let [schema {:objects {:team {:fields {:name {:type 'String}\n                                        :players {:type '(list :player)}}}\n                        :player {:fields {:name {:type 'String}\n                                          :team {:type :team}}}}}]\n\n    (let [gen (lgen/generator schema)]\n      (g/sample (gen :team) 5)))\n\n;; =\u003e {:name \"\u001aö\",\n       :players\n       ({:name \"³2\",\n         :team\n         {:name \"º\u0002N\",\n          :players\n          ({:name \"Ïâ¦\", :team {:name \"¤¼J\"}}\n           {:name \"o\", :team {:name \"æ8\"}}\n           {:name \"/ç\", :team {:name \"ãL\"}}\n           {:name \"éíª6\", :team {:name \"v\"}})}}\n```\n\nIf you want to limit the depth to which certain objects recurse, you can do so with the following option:\n\n```clojure\n(lgen/generator schema {:depth {:team 0}})\n```\n\nThis will ensure that `:team` only appears once in the graph; the team will have players, but it prevents the players from having a team.\nThe default value for all objects is 1, meaning each will recur once (a team will have players which have a team which has players, but no further).\nYou can set any integer value you wish.\n\nIf you want to limit the number of items in lists, you can do so with the following option:\n\n```clojure\n(lgen/generator schema {:width {:player 2}})\n```\n\nThis will ensure that lists of `:player` will have a maximum size of 2.\n\n### Query result\n\nIf you have a GraphQL query and wish to generate data for its result, you can use `lacinia-gen.query`.\n\n```clojure\n(require '[lacinia-gen.query :as query])\n\n(def schema '{:enums {:position {:values [:goalkeeper :defence :attack]}}\n              :objects {:team {:fields {:wins {:type Int}\n                                        :losses {:type Int}\n                                        :players {:type (list :player)}}}\n                        :player {:fields {:name {:type String}\n                                          :age {:type Int}\n                                          :position {:type :position}}}}\n              :queries {:teams {:type (list :team)\n                                :resolve :resolve-teams}}})\n\n(let [f (query/generate-fn schema {})]\n    (f \"query { teams { wins players { name } } }\" {}))\n\n;; =\u003e {:data\n       {:teams\n        ({:wins 0, :players ()}\n         {:wins 0, :players ({:name \"\"})}\n         {:wins 1, :players ()}\n         {:wins 0, :players ({:name \"÷ \"} {:name \"\u0015¢\u0012\"})}\n         {:wins 1, :players ()})}}\n```\n\nCurrently the queries are interpreted by Lacinia and as such require the JVM. This means\n`generate-fn` cannot be used from Clojurescript. The two macros `generate-query` and\n`generate-query*` may be used in Clojurescript and will evaluate to the generated result\nof the query.\n\n```clojure\n(ns my.test\n  (:require-macros [lacinia-gen.query :refer [generate-data*]]))\n\n(def schema '{:objects {:team {:fields {:wins {:type Int}\n                                        :losses {:type Int}}}}\n              :queries {:teams {:type (list :team)\n                                :resolve :resolve-teams}}})\n\n(def query \"query { teams { wins } }\")\n\n(def data (generate-data* schema query {} {}))\n\ndata\n;; =\u003e {:data\n       {:teams\n        ({:wins 0}\n         {:wins 0}\n         {:wins 0)}\n         {:wins -3}\n         {:wins 0})}\n```\n\n### Custom scalars\n\nIf your schema contains [custom scalars](http://lacinia.readthedocs.io/en/latest/custom-scalars.html) you will need to\nprovide generators for them. You can do so in the following way:\n\n```clojure\n(let [schema {:scalars {:Custom {:parse :parse-custom\n                                 :serialize :serialize-custom}}\n              :objects {:obj-with-custom\n                        {:fields\n                         {:custom {:type :Custom}\n                          :custom-list {:type '(list :Custom)}}}}}]\n\n  (let [gen (lgen/generator schema {:scalars {:Custom gen/int}})]\n    (g/sample (gen :obj-with-custom) 10)))\n\n;; =\u003e {:custom 23\n       :custom-list (-1 4 16)}\n```\n\n## Development\n\n[![CircleCI](https://circleci.com/gh/oliyh/lacinia-gen.svg?style=svg)](https://circleci.com/gh/oliyh/lacinia-gen)\n\n## License\n\nCopyright © 2018 oliyh\n\nDistributed under the Eclipse Public License either version 1.0 or (at\nyour option) any later version.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foliyh%2Flacinia-gen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foliyh%2Flacinia-gen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foliyh%2Flacinia-gen/lists"}