Skip to content

Commit

Permalink
Sanitize some docs
Browse files Browse the repository at this point in the history
  • Loading branch information
pozylon committed Jan 6, 2025
1 parent cdfcbf3 commit 3158ab9
Show file tree
Hide file tree
Showing 10 changed files with 348 additions and 191 deletions.
24 changes: 12 additions & 12 deletions docs/docs/Introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,27 @@ description: Overview
slug: /
---

**Unchained Engine is a high-performant, open-source, e-commerce framework for Node.js/Bun**
**Unchained Engine is a high-performance, open-source e-commerce framework for Node.js/Bun**

![diagram](./assets/System-Architecture.png)

#### Core Design Principes of Unchained Engine:
#### Core Design Principles of Unchained Engine:

- **Codeability**, so you can extend the system with endless possibilities not restricted by "customization" or a settings-approach
- **GraphQL API**, allowing you to build modern and fully omni-channel storefronts
- **Stateless architecture**, allowing you to scale horizontally and vertically
- **Low Overhead** because we value simplicity and speed! Unchained runs on Node.js 22/23 and Bun 1.1, is pure ESM and directly uses the native Mongo-DB driver instead of a clunky DB abstraction
- **Production readiness**, because it's been used for years by companies running big B2C and B2B portals with 20'000+ articles and 100 concurrent users
- **Codeability**: Extend the system with endless possibilities, unrestricted by "customization" or settings.
- **GraphQL API**: Build modern, fully omni-channel storefronts.
- **Stateless architecture**: Scale horizontally and vertically.
- **Low Overhead**: We value simplicity and speed! Unchained runs on Node.js 22/23 and Bun 1.1, is pure ESM, and directly uses the native MongoDB driver.
- **Production readiness**: Used by companies running large B2C and B2B portals with 20,000+ articles and 100 concurrent users.

### Solution Overview

The following diagram shows all applications and services provided by Unchained as open-source software for you to easily setup your first eCommerce store in a few minutes.
The following diagram shows all applications and services provided by Unchained as open-source software for you to easily set up your first eCommerce store in a few minutes.

![diagram](./assets/Unchained_Ecosystem.png)

As you can see the Unchained Engine ecosystem consists of
The Unchained Engine ecosystem consists of:

