All Projects → swcarlosrj → E2e Ts Gql Workshop

swcarlosrj / E2e Ts Gql Workshop

Licence: mit
End-to-end Type-Safe GraphQL Workshop

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to E2e Ts Gql Workshop

Graphql
The Swift GraphQL implementation for macOS and Linux
Stars: ✭ 812 (+3283.33%)
Mutual labels:  graphql
Diversidad Media
Diversidad Media is a platform to generate more diverse spaces, through Movies, Books, Music, and others. The project is in fast growth and there are many things to do. We are still covering the basics.
Stars: ✭ 17 (-29.17%)
Mutual labels:  graphql
Swapi Graphql Lambda
A GraphQL schema hosted in AWS Lambda wrapping http://swapi.co/
Stars: ✭ 19 (-20.83%)
Mutual labels:  graphql
Gatsby Starter Personal Blog
A ready to use, easy to customize, fully equipped GatsbyJS blog starter with 'like app' layout and views transitions.
Stars: ✭ 817 (+3304.17%)
Mutual labels:  graphql
Graph Node
Graph Node indexes data from blockchains such as Ethereum and serves it over GraphQL
Stars: ✭ 884 (+3583.33%)
Mutual labels:  graphql
React Hasura Todo
A react todo app using Hasura Graphql engine
Stars: ✭ 18 (-25%)
Mutual labels:  graphql
Aws Mobile Appsync Sdk Js
JavaScript library files for Offline, Sync, Sigv4. includes support for React Native
Stars: ✭ 806 (+3258.33%)
Mutual labels:  graphql
Swapi Graphql
A GraphQL schema and server wrapping SWAPI.
Stars: ✭ 921 (+3737.5%)
Mutual labels:  graphql
Graphql Java Codegen Maven Plugin
Maven plugin for graphql-java-codegen
Stars: ✭ 17 (-29.17%)
Mutual labels:  graphql
Graphql Server Demo
GraphQL server demo with nodejs
Stars: ✭ 19 (-20.83%)
Mutual labels:  graphql
Api Platform
Create REST and GraphQL APIs, scaffold Jamstack webapps, stream changes in real-time.
Stars: ✭ 7,144 (+29666.67%)
Mutual labels:  graphql
Ionic Apollo Simple App
Explains how to develop Ionic application with Apollo GraphQL client
Stars: ✭ 16 (-33.33%)
Mutual labels:  graphql
Api
Stars: ✭ 18 (-25%)
Mutual labels:  graphql
Swagger To Graphql
Swagger to GraphQL API adapter
Stars: ✭ 811 (+3279.17%)
Mutual labels:  graphql
Graphql Mst
Convert GraphQL to mobx-state-tree models
Stars: ✭ 22 (-8.33%)
Mutual labels:  graphql
Batch Loader
⚡️ Powerful tool for avoiding N+1 DB or HTTP queries
Stars: ✭ 812 (+3283.33%)
Mutual labels:  graphql
Strawberry
A new GraphQL library for Python 🍓
Stars: ✭ 891 (+3612.5%)
Mutual labels:  graphql
Apollo Link Maxage
An Apollo Link to invalidate cached queries
Stars: ✭ 23 (-4.17%)
Mutual labels:  graphql
Graphql Moltin Server
⚛️ GraphQL + Moltin + GraphQL Yoga 🧘
Stars: ✭ 22 (-8.33%)
Mutual labels:  graphql
Gatsby Simplefolio
⚡️ A minimal Gatsby portfolio template for Developers
Stars: ✭ 895 (+3629.17%)
Mutual labels:  graphql

👨‍💻 End-to-end Type-Safe GraphQL Workshop

Get introduced to the marvellous GraphQL universe! Discover all the benefits for adding End-to-end Type-Safety to your GraphQL App taking all the advantages of TypeScript, GraphQL & React working together. Apollo, auto-gen Types & Hooks would build the pillars of a SpaceX demo 🛰

