The Vue Storefront Essentials Course is now available! Learn More
Utilising SDK modules

Utilising SDK modules

Introduction

Vue Storefront SDK is a framework-agnostic communication layer in VSF Integrations. It communicates with Commerce Platforms and third-party services through the Server Middleware, which works as a proxy. Vue Storefront SDK creates a contract between the storefront and the Server Middleware.

The Unified SDK module is a module of the Vue Storefront SDK that allows you to interact with the Storefront API. It is designed to work seamlessly with other Vue Storefront SDK modules, such as those for various eCommerce platforms like SAP Commerce Cloud.

Architecture

The Vue Storefront SDK employs a microkernel architecture, consisting of the core Vue Storefront SDK and various modules that extend the microkernel's functionality. A SDK module can extend the core of Vue Storefront SDK in many different ways. In most cases, it would be a commerce module that communicates with:

  • a commerce backend,
  • a cms module that communicates with a CMS provider,
  • a payment module that communicates with a payment provider.

However, the SDK core can be extended with virtually any type of module and not only those created by Vue Storefront.

Installation

Based on the unified-storefront-demo repository template as a starting point.

To extend the install a new module, for instance the SAP Commerce Cloud, you'll need to follow the below steps:

Installing the middleware API module

Remember that each time you add an SDK module, it should have a relevant middleware API Client installed as well. In Storefront, the middleware API Client should be installed into the apps/storefront-middleware directory. Read more about each module's prerequisites in the SDK module documentation.

  1. Install the API Client (Middleware module).
yarn workspace storefront-middleware add @vsf-enterprise/sapcc-api
  1. Install the SDK Module (the client).
yarn workspace storefront-unified-nextjs add @vsf-enterprise/sapcc-sdk

The installation process for each module varies and may necessitate additional package installations. Be sure to consult the installation guide for the specific module you intend to use.

  1. Update apps/storefront-middleware/middleware.config.ts file.
  • Add new API-client integration to the config.
// apps/storefront-middleware/middleware.config.ts
const config = {
  integrations: {
      ...,
      sapcc: {
          location: '@vsf-enterprise/sapcc-api/server',
          configuration: {
              OAuth: {
                  uri: process.env.SAPCC_OAUTH_URI,
                  clientId: process.env.SAPCC_OAUTH_CLIENT_ID,
                  clientSecret: process.env.SAPCC_OAUTH_CLIENT_SECRET,
                  tokenEndpoint: process.env.SAPCC_OAUTH_TOKEN_ENDPOINT,
                  tokenRevokeEndpoint: process.env.SAPCC_OAUTH_TOKEN_REVOKE_ENDPOINT,
                  cookieOptions: {
                      'vsf-sap-token': { secure: process.env.NODE_ENV !== 'development' }
                  }
              },
              api: {
                  uri: process.env.SAPCC_API_URI,
                  baseSiteId: 'apparel-uk',
                  catalogId: 'apparelProductCatalog',
                  catalogVersion: 'Online',
                  defaultLanguage: 'en',
                  defaultCurrency: 'GBP'
              },
          }
      }
  },
};
  1. Update apps/storefront-unified-nextjs/sdk/index.ts file.
  • Add the new module inside initSDK function.
// apps/storefront-unified-nextjs/sdk/index.ts
import { sapccModule } from '@vsf-enterprise/sapcc-sdk';

export const sdk = initSDK({
  ...
  sapcc: buildModule(sapccModule, {
    apiUrl: `${API_BASE_URL}/sapcc`,
    ssrApiUrl: `${API_BASE_URL}/sapcc`,
  }),
});

Now you can use both sdk.unified.<methodName>, which returns the Unified Data Model, and sdk.sapcc.<methodName> which returns the raw data.

Real World Examples

Adding Product Reviews with SAP SDK

In this example, we'll create a custom React hook that utilizes useQuery and sdk.sapcc.createProductReview to add product reviews. We'll also create a form component for adding reviews and update the existing ProductReviews component to include the form.

Creating the useAddProductReview Hook

  1. Create a hooks/useAddProductReview/ directory.
  2. Create a new file useAddProductReview.ts in hooks/useAddProductReview/ directory.
  3. Import the necessary dependencies, including the useQuery hook and the SAP SDK module.
  4. Define the useAddProductReview() function hook.
  5. Implement the useAddProductReview() hook to utilize useQuery and the sdk.sapcc.createProductReview method to add a product review.
  6. Return the necessary variables and functions from the hook.
  7. Create a index.ts file in hooks/useAddProductReview/ directory.
  8. Update the index.ts in hooks/.