- the **Engine** itself as server-side only GraphQL API included app to serve all functionality to manage the store \*
- the **Storefront** boilerplate web app which provides a customizable UI for the public store itself as [Next.js](https://nextjs.org/) project
- The **Engine**: A server-side only GraphQL API to manage the store.
- The **Storefront**: A customizable UI for the public store, provided as a [Next.js](https://nextjs.org/) project.

The next chapter helps you setup an E-Commerce solution self-hosted.
The next chapter helps you set up a self-hosted e-commerce solution.
80 changes: 51 additions & 29 deletions docs/docs/concepts/architecture-overview.md
Original file line number Diff line number Diff line change
@@ -1,61 +1,83 @@
---
sidebar_position: 1
title: Overview
sidebar_label: Overview
sidebar_label: Overview
---

:::
System Design of Unchained Engine
:::
::: System Design of Unchained Engine :::

## Core Values

**Free and Open Source Software**

Usage of OSS prevents vendor lock-in. Using software that is open to the public leads to communities that help each other, the software is resilient to economic issues like bankruptcy of the software owner.
Using OSS prevents vendor lock-in and fosters a community that supports each other. It ensures resilience
against economic issues like the bankruptcy of the software owner.

**Hackable / Code-first**

Non-hackable software (like SaaS) use the technique of "customizing", meaning it provides a massive control panel where every aspect of the software can be configured, themed or disabled. Sadly, there is always something that needs some extra development work and companies need to hire somebody to create a plugin. In Unchained Engine, the software flow is changed through the code and not through the UI. This means a software developer is always required to configure the platform. It's called "hackable" software and allows to configure even parts of the software that were not intended to get configured by the core developers.
Unlike SaaS, which relies on extensive control panels for customization, Unchained Engine allows
configuration through code. This means a developer is always required, enabling customization even beyond
what the core developers intended.

**Headless / API-first**

User interfaces (like Web Shop Storefronts) rot at a much higher speed as the underlying processes and core systems. User interfaces change at a rapid speed: Technologies are born and die only a few years later, devices like smartwatches pop up, screen sizes vary. We think it's extremely important to have an e-commerce system that is going to stay for the long run like an ERP does, only then it's investable. By completely decoupling the Unchained Engine from any web shop user interface, it's usable in very flexible ways. But of course there are also [cons](https://www.semrush.com/blog/going-headless-ecommerce-store/) to that approach.
User interfaces evolve rapidly, while core systems remain stable. By decoupling the Unchained Engine from
any specific UI, it remains flexible and long-lasting. However, there are
[cons](https://www.semrush.com/blog/going-headless-ecommerce-store/) to this approach.

## Layered Approach

Unchained Engine is built in layers:

| Unchained Engine Layers |
| ----------------------------- |
| App |
| Platform |
| Service Gateway (Coming soon) |
| Core Modules |
| Unchained Engine Layers |
| ----------------------- |
| App |
| Platform |
| Service Gateway |
| Core Modules |

When you set up a new Unchained Engine project, you usually just boot the platform layer by running `startPlatform`.
When setting up a new project, you typically boot the platform layer by running `startPlatform`.

**App**
Unchained Engine is loaded as a framework into a common Node.js project. The user-land app is where your project and your custom project-specific code live.

**Platform** loads all the default core modules into a unified object, defines the GraphQL schema and resolvers, starts the API server, the work queue and orchestrates configuration of modules, e-mail templates and authentication. The packages "platform" and "api" both belong to the Platform Layer. In some very rare cases you might want to skip the it and directly access the core modules:
The user-land app is where your project-specific code lives, with Unchained Engine loaded as a framework
into a Node.js project.

**Platform**

The platform layer loads all default core modules, defines the GraphQL schema and resolvers, starts the
API server, work queue, and orchestrates module configuration, email templates, and authentication. The
"platform" and "api" packages belong to this layer. In rare cases, you might skip it to directly access
core modules, such as for federated microservices or custom APIs.

For extending the GraphQL API, adding payment or delivery options, or configuring core modules, check the
basic [configuration options](../config/booting) and [existing plugins](../plugins/plugin-overview.md)
first, then consult [advanced options](../advanced/overview).

- You want to use a very custom version of an existing core module
- You want to decompose the backend into federated microservices (run orders core-module on another instance for example)
- You want to have a custom made REST API instead of the GraphQL API
**Service Gateway**

You don't need to implement your own platform layer if you just want to extend the GraphQL Schema, add new job types or configure core-modules. For these cases, [configuration options](../config/booting) exist.
The service gateway composes functions from multiple modules to enable complex workflows, like checkout.
You can modify services by using or writing custom plugins and extend services by adding functions to
`startPlatform`
[options](https://docs.unchained.shop/types/interfaces/_unchainedshop_core.UnchainedCoreOptions.html).

**Service Gateway** composes functions of multiple modules together to enable sophisticated workflows like a checkout where many different modules have to play together. This layer does not exist yet as the modules currently just interdependent with each other.
**Core Modules**

**Core Modules** are thematically split up packages that contain business logic and database abstraction to allow a developer to influence the way the modules behave. You as a developer can change the way a module behaves by configuration and writing plugins.
Core modules contain business logic and database abstractions. You can modify modules through
configuration and plugins. To add or overwrite modules, check
[write custom modules](../advanced/custom-modules).

## API Design Principles:
## API Design Principles

1. Unchained is stateless and doesn‘t know browser sessions. All data is being held in MongoDB (persistent data, transactional data) or Redis (caching, Pub/Sub).
2. Non-logged in users can only read certain data, but not mutate anything. For cases where you need an anonymous user (like letting a client add stuff to cart and checkout without registration) you can use the loginAsGuest mutation that creates a temporary user.
3. All business logic should stay on the server-side, that way your E-Commerce project stays truly omni-channel and domain logic in the client is reduced to an absolute minimum.
1. Unchained is stateless, with all data stored in MongoDB.
2. Non-logged-in users can only read certain data. For anonymous user actions like adding to cart and
checkout, use the loginAsGuest mutation.
3. All business logic remains server-side, ensuring omni-channel support and minimal client-side domain
logic.

Some consequence of these design decisions:
Consequences of these principles:

1. In Unchained, carts are defined as „open orders“ and are stored server side. A user can add something to a cart on one device and then checkout on another. After checkout, the cart becomes an immutable order.
2. Anonymous users can become real users without loosing order history or bookmarks done as anonymous user. Carts even get merged together if somebody starts anonymously and decides to login during the process of buying a good.
1. Carts are defined as "open orders" and stored server-side, allowing users to add items on one device
and checkout on another. After checkout, the cart becomes an immutable order.
2. Anonymous users can become registered users without losing order history or bookmarks. Carts merge if
a user logs in during the buying process.
39 changes: 21 additions & 18 deletions docs/docs/concepts/cart-behavior.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,35 @@
---
sidebar_position: 2
title: Cart Behavior
description: Learn about the cart and it's advanced features
description: Learn about the cart and its advanced features
sidebar_label: Cart
---
# Cart Behavior


In Unchained, you can add products and quotations to carts, but only products will remain in the cart in the end. When adding products to the cart, they are transformed according to the following rules:
# Cart Behavior

Products:
- When adding a SimpleProduct or BundleProduct, the system adds the product to the cart with no transformation happening.
- When exploding a BundleProduct, it will be removed from the cart and its parts will be added to the cart.
- When adding a ConfigurableProduct, the system resolves to the concrete product if enough variation vector parameters are provided through the product configuration parameters. If not, the operation will fail. The variation configuration is stored on the resolved item along with the user-provided parameters.
In Unchained, you can add products and quotations to carts, but only products will remain in the cart in
the end. When adding products to the cart, they are transformed according to the following rules:

When one product leads to another, the source productId is saved in context.origin. This way, a SimpleProduct item still has a reference to the ConfigurableProduct for UX purposes.
**Products:**

Quotations:
When adding a Quotation to the cart, the actual product will be resolved and added to the cart. It uses the transform method of the quotation plugin system to transform a quotationConfiguration into a productConfiguration. The source quotationId is saved in context.origin.
- Adding a SimpleProduct or BundleProduct adds the product to the cart without transformation.
- Exploding a BundleProduct removes it from the cart and adds its parts instead.
- Adding a ConfigurableProduct resolves to a concrete product if enough variation parameters are
provided. Otherwise, the operation fails. The variation configuration is stored on the resolved item
along with user-provided parameters.

When one product leads to another, the source productId is saved in `orderPosition.originalProductId`, maintaining a
reference for UX purposes.

It is also possible to chain operations:
**Quotations:** When adding a Quotation to the cart, the actual product is resolved and added. The
quotation plugin system transforms a `quotationConfiguration` into a `productConfiguration`, and the
source quotationId is saved in `orderPosition.originalProductId`.

1. addCartQuotation is called with quotation Y
2. quotation Y is resolved to a configurable product X with a specific configuration
3. the specific configuration is handed to the vector logic to try to find a distinct concrete product Z
4. bundle product Z is resolved
**Chaining Operations:**

Now the cart looks like this (you guessed it):
1. `addCartQuotation` is called with quotation Y.
2. Quotation Y resolves to configurable product X with a specific configuration.
3. The configuration is handed to the vector logic to find a distinct concrete product Z.
4. Bundle product Z is resolved.

1 x Bundle Z (e.g. a piece of furniture)
The cart then looks like this: 1 x Bundle Z (e.g., a piece of furniture)
144 changes: 71 additions & 73 deletions docs/docs/concepts/search-behavior.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,92 +3,90 @@ sidebar_position: 3
title: Search Behavior
sidebar_label: Search
---
# Search Behavior
---
::::
Learn about the search feature
::::

Unchained provides you with the ability to search and filter products and assortments.
:::: Learn about the search feature ::::

Unchained allows you to search and filter products and assortments.

### Products Search

There are two ways to search for products in Unchained, first is a general search which is a common scenario where you'd want to search all products in your system.
There are two ways to search for products in Unchained:

```
query searchProducts($queryString: String, $limit: Int) {
searchProducts(queryString: $queryString, includeInactive: true) {
products {
_id
status
texts {
_id
title
description
}
media(limit: $limit) {
texts {
_id
title
}
file {
_id
url
name
}
}
}
}
}
```
There are multiple options available to further tailor your search result like orderBy, includeInactive, assortmentId.
1. **General Search**: Search all products in your system.

```graphql
query searchProducts($queryString: String, $limit: Int) {
searchProducts(queryString: $queryString, includeInactive: true) {
products {
_id
status
texts {
_id
title
description
}
media(limit: $limit) {
texts {
_id
title
}
file {
_id
url
name
}
}
}
}
}
```

The second one is Assortment.searchProducts which provides you with the ability to only search the products attach to an assortment.
Options include `orderBy`, `includeInactive`, and `assortmentId`.

```
query Assortment($assortmentId: ID) {
assortment(assortmentId: $assortmentId) {
...
searchProducts {
filteredProducts
filters {
filteredProducts
definition {
_id
}
isSelected
options {
filteredProducts
definition {
_id
}
isSelected
}
}
products {
_id
}
}
...
```
2. **Assortment Search**: Search products attached to a specific assortment.
```graphql
query Assortment($assortmentId: ID) {
assortment(assortmentId: $assortmentId) {
searchProducts {
filteredProducts
filters {
filteredProducts
definition {
_id
}
isSelected
options {
filteredProducts
definition {
_id
}
isSelected
}
}
products {
_id
}
}
}
}
```

### Assortments Search

Just like the products general search there's also a one available for products
Similar to the general product search, you can search for assortments:

```
query searchAssortments($queryString: String) {
searchAssortments(queryString: $queryString, includeInactive: true) {
assortments {
```graphql
query searchAssortments($queryString: String) {
searchAssortments(queryString: $queryString, includeInactive: true) {
assortments {
_id
isActive
texts {
_id
isActive
texts {
_id
title
description
}
title
description
}
}
}
```
}
```
4 changes: 2 additions & 2 deletions docs/docs/config/booting.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ The main entry point for unchained engine is `startPlatform` imported from `@unc
import { startPlatform } from '@unchainedshop/platform'

const unchainedAPI = await startPlatform({})

```

`startPlatform` returns the unchained api that lets you control all the modules and services defined. for example you can create seed the database with configurations like add currency, language, payment provider, admin accounts etc...

```typescript
Expand All @@ -36,8 +36,8 @@ await unchainedAPI.modules.users.createUser(
},
{ skipMessaging: true },
)

```

Its also possible to configure the platform with a little effort through the various configuration options available.
These options are available:
- `modules: Record<string, { configure: (params: ModuleInput<any>) => any }>`: Custom modules configuration point. allows you to extends the functionality the engine.
Expand Down
Loading

0 comments on commit 3158ab9

Please sign in to comment.