🎯 Goals

  • Understand Why, How & What's GraphQL
  • Create a J/TS GraphQL Server
  • Create a J/TS GraphQL Client
  • Contribute with Open Source

🗓 Agenda

🚀 Server

  • S0: JS GraphQL Server Demo
  • S1: JS GraphQL Server
  • S2: TS GraphQL Server

🌖 Client

  • S0: JS REST Client
  • S1: JS GraphQL Client
  • S2: TS GraphQL Client

🛠 Requirements

👍 Essentials

  • Node. Latest LTS Version (10.15.3).
  • Git. Latest LTS Version (2.21.0).
  • Github. You just need to create an account!

🤙 Nice to have

  • VSCode. The futuristic J/TS IDE!
  • CodeCopy. Copy to clipboard on markdown.

🌏 Intro

Open a terminal

Fork and clone this repository

git clone https://github.com/${👩‍💻👨‍💻}/e2e-ts-gql-workshop

Navigate to the created folder

cd e2e-ts-gql-workshop

🚀 Server

Time -0, it'll be time to liftoff creating (from scratch) a GraphQL Server. TypeDefs, resolvers & context will be the boosters of the GraphQL JS implementation. Then, we'll take all the advantages of having a strongly typed GraphQL Schema to auto-generate the TypeScript types based on our GraphQL type definitions!

Summary

  • S0: JS GraphQL Server Demo
  • S1: JS GraphQL Server
  • S2: TS GraphQL Server

Step 0️⃣ JS GraphQL Server Demo

In this step will create a demo JS GraphQL Server based on mock data! Summary

  • Create folder structure
  • Implement JS GraphQL Server
  • Run Server

📦 Create folder structure

👉 Checkout first step

git checkout server-step-0

👍 Create server folder

mkdir server

👌 Create index.js inside the server folder

cd server
touch index.js

🎮 Implement JS GraphQL Server

Let's implement a demo GraphQL server in our index.js

👉 Declare typeDefs

const typeDefs = gql`
  # Entry Points
  type Query {
    launches: [Launch]
    launch(id: Int!): Launch
  }

  # Types
  type Launch {
    flight_number: Int!
    mission_name: String!
    details: String
    links: LaunchLinks
    rocket: LaunchRocket
  }
  type LaunchLinks {
    flickr_images: [String]
  }
  type LaunchRocket {
    rocket_name: String!
  }
`;

👉 Declare resolvers

const resolvers = {
  Query: {
    launches: (obj, args, context) => launches,
    launch: (obj, args, context) =>
      launches.find(launch => args.id === launch.flight_number)
  }
};

👉 Declare server

const server = new ApolloServer({
  typeDefs,
  resolvers
});

👉 Call server

server.listen().then(({ url }) => console.log(`🚀 Server ready at: ${url}`));

👍 Import mock data

const launches = [...]

👌 Add dependencies

const gql = require("graphql-tag");
const { ApolloServer } = require("apollo-server");

⚡️ Run Server

👉 Install dependencies

npm install graphql apollo-server

👍 Run server

node ./index.js

👌 Explore GraphQL API http://localhost:4000/

Well done 💪, commit your changes and let's get our hands dirty!

Step 1️⃣ JS GraphQL Server

In this step we will connect the server with a database and we will implement an underfecthing solution

Summary

  • Explore the DB
  • Create DB connector
  • Adapt server & resolvers
  • Underfetching implementation

🧐 Explore the DB

Let's discover how to access to SpaceX real data 🔎

👉 Open Humongous

👉 Login on Get Started and choose your fav MongoDB hosting provider

👉 Paste the SpaceX Public DB link

mongodb+srv://public:[email protected]/spacex-api

👍 Click Next & Create Project

👌 Explore all the data collections

🕹 Create DB connector

Now, we are gonna get rid of the mocks to use real data 🔥

👉 Create db.js file

touch db.js

👉 Connect to DB

const url =
  "mongodb+srv://public:[email protected]/spacex-api";

const getDB = async () => {
  const client = await MongoClient.connect(url, {
    poolSize: 20,
    useNewUrlParser: true
  });

  return client.db("spacex-api");
};

