docs: prepare configuration (#7877)
* update configuration * resolve todos + remove events guides * disable v2 docs in v1 navbar * remove v2 from v1 mobile sidebar * resolve build errors * fix build errors * fix lint errors * fix lint
This commit is contained in:
1 parent
012a624ee4
commit
6713d76db3
57 files changed
+678
-958
No files matched your search
@@ -41,6 +41,7 @@ const Navbar = () => {
|
||||
}}
|
||||
additionalActionsBefore={<VersionSwitcher />}
|
||||
additionalActionsAfter={<FeedbackModal />}
|
||||
showSearchOpener
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -12,6 +12,7 @@ const nextConfig = {
|
||||
destination: `${
|
||||
process.env.NEXT_PUBLIC_DOCS_URL || "https://localhost:3001"
|
||||
}/:path*`,
|
||||
basePath: false,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ import { model } from "@medusajs/utils"
|
||||
const MyCustom = model.define("my_custom", {
|
||||
id: model.id().primaryKey(),
|
||||
name: model.text(),
|
||||
age: model.number()
|
||||
age: model.number(),
|
||||
}).indexes([
|
||||
{
|
||||
on: ["name", "age"],
|
||||
@@ -82,13 +82,13 @@ import { model } from "@medusajs/utils"
|
||||
const MyCustom = model.define("my_custom", {
|
||||
id: model.id().primaryKey(),
|
||||
name: model.text(),
|
||||
age: model.number()
|
||||
age: model.number(),
|
||||
}).indexes([
|
||||
{
|
||||
on: ["name", "age"],
|
||||
where: {
|
||||
age: 30
|
||||
}
|
||||
age: 30,
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
@@ -111,15 +111,15 @@ import { model } from "@medusajs/utils"
|
||||
const MyCustom = model.define("my_custom", {
|
||||
id: model.id().primaryKey(),
|
||||
name: model.text(),
|
||||
age: model.number().nullable()
|
||||
age: model.number().nullable(),
|
||||
}).indexes([
|
||||
{
|
||||
on: ["name", "age"],
|
||||
where: {
|
||||
age: {
|
||||
$ne: null
|
||||
}
|
||||
}
|
||||
$ne: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
@@ -146,11 +146,11 @@ import { model } from "@medusajs/utils"
|
||||
const MyCustom = model.define("my_custom", {
|
||||
id: model.id().primaryKey(),
|
||||
name: model.text(),
|
||||
age: model.number()
|
||||
age: model.number(),
|
||||
}).indexes([
|
||||
{
|
||||
on: ["name", "age"],
|
||||
unique: true
|
||||
unique: true,
|
||||
},
|
||||
])
|
||||
|
||||
|
||||
@@ -41,25 +41,6 @@ A subscriber file must export:
|
||||
|
||||
The above subscriber listens to the `product.created` event. Whenever the event is emitted, it logs in the terminal `A product is created`.
|
||||
|
||||
{/* TODO add when we have the admin dashboard to use with V2 for easy testing. */}
|
||||
|
||||
{/\* ### Test Subscriber
|
||||
|
||||
To test the subscriber, start the Medusa application:
|
||||
|
||||
```bash npm2yarn
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Then, create a product using the Medusa Admin dashboard. Afterward, you’ll see the following messages logged in the terminal:
|
||||
|
||||
```bash
|
||||
info: Processing product.created which has 1 subscribers
|
||||
A product is created
|
||||
```
|
||||
|
||||
The first message indicates that the `product.created` event was emitted, and the second one is the message logged from the subscriber. \*/}
|
||||
|
||||
---
|
||||
|
||||
## When to Use Subscribers
|
||||
|
||||
@@ -31,6 +31,7 @@ const Navbar = () => {
|
||||
mobileSidebarOpen,
|
||||
}}
|
||||
isLoading={false}
|
||||
showSearchOpener
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -108,6 +108,13 @@ const nextConfig = {
|
||||
}/v2/resources/:path*`,
|
||||
basePath: false,
|
||||
},
|
||||
{
|
||||
source: "/v2/api/:path*",
|
||||
destination: `${
|
||||
process.env.NEXT_PUBLIC_API_URL || "https://localhost:3001"
|
||||
}/v2/api/:path*`,
|
||||
basePath: false,
|
||||
},
|
||||
// TODO comment out once we have the user guide published
|
||||
// {
|
||||
// source: "/user-guide",
|
||||
@@ -122,7 +129,7 @@ const nextConfig = {
|
||||
{
|
||||
source: "/:path*",
|
||||
destination: `${
|
||||
process.env.NEXT_PUBLIC_DOCS_V1_URL || "https://localhost:3000"
|
||||
process.env.NEXT_PUBLIC_API_V1_URL || "https://localhost:3001"
|
||||
}/:path*`,
|
||||
basePath: false,
|
||||
},
|
||||
|
||||
File renamed without changes.
+1
-3
@@ -91,6 +91,4 @@ The `create` method accepts an object or an array of objects having the followin
|
||||
sectionTitle="Use the Create Method"
|
||||
/>
|
||||
|
||||
{/* TODO add once reference for type once generated */}
|
||||
|
||||
{/* For a full list of properties accepted, refer to [this guide](/references/notification-provider-module#create). */}
|
||||
For a full list of properties accepted, refer to [this guide](/references/notification-provider-module#create).
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -36,8 +36,7 @@ You can create a sales channel through the Medusa Admin or Admin REST APIs.
|
||||
|
||||
{/* TODO add links */}
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "#",
|
||||
title: "Option 1: Use Medusa Admin",
|
||||
@@ -46,18 +45,17 @@ You can create a sales channel through the Medusa Admin or Admin REST APIs.
|
||||
showLinkIcon: false,
|
||||
badge: {
|
||||
variant: "blue",
|
||||
children: "Guide Soon",
|
||||
},
|
||||
children: "Guide Soon"
|
||||
}
|
||||
},
|
||||
{
|
||||
href: "!api!/api/admin#sales-channels_postsaleschannels",
|
||||
title: "Option 2: Using the REST APIs",
|
||||
text: "Create the sales channel using the REST APIs.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
---
|
||||
|
||||
@@ -76,8 +74,7 @@ You can create a publishable API key through the Medusa Admin or the Admin REST
|
||||
|
||||
### Create Key
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "#",
|
||||
title: "Option 1: Use Medusa Admin",
|
||||
@@ -86,25 +83,23 @@ You can create a publishable API key through the Medusa Admin or the Admin REST
|
||||
showLinkIcon: false,
|
||||
badge: {
|
||||
variant: "blue",
|
||||
children: "Guide Soon",
|
||||
},
|
||||
children: "Guide Soon"
|
||||
}
|
||||
},
|
||||
{
|
||||
href: "!api!/api/admin#api-keys_postapikeys",
|
||||
title: "Option 2: Using the REST APIs",
|
||||
text: "Create the publishable API key using the REST APIs.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
### Associate Key with Sales Channel
|
||||
|
||||
{/* TODO add links */}
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "#",
|
||||
title: "Option 1: Use Medusa Admin",
|
||||
@@ -113,18 +108,17 @@ You can create a publishable API key through the Medusa Admin or the Admin REST
|
||||
showLinkIcon: false,
|
||||
badge: {
|
||||
variant: "blue",
|
||||
children: "Guide Soon",
|
||||
},
|
||||
children: "Guide Soon"
|
||||
}
|
||||
},
|
||||
{
|
||||
href: "#",
|
||||
title: "Option 2: Using the REST APIs",
|
||||
text: "Associate the publishable API key with the B2B sales channel using the REST APIs.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
---
|
||||
|
||||
@@ -136,8 +130,7 @@ You can create new products or add existing ones to the B2B sales channel using
|
||||
|
||||
{/* TODO add links */}
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "#",
|
||||
title: "Using Medusa Admin",
|
||||
@@ -146,25 +139,23 @@ You can create new products or add existing ones to the B2B sales channel using
|
||||
showLinkIcon: false,
|
||||
badge: {
|
||||
variant: "blue",
|
||||
children: "Guide Soon",
|
||||
},
|
||||
children: "Guide Soon"
|
||||
}
|
||||
},
|
||||
{
|
||||
href: "!api!/api/admin#products_postproducts",
|
||||
title: "Using REST APIs",
|
||||
text: "Create products using the REST APIs.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
### Add Products to Sales Channel
|
||||
|
||||
{/* TODO add links */}
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "#",
|
||||
title: "Using Medusa Admin",
|
||||
@@ -173,18 +164,17 @@ You can create new products or add existing ones to the B2B sales channel using
|
||||
showLinkIcon: false,
|
||||
badge: {
|
||||
variant: "blue",
|
||||
children: "Guide Soon",
|
||||
},
|
||||
children: "Guide Soon"
|
||||
}
|
||||
},
|
||||
{
|
||||
href: "!api!/api/admin#sales-channels_postsaleschannelsidproductsbatchadd",
|
||||
title: "Using REST APIs",
|
||||
text: "Add the products to the B2B sales channel using the REST APIs.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
---
|
||||
|
||||
@@ -202,35 +192,33 @@ Module Relationships is coming soon.
|
||||
|
||||
</Note>
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "!docs!/basics/modules-and-services",
|
||||
title: "Create Module",
|
||||
text: "Learn how to create a module in Medusa.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
{
|
||||
href: "!docs!/basics/data-models",
|
||||
title: "Create Data Models",
|
||||
text: "Learn how to create data models.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
{/_ <Card
|
||||
{/* <Card
|
||||
href="!docs!/advanced-development/modules/module-relationships"
|
||||
title="Create Module Relationships"
|
||||
text="Learn how to create a relationship between modules."
|
||||
startIcon={<AcademicCapSolid />}
|
||||
showLinkIcon={false}
|
||||
className="mt-1"
|
||||
/> _/}
|
||||
/> */}
|
||||
|
||||
{/\* <Details summaryContent="Example">
|
||||
{/* <Details summaryContent="Example">
|
||||
In this section, you'll create a B2B module that has a `Company` data model. The `Company` data model has a relationship to the `CustomerGroup` data model of the Customer Module.
|
||||
|
||||
Start by creating the `src/modules/b2b` directory.
|
||||
@@ -259,14 +247,13 @@ Next, create the migration in the file `src/modules/b2b/migrations/Migration2024
|
||||
import { Migration } from "@mikro-orm/migrations"
|
||||
|
||||
export class Migration20240516081502 extends Migration {
|
||||
|
||||
async up(): Promise<void> {
|
||||
this.addSql(
|
||||
'create table if not exists "company" ("id" text not null, "name" text not null, "city" text not null, "country_code" text not null, "customer_group_id" text not null, constraint "company_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql("create table if not exists \"company\" (\"id\" text not null, \"name\" text not null, \"city\" text not null, \"country_code\" text not null, \"customer_group_id\" text not null, constraint \"company_pkey\" primary key (\"id\"));")
|
||||
}
|
||||
|
||||
async down(): Promise<void> {
|
||||
this.addSql('drop table if exists "company" cascade;')
|
||||
this.addSql("drop table if exists \"company\" cascade;")
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -294,10 +281,11 @@ Next, create the module definition at `src/modules/b2b/index.ts` with the follow
|
||||
|
||||
```ts title="src/modules/b2b/index.ts"
|
||||
import B2bModuleService from "./service"
|
||||
import { Module } from "@medusajs/utils"
|
||||
|
||||
export default {
|
||||
export default Module("b2b", {
|
||||
service: B2bModuleService,
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Finally, add the module to the `modules` object in `medusa-config.js`:
|
||||
@@ -346,26 +334,15 @@ export type CreateCompanyDTO = {
|
||||
country_code: string
|
||||
customer_group_id?: string
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Then, create the file `src/workflows/create-company.ts` with the following content:
|
||||
|
||||
export const workflowHighlights = [
|
||||
[
|
||||
"23",
|
||||
"tryToCreateCustomerGroupStep",
|
||||
"This step creates the customer group if its data is passed in the `customer_group` property.",
|
||||
],
|
||||
[
|
||||
"36",
|
||||
"createCustomerGroupsWorkflow",
|
||||
"Use the `createCustomerGroupsWorkflow` defined by Medusa to create the customer group.",
|
||||
],
|
||||
[
|
||||
"44",
|
||||
"",
|
||||
"Set the ID of the new customer group in the `customer_group_id` property so that it's added to the created company.",
|
||||
],
|
||||
["23", "tryToCreateCustomerGroupStep", "This step creates the customer group if its data is passed in the `customer_group` property."],
|
||||
["36", "createCustomerGroupsWorkflow", "Use the `createCustomerGroupsWorkflow` defined by Medusa to create the customer group."],
|
||||
["44", "", "Set the ID of the new customer group in the `customer_group_id` property so that it's added to the created company."],
|
||||
["54", "createCompanyStep", "This step creates the company."],
|
||||
]
|
||||
|
||||
@@ -375,7 +352,9 @@ import {
|
||||
createStep,
|
||||
createWorkflow,
|
||||
} from "@medusajs/workflows-sdk"
|
||||
import { createCustomerGroupsWorkflow } from "@medusajs/core-flows"
|
||||
import {
|
||||
createCustomerGroupsWorkflow,
|
||||
} from "@medusajs/core-flows"
|
||||
import { CreateCustomerGroupDTO } from "@medusajs/types"
|
||||
import { CompanyDTO, CreateCompanyDTO } from "../types/b2b"
|
||||
import B2bModuleService from "../modules/b2b/service"
|
||||
@@ -393,15 +372,19 @@ type CreateCustomerGroupStepInput = CreateCompanyWorkflowInput
|
||||
const tryToCreateCustomerGroupStep = createStep(
|
||||
"try-to-create-customer-group-step",
|
||||
async (
|
||||
{ customer_group, ...company }: CreateCustomerGroupStepInput,
|
||||
{ container }
|
||||
) => {
|
||||
{
|
||||
customer_group,
|
||||
...company
|
||||
}: CreateCustomerGroupStepInput,
|
||||
{ container }) => {
|
||||
if (!customer_group) {
|
||||
return new StepResponse({ company })
|
||||
}
|
||||
|
||||
// create customer group
|
||||
const { result } = await createCustomerGroupsWorkflow(container).run({
|
||||
const { result } = await createCustomerGroupsWorkflow(
|
||||
container
|
||||
).run({
|
||||
input: {
|
||||
customersData: [customer_group],
|
||||
},
|
||||
@@ -419,11 +402,17 @@ export type CreateCompanyStep = {
|
||||
|
||||
const createCompanyStep = createStep(
|
||||
"create-company-step",
|
||||
async ({ companyData }: CreateCompanyStep, { container }) => {
|
||||
const b2bModuleService: B2bModuleService =
|
||||
container.resolve("b2bModuleService")
|
||||
async (
|
||||
{ companyData }: CreateCompanyStep,
|
||||
{ container }) => {
|
||||
const b2bModuleService: B2bModuleService = container
|
||||
.resolve(
|
||||
"b2bModuleService"
|
||||
)
|
||||
|
||||
const company = await b2bModuleService.createCompany(companyData)
|
||||
const company = await b2bModuleService.createCompany(
|
||||
companyData
|
||||
)
|
||||
|
||||
return new StepResponse({ company })
|
||||
}
|
||||
@@ -432,13 +421,18 @@ const createCompanyStep = createStep(
|
||||
export const createCompanyWorkflow = createWorkflow<
|
||||
CreateCompanyWorkflowInput,
|
||||
CreateCompanyWorkflowOutput
|
||||
>("create-company", function (input) {
|
||||
const { company: companyData } = tryToCreateCustomerGroupStep(input)
|
||||
>(
|
||||
"create-company",
|
||||
function (input) {
|
||||
const {
|
||||
company: companyData,
|
||||
} = tryToCreateCustomerGroupStep(input)
|
||||
|
||||
const company = createCompanyStep({ companyData })
|
||||
|
||||
return company
|
||||
})
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
You create a workflow with two steps:
|
||||
@@ -449,7 +443,10 @@ You create a workflow with two steps:
|
||||
Finally, create the file `src/api/admin/b2b/company/route.ts` with the following content:
|
||||
|
||||
```ts title="src/api/admin/b2b/company/route.ts" collapsibleLines="1-9" expandButtonLabel="Show Imports"
|
||||
import type { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
|
||||
import type {
|
||||
MedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "@medusajs/medusa"
|
||||
import {
|
||||
CreateCompanyWorkflowInput,
|
||||
createCompanyWorkflow,
|
||||
@@ -461,7 +458,8 @@ export async function POST(
|
||||
req: MedusaRequest<CreateCompanyReq>,
|
||||
res: MedusaResponse
|
||||
) {
|
||||
const { result } = await createCompanyWorkflow(req.scope).run({
|
||||
const { result } = await createCompanyWorkflow(req.scope)
|
||||
.run({
|
||||
input: req.body,
|
||||
})
|
||||
|
||||
@@ -519,8 +517,7 @@ You can do that through the Medusa Admin or Admin REST APIs.
|
||||
|
||||
{/* TODO add links */}
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "#",
|
||||
title: "Option 1: Use Medusa Admin",
|
||||
@@ -529,25 +526,23 @@ You can do that through the Medusa Admin or Admin REST APIs.
|
||||
showLinkIcon: false,
|
||||
badge: {
|
||||
variant: "blue",
|
||||
children: "Guide Soon",
|
||||
},
|
||||
children: "Guide Soon"
|
||||
}
|
||||
},
|
||||
{
|
||||
href: "!api!/api/admin#customers_postcustomers",
|
||||
title: "Option 2: Using the REST APIs",
|
||||
text: "Create the customers using the REST APIs.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
### Assign Customers to Groups
|
||||
|
||||
{/* TODO add links */}
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "#",
|
||||
title: "Option 1: Use Medusa Admin",
|
||||
@@ -556,18 +551,17 @@ You can do that through the Medusa Admin or Admin REST APIs.
|
||||
showLinkIcon: false,
|
||||
badge: {
|
||||
variant: "blue",
|
||||
children: "Guide Soon",
|
||||
},
|
||||
children: "Guide Soon"
|
||||
}
|
||||
},
|
||||
{
|
||||
href: "!api!/api/admin#customer-groups_postcustomergroupsidcustomersbatch",
|
||||
title: "Option 2: Using the REST APIs",
|
||||
text: "Assign the customers to the B2B customer group using the REST APIs.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
---
|
||||
|
||||
@@ -579,8 +573,7 @@ You can create a price list using the Medusa Admin or the Admin REST APIs. Make
|
||||
|
||||
{/* TODO add links */}
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "#",
|
||||
title: "Using Medusa Admin",
|
||||
@@ -589,18 +582,17 @@ You can create a price list using the Medusa Admin or the Admin REST APIs. Make
|
||||
showLinkIcon: false,
|
||||
badge: {
|
||||
variant: "blue",
|
||||
children: "Guide Soon",
|
||||
},
|
||||
children: "Guide Soon"
|
||||
}
|
||||
},
|
||||
{
|
||||
href: "!api!/api/admin#price-lists_postpricelists",
|
||||
title: "Using REST APIs",
|
||||
text: "Create the price list using the REST APIs.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
---
|
||||
|
||||
@@ -634,22 +626,14 @@ The API route can check if the customer has any group with an associated company
|
||||
showLinkIcon={false}
|
||||
/>
|
||||
|
||||
{/\* <Details summaryContent="Example">
|
||||
{/* <Details summaryContent="Example">
|
||||
|
||||
For example, create the API route `src/api/store/b2b/check-customer/route.ts` with the following content:
|
||||
|
||||
export const checkCustomerHighlights = [
|
||||
["19", "retrieveCustomer", "Retrieve the customer along with its groups."],
|
||||
[
|
||||
"26",
|
||||
"listCompanies",
|
||||
"List the companies that have a customer group ID matching any of the customer's group IDs.",
|
||||
],
|
||||
[
|
||||
"31",
|
||||
"",
|
||||
"Return whether there are any companies associated with the customer's groups.",
|
||||
],
|
||||
["26", "listCompanies", "List the companies that have a customer group ID matching any of the customer's group IDs."],
|
||||
["31", "", "Return whether there are any companies associated with the customer's groups."]
|
||||
]
|
||||
|
||||
```ts title="src/api/store/b2b/check-customer/route.ts" highlights={checkCustomerHighlights} collapsibleLines="1-5" expandButtonLabel="Show Imports"
|
||||
@@ -665,11 +649,11 @@ export async function GET(
|
||||
req: AuthenticatedMedusaRequest,
|
||||
res: MedusaResponse
|
||||
) {
|
||||
const customerModuleService: ICustomerModuleService = req.scope.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
const customerModuleService: ICustomerModuleService = req
|
||||
.scope.resolve(ModuleRegistrationName.CUSTOMER)
|
||||
const b2bModuleService: B2bModuleService = req.scope.resolve(
|
||||
"b2bModuleService"
|
||||
)
|
||||
const b2bModuleService: B2bModuleService =
|
||||
req.scope.resolve("b2bModuleService")
|
||||
|
||||
const customer = await customerModuleService.retrieveCustomer(
|
||||
req.auth_context.actor_id,
|
||||
@@ -697,13 +681,18 @@ This creates a `GET` API Route at `/store/b2b/check-customer` that:
|
||||
Before using the API route, create the file `src/api/middlewares.ts` with the following content:
|
||||
|
||||
```ts title="src/api/middlewares.ts"
|
||||
import { MiddlewaresConfig, authenticate } from "@medusajs/medusa"
|
||||
import {
|
||||
MiddlewaresConfig,
|
||||
authenticate,
|
||||
} from "@medusajs/medusa"
|
||||
|
||||
export const config: MiddlewaresConfig = {
|
||||
routes: [
|
||||
{
|
||||
matcher: "/store/b2b*",
|
||||
middlewares: [authenticate("store", ["bearer", "session"])],
|
||||
middlewares: [
|
||||
authenticate("store", ["bearer", "session"]),
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -765,31 +754,29 @@ Based on your use case, you may need to customize the Medusa Admin to add new wi
|
||||
|
||||
The Medusa Admin plugin can be extended to add widgets, new pages, and setting pages.
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "!docs!/advanced-development/admin/widgets",
|
||||
title: "Create Admin Widget",
|
||||
text: "Learn how to add widgets into existing admin pages.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
{
|
||||
href: "!docs!/advanced-development/admin/ui-routes",
|
||||
title: "Create Admin UI Routes",
|
||||
text: "Learn how to add new pages to your Medusa Admin.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
{
|
||||
href: "!docs!/advanced-development/admin/setting-pages",
|
||||
title: "Create Admin Setting Page",
|
||||
text: "Learn how to add new page to the Medusa Admin settings.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
---
|
||||
|
||||
@@ -799,24 +786,22 @@ Medusa provides a Next.js storefront to use with your application. You can eithe
|
||||
|
||||
Use the publishable API key you associated with your B2B sales channel in the storefront to ensure only B2B products are retrieved.
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "/nextjs-starter",
|
||||
title: "Next.js Storefront",
|
||||
text: "Learn how to install and customize the Next.js storefront.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
{
|
||||
href: "/storefront-development",
|
||||
title: "Storefront Development",
|
||||
text: "Find guides for your storefront development.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
<Card
|
||||
href="!api!/api/store#publishable-api-key"
|
||||
|
||||
@@ -40,44 +40,39 @@ The `inventory-item.updated` event is currently not emitted.
|
||||
|
||||
</Note>
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "!docs!/basics/modules-and-services",
|
||||
title: "Create a Module",
|
||||
text: "Learn how to create a module in Medusa.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
{
|
||||
href: "!docs!/basics/data-models",
|
||||
title: "Create a Data Model",
|
||||
text: "Learn how to create a data model.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "!docs!/basics/api-routes",
|
||||
title: "Create an API Route",
|
||||
text: "Learn how to create an API route in Medusa.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
{
|
||||
href: "!docs!/basics/events-and-subscribers",
|
||||
title: "Create a Subscriber",
|
||||
text: "Learn how to create a subscriber in Medusa.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
className="mt-1"
|
||||
/>
|
||||
]} className="mt-1" />
|
||||
|
||||
<Details summaryContent="Example">
|
||||
|
||||
@@ -90,17 +85,9 @@ Start by creating the `src/modules/restock-notification` directory.
|
||||
Then, create the file `src/modules/restock-notification/models/restock-notification.ts` with the following content:
|
||||
|
||||
export const restockModelHighlights = [
|
||||
[
|
||||
"5",
|
||||
"email",
|
||||
"The email of the customer to send the notification to when the item is restocked.",
|
||||
],
|
||||
["5", "email", "The email of the customer to send the notification to when the item is restocked."],
|
||||
["6", "variant_id", "The ID of the variant the customer is subscribed to."],
|
||||
[
|
||||
"7",
|
||||
"sales_channel_id",
|
||||
"The ID of the sales channel the customer is viewing the product variant from.",
|
||||
],
|
||||
["7", "sales_channel_id", "The ID of the sales channel the customer is viewing the product variant from."]
|
||||
]
|
||||
|
||||
```ts title="src/modules/restock-notification/models/restock-notification.ts" highlights={restockModelHighlights}
|
||||
@@ -131,15 +118,15 @@ Next, create the file `src/modules/restock-notification/migrations/Migration2024
|
||||
import { Migration } from "@mikro-orm/migrations"
|
||||
|
||||
export class Migration20240516140616 extends Migration {
|
||||
|
||||
async up(): Promise<void> {
|
||||
this.addSql(
|
||||
'create table if not exists "restock_notification" ("id" text not null, "email" text not null, "variant_id" text not null, "sales_channel_id" text not null, constraint "restock_notification_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql("create table if not exists \"restock_notification\" (\"id\" text not null, \"email\" text not null, \"variant_id\" text not null, \"sales_channel_id\" text not null, constraint \"restock_notification_pkey\" primary key (\"id\"));")
|
||||
}
|
||||
|
||||
async down(): Promise<void> {
|
||||
this.addSql('drop table if exists "restock_notification" cascade;')
|
||||
this.addSql("drop table if exists \"restock_notification\" cascade;")
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@@ -166,10 +153,11 @@ Next, create the module's definition file `src/modules/restock-notification/inde
|
||||
|
||||
```ts title="src/modules/restock-notification/index.ts"
|
||||
import RestockNotificationModuleService from "./service"
|
||||
import { Module } from "@medusajs/utils"
|
||||
|
||||
export default {
|
||||
export default Module("restock-notification", {
|
||||
service: RestockNotificationModuleService,
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Finally, add the module to the `modules` object in `medusa-config.js`:
|
||||
@@ -178,7 +166,7 @@ Finally, add the module to the `modules` object in `medusa-config.js`:
|
||||
module.exports = defineConfig({
|
||||
// ...
|
||||
modules: {
|
||||
restockNotificationModuleService: {
|
||||
"restockNotificationModuleService": {
|
||||
resolve: "./modules/restock-notification",
|
||||
definition: {
|
||||
isQueryable: true,
|
||||
@@ -199,8 +187,12 @@ npx medusa migrations run
|
||||
Create the file `src/api/store/restock-notification/route.ts` with the following content:
|
||||
|
||||
```ts title="src/api/store/restock-notification/route.ts" collapsibleLines="1-13" expandButtonLabel="Show Imports"
|
||||
import type { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
|
||||
import RestockNotificationModuleService from "../../../modules/restock-notification/service"
|
||||
import type {
|
||||
MedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "@medusajs/medusa"
|
||||
import RestockNotificationModuleService
|
||||
from "../../../modules/restock-notification/service"
|
||||
|
||||
type RestockNotificationReq = {
|
||||
email: string
|
||||
@@ -212,10 +204,14 @@ export async function POST(
|
||||
req: MedusaRequest<RestockNotificationReq>,
|
||||
res: MedusaResponse
|
||||
) {
|
||||
const restockNotificationModuleService: RestockNotificationModuleService =
|
||||
req.scope.resolve("restockNotificationModuleService")
|
||||
const restockNotificationModuleService:
|
||||
RestockNotificationModuleService = req.scope.resolve(
|
||||
"restockNotificationModuleService"
|
||||
)
|
||||
|
||||
await restockNotificationModuleService.createRestockNotifications(req.body)
|
||||
await restockNotificationModuleService.createRestockNotifications(
|
||||
req.body
|
||||
)
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
@@ -238,69 +234,21 @@ The `inventory-item.updated` event is currently not emitted.
|
||||
{/* To handle the sending of the restock notifications, create the file `src/subscribers/inventory-item-update.ts` with the following content: */}
|
||||
|
||||
export const subscriberHighlights = [
|
||||
[
|
||||
"48",
|
||||
"inventoryVariantLinkService",
|
||||
"Retrieve an instance of the link service for the product-variant-inventory-item link module.",
|
||||
],
|
||||
[
|
||||
"55",
|
||||
"inventoryVariantItems",
|
||||
"Retrieve the variants linked to the updated inventory item.",
|
||||
],
|
||||
[
|
||||
"68",
|
||||
"restockQuery",
|
||||
"Assemble the query to retrieve the restock notifications with their associated variants.",
|
||||
],
|
||||
[
|
||||
"81",
|
||||
"restockNotifications",
|
||||
"Retrieve the restock notifications using the query.",
|
||||
],
|
||||
[
|
||||
"84",
|
||||
"salesChannelLocationService",
|
||||
"Retrieve an instance of the link service for the sales-channel-stock-location link module.",
|
||||
],
|
||||
[
|
||||
"93",
|
||||
"salesChannelLocations",
|
||||
"Retrieve the stock locations linked to the restock notification's sales channel.",
|
||||
],
|
||||
[
|
||||
"107",
|
||||
"availableQuantity",
|
||||
"Retrieve the available quantity of the variant in the retrieved stock locations.",
|
||||
],
|
||||
[
|
||||
"116",
|
||||
"continue",
|
||||
"Only send the notification if the available quantity is greater than `0`",
|
||||
],
|
||||
[
|
||||
"119",
|
||||
"createNotifications",
|
||||
"Send the notification to the customer using the Notification Module.",
|
||||
],
|
||||
[
|
||||
"122",
|
||||
'"test_template"',
|
||||
"Replace with the actual template used for sending the email.",
|
||||
],
|
||||
[
|
||||
"123",
|
||||
"data",
|
||||
"The data to send along to the third-party service sending the notification.",
|
||||
],
|
||||
[
|
||||
"131",
|
||||
"deleteRestockNotifications",
|
||||
"Delete the restock notification to not send the notification again.",
|
||||
],
|
||||
["48", "inventoryVariantLinkService", "Retrieve an instance of the link service for the product-variant-inventory-item link module."],
|
||||
["55", "inventoryVariantItems", "Retrieve the variants linked to the updated inventory item."],
|
||||
["68", "restockQuery", "Assemble the query to retrieve the restock notifications with their associated variants."],
|
||||
["81", "restockNotifications", "Retrieve the restock notifications using the query."],
|
||||
["84", "salesChannelLocationService", "Retrieve an instance of the link service for the sales-channel-stock-location link module."],
|
||||
["93", "salesChannelLocations", "Retrieve the stock locations linked to the restock notification's sales channel."],
|
||||
["107", "availableQuantity", "Retrieve the available quantity of the variant in the retrieved stock locations."],
|
||||
["116", "continue", "Only send the notification if the available quantity is greater than `0`"],
|
||||
["119", "createNotifications", "Send the notification to the customer using the Notification Module."],
|
||||
["122", '"test_template"', "Replace with the actual template used for sending the email."],
|
||||
["123", "data", "The data to send along to the third-party service sending the notification."],
|
||||
["131", "deleteRestockNotifications", "Delete the restock notification to not send the notification again."]
|
||||
]
|
||||
|
||||
{/\* ```ts title="src/subscribers/inventory-item-update.ts" highlights={subscriberHighlights} collapsibleLines="1-20" expandButtonLabel="Show Imports"
|
||||
{/* ```ts title="src/subscribers/inventory-item-update.ts" highlights={subscriberHighlights} collapsibleLines="1-20" expandButtonLabel="Show Imports"
|
||||
import type {
|
||||
SubscriberArgs,
|
||||
SubscriberConfig,
|
||||
@@ -431,15 +379,13 @@ Modules.NOTIFICATION
|
||||
await restockNotificationModuleService
|
||||
.deleteRestockNotifications(restockNotification.id)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// subscriber config
|
||||
export const config: SubscriberConfig = {
|
||||
event: "inventory-item.updated",
|
||||
}
|
||||
|
||||
````
|
||||
```
|
||||
|
||||
This adds a subscriber to the `inventory-item.updated` event. In the subscriber handler function, you:
|
||||
|
||||
@@ -673,7 +619,7 @@ export const syncProductsWorkflow = createWorkflow<
|
||||
})
|
||||
}
|
||||
)
|
||||
````
|
||||
```
|
||||
|
||||
This creates a workflow with the following steps:
|
||||
|
||||
@@ -686,10 +632,15 @@ Then, create a scheduled job at `src/jobs/sync-products.ts` that executes the wo
|
||||
|
||||
```ts
|
||||
import { MedusaContainer } from "@medusajs/types"
|
||||
import { syncProductsWorkflow } from "../workflows/sync-products"
|
||||
import {
|
||||
syncProductsWorkflow,
|
||||
} from "../workflows/sync-products"
|
||||
|
||||
export default async function syncProductsJob(container: MedusaContainer) {
|
||||
await syncProductsWorkflow(container).run({
|
||||
export default async function syncProductsJob(
|
||||
container: MedusaContainer
|
||||
) {
|
||||
await syncProductsWorkflow(container)
|
||||
.run({
|
||||
input: {
|
||||
name: "John",
|
||||
},
|
||||
@@ -728,7 +679,7 @@ The `order.placed` event is currently not emitted.
|
||||
showLinkIcon={false}
|
||||
/>
|
||||
|
||||
{/_ <CardList items={[
|
||||
{/* <CardList items={[
|
||||
{
|
||||
href: "!docs!/basics/events-and-subscribers",
|
||||
title: "Create a Subscriber",
|
||||
@@ -743,7 +694,7 @@ text: "Check out triggered events by each commerce module.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]} /> _/}
|
||||
]} /> */}
|
||||
|
||||
---
|
||||
|
||||
@@ -757,24 +708,22 @@ Medusa's commerce features are geared towards automating RMA flows and ensuring
|
||||
- Merchants can make order changes and request the customer's approval for them. The customer can also send any additional payment if necessary.
|
||||
- Every order-related action triggers an event, which you can listen to with a subscriber. This allows you to handle order events to automate actions.
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "/commerce-modules/orders",
|
||||
title: "Order Module",
|
||||
text: "Learn about the Order Module and its features.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
{
|
||||
href: "!docs!/basics/events-and-subscribers",
|
||||
title: "Create a Subscriber",
|
||||
text: "Learn how to create a subscriber in Medusa.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
---
|
||||
|
||||
@@ -798,31 +747,29 @@ The `order.placed` event is currently not emitted.
|
||||
|
||||
</Note>
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "/commerce-modules/customer",
|
||||
title: "Customer Module",
|
||||
text: "Learn about the Customer Module and its features.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
{
|
||||
href: "/commerce-modules/pricing",
|
||||
title: "Pricing Module",
|
||||
text: "Learn about the Pricing Module and its features.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
{
|
||||
href: "!docs!/basics/events-and-subscribers",
|
||||
title: "Create a Subscriber",
|
||||
text: "Learn how to create a subscriber in Medusa.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
<Details summaryContent="Example: Add customer to VIP group">
|
||||
|
||||
@@ -835,9 +782,17 @@ The `order.placed` event is currently not emitted.
|
||||
</Note>
|
||||
|
||||
```ts title="src/subscribers/add-custom-to-vip.ts" collapsibleLines="1-12" expandButtonLabel="Show Imports"
|
||||
import type { SubscriberArgs, SubscriberConfig } from "@medusajs/medusa"
|
||||
import { ModuleRegistrationName } from "@medusajs/utils"
|
||||
import { ICustomerModuleService, IOrderModuleService } from "@medusajs/types"
|
||||
import type {
|
||||
SubscriberArgs,
|
||||
SubscriberConfig,
|
||||
} from "@medusajs/medusa"
|
||||
import {
|
||||
ModuleRegistrationName,
|
||||
} from "@medusajs/modules-sdk"
|
||||
import {
|
||||
ICustomerModuleService,
|
||||
IOrderModuleService,
|
||||
} from "@medusajs/types"
|
||||
|
||||
export default async function orderCreatedHandler({
|
||||
data,
|
||||
@@ -845,23 +800,21 @@ export default async function orderCreatedHandler({
|
||||
}: SubscriberArgs<{ id: string }>) {
|
||||
const orderId = "data" in data ? data.data.id : data.id
|
||||
|
||||
const orderModuleService: IOrderModuleService = container.resolve(
|
||||
ModuleRegistrationName.ORDER
|
||||
)
|
||||
const orderModuleService: IOrderModuleService = container
|
||||
.resolve(ModuleRegistrationName.ORDER)
|
||||
|
||||
const customerModuleService: ICustomerModuleService = container.resolve(
|
||||
const customerModuleService:
|
||||
ICustomerModuleService = container.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
|
||||
// check if VIP group exists
|
||||
const vipGroup = await customerModuleService.listCustomerGroups(
|
||||
{
|
||||
const vipGroup = await customerModuleService
|
||||
.listCustomerGroups({
|
||||
name: "VIP",
|
||||
},
|
||||
{
|
||||
}, {
|
||||
relations: ["customers"],
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
if (!vipGroup.length) {
|
||||
return
|
||||
@@ -870,13 +823,11 @@ export default async function orderCreatedHandler({
|
||||
// retrieve the order
|
||||
const order = await orderModuleService.retrieveOrder(orderId)
|
||||
|
||||
if (
|
||||
!order ||
|
||||
if (!order ||
|
||||
!order.customer_id ||
|
||||
vipGroup[0].customers.find(
|
||||
(customer) => customer.id === order.customer_id
|
||||
) !== undefined
|
||||
) {
|
||||
) !== undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -913,24 +864,22 @@ To do that, create a subscriber that listens to the `product.created`, and send
|
||||
|
||||
You can also create a scheduled job that checks whether the number of new products has exceeded a set threshold, then sends out the newsletter.
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "!docs!/basics/events-and-subscribers",
|
||||
title: "Create a Subscriber",
|
||||
text: "Learn how to create a subscriber in Medusa.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
{
|
||||
href: "!docs!/basics/scheduled-jobs",
|
||||
title: "Scheduled Jobs",
|
||||
text: "Learn how to create a scheduled job in Medusa.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
<Details summaryContent="Example: Sending a newsletter email after adding ten products">
|
||||
|
||||
@@ -938,43 +887,24 @@ For example, create the file `src/subscribers/send-products-newsletter.ts` with
|
||||
|
||||
export const newsletterHighlights = [
|
||||
["33", "store", "Retrieve the first store in the application."],
|
||||
[
|
||||
"35",
|
||||
"products",
|
||||
"Retrieve the products created since the last newsletter send date.",
|
||||
],
|
||||
[
|
||||
"41",
|
||||
"",
|
||||
"Check whether more than 10 products have been created before proceeding.",
|
||||
],
|
||||
[
|
||||
"45",
|
||||
"customers",
|
||||
"Retrieve all customers, assuming they're considered subscribed.",
|
||||
],
|
||||
[
|
||||
"47",
|
||||
"createNotifications",
|
||||
"Send a notification (newsletter) to each customer using the Notification Module.",
|
||||
],
|
||||
["35", "products", "Retrieve the products created since the last newsletter send date."],
|
||||
["41", "", "Check whether more than 10 products have been created before proceeding."],
|
||||
["45", "customers", "Retrieve all customers, assuming they're considered subscribed."],
|
||||
["47", "createNotifications", "Send a notification (newsletter) to each customer using the Notification Module."],
|
||||
["50", '"email"', "Send the notification through the email channel."],
|
||||
[
|
||||
"51",
|
||||
'"newsletter_template"',
|
||||
"Specify the template name in the third-party service (for example, SendGrid).",
|
||||
],
|
||||
["51", '"newsletter_template"', "Specify the template name in the third-party service (for example, SendGrid)."],
|
||||
["53", "products", "Pass the created products to the template."],
|
||||
[
|
||||
"58",
|
||||
"updateStores",
|
||||
"Update the store's `last_newsletter_send_date` property with the current date.",
|
||||
],
|
||||
["58", "updateStores", "Update the store's `last_newsletter_send_date` property with the current date."]
|
||||
]
|
||||
|
||||
```ts title="src/subscribers/send-products-newsletter.ts" highlights={newsletterHighlights} collapsibleLines="1-14" expandButtonLabel="Show Imports"
|
||||
import type { SubscriberArgs, SubscriberConfig } from "@medusajs/medusa"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import type {
|
||||
SubscriberArgs,
|
||||
SubscriberConfig,
|
||||
} from "@medusajs/medusa"
|
||||
import {
|
||||
ModuleRegistrationName,
|
||||
} from "@medusajs/modules-sdk"
|
||||
import {
|
||||
ICustomerModuleService,
|
||||
IProductModuleService,
|
||||
@@ -986,20 +916,19 @@ export default async function productCreateHandler({
|
||||
data,
|
||||
container,
|
||||
}: SubscriberArgs<{ id: string }>) {
|
||||
const productModuleService: IProductModuleService = container.resolve(
|
||||
ModuleRegistrationName.PRODUCT
|
||||
)
|
||||
const productModuleService: IProductModuleService =
|
||||
container.resolve(ModuleRegistrationName.PRODUCT)
|
||||
|
||||
const storeModuleService: IStoreModuleService = container.resolve(
|
||||
ModuleRegistrationName.STORE
|
||||
)
|
||||
const storeModuleService: IStoreModuleService =
|
||||
container.resolve(ModuleRegistrationName.STORE)
|
||||
|
||||
const customerModuleService: ICustomerModuleService = container.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
)
|
||||
const customerModuleService: ICustomerModuleService =
|
||||
container.resolve(ModuleRegistrationName.CUSTOMER)
|
||||
|
||||
const notificationModuleService: INotificationModuleService =
|
||||
container.resolve(ModuleRegistrationName.NOTIFICATION)
|
||||
const notificationModuleService:
|
||||
INotificationModuleService = container.resolve(
|
||||
ModuleRegistrationName.NOTIFICATION
|
||||
)
|
||||
|
||||
const store = (await storeModuleService.listStores())[0]
|
||||
|
||||
@@ -1028,7 +957,7 @@ export default async function productCreateHandler({
|
||||
|
||||
await storeModuleService.updateStores(store.id, {
|
||||
metadata: {
|
||||
last_newsletter_send_date: new Date().toString(),
|
||||
last_newsletter_send_date: (new Date()).toString(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -33,24 +33,22 @@ Use a file module provider to manage your stored digital products.
|
||||
|
||||
During development, you can use the Local File Module Provider, which is installed by default in your store. For production, check out available file module providers or create your own.
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "/architectural-modules/file",
|
||||
title: "File Module Providers",
|
||||
text: "Check out available file module providers.",
|
||||
startIcon: <PuzzleSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
{
|
||||
href: "/references/file-provider-module",
|
||||
title: "Create a File Module Provider",
|
||||
text: "Learn how to create a file module provider.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
---
|
||||
|
||||
@@ -64,14 +62,13 @@ You can use one of Medusa’s notification module providers or create your own.
|
||||
|
||||
{/* TODO add links */}
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "/architectural-modules/notification",
|
||||
title: "Notification Module Providers",
|
||||
text: "Check out available official notification module providers.",
|
||||
startIcon: <PuzzleSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
{
|
||||
href: "/references/notification-provider-module",
|
||||
@@ -80,8 +77,7 @@ You can use one of Medusa’s notification module providers or create your own.
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
---
|
||||
|
||||
@@ -121,10 +117,11 @@ Next, create the file `src/modules/digital-product/index.ts` with the following
|
||||
|
||||
```ts title="src/modules/digital-product/index.ts"
|
||||
import DigitalProductModuleService from "./service"
|
||||
import { Module } from "@medusajs/utils"
|
||||
|
||||
export default {
|
||||
export default Module("digital-product", {
|
||||
service: DigitalProductModuleService,
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
This file holds the definition of the module.
|
||||
@@ -166,7 +163,7 @@ Module Relationships is coming soon.
|
||||
showLinkIcon={false}
|
||||
/>
|
||||
|
||||
{/\* <Details summaryContent="Example: Create ProductMedia Data Model">
|
||||
{/* <Details summaryContent="Example: Create ProductMedia Data Model">
|
||||
|
||||
In this section, you’ll create a `ProductMedia` data model that represents your digital products.
|
||||
|
||||
@@ -175,7 +172,7 @@ Before creating the data model, create the file `src/types/digital-product/produ
|
||||
```ts title="src/types/digital-product/product-media.ts"
|
||||
export enum MediaType {
|
||||
MAIN = "main",
|
||||
PREVIEW = "preview",
|
||||
PREVIEW = "preview"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -250,7 +247,7 @@ Medusa facilitates implementing data-management features by providing a service
|
||||
showLinkIcon={false}
|
||||
/>
|
||||
|
||||
{/\* <Details summaryContent="Example: Add Implementation of DigitalProductModuleService">
|
||||
{/* <Details summaryContent="Example: Add Implementation of DigitalProductModuleService">
|
||||
|
||||
In this section, you’ll modify the `DigitalProductModuleService` you created earlier to provide data-management functionalities of the `ProductMedia` data model.
|
||||
|
||||
@@ -275,7 +272,7 @@ The `DigitalProductModuleService` now extends the service factory which generate
|
||||
|
||||
{/* --- */}
|
||||
|
||||
{/\* ## Add Relationship to Product Variants
|
||||
{/* ## Add Relationship to Product Variants
|
||||
|
||||
As mentioned in a previous section, the product media has a `variant_id` that points to the saleable product variant.
|
||||
|
||||
@@ -382,27 +379,24 @@ Fetching data across modules using the remote query is coming soon.
|
||||
|
||||
</Note>
|
||||
|
||||
<CardList
|
||||
itemsPerRow={2}
|
||||
items={[
|
||||
<CardList itemsPerRow={2} items={[
|
||||
{
|
||||
href: "!docs!/basics/api-routes",
|
||||
title: "API Routes",
|
||||
text: "Learn how to create an API route.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
{
|
||||
href: "!docs!/advanced-development/modules/remote-query",
|
||||
title: "Remote Query",
|
||||
text: "Learn about what the remote query is and how to use it.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
{/\* <Details summaryContent="Example: Custom API Routes for Digital Products">
|
||||
{/* <Details summaryContent="Example: Custom API Routes for Digital Products">
|
||||
|
||||
In this section, you’ll create a List and Create API routes to retrieve and create digital products.
|
||||
|
||||
@@ -422,7 +416,7 @@ import {
|
||||
|
||||
export enum MediaType {
|
||||
MAIN = "main",
|
||||
PREVIEW = "preview",
|
||||
PREVIEW = "preview"
|
||||
}
|
||||
|
||||
export type ProductMediaDTO = {
|
||||
@@ -443,9 +437,11 @@ export type CreateProductMediaDTO = {
|
||||
variant_id?: string
|
||||
}
|
||||
|
||||
export type CreateProductMediaWorkflowInput = CreateProductMediaDTO & {
|
||||
export type CreateProductMediaWorkflowInput =
|
||||
CreateProductMediaDTO & {
|
||||
product?: CreateProductWorkflowInputDTO
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Then, create the file `src/workflows/digital-product/create.ts` with the following content:
|
||||
@@ -463,7 +459,8 @@ import {
|
||||
CreateProductMediaWorkflowInput,
|
||||
ProductMediaDTO,
|
||||
} from "../../types/digital-product/product-media"
|
||||
import DigitalProductModuleService from "../../modules/digital-product/service"
|
||||
import DigitalProductModuleService from
|
||||
"../../modules/digital-product/service"
|
||||
import { RemoteQueryFunction } from "@medusajs/modules-sdk"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
@@ -474,7 +471,8 @@ const tryToCreateProductVariantStep = createStep(
|
||||
"try-to-create-product-variant-step",
|
||||
async (input: CreateProductMediaWorkflowInput, { container }) => {
|
||||
if (input.product && !input.variant_id) {
|
||||
const { result, errors } = await createProductsWorkflow(container).run({
|
||||
const { result, errors } = await createProductsWorkflow(container)
|
||||
.run({
|
||||
input: {
|
||||
products: [input.product],
|
||||
},
|
||||
@@ -497,10 +495,13 @@ const tryToCreateProductVariantStep = createStep(
|
||||
const createProductMediaStep = createStep(
|
||||
"create-product-media-step",
|
||||
async (input: CreateProductMediaDTO, { container }) => {
|
||||
const digitalProductModuleService: DigitalProductModuleService =
|
||||
container.resolve("digitalProductModuleService")
|
||||
const digitalProductModuleService:
|
||||
DigitalProductModuleService = container.resolve(
|
||||
"digitalProductModuleService"
|
||||
)
|
||||
|
||||
const productMedia = await digitalProductModuleService.createProductMedias(
|
||||
const productMedia = await digitalProductModuleService
|
||||
.createProductMedias(
|
||||
input
|
||||
)
|
||||
|
||||
@@ -517,7 +518,14 @@ const retrieveProductMediaWithVariant = createStep(
|
||||
|
||||
const query = remoteQueryObjectFromString({
|
||||
entryPoint: "product_media",
|
||||
fields: ["id", "name", "type", "file_key", "mime_type", "variant.*"],
|
||||
fields: [
|
||||
"id",
|
||||
"name",
|
||||
"type",
|
||||
"file_key",
|
||||
"mime_type",
|
||||
"variant.*",
|
||||
],
|
||||
variables: {
|
||||
filters: {
|
||||
id: input.id,
|
||||
@@ -558,10 +566,17 @@ This workflow has three steps:
|
||||
Finally, create the `src/api/admin/digital-products/route.ts` file with the following content:
|
||||
|
||||
```ts title="src/api/admin/digital-products/route.ts" collapsibleLines="1-12" expandButtonLabel="Show Imports"
|
||||
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
|
||||
import {
|
||||
MedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "@medusajs/medusa"
|
||||
import { MedusaError } from "@medusajs/utils"
|
||||
import { CreateProductMediaWorkflowInput } from "../../../types/digital-product/product-media"
|
||||
import { createProductMediaWorkflow } from "../../../workflows/digital-product/create"
|
||||
import {
|
||||
CreateProductMediaWorkflowInput,
|
||||
} from "../../../types/digital-product/product-media"
|
||||
import {
|
||||
createProductMediaWorkflow,
|
||||
} from "../../../workflows/digital-product/create"
|
||||
|
||||
type CreateProductMediaReq = CreateProductMediaWorkflowInput
|
||||
|
||||
@@ -570,7 +585,11 @@ export async function POST(
|
||||
res: MedusaResponse
|
||||
) {
|
||||
// validation omitted for simplicity
|
||||
const { result, errors } = await createProductMediaWorkflow(req.scope).run({
|
||||
const {
|
||||
result,
|
||||
errors,
|
||||
} = await createProductMediaWorkflow(req.scope)
|
||||
.run({
|
||||
input: {
|
||||
data: {
|
||||
...req.body,
|
||||
@@ -580,7 +599,10 @@ export async function POST(
|
||||
})
|
||||
|
||||
if (errors.length) {
|
||||
throw new MedusaError(MedusaError.Types.DB_ERROR, errors[0].error)
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.DB_ERROR,
|
||||
errors[0].error
|
||||
)
|
||||
}
|
||||
|
||||
res.json({
|
||||
@@ -646,7 +668,7 @@ You’ll receive a response similar to the following:
|
||||
"variant_id": "variant_01HXEFRMR3B09EZJX23P1DMYFQ",
|
||||
"variant": {
|
||||
"id": "variant_01HXEFRMR3B09EZJX23P1DMYFQ",
|
||||
"title": "Harry Potter 1"
|
||||
"title": "Harry Potter 1",
|
||||
// ...
|
||||
}
|
||||
}
|
||||
@@ -669,7 +691,10 @@ import {
|
||||
|
||||
// ...
|
||||
|
||||
export async function GET(req: MedusaRequest, res: MedusaResponse) {
|
||||
export async function GET(
|
||||
req: MedusaRequest,
|
||||
res: MedusaResponse
|
||||
) {
|
||||
const remoteQuery: RemoteQueryFunction = req.scope.resolve(
|
||||
ContainerRegistrationKeys.REMOTE_QUERY
|
||||
)
|
||||
@@ -717,26 +742,24 @@ You can extend the Medusa Admin to provide merchants with an interface to manage
|
||||
|
||||
In your customizations, you send requests to the API routes you created to create and list digital products.
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "!docs!/advanced-development/admin/widgets",
|
||||
title: "Create a Widget",
|
||||
text: "Learn how to create a widget in the Medusa Admin.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
{
|
||||
href: "!docs!/advanced-development/admin/ui-routes",
|
||||
title: "Create UI Route",
|
||||
text: "Learn how to create a UI route in the Medusa Admin.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
{/\* <Details summaryContent="Example: Digital Products Page in Admin">
|
||||
{/* <Details summaryContent="Example: Digital Products Page in Admin">
|
||||
|
||||
In this example, you’ll add a single page that lists the digital products and allows you to create a new one. The implementation will be minimal for the purpose of simplicity, so you can elaborate on it based on your use case.
|
||||
|
||||
@@ -745,11 +768,16 @@ To create the UI route, create the file `src/admin/routes/product-media/page.tsx
|
||||
```tsx title="src/admin/routes/product-media/page.tsx" badgeLabel="Medusa Application" collapsibleLines="1-13" expandButtonLabel="Show Imports"
|
||||
import { defineRouteConfig } from "@medusajs/admin-shared"
|
||||
import { useEffect, useState } from "react"
|
||||
import { Container, Heading, Table } from "@medusajs/ui"
|
||||
import {
|
||||
Container,
|
||||
Heading,
|
||||
Table,
|
||||
} from "@medusajs/ui"
|
||||
import { PhotoSolid } from "@medusajs/icons"
|
||||
import { ProductMediaDTO } from "../../../types/digital-product/product-media"
|
||||
import { Link } from "react-router-dom"
|
||||
import ProductMediaCreateForm from "../../components/product-media/CreateForm"
|
||||
import ProductMediaCreateForm
|
||||
from "../../components/product-media/CreateForm"
|
||||
|
||||
const ProductMediaListPage = () => {
|
||||
const [loading, setLoading] = useState(true)
|
||||
@@ -772,18 +800,22 @@ const ProductMediaListPage = () => {
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<div className="mb-4 flex justify-between">
|
||||
<div className="flex justify-between mb-4">
|
||||
<Heading level="h1">Digital Products</Heading>
|
||||
<ProductMediaCreateForm onCreate={() => setLoading(true)} />
|
||||
</div>
|
||||
{loading && <div>Loading...</div>}
|
||||
{!loading && !productMedias.length && <div>No Digital Products</div>}
|
||||
{!loading && !productMedias.length && (
|
||||
<div>No Digital Products</div>
|
||||
)}
|
||||
{!loading && productMedias.length > 0 && (
|
||||
<Table>
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell>Product</Table.HeaderCell>
|
||||
<Table.HeaderCell>Product Variant</Table.HeaderCell>
|
||||
<Table.HeaderCell>
|
||||
Product Variant
|
||||
</Table.HeaderCell>
|
||||
<Table.HeaderCell>File Key</Table.HeaderCell>
|
||||
<Table.HeaderCell>Action</Table.HeaderCell>
|
||||
</Table.Row>
|
||||
@@ -791,15 +823,21 @@ const ProductMediaListPage = () => {
|
||||
<Table.Body>
|
||||
{productMedias.map((product_media) => (
|
||||
<Table.Row key={product_media.id}>
|
||||
<Table.Cell>{product_media.variant?.product.title}</Table.Cell>
|
||||
<Table.Cell>{product_media.variant?.title}</Table.Cell>
|
||||
<Table.Cell>{product_media.file_key}</Table.Cell>
|
||||
<Table.Cell>
|
||||
{product_media.variant && (
|
||||
<Link to={`/products/${product_media.variant.product_id}`}>
|
||||
{product_media.variant?.product.title}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
{product_media.variant?.title}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
{product_media.file_key}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
{product_media.variant && <Link to={`/products/${
|
||||
product_media.variant.product_id
|
||||
}`}>
|
||||
View Product
|
||||
</Link>
|
||||
)}
|
||||
</Link>}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
))}
|
||||
@@ -827,7 +865,14 @@ To create this form, create the file `src/admin/components/product-media/CreateF
|
||||
```tsx title="src/admin/components/product-media/CreateForm/index.tsx" badgeLabel="Medusa Application" collapsibleLines="1-11" expandButtonLabel="Show Imports"
|
||||
import { useState } from "react"
|
||||
import { redirect } from "react-router-dom"
|
||||
import { Button, Container, Input, Label, Select, Drawer } from "@medusajs/ui"
|
||||
import {
|
||||
Button,
|
||||
Container,
|
||||
Input,
|
||||
Label,
|
||||
Select,
|
||||
Drawer,
|
||||
} from "@medusajs/ui"
|
||||
|
||||
type Props = {
|
||||
onCreate: () => void
|
||||
@@ -836,7 +881,10 @@ type Props = {
|
||||
const ProductMediaCreateForm = ({ onCreate }: Props) => {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [productName, setProductName] = useState("")
|
||||
const [productVariantName, setProductVariantName] = useState("")
|
||||
const [
|
||||
productVariantName,
|
||||
setProductVariantName,
|
||||
] = useState("")
|
||||
const [name, setName] = useState("")
|
||||
const [type, setType] = useState("main")
|
||||
const [file, setFile] = useState<File>()
|
||||
@@ -903,12 +951,17 @@ const ProductMediaCreateForm = ({ onCreate }: Props) => {
|
||||
</Drawer.Trigger>
|
||||
<Drawer.Content>
|
||||
<Drawer.Header>
|
||||
<Drawer.Title>Create Digital Product</Drawer.Title>
|
||||
<Drawer.Title>
|
||||
Create Digital Product
|
||||
</Drawer.Title>
|
||||
</Drawer.Header>
|
||||
<Drawer.Body>
|
||||
<Container>
|
||||
<form onSubmit={handleSubmit} className="flex flex-col gap-4">
|
||||
<div className="flex items-center gap-4">
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
className="flex flex-col gap-4"
|
||||
>
|
||||
<div className="flex gap-4 items-center">
|
||||
<Label>Product Name</Label>
|
||||
<Input
|
||||
type="text"
|
||||
@@ -917,16 +970,18 @@ const ProductMediaCreateForm = ({ onCreate }: Props) => {
|
||||
onChange={(e) => setProductName(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex gap-4 items-center">
|
||||
<Label>Product Variant Name</Label>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Product Variant"
|
||||
value={productVariantName}
|
||||
onChange={(e) => setProductVariantName(e.target.value)}
|
||||
onChange={(e) =>
|
||||
setProductVariantName(e.target.value)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex gap-4 items-center">
|
||||
<Label>Media Name</Label>
|
||||
<Input
|
||||
type="text"
|
||||
@@ -935,26 +990,33 @@ const ProductMediaCreateForm = ({ onCreate }: Props) => {
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex gap-4 items-center">
|
||||
<Label>Type</Label>
|
||||
<Select onValueChange={setType} value={type}>
|
||||
<Select.Trigger>
|
||||
<Select.Value placeholder="Type" />
|
||||
</Select.Trigger>
|
||||
<Select.Content className="z-50">
|
||||
<Select.Item value={"main"}>Main</Select.Item>
|
||||
<Select.Item value={"preview"}>Preview</Select.Item>
|
||||
<Select.Item value={"main"}>
|
||||
Main
|
||||
</Select.Item>
|
||||
<Select.Item value={"preview"}>
|
||||
Preview
|
||||
</Select.Item>
|
||||
</Select.Content>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex gap-4 items-center">
|
||||
<Label>File</Label>
|
||||
<Input
|
||||
type="file"
|
||||
onChange={(e) => setFile(e.target.files[0])}
|
||||
/>
|
||||
</div>
|
||||
<Button variant="primary" type="submit" isLoading={loading}>
|
||||
<Button
|
||||
variant="primary"
|
||||
type="submit"
|
||||
isLoading={loading}>
|
||||
Create
|
||||
</Button>
|
||||
</form>
|
||||
@@ -1020,7 +1082,7 @@ In the subscriber, you can send a notification, such as an email, to the custome
|
||||
showLinkIcon={false}
|
||||
/>
|
||||
|
||||
{/\* <Details summaryContent="Example">
|
||||
{/* <Details summaryContent="Example">
|
||||
|
||||
<Note>
|
||||
|
||||
@@ -1031,29 +1093,38 @@ An alternative solution is to create a store download API Route that allows auth
|
||||
Here’s an example of a subscriber that retrieves the download links and sends them to the customer using the installed notification module provider:
|
||||
|
||||
```ts title="src/subscribers/handle-order.ts" badgeLabel="Medusa Application" collapsibleLines="1-15" expandButtonLabel="Show Imports"
|
||||
import { type SubscriberConfig, type SubscriberArgs } from "@medusajs/medusa"
|
||||
import {
|
||||
type SubscriberConfig,
|
||||
type SubscriberArgs,
|
||||
} from "@medusajs/medusa"
|
||||
import {
|
||||
IOrderModuleService,
|
||||
IFileModuleService,
|
||||
INotificationModuleService,
|
||||
} from "@medusajs/types"
|
||||
import { ModuleRegistrationName } from "@medusajs/utils"
|
||||
import DigitalProductModuleService from "../modules/digital-product/service"
|
||||
import {
|
||||
ModuleRegistrationName,
|
||||
} from "@medusajs/modules-sdk"
|
||||
import DigitalProductModuleService
|
||||
from "../modules/digital-product/service"
|
||||
|
||||
export default async function handleOrderPlaced({
|
||||
data,
|
||||
container,
|
||||
data, container,
|
||||
}: SubscriberArgs<{ id: string }>) {
|
||||
const orderModuleService: IOrderModuleService = container.resolve(
|
||||
const orderModuleService: IOrderModuleService =
|
||||
container.resolve(
|
||||
ModuleRegistrationName.ORDER
|
||||
)
|
||||
const fileModuleService: IFileModuleService = container.resolve(
|
||||
const fileModuleService: IFileModuleService =
|
||||
container.resolve(
|
||||
ModuleRegistrationName.FILE
|
||||
)
|
||||
const notificationModuleService: INotificationModuleService =
|
||||
container.resolve(ModuleRegistrationName.NOTIFICATION)
|
||||
const digitalProductModuleService: DigitalProductModuleService =
|
||||
container.resolve("digitalProductModuleService")
|
||||
const digitalProductModuleService:
|
||||
DigitalProductModuleService = container.resolve(
|
||||
"digitalProductModuleService"
|
||||
)
|
||||
|
||||
const orderId = "data" in data ? data.data.id : data.id
|
||||
|
||||
@@ -1064,14 +1135,18 @@ export default async function handleOrderPlaced({
|
||||
// find product medias in the order
|
||||
const urls = []
|
||||
for (const item of order.items) {
|
||||
const productMedias = await digitalProductModuleService.listProductMedias({
|
||||
const productMedias = await digitalProductModuleService
|
||||
.listProductMedias({
|
||||
variant_id: [item.variant_id],
|
||||
})
|
||||
|
||||
const downloadUrls = await Promise.all(
|
||||
productMedias.map(async (productMedia) => {
|
||||
|
||||
// get the download URL from the file service
|
||||
return (await fileModuleService.retrieveFile(productMedia.file_key)).url
|
||||
return (await fileModuleService.retrieveFile(
|
||||
productMedia.file_key
|
||||
)).url
|
||||
})
|
||||
)
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ apiKey: string
|
||||
}
|
||||
|
||||
class ErpModuleService {
|
||||
private client\_: AxiosInstance
|
||||
private client_: AxiosInstance
|
||||
|
||||
constructor({}, { apiKey }: ErpModuleOptions) {
|
||||
this.client_ = axios.create({
|
||||
@@ -87,12 +87,11 @@ private client\_: AxiosInstance
|
||||
async deleteProduct(id: string) {
|
||||
await this.client_.delete(`/product/${id}`)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ErpModuleService
|
||||
|
||||
````
|
||||
```
|
||||
|
||||
This creates the module's main service. Few things to note:
|
||||
|
||||
|
||||
@@ -40,24 +40,22 @@ Module Relationships is coming soon.
|
||||
|
||||
</Note>
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "!docs!/basics/modules-and-services",
|
||||
title: "Create a Module",
|
||||
text: "Learn how to create a module",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
{
|
||||
href: "!docs!/advanced-development/modules/module-relationships",
|
||||
title: "Module Relationships",
|
||||
text: "Create relationships between modules.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
<Details summaryContent="Example">
|
||||
|
||||
@@ -126,27 +124,23 @@ To reflect these changes on the database, create the migration `src/modules/mark
|
||||
import { Migration } from "@mikro-orm/migrations"
|
||||
|
||||
export class Migration20240514143248 extends Migration {
|
||||
|
||||
async up(): Promise<void> {
|
||||
this.addSql(
|
||||
'create table if not exists "store_order" ("id" varchar(255) not null, "store_id" text not null, "order_id" text not null, "parent_order_id" text not null, constraint "store_order_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql("create table if not exists \"store_order\" (\"id\" varchar(255) not null, \"store_id\" text not null, \"order_id\" text not null, \"parent_order_id\" text not null, constraint \"store_order_pkey\" primary key (\"id\"));")
|
||||
|
||||
this.addSql(
|
||||
'create table if not exists "store_product" ("id" varchar(255) not null, "store_id" text not null, "product_id" text not null, constraint "store_product_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql("create table if not exists \"store_product\" (\"id\" varchar(255) not null, \"store_id\" text not null, \"product_id\" text not null, constraint \"store_product_pkey\" primary key (\"id\"));")
|
||||
|
||||
this.addSql(
|
||||
'create table if not exists "store_user" ("id" varchar(255) not null, "store_id" text not null, "user_id" text not null, constraint "store_user_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql("create table if not exists \"store_user\" (\"id\" varchar(255) not null, \"store_id\" text not null, \"user_id\" text not null, constraint \"store_user_pkey\" primary key (\"id\"));")
|
||||
}
|
||||
|
||||
async down(): Promise<void> {
|
||||
this.addSql('drop table if exists "store_order" cascade;')
|
||||
this.addSql("drop table if exists \"store_order\" cascade;")
|
||||
|
||||
this.addSql('drop table if exists "store_product" cascade;')
|
||||
this.addSql("drop table if exists \"store_product\" cascade;")
|
||||
|
||||
this.addSql('drop table if exists "store_user" cascade;')
|
||||
this.addSql("drop table if exists \"store_user\" cascade;")
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@@ -173,8 +167,7 @@ StoreOrder,
|
||||
}
|
||||
|
||||
export default MarketplaceModuleService
|
||||
|
||||
````
|
||||
```
|
||||
|
||||
The module’s main service extends the service factory to generate data management features for the `StoreUser`, `StoreProduct`, and `StoreOrder` data models.
|
||||
|
||||
@@ -182,11 +175,12 @@ Finally, create the module definition at `src/modules/marketplace/index.ts` with
|
||||
|
||||
```ts title="src/modules/marketplace/index.ts"
|
||||
import MarketplaceModuleService from "./service"
|
||||
import { Module } from "@medusajs/utils"
|
||||
|
||||
export default {
|
||||
export default Module("marketplace", {
|
||||
service: MarketplaceModuleService,
|
||||
}
|
||||
````
|
||||
})
|
||||
```
|
||||
|
||||
To use the module, add it to the `modules` object in `medusa-config.js`:
|
||||
|
||||
@@ -234,7 +228,7 @@ To attach admin users to their own stores, create a subscriber that listens to t
|
||||
showLinkIcon={false}
|
||||
/>
|
||||
|
||||
{/\* <Details summaryContent="Example">
|
||||
{/* <Details summaryContent="Example">
|
||||
|
||||
Create the file `src/subscribers/user-created.ts` with the following content:
|
||||
|
||||
@@ -284,14 +278,12 @@ const marketplaceModuleService: MarketplaceModuleService = container.resolve(
|
||||
})
|
||||
|
||||
console.log(`Created StoreUser ${storeUser.id}`)
|
||||
|
||||
}
|
||||
|
||||
export const config: SubscriberConfig = {
|
||||
event: "user.created",
|
||||
}
|
||||
|
||||
````
|
||||
```
|
||||
|
||||
This adds a subscriber to the `user.created` event. In the subscriber, you:
|
||||
|
||||
@@ -303,7 +295,7 @@ To test it out, use the `medusa user` command to create a user:
|
||||
|
||||
```bash npm2yarn
|
||||
npx medusa user -e my-admin@medusa-test.com -p supersecret
|
||||
````
|
||||
```
|
||||
|
||||
At the end of the output, you should see the message `Created StoreUser {store_user_id}` where the `{store_user_id}` is the ID of the created `StoreUser`.
|
||||
|
||||
@@ -330,7 +322,7 @@ Similar to the previous section, to attach products to stores, create a subscrib
|
||||
showLinkIcon={false}
|
||||
/>
|
||||
|
||||
{/\* <Details summaryContent="Example">
|
||||
{/* <Details summaryContent="Example">
|
||||
|
||||
Create the file `src/subscribers/product-created.ts` with the following content:
|
||||
|
||||
@@ -374,14 +366,12 @@ ModuleRegistrationName.PRODUCT
|
||||
store_id: product.metadata.store_id as string,
|
||||
product_id: id,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
export const config: SubscriberConfig = {
|
||||
event: "product.created",
|
||||
}
|
||||
|
||||
````
|
||||
```
|
||||
|
||||
This adds a subscriber to the `product.created` event. In the subscriber, you:
|
||||
|
||||
@@ -393,7 +383,7 @@ To test it out, start the Medusa application:
|
||||
|
||||
```bash npm2yarn
|
||||
npm run dev
|
||||
````
|
||||
```
|
||||
|
||||
Then, send an authenticated `POST` request to `/admin/products`:
|
||||
|
||||
@@ -426,26 +416,24 @@ Retrieving module relationship data using the remote query is coming soon.
|
||||
|
||||
</Note>
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "!docs!/basics/api-routes",
|
||||
title: "API Routes",
|
||||
text: "Learn how to create an API Route in Medusa.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
{
|
||||
href: "!docs!/advanced-development/modules/remote-query",
|
||||
title: "Remote Query",
|
||||
text: "Use the remote query to fetch data across modules.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
|
||||
{/\* <Details summaryContent="Example">
|
||||
{/* <Details summaryContent="Example">
|
||||
|
||||
Create the file `src/api/admin/marketplace/products/route.ts` with the following content:
|
||||
|
||||
@@ -511,10 +499,8 @@ ContainerRegistrationKeys.REMOTE_QUERY
|
||||
store_id: storeUsers[0].store_id,
|
||||
products: result.map((data) => data.product),
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
````
|
||||
```
|
||||
|
||||
This creates a `GET` API route at `/admin/marketplace/products`. In the API route, you:
|
||||
|
||||
@@ -543,7 +529,7 @@ export const config: MiddlewaresConfig = {
|
||||
},
|
||||
],
|
||||
}
|
||||
````
|
||||
```
|
||||
|
||||
This ensures that only authenticated admin users can access your API route.
|
||||
|
||||
@@ -579,7 +565,7 @@ The `order.placed` event is still not emitted in Medusa V2.
|
||||
showLinkIcon={false}
|
||||
/>
|
||||
|
||||
{/\* <Details summaryContent="Example">
|
||||
{/* <Details summaryContent="Example">
|
||||
|
||||
Create the file `src/subscribers/order-created.ts` with the following content:
|
||||
|
||||
@@ -686,14 +672,12 @@ ModuleRegistrationName.ORDER
|
||||
})
|
||||
})
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
export const config: SubscriberConfig = {
|
||||
event: "order.placed",
|
||||
}
|
||||
|
||||
````
|
||||
```
|
||||
|
||||
This adds a subscriber to the `order.placed` event. In the subscriber, you:
|
||||
|
||||
@@ -795,7 +779,7 @@ export async function GET(
|
||||
orders: result.map((data) => data.order),
|
||||
})
|
||||
}
|
||||
````
|
||||
```
|
||||
|
||||
This creates a `GET` API route at `/admin/marketplace/orders`. In the API route, you:
|
||||
|
||||
@@ -822,21 +806,19 @@ Medusa provides a Next.js storefront to use with your application. You can eithe
|
||||
|
||||
For example, you can create an API route that retrieves available stores and another API route that retrieves the products of each store using the remote query as done in previous sections.
|
||||
|
||||
<CardList
|
||||
items={[
|
||||
<CardList items={[
|
||||
{
|
||||
href: "/nextjs-starter",
|
||||
title: "Next.js Storefront",
|
||||
text: "Learn how to install and customize the Next.js storefront.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
{
|
||||
href: "!docs!/storefront-development/tips",
|
||||
title: "Storefront Tips",
|
||||
text: "Find tips on developing a custom storefront.",
|
||||
startIcon: <AcademicCapSolid />,
|
||||
showLinkIcon: false,
|
||||
showLinkIcon: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
]} />
|
||||
@@ -30,6 +30,7 @@ const Navbar = () => {
|
||||
mobileSidebarOpen,
|
||||
}}
|
||||
isLoading={false}
|
||||
showSearchOpener
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
export const filesMap = [
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/_events-reference/page.mdx",
|
||||
"pathname": "/_events-reference"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/admin-widget-injection-zones/page.mdx",
|
||||
"pathname": "/admin-widget-injection-zones"
|
||||
@@ -79,18 +83,18 @@ export const filesMap = [
|
||||
"filePath": "/www/apps/resources/app/architectural-modules/workflow-engine/redis/page.mdx",
|
||||
"pathname": "/architectural-modules/workflow-engine/redis"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/api-key/_events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/api-key/_events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/api-key/_events/page.mdx",
|
||||
"pathname": "/commerce-modules/api-key/_events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/api-key/concepts/page.mdx",
|
||||
"pathname": "/commerce-modules/api-key/concepts"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/api-key/events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/api-key/events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/api-key/events/page.mdx",
|
||||
"pathname": "/commerce-modules/api-key/events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/api-key/examples/page.mdx",
|
||||
"pathname": "/commerce-modules/api-key/examples"
|
||||
@@ -103,6 +107,14 @@ export const filesMap = [
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/api-key/relations-to-other-modules/page.mdx",
|
||||
"pathname": "/commerce-modules/api-key/relations-to-other-modules"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/auth/_events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/auth/_events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/auth/_events/page.mdx",
|
||||
"pathname": "/commerce-modules/auth/_events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/auth/auth-flows/page.mdx",
|
||||
"pathname": "/commerce-modules/auth/auth-flows"
|
||||
@@ -131,14 +143,6 @@ export const filesMap = [
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/auth/create-actor-type/page.mdx",
|
||||
"pathname": "/commerce-modules/auth/create-actor-type"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/auth/events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/auth/events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/auth/events/page.mdx",
|
||||
"pathname": "/commerce-modules/auth/events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/auth/examples/page.mdx",
|
||||
"pathname": "/commerce-modules/auth/examples"
|
||||
@@ -151,18 +155,18 @@ export const filesMap = [
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/auth/page.mdx",
|
||||
"pathname": "/commerce-modules/auth"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/cart/_events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/cart/_events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/cart/_events/page.mdx",
|
||||
"pathname": "/commerce-modules/cart/_events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/cart/concepts/page.mdx",
|
||||
"pathname": "/commerce-modules/cart/concepts"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/cart/events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/cart/events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/cart/events/page.mdx",
|
||||
"pathname": "/commerce-modules/cart/events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/cart/examples/page.mdx",
|
||||
"pathname": "/commerce-modules/cart/examples"
|
||||
@@ -184,12 +188,12 @@ export const filesMap = [
|
||||
"pathname": "/commerce-modules/cart/tax-lines"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/currency/events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/currency/events/_events-table"
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/currency/_events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/currency/_events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/currency/events/page.mdx",
|
||||
"pathname": "/commerce-modules/currency/events"
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/currency/_events/page.mdx",
|
||||
"pathname": "/commerce-modules/currency/_events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/currency/examples/page.mdx",
|
||||
@@ -203,18 +207,18 @@ export const filesMap = [
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/currency/relations-to-other-modules/page.mdx",
|
||||
"pathname": "/commerce-modules/currency/relations-to-other-modules"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/customer/_events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/customer/_events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/customer/_events/page.mdx",
|
||||
"pathname": "/commerce-modules/customer/_events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/customer/customer-accounts/page.mdx",
|
||||
"pathname": "/commerce-modules/customer/customer-accounts"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/customer/events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/customer/events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/customer/events/page.mdx",
|
||||
"pathname": "/commerce-modules/customer/events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/customer/examples/page.mdx",
|
||||
"pathname": "/commerce-modules/customer/examples"
|
||||
@@ -227,18 +231,18 @@ export const filesMap = [
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/customer/relations-to-other-modules/page.mdx",
|
||||
"pathname": "/commerce-modules/customer/relations-to-other-modules"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/fulfillment/_events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/fulfillment/_events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/fulfillment/_events/page.mdx",
|
||||
"pathname": "/commerce-modules/fulfillment/_events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/fulfillment/concepts/page.mdx",
|
||||
"pathname": "/commerce-modules/fulfillment/concepts"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/fulfillment/events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/fulfillment/events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/fulfillment/events/page.mdx",
|
||||
"pathname": "/commerce-modules/fulfillment/events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/fulfillment/fulfillment-provider/page.mdx",
|
||||
"pathname": "/commerce-modules/fulfillment/fulfillment-provider"
|
||||
@@ -263,18 +267,18 @@ export const filesMap = [
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/fulfillment/shipping-option/page.mdx",
|
||||
"pathname": "/commerce-modules/fulfillment/shipping-option"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/inventory/_events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/inventory/_events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/inventory/_events/page.mdx",
|
||||
"pathname": "/commerce-modules/inventory/_events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/inventory/concepts/page.mdx",
|
||||
"pathname": "/commerce-modules/inventory/concepts"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/inventory/events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/inventory/events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/inventory/events/page.mdx",
|
||||
"pathname": "/commerce-modules/inventory/events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/inventory/examples/page.mdx",
|
||||
"pathname": "/commerce-modules/inventory/examples"
|
||||
@@ -291,18 +295,18 @@ export const filesMap = [
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/inventory/relations-to-other-modules/page.mdx",
|
||||
"pathname": "/commerce-modules/inventory/relations-to-other-modules"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/order/_events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/order/_events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/order/_events/page.mdx",
|
||||
"pathname": "/commerce-modules/order/_events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/order/concepts/page.mdx",
|
||||
"pathname": "/commerce-modules/order/concepts"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/order/events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/order/events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/order/events/page.mdx",
|
||||
"pathname": "/commerce-modules/order/events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/order/order-change/page.mdx",
|
||||
"pathname": "/commerce-modules/order/order-change"
|
||||
@@ -336,12 +340,12 @@ export const filesMap = [
|
||||
"pathname": "/commerce-modules"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/payment/events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/payment/events/_events-table"
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/payment/_events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/payment/_events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/payment/events/page.mdx",
|
||||
"pathname": "/commerce-modules/payment/events"
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/payment/_events/page.mdx",
|
||||
"pathname": "/commerce-modules/payment/_events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/payment/examples/page.mdx",
|
||||
@@ -387,18 +391,18 @@ export const filesMap = [
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/payment/webhook-events/page.mdx",
|
||||
"pathname": "/commerce-modules/payment/webhook-events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/pricing/_events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/pricing/_events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/pricing/_events/page.mdx",
|
||||
"pathname": "/commerce-modules/pricing/_events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/pricing/concepts/page.mdx",
|
||||
"pathname": "/commerce-modules/pricing/concepts"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/pricing/events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/pricing/events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/pricing/events/page.mdx",
|
||||
"pathname": "/commerce-modules/pricing/events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/pricing/examples/page.mdx",
|
||||
"pathname": "/commerce-modules/pricing/examples"
|
||||
@@ -420,12 +424,12 @@ export const filesMap = [
|
||||
"pathname": "/commerce-modules/pricing/relations-to-other-modules"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/product/events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/product/events/_events-table"
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/product/_events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/product/_events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/product/events/page.mdx",
|
||||
"pathname": "/commerce-modules/product/events"
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/product/_events/page.mdx",
|
||||
"pathname": "/commerce-modules/product/_events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/product/examples/page.mdx",
|
||||
@@ -439,6 +443,14 @@ export const filesMap = [
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/product/relations-to-other-modules/page.mdx",
|
||||
"pathname": "/commerce-modules/product/relations-to-other-modules"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/promotion/_events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/promotion/_events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/promotion/_events/page.mdx",
|
||||
"pathname": "/commerce-modules/promotion/_events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/promotion/actions/page.mdx",
|
||||
"pathname": "/commerce-modules/promotion/actions"
|
||||
@@ -455,14 +467,6 @@ export const filesMap = [
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/promotion/concepts/page.mdx",
|
||||
"pathname": "/commerce-modules/promotion/concepts"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/promotion/events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/promotion/events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/promotion/events/page.mdx",
|
||||
"pathname": "/commerce-modules/promotion/events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/promotion/examples/page.mdx",
|
||||
"pathname": "/commerce-modules/promotion/examples"
|
||||
@@ -476,12 +480,12 @@ export const filesMap = [
|
||||
"pathname": "/commerce-modules/promotion/relations-to-other-modules"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/region/events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/region/events/_events-table"
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/region/_events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/region/_events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/region/events/page.mdx",
|
||||
"pathname": "/commerce-modules/region/events"
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/region/_events/page.mdx",
|
||||
"pathname": "/commerce-modules/region/_events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/region/examples/page.mdx",
|
||||
@@ -496,12 +500,12 @@ export const filesMap = [
|
||||
"pathname": "/commerce-modules/region/relations-to-other-modules"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/sales-channel/events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/sales-channel/events/_events-table"
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/sales-channel/_events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/sales-channel/_events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/sales-channel/events/page.mdx",
|
||||
"pathname": "/commerce-modules/sales-channel/events"
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/sales-channel/_events/page.mdx",
|
||||
"pathname": "/commerce-modules/sales-channel/_events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/sales-channel/examples/page.mdx",
|
||||
@@ -519,18 +523,18 @@ export const filesMap = [
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/sales-channel/relations-to-other-modules/page.mdx",
|
||||
"pathname": "/commerce-modules/sales-channel/relations-to-other-modules"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/stock-location/_events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/stock-location/_events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/stock-location/_events/page.mdx",
|
||||
"pathname": "/commerce-modules/stock-location/_events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/stock-location/concepts/page.mdx",
|
||||
"pathname": "/commerce-modules/stock-location/concepts"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/stock-location/events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/stock-location/events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/stock-location/events/page.mdx",
|
||||
"pathname": "/commerce-modules/stock-location/events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/stock-location/examples/page.mdx",
|
||||
"pathname": "/commerce-modules/stock-location/examples"
|
||||
@@ -544,12 +548,12 @@ export const filesMap = [
|
||||
"pathname": "/commerce-modules/stock-location/relations-to-other-modules"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/store/events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/store/events/_events-table"
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/store/_events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/store/_events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/store/events/page.mdx",
|
||||
"pathname": "/commerce-modules/store/events"
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/store/_events/page.mdx",
|
||||
"pathname": "/commerce-modules/store/_events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/store/examples/page.mdx",
|
||||
@@ -564,12 +568,12 @@ export const filesMap = [
|
||||
"pathname": "/commerce-modules/store/relations-to-other-modules"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/tax/events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/tax/events/_events-table"
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/tax/_events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/tax/_events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/tax/events/page.mdx",
|
||||
"pathname": "/commerce-modules/tax/events"
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/tax/_events/page.mdx",
|
||||
"pathname": "/commerce-modules/tax/_events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/tax/examples/page.mdx",
|
||||
@@ -596,12 +600,12 @@ export const filesMap = [
|
||||
"pathname": "/commerce-modules/tax/tax-region"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/user/events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/user/events/_events-table"
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/user/_events/_events-table/page.mdx",
|
||||
"pathname": "/commerce-modules/user/_events/_events-table"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/user/events/page.mdx",
|
||||
"pathname": "/commerce-modules/user/events"
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/user/_events/page.mdx",
|
||||
"pathname": "/commerce-modules/user/_events"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/commerce-modules/user/examples/page.mdx",
|
||||
@@ -671,10 +675,6 @@ export const filesMap = [
|
||||
"filePath": "/www/apps/resources/app/deployment/storefront/vercel/page.mdx",
|
||||
"pathname": "/deployment/storefront/vercel"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/events-reference/page.mdx",
|
||||
"pathname": "/events-reference"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/favicon.ico",
|
||||
"pathname": "/"
|
||||
|
||||
@@ -162,13 +162,6 @@ export const generatedSidebar = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"path": "/commerce-modules/api-key/events",
|
||||
"title": "Events Reference",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -371,13 +364,6 @@ export const generatedSidebar = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"path": "/commerce-modules/auth/events",
|
||||
"title": "Events Reference",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -880,13 +866,6 @@ export const generatedSidebar = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"path": "/commerce-modules/cart/events",
|
||||
"title": "Events Reference",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -990,13 +969,6 @@ export const generatedSidebar = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"path": "/commerce-modules/currency/events",
|
||||
"title": "Events Reference",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1275,13 +1247,6 @@ export const generatedSidebar = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"path": "/commerce-modules/customer/events",
|
||||
"title": "Events Reference",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1931,13 +1896,6 @@ export const generatedSidebar = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"path": "/commerce-modules/fulfillment/events",
|
||||
"title": "Events Reference",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -2293,13 +2251,6 @@ export const generatedSidebar = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"path": "/commerce-modules/inventory/events",
|
||||
"title": "Events Reference",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -3187,13 +3138,6 @@ export const generatedSidebar = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"path": "/commerce-modules/order/events",
|
||||
"title": "Events Reference",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -3557,13 +3501,6 @@ export const generatedSidebar = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"path": "/commerce-modules/payment/events",
|
||||
"title": "Events Reference",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -3947,13 +3884,6 @@ export const generatedSidebar = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"path": "/commerce-modules/pricing/events",
|
||||
"title": "Events Reference",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -4533,13 +4463,6 @@ export const generatedSidebar = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"path": "/commerce-modules/product/events",
|
||||
"title": "Events Reference",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -4881,13 +4804,6 @@ export const generatedSidebar = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"path": "/commerce-modules/promotion/events",
|
||||
"title": "Events Reference",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -5061,13 +4977,6 @@ export const generatedSidebar = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"path": "/commerce-modules/region/events",
|
||||
"title": "Events Reference",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -5220,13 +5129,6 @@ export const generatedSidebar = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"path": "/commerce-modules/sales-channel/events",
|
||||
"title": "Events Reference",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -5386,13 +5288,6 @@ export const generatedSidebar = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"path": "/commerce-modules/stock-location/events",
|
||||
"title": "Events Reference",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -5545,13 +5440,6 @@ export const generatedSidebar = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"path": "/commerce-modules/store/events",
|
||||
"title": "Events Reference",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -5823,13 +5711,6 @@ export const generatedSidebar = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"path": "/commerce-modules/tax/events",
|
||||
"title": "Events Reference",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -6052,13 +5933,6 @@ export const generatedSidebar = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"path": "/commerce-modules/user/events",
|
||||
"title": "Events Reference",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -7917,13 +7791,6 @@ export const generatedSidebar = [
|
||||
"title": "Medusa Container Resources",
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"path": "/events-reference",
|
||||
"title": "Events",
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
|
||||
@@ -65,10 +65,10 @@ export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/commerce-modules/api-key/events",
|
||||
title: "Events Reference",
|
||||
},
|
||||
// {
|
||||
// path: "/commerce-modules/api-key/events",
|
||||
// title: "Events Reference",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -156,10 +156,10 @@ export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/commerce-modules/auth/events",
|
||||
title: "Events Reference",
|
||||
},
|
||||
// {
|
||||
// path: "/commerce-modules/auth/events",
|
||||
// title: "Events Reference",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -224,10 +224,10 @@ export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/commerce-modules/cart/events",
|
||||
title: "Events Reference",
|
||||
},
|
||||
// {
|
||||
// path: "/commerce-modules/cart/events",
|
||||
// title: "Events Reference",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -280,10 +280,10 @@ export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/commerce-modules/currency/events",
|
||||
title: "Events Reference",
|
||||
},
|
||||
// {
|
||||
// path: "/commerce-modules/currency/events",
|
||||
// title: "Events Reference",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -340,10 +340,10 @@ export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/commerce-modules/customer/events",
|
||||
title: "Events Reference",
|
||||
},
|
||||
// {
|
||||
// path: "/commerce-modules/customer/events",
|
||||
// title: "Events Reference",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -417,10 +417,10 @@ export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/commerce-modules/fulfillment/events",
|
||||
title: "Events Reference",
|
||||
},
|
||||
// {
|
||||
// path: "/commerce-modules/fulfillment/events",
|
||||
// title: "Events Reference",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -482,10 +482,10 @@ export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/commerce-modules/inventory/events",
|
||||
title: "Events Reference",
|
||||
},
|
||||
// {
|
||||
// path: "/commerce-modules/inventory/events",
|
||||
// title: "Events Reference",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -558,10 +558,10 @@ export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/commerce-modules/order/events",
|
||||
title: "Events Reference",
|
||||
},
|
||||
// {
|
||||
// path: "/commerce-modules/order/events",
|
||||
// title: "Events Reference",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -657,10 +657,10 @@ export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/commerce-modules/payment/events",
|
||||
title: "Events Reference",
|
||||
},
|
||||
// {
|
||||
// path: "/commerce-modules/payment/events",
|
||||
// title: "Events Reference",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -725,10 +725,10 @@ export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/commerce-modules/pricing/events",
|
||||
title: "Events Reference",
|
||||
},
|
||||
// {
|
||||
// path: "/commerce-modules/pricing/events",
|
||||
// title: "Events Reference",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -781,10 +781,10 @@ export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/commerce-modules/product/events",
|
||||
title: "Events Reference",
|
||||
},
|
||||
// {
|
||||
// path: "/commerce-modules/product/events",
|
||||
// title: "Events Reference",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -853,10 +853,10 @@ export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/commerce-modules/promotion/events",
|
||||
title: "Events Reference",
|
||||
},
|
||||
// {
|
||||
// path: "/commerce-modules/promotion/events",
|
||||
// title: "Events Reference",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -909,10 +909,10 @@ export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/commerce-modules/region/events",
|
||||
title: "Events Reference",
|
||||
},
|
||||
// {
|
||||
// path: "/commerce-modules/region/events",
|
||||
// title: "Events Reference",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -971,10 +971,10 @@ export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/commerce-modules/sales-channel/events",
|
||||
title: "Events Reference",
|
||||
},
|
||||
// {
|
||||
// path: "/commerce-modules/sales-channel/events",
|
||||
// title: "Events Reference",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -1034,10 +1034,10 @@ export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/commerce-modules/stock-location/events",
|
||||
title: "Events Reference",
|
||||
},
|
||||
// {
|
||||
// path: "/commerce-modules/stock-location/events",
|
||||
// title: "Events Reference",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -1090,10 +1090,10 @@ export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/commerce-modules/store/events",
|
||||
title: "Events Reference",
|
||||
},
|
||||
// {
|
||||
// path: "/commerce-modules/store/events",
|
||||
// title: "Events Reference",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -1162,10 +1162,10 @@ export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/commerce-modules/tax/events",
|
||||
title: "Events Reference",
|
||||
},
|
||||
// {
|
||||
// path: "/commerce-modules/tax/events",
|
||||
// title: "Events Reference",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -1222,10 +1222,10 @@ export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/commerce-modules/user/events",
|
||||
title: "Events Reference",
|
||||
},
|
||||
// {
|
||||
// path: "/commerce-modules/user/events",
|
||||
// title: "Events Reference",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -2104,10 +2104,10 @@ export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
path: "/medusa-container-resources",
|
||||
title: "Medusa Container Resources",
|
||||
},
|
||||
{
|
||||
path: "/events-reference",
|
||||
title: "Events",
|
||||
},
|
||||
// {
|
||||
// path: "/events-reference",
|
||||
// title: "Events",
|
||||
// },
|
||||
{
|
||||
path: "/admin-widget-injection-zones",
|
||||
title: "Admin Widget Injection Zones",
|
||||
|
||||
@@ -9,4 +9,3 @@ NEXT_PUBLIC_SEGMENT_API_KEY=
|
||||
NEXT_PUBLIC_AI_ASSISTANT_URL=
|
||||
NEXT_PUBLIC_AI_WEBSITE_ID=
|
||||
NEXT_PUBLIC_AI_API_ASSISTANT_RECAPTCHA_SITE_KEY=
|
||||
NEXT_PUBLIC_SHOW_V2=
|
||||
@@ -1,10 +1,5 @@
|
||||
import { ArrowUpRightOnBox } from "@medusajs/icons"
|
||||
import {
|
||||
NavbarItem,
|
||||
getNavbarItems,
|
||||
legacyMobileSidebarItems,
|
||||
mobileSidebarItemsV1,
|
||||
} from "docs-ui"
|
||||
import { NavbarItem, getNavbarItems, mobileSidebarItemsV1 } from "docs-ui"
|
||||
import { SidebarSectionItemsType } from "types"
|
||||
import { siteConfig } from "./site"
|
||||
|
||||
@@ -17,7 +12,7 @@ export const docsConfig: DocsConfig = {
|
||||
mainNav: getNavbarItems({
|
||||
basePath: siteConfig.baseUrl,
|
||||
activePath: process.env.NEXT_PUBLIC_BASE_PATH || "/ui",
|
||||
version: process.env.NEXT_PUBLIC_SHOW_V2 ? "v1" : "legacy",
|
||||
version: "v1",
|
||||
}),
|
||||
sidebar: {
|
||||
top: [
|
||||
@@ -285,8 +280,6 @@ export const docsConfig: DocsConfig = {
|
||||
],
|
||||
},
|
||||
],
|
||||
mobile: process.env.NEXT_PUBLIC_SHOW_V2
|
||||
? mobileSidebarItemsV1
|
||||
: legacyMobileSidebarItems,
|
||||
mobile: mobileSidebarItemsV1,
|
||||
},
|
||||
}
|
||||
@@ -52,22 +52,23 @@ export const navbarItemsV1: NavbarItem[] = [
|
||||
href: `/ui`,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "divider",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
props: {
|
||||
label: "Learn Medusa v2",
|
||||
target: "_blank",
|
||||
rel: "noreferrer",
|
||||
href: `/v2`,
|
||||
badge: {
|
||||
variant: "blue",
|
||||
children: "New",
|
||||
},
|
||||
},
|
||||
},
|
||||
// TODO enable them later
|
||||
// {
|
||||
// type: "divider",
|
||||
// },
|
||||
// {
|
||||
// type: "link",
|
||||
// props: {
|
||||
// label: "Learn Medusa v2",
|
||||
// target: "_blank",
|
||||
// rel: "noreferrer",
|
||||
// href: `/v2`,
|
||||
// badge: {
|
||||
// variant: "blue",
|
||||
// children: "New",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
]
|
||||
|
||||
export const navbarItemsV2: NavbarItem[] = [
|
||||
@@ -122,71 +123,10 @@ export const navbarItemsV2: NavbarItem[] = [
|
||||
{
|
||||
type: "link",
|
||||
props: {
|
||||
label: "Medusa V1",
|
||||
label: "Medusa v1",
|
||||
target: "_blank",
|
||||
rel: "noreferrer",
|
||||
href: `/`,
|
||||
badge: {
|
||||
variant: "neutral",
|
||||
children: "v1",
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const legacyNavbarItems: NavbarItem[] = [
|
||||
{
|
||||
type: "link",
|
||||
props: {
|
||||
label: "Docs",
|
||||
target: "_blank",
|
||||
rel: "noreferrer",
|
||||
href: `/`,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
props: {
|
||||
label: "Resources",
|
||||
target: "_blank",
|
||||
rel: "noreferrer",
|
||||
href: `/resources`,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
props: {
|
||||
label: "User Guide",
|
||||
target: "_blank",
|
||||
rel: "noreferrer",
|
||||
href: `/user-guide`,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
props: {
|
||||
label: "Store API",
|
||||
target: "_blank",
|
||||
rel: "noreferrer",
|
||||
href: `/api/store`,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
props: {
|
||||
label: "Admin API",
|
||||
target: "_blank",
|
||||
rel: "noreferrer",
|
||||
href: `/api/admin`,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
props: {
|
||||
label: "UI",
|
||||
target: "_blank",
|
||||
rel: "noreferrer",
|
||||
href: `/ui`,
|
||||
},
|
||||
},
|
||||
]
|
||||
@@ -222,13 +162,13 @@ export const mobileSidebarItemsV1: SidebarItemType[] = [
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Learn Medusa V2",
|
||||
path: `/v2`,
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
additionalElms: <Badge variant="blue">v2</Badge>,
|
||||
},
|
||||
// {
|
||||
// title: "Learn Medusa V2",
|
||||
// path: `/v2`,
|
||||
// loaded: true,
|
||||
// isPathHref: true,
|
||||
// additionalElms: <Badge variant="blue">v2</Badge>,
|
||||
// },
|
||||
]
|
||||
|
||||
export const mobileSidebarItemsV2: SidebarItemType[] = [
|
||||
@@ -263,51 +203,17 @@ export const mobileSidebarItemsV2: SidebarItemType[] = [
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Docs",
|
||||
title: "Medusa v1",
|
||||
path: `/`,
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
additionalElms: <Badge variant="neutral">v1</Badge>,
|
||||
},
|
||||
]
|
||||
|
||||
export const legacyMobileSidebarItems: SidebarItemType[] = [
|
||||
{
|
||||
title: "Docs",
|
||||
path: `/`,
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "User Guide",
|
||||
path: `/user-guide`,
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Store API",
|
||||
path: `/api/store`,
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "Admin API",
|
||||
path: `/api/admin`,
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
title: "UI",
|
||||
path: `/ui`,
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
]
|
||||
|
||||
export const searchFiltersV2: OptionType[] = [
|
||||
{
|
||||
value: "book",
|
||||
label: "Docs V2",
|
||||
label: "Docs v2",
|
||||
},
|
||||
{
|
||||
value: "resources",
|
||||
@@ -315,11 +221,11 @@ export const searchFiltersV2: OptionType[] = [
|
||||
},
|
||||
{
|
||||
value: "admin-v2",
|
||||
label: "Admin API",
|
||||
label: "Admin API (v2)",
|
||||
},
|
||||
{
|
||||
value: "store-v2",
|
||||
label: "Store API",
|
||||
label: "Store API (v2)",
|
||||
},
|
||||
// TODO add more filters
|
||||
]
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
import { NavbarItem, legacyNavbarItems, navbarItemsV1, navbarItemsV2 } from ".."
|
||||
import { NavbarItem, navbarItemsV1, navbarItemsV2 } from ".."
|
||||
|
||||
type Options = {
|
||||
basePath: string
|
||||
activePath: string
|
||||
version?: "v1" | "v2" | "legacy"
|
||||
version?: "v1" | "v2"
|
||||
}
|
||||
|
||||
export function getNavbarItems({
|
||||
basePath,
|
||||
activePath,
|
||||
version = "legacy",
|
||||
version = "v1",
|
||||
}: Options): NavbarItem[] {
|
||||
const navbarItems =
|
||||
version === "v2"
|
||||
? navbarItemsV2
|
||||
: version === "v1"
|
||||
? navbarItemsV1
|
||||
: legacyNavbarItems
|
||||
const navbarItems = version === "v2" ? navbarItemsV2 : navbarItemsV1
|
||||
return navbarItems.map((item) => {
|
||||
if (item.type === "divider") {
|
||||
return item
|
||||
|
||||
Reference in new issue
Block a user