docs: create docs workspace (#5174)
* docs: migrate ui docs to docs universe * created yarn workspace * added eslint and tsconfig configurations * fix eslint configurations * fixed eslint configurations * shared tailwind configurations * added shared ui package * added more shared components * migrating more components * made details components shared * move InlineCode component * moved InputText * moved Loading component * Moved Modal component * moved Select components * Moved Tooltip component * moved Search components * moved ColorMode provider * Moved Notification components and providers * used icons package * use UI colors in api-reference * moved Navbar component * used Navbar and Search in UI docs * added Feedback to UI docs * general enhancements * fix color mode * added copy colors file from ui-preset * added features and enhancements to UI docs * move Sidebar component and provider * general fixes and preparations for deployment * update docusaurus version * adjusted versions * fix output directory * remove rootDirectory property * fix yarn.lock * moved code component * added vale for all docs MD and MDX * fix tests * fix vale error * fix deployment errors * change ignore commands * add output directory * fix docs test * general fixes * content fixes * fix announcement script * added changeset * fix vale checks * added nofilter option * fix vale error
This commit is contained in:
33
www/apps/docs/src/utils/filter-list-items.ts
Normal file
33
www/apps/docs/src/utils/filter-list-items.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import {
|
||||
PropSidebarItem,
|
||||
PropSidebarItemLink,
|
||||
} from "@docusaurus/plugin-content-docs"
|
||||
|
||||
export default function filterListItems(
|
||||
items: PropSidebarItemLink[],
|
||||
pathPattern: string | RegExp
|
||||
): PropSidebarItemLink[] {
|
||||
if (!items.length) {
|
||||
return items
|
||||
}
|
||||
|
||||
const pattern = new RegExp(pathPattern)
|
||||
|
||||
return items.filter((item: PropSidebarItemLink) => pattern.test(item.href))
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatting a sidebar list moving items from category
|
||||
* to links
|
||||
*/
|
||||
export function flattenList(items: PropSidebarItem[]): PropSidebarItem[] {
|
||||
const newItems = items.map((item: PropSidebarItem) => {
|
||||
if (item.type !== "category") {
|
||||
return item
|
||||
}
|
||||
|
||||
return item.items
|
||||
})
|
||||
|
||||
return newItems.flat()
|
||||
}
|
||||
14
www/apps/docs/src/utils/get-first-category-item.ts
Normal file
14
www/apps/docs/src/utils/get-first-category-item.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import {
|
||||
findSidebarCategory,
|
||||
useDocsSidebar,
|
||||
} from "@docusaurus/theme-common/internal"
|
||||
import { PropSidebarItem } from "@docusaurus/plugin-content-docs"
|
||||
|
||||
export default function getFirstCategoryItem(
|
||||
categoryLabel: string
|
||||
): PropSidebarItem | undefined {
|
||||
return findSidebarCategory(
|
||||
useDocsSidebar().items,
|
||||
(item) => item.label === categoryLabel
|
||||
)?.items[0]
|
||||
}
|
||||
8
www/apps/docs/src/utils/get-os-shortcut.ts
Normal file
8
www/apps/docs/src/utils/get-os-shortcut.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export default function getOsShortcut() {
|
||||
const isMacOs =
|
||||
typeof navigator !== "undefined"
|
||||
? navigator.userAgent.toLowerCase().indexOf("mac") !== 0
|
||||
: true
|
||||
|
||||
return isMacOs ? "⌘" : "Ctrl"
|
||||
}
|
||||
192
www/apps/docs/src/utils/glossary.ts
Normal file
192
www/apps/docs/src/utils/glossary.ts
Normal file
@@ -0,0 +1,192 @@
|
||||
export type GlossaryType = {
|
||||
matchTextRegex: RegExp
|
||||
ignoreTextRegex?: RegExp
|
||||
title: string
|
||||
content: string
|
||||
referenceLink: string
|
||||
}
|
||||
|
||||
const glossary: GlossaryType[] = [
|
||||
{
|
||||
title: "Migration",
|
||||
content: "A script that is used to reflect changes to the database schema.",
|
||||
matchTextRegex: /migration/i,
|
||||
referenceLink: "/development/entities/migrations/overview",
|
||||
},
|
||||
{
|
||||
title: "Repository",
|
||||
content:
|
||||
"A class that provides generic methods to retrieve and manipulate entities.",
|
||||
matchTextRegex: /(repository|repositories)/i,
|
||||
referenceLink: "/development/entities/repositories",
|
||||
},
|
||||
{
|
||||
title: "Entity",
|
||||
content: "A class that represents a table in the database.",
|
||||
matchTextRegex: /(entity|entities)/i,
|
||||
referenceLink: "/development/entities/overview",
|
||||
},
|
||||
{
|
||||
title: "Dependency Injection",
|
||||
content:
|
||||
"Classes receive other resources, such as services or repositories, in their constructor using dependency injection.",
|
||||
matchTextRegex: /(dependency injection|dependency-injection)/i,
|
||||
referenceLink: "/development/fundamentals/dependency-injection",
|
||||
},
|
||||
{
|
||||
title: "Middleware",
|
||||
content:
|
||||
"A function that can be executed before or after endpoint requests are handled.",
|
||||
matchTextRegex: /middleware/i,
|
||||
referenceLink: "/development/endpoints/add-middleware",
|
||||
},
|
||||
{
|
||||
title: "Endpoint",
|
||||
content: "REST API routes exposed to frontends or external systems.",
|
||||
matchTextRegex: /endpoint/i,
|
||||
referenceLink: "/development/endpoints/overview",
|
||||
},
|
||||
{
|
||||
title: "Subscriber",
|
||||
content: "A class that registers handler methods to an event.",
|
||||
matchTextRegex: /subscriber/i,
|
||||
referenceLink: "/development/events/subscribers",
|
||||
},
|
||||
{
|
||||
title: "Module",
|
||||
content:
|
||||
"Reusable pieces of code, typically as NPM packages, that provide specific functionality or feature.",
|
||||
matchTextRegex: /module/,
|
||||
ignoreTextRegex: /commerce module/i,
|
||||
referenceLink: "/development/modules/overview",
|
||||
},
|
||||
{
|
||||
title: "Loader",
|
||||
content: "A script that runs when the Medusa backend starts.",
|
||||
matchTextRegex: /loader/i,
|
||||
referenceLink: "/development/loaders/overview",
|
||||
},
|
||||
{
|
||||
title: "Scheduled Job",
|
||||
content:
|
||||
"A task that is performed at specific times during the Medusa backend's runtime.",
|
||||
matchTextRegex: /scheduled job/i,
|
||||
referenceLink: "/development/scheduled-jobs/overview",
|
||||
},
|
||||
{
|
||||
title: "Batch Job",
|
||||
content: "A task that is performed asynchronously and iteratively.",
|
||||
matchTextRegex: /batch job/i,
|
||||
referenceLink: "/development/batch-jobs",
|
||||
},
|
||||
{
|
||||
title: "Strategy",
|
||||
content:
|
||||
"A class that contains an isolated piece of logic that can be overridden and customized.",
|
||||
matchTextRegex: /(strategy|strategies)/i,
|
||||
referenceLink: "/development/strategies/overview",
|
||||
},
|
||||
{
|
||||
title: "Feature Flag",
|
||||
content:
|
||||
"A flag that guards beta features in the Medusa backend and ensures they can only be used when enabled.",
|
||||
matchTextRegex: /(feature-flag|feature flag)/i,
|
||||
referenceLink: "/development/feature-flags/overview",
|
||||
},
|
||||
{
|
||||
title: "Idempotency Key",
|
||||
content:
|
||||
"A unique, randomly-generated key associated with a process, such as cart completion.",
|
||||
matchTextRegex: /(idempotency-key|idempotency key)/i,
|
||||
referenceLink: "/development/idempotency-key/overview",
|
||||
},
|
||||
{
|
||||
title: "Search Service",
|
||||
content:
|
||||
"A class that implements an interface to provide search functionalities.",
|
||||
matchTextRegex: /(search service|search-service)/i,
|
||||
referenceLink: "/development/search/overview",
|
||||
},
|
||||
{
|
||||
title: "File Service",
|
||||
content:
|
||||
"A class that implements an interface to provide storage functionalities.",
|
||||
matchTextRegex: /(file service|file-service)/i,
|
||||
referenceLink: "/development/file-service/overview",
|
||||
},
|
||||
{
|
||||
title: "Notification Service",
|
||||
content:
|
||||
"A class that implements an interface to provide notification functionalities.",
|
||||
matchTextRegex: /(notification service|notification-service)/i,
|
||||
referenceLink: "/development/notification/overview",
|
||||
},
|
||||
{
|
||||
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,
|
||||
referenceLink: "/development/plugins/overview",
|
||||
},
|
||||
{
|
||||
title: "Service",
|
||||
content:
|
||||
"A class that typically includes helper methods associated with an entity.",
|
||||
matchTextRegex: /service/i,
|
||||
ignoreTextRegex:
|
||||
/(file-service|file service|notification service|notification-service|search service|search-service)/i,
|
||||
referenceLink: "/development/services/overview",
|
||||
},
|
||||
{
|
||||
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,
|
||||
referenceLink: "/development/publishable-api-keys",
|
||||
},
|
||||
{
|
||||
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,
|
||||
referenceLink: "/js-client/overview",
|
||||
},
|
||||
{
|
||||
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,
|
||||
referenceLink: "/medusa-react/overview",
|
||||
},
|
||||
{
|
||||
title: "Admin Widget",
|
||||
content:
|
||||
"Custom React components that can be injected into different locations in the Medusa admin dashboard.",
|
||||
matchTextRegex: /admin widget/i,
|
||||
referenceLink: "/admin/widgets",
|
||||
},
|
||||
{
|
||||
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,
|
||||
referenceLink: "/admin/routes",
|
||||
},
|
||||
{
|
||||
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,
|
||||
referenceLink: "/admin/setting-pages",
|
||||
},
|
||||
]
|
||||
|
||||
export const getGlossary = () => [...glossary]
|
||||
|
||||
export const getGlossaryByPath = (path: string): GlossaryType | undefined => {
|
||||
return glossary.find(
|
||||
(g) => g.matchTextRegex.test(path) && !g.ignoreTextRegex?.test(path)
|
||||
)
|
||||
}
|
||||
797
www/apps/docs/src/utils/learning-paths.tsx
Normal file
797
www/apps/docs/src/utils/learning-paths.tsx
Normal file
@@ -0,0 +1,797 @@
|
||||
import React from "react"
|
||||
import { LearningPathType } from "../providers/LearningPath"
|
||||
import Link from "@docusaurus/Link"
|
||||
|
||||
const paths: LearningPathType[] = [
|
||||
{
|
||||
name: "simple-quickstart",
|
||||
label: "Start Selling in 3 Steps",
|
||||
description: "Create and deploy a full-fledged ecommerce store.",
|
||||
steps: [
|
||||
{
|
||||
title: "Create a Next.js Starter Template",
|
||||
description:
|
||||
"Create a Next.js Starter Template and connect it to your Medusa backend.",
|
||||
path: "/starters/nextjs-medusa-starter",
|
||||
},
|
||||
{
|
||||
title: "Deploy the backend",
|
||||
path: "/deployments/server/deploying-on-railway",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
Deploy your backend to Railway. You can alternatively check out{" "}
|
||||
<Link href="/deployments/server">other deployment guides</Link>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Deploy the storefront",
|
||||
description: "Deploy your storefront to your preferred hosting.",
|
||||
path: "/deployments/storefront",
|
||||
},
|
||||
],
|
||||
finish: {
|
||||
type: "rating",
|
||||
step: {
|
||||
title: "Congratulations on building your store!",
|
||||
description: "Please rate your experience using this recipe.",
|
||||
eventName: "rating_path_simple-quickstart",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "marketplace",
|
||||
label: "Build a marketplace",
|
||||
description:
|
||||
"Customize the backend and handle events to build a marketplace.",
|
||||
steps: [
|
||||
{
|
||||
title: "Extend entities",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
Extend entities, such as <code>User</code> or <code>Product</code>{" "}
|
||||
entites, to associate them with the <code>Store</code> entity.
|
||||
</>
|
||||
),
|
||||
path: "/development/entities/extend-entity",
|
||||
},
|
||||
{
|
||||
title: "Access logged-in user",
|
||||
description:
|
||||
"Create a middleware that registers the logged-in user in the dependency container.",
|
||||
path: "/development/endpoints/example-logged-in-user",
|
||||
},
|
||||
{
|
||||
title: "Extend services",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
Extend services, such as <code>ProductService</code> to customize
|
||||
data management functionalities
|
||||
</>
|
||||
),
|
||||
path: "/development/services/extend-service",
|
||||
},
|
||||
{
|
||||
title: "Handle events",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
Listen to events like <code>order.placed</code> and handle them with
|
||||
subscribers
|
||||
</>
|
||||
),
|
||||
path: "/development/events/create-subscriber",
|
||||
},
|
||||
{
|
||||
title: "Add Payment Provider",
|
||||
path: "/plugins/payment",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
Add a payment provider to your Medusa backend. You can choose to
|
||||
install a plugin or{" "}
|
||||
<Link href="/modules/carts-and-checkout/backend/add-payment-provider">
|
||||
create your own provider
|
||||
</Link>
|
||||
.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Customize Admin",
|
||||
path: "/admin/widgets",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
As you add marketplace features to your store, you'll most
|
||||
likely need to customize the admin to provide an interface to manage
|
||||
these features.
|
||||
<br />
|
||||
You can extend the admin plugin to add widgets,{" "}
|
||||
<Link to="/admin/routes">UI routes</Link>, or{" "}
|
||||
<Link to="/admin/setting-pages">setting pages</Link>.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Implement Role-Based Access Control",
|
||||
path: "/modules/users/backend/rbac",
|
||||
description:
|
||||
"In your marketplace, you may need to implement role-based access control (RBAC) within stores. This will restrict some users' permissions to specified functionalities or endpoints.",
|
||||
},
|
||||
{
|
||||
title: "Create a storefront",
|
||||
path: "/starters/nextjs-medusa-starter",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
Build a storefront either using the Next.js Starter Template or{" "}
|
||||
<Link href="/storefront/roadmap">from scratch</Link>.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Deploy the backend",
|
||||
path: "/deployments/server/deploying-on-railway",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
Deploy your backend to Railway. You can alternatively check out{" "}
|
||||
<Link href="/deployments/server">other deployment guides</Link>
|
||||
</>
|
||||
),
|
||||
},
|
||||
],
|
||||
finish: {
|
||||
type: "rating",
|
||||
step: {
|
||||
title: "Congratulations on building your marketplace!",
|
||||
description: "Please rate your experience using this recipe.",
|
||||
eventName: "rating_path_marketplace",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "subscriptions",
|
||||
label: "Build Subscription-based Purchases",
|
||||
description:
|
||||
"Customize the backend and handle events to implement subscriptions",
|
||||
steps: [
|
||||
{
|
||||
title: "Extend entities",
|
||||
path: "/development/entities/extend-entity",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
Extend entities, such as the <code>Order</code> entity, to associate
|
||||
them with the <code>Store</code> entity. You can also{" "}
|
||||
<Link href="/development/entities/create">
|
||||
Create a custom entity
|
||||
</Link>
|
||||
.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Handle events",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
Create a subscriber that listens to the <code>order.placed</code>{" "}
|
||||
event, or other{" "}
|
||||
<Link href="/development/events/events-list">events</Link>, and
|
||||
handles creating the subscription in Medusa.
|
||||
</>
|
||||
),
|
||||
path: "/development/events/create-subscriber",
|
||||
},
|
||||
{
|
||||
title: "Create a Scheduled Job",
|
||||
description:
|
||||
"Create a scheduled job that checks daily for subscriptions that needs renewal.",
|
||||
path: "/development/scheduled-jobs/create",
|
||||
},
|
||||
{
|
||||
title: "Customize Admin",
|
||||
path: "/admin/widgets",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
As you add subscription features to your store, you may need to
|
||||
customize the admin to provide an interface to manage these
|
||||
features.
|
||||
<br />
|
||||
You can extend the admin plugin to add widgets,{" "}
|
||||
<Link to="/admin/routes">UI routes</Link>, or{" "}
|
||||
<Link to="/admin/setting-pages">setting pages</Link>.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Create a storefront",
|
||||
path: "/starters/nextjs-medusa-starter",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
Build a storefront either using the Next.js Starter Template or{" "}
|
||||
<Link href="/storefront/roadmap">from scratch</Link>.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Deploy the backend",
|
||||
path: "/deployments/server/deploying-on-railway",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
Deploy your backend to Railway. You can alternatively check out{" "}
|
||||
<Link href="/deployments/server">other deployment guides</Link>
|
||||
</>
|
||||
),
|
||||
},
|
||||
],
|
||||
finish: {
|
||||
type: "rating",
|
||||
step: {
|
||||
title: "Congratulations on implementing subscription-based purchases!",
|
||||
description: "Please rate your experience using this recipe.",
|
||||
eventName: "rating_path_subscriptions",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "b2b",
|
||||
label: "Build a B2B store",
|
||||
description:
|
||||
"Utilize Medusa's features and customization capabilities to build a B2B store.",
|
||||
steps: [
|
||||
{
|
||||
title: "Create a B2B Sales Channel",
|
||||
path: "/user-guide/sales-channels/manage",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
You can create a B2B sales channel that will include only your
|
||||
wholesale products.
|
||||
<br />
|
||||
You can either use the Medusa admin, or the{" "}
|
||||
<Link to="/modules/sales-channels/admin/manage">
|
||||
Admin REST APIs
|
||||
</Link>
|
||||
.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Create a Publishable API Key",
|
||||
path: "/user-guide/settings/publishable-api-keys",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
Publishable API keys can be associated with one or more sales
|
||||
channels. You can then use the publishable API key in your
|
||||
storefront or client.
|
||||
<br />
|
||||
You can either use the Medusa admin, or the{" "}
|
||||
<Link to="/development/publishable-api-keys/admin/manage-publishable-api-keys">
|
||||
Admin REST APIs
|
||||
</Link>
|
||||
.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Add Wholesale Products",
|
||||
path: "/user-guide/products/manage",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
You can add your wholesale products and make them only available in
|
||||
the B2B sales channel.
|
||||
<br />
|
||||
You can use the Medusa admin to add the products. Other alternatives
|
||||
are:
|
||||
<ul>
|
||||
<li>
|
||||
<Link to="/modules/products/admin/manage-products">
|
||||
Add Products Using REST APIs
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/user-guide/products/import">
|
||||
Import Products Using Medusa Admin
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/modules/products/admin/import-products">
|
||||
Import Products Using REST APIs
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Create a B2B Customer Group",
|
||||
path: "/user-guide/customers/groups",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
Customer groups can be used to apply different prices for different
|
||||
subsets of customers, in this case B2B customers.
|
||||
<br />
|
||||
You can either use the Medusa admin, or the{" "}
|
||||
<Link to="/modules/customers/admin/manage-customer-groups">
|
||||
Admin REST APIs
|
||||
</Link>
|
||||
.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Add B2B Customers",
|
||||
path: "/user-guide/customers/manage",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
You can now add B2B customers and assign them to the B2B customer
|
||||
group. Alternatively, if you want to allow B2B customers to register
|
||||
themselves, you can implement that logic within your storefront.
|
||||
<br />
|
||||
You can either use the Medusa admin, or the{" "}
|
||||
<Link to="/modules/customers/admin/manage-customers">
|
||||
Admin REST APIs
|
||||
</Link>
|
||||
.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Create B2B Price Lists",
|
||||
path: "/user-guide/price-lists/manage",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
A price list allows you to set different prices on a set of products
|
||||
for different conditions. You can use this when building a B2B store
|
||||
to assign different prices for B2B customer groups.
|
||||
<br />
|
||||
You can use the Medusa admin to add the price list. Other
|
||||
alternatives are:
|
||||
<ul>
|
||||
<li>
|
||||
<Link to="/modules/price-lists/admin/manage-price-lists">
|
||||
Add Price List Using REST APIs
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/user-guide/price-lists/import">
|
||||
Import Prices Using Medusa Admin
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/modules/price-lists/admin/import-prices">
|
||||
Import Prices Using REST APIs
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Create Custom Entities",
|
||||
path: "/development/entities/create",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
Your use case may be more elaborate than what is shown in this
|
||||
recipe.
|
||||
<br />
|
||||
Medusa can be customized to add custom entities, endpoints,
|
||||
services, and more.
|
||||
<br />
|
||||
You can find additional development resources in the{" "}
|
||||
<Link to="/development/overview">Medusa development section</Link>.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Create an Endpoint to Check Customers",
|
||||
path: "/development/entities/create",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
On the clients communicating with your store, such as the
|
||||
storefront, you’ll need to check if the currently logged-in customer
|
||||
is a normal customer or a B2B customer.
|
||||
<br />
|
||||
To do that, you need to create a custom endpoint that handles the
|
||||
checking based on the custom logic you've chosen to indicate a
|
||||
customer is a B2B customer.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Customize Admin",
|
||||
path: "/admin/widgets",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
As you add B2B features to your store, you may need to customize the
|
||||
admin to provide an interface to manage these features.
|
||||
<br />
|
||||
You can extend the admin plugin to add widgets,{" "}
|
||||
<Link to="/admin/routes">UI routes</Link>, or{" "}
|
||||
<Link to="/admin/setting-pages">setting pages</Link>.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Customize Storefront",
|
||||
path: "/starters/nextjs-medusa-starter",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
You may need to customize your storefront to add different
|
||||
interfaces for B2B and regular customers, or show products
|
||||
differently.
|
||||
<br />
|
||||
You can customize the Next.js storefront, or you can{" "}
|
||||
<Link to="/storefront/roadmap">build a custom storefront</Link>.
|
||||
<br />
|
||||
In your storefront, make sure to{" "}
|
||||
<Link to="/development/publishable-api-keys/storefront/use-in-requests">
|
||||
use publishable API keys
|
||||
</Link>{" "}
|
||||
in your requests.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Deploy the B2B store",
|
||||
path: "/deployments/server",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
Once you finish your development, you can deploy your B2B backend to
|
||||
your preferred hosting provider. You can also{" "}
|
||||
<Link to="/deployments/storefront">deploy your storefront</Link> to
|
||||
your preferred hosting provider.
|
||||
</>
|
||||
),
|
||||
},
|
||||
],
|
||||
finish: {
|
||||
type: "rating",
|
||||
step: {
|
||||
title: "Congratulations on building a B2B store!",
|
||||
description: "Please rate your experience using this recipe.",
|
||||
eventName: "rating_path_b2b",
|
||||
},
|
||||
},
|
||||
},
|
||||
// TODO: Eventually remove these learning paths
|
||||
{
|
||||
name: "rbac",
|
||||
label: "Role-based access control (RBAC)",
|
||||
description: "Implement roles and permissions for admin users in Medusa",
|
||||
steps: [
|
||||
{
|
||||
title: "Create Role and Permission Entities",
|
||||
path: "/development/entities/create",
|
||||
description:
|
||||
"When implementing RBAC, you typically require the availability of roles and permissions, both of which would require new entities. A role would include different permissions, such as the ability to access the products’ route, and it can be assigned to one or more users.",
|
||||
},
|
||||
{
|
||||
title: "Extend Entities",
|
||||
path: "/development/entities/extend-entity",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
To associate roles with users, you need to extend the{" "}
|
||||
<code>User</code> entity to add the relation between it and the new{" "}
|
||||
<code>Role</code> entity. You can also extend other entities that
|
||||
are associated with your custom one, such as the <code>Store</code>{" "}
|
||||
entity.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Create Guard Middleware",
|
||||
path: "/development/endpoints/add-middleware",
|
||||
description:
|
||||
"To ensure that users who have the privilege can access an endpoint, you must create a middleware that guards admin routes. This middleware will run on all authenticated admin requests to ensure that only allowed users can access an endpoint.",
|
||||
},
|
||||
{
|
||||
title: "Create Services",
|
||||
path: "/development/services/create-service",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
For every entity you create, such as the <code>Role</code> and{" "}
|
||||
<code>Permission</code> entities, you must create a service that
|
||||
provides create, read, update, and delete (CRUD) functionalities at
|
||||
the very least.
|
||||
<br />
|
||||
If you also extended entities, such as the <code>User</code> entity,
|
||||
you may need to{" "}
|
||||
<Link to="/development/services/extend-service">
|
||||
extend its core service
|
||||
</Link>{" "}
|
||||
<code>UserService</code> as well to perform custom functionalities
|
||||
related to your implementation.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Create Endpoints",
|
||||
path: "/development/endpoints/create",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
To manage the roles and permissions, you’ll need to create custom
|
||||
endpoints, typically for Create, Read, Update, and Delete (CRUD)
|
||||
operations.
|
||||
<br />
|
||||
After creating the endpoints, you may test adding roles and
|
||||
permissions, and how they provide different access for different
|
||||
roles and users.
|
||||
</>
|
||||
),
|
||||
},
|
||||
],
|
||||
finish: {
|
||||
type: "rating",
|
||||
step: {
|
||||
title: "Congratulations on implementing RBAC!",
|
||||
description: "Please rate your experience using this recipe.",
|
||||
eventName: "rating_path_rbac",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "entity-and-api",
|
||||
label: "Create Entity and Expose it with Endpoints",
|
||||
description:
|
||||
"Learn how to create a new table in your database, then create endpoints to expose and manipulate its data.",
|
||||
steps: [
|
||||
{
|
||||
title: "Create entity",
|
||||
path: "/development/entities/create",
|
||||
description: "Create your entity, its migration, and repository.",
|
||||
},
|
||||
{
|
||||
title: "Create service",
|
||||
path: "/development/services/create-service",
|
||||
description:
|
||||
"A service is a class that defines helper methods for your entity. The service will be used by the endpoints to access or modify the entity's data.",
|
||||
},
|
||||
{
|
||||
title: "Create endpoints",
|
||||
path: "/development/endpoints/create",
|
||||
},
|
||||
],
|
||||
finish: {
|
||||
type: "rating",
|
||||
step: {
|
||||
title: "Congratulations on creating your entity and endpoints!",
|
||||
description: "Please rate your experience using this recipe.",
|
||||
eventName: "rating_path_entity-and-api",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "storefront",
|
||||
label: "Create a Custom Storefront",
|
||||
description:
|
||||
"Learn how to create a custom storefront with your preferred language or framework.",
|
||||
steps: [
|
||||
{
|
||||
title: "Choose your client",
|
||||
path: "/medusa-react/overview",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
As your storefront connect to the Medusa backend, you need a way to
|
||||
interact with the backend's REST APIs. There are three ways to
|
||||
do so, based on your type of project:
|
||||
<ul>
|
||||
<li>
|
||||
<Link to="/medusa-react/overview">Medusa React</Link>: Can be
|
||||
used in any React-based project. For example, in a Next.js
|
||||
storefront.
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/js-client/overview">Medusa JS Client</Link>: Can be
|
||||
used in any JavaScript and NPM based project. For example, in a
|
||||
Nuxt storefront.
|
||||
</li>
|
||||
<li>
|
||||
<Link to={`https://docs.medusajs.com/api/store`}>
|
||||
Store REST APIs
|
||||
</Link>
|
||||
: You can send requests directly to the API endpoints without
|
||||
using Medusa's clients.
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Set CORS configurations in Backend",
|
||||
path: "/development/backend/configurations#admin_cors-and-store_cors",
|
||||
description:
|
||||
"To ensure your storefront can connect to the backend, make sure to configure the backend's CORS configuration based on your storefront's local or remote URL.",
|
||||
},
|
||||
{
|
||||
title: "Create a Publishable API Key",
|
||||
path: "/user-guide/settings/publishable-api-keys",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
A publishable API key allows you to associate a key with a sales
|
||||
channel. Then, you can include that key in the headers of all your
|
||||
requests.
|
||||
<br />
|
||||
You can create the publishable API key from the dashboard.
|
||||
Alternatively, you can create it using the{" "}
|
||||
<Link to="/development/publishable-api-keys/admin/manage-publishable-api-keys">
|
||||
Admin APIs
|
||||
</Link>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Use Publishable API Key",
|
||||
path: "/development/publishable-api-keys/storefront/use-in-requests",
|
||||
description:
|
||||
"After creating the publishable API key and associating it with sales channels, you can pass it in the header of your requests to Store API endpoints.",
|
||||
},
|
||||
{
|
||||
title: "Add Region Selection",
|
||||
path: "/modules/regions-and-currencies/storefront/use-regions",
|
||||
description:
|
||||
"In your storefront, you can allow your customers to view available regions and select their current region. This can affect the prices, discounts, and shipping and payment providers available to the customer.",
|
||||
},
|
||||
{
|
||||
title: "Display Products",
|
||||
path: "/modules/products/storefront/show-products",
|
||||
description: "Display products to your customers in the storefront.",
|
||||
},
|
||||
{
|
||||
title: "Implement Cart Functionalities",
|
||||
path: "/modules/carts-and-checkout/storefront/implement-cart",
|
||||
description:
|
||||
"Allow your customers to add items to their cart, update them, and more in preparation for checkout.",
|
||||
},
|
||||
{
|
||||
title: "Implement Checkout Flow",
|
||||
path: "/modules/carts-and-checkout/storefront/implement-checkout-flow",
|
||||
description:
|
||||
"Implement the checkout flow that allows customers to handle shipping and payment, then place their orders.",
|
||||
},
|
||||
{
|
||||
title: "Implement Customer Profiles",
|
||||
path: "/modules/customers/storefront/implement-customer-profiles",
|
||||
description:
|
||||
"Allow customers to register, login, edit their profile information, and more.",
|
||||
},
|
||||
{
|
||||
title: "More Commerce Functionalities",
|
||||
path: "/modules/overview",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
This recipe guided you to create a storefront with basic
|
||||
functionalities. You can add more functionalities to your storefront
|
||||
based on your use case.
|
||||
<ul>
|
||||
<li>
|
||||
The <Link to="/modules/overview">Commerce Modules</Link>{" "}
|
||||
documentation holds various storefront-related how-to guides to
|
||||
help you implement different features.
|
||||
</li>
|
||||
<li>
|
||||
You can also checkout the{" "}
|
||||
<Link to={`https://docs.medusajs.com/api/store`}>
|
||||
Store REST APIs
|
||||
</Link>{" "}
|
||||
for a full list of available REST APIs.
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
},
|
||||
],
|
||||
finish: {
|
||||
type: "rating",
|
||||
step: {
|
||||
title: "Congratulations on creating your storefront!",
|
||||
description: "Please rate your experience using this recipe.",
|
||||
eventName: "rating_path_storefront",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "plugin",
|
||||
label: "Create a Plugin",
|
||||
description:
|
||||
"Learn how to create a plugin that can be re-used across Medusa backends.",
|
||||
steps: [
|
||||
{
|
||||
title: "Setup plugin project",
|
||||
path: "/development/backend/install",
|
||||
description:
|
||||
"A plugin is initially a Medusa backend with customizations. If you don't have a project ready, you can create one using Medusa's CLI tool.",
|
||||
},
|
||||
{
|
||||
title: "Implement Customizations",
|
||||
path: "/development/entities/create",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
Your plugin can hold backend and admin customizations. Those
|
||||
include:
|
||||
<ul>
|
||||
<li>
|
||||
<Link to="/development/entities/create">Create Entity</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/development/services/create-service">
|
||||
Create Service
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/development/endpoints/create">
|
||||
Create an Endpoint
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/development/events/create-subscriber">
|
||||
Create Subscriber
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/admin/widgets">Create Admin Widgets</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/admin/routes">Create Admin Routes</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/admin/setting-pages">
|
||||
Create Admin Setting Pages
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/development/search/create">
|
||||
Create Search Service
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/development/file-service/create-file-service">
|
||||
Create File Service
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/development/notification-service/create-notification-service">
|
||||
Create Notification Service
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
If you've already made your custom development, you can skip to
|
||||
the next step.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Change your package.json",
|
||||
path: "/development/plugins/create#changes-to-packagejson",
|
||||
descriptionJSX: (
|
||||
<>
|
||||
Once you're done making your customizations and you're
|
||||
ready to publish your plugin, make changes to your{" "}
|
||||
<code>package.json</code> in preparation for publishing.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Optionally test locally",
|
||||
path: "/development/plugins/create#test-your-plugin",
|
||||
description:
|
||||
"If necessary, you can test your plugin in a separate local Medusa backend. It's recommended, however, to do your plugin testing within the plugin project.",
|
||||
},
|
||||
{
|
||||
title: "Publish plugin",
|
||||
path: "/development/plugins/publish",
|
||||
description: "Publish your plugin on NPM.",
|
||||
},
|
||||
],
|
||||
finish: {
|
||||
type: "rating",
|
||||
step: {
|
||||
title: "Congratulations on creating your plugin!",
|
||||
description: "Please rate your experience using this recipe.",
|
||||
eventName: "rating_path_plugin",
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
// get a shallow copy
|
||||
export const getLearningPaths = () => [...paths]
|
||||
|
||||
export const getLearningPath = (
|
||||
pathName: string
|
||||
): LearningPathType | undefined => paths.find((path) => path.name === pathName)
|
||||
27
www/apps/docs/src/utils/reverseSidebar.js
Normal file
27
www/apps/docs/src/utils/reverseSidebar.js
Normal file
@@ -0,0 +1,27 @@
|
||||
function reverseSidebarItems(sidebarItems, categoryItem) {
|
||||
let result = sidebarItems
|
||||
if (categoryItem.customProps?.reverse) {
|
||||
// Reverse items in categories
|
||||
result = result.map((item) => {
|
||||
if (item.type === "category") {
|
||||
return { ...item, items: reverseSidebarItems(item.items, categoryItem) }
|
||||
}
|
||||
return item
|
||||
})
|
||||
// Reverse items at current level
|
||||
// use localeCompare since the reverse array method doesn't account for
|
||||
// numeric strings
|
||||
result.sort((a, b) => {
|
||||
const aToCompare = a.id || a.href || a.value || ""
|
||||
const bToCompare = b.id || b.href || b.value || ""
|
||||
const comparison = aToCompare.localeCompare(bToCompare, undefined, {
|
||||
numeric: true,
|
||||
})
|
||||
|
||||
return comparison < 0 ? 1 : comparison > 0 ? -1 : 0
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
module.exports = reverseSidebarItems
|
||||
Reference in New Issue
Block a user