import { useMutation } from "@tanstack/react-query";
import { sdk } from "~/sdk";

export const useAddProductReview = (productCode: string) => {
  return useMutation(["addProductReview", productCode], ({ review }) =>
    sdk.sapcc.createProductReview({ productCode, review }),
  );
};

Now, create a index.ts file in hooks/useAddProductReview/ directory that exports a created hook:

export * from "./useAddProductReview";

Then update the index.ts in the hooks/ directory and export useAddProductReview module:

export * from "./useAddProductReview";

Creating the AddProductReviewForm Component

  1. Create AddProductReviewForm directory in components.
  2. Create a new file called AddProductReviewForm.tsx in the AddProductReviewForm directory.
  3. Import the necessary React components from the @storefront-ui library (e.g., SfInput, SfTextarea).
  4. Import the useAddProductReview hook.
  5. Define the AddProductReviewForm component as a functional component.
  6. Implement the form submission handler function that will utilize the createProductReview function from the useAddProductReview hook.
  7. Render the form fields and UI components using SFUI library.
  8. Export the AddProductReviewForm component for use in other components.
  9. Create a index.ts with exported AddProductReviewForm component.
  10. Update the index.ts in components.
import { useState } from 'react';
import { SfButton, SfInput, SfTextarea, SfRatingButton } from '@storefront-ui/react';
import useAddProductReview from '~/hooks';

export function AddProductReviewForm({ productId }) {
  const [title, setTitle] = useState('');
  const [rating, setRating] = useState(0);
  const [review, setReview] = useState('');

  const { mutate: createProductReview } = useAddProductReview(productId);

const handleSubmit: FormEventHandler<HTMLFormElement> = async (event) => {
  event.preventDefault();
  const reviewData = {
    alias: title,
    rating,
    comment: review,
  };
  createProductReview(
    { review: reviewData },
    {
      onSuccess() {
        // Handle successful review submission
        setTitle('');
        setRating(0);
        setReview('');
      },
      onError() {
        // Handle error
        console.error('Failed to submit product review:', error);
      },
    },
  );
};

  return (
    <div>
      <h3 className="my-3">Write a Review</h3>
      <form onSubmit={handleSubmit} className="space-y-5 mx-3">
        <div>
          <p id="rating">Select Rating</p>
          <SfRatingButton value={rating} onChange={setRating} aria-labelledby="rating" />
        </div>
        <div>
          <label htmlFor="title">Title:</label>
          <SfInput id="title" type="text" value={title} onChange={(event) => setTitle(event.target.value)} required />
        </div>
        <div>
          <label htmlFor="review" className="block">
            Review:
          </label>
          <SfTextarea
            id="review"
            className="w-full"
            value={review}
            onChange={(event) => setReview(event.target.value)}
            required
          />
        </div>
        <div>
          <SfButton type="submit">Submit Review</SfButton>
        </div>
      </form>
    </div>
  );
};

export default AddProductReviewForm;

Now create the index.ts file with the content:

export * from "./AddProductReviewForm";

And then update the index.ts in the components directory:

export * from "./AddProductReviewForm";

Updating the ProductReviews Component

  1. Import the AddProductReviewForm component into the existing ProductReviews component.
  2. Add the AddProductReviewForm component to the JSX of the ProductReviews component.
import { SfLoaderCircular } from "@storefront-ui/react";
import { SfProductReview } from "@vsf-enterprise/unified-api-sapcc";
import { useTranslation } from "next-i18next";
import type { ProductReviewsProps } from "~/components/ProductReviews/types";
import { Review } from "~/components/ui";
import { useProductReviews } from "~/hooks";
import { AddProductReviewForm } from "../AddProductReviewForm";

// ...

export function ProductReviews({ productId }: ProductReviewsProps) {
  // ...

  if (!reviewsList.length) {
    return (
      <>
        {t("noReviews")}
        <AddProductReviewForm />
      </>
    );
  }

  return (
    <>
      {/* Existing code for displaying product reviews */}
      {reviewsList.map((review) => (
        <Review
          className="mb-4"
          key={review.id}
          content={review.text ?? undefined}
          author={review.reviewer ?? undefined}
          title={review.title ?? undefined}
          rating={review.rating ?? undefined}
          date={getReviewDate(review)}
          showLessText={t("readLess")}
          showMoreText={t("readMore")}
        />
      ))}
      {/* Add product review form */}
      <AddProductReviewForm productId={productId} />
    </>
  );
}

export default ProductReviews;