Skip to content

Commit

Permalink
Merge branch 'main' into filrak-patch-2
Browse files Browse the repository at this point in the history
  • Loading branch information
filrak authored Dec 5, 2023
2 parents 9787609 + 9dbbaea commit 1e19cbe
Show file tree
Hide file tree
Showing 80 changed files with 10,018 additions and 10,547 deletions.
Empty file modified .husky/pre-commit
100644 → 100755
Empty file.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ Continue with the configuration steps described in the documentation for your in

## **Contribution** 🤝

Vue Storefront is an Open Source project and we encourage everyone to help us making it better. If you are interested in contributing to the project, please read our [Contributing Guide](https://github.com/vuestorefront/vue-storefront/blob/main/CONTRIBUTING.md) and [Code of Conduct](https://github.com/vuestorefront/vue-storefront/blob/main/CODE_OF_CONDUCT.md).
Vue Storefront is an Open Source project and we encourage everyone to help us making it better. If you are interested in contributing to the project, please read our [Contributing Guide](https://github.com/vuestorefront/.github/blob/main/CONTRIBUTING.md) and [Code of Conduct](https://github.com/vuestorefront/.github/blob/main//CODE_OF_CONDUCT.md).

If you have any questions about contributing, please join our [Discord server](https://discord.vuestorefront.io/) - we are happy to help you!

Expand Down
13 changes: 8 additions & 5 deletions docs/content/1.index.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,24 @@ Learn more
:card{to="/general" title="What is Vue Storefront?" description="New here? Learn about all the different ways Vue Storefront can help you build with performant websites." icon="ri:book-2-fill"}

#section-2
:card{to="/integrations" title="Integrations" description="Connect to the third-party services you need to run your storefront, all through one consistent pattern." icon="ri:terminal-box-fill"}
:card{to="/storefront" title="Storefront" description="Build your next storefront with a world-class e-commerce Accelerator." icon="material-symbols:storefront"}

#section-3
:card{to="https://docs.storefrontui.io" title="Storefront UI" description="Implement your design system with our ready to customize UI elements built for e-commerce" icon="IconStorefrontUi" }
:card{to="/integrations" title="Integrations" description="Connect to the third-party services you need to run your storefront, all through one consistent pattern." icon="ri:terminal-box-fill"}

#section-4
:card{to="/cloud" title="Cloud" description="Deploy with confidence with production-grade cloud hosting for your Vue Storefront applications" icon="ri:cloud-fill"}
:card{to="https://docs.storefrontui.io" title="Storefront UI" description="Implement your design system with our ready to customize UI elements built for e-commerce" icon="IconStorefrontUi" }

#section-5
:card{to="/console" title="Console" description="Deploy, monitor, and manage your storefront with our cloud hosting platform " icon="ri:community-line"}
:card{to="/cloud" title="Cloud" description="Deploy with confidence with production-grade cloud hosting for your Vue Storefront applications" icon="ri:cloud-fill"}

#section-6
:card{to="/enterprise" title="Enterprise" description="Ready to take your storefront next to the next level? Reach out to sales to see how we can help you." icon="ri:store-3-fill"}
:card{to="/console" title="Console" description="Deploy, monitor, and manage your storefront with our cloud hosting platform " icon="ri:community-line"}

#section-7
:card{to="/enterprise" title="Enterprise" description="Ready to take your storefront next to the next level? Reach out to sales to see how we can help you." icon="ri:store-3-fill"}

#section-8
:card{to="https://docs.vuestorefront.io/v2" title="VSF v2 Docs" description="Looking for our v2 docs and Nuxt 2 integrations?" icon="IconVsf"}


Expand Down
6 changes: 0 additions & 6 deletions docs/content/2.general/1.index.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,6 @@ With Vue Storefront's Middleware and SDK, you can connect to different platforms
:card{to="/middleware" title="Middleware" description="Integrate and orchestrate all your API's" icon="fa6-solid:layer-group"}

#section-3
:card{to="/storefronts" title="Storefronts" description="Accelerate your development with pre-built, customizable, and fully functional projects" icon="material-symbols:storefront"}

#section-4
:card{to="https://docs.storefrontui.io" title="Storefront UI" description="Our open-source component library built for e-commerce" icon="IconStorefrontUi"}
::

Expand All @@ -91,7 +88,4 @@ Our demo Storefront is using:
::grid{:columns="2"}
#section-1
:card{to="https://demo.vuestorefront.io" title="Demo" description="Check out our demo storefront to see how a generic Vue Storefront project look like" icon="pepicons-pencil:internet"}

#section-2
:card{to="/storefronts" title="Storefronts" description="Demo Storefront is just one of many. We support leading meta-frameworks from Vue and React ecosystems. See what else is available!" icon="material-symbols:storefront"}
::
2 changes: 1 addition & 1 deletion docs/content/2.general/3.basics/3.architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Let’s see how our products fit into the typical headless architecture. Each ad
- [**SDK**](/sdk) (Frontend integration layer) - Ensures the connection with Middleware is stable, and responses are fully typed.
- [**Middleware**](/middleware) (Backend integration layer) - Connects third-party vendors and exposes a single API for the frontend.
- [**Console**](/console) - (Hosting and monitoring platform) - Multi-region SaaS hosting platform for your storefront and middleware with observability monitoring and analytics
- [**Storefront**](/storefronts) (Project Accelerator) - A ready-to-use Storefront Accelerator that is using all of the above products and is already connected to your eCommerce, CMS, Search and Payment vendors (we will talk about integrations in a moment!)
- [**Storefront**](/storefront) (Project Accelerator) - A ready-to-use Storefront Accelerator that is using all of the above products and is already connected to your eCommerce, CMS, Search and Payment vendors (we will talk about integrations in a moment!)

Storefront UI, SDK, Middleware, and Console are the barebones of your Vue Storefront application. Using them ensures that you’re applying state-of-the-art architecture that will protect the scalability and flexibility of your project.

Expand Down
1 change: 0 additions & 1 deletion docs/content/2.general/3.basics/4.data-flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ Every composable/hook in our storefront under the hood uses SDK methods. SDK met

At the very bottom of Storefront flow, an SDK method calls Vue Storefront Middleware. Let’s see how the data flows there!

:card{to="/storefronts" title="Storefronts" description="Storefronts lay out solid architectural foundations for your project and allow you to skip the repetitive groundwork." icon="material-symbols:storefront"}

## Middleware Data Flow

Expand Down
1 change: 0 additions & 1 deletion docs/content/2.general/4.next-steps/1.index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ One of the fastest ways to build a storefront is to use one of our pre-built sto

Depending on your stack, we may have a storefront that exactly matches the backends you're using. If not, you can use one of our boilerplates to have a good starting point for your project.

:card{to="/storefronts" title="Storefronts" description="Accelerate your development with pre-built, customizable, and fully functional projects" icon="material-symbols:storefront"}

## Start from Scratch

Expand Down
2 changes: 1 addition & 1 deletion docs/content/3.middleware/1.index.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Our different [integrations](/integrations) add onto the middleware to provide a

## Getting Started

If you're using one of our [storefronts](/storefronts), the middleware is set up for you. Our storefronts come with a middleware and frontend app already configured, so you can get started right away.
If you're using our storefront, the middleware is set up for you. Our storefronts come with a middleware and frontend app already configured, so you can get started right away.

But if you're building your Vue Storefront application from scratch, you'll need to set up the middleware to connect to your backend services.

Expand Down
13 changes: 0 additions & 13 deletions docs/content/3.middleware/2.guides/2.getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,6 @@

If you're building your Vue Storefront application from scratch, you'll need to set up the middleware to connect to your backend services.

::tip
#title
Use one of our storefronts to get this out of the box!
#default
Our storefronts and boilerplates come with a middleware and frontend app already configured, so you can get started right away.

:::div{class="mt-8 "}
::::docs-button{to="/storefronts"}
Take a look
::::
:::
::

## Creating the Application

Since the middleware is a separate app, it should be built outside of your frontend Vue Storefront application. We recommend using a monorepo to keep both applications in a single repository.
Expand Down
262 changes: 262 additions & 0 deletions docs/content/3.middleware/2.guides/4.orchestration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
# Orchestration

Orchestration is a powerful way to optimize server requests. This guide will take you through the key aspects of using the orchestration feature, focusing on integrating extensions and how to get the best out of your frontend code.

## Orchestration for Frontend Optimization

One of the primary advantages of orchestration is the ability to combine multiple requests into a single endpoint. This can drastically reduce the overhead on the frontend, especially in applications where numerous server requests might be initiated simultaneously.

### Benefits:

- Reduced Network Calls: Fewer calls to the server means reduced latency and faster performance.
- Simplified Frontend Logic: Grouping related server requests can help simplify frontend code and logic.
- Consistent Data Retrieval: With orchestration, you can ensure data from multiple integrations is fetched consistently and returned in a unified format.

### Implementation:

## The `getApiClient` Method

If you want to retrieve a loaded integration within the context of another, you can use the `getApiClient` method. This method serves as a bridge between various integrations, ensuring seamless data flow and interaction.

Usage:

```javascript
const sapcc = context.getApiClient("sapcc");
```

The `getApiClient` method takes a single argument, which is the key of the api client you wish to retrieve. This is the key you would define in the `middleware.config.js` file for the integration you wish to retrieve. The key is essentially an identifier for the integration.

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

```javascript
export const integrations = {
sapcc: {
location: "@vsf-enterprise/sapcc-api/server",
configuration: {
// ...
},
extensions: (extensions) => [
...extensions,
{
name: "sapcc-contentful-extension",
extendApiMethods: {
getPDP: async (context, params: { id: string }) => {
const sapcc = context.getApiClient("sapcc");
const contentful = context.getApiClient("contentful");

const [product, content] = Promise.all(
sapcc.api.getProduct({ id: params.id }),
contentful.api.getEntries({
content_type: "product",
"fields.sku": params.id,
})
);

return {
product,
content,
};
},
},
},
],
},
contentful: {
location: "@vsf-enterprise/contentful-api/server",
configuration: {
// ...
},
},
};
```

1. Extend the integration with new endpoint: Create a new endpoint that will act as the main entry point for the grouped requests.

2. Group Server Requests: Within this endpoint, utilize the `getApiClient` method to retrieve and interact with the required integrations.

3. Aggregate Data: Once data from all required integrations is retrieved, aggregate and format it as needed.

4. Return Unified Response: Send a consolidated response back to the frontend.:

### Using orchestration methods in the frontend

To call the orchestration endpoint, you need to send a POST request to the endpoint URL. In our example it would be `POST http://localhost:8080/sapcc/getPDP`. The request body should contain the parameters required by the endpoint.

When it comes to extending the Vue Storefront integrations like `sapcc` or `contentful`, you can use the SDK extension mechanism as described in the [Extending a Module](/sdk/advanced/extending-module) guide.

To extend the `sapcc-sdk` with our new `getPDP` method, we would need to create a new extension:

```javascript [sapccExtension.ts]
import { client } from "@vsf-enterprise/sapcc-sdk";

export const sapccExtension = {
extend: {
getPDP: async (params: { id: string }) => {
const { product, content } = await client.post("/getPDP", params);

return {
product,
content,
};
},
},
};
```

Of course, you can use another fetching mechanism, like `axios` or `fetch`, but the `client` is already configured with the correct URL and headers.

## Examples

Let's take a look at some examples of how you can use orchestration.

### Example 1: Fetching Custom Product Properties from Legacy Systems

This use case involves calling the commerce backend to fetch specific product data. Additionally, a separate call is made to a legacy custom system of the customer, to retrieve a custom product property (e.g., stock of the product). This data is used, for example, to display stock information on the product page.

Example implementation might look like this:

```typescript [middleware.config.ts]
export const integrations = {
sapcc: {
// ...
extensions: (extensions) => [
...extensions,
{
name: "orchestration-extension",
extendApiMethods: {
enrichedSearch: async (context, params: { productId: string }) => {
const sapcc = context.getApiClient("sapcc");
const legacyCustomSystem = context.getApiClient("legacyCustomSystem");

const prouctStock = await legacyCustomSystem.api.getProductStock({
productId: params.productId,
});

const product = await sapcc.api.getProduct({
{ id: params.productId },
});

return {
...product,
stock: productStock,
};
},
},
},
],
},
legacyCustomSystem: {
// ...
},
};
```

### Example 2: Product Slider Orchestration with Commerce Backend Data

In this scenario, the CMS returns a product slider component that lacks sufficient product data (or contains only product IDs). The orchestration layer enhances the product slider by adding product data from the commerce backend, ensuring a comprehensive and informative display.

```typescript [middleware.config.ts]
export const integrations = {
sapcc: {
// ...
extensions: (extensions) => [
...extensions,
{
name: "orchestration-extension",
extendApiMethods: {
getProductSlider: async (
context: IntegrationContext,
props: { entryId: string }
) => {
const contentful: ApiClient<ContentfulEndpoints> =
context.getApiClient("contentful");
const sapcc: ApiClient<SapccEndpoints> =
context.getApiClient("sapcc");

const content = await contentful.api.getEntry(props.entryId);
const productItems = await Promise.all(
content.fields.items.map(async (item) => {
const product = await sapcc.api.getProduct({
id: item.fields.productId,
});

return {
...item,
fields: {
...item.fields,
...product,
},
};
})
);

return {
...content,
fields: {
...content.fields,
items: productItems,
},
};
},
},
},
],
},
contentful: {
// ...
},
};
```

## TypeScript Support

`getApiClient` helper returns the `ApiClient` interface, which is a generic type. It takes three type arguments:

- `Api` - the type of the API object returned by the integration,
- `Config` - the type of the configuration object passed to the integration,
- `Client` - the type of the HTTP client object returned by the integration.

Usually, an integration exports those types. For example, the `sapcc` integration exports the following types:

```typescript
import {
Endpoints,
MiddlewareConfig,
AxiosInstance,
} 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
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.
:::
Loading

0 comments on commit 1e19cbe

Please sign in to comment.