Giter VIP home page Giter VIP logo

grafoo's Introduction

Grafoo

A GraphQL Client and Toolkit

build coverage npm downloads code style: prettier mantained with: lerna

Grafoo is a GraphQL client that tries to be different by adopting a simpler API, without giving up of a good caching strategy.

Some useful information

  • It's a multiple paradigm library. So far we have view layer integrations for react and preact and there are more to come.
  • 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.
  • 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.
  • It's environment agnostic. Apart from the browser you can run Grafoo on the server and even on native with react.

Why should I use this

Many 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.

Example applications

You can refer to examples in this repository.

Basic usage

Installation

The basic packages you'll have to install in order to use Grafoo are core and babel-plugin.

$ npm i @grafoo/core && npm i -D @grafoo/babel-plugin

Configure babel

In @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.

{
  "plugins": [
    [
      "@grafoo/babel-plugin",
      {
        "schema": "schema.graphql",
        "idFields": ["id"]
      }
    ]
  ]
}

Writing your app

From @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.

import createClient from "@grafoo/core";
import gql from "@grafoo/core/tag";

function fetchQuery(query, variables) {
  const init = {
    method: "POST",
    body: JSON.stringify({ query, variables }),
    headers: {
      "content-type": "application/json"
    }
  };

  return fetch("http://some.graphql.api", init).then(res => res.json());
}

const client = createClient(fetchQuery);

const USER_QUERY = gql`
  query($id: ID!) {
    user(id: $id) {
      name
    }
  }
`;

const variables = { id: 123 };

client.request(USER_QUERY, variables).then(data => {
  client.write(USER_QUERY, variables, data);

  console.log(client.read(USER_QUERY, variables));
});

With a framework

Here is how it would go for you to write a simple react app.

index.js

import React from "react";
import ReactDom from "react-dom";
import createClient from "@grafoo/core";
import { Provider } from "@grafoo/react";

import Posts from "./Posts";

function fetchQuery(query, variables) {
  const init = {
    method: "POST",
    body: JSON.stringify({ query, variables }),
    headers: {
      "content-type": "application/json"
    }
  };

  return fetch("http://some.graphql.api", init).then(res => res.json());
}

const client = createClient(fetchQuery);

ReactDom.render(
  <Provider client={client}>
    <Posts />
  </Provider>,
  document.getElementById("mnt")
);

Posts.js

import React from "react";
import gql from "@grafoo/core/tag";
import { Consumer } from "@grafoo/react";

const ALL_POSTS = gql`
  query getPosts($orderBy: PostOrderBy) {
    allPosts(orderBy: $orderBy) {
      title
      content
      createdAt
      updatedAt
    }
  }
`;

export default function Posts() {
  return (
    <Consumer query={ALL_POSTS} variables={{ orderBy: "createdAt_DESC" }}>
      {({ client, load, loaded, loading, errors, allPosts }) => (
        <h1>
          <marquee>๐Ÿ‘† do whatever you want with the variables above ๐Ÿ‘†</marquee>
        </h1>
      )}
    </Consumer>
  );
}

Mutations

import React from "react";
import gql from "@grafoo/core/tag";
import { Consumer } from "@grafoo/react";

const ALL_POSTS = gql`
  query getPosts($orderBy: PostOrderBy) {
    allPosts(orderBy: $orderBy) {
      title
      content
      createdAt
      updatedAt
    }
  }
`;

const CREATE_POST = gql`
  mutation createPost($content: String, $title: String, $authorId: ID) {
    createPost(content: $content, title: $title, authorId: $authorId) {
      title
      content
      createdAt
      updatedAt
    }
  }
`;

const mutations = {
  createPost: {
    query: CREATE_POST,
    optimisticUpdate: ({ allPosts }, variables) => ({
      allPosts: [{ ...variables, id: "tempID" }, ...allPosts]
    }),
    update: ({ allPosts }, data) => ({
      allPosts: allPosts.map(p => (p.id === "tempID" ? data.createPost : p))
    })
  }
};

const submit = mutate => event => {
  event.preventDefault();

  const { title, content } = event.target.elements;

  mutate({ title: title.value, content: content.value });
};

export default function PostForm() {
  return (
    <Consumer query={ALL_POSTS} variables={{ orderBy: "createdAt_DESC" }} mutations={mutations}>
      {({ createPost }) => (
        <form onSubmit={submit(createPost)}>
          <input name="title" />
          <textarea name="content" />
          <button>submit</button>
        </form>
      )}
    </Consumer>
  );
}

LICENSE

MIT

grafoo's People

Contributors

malbernaz avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.