Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(IN-3860): Update integrations-related docs #7075

Merged
merged 20 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 1 addition & 32 deletions docs/content/3.middleware/2.guides/4.orchestration.md
WojtekTheWebDev marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ The `getApiClient` method takes a single argument, which is the key of the api c

Here's a basic example of what this might look like:

```javascript
```typescript
export const integrations = {
sapcc: {
location: "@vsf-enterprise/sapcc-api/server",
WojtekTheWebDev marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -204,37 +204,6 @@ import {
} from "@vsf-enterprise/sapcc-api";
```

### Endpoints and the `context` object

Each method of the integration api client contains the `context` object as the first argument. However, the `context` is not something that is passed by the developer to the method during the call. This is because the `context` is passed automatically by the `@vue-storefront/middleware` package logic. Because of this, the `context` object should be excluded from the `Api` interface passed to the `ApiClient` type.

To achieve that, the `@vue-storefront/middleware` export the interface `ContextualizedApi`, which basically removes the context from the API.

### Example

Let's take a look at the `sapcc` integration. The `sapcc` integration exports the following types:

```typescript
import {
Endpoints,
MiddlewareConfig,
AxiosInstance,
} from "@vsf-enterprise/sapcc-api";
import { ContextualizedApi } from "@vue-storefront/middleware";

// ...

const sapcc = context.getApiClient<
ContextualizedApi<Endpoints>,
MiddlewareConfig,
AxiosInstance
>("sapcc");

// sapcc.api now is aware of the SAPCC methods that are not expecting the `context` object
// sapcc.config is now aware of the SAPCC configuration object
// sapcc.client is now aware of the SAPCC HTTP client object
```

:::tip Type of endpoints
WojtekTheWebDev marked this conversation as resolved.
Show resolved Hide resolved
Sometimes, the `Endpoints` type is not exported by the integration. If that's the case, you can import the `XyzIntegrationContext` type from the integration package. For example, the `sapcc` integration exports the `SapccIntegrationContext` type, which contains the endpoints type as `SapccIntegrationContext['api']`. It contains also the type of the configuration object as `SapccIntegrationContext['config']` and the type of the HTTP client object as `SapccIntegrationContext['client']`. This should be applied to all integrations.
:::
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# Creating an API Client
WojtekTheWebDev marked this conversation as resolved.
Show resolved Hide resolved



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

## Creating the integration client
Expand All @@ -12,7 +10,7 @@ First, you should create the `index.server.ts` file. It will be the entry point

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

const onCreate = (settings: any) => {
// TODO: create a client here and return it with the integration configuration
Expand All @@ -32,7 +30,7 @@ The `onCreate` function is called when the server middleware is initialized. It

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

Now, let's create the client.
Now, let's create the client.

:::tip
In the following example we used the `axios` library to create a client. However, you can use any client that you suits your needs.
WojtekTheWebDev marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -57,9 +55,9 @@ You should use the `MiddlewareConfig` interface in the `onCreate` function.

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

const buildClient = () => {
WojtekTheWebDev marked this conversation as resolved.
Show resolved Hide resolved
const axiosInstance = axios.create();
Expand Down Expand Up @@ -87,16 +85,11 @@ The server middleware can be initialized now, but it does not contain any API fu

WojtekTheWebDev marked this conversation as resolved.
Show resolved Hide resolved
```ts
// types/context/index.ts
import { IntegrationContext } from '@vue-storefront/middleware';
import { AxiosInstance } from 'axios';
import { MiddlewareConfig } from '../config';
import { IntegrationContext } from "@vue-storefront/middleware";
import { AxiosInstance } from "axios";
import { MiddlewareConfig } from "../config";

/**
* All available API Endpoints without first argument - `context`, because this prop is set automatically.
*/
export type ContextualizedEndpoints = {
[T in keyof Endpoints]: Endpoints[T] extends (x: any, ...args: infer P) => infer R ? (...args: P) => R : never;
};
export type TODO = any;

/**
* Runtime integration context, which includes API client instance, settings, and endpoints that will be passed via middleware server.
Expand All @@ -105,71 +98,91 @@ export type ContextualizedEndpoints = {
export type MyIntegrationIntegrationContext = IntegrationContext<
AxiosInstance, // HTTP client instance
MiddlewareConfig,
ContextualizedEndpoints
TODO
>;
```

/**
* Global context of the application which includes runtime integration context.
**/
export interface Context {
// This property is named `myIntegration`, but you should use your integration name in here.
$myIntegration: MyIntegrationIntegrationContext;
}
Now, you can create the first API method - an `exampleEndpoint` function.

```ts
// 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 });
};
```

The `ContextualizedEndpoints` type is a set of API functions without the `context` argument. It's necessary for the `IntegrationContext` type. It also requires the type of client used in the integration and the type of integration configuration.
You should also export the `exampleEndpoint` function in the `api/index.ts` file.

The `Context` type is the global context of the application. It's used by api-client methods to access the integration client and the configuration.
```ts
// api/index.ts
export * from "./exampleEndpoint";
```

Now you can add the interface for the API functions.
Then, let's create the `Endpoints` type.

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

type TODO = any;
export type ApiMethods = typeof apiMethods;

/**
* Definition of all API-client methods available in {@link https://docs.alokai.com/v2/advanced/context.html#context-api | context}.
*/
export interface Endpoints {
/**
* Here you can find an example endpoint definition. Based on this example, you should define how your endpoint will look like.
* This description will appear in the API extractor, so try to document all endpoints added here.
*/
exampleEndpoint: (context: MyIntegrationContext, params: TODO) => Promise<TODO>;
}
export type Endpoints = WithoutContext<ApiMethods>;
jagoral marked this conversation as resolved.
Show resolved Hide resolved
```

Finally, you can create the `exampleEndpoint` function.
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.

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

export const exampleEndpoint: Endpoints['exampleEndpoint'] = async (context, params) => {
console.log('exampleEndpoint has been called');
export type TODO = any;

// Example request could look like this:
// return await context.client.get(`example-url?id=${params.id}`);
return Promise.resolve({ success: true });
};
export type MyIntegrationIntegrationContext = IntegrationContext<
AxiosInstance, // HTTP client instance, you should use your client type here
MiddlewareConfig,
Endpoints
>;
```

You should also export the `exampleEndpoint` function in the `api/index.ts` file.
Remember to export all the types in the `types/index.ts` file.

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

And from `index.ts` as well.

```ts
// 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.

```ts
import { apiClientFactory } from '@vue-storefront/middleware';
import axios from 'axios';
import * as api from './api';
import { MiddlewareConfig } from './types/config';
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();
Expand Down Expand Up @@ -207,7 +220,7 @@ This guide described the details of creating the integration, but it does not co
module.exports = {
integrations: {
boilerplate: {
location: '@vsf-enterprise/my-integration-api/server', // This should be the path to your built index.server.js file
location: "@vsf-enterprise/my-integration-api/server", // This should be the path to your built index.server.js file
configuration: {
// Add your configuration here
},
Expand All @@ -220,20 +233,22 @@ You can run the server middleware with this example script:

```js
// server.js
const { createServer } = require('@vue-storefront/middleware');
const { integrations } = require('./middleware.config');
const cors = require('cors');
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 host = process.argv[2] ?? "0.0.0.0";
const port = process.argv[3] ?? 8181;
const CORS_MIDDLEWARE_NAME = 'corsMiddleware';
const CORS_MIDDLEWARE_NAME = "corsMiddleware";

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

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

Expand Down
4 changes: 2 additions & 2 deletions docs/content/4.sdk/1.index.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ By utilizing the Alokai SDK, you can establish a type-safe contract between your
The SDK has two components:

1. The SDK Core - the core package, `@vue-storefront/sdk`, that initializes all modules and implements the plug-in architecture
2. Modules - pluggable pieces of code as standalone packages that integrate into the core to add functionality (eg.: `@vsf-enterprise/sapcc-sdk`)
2. Modules - pluggable pieces of code as standalone packages that integrate into the core to add functionality (eg.: `middlewareModule`)

In most cases, these modules will come through our [Integrations](/integrations) - which contain both an SDK Module and an API Client (Middleware) - but you can also create your own modules.
In most cases, you would use `middlewareModule` with different configurations - but you can also create your own modules.

:card{to="/integrations" title="Integrations" description="See all of the available integrations that you can use with the SDK" icon="fluent:puzzle-cube-piece-20-filled"}

Expand Down
Loading
Loading