docs: added glossary functionality (#4805)

This commit is contained in:
Shahed Nasser
2023-08-18 17:07:00 +03:00
committed by GitHub
parent ac25c422a3
commit f5d8696123
8 changed files with 239 additions and 12 deletions

View File

@@ -8,20 +8,20 @@ In this document, you'll get an overview of Medusa's architecture to better unde
## Architecture Overview
Medusa's core package `@medusajs/medusa` is a Node.js backend built on top of [Express](https://expressjs.com/). It combines all the [**Commerce Modules**](../../modules/overview.mdx) that Medusa provides. Commerce Modules are ecommerce features that can be used as building blocks in an ecommerce ecosystem. Product is an example of a Commerce Module.
Medusa's core package `@medusajs/medusa` is a Node.js backend built on top of [Express](https://expressjs.com/). It combines all the [Commerce Modules](../../modules/overview.mdx) that Medusa provides. Commerce Modules are ecommerce features that can be used as building blocks in an ecommerce ecosystem. Product is an example of a Commerce Module.
![Medusa Core Architecture](https://res.cloudinary.com/dza7lstvk/image/upload/v1677607702/Medusa%20Docs/Diagrams/medusa-architecture-3_e385zk.jpg)
The backend connects to a **database**, such as [PostgreSQL](https://www.postgresql.org/), to store the ecommerce stores data. The tables in that database are represented by [**Entities**](../entities/overview.mdx), built on top of [Typeorm](https://typeorm.io/). Entities can also be reflected in the database using [**Migrations**](../entities/migrations/overview.mdx).
The backend connects to a database, such as [PostgreSQL](https://www.postgresql.org/), to store the ecommerce stores data. The tables in that database are represented by [Entities](../entities/overview.mdx), built on top of [Typeorm](https://typeorm.io/). Entities can also be reflected in the database using [Migrations](../entities/migrations/overview.mdx).
The retrieval, manipulation, and other utility methods related to that entity are created inside a [**Service**](../services/overview.mdx). Services are TypeScript or JavaScript classes that, along with other resources, can be accessed throughout the Medusa backend through [**dependency injection**](./dependency-injection.md).
The retrieval, manipulation, and other utility methods related to that entity are created inside a [Service](../services/overview.mdx). Services are TypeScript or JavaScript classes that, along with other resources, can be accessed throughout the Medusa backend through [dependency injection](./dependency-injection.md).
The backend does not have any tightly-coupled frontend. Instead, it exposes [**Endpoints**](../endpoints/overview.mdx) which are REST APIs that frontends such as an admin or a storefront can use to communicate with the backend. Endpoints are [Express routes](https://expressjs.com/en/guide/routing.html).
The backend does not have any tightly-coupled frontend. Instead, it exposes [Endpoints](../endpoints/overview.mdx) which are REST APIs that frontends such as an admin or a storefront can use to communicate with the backend. Endpoints are [Express routes](https://expressjs.com/en/guide/routing.html).
Medusa also uses an [**Events Architecture**](../events/index.mdx) to trigger and handle events. Events are triggered when a specific action occurs, such as when an order is placed. To manage this events system, Medusa connects to a service that implements a pub/sub model, such as [Redis](https://redis.io/).
Medusa also uses an [Events Architecture](../events/index.mdx) to trigger and handle events. Events are triggered when a specific action occurs, such as when an order is placed. To manage this events system, Medusa connects to a service that implements a pub/sub model, such as [Redis](https://redis.io/).
Events can be handled using [**Subscribers**](../events/subscribers.mdx). Subscribers are TypeScript or JavaScript classes that add their methods as handlers for specific events. These handler methods are only executed when an event is triggered.
Events can be handled using [Subscribers](../events/subscribers.mdx). Subscribers are TypeScript or JavaScript classes that add their methods as handlers for specific events. These handler methods are only executed when an event is triggered.
You can create any of the resources in the backends architecture, such as entities, endpoints, services, and more, as part of your custom development without directly modifying the backend itself. The Medusa backend uses [**loaders**](../loaders/overview.mdx) to load the backends resources, as well as your custom resources and resources in [**Plugins**](../plugins/overview.mdx).
You can create any of the resources in the backends architecture, such as entities, endpoints, services, and more, as part of your custom development without directly modifying the backend itself. The Medusa backend uses [loaders](../loaders/overview.mdx) to load the backends resources, as well as your custom resources and resources in [Plugins](../plugins/overview.mdx).
You can package your customizations into Plugins to reuse them in different Medusa backends or publish them for others to use. You can also install existing plugins into your Medusa backend.

View File

@@ -3,11 +3,13 @@ import { Tooltip as ReactTooltip } from "react-tooltip"
import type { ITooltip } from "react-tooltip"
import uuid from "react-uuid"
import "react-tooltip/dist/react-tooltip.css"
import clsx from "clsx"
type TooltipProps = {
text?: string
tooltipClassName?: string
html?: string
tooltipChildren?: React.ReactNode
} & React.HTMLAttributes<HTMLSpanElement> &
ITooltip
@@ -16,6 +18,8 @@ const Tooltip: React.FC<TooltipProps> = ({
tooltipClassName = "",
children,
html = "",
tooltipChildren,
...tooltipProps
}) => {
const [elementId, setElementId] = useState(null)
@@ -32,9 +36,12 @@ const Tooltip: React.FC<TooltipProps> = ({
</span>
<ReactTooltip
anchorId={elementId}
className={tooltipClassName}
className={clsx(tooltipClassName, "z-[399]")}
wrapper="span"
/>
{...tooltipProps}
>
{tooltipChildren}
</ReactTooltip>
</>
)
}

View File

@@ -43,8 +43,8 @@
--ifm-h4-font-size: var(--ifm-font-size-base);
/* Links */
--ifm-link-color: var(--ifm-color-primary);
--ifm-link-hover-color: var(--ifm-color-content);
--ifm-link-color: theme(colors.medusa.fg.interactive.DEFAULT);
--ifm-link-hover-color: theme(colors.medusa.fg.interactive.hover.DEFAULT);
--ifm-link-decoration: none;
--ifm-link-hover-decoration: none;
@@ -134,6 +134,10 @@ html[data-theme="dark"] {
--ifm-base-border-color: theme(colors.medusa.border.base.dark);
--ifm-strong-border-color: theme(colors.medusa.border.strong.dark);
/* Links */
--ifm-link-color: theme(colors.medusa.fg.interactive.DEFAULT);
--ifm-link-hover-color: theme(colors.medusa.fg.interactive.hover.DEFAULT);
/* Sidebar */
--ifm-menu-color: theme(colors.medusa.fg.subtle.dark);
--ifm-menu-color-active: theme(colors.medusa.fg.base.dark);

View File

@@ -174,7 +174,7 @@ export default function Admonition(props: Props): JSX.Element {
className={clsx(
"p-1 border border-solid border-medusa-border-base dark:border-medusa-border-base-dark rounded",
"bg-medusa-bg-subtle dark:bg-medusa-bg-base-dark shadow-none",
"[&_a]:no-underline [&_a]:text-medusa-fg-base dark:[&_a]:text-medusa-fg-base-dark hover:[&_a]:text-medusa-fg-subtle dark:hover:[&_a]:text-medusa-fg-subtle-dark",
"[&_a]:no-underline [&_a]:text-medusa-fg-interactive dark:[&_a]:text-medusa-fg-interactive-dark hover:[&_a]:text-medusa-fg-interactive-hover dark:hover:[&_a]:text-medusa-fg-interactive-hover-dark",
"mb-2 alert"
)}
>

View File

@@ -0,0 +1,46 @@
import React from "react"
import type { Props } from "@theme/MDXComponents/A"
import { getGlossaryByPath } from "../../utils/glossary"
import useDocusaurusContext from "@docusaurus/useDocusaurusContext"
import { MedusaDocusaurusContext } from "@medusajs/docs"
import Tooltip from "../../components/Tooltip"
import Link from "@docusaurus/Link"
import clsx from "clsx"
const MDXA = (props: Props) => {
const { href, children } = props
const {
siteConfig: { url },
} = useDocusaurusContext() as MedusaDocusaurusContext
// check if a glossary exists for href
const glossary =
(typeof children === "string" && href.startsWith("/")) || href.includes(url)
? getGlossaryByPath(children as string)
: null
if (!glossary) {
return <Link {...props} />
}
return (
<Tooltip
tooltipChildren={
<span className="flex flex-col gap-0.25 max-w-[200px]">
<span className="text-compact-small-plus text-medusa-fg-base dark:text-medusa-fg-base-dark">
{glossary.title}
</span>
<span className="text-compact-small">{glossary.content}</span>
</span>
}
clickable={true}
>
<Link
{...props}
className={clsx(props.className, "border-0 border-b border-dashed")}
/>
</Tooltip>
)
}
export default MDXA

View File

@@ -4,6 +4,7 @@ import MDXInlineCode from "@site/src/components/MDXComponents/InlineCode"
import CloudinaryImage from "@site/src/components/CloudinaryImage"
import MDXDetails from "./Details"
import MDXSummary from "./Summary"
import MDXA from "./A"
export default {
// Re-use the default mapping
@@ -12,4 +13,5 @@ export default {
img: CloudinaryImage,
details: MDXDetails,
summary: MDXSummary,
a: MDXA,
}

View File

@@ -32,6 +32,7 @@ declare module "@medusajs/docs" {
import { DocContextValue as DocusaurusDocContextValue } from "@docusaurus/theme-common/internal"
import { ReactNode } from "react"
import { NavbarLogo } from "@docusaurus/theme-common"
import type { DocusaurusContext } from "@docusaurus/types"
type ItemCustomProps = {
customProps?: {
@@ -168,4 +169,8 @@ declare module "@medusajs/docs" {
}
}
} & DocusaurusDocContextValue
export declare type MedusaDocusaurusContext = DocusaurusContext & {
siteConfig: MedusaDocusaurusConfig
}
}

View File

@@ -0,0 +1,163 @@
type GlossaryType = {
matchTextRegex: RegExp
ignoreTextRegex?: RegExp
title: string
content: string
}
const glossary: GlossaryType[] = [
{
title: "Migration",
content: "A script that is used to reflect changes to the database schema.",
matchTextRegex: /migration/i,
},
{
title: "Repository",
content:
"A class that provides generic methods to retrieve and manipulate entities.",
matchTextRegex: /(repository|repositories)/i,
},
{
title: "Entity",
content: "A class that represents a table in the database.",
matchTextRegex: /(entity|entities)/i,
},
{
title: "Dependency Injection",
content: "The act of delivering the required resources to a class",
matchTextRegex: /(dependency injection|dependency-injection)/i,
},
{
title: "Middleware",
content:
"A function that can be executed before or after endpoint requests are handled.",
matchTextRegex: /middleware/i,
},
{
title: "Endpoint",
content: "REST API exposed to frontends or external systems.",
matchTextRegex: /endpoint/i,
},
{
title: "Subscriber",
content: "A class that registers handler methods to an event.",
matchTextRegex: /subscriber/i,
},
{
title: "Module",
content:
"Reusable pieces of code that provide specific functionality or feature.",
matchTextRegex: /module/,
ignoreTextRegex: /commerce module/i,
},
{
title: "Loader",
content: "A script that runs when the Medusa backend starts.",
matchTextRegex: /loader/i,
},
{
title: "Scheduled Job",
content:
"A task that is performed at specific times during the Medusa backend's runtime.",
matchTextRegex: /scheduled job/i,
},
{
title: "Batch Job",
content: "A task that is performed asynchronously and iteratively.",
matchTextRegex: /batch job/i,
},
{
title: "Strategy",
content:
"A class that contains an isolated piece of logic that can be overridden and customized",
matchTextRegex: /(strategy|strategies)/i,
},
{
title: "Feature Flag",
content: "Guards beta features in the Medusa backend.",
matchTextRegex: /(feature-flag|feature flag)/i,
},
{
title: "Idempotency Key",
content:
"A unique, randomly-generated key associated with a process, such as cart completion.",
matchTextRegex: /(idempotency-key|idempotency key)/i,
},
{
title: "Search Service",
content:
"A class that implements an interface to provide search functionalities.",
matchTextRegex: /(search service|search-service)/i,
},
{
title: "File Service",
content:
"A class that implements an interface to provide storage functionalities.",
matchTextRegex: /(file service|file-service)/i,
},
{
title: "Notification Service",
content:
"A class that implements an interface to provide notification functionalities.",
matchTextRegex: /(notification service|notification-service)/i,
},
{
title: "Plugin",
content:
"A reusable NPM package that can be reused in Medusa backends and provide custom functionalities.",
matchTextRegex: /plugin/i,
ignoreTextRegex:
/(file-service plugin|file service plugin|notification service plugin|notification-service plugin|search service plugin|search-service plugin)/i,
},
{
title: "Service",
content: "A class that includes helper methods associated with an entity.",
matchTextRegex: /service/i,
ignoreTextRegex:
/(file-service|file service|notification service|notification-service|search service|search-service)/i,
},
{
title: "Publishable API Key",
content:
"An API key that is associated with a set of resources and used on the client (storefront) side.",
matchTextRegex: /(publishable-api-key|publishable api key)/i,
},
{
title: "JavaScript Client",
content:
"An NPM package that provides methods to interact with the Medusa backend's REST APIs.",
matchTextRegex: /(js-client|js client|medusa javascript client)/i,
},
{
title: "Medusa React",
content:
"An NPM package that provides React hooks and utility methods to interact with the Medusa backend's REST APIs.",
matchTextRegex: /(medusa-react|medusa react)/i,
},
{
title: "Admin Widget",
content:
"Custom React components that can be injected into different locations in the Medusa admin dashboard",
matchTextRegex: /admin widget/i,
},
{
title: "Admin UI Route",
content:
"A React component that is used to create a new page in the Medusa admin dashboard.",
matchTextRegex: /(admin route|admin UI route)/i,
},
{
title: "Admin Setting Page",
content:
"A React component that is used to create a new setting page in the Medusa admin dashboard",
matchTextRegex: /admin setting page/i,
},
]
export const getGlossary = () => [...glossary]
export const getGlossaryByPath = (path: string): GlossaryType | undefined => {
return glossary.find(
(g) => g.matchTextRegex.test(path) && !g.ignoreTextRegex?.test(path)
)
}