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.
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:
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.
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:
export const log = (message: string) => {
console.log(message);
};
Now, you can use the log
method in the connector.
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.
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.
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.
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!