Building the Listings Resolvers
With the root-level `listings` field prepared in our GraphQL API, we'll construct the resolver function for this field to attempt to query for a list of listings from the "listings" collection in our database.
Now that we have the listings
GraphQL query field established, let's update the resolver function for this field such that it will retrieve a list of listings from the "listings"
collection from our database when queried.
listings
typeDefs#
We'll first update the GraphQL type definitions of the listings
field before implementing the resolver function.
The listings
field will have three input arguments:
It will have a
filter
argument that will be of an Enum type we'll create shortly calledListingsFilter
. When thisfilter
argument is passed in, it'll allow the field to return a list of listings that are sorted based on the filter applied.It will have a
limit
argument which is to be an integer to determine the number of listings to return for a certain query.It'll have a
page
argument of type integer which is to determine the page (or in other words the sub-list) of listings to be returned.
When the listings
field is to be resolved, it'll return a Listings
object type we've set up before which contains the total
number of items returned and the list of items returned.
type Query {
authUrl: String!
user(id: ID!): User!
listing(id: ID!): Listing!
listings(filter: ListingsFilter!, limit: Int!, page: Int!): Listings!
}
Next, we'll set up the GraphQL type definition for the ListingsFilter
Enum. There are to kinds of filters we'll allow the client to specify for how it wants the collection of listings to be returned in this field. We'll have a filter that will allow the client to query listings from the lowest price to the highest price and we can call the Enum value for this "PRICE_LOW_TO_HIGH"
. Similarly, the client will also be able to pass in a filter value that will filter listings from the highest price to the lowest. We'll call this filter Enum value "PRICE_HIGH_TO_LOW"
.
enum ListingsFilter {
PRICE_LOW_TO_HIGH
PRICE_HIGH_TO_LOW
}
listings()
resolver#
With the GraphQL type definition for the root-level listings
field prepared, we'll now look to update the accompanying resolver function. The first thing we'll do is define the TypeScript type definitions of the expected arguments and return value of the listings()
function resolver. We'll define these TypeScript types in the src/graphql/resolvers/Listing/types.ts
file.
We'll first define the shape of arguments that can be passed into the listings
field and we'll establish this in an interface we'll call ListingsArgs
. There are three current expected arguments - filter
, limit
, and page
. limit
and page
are to be number
's while filter
is to be a defined set of values or in other words an Enum. So we'll declare a string-based TypeScript Enum, labeled ListingsFilter
, to reflect the different listing filters that can be applied - "PRICE_LOW_TO_HIGH"
and "PRICE_HIGH_TO_LOW"
.
export enum ListingsFilter {
PRICE_LOW_TO_HIGH = "PRICE_LOW_TO_HIGH",
PRICE_HIGH_TO_LOW = "PRICE_HIGH_TO_LOW"
}
export interface ListingsArgs {
filter: ListingsFilter;
limit: number;
page: number;
}
We'll then create the shape of the data that is expected to be returned from the listings()
resolver function. We'll call this interface ListingsData
and it is to have a total
field of type number
and a result
field which is to be a list of listings. We have the definition of a single Listing
document defined in our src/lib/types.ts
types file so we'll import it and use it within the ListingsData
interface.
With these changes, the src/graphql/resolvers/Listing/types.ts
file will now look like the following:
import { Booking, Listing } from "../../../lib/types";
export enum ListingsFilter {
PRICE_LOW_TO_HIGH = "PRICE_LOW_TO_HIGH",
PRICE_HIGH_TO_LOW = "PRICE_HIGH_TO_LOW"
}
export interface ListingArgs {
id: string;
}
export interface ListingBookingsArgs {
limit: number;
page: number;
}
export interface ListingBookingsData {
total: number;
result: Booking[];
}
export interface ListingsArgs {
filter: ListingsFilter;
limit: number;
page: number;
}
export interface ListingsData {
total: number;
result: Listing[];
}
We'll now head over to the listingResolvers
map file (src/graphql/resolvers/Listing/index.ts
) and look to create the resolver functionality for the listings
field. We'll import the ListingsArgs
and ListingsData
interfaces from the adjacent types file and we'll state the arguments and expected return statement for the listings()
resolver. In the listing()
resolver function, the root
object argument will be undefined. The resolver will expect a filter
, limit
, and page
arguments. We'll need access to the db
object available in context and when the resolver function is completed successfully, it'll return a Promise
that when resolved will resolve to an object that conforms to the ListingsData
shape.
This page is a preview of TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two