module.exports = {
  getDB
};

👍 Add mongodb dependendy

const MongoClient = require("mongodb");

👌 Install mongodb dependency

npm install mongodb

💫 Adapt server & resolvers

👉 Adapt our server on index.js replacing the current definition with:

(async () => {
  const db = await getDB();

  const server = new ApolloServer({
    typeDefs,
    resolvers,
    context: { db }
  });

  server.listen().then(({ url }) => console.log(`🚀 Server ready at ${url}`));
})();

👉 Import the DB

const { getDB } = require("./db");

👉 Implement resolvers replacing the current with:

const resolvers = {
  Query: {
    launches: async (obj, args, context) => {
      const data = await context.db
        .collection("launch")
        .find()
        .limit(10)
        .toArray();
      return data;
    },
    launch: async (obj, { flight_number }, context) => {
      const [data] = await context.db
        .collection("launch")
        .find({ flight_number })
        .limit(1)
        .toArray();
      return data;
    }
  }
};

👉 Remove launches on index.js

👍 Run server

node ./index.js

👌 Explore explore real data through the GraphQL API (refresh your browser) http://localhost:4000/

♻️ Underfetching implementation

👉 Add rocket to LaunchRocket

type LaunchRocket {
  rocket_name: String!
  rocket: Rocket
}

👉 Include the Rocket type

type Rocket {
  id: ID!
  name: String
  description: String
  cost_per_launch: Int
}

👍 Add the LaunchRocket resolver

const resolvers = {
  Query: {...},
  LaunchRocket: {
    rocket: async (obj, args, context) => {
      console.log("obj: ", obj);
      const [data] = await context.db
        .collection("rocket")
        .find({ id: obj.rocket_id })
        .limit(1)
        .toArray();
      return data;
    }
  }
}

👌 Run the server & explore real data (refresh your browser)

node ./index.js

Look 👀 what you're getting on obj when asking for launches { rocket { rocket { ... } } } (don't forget to remove the console.log)

2/3 ✅, creating APIs has never been easier, commit your changes and let's move on to the last step!

Step 2️⃣ TS GraphQL Server

In this step will auto-generate TypeScript types based on our GraphQL implementation to make our API type safe

Sumary

  • Explore API & Codebase
  • Evolve the API
  • Generate TS types
  • Evolve Safely the API

🤔 Explore API & Codebase

👉 Checkout

git checkout server-step-2

👉 Install dependencies & run the server

cd server
npm install
npm start

👉 Explore the API http://localhost:4000

👍 Explore the codebase

👌 Try to understand how this query is being resolved

{
  history(id: 17) {
    title
    flight {
      mission_name
      rocket {
        rocket {
          name
          cost_per_launch
        }
      }
    }
  }
}

🎸 Evolve the API

👍 Add to Rocket typeDefs rocketByName

extend type Query {
  ...
  rocketByName(name: String!): Rocket
}

👌 Add it resolver

rocketByName: async (obj, { name }, context) => {
  const [data] = await context.db
    .collection(collection)
    .find({ name })
    .limit(1)
    .toArray();
  return data;
};

👍 Run server

node ./index.js

👌 Explore GraphQL API testing the new evolution (refresh your browser) http://localhost:4000/

If everything went well, commit your changes!

🎶 Generate TS types

👉 Checkout

git checkout server-step-3

👉 Install dependencies & run the server

npm install
npm run dev

👉 Create codegen.yml file

touch codegen.yml

👉 Include the configuration

schema: src/schema/**/*.ts
overwrite: true
watch: true
require:
  - ts-node/register
generates:
  ./src/types/types.d.ts:
    config:
      contextType: ./context#MyContext
    plugins:
      - typescript-common
      - typescript-server
      - typescript-resolvers

Indentation here is crucial!

👉 Install codegen dependencies

npm install [email protected] [email protected] [email protected] [email protected]

👉 Install dependencies

npm install

👍 Open a terminal and run

npm run dev

