create Hydrogen Contextutility
The function creates the context object required to use Hydrogen utilities throughout a Hydrogen project.
Anchor to createhydrogencontext(options)createHydrogenContext(options)
- TEnvrequired
- Anchor to requestrequestrequired
- Anchor to sessionsessionTSessionrequired
Any cookie implementation. By default Hydrogen ships with cookie session storage, but you can use another session storage implementation.
- Anchor to cachecacheCache
An instance that implements the Cache API
- Anchor to cartcart{ getId?: () => string; setId?: (cartId: string) => ; queryFragment?: string; mutateFragment?: string; customMethods?: Record<string, Function>; }
Cart handler overwrite options. See documentation for createCartHandler for more information.
- Anchor to customerAccountcustomerAccount{ apiVersion?: string; authUrl?: string; customAuthStatusHandler?: () => {} | Response; unstableB2b?: boolean; }
Customer Account client overwrite options. See documentation for createCustomerAccountClient for more information.
- Anchor to i18ni18nTI18n
An object containing a country code and language code
- Anchor to logErrorslogErrorsboolean | ((error?: Error) => boolean)
Whether it should print GraphQL errors automatically. Defaults to true
- Anchor to storefrontstorefront{ headers?: StorefrontHeaders; apiVersion?: string; }
Storefront client overwrite options. See documentation for createStorefrontClient for more information.
- Anchor to waitUntilwaitUntilWaitUntil
The
function is used to keep the current request/response lifecycle alive even after a response has been sent. It should be provided by your platform.
HydrogenContextOptionsForDocs
- cache
An instance that implements the [Cache API](https://developer.mozilla.org/en-US/docs/Web/API/Cache)
Cache
- cart
Cart handler overwrite options. See documentation for createCartHandler for more information.
{ getId?: () => string; setId?: (cartId: string) => Headers; queryFragment?: string; mutateFragment?: string; customMethods?: Record<string, Function>; }
- customerAccount
Customer Account client overwrite options. See documentation for createCustomerAccountClient for more information.
{ apiVersion?: string; authUrl?: string; customAuthStatusHandler?: () => {} | Response; unstableB2b?: boolean; }
- env
TEnv
- i18n
An object containing a country code and language code
TI18n
- logErrors
Whether it should print GraphQL errors automatically. Defaults to true
boolean | ((error?: Error) => boolean)
- request
CrossRuntimeRequest
- session
Any cookie implementation. By default Hydrogen ships with cookie session storage, but you can use [another session storage](https://remix.run/docs/en/main/utils/sessions) implementation.
TSession
- storefront
Storefront client overwrite options. See documentation for createStorefrontClient for more information.
{ headers?: StorefrontHeaders; apiVersion?: string; }
- waitUntil
The `waitUntil` function is used to keep the current request/response lifecycle alive even after a response has been sent. It should be provided by your platform.
WaitUntil
{
/* Environment variables from the fetch function */
env: TEnv;
/* Request object from the fetch function */
request: CrossRuntimeRequest;
/** An instance that implements the [Cache API](https://developer.mozilla.org/en-US/docs/Web/API/Cache) */
cache?: Cache;
/** The `waitUntil` function is used to keep the current request/response lifecycle alive even after a response has been sent. It should be provided by your platform. */
waitUntil?: WaitUntil;
/** Any cookie implementation. By default Hydrogen ships with cookie session storage, but you can use [another session storage](https://remix.run/docs/en/main/utils/sessions) implementation. */
session: TSession;
/** An object containing a country code and language code */
i18n?: TI18n;
/** Whether it should print GraphQL errors automatically. Defaults to true */
logErrors?: boolean | ((error?: Error) => boolean);
/** Storefront client overwrite options. See documentation for createStorefrontClient for more information. */
storefront?: {
/** Storefront API headers. Default values set from request header. */
headers?: StorefrontHeaders;
/** Override the Storefront API version for this query. */
apiVersion?: string;
};
/** Customer Account client overwrite options. See documentation for createCustomerAccountClient for more information. */
customerAccount?: {
/** Override the version of the API */
apiVersion?: string;
/** This is the route in your app that authorizes the customer after logging in. Make sure to call `customer.authorize()` within the loader on this route. It defaults to `/account/authorize`. */
authUrl?: string;
/** Use this method to overwrite the default logged-out redirect behavior. The default handler [throws a redirect](https://remix.run/docs/en/main/utils/redirect#:~:text=!session) to `/account/login` with current path as `return_to` query param. */
customAuthStatusHandler?: () => Response | NonNullable<unknown> | null;
/** Deprecated. `unstableB2b` is now stable. Please remove. */
unstableB2b?: boolean;
};
/** Cart handler overwrite options. See documentation for createCartHandler for more information. */
cart?: {
/** A function that returns the cart id in the form of `gid://shopify/Cart/c1-123`. */
getId?: () => string | undefined;
/** A function that sets the cart ID. */
setId?: (cartId: string) => Headers;
/**
* The cart query fragment used by `cart.get()`.
* See the [example usage](/docs/api/hydrogen/utilities/createcarthandler#example-cart-fragments) in the documentation.
*/
queryFragment?: string;
/**
* The cart mutation fragment used in most mutation requests, except for `setMetafields` and `deleteMetafield`.
* See the [example usage](/docs/api/hydrogen/utilities/createcarthandler#example-cart-fragments) in the documentation.
*/
mutateFragment?: string;
/**
* Define custom methods or override existing methods for your cart API instance.
* See the [example usage](/docs/api/hydrogen/utilities/createcarthandler#example-custom-methods) in the documentation.
*/
customMethods?: Record<string, Function>;
};
}
Headers
Headers
CrossRuntimeRequest
- headers
{ [key: string]: any; get?: (key: string) => string; }
- method
string
- url
string
{
url?: string;
method?: string;
headers: {
get?: (key: string) => string | null | undefined;
[key: string]: any;
};
}
Anchor to returnsReturns
- Anchor to cartcartTCustomMethods extends ? <TCustomMethods> :required
A collection of utilities used to interact with the cart.
- Anchor to customerAccountcustomerAccountrequired
A GraphQL client for querying the Customer Account API. It also provides methods to authenticate and check if the user is logged in.
- TEnvrequired
- Anchor to sessionsessionTSessionrequired
Any cookie implementation. By default Hydrogen ships with cookie session storage, but you can use another session storage implementation.
- Anchor to storefrontstorefront<TI18n>required
A GraphQL client for querying the Storefront API.
- Anchor to waitUntilwaitUntilWaitUntil
The
function is used to keep the current request/response lifecycle alive even after a response has been sent. It should be provided by your platform.
HydrogenContext
- cart
A collection of utilities used to interact with the cart.
TCustomMethods extends CustomMethodsBase ? HydrogenCartCustom<TCustomMethods> : HydrogenCart
- customerAccount
A GraphQL client for querying the [Customer Account API](https://shopify.dev/docs/api/customer). It also provides methods to authenticate and check if the user is logged in.
CustomerAccount
- env
TEnv
- session
Any cookie implementation. By default Hydrogen ships with cookie session storage, but you can use [another session storage](https://remix.run/docs/en/main/utils/sessions) implementation.
TSession
- storefront
A GraphQL client for querying the [Storefront API](https://shopify.dev/docs/api/storefront).
Storefront<TI18n>
- waitUntil
The `waitUntil` function is used to keep the current request/response lifecycle alive even after a response has been sent. It should be provided by your platform.
WaitUntil
export interface HydrogenContext<
TSession extends HydrogenSession = HydrogenSession,
TCustomMethods extends CustomMethodsBase | undefined = {},
TI18n extends I18nBase = I18nBase,
TEnv extends HydrogenEnv = Env,
> {
/** A GraphQL client for querying the [Storefront API](https://shopify.dev/docs/api/storefront). */
storefront: StorefrontClient<TI18n>['storefront'];
/** A GraphQL client for querying the [Customer Account API](https://shopify.dev/docs/api/customer). It also provides methods to authenticate and check if the user is logged in. */
customerAccount: CustomerAccount;
/** A collection of utilities used to interact with the cart. */
cart: TCustomMethods extends CustomMethodsBase
? HydrogenCartCustom<TCustomMethods>
: HydrogenCart;
/* Request object from the fetch function */
env: TEnv;
/** The `waitUntil` function is used to keep the current request/response lifecycle alive even after a response has been sent. It should be provided by your platform. */
waitUntil?: WaitUntil;
/** Any cookie implementation. By default Hydrogen ships with cookie session storage, but you can use [another session storage](https://remix.run/docs/en/main/utils/sessions) implementation. */
session: TSession;
}
CustomMethodsBase
Record<string, Function>
HydrogenCartCustom
Omit<HydrogenCart, keyof TCustomMethods> & TCustomMethods
HydrogenCart
- addDeliveryAddresses
Adds delivery addresses to the cart. This function sends a mutation to the storefront API to add one or more delivery addresses to the cart. It returns the result of the mutation, including any errors that occurred.
ReturnType<typeof cartDeliveryAddressesAddDefault>
- addLines
ReturnType<typeof cartLinesAddDefault>
- create
ReturnType<typeof cartCreateDefault>
- deleteMetafield
ReturnType<typeof cartMetafieldDeleteDefault>
- get
ReturnType<typeof cartGetDefault>
- getCartId
() => string
- removeDeliveryAddresses
Removes delivery addresses from the cart. This function sends a mutation to the storefront API to remove one or more delivery addresses from the cart. It returns the result of the mutation, including any errors that occurred.
ReturnType< typeof cartDeliveryAddressesRemoveDefault >
- removeLines
ReturnType<typeof cartLinesRemoveDefault>
- setCartId
(cartId: string) => Headers
- setMetafields
ReturnType<typeof cartMetafieldsSetDefault>
- updateAttributes
ReturnType<typeof cartAttributesUpdateDefault>
- updateBuyerIdentity
ReturnType<typeof cartBuyerIdentityUpdateDefault>
- updateDeliveryAddresses
Updates delivery addresses in the cart. This function sends a mutation to the storefront API to update one or more delivery addresses in the cart. It returns the result of the mutation, including any errors that occurred.
ReturnType< typeof cartDeliveryAddressesUpdateDefault >
- updateDiscountCodes
ReturnType<typeof cartDiscountCodesUpdateDefault>
- updateGiftCardCodes
ReturnType<typeof cartGiftCardCodesUpdateDefault>
- updateLines
ReturnType<typeof cartLinesUpdateDefault>
- updateNote
ReturnType<typeof cartNoteUpdateDefault>
- updateSelectedDeliveryOption
ReturnType< typeof cartSelectedDeliveryOptionsUpdateDefault >
{
get: ReturnType<typeof cartGetDefault>;
getCartId: () => string | undefined;
setCartId: (cartId: string) => Headers;
create: ReturnType<typeof cartCreateDefault>;
addLines: ReturnType<typeof cartLinesAddDefault>;
updateLines: ReturnType<typeof cartLinesUpdateDefault>;
removeLines: ReturnType<typeof cartLinesRemoveDefault>;
updateDiscountCodes: ReturnType<typeof cartDiscountCodesUpdateDefault>;
updateGiftCardCodes: ReturnType<typeof cartGiftCardCodesUpdateDefault>;
updateBuyerIdentity: ReturnType<typeof cartBuyerIdentityUpdateDefault>;
updateNote: ReturnType<typeof cartNoteUpdateDefault>;
updateSelectedDeliveryOption: ReturnType<
typeof cartSelectedDeliveryOptionsUpdateDefault
>;
updateAttributes: ReturnType<typeof cartAttributesUpdateDefault>;
setMetafields: ReturnType<typeof cartMetafieldsSetDefault>;
deleteMetafield: ReturnType<typeof cartMetafieldDeleteDefault>;
/**
* Adds delivery addresses to the cart.
*
* This function sends a mutation to the storefront API to add one or more delivery addresses to the cart.
* It returns the result of the mutation, including any errors that occurred.
*
* @param {CartQueryOptions} options - The options for the cart query, including the storefront API client and cart fragment.
* @returns {ReturnType<typeof cartDeliveryAddressesAddDefault>} - A function that takes an array of addresses and optional parameters, and returns the result of the API call.
*
* @example
* const result = await cart.addDeliveryAddresses(
* [
* {
* address1: '123 Main St',
* city: 'Anytown',
* countryCode: 'US'
* }
* ],
* { someOptionalParam: 'value' }
* );
*/
addDeliveryAddresses: ReturnType<typeof cartDeliveryAddressesAddDefault>;
/**
* Removes delivery addresses from the cart.
*
* This function sends a mutation to the storefront API to remove one or more delivery addresses from the cart.
* It returns the result of the mutation, including any errors that occurred.
*
* @param {CartQueryOptions} options - The options for the cart query, including the storefront API client and cart fragment.
* @returns {CartDeliveryAddressRemoveFunction} - A function that takes an array of address IDs and optional parameters, and returns the result of the API call.
*
* @example
* const result = await cart.removeDeliveryAddresses([
* "gid://shopify/<objectName>/10079785100"
* ],
* { someOptionalParam: 'value' });
*/
removeDeliveryAddresses: ReturnType<
typeof cartDeliveryAddressesRemoveDefault
>;
/**
* Updates delivery addresses in the cart.
*
* This function sends a mutation to the storefront API to update one or more delivery addresses in the cart.
* It returns the result of the mutation, including any errors that occurred.
*
* @param {CartQueryOptions} options - The options for the cart query, including the storefront API client and cart fragment.
* @returns {CartDeliveryAddressUpdateFunction} - A function that takes an array of addresses and optional parameters, and returns the result of the API call.
*
* const result = await cart.updateDeliveryAddresses([
{
"address": {
"copyFromCustomerAddressId": "gid://shopify/<objectName>/10079785100",
"deliveryAddress": {
"address1": "<your-address1>",
"address2": "<your-address2>",
"city": "<your-city>",
"company": "<your-company>",
"countryCode": "AC",
"firstName": "<your-firstName>",
"lastName": "<your-lastName>",
"phone": "<your-phone>",
"provinceCode": "<your-provinceCode>",
"zip": "<your-zip>"
}
},
"id": "gid://shopify/<objectName>/10079785100",
"oneTimeUse": true,
"selected": true,
"validationStrategy": "COUNTRY_CODE_ONLY"
}
],{ someOptionalParam: 'value' });
*/
updateDeliveryAddresses: ReturnType<
typeof cartDeliveryAddressesUpdateDefault
>;
}
Headers
Headers
CustomerAccount
- authorize
On successful login, the customer redirects back to your app. This function validates the OAuth response and exchanges the authorization code for an access token and refresh token. It also persists the tokens on your session. This function should be called and returned from the Remix loader configured as the redirect URI within the Customer Account API settings in admin.
() => Promise<Response>
- getAccessToken
Returns CustomerAccessToken if the customer is logged in. It also run a expiry check and does a token refresh if needed.
() => Promise<string>
- getApiUrl
Creates the fully-qualified URL to your store's GraphQL endpoint.
() => string
- getBuyer
Get buyer token and company location id from session.
() => Promise<Partial<BuyerInput>>
- handleAuthStatus
Check for a not logged in customer and redirect customer to login page. The redirect can be overwritten with `customAuthStatusHandler` option.
() => void | DataFunctionValue
- isLoggedIn
Returns if the customer is logged in. It also checks if the access token is expired and refreshes it if needed.
() => Promise<boolean>
- login
Start the OAuth login flow. This function should be called and returned from a Remix loader. It redirects the customer to a Shopify login domain. It also defined the final path the customer lands on at the end of the oAuth flow with the value of the `return_to` query param. (This is automatically setup unless `customAuthStatusHandler` option is in use)
(options?: LoginOptions) => Promise<Response>
- logout
Logout the customer by clearing the session and redirecting to the login domain. It should be called and returned from a Remix action. The path app should redirect to after logout can be setup in Customer Account API settings in admin.
(options?: LogoutOptions) => Promise<Response>
- mutate
Execute a GraphQL mutation against the Customer Account API. This method execute `handleAuthStatus()` ahead of mutation.
<OverrideReturnType extends unknown = never, RawGqlString extends string = string>(mutation: RawGqlString, ...options: IsOptionalVariables<CustomerAccountMutations[RawGqlString]["variables"], never, Omit<CustomerAccountMutations[RawGqlString]["variables"], never>> extends true ? [({} & ClientVariables<CustomerAccountMutations, RawGqlString, never, "variables", RawGqlString extends never ? SetOptional<CustomerAccountMutations[RawGqlString]["variables"], Extract<keyof CustomerAccountMutations[RawGqlString]["variables"], never>> : { readonly [variable: string]: unknown; }, Record<"variables", RawGqlString extends never ? SetOptional<CustomerAccountMutations[RawGqlString]["variables"], Extract<keyof CustomerAccountMutations[RawGqlString]["variables"], never>> : { readonly [variable: string]: unknown; }>>)?] : [{} & ClientVariables<CustomerAccountMutations, RawGqlString, never, "variables", RawGqlString extends never ? SetOptional<CustomerAccountMutations[RawGqlString]["variables"], Extract<keyof CustomerAccountMutations[RawGqlString]["variables"], never>> : { readonly [variable: string]: unknown; }, Record<"variables", RawGqlString extends never ? SetOptional<CustomerAccountMutations[RawGqlString]["variables"], Extract<keyof CustomerAccountMutations[RawGqlString]["variables"], never>> : { readonly [variable: string]: unknown; }>>]) => Promise<Omit<CustomerAPIResponse<ClientReturn<CustomerAccountMutations, RawGqlString, OverrideReturnType>>, "errors"> & { errors?: Pick<GraphQLError, "path" | "name" | "message" | "extensions" | "locations" | "stack">[]; }>
- query
Execute a GraphQL query against the Customer Account API. This method execute `handleAuthStatus()` ahead of query.
<OverrideReturnType extends unknown = never, RawGqlString extends string = string>(query: RawGqlString, ...options: IsOptionalVariables<CustomerAccountQueries[RawGqlString]["variables"], never, Omit<CustomerAccountQueries[RawGqlString]["variables"], never>> extends true ? [({} & ClientVariables<CustomerAccountQueries, RawGqlString, never, "variables", RawGqlString extends never ? SetOptional<CustomerAccountQueries[RawGqlString]["variables"], Extract<keyof CustomerAccountQueries[RawGqlString]["variables"], never>> : { readonly [variable: string]: unknown; }, Record<"variables", RawGqlString extends never ? SetOptional<CustomerAccountQueries[RawGqlString]["variables"], Extract<keyof CustomerAccountQueries[RawGqlString]["variables"], never>> : { readonly [variable: string]: unknown; }>>)?] : [{} & ClientVariables<CustomerAccountQueries, RawGqlString, never, "variables", RawGqlString extends never ? SetOptional<CustomerAccountQueries[RawGqlString]["variables"], Extract<keyof CustomerAccountQueries[RawGqlString]["variables"], never>> : { readonly [variable: string]: unknown; }, Record<"variables", RawGqlString extends never ? SetOptional<CustomerAccountQueries[RawGqlString]["variables"], Extract<keyof CustomerAccountQueries[RawGqlString]["variables"], never>> : { readonly [variable: string]: unknown; }>>]) => Promise<Omit<CustomerAPIResponse<ClientReturn<CustomerAccountQueries, RawGqlString, OverrideReturnType>>, "errors"> & { errors?: Pick<GraphQLError, "path" | "name" | "message" | "extensions" | "locations" | "stack">[]; }>
- setBuyer
Set buyer information into session.
(buyer: Partial<BuyerInput>) => void
- UNSTABLE_getBuyer
Deprecated. Please use getBuyer. Get buyer token and company location id from session.
() => Promise<Partial<BuyerInput>>
- UNSTABLE_setBuyer
Deprecated. Please use setBuyer. Set buyer information into session.
(buyer: Partial<BuyerInput>) => void
{
/** Start the OAuth login flow. This function should be called and returned from a Remix loader.
* It redirects the customer to a Shopify login domain. It also defined the final path the customer
* lands on at the end of the oAuth flow with the value of the `return_to` query param. (This is
* automatically setup unless `customAuthStatusHandler` option is in use)
*
* @param options.uiLocales - The displayed language of the login page. Only support for the following languages:
* `en`, `fr`, `cs`, `da`, `de`, `es`, `fi`, `it`, `ja`, `ko`, `nb`, `nl`, `pl`, `pt-BR`, `pt-PT`,
* `sv`, `th`, `tr`, `vi`, `zh-CN`, `zh-TW`. If supplied any other language code, it will default to `en`.
* */
login: (options?: LoginOptions) => Promise<Response>;
/** On successful login, the customer redirects back to your app. This function validates the OAuth response and exchanges the authorization code for an access token and refresh token. It also persists the tokens on your session. This function should be called and returned from the Remix loader configured as the redirect URI within the Customer Account API settings in admin. */
authorize: () => Promise<Response>;
/** Returns if the customer is logged in. It also checks if the access token is expired and refreshes it if needed. */
isLoggedIn: () => Promise<boolean>;
/** Check for a not logged in customer and redirect customer to login page. The redirect can be overwritten with `customAuthStatusHandler` option. */
handleAuthStatus: () => void | DataFunctionValue;
/** Returns CustomerAccessToken if the customer is logged in. It also run a expiry check and does a token refresh if needed. */
getAccessToken: () => Promise<string | undefined>;
/** Creates the fully-qualified URL to your store's GraphQL endpoint.*/
getApiUrl: () => string;
/** Logout the customer by clearing the session and redirecting to the login domain. It should be called and returned from a Remix action. The path app should redirect to after logout can be setup in Customer Account API settings in admin.
*
* @param options.postLogoutRedirectUri - The url to redirect customer to after logout, should be a relative URL. This url will need to included in Customer Account API's application setup for logout URI. The default value is current app origin, which is automatically setup in admin when using `--customer-account-push` flag with dev.
* @param options.headers - These will be passed along to the logout redirect. You can use these to set/clear cookies on logout, like the cart.
* @param options.keepSession - If true, custom data in the session will not be cleared on logout.
* */
logout: (options?: LogoutOptions) => Promise<Response>;
/** Execute a GraphQL query against the Customer Account API. This method execute `handleAuthStatus()` ahead of query. */
query: <
OverrideReturnType extends any = never,
RawGqlString extends string = string,
>(
query: RawGqlString,
...options: ClientVariablesInRestParams<
CustomerAccountQueries,
RawGqlString
>
) => Promise<
Omit<
CustomerAPIResponse<
ClientReturn<CustomerAccountQueries, RawGqlString, OverrideReturnType>
>,
'errors'
> & {errors?: JsonGraphQLError[]}
>;
/** Execute a GraphQL mutation against the Customer Account API. This method execute `handleAuthStatus()` ahead of mutation. */
mutate: <
OverrideReturnType extends any = never,
RawGqlString extends string = string,
>(
mutation: RawGqlString,
...options: ClientVariablesInRestParams<
CustomerAccountMutations,
RawGqlString
>
) => Promise<
Omit<
CustomerAPIResponse<
ClientReturn<CustomerAccountMutations, RawGqlString, OverrideReturnType>
>,
'errors'
> & {errors?: JsonGraphQLError[]}
>;
/** Set buyer information into session.*/
setBuyer: (buyer: Buyer) => void;
/** Get buyer token and company location id from session.*/
getBuyer: () => Promise<Buyer>;
/** Deprecated. Please use setBuyer. Set buyer information into session.*/
UNSTABLE_setBuyer: (buyer: Buyer) => void;
/** Deprecated. Please use getBuyer. Get buyer token and company location id from session.*/
UNSTABLE_getBuyer: () => Promise<Buyer>;
}
DataFunctionValue
Response | NonNullable<unknown> | null
LoginOptions
- uiLocales
LanguageCode
{
uiLocales?: LanguageCode;
}
LogoutOptions
- headers
Add custom headers to the logout redirect.
HeadersInit
- keepSession
If true, custom data in the session will not be cleared on logout.
boolean
- postLogoutRedirectUri
The url to redirect customer to after logout, should be a relative URL. This url will need to included in Customer Account API's application setup for logout URI. The default value is current app origin, which is automatically setup in admin when using `--customer-account-push` flag with dev.
string
{
/** The url to redirect customer to after logout, should be a relative URL. This url will need to included in Customer Account API's application setup for logout URI. The default value is current app origin, which is automatically setup in admin when using `--customer-account-push` flag with dev. */
postLogoutRedirectUri?: string;
/** Add custom headers to the logout redirect. */
headers?: HeadersInit;
/** If true, custom data in the session will not be cleared on logout. */
keepSession?: boolean;
}
CustomerAccountMutations
export interface CustomerAccountMutations {
// Example of how a generated mutation type looks like:
// '#graphql mutation m1 {...}': {return: M1Mutation; variables: M1MutationVariables};
}
CustomerAPIResponse
- data
ReturnType
- errors
Array<{ message: string; locations?: Array<{line: number; column: number}>; path?: Array<string>; extensions: {code: string}; }>
- extensions
{ cost: { requestQueryCost: number; actualQueryCakes: number; throttleStatus: { maximumAvailable: number; currentAvailable: number; restoreRate: number; }; }; }
{
data: ReturnType;
errors: Array<{
message: string;
locations?: Array<{line: number; column: number}>;
path?: Array<string>;
extensions: {code: string};
}>;
extensions: {
cost: {
requestQueryCost: number;
actualQueryCakes: number;
throttleStatus: {
maximumAvailable: number;
currentAvailable: number;
restoreRate: number;
};
};
};
}
GraphQLError
- locations
If an error can be associated to a particular point in the requested GraphQL document, it should contain a list of locations.
{ line: number; column: number; }[]
- path
If an error can be associated to a particular field in the GraphQL result, it _must_ contain an entry with the key `path` that details the path of the response field which experienced the error. This allows clients to identify whether a null result is intentional or caused by a runtime error.
(string | number)[]
- extensions
Reserved for implementors to extend the protocol however they see fit, and hence there are no additional restrictions on its contents.
{ [key: string]: unknown; }
- toString
Note: `toString()` is internally used by `console.log(...)` / `console.error(...)` when ingesting logs in Oxygen production. Therefore, we want to make sure that the error message is as informative as possible instead of `[object Object]`.
() => string
- toJSON
Note: toJSON` is internally used by `JSON.stringify(...)`. The most common scenario when this error instance is going to be stringified is when it's passed to Remix' `json` and `defer` functions: e.g. `{promise: storefront.query(...)}`. In this situation, we don't want to expose private error information to the browser so we only do it in development.
() => Pick<GraphQLError, "path" | "name" | "message" | "extensions" | "locations" | "stack">
- __@toStringTag@685
string
- name
string
- message
string
- stack
string
export class GraphQLError extends Error {
/**
* If an error can be associated to a particular point in the requested
* GraphQL document, it should contain a list of locations.
*/
locations?: Array<{line: number; column: number}>;
/**
* If an error can be associated to a particular field in the GraphQL result,
* it _must_ contain an entry with the key `path` that details the path of
* the response field which experienced the error. This allows clients to
* identify whether a null result is intentional or caused by a runtime error.
*/
path?: Array<string | number>;
/**
* Reserved for implementors to extend the protocol however they see fit,
* and hence there are no additional restrictions on its contents.
*/
extensions?: {[key: string]: unknown};
constructor(
message?: string,
options: Pick<
GraphQLError,
'locations' | 'path' | 'extensions' | 'stack' | 'cause'
> & {
query?: string;
queryVariables?: GenericVariables;
requestId?: string | null;
clientOperation?: string;
} = {},
) {
const h2Prefix = options.clientOperation
? `[h2:error:${options.clientOperation}] `
: '';
const enhancedMessage =
h2Prefix +
message +
(options.requestId ? ` - Request ID: ${options.requestId}` : '');
super(enhancedMessage);
this.name = 'GraphQLError';
this.extensions = options.extensions;
this.locations = options.locations;
this.path = options.path;
this.stack = options.stack || undefined;
try {
this.cause = JSON.stringify({
...(typeof options.cause === 'object' ? options.cause : {}),
requestId: options.requestId,
...(process.env.NODE_ENV === 'development' && {
path: options.path,
extensions: options.extensions,
graphql: h2Prefix &&
options.query && {
query: options.query,
variables: JSON.stringify(options.queryVariables),
},
}),
});
} catch {
if (options.cause) this.cause = options.cause;
}
}
get [Symbol.toStringTag]() {
return this.name;
}
/**
* Note: `toString()` is internally used by `console.log(...)` / `console.error(...)`
* when ingesting logs in Oxygen production. Therefore, we want to make sure that
* the error message is as informative as possible instead of `[object Object]`.
*/
override toString() {
let result = `${this.name}: ${this.message}`;
if (this.path) {
try {
result += ` | path: ${JSON.stringify(this.path)}`;
} catch {}
}
if (this.extensions) {
try {
result += ` | extensions: ${JSON.stringify(this.extensions)}`;
} catch {}
}
result += '\n';
if (this.stack) {
// Remove the message line from the stack.
result += `${this.stack.slice(this.stack.indexOf('\n') + 1)}\n`;
}
return result;
}
/**
* Note: toJSON` is internally used by `JSON.stringify(...)`.
* The most common scenario when this error instance is going to be stringified is
* when it's passed to Remix' `json` and `defer` functions: e.g. `{promise: storefront.query(...)}`.
* In this situation, we don't want to expose private error information to the browser so we only
* do it in development.
*/
toJSON() {
const formatted: Pick<
GraphQLError,
'name' | 'message' | 'path' | 'extensions' | 'locations' | 'stack'
> = {name: 'Error', message: ''};
if (process.env.NODE_ENV === 'development') {
formatted.name = this.name;
formatted.message = 'Development: ' + this.message;
if (this.path) formatted.path = this.path;
if (this.locations) formatted.locations = this.locations;
if (this.extensions) formatted.extensions = this.extensions;
// Skip stack on purpose because we don't want to expose it to the browser.
}
return formatted;
}
}
CustomerAccountQueries
export interface CustomerAccountQueries {
// Example of how a generated query type looks like:
// '#graphql query q1 {...}': {return: Q1Query; variables: Q1QueryVariables};
}
Storefront
Interface to interact with the Storefront API.
- cache
Cache
- CacheCustom
(overrideOptions: AllCacheOptions) => AllCacheOptions
- CacheLong
(overrideOptions?: AllCacheOptions) => AllCacheOptions
- CacheNone
() => NoStoreStrategy
- CacheShort
(overrideOptions?: AllCacheOptions) => AllCacheOptions
- generateCacheControlHeader
(cacheOptions: AllCacheOptions) => string
- getApiUrl
(props?: Partial<Pick<StorefrontClientProps, "storefrontApiVersion" | "storeDomain">>) => string
- getPrivateTokenHeaders
(props?: Partial<Pick<StorefrontClientProps, "contentType">> & Pick<StorefrontClientProps, "privateStorefrontToken"> & { buyerIp?: string; }) => Record<string, string>
- getPublicTokenHeaders
(props?: Partial<Pick<StorefrontClientProps, "contentType">> & Pick<StorefrontClientProps, "publicStorefrontToken">) => Record<string, string>
- getShopifyDomain
(props?: Partial<Pick<StorefrontClientProps, "storeDomain">>) => string
- i18n
TI18n
- mutate
<OverrideReturnType extends unknown = never, RawGqlString extends string = string>(mutation: RawGqlString, ...options: IsOptionalVariables<StorefrontMutations[RawGqlString]["variables"], AutoAddedVariableNames, Omit<StorefrontMutations[RawGqlString]["variables"], AutoAddedVariableNames>> extends true ? [(StorefrontCommonExtraParams & ClientVariables<StorefrontMutations, RawGqlString, AutoAddedVariableNames, "variables", RawGqlString extends never ? SetOptional<StorefrontMutations[RawGqlString]["variables"], Extract<keyof StorefrontMutations[RawGqlString]["variables"], AutoAddedVariableNames>> : { readonly [variable: string]: unknown; }, Record<"variables", RawGqlString extends never ? SetOptional<StorefrontMutations[RawGqlString]["variables"], Extract<keyof StorefrontMutations[RawGqlString]["variables"], AutoAddedVariableNames>> : { readonly [variable: string]: unknown; }>>)?] : [StorefrontCommonExtraParams & ClientVariables<StorefrontMutations, RawGqlString, AutoAddedVariableNames, "variables", RawGqlString extends never ? SetOptional<StorefrontMutations[RawGqlString]["variables"], Extract<keyof StorefrontMutations[RawGqlString]["variables"], AutoAddedVariableNames>> : { readonly [variable: string]: unknown; }, Record<"variables", RawGqlString extends never ? SetOptional<StorefrontMutations[RawGqlString]["variables"], Extract<keyof StorefrontMutations[RawGqlString]["variables"], AutoAddedVariableNames>> : { readonly [variable: string]: unknown; }>>]) => Promise<ClientReturn<StorefrontMutations, RawGqlString, OverrideReturnType> & StorefrontError>
- query
<OverrideReturnType extends unknown = never, RawGqlString extends string = string>(query: RawGqlString, ...options: IsOptionalVariables<StorefrontQueries[RawGqlString]["variables"], AutoAddedVariableNames, Omit<StorefrontQueries[RawGqlString]["variables"], AutoAddedVariableNames>> extends true ? [(StorefrontCommonExtraParams & Pick<StorefrontQueryOptions, "cache"> & ClientVariables<StorefrontQueries, RawGqlString, AutoAddedVariableNames, "variables", RawGqlString extends never ? SetOptional<StorefrontQueries[RawGqlString]["variables"], Extract<keyof StorefrontQueries[RawGqlString]["variables"], AutoAddedVariableNames>> : { readonly [variable: string]: unknown; }, Record<"variables", RawGqlString extends never ? SetOptional<StorefrontQueries[RawGqlString]["variables"], Extract<keyof StorefrontQueries[RawGqlString]["variables"], AutoAddedVariableNames>> : { readonly [variable: string]: unknown; }>>)?] : [StorefrontCommonExtraParams & Pick<StorefrontQueryOptions, "cache"> & ClientVariables<StorefrontQueries, RawGqlString, AutoAddedVariableNames, "variables", RawGqlString extends never ? SetOptional<StorefrontQueries[RawGqlString]["variables"], Extract<keyof StorefrontQueries[RawGqlString]["variables"], AutoAddedVariableNames>> : { readonly [variable: string]: unknown; }, Record<"variables", RawGqlString extends never ? SetOptional<StorefrontQueries[RawGqlString]["variables"], Extract<keyof StorefrontQueries[RawGqlString]["variables"], AutoAddedVariableNames>> : { readonly [variable: string]: unknown; }>>]) => Promise<ClientReturn<StorefrontQueries, RawGqlString, OverrideReturnType> & StorefrontError>
{
query: <
OverrideReturnType extends any = never,
RawGqlString extends string = string,
>(
query: RawGqlString,
...options: ClientVariablesInRestParams<
StorefrontQueries,
RawGqlString,
StorefrontCommonExtraParams & Pick<StorefrontQueryOptions, 'cache'>,
AutoAddedVariableNames
>
) => Promise<
ClientReturn<StorefrontQueries, RawGqlString, OverrideReturnType> &
StorefrontError
>;
mutate: <
OverrideReturnType extends any = never,
RawGqlString extends string = string,
>(
mutation: RawGqlString,
...options: ClientVariablesInRestParams<
StorefrontMutations,
RawGqlString,
StorefrontCommonExtraParams,
AutoAddedVariableNames
>
) => Promise<
ClientReturn<StorefrontMutations, RawGqlString, OverrideReturnType> &
StorefrontError
>;
cache?: Cache;
CacheNone: typeof CacheNone;
CacheLong: typeof CacheLong;
CacheShort: typeof CacheShort;
CacheCustom: typeof CacheCustom;
generateCacheControlHeader: typeof generateCacheControlHeader;
getPublicTokenHeaders: ReturnType<
typeof createStorefrontUtilities
>['getPublicTokenHeaders'];
getPrivateTokenHeaders: ReturnType<
typeof createStorefrontUtilities
>['getPrivateTokenHeaders'];
getShopifyDomain: ReturnType<
typeof createStorefrontUtilities
>['getShopifyDomain'];
getApiUrl: ReturnType<
typeof createStorefrontUtilities
>['getStorefrontApiUrl'];
i18n: TI18n;
}
AllCacheOptions
Override options for a cache strategy.
- maxAge
The maximum amount of time in seconds that a resource will be considered fresh. See `max-age` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#:~:text=Response%20Directives-,max%2Dage,-The%20max%2Dage).
number
- mode
The caching mode, generally `public`, `private`, or `no-store`.
string
- sMaxAge
Similar to `maxAge` but specific to shared caches. See `s-maxage` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#s-maxage).
number
- staleIfError
Indicate that the cache should serve the stale response if an error occurs while revalidating the cache. See `stale-if-error` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-if-error).
number
- staleWhileRevalidate
Indicate that the cache should serve the stale response in the background while revalidating the cache. See `stale-while-revalidate` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-while-revalidate).
number
export interface AllCacheOptions {
/**
* The caching mode, generally `public`, `private`, or `no-store`.
*/
mode?: string;
/**
* The maximum amount of time in seconds that a resource will be considered fresh. See `max-age` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#:~:text=Response%20Directives-,max%2Dage,-The%20max%2Dage).
*/
maxAge?: number;
/**
* Indicate that the cache should serve the stale response in the background while revalidating the cache. See `stale-while-revalidate` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-while-revalidate).
*/
staleWhileRevalidate?: number;
/**
* Similar to `maxAge` but specific to shared caches. See `s-maxage` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#s-maxage).
*/
sMaxAge?: number;
/**
* Indicate that the cache should serve the stale response if an error occurs while revalidating the cache. See `stale-if-error` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-if-error).
*/
staleIfError?: number;
}
NoStoreStrategy
- mode
string
{
mode: string;
}
StorefrontMutations
Maps all the mutations found in the project to variables and return types.
export interface StorefrontMutations {
// Example of how a generated mutation type looks like:
// '#graphql mutation m1 {...}': {return: M1Mutation; variables: M1MutationVariables};
}
AutoAddedVariableNames
'country' | 'language'
StorefrontCommonExtraParams
- displayName
string
- headers
HeadersInit
- storefrontApiVersion
string
{
headers?: HeadersInit;
storefrontApiVersion?: string;
displayName?: string;
}
StorefrontError
- errors
StorefrontApiErrors
{
errors?: StorefrontApiErrors;
}
StorefrontApiErrors
JsonGraphQLError[] | undefined
JsonGraphQLError
ReturnType<GraphQLError['toJSON']>
StorefrontQueries
Maps all the queries found in the project to variables and return types.
export interface StorefrontQueries {
// Example of how a generated query type looks like:
// '#graphql query q1 {...}': {return: Q1Query; variables: Q1QueryVariables};
}
StorefrontQueryOptions
StorefrontCommonExtraParams & {
query: string;
mutation?: never;
cache?: CachingStrategy;
}
CachingStrategy
Use the `CachingStrategy` to define a custom caching mechanism for your data. Or use one of the pre-defined caching strategies: CacheNone, CacheShort, CacheLong.
- maxAge
The maximum amount of time in seconds that a resource will be considered fresh. See `max-age` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#:~:text=Response%20Directives-,max%2Dage,-The%20max%2Dage).
number
- mode
The caching mode, generally `public`, `private`, or `no-store`.
string
- sMaxAge
Similar to `maxAge` but specific to shared caches. See `s-maxage` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#s-maxage).
number
- staleIfError
Indicate that the cache should serve the stale response if an error occurs while revalidating the cache. See `stale-if-error` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-if-error).
number
- staleWhileRevalidate
Indicate that the cache should serve the stale response in the background while revalidating the cache. See `stale-while-revalidate` in the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-while-revalidate).
number
AllCacheOptions
Example code
examples
Example code
description
I am the default example
JavaScript
import {createHydrogenContext} from '@shopify/hydrogen'; // @ts-expect-error import * as reactRouterBuild from 'virtual:react-router/server-build'; import { createRequestHandler, createCookieSessionStorage, } from '@shopify/remix-oxygen'; export default { async fetch(request, env, executionContext) { const waitUntil = executionContext.waitUntil.bind(executionContext); const [cache, session] = await Promise.all([ caches.open('hydrogen'), AppSession.init(request, [env.SESSION_SECRET]), ]); /* Create context objects required to use Hydrogen with your credentials and options */ const hydrogenContext = createHydrogenContext({ /* Environment variables from the fetch function */ env, /* Request object from the fetch function */ request, /* Cache API instance */ cache, /* Runtime utility in serverless environments */ waitUntil, session, }); const handleRequest = createRequestHandler({ build: reactRouterBuild, mode: process.env.NODE_ENV, /* Inject the customer account client in the Remix context */ getLoadContext: () => ({...hydrogenContext}), }); const response = await handleRequest(request); if (session.isPending) { response.headers.set('Set-Cookie', await session.commit()); } return response; }, }; class AppSession { isPending = false; static async init(request, secrets) { const storage = createCookieSessionStorage({ cookie: { name: 'session', httpOnly: true, path: '/', sameSite: 'lax', secrets, }, }); const session = await storage.getSession(request.headers.get('Cookie')); return new this(storage, session); } get(key) { return this.session.get(key); } destroy() { return this.sessionStorage.destroySession(this.session); } flash(key, value) { this.session.flash(key, value); } unset(key) { this.isPending = true; this.session.unset(key); } set(key, value) { this.isPending = true; this.session.set(key, value); } commit() { this.isPending = false; return this.sessionStorage.commitSession(this.session); } }
TypeScript
import {createHydrogenContext, type HydrogenSession} from '@shopify/hydrogen'; // @ts-expect-error import * as reactRouterBuild from 'virtual:react-router/server-build'; import { createRequestHandler, createCookieSessionStorage, type SessionStorage, type Session, } from '@shopify/remix-oxygen'; export default { async fetch(request: Request, env: Env, executionContext: ExecutionContext) { const waitUntil = executionContext.waitUntil.bind(executionContext); const [cache, session] = await Promise.all([ caches.open('hydrogen'), AppSession.init(request, [env.SESSION_SECRET]), ]); /* Create context objects required to use Hydrogen with your credentials and options */ const hydrogenContext = createHydrogenContext({ /* Environment variables from the fetch function */ env, /* Request object from the fetch function */ request, /* Cache API instance */ cache, /* Runtime utility in serverless environments */ waitUntil, session, }); const handleRequest = createRequestHandler({ build: reactRouterBuild, mode: process.env.NODE_ENV, /* Inject the customer account client in the Remix context */ getLoadContext: () => ({...hydrogenContext}), }); const response = await handleRequest(request); if (session.isPending) { response.headers.set('Set-Cookie', await session.commit()); } return response; }, }; class AppSession implements HydrogenSession { public isPending = false; constructor( private sessionStorage: SessionStorage, private session: Session, ) {} static async init(request: Request, secrets: string[]) { const storage = createCookieSessionStorage({ cookie: { name: 'session', httpOnly: true, path: '/', sameSite: 'lax', secrets, }, }); const session = await storage.getSession(request.headers.get('Cookie')); return new this(storage, session); } get(key: string) { return this.session.get(key); } destroy() { return this.sessionStorage.destroySession(this.session); } flash(key: string, value: any) { this.session.flash(key, value); } unset(key: string) { this.isPending = true; this.session.unset(key); } set(key: string, value: any) { this.isPending = true; this.session.set(key, value); } commit() { this.isPending = false; return this.sessionStorage.commitSession(this.session); } }