{"id":13452588,"url":"https://github.com/grafoojs/grafoo","last_synced_at":"2025-10-03T01:30:42.148Z","repository":{"id":33115303,"uuid":"125933194","full_name":"grafoojs/grafoo","owner":"grafoojs","description":"A GraphQL Client and Toolkit","archived":true,"fork":false,"pushed_at":"2023-02-03T04:54:56.000Z","size":3589,"stargazers_count":274,"open_issues_count":9,"forks_count":9,"subscribers_count":12,"default_branch":"main","last_synced_at":"2025-01-14T18:59:11.981Z","etag":null,"topics":["babel-plugin","graphql","react","typesc","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/grafoojs.png","metadata":{"files":{"readme":"readme.md","changelog":"changelog.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-03-19T23:24:17.000Z","updated_at":"2024-07-22T23:38:53.000Z","dependencies_parsed_at":"2023-02-18T03:20:15.150Z","dependency_job_id":null,"html_url":"https://github.com/grafoojs/grafoo","commit_stats":null,"previous_names":[],"tags_count":62,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grafoojs%2Fgrafoo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grafoojs%2Fgrafoo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grafoojs%2Fgrafoo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grafoojs%2Fgrafoo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/grafoojs","download_url":"https://codeload.github.com/grafoojs/grafoo/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235059234,"owners_count":18929279,"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":["babel-plugin","graphql","react","typesc","typescript"],"created_at":"2024-07-31T07:01:28.365Z","updated_at":"2025-10-03T01:30:41.807Z","avatar_url":"https://github.com/grafoojs.png","language":"TypeScript","funding_links":[],"categories":["Libraries","TypeScript"],"sub_categories":["JavaScript Libraries"],"readme":"\u003ch1 align=center\u003e\n  \u003cbr /\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/grafoojs/grafoo/master/logo.svg\" alt=Grafoo /\u003e\n  \u003cbr /\u003e\n  \u003cbr /\u003e\n\u003c/h1\u003e\n\n\u003cp align=center\u003e\u003ci\u003eA GraphQL Client and Toolkit\u003c/i\u003e\u003c/p\u003e\n\n\u003cp align=center\u003e\n  \u003ca href=https://circleci.com/gh/grafoojs/grafoo\u003e\n    \u003cimg\n      src=https://img.shields.io/circleci/project/github/grafoojs/grafoo/master.svg?label=build\n      alt=build\n    /\u003e\n  \u003c/a\u003e\n  \u003ca href=https://codecov.io/github/grafoojs/grafoo\u003e\n    \u003cimg\n      src=https://img.shields.io/codecov/c/github/grafoojs/grafoo/master.svg\n      alt=\"coverage\"\n    /\u003e\n  \u003c/a\u003e\n  \u003ca href=https://github.com/grafoojs/grafoo\u003e\n    \u003cimg\n      src=https://img.shields.io/npm/v/@grafoo/babel-plugin.svg\n      alt=npm\n    \u003e\n  \u003c/a\u003e\n  \u003ca href=https://github.com/grafoojs/grafoo\u003e\n    \u003cimg\n      src=https://img.shields.io/npm/dm/@grafoo/babel-plugin.svg\n      alt=downloads\n    \u003e\n  \u003c/a\u003e\n  \u003ca href=https://prettier.io\u003e\n    \u003cimg\n      src=https://img.shields.io/badge/code_style-prettier-ff69b4.svg\n      alt=\"code style: prettier\"\n    /\u003e\n  \u003c/a\u003e\n  \u003ca href=https://lernajs.io\u003e\n    \u003cimg\n      src=https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg\n      alt=\"mantained with: lerna\"\n    /\u003e\n  \u003c/a\u003e\n  \u003ca href=https://grafoo-slack.herokuapp.com\u003e\n    \u003cimg\n      src=https://grafoo-slack.herokuapp.com/badge.svg\n      alt=\"slack\"\n    /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\nGrafoo is a GraphQL client that tries to be different by adopting a **simpler API**, without giving up of a **good caching strategy**.\n\n## Some useful information\n\n- **It's a multiple paradigm library**. So far we have **view layer integrations** for [react](https://github.com/grafoojs/grafoo/tree/master/packages/react) and [preact](https://github.com/grafoojs/grafoo/tree/master/packages/preact) and there are more to come.\n- **It's not just a HTTP client**. It comes with a sophisticated caching system under the hood to make sure your data is consistent across your app.\n- **It's build time dependent**. A important piece of Grafoo is it's **babel** plugin that compiles your queries based on the schema your app consumes.\n- **It's environment agnostic**. Apart from the browser you can run Grafoo on the **server** and even on **native** with react.\n\n## Why should I use this\n\nMany of the work that has been put into this project came from borrowed ideas and concepts that are present in the GraphQL clients we have today. Grafoo wants to stand apart from the others trying to be in that sweet spot between **simplicity** and **usability**. Moreover, most of the benefits this library brings to the table are related to the fact that it does a lot at build time. It's **fast**, because it spares runtime computation and it's really **small** (something like **~1.6kb** for core and react) because it does not ship with a GraphQL parser.\n\n## Example applications\n\nYou can refer to examples in [this repository](https://github.com/grafoojs/grafoo-examples).\n\n## Basic usage\n\n### Installation\n\nThe basic packages you'll have to install in order to use Grafoo are core and babel-plugin.\n\n```\n$ npm i @grafoo/core \u0026\u0026 npm i -D @grafoo/babel-plugin\n```\n\n### Configure babel\n\nIn `@grafoo/babel-plugin` the option `schema` is a path to a GraphQL schema in your file system relative to the root of your project and `idFields` is an array of strings that represent the fields that Grafoo will automatically insert on your queries to build unique identifiers in order to normalize the cache. **Both options are required**.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@grafoo/babel-plugin\",\n      {\n        \"schema\": \"schema.graphql\",\n        \"idFields\": [\"id\"]\n      }\n    ]\n  ]\n}\n```\n\n### Writing your app\n\nFrom `@grafoo/core` you will import the factory that creates the client instance and from submodule `@grafoo/core/tag` you'll import the `graphql` or `gql` tag that will be compiled at build time.\n\n```js\nimport createClient from \"@grafoo/core\";\nimport gql from \"@grafoo/core/tag\";\n\nfunction fetchQuery(query, variables) {\n  const init = {\n    method: \"POST\",\n    body: JSON.stringify({ query, variables }),\n    headers: {\n      \"content-type\": \"application/json\"\n    }\n  };\n\n  return fetch(\"http://some.graphql.api\", init).then(res =\u003e res.json());\n}\n\nconst client = createClient(fetchQuery);\n\nconst USER_QUERY = gql`\n  query($id: ID!) {\n    user(id: $id) {\n      name\n    }\n  }\n`;\n\nconst variables = { id: 123 };\n\nclient.execute(USER_QUERY, variables).then(data =\u003e {\n  // Write to cache\n  client.write(USER_QUERY, variables, data);\n\n  // Do whatever with returned data\n  console.log(data);\n\n  // Read from cache at a later stage\n  console.log(client.read(USER_QUERY, variables));\n});\n\n// If you wish to reset (clear) the cache:\nclient.reset();\n```\n\n### With a framework\n\nHere is how it would go for you to write a simple react app.\n\n#### `index.js`\n\n```jsx\nimport React from \"react\";\nimport ReactDom from \"react-dom\";\nimport createClient from \"@grafoo/core\";\nimport { Provider } from \"@grafoo/react\";\n\nimport Posts from \"./Posts\";\n\nfunction fetchQuery(query, variables) {\n  const init = {\n    method: \"POST\",\n    body: JSON.stringify({ query, variables }),\n    headers: {\n      \"content-type\": \"application/json\"\n    }\n  };\n\n  return fetch(\"http://some.graphql.api\", init).then(res =\u003e res.json());\n}\n\nconst client = createClient(fetchQuery);\n\nReactDom.render(\n  \u003cProvider client={client}\u003e\n    \u003cPosts /\u003e\n  \u003c/Provider\u003e,\n  document.getElementById(\"mnt\")\n);\n```\n\n#### `Posts.js`\n\n```jsx\nimport React from \"react\";\nimport gql from \"@grafoo/core/tag\";\nimport { Consumer } from \"@grafoo/react\";\n\nconst ALL_POSTS = gql`\n  query getPosts($orderBy: PostOrderBy) {\n    allPosts(orderBy: $orderBy) {\n      title\n      content\n      createdAt\n      updatedAt\n    }\n  }\n`;\n\nexport default function Posts() {\n  return (\n    \u003cConsumer query={ALL_POSTS} variables={{ orderBy: \"createdAt_DESC\" }}\u003e\n      {({ client, load, loaded, loading, errors, allPosts }) =\u003e (\n        \u003cmarquee\u003e👆 do whatever you want with the variables above 👆\u003c/marquee\u003e\n      )}\n    \u003c/Consumer\u003e\n  );\n}\n```\n\n### Mutations\n\n```jsx\nimport React from \"react\";\nimport gql from \"@grafoo/core/tag\";\nimport { Consumer } from \"@grafoo/react\";\n\nconst ALL_POSTS = gql`\n  query getPosts($orderBy: PostOrderBy) {\n    allPosts(orderBy: $orderBy) {\n      title\n      content\n      createdAt\n      updatedAt\n    }\n  }\n`;\n\nconst CREATE_POST = gql`\n  mutation createPost($content: String, $title: String, $authorId: ID) {\n    createPost(content: $content, title: $title, authorId: $authorId) {\n      title\n      content\n      createdAt\n      updatedAt\n    }\n  }\n`;\n\nconst mutations = {\n  createPost: {\n    query: CREATE_POST,\n    optimisticUpdate: ({ allPosts }, variables) =\u003e ({\n      allPosts: [{ ...variables, id: \"tempID\" }, ...allPosts]\n    }),\n    update: ({ allPosts }, data) =\u003e ({\n      allPosts: allPosts.map(p =\u003e (p.id === \"tempID\" ? data.createPost : p))\n    })\n  }\n};\n\nconst submit = mutate =\u003e event =\u003e {\n  event.preventDefault();\n\n  const { title, content } = event.target.elements;\n\n  mutate({ title: title.value, content: content.value });\n};\n\nexport default function PostForm() {\n  return (\n    \u003cConsumer query={ALL_POSTS} variables={{ orderBy: \"createdAt_DESC\" }} mutations={mutations}\u003e\n      {({ createPost }) =\u003e (\n        \u003cform onSubmit={submit(createPost)}\u003e\n          \u003cinput name=\"title\" /\u003e\n          \u003ctextarea name=\"content\" /\u003e\n          \u003cbutton\u003esubmit\u003c/button\u003e\n        \u003c/form\u003e\n      )}\n    \u003c/Consumer\u003e\n  );\n}\n```\n\n## LICENSE\n\n[MIT](https://github.com/grafoojs/grafoo/blob/master/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrafoojs%2Fgrafoo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgrafoojs%2Fgrafoo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrafoojs%2Fgrafoo/lists"}