Vue Storefront is now Alokai! Learn More
LoginCustomer

LoginCustomer

Implements LoginCustomer Unified Method.

Source

import "./extended";
import { getNormalizers } from "@alokai/connect/integration-kit";
import { HttpStatusCode } from "@alokai/connect/middleware";
import type { SFCCIntegrationContext } from "@vsf-enterprise/sfcc-api";
import type { Customer } from "@vsf-enterprise/sfcc-types";
import { z } from "zod";

import { defineApi } from "@vsf-enterprise/unified-api-sfcc";

const argsSchema = z.object({
  email: z.string().email(),
  password: z.string().min(1),
});

const MESSAGE_LOGIN_ERROR = "Could not login customer";
const MESSAGE_ALREADY_LOGGED_IN = "Customer is already logged in";

export const loginCustomer = defineApi.loginCustomer(async (context, args) => {
  argsSchema.parse(args);

  const { api } = await context.getApiClient();
  const { email, password } = args;
  const { normalizeCustomer } = getNormalizers(context);
  let customerData: Customer;
  const basket = await api.getBasket();

  if (await isAlreadyLoggedIn(context)) {
    throw context.createHttpError({
      message: MESSAGE_ALREADY_LOGGED_IN,
      statusCode: HttpStatusCode.FORBIDDEN,
    });
  }

  try {
    customerData = await api.signIn({
      password: password,
      username: email,
    });
  } catch (error) {
    throw context.createHttpError({
      cause: error,
      message: MESSAGE_LOGIN_ERROR,
      statusCode: HttpStatusCode.UNAUTHORIZED,
    });
  }

  if (basket?.productItems?.length) {
    await api.setBasketCustomerInfo({
      basketId: basket.basketId,
      email: customerData.email!,
    });
  }

  return { customer: normalizeCustomer(customerData) };
});

async function isAlreadyLoggedIn(context: SFCCIntegrationContext) {
  const { api } = await context.getApiClient();
  try {
    const customer = await api.getCustomer();
    return !!customer.customerId;
  } catch {
    return false;
  }
}