• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

arjunyel/firestore-apollo-graphql: An example of a GraphQL setup with a Firebase ...

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称(OpenSource Name):

arjunyel/firestore-apollo-graphql

开源软件地址(OpenSource Url):

https://github.com/arjunyel/firestore-apollo-graphql

开源编程语言(OpenSource Language):

TypeScript 100.0%

开源软件介绍(OpenSource Introduction):

firebase-firestore-graphql

An example of a GraphQL setup with a Firebase Firestore backend. Uses Apollo Engine/Server 2.0 and deployed to Google App Engine.

Initial setup

npm init --yes
npm install apollo-server@beta firebase-admin graphql graphql-tag
npm install --save-dev typescript tslint

You'll also want to set up some scripts and other settings, as of writing here is what the package.json looks like

{
  "name": "firebase-firestore-graphql",
  "scripts": {
      "build": "tsc",
      "serve": "npm run build && node lib/index.js",
      "start": "node lib/index.js",
      "deploy": "npm run build && gcloud app deploy"
  },
  "main": "lib/index.js",
  "dependencies": {
      "apollo-server": "^2.0.0-beta.10",
      "firebase-admin": "^5.12.1",
      "graphql": "^0.13.2",
      "graphql-tag": "^2.9.2"
  },
  "devDependencies": {
      "tslint": "^5.10.0",
      "typescript": "^2.9.1"
  }
}

Firebase setup

Download Firebase service account as service-account.json and put in root of this directory.

In your firestore database setup two collections, one of tweets and one of users. The userId in tweets should point to a user Id that the tweet came from.

interface User {
  id: string;
  name: string;
  screenName: string;
  statusesCount: number;
}

interface Tweet {
  id: string;
  name: string;
  screenName: string;
  statusesCount: number;
  userId: string;
}

Typescript

Copy the tslint and tsconfig json files from this repo into your own.

GraphQL

Make a src directory and a index.ts file inside. Setup the imports

import * as admin from 'firebase-admin';

const serviceAccount = require('../service-account.json');

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount)
});

import { ApolloServer, ApolloError, ValidationError, gql } from 'apollo-server';

interface User {
  id: string;
  name: string;
  screenName: string;
  statusesCount: number;
}

interface Tweet {
  id: string;
  name: string;
  screenName: string;
  statusesCount: number;
  userId: string;
}

Schema

Now we setup our GraphQL schema

const typeDefs = gql`
  # A Twitter User
  type User {
    id: ID!
    name: String!
    screenName: String!
    statusesCount: Int!
    tweets: [Tweets]!
  }

  # A Tweet Object
  type Tweets {
    id: ID!
    text: String!
    userId: String!
    user: User!
    likes: Int!
  }

  type Query {
    tweets: [Tweets]
    user(id: String!): User
  }
`;

The ! signifies that this property is guaranteed to not be null. You'll notice that a user has an array of Tweets and a tweet has a user object in it, despite them being separate collections in our database. This is the magic of GraphQL, we can combine things across collections.

For the purpose of this tutorial we have two queries, an array of all tweets and a specific user based on their ID.

Resolver

Next we setup our resolver, this turns GraphQL queries into data. First we setup our resolver for the base queries

const resolvers = {
  Query: {
    async tweets() {
      const tweets = await admin
        .firestore()
        .collection('tweets')
        .get();
      return tweets.docs.map(tweet => tweet.data()) as Tweet[];
    },
    async user(_: null, args: { id: string }) {
      try {
        const userDoc = await admin
          .firestore()
          .doc(`users/${args.id}`)
          .get();
        const user = userDoc.data() as User | undefined;
        return user || new ValidationError('User ID not found');
      } catch (error) {
        throw new ApolloError(error);
      }
    }
  }
};

This will get an array of tweets or a user but how do we add the graph part of GraphQL and interconnect different collections such as all the Tweets a user has made or the details of a user that made a certain tweet?

const resolvers = {
  Query: {
    ...
  },
  User: {
    async tweets(user) {
      try {
        const userTweets = await admin
          .firestore()
          .collection('tweets')
          .where('userId', '==', user.id)
          .get();
        return userTweets.docs.map(tweet => tweet.data()) as Tweet[];
      } catch (error) {
        throw new ApolloError(error);
      }
    }
  },
  Tweets: {
    async user(tweet) {
      try {
        const tweetAuthor = await admin
          .firestore()
          .doc(`users/${tweet.userId}`)
          .get();
        return tweetAuthor.data() as User;
      } catch (error) {
        throw new ApolloError(error);
      }
    }
  }
};

Take getting all the tweets a user has made as an example. You can see in our resolver we have a user object with a tweets property. Because tweets is a child of user, we can use the parent user to then query the tweets collection for all the tweets with that user ID.

Apollo Server

Finally we setup our Apollo server, to work on App Engine we need to grab the port from the enviroment variables


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap