Vue Storefront is now Alokai! Learn More
@vsf-enterprise/unified-api-sfcc

@vsf-enterprise/unified-api-sfcc

1.0.0

Major Changes

The version v1.0.0 of @vsf-enterprise/unified-api-[commerce] packages brings the following changes:

  • ✨ Simplified the extension initialization
  • 🛠️ A new addCustomFields API which simplifies adding custom fields to the normalizers
  • ⚠️ Deprecation of the unifiedSdk
  • 🔄 Redefined a way to add custom methods
  • 🔍 New utilities such as defineNormalizer which allow you to override the normalizer with the inferred typed of the raw data

Migration

If you are interested in migrating to the new version, check the Migration guide page.

Simplified the extension initialization

There is no need to pass the generics to the createUnifiedExtension, nor to pass the default normalizers and methods. Now all of them are built into the extension.

In examples, we are using sapcc package. Remember to replace it with the name of the commerce you are using.

- import {
-   Config,
-   Context,
-   createUnifiedExtension,
-   methods,
-   normalizers,
- } from "@vsf-enterprise/unified-api-sapcc";
+ import { createUnifiedExtension } from "@vsf-enterprise/unified-api-sapcc";

- export const unifiedApiExtension = createUnifiedExtension<Context, Config>()({
-   normalizers,
-   apiMethods: {
-    ...apiMethods,
-   },
+ export const unifiedApiExtension = createUnifiedExtension({
+ normalizers: {
+   addCustomFields: [{}],
+ },
  config: {
    ...
  },
});

addCustomFields API

The addCustomFields API allows you to add custom fields to the normalizers. The defineNormalizers utility have been removed and replaced with this API.

Before:

import { normalizers as normalizersSAP, defineNormalizers } from "@vsf-enterprise/unified-api-sapcc";

const normalizersSAP = defineNormalizers<typeof normalizersSAP>()({
  ...normalizersSAP,
  normalizeProductCatalogItem: (rawProduct) => ({
    ...normalizersSAP.normalizeProductCatalogItem(product, context),
    description: rawProduct.description,
  }),
});

export const unifiedApiExtension = createUnifiedExtension<Context, Config>()({
  normalizers,
  apiMethods: {
   ...apiMethods,
  },
  config: {
    ...
  }
});

Now:

export const unifiedApiExtension = createUnifiedExtension({
  normalizers: {
    addCustomFields: [
      {
        normalizeProductCatalogItem: (context, rawProduct) => ({
          description: rawProduct.description,
        }),
      },
    ],
  },
  config: {
    ...
  },
});

addCustomFields is an array, so you can easily split the custom fields into separate files or import the custom fields from other packages.

import { customFields } from "@example/module";
import { productCustomFields, cartCustomFields } from "./customFields";

export const unifiedApiExtension = createUnifiedExtension({
  normalizers: {
    addCustomFields: [
      productCustomFields,
      cartCustomFields,
      customFields,
    ],
  },
  config: {
    ...
  },
});

If you want to override the default normalizers, you can use the override key:

import { normalizers } from "@vsf-enterprise/unified-api-sapcc";

export const unifiedApiExtension = createUnifiedExtension({
  normalizers: {
    override: {
      normalizeProductCatalogItem: (context, rawProduct) => ({
        // to call the default normalizer
        ...normalizers.normalizeProductCatalogItem(context, rawProduct),
        name: `${rawProduct.name} - ${rawProduct.sku}`,
      }),
    },
  },
  config: {
    ...
  },
});

Deprecation of the unifiedSdk

The @vsf-enterprise/unified-sdk package has been deprecated. Now the same functionality can be achieved by using the @vue-storefront/sdk.

- import { unifiedModule } from '@vsf-enterprise/unified-sdk';
import { CreateSdkOptions, createSdk } from '@vue-storefront/next';
- import { UnifiedApiExtension } from 'storefront-middleware/middleware.config';
+ import { UnifiedEndpoints } from 'storefront-middleware/middleware.config';

-export const { getSdk } = createSdk(options, ({ buildModule, middlewareUrl, getRequestHeaders }) => ({
+export const { getSdk } = createSdk(options, ({ buildModule, middlewareUrl, getRequestHeaders, middlewareModule }) => ({
- unified: buildModule(unifiedModule<UnifiedApiExtension>, {
+ unified: buildModule(middlewareModule<UnifiedEndpoints>, {
    apiUrl: `${middlewareUrl}/commerce`,
-   requestOptions: {
-     headers: () => getRequestHeaders() as Record<string, string>,
+   defaultRequestConfig: {
+     headers: getRequestHeaders(),
    },
  }),

The middlewareModule can be used with any other extension, not only the Unified. It requires an endpoints type to be passed as a generic. An endpoint is just a record containing names of the methods and its contract:

export type MyEndpoints = {
  getProduct: (params: { id: string }) => Promise<Product>;
};

Redefined a way to add custom methods

Thanks to the middlewareModule you can now add custom methods to the SDK, by just implementing a new extension to the middleware.

import type { ContextualizedEndpoints, SAPIntegrationContext } from "@vsf-enterprise/sapcc-api"

export const customMethodsExtension = {
  name: "customMethods",
  extendApiMethods: {
    getProduct: async (context, params: { id: string }) => {
      // your implementation
    },
  },
} satisfies ApiClientExtension<ContextualizedEndpoints, SAPIntegrationContext>;

// the Endpoints type can be written manually, or inferred from the extension
export type CustomMethodsEndpoints = WithoutContext<CustomMethodsExtension["extendApiMethods"]>;

export const config = {
  location: "@vsf-enterprise/sapcc-api/server",
  configuration: {
    ...
  },
  extensions: (extensions: ApiClientExtension[]) => [
    ...extensions,
    unifiedApiExtension,
    // register your extension in extensions array
    customMethodsExtension,
  ],
} satisfies Integration<MiddlewareConfig>;

Then you can use it on the Storefront side, in the sdk.config.ts file add the new module:

  unified: buildModule(middlewareModule<UnifiedEndpoints>, {
    apiUrl: `${middlewareUrl}/commerce`,
    defaultRequestConfig: {
      headers: getRequestHeaders(),
    },
  }),
+ customExtension: buildModule(middlewareModule<CustomMethodsEndpoints>, {
+   apiUrl: `${middlewareUrl}/commerce`,
+   defaultRequestConfig: {
+     headers: getRequestHeaders(),
+   },
+ }),
  cms: buildModule(contentfulModule, {
    apiUrl: `${middlewareUrl}/cntf`,
  }),

You can now call the new method in the application:

sdk.customMethods.getProduct({ id: "123" });

This change is important in terms of the createUnifiedExtension API. Our goal is to make a clear separation between the Unified Methods, which are shared across all supported eCommerce backends, and your custom methods. This approach should help you in the future if you will decide to migrate to another eCommerce.

Now you you should implement every non-Unified Method in a separate extension.

export const unifiedApiExtension = createUnifiedExtension<Context, Config>()({
  apiMethods: {
    ...apiMethods,
-   customMethod: async (context, params) => {...}
  },
})
export const customMethodsExtension = {
  name: "customMethods",
  extendApiMethods: {
    getProduct: async (context, params: { id: string }) => {
      // your implementation
    },
+   customMethod: async (context, params) => {...}
  },
} satisfies ApiClientExtension<ContextualizedEndpoints, SAPIntegrationContext>;

If you want to override the Unified Method, you can use the override key:

export const unifiedApiExtension = createUnifiedExtension({
  apiMethods: {
    override: {
      getProduct: async (context, params) => {
        // your implementation
      },
    },
  },
});

Please remember that in this case, the parameters and return type of the method should be the same as in the Unified Method.

New utilities

defineNormalizer

You can split the override normalizer entries into separate variables. To get proper typings, you can use the defineNormalizer utility.

import { normalizers, defineNormalizer } from "@vsf-enterprise/unified-api-sapcc";

const normalizeProductCatalogItem = defineNormalizer.normalizeProductCatalogItem((context, rawProduct) => ({
  // to call the default normalizer
  ...normalizers.normalizeProductCatalogItem(context, rawProduct),
  name: `${rawProduct.name} - ${rawProduct.sku}`,
}));

export const unifiedApiExtension = createUnifiedExtension({
  normalizers: {
    override: {
      normalizeProductCatalogItem,
    },
  },
  config: {
    ...
  },
});

defineAddCustomFields

Similarly, you can use the defineAddCustomFields utility to split the custom fields into separate variables.

import { defineAddCustomFields } from "@vsf-enterprise/unified-api-sapcc";

const productCustomFields = defineAddCustomFields({
  normalizeProductCatalogItem: (context, rawProduct) => ({
    description: rawProduct.description,
  }),
});

export const unifiedApiExtension = createUnifiedExtension({
  normalizers: {
   addCustomFields: [productCustomFields],
  },
  config: {
    ...
  },
});

Patch Changes

  • ADDED beforeCall hook to Unified Extension, which set the defaultCurrency for vsf-locale, when vsf-locale is empty.
  • ADDED export getNormalizers from package

1.0.0-rc.1

Patch Changes

  • ADDED export getNormalizers from package

1.0.0-rc.0

Major Changes

First draft of v1.0.0

Patch Changes

  • ADDED beforeCall hook to Unified Extension, which set the defaultCurrency for vsf-locale, when vsf-locale is empty.

0.16.3

Patch Changes

  • CHANGED loginCustomer returns 403, when customer is already logged in.
  • FIXED After loginCustomer or registerCustomer, if the guest cart is not empty, it will be set as the customer cart. Previously a new, empty, cart was created for the customer every time they logged in or registered.

0.16.2

Patch Changes

  • CHANGED Required version of SFCC API Client to @vsf-enterprise/sfcc-api@^1.0.0-rc.12

0.16.1

Patch Changes

  • ADDED beforeCall hook to Unified Extension, which set the defaultCurrency for vsf-locale, when vsf-locale is empty.

0.16.0

Minor Changes

  • ADDED defineNormalizer utility which helps in overriding the normalizers. It should be used only when you want to override the default normalizers. If you want to add custom fields, you should still declare the normalizer within the defineNormalizers.
import {
  defineNormalizer,
  normalizers as normalizersSFCC,
  defineNormalizers,
} from "@vsf-enterprise/unified-api-sfcc";

const customNormalizeProduct = defineNormalizer.normalizeProduct(
  (rawProduct, ctx) => {
    // your implementation goes here, no custom fields
  },
);

const normalizers = defineNormalizers<typeof normalizersSFCC>()({
  ...normalizersSFCC,
  normalizeProduct: customNormalizeProduct,
  normalizeCart: (cart, context) => ({
    ...normalizersSFCC.normalizeCart(cart, context),
    // still use inline normalizer to add custom fields
    version: cart.version,
  }),
});
  • ADDED normalizers to NormalizerContext. You can now access the other normalizers from the context. This is useful when you want to reuse the existing normalizers in your custom normalizer.
const customNormalizeProduct = defineNormalizer.normalizeProduct(
  (rawProduct, ctx) => {
    // ctx.normalizers.normalizeMoney is now available
  },
);
  • REMOVED normalizeAttributes from normalizersSFCC. Now a normalizeAttribute should be used instead. The normalizeAttribute accepts as an input an object containing an array of variationAttributes and key and value of a single variation value.

Patch Changes

  • FIXED Normalizers such as normalizeMoney can be now overridden globally. This is useful when you want to change the way the money is represented accross the whole Unified extension.

0.15.3

Patch Changes

  • FIXED - getOrderDetails() API method resolves order data for authorized user.

0.15.2

Patch Changes

  • 04a9ef6: FIXED Allow 0 to be a valid shipping price in normalizeOrder

0.15.1

Patch Changes

  • a4d76f8: FIXED Handle null price and image_groups in normalizeAlgoliaProductCatalogItem in Algolia extension.

0.15.0

Minor Changes

  • 724a3a2: Exported NormalizerContext type

0.14.0

Minor Changes

  • 64b7b17: Added error handling on registerCustomer endpoint. Now if e-commerce response will be negative, unified endpoint return HTTP 400 with message Could not register customer

0.13.0

Minor Changes

  • 2ac49bc: Added support for Algolia. A separate sub-package available as @vsf-enterprise/unified-api-sfcc/algolia. Using this API methods you can easily replace the searchProduct endpoint to the one based on the Algolia API. For further information check the Algolia Integration chapter in the docs.

0.12.0

Minor Changes

  • 82a761c: - Unified Data Model model and methods integration.
    • UDM extension import:
      • import { createUnifiedExtension } from "@vsf-enterprise/unified-api-sfcc"
    • UDM model types import:
      • import { SfCategory, GetCategory } from "@vsf-enterprise/unified-api-sfcc"

0.11.0

Minor Changes

  • 98c8e77: Add new field categoryParentId to the SfCategory model.

0.10.2

Patch Changes

  • a856688: Updated unnormalizeAddres function to match new type reqiurements

0.10.1

Patch Changes

  • 459d20a: Update dependencies

0.10.0

Minor Changes

  • 8401301: Integrated normalization methods from the @vsf-enterprise/normalizer-sfcc library. Update imports for normalizer methods as follows:
    • import { normalizers } from "@vsf-enterprise/unified-api-sfcc"

0.9.0

Minor Changes

  • a912cf6: - Update searchProducts() API method:
    • remove categoryHierarchy, currentCategory & subCategories fields
    • Remove productCount field from SfCategory

Patch Changes

  • Updated dependencies a912cf6
    • @vsf-enterprise/normalizer-sfcc@0.9.0

0.8.0

Minor Changes

  • d514fe7: Implement a new GetCategory method which allows to get the category and its ancestors by category id.

0.7.0

Minor Changes

  • d3b0594: The searchProducts endpoint is updated to match the updated behavior of the unified-data-model. Removed the "latest" from the translated sort options, which wasn't available by default in SFCC. Still, all non-standard sorting options are passing by directly to the API request.

0.6.2

Patch Changes

  • 1f52ffa: Update dependencies

0.6.1

Patch Changes

  • b7cccc5: Update dependencies

0.6.0

Minor Changes

  • 6a3e0e8: Customize SfFacet type with getFacetType config method. Filter out facets data from searchProducts API method with filterFacets config method.

Patch Changes

  • Updated dependencies 6a3e0e8
    • @vsf-enterprise/normalizer-sfcc@0.8.0

0.5.2

Patch Changes

  • 027ba5cc: Fixed product discount on PLP

0.5.1

Patch Changes

  • f5d72f14: Update unified-data-model version

0.5.0

Minor Changes

  • 1df82d2c: Enhanced getCurrencies method to return current currency value
  • f5a32640: Unified error response for changeCustomerPassword. Now when currentPassword is invalid, a 403 error response will be returned.

Patch Changes

  • Updated dependencies 1df82d2c
    • @vue-storefront/unified-data-model@0.10.0

0.4.0

Minor Changes

  • Added endpoints for fetching list or user's orders and particular one. Also added necessary normalizers for SfOrder, SfOrderLineItem and SfOrderListItem.
  • Added placeOrder endpoint

Patch Changes

  • Updated dependencies:
    • @vsf-enterprise/normalizer-sfcc@0.7.0

0.3.2

Patch Changes

  • Fixed addCartLineItem for product variants
  • Fixed searchProducts's categoryHierarchy including selected category

0.3.1

Patch Changes

  • Changed the way of calculating SfDiscountedPrice to be based on comparing pricelists for given product.
  • Updated dependencies:
    • @vsf-enterprise/normalizer-sfcc@0.6.0

0.3.0

Minor Changes

  • Added endpoints for adding, removing & updating line items in cart
  • Implemented getProducts() api handler
  • Implemented setCartAddress method for checkout
  • Implemented setCustomerEmail method for checkout
  • Implemented getAvailableShippingMethods and setShippingMethod methods for checkout

Patch Changes

  • Created normalization function for SfCartLineItem. Updated getCart method to fetch product data for line items.
  • Updated dependencies:
    • @vsf-enterprise/normalizer-sfcc@0.5.0

0.2.0

Minor Changes

  • getCategories api method

Patch Changes

  • Updated dependencies:
    • @vsf-enterprise/normalizer-sfcc@0.3.0