GraphQLClient
The GraphQLClient
allows you to execute custom GraphQL queries and mutations, giving you the flexibility to fetch and manipulate data as needed.
Quick Start
import { GeinsCore, gql } from '@geins/core';
const geinsCore = new GeinsCore(geinsSettings);
const graphqlClient = geinsCore.graphql;
const MY_PLP_QUERY = gql`
query MyProductList($skip: Int, $take: Int) {
products(skip: $skip, take: $take) {
count
products {
productId
name
unitPrice {
sellingPriceIncVat
sellingPriceIncVatFormatted
}
productImages {
fileName
}
canonicalUrl
}
}
}
`;
const options = {
query: MY_PLP_QUERY,
variables: { skip: 0, take: 10 },
};
const myProductList = await graphqlClient.Query<MyProductListType>(options);
Overview
GeinsCore
: The central class of the Geins SDK, used to configure and access various services.GraphQLClient
: A class exposed throughGeinsCore
that allows you to execute custom GraphQL queries and mutations against the Geins API.gql
: A function exposed through@geins/core
used to parse GraphQL queries and mutations.@geins/types
: A package that exports TypeScript types generated from the Geins GraphQL schema, providing type definitions for the API.
By using the GraphQLClient
and types from @geins/types
, you can interact with the Geins API in a flexible and type-safe manner, leveraging the power of GraphQL and TypeScript. Using the GraphQLClient
will automatically handle authentication and spoofing for you.
Accessing the GraphQLClient
Once you have an instance of GeinsCore
(refer to the initialization guide), you can access the GraphQLClient
through the graphql
property.
const graphqlClient = geinsCore.graphql;
The GraphQLClient
provides two primary methods:
query<T>(options)
mutation<T>(options)
Using TypeScript Types from @geins/types
The @geins/types
package exports TypeScript interfaces and types generated from the Geins GraphQL schema. These types correspond to the data structures returned by the API and can be used to ensure type safety in your application.
Installation
First, install the @geins/types
package. Refer to the installation guide for detailed instructions.
Importing Types
You can import the pre defined types and enums directly from @geins/types
:
import {
GeinsProductTypeType,
GeinsProductsResultTypeType,
ProductListFilterType,
ProductListSortType,
} from '@geins/types';
GeinsProductTypeType
: Represents the product data structure.GeinsProductsResultTypeType
: Represents the result type of the products query.
Note: The
TypeType
suffix is abit of a misnomer, but it's used to avoid naming conflicts with existing types.
Options for query
and mutation
Methods
The option interfaces and types for the query
and mutation
methods is as follows:
interface GraphQLQueryOptions {
query?: DocumentNode | undefined;
queryAsString?: string | undefined;
variables?: any;
requestOptions?: RequestOptions;
}
interface RequestOptions {
fetchPolicy?: FetchPolicyOptions;
pollInterval?: number;
context?: any;
[key: string]: any;
}
enum FetchPolicyOptions {
CACHE_FIRST = 'cache-first',
NETWORK_ONLY = 'network-only',
CACHE_ONLY = 'cache-only',
NO_CACHE = 'no-cache',
STANDBY = 'standby',
}
GraphQLQueryOptions
query
: The GraphQL query document node.queryAsString
: The GraphQL query as a string.variables
: An object containing variables for the query or mutation.requestOptions
: Additional settings for the request.
Use query
or queryAsString
to specify the GraphQL query. You can pass variables as an object to the variables
property. Variables set in GeinsSettings
will be automatically added to the query (see below). Additional settings can be passed in the requestOptions
object.
All exposed through @geins/core
.
Benefits of Using the GraphQLClient
Automatic Adding of Headers
The GraphQLClient
automatically adds the necessary headers for user authentication and spoofing, simplifying the process of interacting with the Geins API.
Automatic Adding variables to the query
The GraphQLClient
automatically adds the variables that are set in GeinsSettings to the query.
const geinsSettings: GeinsSettings = {
apiKey: process.env.GEINS_API_KEY || '',
accountName: process.env.GEINS_ACCOUNT_NAME || '',
channel: process.env.GEINS_CHANNEL || '',
tld: process.env.GEINS_TLD || '',
locale: process.env.GEINS_LOCALE || '',
market: process.env.GEINS_MARKET || '',
environment: 'qa',
};
const geinsCore = new GeinsCore(geinsSettings);
Ofcourse you can override these variables by setting them in the options object like so:
const options = {
query: MY_QUERY,
variables: { market: 'us', locale: 'en-US' },
};
Running GraphQL Queries
Method Signature
async query<T = any>(options: GraphQLQueryOptions): Promise<T | null>
T
: The expected shape of the response data.options
: options for the query, including the query itself, variables, and additional settings.
Example: Fetching Products
Let's fetch a list of products using a GraphQL query and utilize the types from @geins/types
.
Import Necessary Modules
import { gql } from '@geins/core';
import { GeinsProductTypeType, GeinsProductsResultTypeType } from '@geins/types';
Define the GraphQL Query
const GET_PRODUCTS_QUERY = gql`
query GetProducts($skip: Int, $take: Int) {
products(skip: $skip, take: $take) {
count
products {
productId
name
alias
unitPrice {
sellingPriceIncVat
sellingPriceIncVatFormatted
}
productImages {
fileName
}
canonicalUrl
}
}
}
`;
Execute the Query
async function fetchProducts() {
try {
const options = {
query: GET_PRODUCTS_QUERY,
variables: { skip: 0, take: 10 },
};
const data = await geinsCore.graphql.query<GeinsProductsResultTypeType>(options);
if (data) {
console.log('Total Products:', data.products.count);
data.products.products?.forEach((product: GeinsProductTypeType) => {
console.log('Product:', product.name);
console.log('Price:', product.unitPrice?.sellingPriceIncVatFormatted);
});
} else {
console.error('No data returned from query.');
}
} catch (error) {
console.error('Error fetching products:', error);
}
}
fetchProducts();
In this example:
- We import types from
@geins/types
to ensure type safety. - We use
GeinsProductsResultTypeType
for the response data type. - We specify the variables type inline
{ skip: number; take: number }
if we want we can define it as a type.
Running GraphQL Mutations
Running mutations is similar to running queries but involves modifying data in Geins.
Method Signature
runMutation<TData, TVariables>(
mutation: DocumentNode,
variables?: TVariables,
options?: {
fetchPolicy?: FetchPolicy;
[key: string]: any;
}
): Promise<TData | null>;
TData
: The expected shape of the response data.TVariables
: The shape of the variables object for the mutation.mutation
: The GraphQL mutation, written usinggql
.variables
: An optional object containing variables for the mutation.options
: Optional settings, such asfetchPolicy
.
Example: Adding a Product to Cart
Let's add a product to the cart using a GraphQL mutation and types from @geins/types
.
Import Necessary Modules
import { gql } from '@geins/core';
import { GeinsCartTypeType, GeinsCartItemInputTypeType } from '@geins/types';
Define the GraphQL Mutation
const ADD_TO_CART_MUTATION = gql`
mutation AddToCart($cartId: String!, $item: CartItemInputType!) {
addToCart(id: $cartId, item: $item) {
id
items {
id
product {
productId
name
}
quantity
}
summary {
total {
sellingPriceIncVatFormatted
}
}
}
}
`;
Execute the Mutation
async function addToCart() {
try {
const cartId = 'your-cart-id';
const itemToAdd: GeinsCartItemInputTypeType = {
skuId: 12345,
quantity: 1,
};
const options: GraphQLQueryOptions = {
mutation: ADD_TO_CART_MUTATION,
variables: { cartId, item: itemToAdd },
};
const data = await geinsCore.graphql.mutation<GeinsCartTypeType>(options);
if (data && data.addToCart) {
console.log('Cart Id:', data.addToCart.id);
data.addToCart.items?.forEach(cartItem => {
console.log('Product:', cartItem.product?.name);
console.log('Quantity:', cartItem.quantity);
});
console.log('Total:', data.addToCart.summary?.total?.sellingPriceIncVatFormatted);
} else {
console.error('No data returned from mutation.');
}
} catch (error) {
console.error('Error adding to cart:', error);
}
}
addToCart();
In this example:
- We use
GeinsCartTypeType
for the response data type. - We use
GeinsCartItemInputTypeType
from@geins/types
for the variables type.
Note: The
TypeType
suffix is abit of a misnomer, but it's used to avoid naming conflicts with existing types.
Handling Responses and Errors
- Successful Response: The
data
variable contains the result of the query or mutation. - No Data: If no data is returned, the method resolves to
null
. Handle this case in your code. - Errors: Any errors during execution are caught in the
catch
block. Always include error handling to manage exceptions.
try {
// ... Query or Mutation
} catch (error) {
console.error('An error occurred:', error);
}
Debugging Requests
If the enviroment is not set to production (prod
) you can set the property log_to_console
to true
to log the full options object to the console. This can be done globally on the GeinsCore
object or per request.
// setting globally
const geinsCore = new GeinsCore(geinsSettings);
geinsCore.graphql.log_to_console = true;
// setting for one request
const options: GraphQLQueryOptions = {
query: MY_QUERY,
variables: { skip: 0, take: 10 },
requestOptions: {
log_to_console: true,
},
};
Setting Fetch Policies
Fetch policies determine how the cache interacts with your GraphQL operations. You can set a global default when initializing GeinsCore
or override it per request.
You can get the available fetch policies by importing the enum FetchPolicyOptions
from @geins/core
.
export enum FetchPolicyOptions {
CACHE_FIRST = 'cache-first',
NETWORK_ONLY = 'network-only',
CACHE_ONLY = 'cache-only',
NO_CACHE = 'no-cache',
STANDBY = 'standby',
}
FetchPolicyOptions are:
cache-first
: Fetch from the cache first, then the network if the cache is empty.network-only
: Fetch from the network only.cache-only
: Fetch from the cache only.no-cache
: Bypass the cache and fetch from the network.standby
: Do not fetch from the cache or network.
Per Request Fetch Policy
const options: GraphQLQueryOptions = {
query: MY_QUERY,
variables: { skip: 0, take: 10 },
requestOptions: {
fetchPolicy: FetchPolicyOptions.NETWORK_ONLY,
},
};
const data = await geinsCore.graphql.query<MyType>(options);
Additional Tips
Type Safety: Use the TypeScript interfaces and types exported by
@geins/types
to ensure type safety and leverage IntelliSense in your IDE.GraphQL Variables: Use variables in your queries and mutations to make them dynamic and reusable.
IDE Support: Install GraphQL plugins for your IDE to get syntax highlighting and validation inside
gql
tagged templates.- For VSCode: GraphQL extension
Importing
gql
: You can importgql
directly from@geins/core
:import { gql } from '@geins/core';
Conclusion
The GraphQLClient
exposed through GeinsCore
empowers you to execute custom GraphQL queries and mutations against the Geins API with ease. By leveraging TypeScript and GraphQL, along with the types from @geins/types
, you can build robust applications with precise control over the data you fetch and manipulate.
For more information on available queries and mutations, refer to the Geins API Documentation.