Vue Storefront is now Alokai! Learn More
Creating an API Client

Creating an API Client

The API client is used by the server middleware to create a server-to-server communication with your custom backend.

Creating the integration client

To start, create a new folder called api-client in the src folder of your integration. This package will contain your integration API client.

First, you should create the index.server.ts file. It will be the entry point for the server middleware. It should look like this:

// index.server.ts
import { apiClientFactory } from "@vue-storefront/middleware";

const onCreate = (settings: any) => {
  // TODO: create a client here and return it with the integration configuration
};

const { createApiClient } = apiClientFactory({
  onCreate,
  api: {},
});

export { createApiClient };

The apiClientFactory is a function that creates a factory for creating API clients.

The onCreate function is called when the server middleware is initialized. It should return an object with the integration configuration and the client.

The api object is a set of functions that will be available in the integration client.

Now, let's create the client.

In the following example we used the axios library to create a client. However, you can use any client that suits your needs.

The buildClient function creates an instance of the axios client. It's a good practice to create a separate function for creating the client, so you can easily mock it in the tests.

The onCreate function accepts the integration configuration, and we recommend that you create an interface for it.

// types/config/index.ts

/**
 * Settings to be provided in the `middleware.config.js` file.
 */
export interface MiddlewareConfig {
  // Add the fields provided in the `middleware.config.js` file.
}

You should use the MiddlewareConfig interface in the onCreate function.

// index.server.ts
import { apiClientFactory } from "@vue-storefront/middleware";
import axios from "axios";
import { MiddlewareConfig } from "./types/config";

const buildClient = () => {
  const axiosInstance = axios.create();
  return axiosInstance;
};

const onCreate = (config: MiddlewareConfig) => {
  const client = buildClient();

  return {
    config,
    client,
  };
};

const { createApiClient } = apiClientFactory({
  onCreate,
  api: {},
});

export { createApiClient };

Now, we can initialize the server middleware, but it does not contain any API methods. Before adding them, let's create a type for the integration context.

// types/context/index.ts
import { IntegrationContext } from "@vue-storefront/middleware";
import { AxiosInstance } from "axios";
import { MiddlewareConfig } from "../config";

export type TODO = any;

/**
 * Runtime integration context, which includes API client instance, settings, and endpoints that will be passed via middleware server.
 * This interface name is starting with `MyIntegration`, but you should use your integration name in here.
 **/
export type MyIntegrationIntegrationContext = IntegrationContext<
  AxiosInstance, // HTTP client instance
  MiddlewareConfig,
  TODO
>;

Now, you can create the first API method - an exampleEndpoint function.

// api/exampleEndpoint/index.ts
import { MyIntegrationIntegrationContext, TODO } from "../../types";

export const exampleEndpoint = async (
  context: MyIntegrationIntegrationContext,
  params: TODO
) => {
  console.log("exampleEndpoint has been called");

  // Example request could look like this:
  // return await context.client.get(`example-url?id=${params.id}`);
  return Promise.resolve({ success: true });
};

You should also export the exampleEndpoint function in the api/index.ts file.

// api/index.ts
export * from "./exampleEndpoint";

Then, let's create the Endpoints type.

// types/api/endpoints.ts
import { WithoutContext } from "@vue-storefront/middleware";
import * as apiMethods from "../../api";

export type ApiMethods = typeof apiMethods;

export type Endpoints = WithoutContext<ApiMethods>;

Notice that we use the WithoutContext type from the @vue-storefront/middleware package. It's a utility type that removes the context parameter from the API methods. Server Middleware creates the context object based on the middleware configuration and request that has been made. The Endpoints interface should reflect only the available API endpoints.

Finally, let's add the Endpoints type to the MyIntegrationIntegrationContext interface.

// types/context/index.ts
import { IntegrationContext } from "@vue-storefront/middleware";
import { AxiosInstance } from "axios";
import { MiddlewareConfig } from "../config";
import { Endpoints } from "../api/endpoints";

export type TODO = any;

export type MyIntegrationIntegrationContext = IntegrationContext<
  AxiosInstance, // HTTP client instance, you should use your client type here
  MiddlewareConfig,
  Endpoints
>;

Remember to export all the types in the types/index.ts file.

// types/index.ts
export * from "./config";
export * from "./context";
export * from "./api/endpoints";

And from index.ts as well.

// index.ts
export * from "./types";

To be able to call the exampleEndpoint function, you should add it to the api object in the index.server.ts file.

import { apiClientFactory } from "@vue-storefront/middleware";
import axios from "axios";
import * as api from "./api";
import { MiddlewareConfig } from "./types/config";

const buildClient = () => {
  const axiosInstance = axios.create();
  return axiosInstance;
};

const onCreate = (settings: MiddlewareConfig) => {
  const client = buildClient();

  return {
    config: settings,
    client,
  };
};

const { createApiClient } = apiClientFactory({
  onCreate,
  api,
});

export { createApiClient };

Running the integration

Your integration is ready to use. You can test it by setting up the middleware.config.js file and running the middleware

Building your integration

This guide described the details of creating the integration, but it does not cover the details of the building process. You can find the tools and configuration we use by default in our integrations in our integration boilerplate repository

// middleware.config.js

module.exports = {
  integrations: {
    boilerplate: {
      location: "@vsf-enterprise/my-integration-api/server", // This should be the path to your built index.server.js file
      configuration: {
        // Add your configuration here
      },
    },
  },
};

You can run the server middleware with this example script:

// server.js
const { createServer } = require("@vue-storefront/middleware");
const { integrations } = require("./middleware.config");
const cors = require("cors");

(async () => {
  const app = await createServer({ integrations });
  const host = process.argv[2] ?? "0.0.0.0";
  const port = process.argv[3] ?? 8181;
  const CORS_MIDDLEWARE_NAME = "corsMiddleware";

  const corsMiddleware = app._router.stack.find(
    (middleware) => middleware.name === CORS_MIDDLEWARE_NAME
  );

  corsMiddleware.handle = cors({
    origin: ["http://localhost:3000"],
    credentials: true,
  });

  app.listen(port, host, () => {
    console.log(`Middleware started: ${host}:${port}`);
  });
})();

To run the middleware, you should run the following command:

node server.js

To call the endpoint, simply run a POST request to the http://localhost:8181/myIntegration/exampleEndpoint endpoint.