👌 Explore the API http://localhost:4000

👍 Open another terminal and run

npm run generate

👌 Explore types/types.d.ts file

Commit your changes and let's wrap this up!

🎻 Evolve Safely the API

👉 Add again rocketByName into the Rocket typeDefs

  extend type Query {
    ...
    rocketByName(name: String!): Rocket
  }

👉 Explore the types/types.d.ts file changes

👉 Add again it resolver

rocketByNome: async (obj, { nome }, context) => {
  const [data] = await context.db
    .collection(collection)
    .find({ nome })
    .limit(1)
    .toArray();
  return data;
};

👉 Type your rocket's resolvers

const Query: QueryResolvers.Resolvers = {
  ...
}

👍 Import the QueryResolvers type definitions

import { QueryResolvers } from "../../types/types";

👌 Fix all the erros that you could find with the help of TypeScript!

Step 👽 Create a REST API based on GraphQL

👉 Checkout

git checkout server-step-5

👉 Install dependencies & run the server

npm install
npm run dev

👍 Explore the GraphQL API http://localhost:4000/graphql 🤙 Explore the REST API http://localhost:4000/rest

👌 Explore the codebase Take a look at the servers folder, excluding that folder eveything is same than last step!

GraphQL 💜 REST

🎉 You're just finished all GraphQL Server steps, let's now learn about GraphQL Clients!


🌖 Client

Approaching landing... we will create a React-Apollo client in JS (using hooks, of course). Later on we will evolve it safely generating the TypeScript types from our GraphQL documents!

Summary

  • S0: JS REST Client
  • S1: JS GraphQL Client
  • S2: TS GraphQL Client

Step 0️⃣ JS REST Client

Summary

  • Create folder structure
  • Setup Suspense
  • Fetch data from REST

📦 Create folder structure

👉 Checkout first step

git checkout client-step-0

👍 Install create-react-app

npm install --global create-react-app

👌 Create client folder

create-react-app client

⭐️ Setup Suspense

👉 Add Suspense into your index.js ReactDom.render:

ReactDOM.render(
  <Suspense fallback="Loading...">
    <App />
  </Suspense>,
  document.getElementById("root")
);

👉 Import Suspense:

import React, { Suspense } from "react";

💫 Fetch data from REST

👉 Change your App component as follow:

function App() {
  const launchesPast = useFetch("https://api.spacex.land/rest/launches-past");
  return (
    <React.Fragment>
      {launchesPast.map(({ mission_name, details, links, rocket }) => (
        <div key={String(mission_name)}>
          <h3>
            🛰 {mission_name} 🚀 {rocket.name}
          </h3>
          <p>{details}</p>
          <img src={links.flickr_images[0]} width="200" />
        </div>
      ))}
    </React.Fragment>
  );
}

👉 Import useFetch

import useFetch from "fetch-suspense";

👉 Install fetch-suspense

cd client
npm install fetch-suspense

👍 Install dependencies & run the client

npm install
npm start

👌 Explore the Client http://localhost:3000

Step 1️⃣ JS GraphQL Client

Summary

  • Setup GraphQL Client
  • Fetch data from GraphQL

🌟 Setup GraphQL Client

👉 Create on index.js a new Apollo Client

const client = new ApolloClient({
  uri: "http://api.spacex.land/graphql"
});

👉 Include ApolloProvider

ReactDOM.render(
  <ApolloProvider client={client}>
    <Suspense fallback="Loading...">
      <App />
    </Suspense>
  </ApolloProvider>,
  document.getElementById("root")
);

👍 Import dependencies

import { ApolloProvider } from "react-apollo-hooks";
import ApolloClient from "apollo-boost";

👌 Install dependencies

npm install react-apollo-hooks apollo-boost graphql

⚡️ Fetch data from GraphQL

👉 Write on 'App.js' the GraphQL query

const query = gql`
  query getLaunches {
    launchesPast {
      mission_name
      details
      links {
        flickr_images
      }
      rocket {
        name: rocket_name
      }
    }
  }
`;

