Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

https://github.com/CannerCMS/apollo-link-firebase

:fire: :link: apollo-link-firebase provides you a simple way to use Firebase with graphQL.
https://github.com/CannerCMS/apollo-link-firebase

apollo-client apollo-link firebase graphql

Last synced: 2 months ago
JSON representation

:fire: :link: apollo-link-firebase provides you a simple way to use Firebase with graphQL.

Lists

README

        

[![npm version](https://badge.fury.io/js/apollo-link-firebase.svg)](https://badge.fury.io/js/apollo-link-firebase) [![CircleCI](https://circleci.com/gh/Canner/apollo-link-firebase.svg?style=shield)](https://circleci.com/gh/Canner/apollo-link-firebase) [![gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/Canner/apollo-link-firebase)

## Apollo-link-firebase
apollo-link-firebase provides you a simple way to query Firebase in graphQL with [Apollo-client](https://www.apollographql.com/client/) **without building a graphQL server**

Currently, we support features below:

1. **Query**: All sorting and filtering methods on [document](https://firebase.google.com/docs/database/web/lists-of-data#sorting_and_filtering_data) are supported.
1. **Mutation**: deal with `set`, `update`, `remove` methods with graphQL mutation.
1. **Realtime Subscription**: Listen to your [Firebase events](https://firebase.google.com/docs/database/web/lists-of-data#listen_for_child_events) using graphQL Subscription.
1. **Data Join**: Retrieve your data from different paths using **one graphQL**.

## Contents
* [Installation](#installation)
* [Quickstart](#quickstart)
* [Retrieve Object Data](#retrieve-object-data)
* [Work With Lists of Data](#work-with-lists-of-data)
* [Mutation](#mutation)
* [Subscription](#subscription)
* [Example](#example)

## Installation
``` console
yarn add apollo-link-firebase
```

## Quickstart
``` typescript
// rtdb stands for realtime database
import {createRtdbLink} from 'apollo-link-firebase';
import * as firebase from 'firebase';

// initialize firebase
firebase.initializeApp({
// configs
});

// create Realtime Database link
const rtdbLink = createRtdbLink({
database: firebase.database()
});

const client = new ApolloClient({
link: rtdbLink,
cache: new InMemoryCache(),
});

// A simple query to retrieve data from
// firebase.database().ref("/profile/me")
// @rtdbQuery stands for Realtime Database Query
const query = gql`
query myProfile {
me @rtdbQuery(ref: "/profile/me") {
name
}
}
`;

// Invoke the query and log the person's name
client.query({ query }).then(response => {
console.log(response.data.name);
});
```

## Retrieve Object Data
### Return with __typename
In Apollo client, `InMemoryCache` use `__typename` and `id` to save your data in store.

Using `@key` directive, you can speficy which field you want to return with the [key of snapshot](https://firebase.google.com/docs/reference/js/firebase.database.DataSnapshot?authuser=0#key)
``` js
const query = gql`
query myProfile {
me @rtdbQuery(ref: "/profile/me", type: "Profile") {
id @key
name
}
}
`;
```
#### Response
``` js
{
__typename: "Profile",
id: "me",
name: "wwwy3y3"
}
```

## Work with Lists of Data
For example, your data in Firebase could be like
``` js
{
users: {
id1: {
name: "alovelace",
birth: 1815
},
id2: {
name: "ghopper",
birth: 1906
}
}
}
```

### Basic Query
We can query all users, and use `@array` directive to parse data to array
``` js
const query = gql`
query getUsers {
users @rtdbQuery(ref: "/users", type: "Users") @array {
id @key
name
}
}
`;
```
#### Response
``` js
[{
__typename: "Users",
id: "id1",
name: "alovelace",
birth: 1815
}, {
__typename: "Users",
id: "id2",
name: "ghopper",
birth: 1906
}]
```

### Advance Query
In firebase client js sdk, We can get data by using [sorting and filtering API](https://firebase.google.com/docs/database/web/lists-of-data#sorting_and_filtering_data)

We provide corresponding API in `@rtdbQuery` directive arguments. In the following example, we query lists of data using `orderByChild("birth")` and `limitToFirst(1)`
``` js
const query = gql`
query getUsers {
users @rtdbQuery(ref: "/users", orderByChild: "birth", limitToFirst: 1, type: "Users") {
name
}
}
`;
```

#### Response
``` js
[{
__typename: "Users",
id: "id1",
name: "alovelace",
birth: 1815
}]
```

### rtdbQuery Directive Arguments
* `ref`: string
* `orderByChild`: string
* `orderByKey`: boolean. e,g `orderByKey: true`
* `orderByValue`: boolean
* `startAt`: any
* `endAt`: any
* `equalTo`: any
* `limitToFirst`: number
* `limitToLast`: number

### More Examples
* [Basic API Usage](https://github.com/Canner/apollo-link-firebase/wiki/Simple-Query-Example) (orderBy*, limitTo*...)
* [Advanced API Usage](https://github.com/Canner/apollo-link-firebase/wiki/Advance-Query) (nested array, data join...)

## Mutation
We only take payload from `input` key from the recommendations in this [article](https://dev-blog.apollodata.com/designing-graphql-mutations-e09de826ed97)

``` js
const mutation = gql`
fragment Input on firebase {
string: String
number: Number
}

mutation($ref: string, $input: Input!) {
updateArticle(input: $input) @rtdbUpdate(ref: $ref, type: "Article") {
id @key
string
number
}
}
`;
```

We support four directives for mutation
* `@rtdbUpdate`: Firebase [update](https://firebase.google.com/docs/reference/js/firebase.database.Reference?authuser=0#update)
* `@rtdbSet`: Firebase [set](https://firebase.google.com/docs/reference/js/firebase.database.Reference?authuser=0#set)
* `@rtdbRemove`: Firebase [remove](https://firebase.google.com/docs/reference/js/firebase.database.Reference?authuser=0#remove)
* `@rtdbPush`: Push new element under ref, sugar api for firebase [push and set](https://firebase.google.com/docs/reference/js/firebase.database.Reference?authuser=0#push)
### Examples
#### @rtdbRemove
``` js
const mutation = gql`
mutation($ref: string) {
remove @rtdbRemove(ref: $ref)
}
`;
```

#### @rtdbPush and @pushKey
``` js
const mutation = gql`
fragment ProfileInput on firebase {
string: String
number: Number
}

mutation($ref: string, $input: ProfileInput!) {
pushdata(input: $input) @rtdbPush(ref: $ref) {
id @pushKey
string
number
}
}
`;

// variables
const variables = {
ref: "/users",
input: {
string: "string",
number: 1
}
}

// response
{
id: "-KjCIvxsKueb3Hf2LIOp",
string: "string",
number: 1
}
```

## Subscription
We support four events in Firebase, more on [Firebase document](https://firebase.google.com/docs/database/web/lists-of-data?authuser=0#listen_for_child_events)

You can use all the query api supported in `@rtdbQuery`, more advanced query examples in [wiki](https://github.com/Canner/apollo-link-firebase/wiki/Advance-Query)
### Usage
``` js
const subQuery = gql`
subscription {
newComment @rtdbSub(ref: "/comments", event: "value") {
id @key
content
}
}
`;
```
### Directives
* `value`: `@rtdbSub(ref: string, event: "value")`
* `child_added`: `@rtdbSub(ref: string, event: "child_added")`
* `child_changed`: `@rtdbSub(ref: string, event: "child_changed")`
* `child_removed`: `@rtdbSub(ref: string, event: "child_removed")`

## Example
### Simple Todo React Application
[![](https://i.imgur.com/rlCTO4V.png)](https://github.com/Canner/apollo-link-firebase/tree/master/examples/simple-todo)
Here's a simple [React + apollo-link-firebase todo app](https://github.com/Canner/apollo-link-firebase/tree/master/examples/simple-todo)

## Roadmap
* support firebase transaction
* support firestore
* support authenticate mutation
* support storage mutation

## Contribution
Contributions are **welcome and extremely helpful** 🙌

Feel free to join [our gitter channel](https://gitter.im/Canner/apollo-link-firebase) to discuss with us!

[![](https://user-images.githubusercontent.com/26116324/37811196-a437d930-2e93-11e8-97d8-0653ace2a46d.png)](https://www.canner.io/)