Margarita Monorepo

Margarita Monorepo

  • First time here?
  • Developers
  • Got a question?
  • GitHub

โ€บApps

Home

  • What is this all about?
  • Web and Mobile demos
  • Features
  • What is Tequila API?
  • Questions/Bugs/Feature Requests

Developing

  • Getting Started
  • Contributing
  • Folder Structure
  • Technical Overview
  • Guide: Get your Tequila API key
  • Guide: Firebase implementation

Apps

  • List of Apps
  • GraphQL Server
  • Mobile
  • Web

Packages

  • List of Packages
  • Universal Components

    • Introduction
    • Getting Started
    • Contributing
  • Margarita Components

GraphQL Server

Explore deployed version

  • ๐ŸŽฎ GraphQL Playground
  • ๐Ÿš€ GraphQL Voyager

Running server locally

Check the instructions to have the project correctly set up first.

From the root of margarita, run

yarn server

and open the GraphQL Playground by visiting http://localhost:4000.

Folder structure

The code is organised by feature, as you can see in apps/graphql/src/apps.

apps/graphql/
โ”œโ”€โ”€ index.js
โ”œโ”€โ”€ src
โ”‚   โ”œโ”€โ”€ Schema.js                           # lists all the queries and mutations
โ”‚   โ”œโ”€โ”€ apps
โ”‚   โ”‚   โ”œโ”€โ”€ booking
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ Booking.js                  # Flow types concerning booking feature
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ __datasets__                # datasets to mock API responses
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ AllBookings.json
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ booking-16463447.json
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ booking-6676524.json
โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ booking-8142828.json
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ dataloaders                 # contains the logic to fetch and sanitize data
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ BookingDetail.js
โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ Bookings.js
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ queries                     # GraphQL queries concerning booking feature
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ BookingDetail.js
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ CustomerBookings.js
โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ __tests__
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ types                       # GraphQL types concerning booking feature
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ enums
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ inputs
โ”‚   โ”‚   โ”‚       โ””โ”€โ”€ outputs
โ”‚   โ”‚   โ”œโ”€โ”€ common
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ types
โ”‚   โ”‚   โ”œโ”€โ”€ itinerary
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ Itinerary.js
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ __datasets__
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ __mocks__
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ dataloaders
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ helpers
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ queries
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ types
โ”‚   โ”‚   โ””โ”€โ”€ location
โ”‚   โ”‚       โ”œโ”€โ”€ Location.js
โ”‚   โ”‚       โ”œโ”€โ”€ __datasets__
โ”‚   โ”‚       โ”œโ”€โ”€ dataloaders
โ”‚   โ”‚       โ”œโ”€โ”€ queries
โ”‚   โ”‚       โ””โ”€โ”€ types
โ”‚   โ”œโ”€โ”€ server.js
โ”‚   โ””โ”€โ”€ services                            # lists of services/helpers useful across all features
โ”‚       โ”œโ”€โ”€ fetch
โ”‚       โ”œโ”€โ”€ graphqlContext
โ”‚       โ”œโ”€โ”€ logger
โ”‚       โ””โ”€โ”€ testingTools

Each feature has a similar folder structure:

โ”œโ”€โ”€ feature
โ”‚    โ”œโ”€โ”€ Feature.js             # Flow types concerning feature
โ”‚    โ”œโ”€โ”€ __datasets__           # datasets to mock API responses
โ”‚    โ”œโ”€โ”€ dataloaders            # contains the logic to fetch and sanitize data
โ”‚    โ”œโ”€โ”€ queries                # GraphQL queries concerning feature
โ”‚    โ”œโ”€โ”€ mutations              # GraphQL mutations concerning feature
โ”‚    โ”œโ”€โ”€ resolvers              # more complex GraphQL resolvers
โ”‚    โ””โ”€โ”€ types                  # GraphQL types concerning feature
โ”‚        โ”œโ”€โ”€ enums
โ”‚        โ”œโ”€โ”€ inputs             # definitions of INPUT types exposed to the client, e.g. arguments in a query
โ”‚        โ””โ”€โ”€ outputs            # definitions of OUTPUT types exposed to the client, e.g. GraphQL type for GPS coordinates

The dataloaders folder is where the logic to connect to external APIs is stored. It has this name because it relies under the hood on https://github.com/facebook/dataloader which allows batching (i.e. trigger one API request even if your code needs to call the same API endpoint with different queries) and caching (i.e. using previously obtained data and not calling the API endpoint if the same call has already been made before).

Note: The cache offered by dataloaders is per request. On every request, a new context is created as you can see in apps/graphql/src/server.js. That context is defined in apps/graphql/src/services/graphqlContext/GraphQLContext.js and creates new dataloaders when invoked.

Connecting to Tequila API

Looking at the dataloaders for location, you see there is a function called fetchLocations which uses the fetch service.

const fetchLocations = async (params: $ReadOnlyArray<LocationInput>) => {
  const data = await Promise.all(
    params.map(param => {
      if (param.term !== undefined) {
        return fetch(`/locations/query?${qs.stringify({ term: param.term })}`);
      }

      return fetch(`/locations/id?id=${param.code}`);
    }),
  );
  return data.map(({ locations }) => sanitizeLocations(locations));
};

The fetch service allows to reuse the same base url and authorization headers containing your Tequila API key, so that you can just focus on querying the endpoint you need.

After the data comes back, it is sanitized so that its shape corresponds to how the GraphQL schema prefers to resolve it.

Note the use of OptimisticDataloader which locally caches the API responses in the GraphQL context so that querying the same endpoint with the same parameters somewhere else in your GraphQL schema will not trigger the same request twice.

Last updated on 5/30/2019 by Josef Duda
โ† List of AppsMobile โ†’
  • Explore deployed version
  • Running server locally
  • Folder structure
  • Connecting to Tequila API
Copyright ยฉ 2019 Kiwi.com