{"id":13941829,"url":"https://github.com/schloerke/gqlr","last_synced_at":"2025-03-16T13:31:20.230Z","repository":{"id":56936675,"uuid":"46367106","full_name":"schloerke/gqlr","owner":"schloerke","description":"R GraphQL Implementation","archived":false,"fork":false,"pushed_at":"2023-01-08T02:43:01.000Z","size":2538,"stargazers_count":58,"open_issues_count":3,"forks_count":3,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-02-27T09:44:21.758Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://schloerke.com/gqlr/","language":"JavaScript","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/schloerke.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}},"created_at":"2015-11-17T18:33:08.000Z","updated_at":"2024-09-24T03:33:54.000Z","dependencies_parsed_at":"2023-02-08T04:32:18.789Z","dependency_job_id":null,"html_url":"https://github.com/schloerke/gqlr","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schloerke%2Fgqlr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schloerke%2Fgqlr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schloerke%2Fgqlr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schloerke%2Fgqlr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/schloerke","download_url":"https://codeload.github.com/schloerke/gqlr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243817082,"owners_count":20352497,"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":[],"created_at":"2024-08-08T02:01:30.530Z","updated_at":"2025-03-16T13:31:19.627Z","avatar_url":"https://github.com/schloerke.png","language":"JavaScript","funding_links":[],"categories":["Libraries","Implementations","JavaScript"],"sub_categories":["R Libraries","R (Rstat)"],"readme":"#  gqlr: A GraphQL Implementation in R\n\u003c!-- badges: start --\u003e\n[![R-CMD-check](https://github.com/schloerke/gqlr/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/schloerke/gqlr/actions/workflows/R-CMD-check.yaml)\n[![Coverage Status](https://codecov.io/github/schloerke/gqlr/coverage.svg?branch=master)](https://codecov.io/github/schloerke/gqlr?branch=master)\n[![CRAN status](https://www.r-pkg.org/badges/version/gqlr)](https://CRAN.R-project.org/package=gqlr)\n[![CRAN Downloads](https://cranlogs.r-pkg.org/badges/gqlr)](https://cran.r-project.org/package=gqlr)\n\u003c!-- badges: end --\u003e\n\n\n\n## Overview\n\nGraphQL is a data \"query language created by Facebook in 2015 for describing the capabilities and requirements of data models for client‐server applications\".  The [GraphQL specification can be read on their hosted GitHub](https://graphql.github.io/graphql-spec/). A [cliff notes version is described on GraphQL's GitHub](https://github.com/graphql/graphql-spec). To learn more about the GraphQL language, I highly recommend [GraphQL's website](http://graphql.org/learn/).\n\nThis package pulls inspiration from [graphql-js](https://github.com/graphql/graphql-js) and [Mathew Mueller's graph.ql](https://github.com/matthewmueller/graph.ql). I wanted the full functionality of GraphQL, but I didn't want to force users to write full object definitions when can already be defined with GraphQL syntax.\n\n`gqlr` merges R's rapid development speed with the consistent query language of GraphQL.\n\n\n## Installation\n\n```r\n# The development version from GitHub:\n# install.packages(\"devtools\")\ndevtools::install_github(\"schloerke/gqlr\")\n```\n\nIf you encounter a clear bug, please file a minimal reproducible example on [GitHub](https://github.com/schloerke/gqlr/issues).\n\n\n## Usage\n\n### Hello World\n\n```r\n\nlibrary(magrittr)\nlibrary(gqlr)\n\nschema \u003c- \"\n  type Hello {\n    world: String\n  }\n  schema {\n    query: Hello\n  }\n\" %\u003e%\n  gqlr_schema()\n\nexecute_request(\"{world}\", schema, initial_value = list(world = \"Hi!\"))\n# {\n#   \"data\": {\n#     \"world\": \"Hi!\"\n#   }\n# }\n```\n\n### Star Wars\n\n#### Star Wars Data\n\n```r\nadd_human \u003c- function(human_data, id, name, appear, home, friend) {\n  human \u003c- list(id = id, name = name, appearsIn = appear, friends = friend, homePlanet = home)\n  # set up a function to be calculated if the field totalCredits is required\n  human$totalCredits \u003c- function(obj, args, schema) {\n    length(human$appearsIn)\n  }\n  human_data[[id]] \u003c- human\n  human_data\n}\nadd_droid \u003c- function(droid_data, id, name, appear, pf, friend) {\n  droid \u003c- list(id = id, name = name, appearsIn = appear, friends = friend, primaryFunction = pf)\n  # set extra fields manually\n  droid$totalCredits \u003c- length(droid$appearsIn)\n  droid_data[[id]] \u003c- droid\n  droid_data\n}\n\nhuman_data \u003c- list() %\u003e%\n  add_human(\"1000\", \"Luke Skywalker\", c(4, 5, 6), \"Tatooine\", c(\"1002\", \"1003\", \"2000\", \"2001\")) %\u003e%\n  add_human(\"1002\", \"Han Solo\",       c(4, 5, 6), \"Corellia\", c(\"1000\", \"1003\", \"2001\")) %\u003e%\n  add_human(\"1003\", \"Leia Organa\",    c(4, 5, 6), \"Alderaan\", c(\"1000\", \"1002\", \"2000\", \"2001\"))\n\ndroid_data \u003c- list() %\u003e%\n  add_droid(\"2000\", \"C-3PO\", c(4, 5, 6), \"Protocol\", c(\"1000\", \"1002\", \"1003\", \"2001\")) %\u003e%\n  add_droid(\"2001\", \"R2-D2\", c(4, 5, 6), \"Astromech\", c(\"1000\", \"1002\", \"1003\"))\n\nall_characters \u003c- list() %\u003e% append(human_data) %\u003e% append(droid_data)\nall_characters[[1]]\n# $id\n# [1] \"1000\"\n#\n# $name\n# [1] \"Luke Skywalker\"\n#\n# $appearsIn\n# [1] 4 5 6\n#\n# $friends\n# [1] \"Tatooine\"\n#\n# $homePlanet\n# [1] \"1002\" \"1003\" \"2000\" \"2001\"\n#\n# $totalCredits\n# function (obj, args, schema)\n# {\n#     length(human$appearsIn)\n# }\n# \u003cenvironment: 0x7fadd8ca2038\u003e\n```\n\n\n#### Star Wars Schema\n```r\n\"\nenum Episode { NEWHOPE, EMPIRE, JEDI }\n\ninterface Character {\n  id: String!\n  name: String\n  friends: [Character]\n  appearsIn: [Episode]\n}\n\ntype Droid implements Character {\n  id: String!\n  name: String\n  friends: [Character]\n  appearsIn: [Episode]\n  primaryFunction: String\n}\ntype Human implements Character {\n  id: String!\n  name: String\n  friends: [Character]\n  appearsIn: [Episode]\n  homePlanet: String\n}\n\ntype Query {\n  hero(episode: Episode): Character\n  human(id: String!): Human\n  droid(id: String!): Droid\n}\n# the schema type must be provided if a query or mutation is to be executed\nschema {\n  query: Query\n}\n\" %\u003e%\n  gqlr_schema(\n    Episode = list(\n      resolve = function(episode_id, schema) {\n        switch(as.character(episode_id),\n          \"4\" = \"NEWHOPE\",\n          \"5\" = \"EMPIRE\",\n          \"6\" = \"JEDI\",\n          \"UNKNOWN_EPISODE\"\n        )\n      }\n    ),\n    Character = list(\n      resolve_type = function(id, schema) {\n        ifelse(id %in% names(droid_data), \"Droid\", \"Human\")\n      }\n    ),\n    Human = list(\n      # Add a resolve method for type Human that takes in an id and returns the human data\n      resolve = function(id, args, schema) {\n        human_data[[id]]\n      }\n    ),\n    Droid = list(\n      # description for Droid\n      description = \"A mechanical creature in the Star Wars universe.\",\n      # Add a resolve method for type Droid that takes in an id and returns the droid data\n      resolve = function(id, schema) {\n        droid_data[[id]]\n      }\n    ),\n    Query = function(null, schema) {\n      list(\n        # return a function for key 'hero'\n        # the id will be resolved by the appropriate resolve() method of Droid or Human\n        hero = function(obj, args, schema) {\n          episode \u003c- args$episode\n          if (identical(episode, 5) || identical(episode, \"EMPIRE\")) {\n            \"1000\" # Luke\n          } else {\n            \"2001\" # R2-D2\n          }\n        },\n        # the id will be resolved by the Human resolve() method\n        human = function(obj, args, schema) {\n          args$id\n        },\n        # the id will be resolved by the Droid resolve() method\n        droid = function(obj, args, schema) {\n          args$id\n        }\n      )\n    }\n  ) -\u003e\nstar_wars_schema\n```\n\n#### Star Wars Execution\n\n```r\n# Use the resolve method to initialize the data\n\"\n{\n  hero {\n    id\n    name\n    friends {\n      id\n      name\n    }\n  }\n}\n\" %\u003e%\n  execute_request(star_wars_schema)\n# {\n#   \"data\": {\n#     \"hero\": {\n#       \"id\": \"2001\",\n#       \"name\": \"R2-D2\",\n#       \"friends\": [\n#         {\n#           \"id\": \"1000\",\n#           \"name\": \"Luke Skywalker\"\n#         },\n#         {\n#           \"id\": \"1002\",\n#           \"name\": \"Han Solo\"\n#         },\n#         {\n#           \"id\": \"1003\",\n#           \"name\": \"Leia Organa\"\n#         }\n#       ]\n#     }\n#   }\n# }\n\n\n# Use variables...\n\"\nquery FetchSomeIDQuery($someId: String!) {\n  human(id: $someId) {\n    name\n  }\n}\n\" %\u003e%\n  execute_request(star_wars_schema, variables = list(someId = \"1000\"))\n# {\n#   \"data\": {\n#     \"human\": {\n#       \"name\": \"Luke Skywalker\"\n#     }\n#   }\n# }\n\n\n# Introspection\n\"\nquery IntrospectionTypeQuery {\n  __type(name: \\\"Droid\\\") {\n    kind\n    name\n    fields {\n      name\n    }\n  }\n}\n\" %\u003e%\n  execute_request(star_wars_schema)\n# {\n#   \"data\": {\n#     \"__type\": {\n#       \"kind\": \"OBJECT\",\n#       \"name\": \"Droid\",\n#       \"fields\": [\n#         {\n#           \"name\": \"id\"\n#         },\n#         {\n#           \"name\": \"name\"\n#         },\n#         {\n#           \"name\": \"friends\"\n#         },\n#         {\n#           \"name\": \"appearsIn\"\n#         },\n#         {\n#           \"name\": \"primaryFunction\"\n#         },\n#         {\n#           \"name\": \"__typename\"\n#         }\n#       ]\n#     }\n#   }\n# }\n```\n\n\n#### Star Wars Server\n```r\n# R\ngqlr:::server(star_wars_schema, log = TRUE) # forgot to export\n```\n\nExplore with `curl`\n```bash\n\n# GET R2-D2 and his friends' names\ncurl '127.0.0.1:8000/graphql?query=%7Bhero%7Bname%7D%7D\u0026pretty=TRUE'\n# {\n#   \"data\": {\n#     \"hero\": {\n#       \"name\": \"R2-D2\"\n#     }\n#   }\n# }\n\n# POST for R2-D2 and his friends' names (no need to url escape the query)\ncurl --data '{\"query\":\"{hero{name}}\"}' '127.0.0.1:8000/graphql' # defaults to parse as JSON\n# {\"data\":{\"hero\":{\"name\":\"R2-D2\"}}}\n\ncurl --data '{\"query\":\"{hero{name}}\"}' '127.0.0.1:8000/graphql' --header \"Content-Type:application/json\"\n# {\"data\":{\"hero\":{\"name\":\"R2-D2\"}}}\n\ncurl --data '{hero{name}}' '127.0.0.1:8000/graphql' --header \"Content-Type:application/graphql\"\n# {\"data\":{\"hero\":{\"name\":\"R2-D2\"}}}\n\n\n# GET Schema definition\ncurl '127.0.0.1:8000/'\n# enum Episode {\n#   NEWHOPE\n#   EMPIRE\n#   JEDI\n# }\n#\n# type Droid implements Character {\n#   id: String!\n#   name: String\n#   friends: [Character]\n#   appearsIn: [Episode]\n#   primaryFunction: String\n# }\n#\n# type Human implements Character {\n#   id: String!\n#   name: String\n#   friends: [Character]\n#   appearsIn: [Episode]\n#   homePlanet: String\n# }\n#\n# type Query {\n#   hero(episode: Episode): Character\n#   human(id: String!): Human\n#   droid(id: String!): Droid\n# }\n#\n# interface Character {\n#   id: String!\n#   name: String\n#   friends: [Character]\n#   appearsIn: [Episode]\n# }\n#\n# schema {\n#   query: Query\n# }\n```\n\n\n## Presentations\n\n[WOMBAT2016 in Melbourne, Australia; Feb 2016](https://github.com/schloerke/presentation-2016_02_18-graphql/blob/master/GraphQL-Wombat-2016-Barret.pdf).\n\n\n## Other R GraphQL related packages\n\n* [graphql](https://github.com/ropensci/graphql)\n    * Bindings to libgraphqlparser for R.\n    * `gqlr` uses this package to parse all requests strings and schema strings into json\n* [ghql](https://github.com/ropensci/ghql)\n    * General purpose GraphQL client\n    * The `ghql` client could be used to submit requests to `gqlr` server to be executed\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fschloerke%2Fgqlr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fschloerke%2Fgqlr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fschloerke%2Fgqlr/lists"}