Vue Storefront is now Alokai! Learn More
Custom modules

Custom modules

When is a custom module necessary?

Many times, the default middlewareModule is enough to handle the communication with the Server Middleware. You can achieve customizing the behavior and logic of the endpoints by extending the module.

However, you may need to create a module that doesn't communicate with the Server Middleware at all. For example, a logger module, or a module that is communicating with a third-party service directly and needs to run on the frontend. In this case, a custom module is the way to go.

Module

Let's start with the module itself. The module is a function that implements the Module interface. Frist, create a new directory sdk/modules/logger. Then, navigate to it and create a new file module.ts with the following code:

import { Module } from "@vue-storefront/sdk";

export const loggerModule = () => {
  return {
    connector: {},
    utils: {},
    subscribers: {},
  } satisfies Module;
};

The connector, utils, and subscribers are the parts of the module. The connector is the part that is responsible for the module's methods. The utils are the helper functions that can be used in the module. The subscribers are the functions that are called when the event is emitted.

Connector

The connector is the part of the module that is responsible for the module's methods. The connector is an object that contains the methods.

module.ts
import { Module } from "@vue-storefront/sdk";

export const loggerModule = () => {
  return {
    connector: {
      log: (message: string) => {
        console.log(message);
      },
    },
    utils: {},
    subscribers: {},
  } satisfies Module;
};

You can also separate the connector into a separate file. Create a new file connector.ts and add the following code:

connector.ts
import { Connector } from "@vue-storefront/sdk";

export const loggerConnector = () => {
  return {
    log: (message: string) => {
      console.log(message);
    },
  } satisfies Connector;
};

Now, the logger connector is in a separate file and can be used in the module.

module.ts
import { Module } from "@vue-storefront/sdk";
import { loggerConnector } from "./connector";

export const loggerModule = () => {
  return {
    connector: loggerConnector(),
    utils: {},
    subscribers: {},
  } satisfies Module;
};

Methods

To keep the connector clean, you can separate the methods into a separate file. Create a new file methods.ts and add the following code:

methods.ts
export const log = (message: string) => {
  console.log(message);
};

Now, you can use the log method in the connector.

connector.ts
import { Connector } from "@vue-storefront/sdk";
import * as methods from "./methods";

export const loggerConnector = () => {
  return {
    ...methods,
  } satisfies Connector;
};

Let's also make the methods more complex by extending their functionality. Let's assume that we want to log the message to the server as well.

methods.ts
export const log = (message: string) => {
  console.log(message);
  fetch("https://example.com/log", {
    method: "POST",
    body: JSON.stringify({ message }),
  });
};

Now, the log method is logging the message to the console and sending it to the server.

Utils

Utils are the helper functions that can be helpful when working with the module. For example, you can create a helper function that is adding a timestamp.

module.ts
import { Module } from "@vue-storefront/sdk";
import { loggerConnector } from "./connector";

export const loggerModule = () => {
  return {
    connector: loggerConnector(),
    utils: {
      formatMessage: (message: string) => {
        return `${new Date().toISOString()} - ${message}`;
      },
    },
    subscribers: {},
  } satisfies Module;
};

Subscribers

Subscribers are the functions that are called when the event is emitted. For example, you can create a subscriber that is logging the message to the server. You can learn more about the subscribers in the Subscribers docs.

module.ts
import { Module } from "@vue-storefront/sdk";
import { loggerConnector } from "./connector";

export const loggerModule = () => {
  return {
    connector: loggerConnector(),
    utils: {
      formatMessage: (message: string) => {
        return `${new Date().toISOString()} - ${message}`;
      },
    },
    subscribers: {
      "*_after": (payload) => {
        fetch("https://example.com/log", {
          method: "POST",
          body: JSON.stringify(payload),
        });
      },
    },
  } satisfies Module;
};

Now, the subscriber is logging the payload to the server after every method call of every SDK module.

Finally, you can use the module in your application.

import { initSdk, buildModule } from "@vue-storefront/sdk";
import { loggerModule } from "./module";

const sdk = initSdk({
  logger: buildModule(loggerModule),
});

sdk.utils.formatMessage(sdk.logger.log("Hello, World!")); // 2021-01-01T00:00:00.000Z - Hello, World!