create Customer Client
This component is in an unstable pre-release state and may have breaking changes in a future release.
This component is in an unstable pre-release state and may have breaking changes in a future release.
Caution: This component is in an unstable pre-release state and may have breaking changes in a future release.
The function creates a GraphQL client for querying the Customer Account API. It also provides methods to authenticate and check if the user is logged in.
See an end to end example on using the Customer Account API client.
- Anchor to input1input1input1CustomerClientOptionsCustomerClientOptionsrequiredrequired
- loginlogin() => Promise<Response>() => Promise<Response>
Start the OAuth login flow. This function should be called and returned from a Remix action. It redirects the user to a login domain.
- authorizeauthorize(redirectPath?: string) => Promise<Response>(redirectPath?: string) => Promise<Response>
On successful login, the user is redirect 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.
- isLoggedInisLoggedIn() => Promise<boolean>() => Promise<boolean>
Returns if the user is logged in. It also checks if the access token is expired and refreshes it if needed.
- logoutlogout() => Promise<Response>() => Promise<Response>
Logout the user by clearing the session and redirecting to the login domain. It should be called and returned from a Remix action.
- queryquery<ReturnType = any, RawGqlString extends string = string>(query: RawGqlString, options?: { variables: Record<string, any>; }) => Promise<ReturnType><ReturnType = any, RawGqlString extends string = string>(query: RawGqlString, options?: { variables: Record<string, any>; }) => Promise<ReturnType>
Execute a GraphQL query against the Customer Account API. Usually you should first check if the user is logged in before querying the API.
- mutatemutate<ReturnType = any, RawGqlString extends string = string>(mutation: RawGqlString, options?: { variables: Record<string, any>; }) => Promise<ReturnType><ReturnType = any, RawGqlString extends string = string>(mutation: RawGqlString, options?: { variables: Record<string, any>; }) => Promise<ReturnType>
Execute a GraphQL mutation against the Customer Account API. Usually you should first check if the user is logged in before querying the API.
CustomerClient
CustomerClientOptions
- session
The client requires a session to persist the auth and refresh token. By default Hydrogen ships with cookie session storage, but you can use [another session storage](https://remix.run/docs/en/main/utils/sessions) implementation.
HydrogenSession - customerAccountId
Unique UUID prefixed with `shp_` associated with the application, this should be visible in the customer account api settings in the Hydrogen admin channel.
string - customerAccountUrl
The account URL associated with the application, this should be visible in the customer account api settings in the Hydrogen admin channel.
string - customerApiVersion
Override the version of the API
string - request
The object for the current Request. It should be provided by your platform.
CrossRuntimeRequest - 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.
ExecutionContext
HydrogenSession
- get
(key: string) => string - set
(key: string, value: string) => void - unset
(key: string) => void - commit
() => Promise<string>
CrossRuntimeRequest
- url
string - method
string - headers
{ [key: string]: any; get?: (key: string) => string; }
CustomerClient
- login
Start the OAuth login flow. This function should be called and returned from a Remix action. It redirects the user to a login domain.
() => Promise<Response> - authorize
On successful login, the user is redirect 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.
(redirectPath?: string) => Promise<Response> - isLoggedIn
Returns if the user is logged in. It also checks if the access token is expired and refreshes it if needed.
() => Promise<boolean> - logout
Logout the user by clearing the session and redirecting to the login domain. It should be called and returned from a Remix action.
() => Promise<Response> - query
Execute a GraphQL query against the Customer Account API. Usually you should first check if the user is logged in before querying the API.
<ReturnType = any, RawGqlString extends string = string>(query: RawGqlString, options?: { variables: Record<string, any>; }) => Promise<ReturnType> - mutate
Execute a GraphQL mutation against the Customer Account API. Usually you should first check if the user is logged in before querying the API.
<ReturnType = any, RawGqlString extends string = string>(mutation: RawGqlString, options?: { variables: Record<string, any>; }) => Promise<ReturnType>
Examples
Example code
Description
I am the default example
JavaScript
import {createCustomerClient__unstable} from '@shopify/hydrogen'; import * as remixBuild from '@remix-run/dev/server-build'; import { createRequestHandler, createCookieSessionStorage, } from '@shopify/remix-oxygen'; export default { async fetch(request, env, executionContext) { const session = await HydrogenSession.init(request, [env.SESSION_SECRET]); /* Create a Customer API client with your credentials and options */ const customer = createCustomerClient__unstable({ /* Runtime utility in serverless environments */ waitUntil: (p) => executionContext.waitUntil(p), /* Public Customer Account API token for your store */ customerAccountId: env.PUBLIC_CUSTOMER_ACCOUNT_ID, /* Public account URL for your store */ customerAccountUrl: env.PUBLIC_CUSTOMER_ACCOUNT_URL, request, session, }); const handleRequest = createRequestHandler({ build: remixBuild, mode: process.env.NODE_ENV, /* Inject the customer account client in the Remix context */ getLoadContext: () => ({customer}), }); return handleRequest(request); }, }; class HydrogenSession { 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.session.unset(key); } set(key, value) { this.session.set(key, value); } commit() { return this.sessionStorage.commitSession(this.session); } }TypeScript
import {createCustomerClient__unstable} from '@shopify/hydrogen'; import * as remixBuild from '@remix-run/dev/server-build'; import { createRequestHandler, createCookieSessionStorage, type SessionStorage, type Session, } from '@shopify/remix-oxygen'; export default { async fetch( request: Request, env: Record<string, string>, executionContext: ExecutionContext, ) { const session = await HydrogenSession.init(request, [env.SESSION_SECRET]); /* Create a Customer API client with your credentials and options */ const customer = createCustomerClient__unstable({ /* Runtime utility in serverless environments */ waitUntil: (p) => executionContext.waitUntil(p), /* Public Customer Account API client ID for your store */ customerAccountId: env.PUBLIC_CUSTOMER_ACCOUNT_ID, /* Public account URL for your store */ customerAccountUrl: env.PUBLIC_CUSTOMER_ACCOUNT_URL, request, session, }); const handleRequest = createRequestHandler({ build: remixBuild, mode: process.env.NODE_ENV, /* Inject the customer account client in the Remix context */ getLoadContext: () => ({customer}), }); return handleRequest(request); }, }; class HydrogenSession { 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.session.unset(key); } set(key: string, value: any) { this.session.set(key, value); } commit() { return this.sessionStorage.commitSession(this.session); } }