Skip to content

Commit

Permalink
♻️ the api to pass customerAccount into cart from the server
Browse files Browse the repository at this point in the history
  • Loading branch information
michenly committed Feb 7, 2024
1 parent d63e5a5 commit 1c9072a
Show file tree
Hide file tree
Showing 11 changed files with 167 additions and 52 deletions.
2 changes: 1 addition & 1 deletion .changeset/soft-sloths-double.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
---

🐛 Fix issue where customer login does not persist to checkout
✨ Add `customerLoggedIn` option to `cart.get()`. Where a `?logged_in=true` will be added to the checkoutUrl if a customer is logged in.
✨ Add `customerAccount` option to `createCartHandler`. Where a `?logged_in=true` will be added to the checkoutUrl for cart query if a customer is logged in.
132 changes: 109 additions & 23 deletions packages/hydrogen/docs/generated/generated_docs_data.json

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions packages/hydrogen/src/cart/createCartHandler.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {Storefront} from '../storefront';
import type {CustomerAccount} from '../customer/types';
import {type CartGetFunction, cartGetDefault} from './queries/cartGetDefault';
import {
type CartCreateFunction,
Expand Down Expand Up @@ -47,6 +48,7 @@ import {

export type CartHandlerOptions = {
storefront: Storefront;
customerAccount?: CustomerAccount;
getCartId: () => string | undefined;
setCartId: (cartId: string) => Headers;
cartQueryFragment?: string;
Expand Down Expand Up @@ -97,6 +99,7 @@ export function createCartHandler<TCustomMethods extends CustomMethodsBase>(
getCartId,
setCartId,
storefront,
customerAccount,
cartQueryFragment,
cartMutateFragment,
} = options;
Expand All @@ -113,6 +116,7 @@ export function createCartHandler<TCustomMethods extends CustomMethodsBase>(
const methods: HydrogenCart = {
get: cartGetDefault({
storefront,
customerAccount,
getCartId,
cartFragment: cartQueryFragment,
}),
Expand Down
46 changes: 25 additions & 21 deletions packages/hydrogen/src/cart/queries/cartGetDefault.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {StorefrontApiErrors, formatAPIResult} from '../../storefront';
import type {CustomerAccount} from '../../customer/types';
import type {CartQueryOptions, CartReturn} from './cart-types';
import type {
Cart,
Expand Down Expand Up @@ -29,43 +30,46 @@ type CartGetProps = {
numCartLines?: number;
};

type CartGetOptions = CartGetProps & {
customerLoggedIn?: Promise<boolean> | boolean;
};

export type CartGetFunction = (
cartGetOptions?: CartGetOptions,
cartInput?: CartGetProps,
) => Promise<CartReturn | null>;

export function cartGetDefault(options: CartQueryOptions): CartGetFunction {
return async (cartGetOptions?: CartGetOptions) => {
const cartId = options.getCartId();
type CartGetOptions = CartQueryOptions & {
/**
* The customer account client instance created by [`createCustomerAccountClient`](docs/api/hydrogen/latest/utilities/createcustomeraccountclient).
*/
customerAccount?: CustomerAccount;
};

export function cartGetDefault({
storefront,
customerAccount,
getCartId,
cartFragment,
}: CartGetOptions): CartGetFunction {
return async (cartInput?: CartGetProps) => {
const cartId = getCartId();

if (!cartId) return null;

const {customerLoggedIn, ...cartInput} = cartGetOptions || {};

const [isCustomerLoggedIn, {cart, errors}] = await Promise.all([
customerLoggedIn,
options.storefront.query<{
customerAccount ? customerAccount.isLoggedIn() : false,
storefront.query<{
cart: Cart;
errors: StorefrontApiErrors;
}>(CART_QUERY(options.cartFragment), {
}>(CART_QUERY(cartFragment), {
variables: {
cartId,
...cartInput,
},
cache: options.storefront.CacheNone(),
cache: storefront.CacheNone(),
}),
]);

const formattedResult = formatAPIResult(cart, errors);

if (isCustomerLoggedIn) {
return addCustomerLoggedInParam(isCustomerLoggedIn, formattedResult);
}

return formattedResult;
return formatAPIResult(
addCustomerLoggedInParam(isCustomerLoggedIn, cart),
errors,
);
};
}

Expand Down
2 changes: 1 addition & 1 deletion templates/demo-store/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export async function loader({request, context}: LoaderFunctionArgs) {
const layout = await getLayoutData(context);

const isLoggedInPromise = customerAccount.isLoggedIn();
const cartPromise = cart.get({customerLoggedIn: isLoggedInPromise});
const cartPromise = cart.get();

const seo = seoPayload.root({shop: layout.shop, url: request.url});

Expand Down
6 changes: 1 addition & 5 deletions templates/demo-store/app/routes/($locale).cart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@ import {useRootLoaderData} from '~/root';
export async function action({request, context}: ActionFunctionArgs) {
const {cart} = context;

const [formData, customerAccessToken] = await Promise.all([
request.formData(),
context.customerAccount.getAccessToken(),
]);
const formData = await request.formData();

const {action, inputs} = CartForm.getFormInput(formData);
invariant(action, 'No cartAction defined');
Expand Down Expand Up @@ -51,7 +48,6 @@ export async function action({request, context}: ActionFunctionArgs) {
case CartForm.ACTIONS.BuyerIdentityUpdate:
result = await cart.updateBuyerIdentity({
...inputs.buyerIdentity,
customerAccessToken,
});
break;
default:
Expand Down
1 change: 1 addition & 0 deletions templates/demo-store/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export default {

const cart = createCartHandler({
storefront,
customerAccount,
getCartId: cartGetIdDefault(request.headers),
setCartId: cartSetIdDefault(),
});
Expand Down
12 changes: 12 additions & 0 deletions templates/skeleton/app/lib/fragments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ export const CART_QUERY_FRAGMENT = `#graphql
id
checkoutUrl
totalQuantity
buyerIdentity {
countryCode
customer {
id
email
firstName
lastName
displayName
}
email
phone
}
lines(first: $numCartLines) {
nodes {
...CartLine
Expand Down
2 changes: 1 addition & 1 deletion templates/skeleton/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export async function loader({context}: LoaderFunctionArgs) {
const publicStoreDomain = context.env.PUBLIC_STORE_DOMAIN;

const isLoggedInPromise = customerAccount.isLoggedIn();
const cartPromise = cart.get({customerLoggedIn: isLoggedInPromise});
const cartPromise = cart.get();

// defer the footer query (below the fold)
const footerPromise = storefront.query(FOOTER_QUERY, {
Expand Down
1 change: 1 addition & 0 deletions templates/skeleton/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export default {
*/
const cart = createCartHandler({
storefront,
customerAccount,
getCartId: cartGetIdDefault(request.headers),
setCartId: cartSetIdDefault(),
cartQueryFragment: CART_QUERY_FRAGMENT,
Expand Down
11 changes: 11 additions & 0 deletions templates/skeleton/storefrontapi.generated.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,17 @@ export type CartApiQueryFragment = Pick<
StorefrontAPI.Cart,
'id' | 'checkoutUrl' | 'totalQuantity' | 'note'
> & {
buyerIdentity: Pick<
StorefrontAPI.CartBuyerIdentity,
'countryCode' | 'email' | 'phone'
> & {
customer?: StorefrontAPI.Maybe<
Pick<
StorefrontAPI.Customer,
'id' | 'email' | 'firstName' | 'lastName' | 'displayName'
>
>;
};
lines: {
nodes: Array<
Pick<StorefrontAPI.CartLine, 'id' | 'quantity'> & {
Expand Down

0 comments on commit 1c9072a

Please sign in to comment.