Extending API schemas
In this guide, learn how to extend VTEX and third-party APIs to customize them according to your store's needs, allowing you to efficiently retrieve and manipulate the necessary data.
Before you start
Avoid over-fetching data on pages
Even though you can add information to the FastStore API schema, you must be careful not to over-fetch data on your pages. See the best practices for fetching data on your storefront.
Extending VTEX API Schemas
FastStore streamlines the way of using data from VTEX APIs that the FastStore API does not expose.
As FastStore uses GraphQL, it's required to write type definitions (opens in a new tab) and resolvers (opens in a new tab) to fetch the data you need. To define new type definitions and resolvers for FastStore using GraphQL, learn how to create a specific directory structure in the following step by step.
Step by step
Step 1 - Preparing the folders and files
To declare a new type definition and resolver, create the following directory structure:
- In your store repository, go to the
src
folder and create thegraphql
subfolder. You can do this by running the following command in your terminal:
mkdir graphql
- Inside the new
graphql
folder, create thevtex
subfolder.
mkdir vtex
- In the
vtex
folder, createresolvers
andtypeDefs
subfolders.
mkdir resolvers typeDefs
The src/graphql/vtex/resolvers
and src/graphql/vtex/typeDefs
paths are mandatory when adding VTEX API Extensions, but you can organize the files inside those directories as you wish.
- Create a
index.ts
file inside theresolvers
folder.
Once you have created the essentials folders, you will have a folder structure for the VTEX API Schema extensions in the src/graphql/vtex
folder similiar to the the following:
starter.store/
└─ src/
└─ graphql/
└─ vtex/
├─ resolvers/
└─ index.ts
└─ <resolverName>.ts
└─ …
├─ typeDefs/
└─<typeName>.graphql
└─ …
Note that in the code example above, the type definitions and resolvers files were created at <resolverName>.ts
and <typeName>.graphql
.
Step 2 - Creating type definitions (typeDefs
)
Your new type definitions set the data structure for your new fields, extended from the existing FastStore API GraphQL queries and types.
- Create a new
<typeName>.graphql
file inside thevtex/typeDefs
folder. For example, let's extends the StoreProduct (opens in a new tab) type from FastStore API, so the name of the file isproduct.graphql
.
The way that it will be organized inside this folder is flexible, it's possible to create multiple typeDefs files or group them all together in just one file.
During the build process and when running the local server file, all .graphql
files under this directory will be considered.
- To extend the
StoreProduct
, let's add acustomData
field in theproduct.graphql
and it should return a string value. This field can store custom information related to a product in your store. For example, you might use this field to store additional product details that are not present in the native FastStore API schema.
extend type StoreProduct {
"""
Custom data extending StoreProduct
"""
customData: String!
}
The typeDefs files must have .graphql
extension.
Also, the index.ts
is not needed for typeDefs, only for resolvers.
Now, refer to the next step to create the resolvers to provide the actual data to the customData
field.
Step 3 - Creating resolvers
Now, let's create a resolver to define how the new customData
field should be resolved, or in other words, what data or logic should be associated with them when queried.
- Create a new
<resolverName>.ts
file inside thevtex/resolvers
folder. Let's continue the StoreProduct (opens in a new tab) type example, so the name of the file isproduct.ts
.
The way that it will be organized inside this folder is flexible, it's possible to create multiple resolvers files or group them all together in just one file.
- Define the resolver in the
product.ts
file. This resolver specifies how to fetch the data for thecustomData
field based on the root object.
import type { StoreProductRoot } from '@faststore/core/api'
const productResolver = {
StoreProduct: {
customData: (root: StoreProductRoot) => {
return 'My item id: ' + root.itemId
},
},
}
export default productResolver
Note that you can leverage the use of TypeScript by typing the root param as StoreProductRoot (opens in a new tab):
-
Open the
index.ts
file inside thevtex/resolvers
folder and import the resolver,StoreProductResolver
, you created in the previous step. -
Export a new
resolvers
object that includes the imported resolver(s).
import { default as StoreProductResolver } from './product'
const resolvers = {
...StoreProductResolver,
}
export default resolvers
Once you have defined these files in the vtex
folder, the new fields are already available for use. To consume the fields, refer to the Consuming FastStore API extension with custom components guide.
If the changes you made are still not available, refer to the troubleshooting section GraphQL changes not visible during development.
Extending FastStore API with third-party API schemas
As stores tend to grow, so does the possibility of consuming new data that is not provided by default in the FastStore API or other VTEX APIs. As such, FastStore must consume new data from third-party APIs.
Step by step
Step 1 - Preparing the folders and files
For third-party API schemas, you only need to add the thirdParty
folder within the 'src/graphql' directory.
- In your store repository, go to the
src
folder and create thegraphql
subfolder. You can do this by running the following command in your terminal:
mkdir graphql
- Inside the new
graphql
folder, create thethirdParty
subfolder.
mkdir thirdParty
- In
thirdParty
, createresolvers
andtypeDefs
subfolders.
mkdir resolvers typeDefs
The src/graphql/vtex/resolvers
and src/graphql/vtex/typeDefs
path is mandatory, but you can organize the files inside those directory as you wish.
- Create a
index.ts
file inside theresolvers
folder.
Once you have created the essentials folders, you will have a folder structure similiar to the the following:
starter.store/
└── src/
└── graphql/
├── thirdParty/
│ ├── resolvers/
│ └── index.ts
│ └── <resolverName>.ts
│ └── …
│ ├── typeDefs/
│ └── <typeName>.graphql
│ └── …
This directory structure distinguishes between data originating from VTEX and data from third-party APIs.
Step 2 - Creating type definitions and resolvers
- Create a new
<typeName>.graphql
inside thethirdParty
folder. As we are creating new queries, the name of the file that defines the type definitions can beextra.graphql
. - Create a new
<resolver>.ts
file inside thegraphql/thirdParty/resolvers folder
.
Step 3 - Creating query or mutation schemas
It's important to mention that it's possible to extend the existing FastStore API Objects (opens in a new tab) as mentioned in the Extending VTEX API Schemas, or even create new queries entry points. Below, you'll find an example of code for implementing a third-party extension using new queries.
- In the
extra.graphql
file, add the following:
type ExtraData {
"""
Data customizing ExtraData
"""
data: String!
}
type Query {
extraData: ExtraData
namedExtraData(name: String!): ExtraData
}
- In the
<resolver>.ts
file, let's continue the example, so the file name can beextra.ts
. This file defines the resolvers that handle the logic for the defined queries or mutations.
const extraDataResolver = {
Query: {
extraData: () => {
return {
data: 'Extra data',
}
},
namedExtraData: (_, { name }) => {
return {
data: `Named extra data: ${name}`,
}
},
},
}
export default extraDataResolver
3 - In the graphql/thirdParty/resolvers
folder, create an index.ts
file to combine all the resolvers into a single object.
import { default as StoreExtraResolver } from './extra'
const resolvers = {
...StoreExtraResolver,
}
export default resolvers
4 - With the schema and resolvers in place, you can query the data using GraphQL queries. Here's an example query to access the extra data:
query {
extraData {
data
}
namedExtraData(name: "Hello") {
data
}
}
Once you have defined these files in the thirdParty
folder, you can query the data you defined.
If the changes you made are still not available, refer to the troubleshooting section GraphQL changes not visible during development.