👉 Add useQuery to fetch data from the GraphQL API

const launchesPastRest = useFetch("https://api.spacex.land/rest/launches-past");
const {
  data: { launchesPast = [] }
} = useQuery(query);

👉 Import useQuery

import { useQuery } from "react-apollo-hooks";
import gql from "graphql-tag";

👉 Run the client again

npm start

👍 Explore the Client http://localhost:3000

👌 Open your browser inspector tool and give a 👀 to both size & time GraphQL-REST calls!

Commit your changes! It's time to finish the workshop off 💪

Step 2️⃣ TS GraphQL Client

Summary

  • Evolve the Client
  • Generate TS types
  • Evolve Safely the Client

🎸 Evolve the Client

👉 Checkout last step

git checkout client-step-2

👉 Include launch_success field into our query

const query = gql`
  query getLaunches {
    launchesPast {
      mission_name
      details
      links {
        flickr_images
      }
      rocket {
        name: rocket_name
      }
      launch_success
    }
  }
`;

👉 Remove useFetch call and log the query to verify that launch_success is there

function App() {
  // const launchesPast = useFetch("https://api.spacex.land/rest/launches-past");
  const {
    data: { launchesPast }
  } = useQuery(query);

  console.log("launchesPast", launchesPast)

  return (...);
}

👍 Display launch_success

function App() {
  const {
    data: { launchesPast = [] }
  } = useQuery(query);
  return (
    <React.Fragment>
      {launchesPast.map(
        ({ mission_name, details, links, rocket, launch_success }) => (
          <div key={String(mission_name)}>
            <h3>
              🛰 {mission_name} 🚀 {rocket.
              }
            </h3>
            <p>{details}</p>
            <h3>Success: {launch_success ? "✅" : "❌"}</h3>
            <img src={links.flickr_images[0]} width="200" />
          </div>
        )
      )}
    </React.Fragment>
  );
}

👌 Explore the Client to see the new field http://localhost:3000

🎶 Generate TS types

👉 Create codegen.yml file

touch codegen.yml

👉 Include the configuration

schema: https://api.spacex.land/graphql
documents:
  - src/**/*.tsx
overwrite: true
watch: true
generates:
  ./src/types/types.d.ts:
    plugins:
      - typescript-common
      - typescript-client

👉 Install codegen dependencies

npm install [email protected] [email protected] [email protected]

👉 Install dependencies

npm install

👍 Open a terminal and run

npm start

👌 Explore the Client http://localhost:3000

👍 Open another terminal and run

npm run generate

👌 Explore types/types.d.ts file

Fantastic, we are almost done. Don't forget to commit the changes!

🎻 Evolve Safely the Client

👉 Type your returned data

const {
  data: { launchesPast }
} = useQuery<GetLaunches.Query>(query);

👉 Import GetLaunches type definition

import { GetLaunches } from "../types";

👍 Add the ships field to the query

const query = gql`
  query getLaunches {
    launchesPast {
      # ...
      ships {
        id
        name
        port: home_port
        image
      }
    }
  }
`;

👌 Display the ships with the help of TypeScript auto-completion!

return (
  <React.Fragment>
    {launchesPast.map(
      ({ ..., ships }) => (
          // ...
          {ships.map(({ id, name, port, image }) => (
            <div key={id}>
              <h3>
                 {name} 🌊 {port}
              </h3>
              <img src={image} alt="" width={200} />
            </div>
          ))}
        </div>
      )
    )}
  </React.Fragment>
);

Step 👽 Introspect API from the IDE

👉 Install Apollo GraphQL VS Code extension

👍 Create apollo.config.js file:

module.exports = {
  client: {
    service: {
      url: "https://api.spacex.land/graphql"
    }
  }
};

👌 Press Ctrl + Space Bar inside your query 🤯

🎊 You're just finished all GraphQL Client steps, hoping that you've enjoyed & learned something new!

😄 Thanks for coming

Don't hesitate to contact @swcarlosrj if you'd have any question!

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].