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.