diff --git a/www/docs/content/development/fundamentals/architecture-overview.md b/www/docs/content/development/fundamentals/architecture-overview.md index 0213a6b39c..b282cb9260 100644 --- a/www/docs/content/development/fundamentals/architecture-overview.md +++ b/www/docs/content/development/fundamentals/architecture-overview.md @@ -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 store’s 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 store’s 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 backend’s 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 backend’s resources, as well as your custom resources and resources in [**Plugins**](../plugins/overview.mdx). +You can create any of the resources in the backend’s 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 backend’s 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. diff --git a/www/docs/src/components/Tooltip/index.tsx b/www/docs/src/components/Tooltip/index.tsx index c42cfeb448..9cad94b244 100644 --- a/www/docs/src/components/Tooltip/index.tsx +++ b/www/docs/src/components/Tooltip/index.tsx @@ -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 & ITooltip @@ -16,6 +18,8 @@ const Tooltip: React.FC = ({ tooltipClassName = "", children, html = "", + tooltipChildren, + ...tooltipProps }) => { const [elementId, setElementId] = useState(null) @@ -32,9 +36,12 @@ const Tooltip: React.FC = ({ + {...tooltipProps} + > + {tooltipChildren} + ) } diff --git a/www/docs/src/css/_variables.css b/www/docs/src/css/_variables.css index 0bbc34efb2..b3eac87093 100644 --- a/www/docs/src/css/_variables.css +++ b/www/docs/src/css/_variables.css @@ -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); diff --git a/www/docs/src/theme/Admonition/index.tsx b/www/docs/src/theme/Admonition/index.tsx index fea68e5392..b5a31ea467 100644 --- a/www/docs/src/theme/Admonition/index.tsx +++ b/www/docs/src/theme/Admonition/index.tsx @@ -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" )} > diff --git a/www/docs/src/theme/MDXComponents/A.tsx b/www/docs/src/theme/MDXComponents/A.tsx new file mode 100644 index 0000000000..6676e2a05e --- /dev/null +++ b/www/docs/src/theme/MDXComponents/A.tsx @@ -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 + } + + return ( + + + {glossary.title} + + {glossary.content} + + } + clickable={true} + > + + + ) +} + +export default MDXA diff --git a/www/docs/src/theme/MDXComponents/index.tsx b/www/docs/src/theme/MDXComponents/index.tsx index 56c1477383..a76ae38bb7 100644 --- a/www/docs/src/theme/MDXComponents/index.tsx +++ b/www/docs/src/theme/MDXComponents/index.tsx @@ -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, } diff --git a/www/docs/src/types/index.d.ts b/www/docs/src/types/index.d.ts index e8d84a2589..3772644316 100644 --- a/www/docs/src/types/index.d.ts +++ b/www/docs/src/types/index.d.ts @@ -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 + } } diff --git a/www/docs/src/utils/glossary.ts b/www/docs/src/utils/glossary.ts new file mode 100644 index 0000000000..8f6b3f0b27 --- /dev/null +++ b/www/docs/src/utils/glossary.ts @@ -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) + ) +}