From 3298cd3fd2fd2d870d9ee4fb85ea9b8c1d9727e1 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Wed, 9 Oct 2024 12:53:17 +0300 Subject: [PATCH] docs: improved commerce module docs [2/n] (#9501) Improve + add docs for commerce modules from currency to inventory [2/n] --- .../currency/examples/page.mdx | 18 +- .../app/commerce-modules/currency/page.mdx | 57 +- .../relations-to-other-modules/page.mdx | 13 - .../customer/customer-accounts/page.mdx | 2 +- .../customer/examples/page.mdx | 36 +- .../commerce-modules/customer/extend/page.mdx | 684 ++++++++++++++++++ .../app/commerce-modules/customer/page.mdx | 59 +- .../relations-to-other-modules/page.mdx | 22 - .../fulfillment/fulfillment-provider/page.mdx | 2 +- .../fulfillment/item-fulfillment/page.mdx | 2 +- .../links-to-other-modules/page.mdx | 43 ++ .../app/commerce-modules/fulfillment/page.mdx | 53 +- .../relations-to-other-modules/page.mdx | 29 - .../fulfillment/shipping-option/page.mdx | 2 +- .../inventory/concepts/page.mdx | 2 +- .../inventory/examples/page.mdx | 81 +-- .../inventory/inventory-in-flows/page.mdx | 4 + .../inventory/links-to-other-modules/page.mdx | 15 + .../app/commerce-modules/inventory/page.mdx | 65 +- .../relations-to-other-modules/page.mdx | 25 - www/apps/resources/generated/edit-dates.mjs | 37 +- www/apps/resources/generated/files-map.mjs | 28 +- www/apps/resources/generated/sidebar.mjs | 40 +- www/apps/resources/next.config.mjs | 14 + www/apps/resources/sidebar.mjs | 33 +- 25 files changed, 993 insertions(+), 373 deletions(-) delete mode 100644 www/apps/resources/app/commerce-modules/currency/relations-to-other-modules/page.mdx create mode 100644 www/apps/resources/app/commerce-modules/customer/extend/page.mdx delete mode 100644 www/apps/resources/app/commerce-modules/customer/relations-to-other-modules/page.mdx create mode 100644 www/apps/resources/app/commerce-modules/fulfillment/links-to-other-modules/page.mdx delete mode 100644 www/apps/resources/app/commerce-modules/fulfillment/relations-to-other-modules/page.mdx create mode 100644 www/apps/resources/app/commerce-modules/inventory/links-to-other-modules/page.mdx delete mode 100644 www/apps/resources/app/commerce-modules/inventory/relations-to-other-modules/page.mdx diff --git a/www/apps/resources/app/commerce-modules/currency/examples/page.mdx b/www/apps/resources/app/commerce-modules/currency/examples/page.mdx index 18b1b32c7e..0aaa085521 100644 --- a/www/apps/resources/app/commerce-modules/currency/examples/page.mdx +++ b/www/apps/resources/app/commerce-modules/currency/examples/page.mdx @@ -13,16 +13,15 @@ In this guide, you’ll find common examples of how you can use the Currency Mod - ```ts - import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" - import { ICurrencyModuleService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" export async function GET( req: MedusaRequest, res: MedusaResponse ): Promise { - const currencyModuleService: ICurrencyModuleService = req.scope.resolve( + const currencyModuleService = req.scope.resolve( Modules.CURRENCY ) @@ -59,16 +58,15 @@ export async function GET(request: Request) { - ```ts - import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" - import { ICurrencyModuleService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" export async function GET( req: MedusaRequest, res: MedusaResponse ): Promise { - const currencyModuleService: ICurrencyModuleService = req.scope.resolve( + const currencyModuleService = req.scope.resolve( Modules.CURRENCY ) diff --git a/www/apps/resources/app/commerce-modules/currency/page.mdx b/www/apps/resources/app/commerce-modules/currency/page.mdx index 189747ac19..8168722ecc 100644 --- a/www/apps/resources/app/commerce-modules/currency/page.mdx +++ b/www/apps/resources/app/commerce-modules/currency/page.mdx @@ -6,7 +6,7 @@ export const metadata = { # {metadata.title} -The Currency Module is the `@medusajs/medusa/currency` NPM package that provides currency-related features in your Medusa and Node.js applications. +The Currency Module provides currency-related features in your Medusa and Node.js applications. ## How to Use Currency Module's Service @@ -15,18 +15,33 @@ You can use the Currency Module's main service by resolving from the Medusa cont For example: + + +```ts title="src/workflows/hello-world/step1.ts" +import { createStep } from "@medusajs/framework/workflows-sdk" +import { Modules } from "@medusajs/framework/utils" + +const step1 = createStep("step-1", async (_, { container }) => { + const currencyModuleService = container.resolve( + Modules.CURRENCY + ) + + const currencies = await currencyModuleService.listCurrencies() +}) +``` + + - ```ts title="src/api/store/custom/route.ts" - import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" - import { ICurrencyModuleService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts title="src/api/store/custom/route.ts" +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" export async function GET( req: MedusaRequest, res: MedusaResponse ): Promise { - const currencyModuleService: ICurrencyModuleService = req.scope.resolve( + const currencyModuleService = req.scope.resolve( Modules.CURRENCY ) @@ -39,35 +54,17 @@ export async function GET( - ```ts title="src/subscribers/custom-handler.ts" - import { SubscriberArgs } from "@medusajs/framework" - import { ICurrencyModuleService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts title="src/subscribers/custom-handler.ts" +import { SubscriberArgs } from "@medusajs/framework" +import { Modules } from "@medusajs/framework/utils" export default async function subscriberHandler({ container }: SubscriberArgs) { - const currencyModuleService: ICurrencyModuleService = container.resolve( + const currencyModuleService = container.resolve( Modules.CURRENCY ) const currencies = await currencyModuleService.listCurrencies() } -``` - - - - - ```ts title="src/workflows/hello-world/step1.ts" - import { createStep } from "@medusajs/framework/workflows-sdk" - import { ICurrencyModuleService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" - -const step1 = createStep("step-1", async (_, { container }) => { - const currencyModuleService: ICurrencyModuleService = container.resolve( - Modules.CURRENCY - ) - - const currencies = await currencyModuleService.listCurrencies() -}) ``` @@ -87,12 +84,12 @@ const currency = await currencyModuleService.retrieveCurrency("usd") ### Support Currencies in Modules -Other commerce modules use currency codes in their data models or operations. You can use the Currency Module to retrieve a currency code and its details. +Other commerce modules use currency codes in their data models or operations. Use the Currency Module to retrieve a currency code and its details. An example with the Region Module: ```ts -const region = await regionModuleService.retrieveCurrency("reg_123") +const region = await regionModuleService.retrieveRegion("reg_123") const currency = await currencyModuleService.retrieveCurrency( region.currency_code ) diff --git a/www/apps/resources/app/commerce-modules/currency/relations-to-other-modules/page.mdx b/www/apps/resources/app/commerce-modules/currency/relations-to-other-modules/page.mdx deleted file mode 100644 index 1d45624c6b..0000000000 --- a/www/apps/resources/app/commerce-modules/currency/relations-to-other-modules/page.mdx +++ /dev/null @@ -1,13 +0,0 @@ -export const metadata = { - title: `Relations between Currency Module and Other Modules`, -} - -# {metadata.title} - -This document showcases the link modules defined between the Currency Module and other commerce modules. - -## Store Module - -A store has a default currency. Medusa defines a link module that builds a relationship between the `Store` and `Currency` data models. - -![A diagram showcasing an example of how resources from the Stock Location and Inventory modules are linked.](https://res.cloudinary.com/dza7lstvk/image/upload/v1716798146/Medusa%20Resources/store-currency_wzftwh.jpg) diff --git a/www/apps/resources/app/commerce-modules/customer/customer-accounts/page.mdx b/www/apps/resources/app/commerce-modules/customer/customer-accounts/page.mdx index 54dda6c6e5..c4b5806bf4 100644 --- a/www/apps/resources/app/commerce-modules/customer/customer-accounts/page.mdx +++ b/www/apps/resources/app/commerce-modules/customer/customer-accounts/page.mdx @@ -18,6 +18,6 @@ When this or another guest customer registers an account with the same email, a ## Email Uniqueness -The above behavior means that two `Customer` records may exist of the same email. However, the main difference is the `has_account` property's value. +The above behavior means that two `Customer` records may exist with the same email. However, the main difference is the `has_account` property's value. So, there can only be one guest customer (having `has_account=false`) and one registered customer (having `has_account=true`) with the same email. diff --git a/www/apps/resources/app/commerce-modules/customer/examples/page.mdx b/www/apps/resources/app/commerce-modules/customer/examples/page.mdx index d9561ab441..c2f5b0759f 100644 --- a/www/apps/resources/app/commerce-modules/customer/examples/page.mdx +++ b/www/apps/resources/app/commerce-modules/customer/examples/page.mdx @@ -13,13 +13,12 @@ In this guide, you’ll find common examples of how you can use the Customer Mod - ```ts - import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" - import { ICustomerModuleService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" export async function POST(request: MedusaRequest, res: MedusaResponse) { - const customerModuleService: ICustomerModuleService = request.scope.resolve( + const customerModuleService = request.scope.resolve( Modules.CUSTOMER ) @@ -68,13 +67,12 @@ export async function POST(request: Request) { - ```ts - import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" - import { ICustomerModuleService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" export async function POST(request: MedusaRequest, res: MedusaResponse) { - const customerModuleService: ICustomerModuleService = request.scope.resolve( + const customerModuleService = request.scope.resolve( Modules.CUSTOMER ) @@ -119,13 +117,12 @@ export async function POST(request: Request) { - ```ts - import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" - import { ICustomerModuleService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" export async function POST(request: MedusaRequest, res: MedusaResponse) { - const customerModuleService: ICustomerModuleService = request.scope.resolve( + const customerModuleService = request.scope.resolve( Modules.CUSTOMER ) @@ -168,13 +165,12 @@ export async function POST(request: Request) { - ```ts - import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" - import { ICustomerModuleService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" export async function POST(request: MedusaRequest, res: MedusaResponse) { - const customerModuleService: ICustomerModuleService = request.scope.resolve( + const customerModuleService = request.scope.resolve( Modules.CUSTOMER ) diff --git a/www/apps/resources/app/commerce-modules/customer/extend/page.mdx b/www/apps/resources/app/commerce-modules/customer/extend/page.mdx new file mode 100644 index 0000000000..6c4a4568d4 --- /dev/null +++ b/www/apps/resources/app/commerce-modules/customer/extend/page.mdx @@ -0,0 +1,684 @@ +import { Prerequisites } from "docs-ui" + +export const metadata = { + title: `Extend Customer Data Model`, +} + +# {metadata.title} + +In this documentation, you'll learn how to extend a data model of the Customer Module to add a custom property. + +You'll create a `Custom` data model in a module. This data model will have a `custom_name` property, which is the property you want to add to the [Customer data model](/references/customer/models/Customer) defined in the Customer Module. + +You'll then learn how to: + +- Link the `Custom` data model to the `Customer` data model. +- Set the `custom_name` property when a customer is created or updated using Medusa's API routes. +- Retrieve the `custom_name` property with the customer's details, in custom or existing API routes. + + + +Similar steps can bee applied to the `CustomerAddress` data model. + + + +## Step 1: Define Custom Data Model + +Consider you have a Hello Module defined in the `/src/modules/hello` directory. + + + +If you don't have a module, follow [this guide](!docs!/basics/modules) to create one. + + + +To add the `custom_name` property to the `Customer` data model, you'll create in the Hello Module a data model that has the `custom_name` property. + +Create the file `src/modules/hello/models/custom.ts` with the following content: + +```ts title="src/modules/hello/models/custom.ts" +import { model } from "@medusajs/framework/utils" + +export const Custom = model.define("custom", { + id: model.id().primaryKey(), + custom_name: model.text(), +}) +``` + +This creates a `Custom` data model that has the `id` and `custom_name` properties. + + + +Learn more about data models in [this guide](!docs!/data-models). + + + +--- + +## Step 2: Define Link to Customer Data Model + +Next, you'll define a module link between the `Custom` and `Customer` data model. A module link allows you to form a relation between two data models of separate modules while maintaining module isolation. + + + +Learn more about module links in [this guide](!docs!/module-links). + + + +Create the file `src/links/customer-custom.ts` with the following content: + +```ts title="src/links/customer-custom.ts" +import { defineLink } from "@medusajs/framework/utils" +import HelloModule from "../modules/hello" +import CustomerModule from "@medusajs/medusa/customer" + +export default defineLink( + CustomerModule.linkable.customer, + HelloModule.linkable.custom +) +``` + +This defines a link between the `Customer` and `Custom` data models. Using this link, you'll later query data across the modules, and link records of each data model. + +--- + +## Step 3: Generate and Run Migrations + + + +To reflect the `Custom` data model in the database, generate a migration that defines the table to be created for it. + +Run the following command in your Medusa project's root: + +```bash +npx medusa db:generate helloModuleService +``` + +Where `helloModuleService` is your module's name. + +Then, run the `db:migrate` command to run the migrations and create a table in the database for the link between the `Customer` and `Custom` data models: + +```bash +npx medusa db:migrate +``` + +A table for the link is now created in the database. You can now retrieve and manage the link between records of the data models. + +--- + +## Step 4: Consume customersCreated Workflow Hook + +When a customer is created, you also want to create a `Custom` record and set the `custom_name` property, then create a link between the `Customer` and `Custom` records. + +To do that, you'll consume the [customersCreated](/resources/references/medusa-workflows/createCustomersWorkflow#customerscreated) hook of the [createCustomersWorkflow](/references/medusa-workflows/createCustomersWorkflow). This workflow is executed in the [Create Customer Admin API route](!api!/admin#customers_postcustomers) + + + +Learn more about workflow hooks in [this guide](!docs!/advanced-development/workflows/workflow-hooks). + + + +The API route accepts in its request body an `additional_data` parameter. You can pass in it custom data, which is passed to the workflow hook handler. + +### Add custom_name to Additional Data Validation + +To pass the `custom_name` in the `additional_data` parameter, you must add a validation rule that tells the Medusa application about this custom property. + +Create the file `src/api/middlewares.ts` with the following content: + +```ts title="src/api/middlewares.ts" +import { defineMiddlewares } from "@medusajs/medusa" +import { z } from "zod" + +export default defineMiddlewares({ + routes: [ + { + method: "POST", + matcher: "/admin/customers", + additionalDataValidator: { + custom_name: z.string().optional(), + }, + }, + ], +}) +``` + +The `additional_data` parameter validation is customized using the `defineMiddlewares` utility function. In the routes middleware configuration object, the `additionalDataValidator` property accepts [Zod](https://zod.dev/) validaiton rules. + +In the snippet above, you add a validation rule indicating that `custom_name` is a string that can be passed in the `additional_data` object. + + + +Learn more about additional data validation in [this guide](!docs!/advanced-development/api-routes/additional-data). + + + +### Create Workflow to Create Custom Record + +You'll now create a workflow that will be used in the hook handler. + +This workflow will create a `Custom` record, then link it to the customer. + +Start by creating the step that creates the `Custom` record. Create the file `src/workflows/create-custom-from-customer/steps/create-custom.ts` with the following content: + +```ts title="src/workflows/create-custom-from-customer/steps/create-custom.ts" +import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk" +import HelloModuleService from "../../../modules/hello/service" +import { HELLO_MODULE } from "../../../modules/hello" + +type CreateCustomStepInput = { + custom_name?: string +} + +export const createCustomStep = createStep( + "create-custom", + async (data: CreateCustomStepInput, { container }) => { + if (!data.custom_name) { + return + } + + const helloModuleService: HelloModuleService = container.resolve( + HELLO_MODULE + ) + + const custom = await helloModuleService.createCustoms(data) + + return new StepResponse(custom, custom) + }, + async (custom, { container }) => { + const helloModuleService: HelloModuleService = container.resolve( + HELLO_MODULE + ) + + await helloModuleService.deleteCustoms(custom.id) + } +) +``` + +In the step, you resolve the Hello Module's main service and create a `Custom` record. + +In the compensation function that undoes the step's actions in case of an error, you delete the created record. + + + +Learn more about compensation functions in [this guide](!docs!/advanced-development/workflows/compensation-function). + + + +Then, create the workflow at `src/workflows/create-custom-from-customer/index.ts` with the following content: + +```ts title="src/workflows/create-custom-from-customer/index.ts" collapsibleLines="1-7" expandButtonLabel="Show Imports" +import { createWorkflow, transform, when, WorkflowResponse } from "@medusajs/framework/workflows-sdk" +import { CustomerDTO } from "@medusajs/framework/types" +import { createRemoteLinkStep } from "@medusajs/medusa/core-flows" +import { Modules } from "@medusajs/framework/utils" +import { HELLO_MODULE } from "../../modules/hello" +import { createCustomStep } from "./steps/create-custom" + +export type CreateCustomFromCustomerWorkflowInput = { + customer: CustomerDTO + additional_data?: { + custom_name?: string + } +} + +export const createCustomFromCustomerWorkflow = createWorkflow( + "create-custom-from-customer", + (input: CreateCustomFromCustomerWorkflowInput) => { + const customName = transform( + { + input, + }, + (data) => data.input.additional_data.custom_name || "" + ) + + const custom = createCustomStep({ + custom_name: customName, + }) + + when(({ custom }), ({ custom }) => custom !== undefined) + .then(() => { + createRemoteLinkStep([{ + [Modules.CUSTOMER]: { + customer_id: input.customer.id, + }, + [HELLO_MODULE]: { + custom_id: custom.id, + }, + }]) + }) + + return new WorkflowResponse({ + custom, + }) + } +) +``` + +The workflow accepts as an input the created customer and the `additional_data` parameter passed in the request. This is the same input that the `customersCreated` hook accepts. + +In the workflow, you: + +1. Use the `transform` utility to get the value of `custom_name` based on whether it's set in `additional_data`. Learn more about why you can't use conditional operators in a workflow without using `transform` in [this guide](!docs!/advanced-development/workflows/conditions#why-if-conditions-arent-allowed-in-workflows). +2. Create the `Custom` record using the `createCustomStep`. +3. Use the `when-then` utility to link the customer to the `Custom` record if it was created. Learn more about why you can't use if-then conditions in a workflow without using `when-then` in [this guide](!docs!/advanced-development/workflows/conditions#why-if-conditions-arent-allowed-in-workflows). + +You'll next call the workflow in the hook handler. + +### Consume Workflow Hook + +You can now consume the `customersCreated` hook, which is executed in the `createCustomersWorkflow` after the customer is created. + +To consume the hook, create the file `src/workflow/hooks/customer-created.ts` with the following content: + +```ts title="src/workflow/hooks/customer-created.ts" collapsibleLines="1-6" expandButtonLabel="Show Imports" +import { createCustomersWorkflow } from "@medusajs/medusa/core-flows" +import { + createCustomFromCustomerWorkflow, + CreateCustomFromCustomerWorkflowInput, +} from "../create-custom-from-customer" + +createCustomersWorkflow.hooks.customersCreated( + async ({ customers, additional_data }, { container }) => { + const workflow = createCustomFromCustomerWorkflow(container) + + for (const customer of customers) { + await workflow.run({ + input: { + customer, + additional_data, + } as CreateCustomFromCustomerWorkflowInput, + }) + } + } +) +``` + +The hook handler executes the `createCustomFromCustomerWorkflow`, passing it its input. + +### Test it Out + +To test it out, send a `POST` request to `/admin/customers` to create a customer, passing `custom_name` in `additional_data`: + +```bash +curl --location 'localhost:9000/admin/customers' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer {token}' \ +--data-raw '{ + "email": "customer@gmail.com", + "additional_data": { + "custom_name": "test" + } +}' +``` + +Make sure to replace `{token}` with an admin user's JWT token. Learn how to retrieve it in the [API reference](!api!/admin#1-bearer-authorization-with-jwt-tokens). + +The request will return the customer's details. You'll learn how to retrive the `custom_name` property with the customer's details in the next section. + +--- + +## Step 5: Retrieve custom_name with Customer Details + +When you extend an existing data model through links, you also want to retrieve the custom properties with the data model. + +### Retrieve in API Routes + +To retrieve the `custom_name` property when you're retrieving the customer through API routes, such as the [Get Customer API Route](!api!/admin#customers_getcustomersid), pass in the `fields` query parameter `+custom.*`, which retrieves the linked `Custom` record's details. + + + +The `+` prefix in `+custom.*` indicates that the relation should be retrieved with the default customer fields. Learn more about selecting fields and relations in the [API reference](!api!/admin#select-fields-and-relations). + + + +For example: + +```bash +curl -X POST 'localhost:9000/admin/customers/{customer_id}?fields=+custom.*' \ +-H 'Authorization: Bearer {token}' +``` + +Make sure to replace `{customer_id}` with the customer's ID, and `{token}` with an admin user's JWT token. + +Among the returned `customer` object, you'll find a `custom` property which holds the details of the linked `Custom` record: + +```json +{ + "customer": { + // ... + "custom": { + "id": "01J9NP7ANXDZ0EAYF0956ZE1ZA", + "custom_name": "test", + "created_at": "2024-10-08T09:09:06.877Z", + "updated_at": "2024-10-08T09:09:06.877Z", + "deleted_at": null + } + } +} +``` + +### Retrieve using Query + +You can also retrieve the `Custom` record linked to a customer in your code using [Query](!docs!/advanced-development/module-links/query). + +For example: + +```ts +const { data: [customer] } = await query.graph({ + entity: "customer", + fields: ["*", "custom.*"], + filters: { + id: customer_id, + }, +}) +``` + +Learn more about how to use Query in [this guide](!docs!/advanced-development/module-links/query). + +--- + +## Step 6: Consume customersUpdated Workflow Hook + +Similar to the `customersCreated` hook, you'll consume the [customersUpdated](/references/medusa-workflows/updateCustomersWorkflow#customersUpdated) hook of the [updateCustomersWorkflow](/references/medusa-workflows/updateCustomersWorkflow) to update `custom_name` when the customer is updated. + +The `updateCustomersWorkflow` is executed by the [Update Customer API route](!api!/admin#customers_postcustomersid), which accepts the `additional_data` parameter to pass custom data to the hook. + +### Add custom_name to Additional Data Validation + +To allow passing `custom_name` in the `additional_data` parameter of the update customer route, add in `src/api/middlewares.ts` a new route middleware configuration object: + +```ts title="src/api/middlewares.ts" +import { defineMiddlewares } from "@medusajs/medusa" +import { z } from "zod" + +export default defineMiddlewares({ + routes: [ + // ... + { + method: "POST", + matcher: "/admin/customers/:id", + additionalDataValidator: { + custom_name: z.string().nullish(), + }, + }, + ], +}) +``` + +The validation schema is the similar to that of the Create Customer API route, except you can pass a `null` value for `custom_name` to remove or unset the `custom_name`'s value. + +### Create Workflow to Update Custom Record + +Next, you'll create a workflow that creates, updates, or deletes `Custom` records based on the provided `additional_data` parameter: + +1. If `additional_data.custom_name` is set and it's `null`, the `Custom` record linked to the customer is deleted. +2. If `additional_data.custom_name` is set and the customer doesn't have a linked `Custom` record, a new record is created and linked to the customer. +3. If `additional_data.custom_name` is set and the customer has a linked `Custom` record, the `custom_name` property of the `Custom` record is updated. + +Start by creating the step that updates a `Custom` record. Create the file `src/workflows/update-custom-from-customer/steps/update-custom.ts` with the following content: + +```ts title="src/workflows/update-custom-from-customer/steps/update-custom.ts" +import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk" +import { HELLO_MODULE } from "../../../modules/hello" +import HelloModuleService from "../../../modules/hello/service" + +type UpdateCustomStepInput = { + id: string + custom_name: string +} + +export const updateCustomStep = createStep( + "update-custom", + async ({ id, custom_name }: UpdateCustomStepInput, { container }) => { + const helloModuleService: HelloModuleService = container.resolve( + HELLO_MODULE + ) + + const prevData = await helloModuleService.retrieveCustom(id) + + const custom = await helloModuleService.updateCustoms({ + id, + custom_name, + }) + + return new StepResponse(custom, prevData) + }, + async (prevData, { container }) => { + const helloModuleService: HelloModuleService = container.resolve( + HELLO_MODULE + ) + + await helloModuleService.updateCustoms(prevData) + } +) +``` + +In this step, you update a `Custom` record. In the compensation function, you revert the update. + +Next, you'll create the step that deletes a `Custom` record. Create the file `src/workflows/update-custom-from-customer/steps/delete-custom.ts` with the following content: + +```ts title="src/workflows/update-custom-from-customer/steps/delete-custom.ts" collapsibleLines="1-6" expandButtonLabel="Show Imports" +import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk" +import { Custom } from "../../../modules/hello/models/custom" +import { InferTypeOf } from "@medusajs/framework/types" +import HelloModuleService from "../../../modules/hello/service" +import { HELLO_MODULE } from "../../../modules/hello" + +type DeleteCustomStepInput = { + custom: InferTypeOf +} + +export const deleteCustomStep = createStep( + "delete-custom", + async ({ custom }: DeleteCustomStepInput, { container }) => { + const helloModuleService: HelloModuleService = container.resolve( + HELLO_MODULE + ) + + await helloModuleService.deleteCustoms(custom.id) + + return new StepResponse(custom, custom) + }, + async (custom, { container }) => { + const helloModuleService: HelloModuleService = container.resolve( + HELLO_MODULE + ) + + await helloModuleService.createCustoms(custom) + } +) +``` + +In this step, you delete a `Custom` record. In the compensation function, you create it again. + +Finally, you'll create the workflow. Create the file `src/workflows/update-custom-from-customer/index.ts` with the following content: + +```ts title="src/workflows/update-custom-from-customer/index.ts" collapsibleLines="1-9" expandButtonLabel="Show Imports" +import { CustomerDTO } from "@medusajs/framework/types" +import { createWorkflow, when, WorkflowResponse } from "@medusajs/framework/workflows-sdk" +import { createRemoteLinkStep, dismissRemoteLinkStep, useRemoteQueryStep } from "@medusajs/medusa/core-flows" +import { createCustomStep } from "../create-custom-from-customer/steps/create-custom" +import { Modules } from "@medusajs/framework/utils" +import { HELLO_MODULE } from "../../modules/hello" +import { deleteCustomStep } from "./steps/delete-custom" +import { updateCustomStep } from "./steps/update-custom" + +export type UpdateCustomFromCustomerStepInput = { + customer: CustomerDTO + additional_data?: { + custom_name?: string | null + } +} + +export const updateCustomFromCustomerWorkflow = createWorkflow( + "update-custom-from-customer", + (input: UpdateCustomFromCustomerStepInput) => { + const customerData = useRemoteQueryStep({ + entry_point: "customer", + fields: ["custom.*"], + variables: { + filters: { + id: input.customer.id, + }, + }, + list: false, + }) + + // TODO create, update, or delete Custom record + } +) +``` + +The workflow accepts the same input as the `customersUpdated` workflow hook handler would. + +In the workflow, you retrieve the customer's linked `Custom` record using Query. + +Next, replace the `TODO` with the following: + +```ts title="src/workflows/update-custom-from-customer/index.ts" +const created = when({ + input, + customerData, +}, (data) => + !data.customerData.custom && + data.input.additional_data?.custom_name?.length > 0 +) +.then(() => { + const custom = createCustomStep({ + custom_name: input.additional_data.custom_name, + }) + + createRemoteLinkStep([{ + [Modules.CUSTOMER]: { + customer_id: input.customer.id, + }, + [HELLO_MODULE]: { + custom_id: custom.id, + }, + }]) + + return custom +}) + +// TODO update, or delete Custom record +``` + +Using the `when-then` utility, you check if the customer doesn't have a linked `Custom` record and the `custom_name` property is set. If so, you create a `Custom` record and link it to the customer. + +To create the `Custom` record, you use the `createCustomStep` you created in an earlier section. + +Next, replace the new `TODO` with the following: + +```ts title="src/workflows/update-custom-from-customer/index.ts" +const deleted = when({ + input, + customerData, +}, (data) => + data.customerData.custom && ( + data.input.additional_data?.custom_name === null || + data.input.additional_data?.custom_name.length === 0 + ) +) +.then(() => { + deleteCustomStep({ + custom: customerData.custom, + }) + + dismissRemoteLinkStep({ + [HELLO_MODULE]: { + custom_id: customerData.custom.id, + }, + }) + + return customerData.custom.id +}) + +// TODO delete Custom record +``` + +Using the `when-then` utility, you check if the customer has a linked `Custom` record and `custom_name` is `null` or an empty string. If so, you delete the linked `Custom` record and dismiss its links. + +Finally, replace the new `TODO` with the following: + +```ts title="src/workflows/update-custom-from-customer/index.ts" +const updated = when({ + input, + customerData, +}, (data) => data.customerData.custom && data.input.additional_data?.custom_name?.length > 0) +.then(() => { + const custom = updateCustomStep({ + id: customerData.custom.id, + custom_name: input.additional_data.custom_name, + }) + + return custom +}) + +return new WorkflowResponse({ + created, + updated, + deleted, +}) +``` + +Using the `when-then` utility, you check if the customer has a linked `Custom` record and `custom_name` is passed in the `additional_data`. If so, you update the linked `Custom` recod. + +You return in the workflow response the created, updated, and deleted `Custom` record. + +### Consume customersUpdated Workflow Hook + +You can now consume the `customersUpdated` and execute the workflow you created. + +Create the file `src/workflows/hooks/customer-updated.ts` with the following content: + +```ts title="src/workflows/hooks/customer-updated.ts" +import { updateCustomersWorkflow } from "@medusajs/medusa/core-flows" +import { + UpdateCustomFromCustomerStepInput, + updateCustomFromCustomerWorkflow, +} from "../update-custom-from-customer" + +updateCustomersWorkflow.hooks.customersUpdated( + async ({ customers, additional_data }, { container }) => { + const workflow = updateCustomFromCustomerWorkflow(container) + + for (const customer of customers) { + await workflow.run({ + input: { + customer, + additional_data, + } as UpdateCustomFromCustomerStepInput, + }) + } + } +) +``` + +In the workflow hook handler, you execute the workflow, passing it the hook's input. + +### Test it Out + +To test it out, send a `POST` request to `/admin/customers/:id` to update a customer, passing `custom_name` in `additional_data`: + +```bash +curl -X POST 'localhost:9000/admin/customers/{customer_id}' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer {token}' \ +--data '{ + "additional_data": { + "custom_name": "test3" + } +}' +``` + +Make sure to replace `{customer_id}` with the customer's ID, and `{token}` with the JWT token of an admin user. + +The request will return the customer's details with the updated `custom` linked record. diff --git a/www/apps/resources/app/commerce-modules/customer/page.mdx b/www/apps/resources/app/commerce-modules/customer/page.mdx index b05ff8eca5..725bc89769 100644 --- a/www/apps/resources/app/commerce-modules/customer/page.mdx +++ b/www/apps/resources/app/commerce-modules/customer/page.mdx @@ -6,7 +6,7 @@ export const metadata = { # {metadata.title} -The Customer Module is the `@medusajs/medusa/customer` NPM package that provides customer-related features in your Medusa and Node.js applications. +The Customer Module provides customer-related features in your Medusa and Node.js applications. ## How to Use Customer Module's Service @@ -15,15 +15,30 @@ You can use the Customer Module's main service by resolving from the Medusa cont For example: + + +```ts title="src/workflows/hello-world/step1.ts" +import { createStep } from "@medusajs/framework/workflows-sdk" +import { Modules } from "@medusajs/framework/utils" + +const step1 = createStep("step-1", async (_, { container }) => { + const customerModuleService = container.resolve( + Modules.CUSTOMER + ) + + const customers = await customerModuleService.listCustomers() +}) +``` + + - ```ts title="src/api/store/custom/route.ts" - import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" - import { ICustomerModuleService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts title="src/api/store/custom/route.ts" +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" export async function GET(request: MedusaRequest, res: MedusaResponse) { - const customerModuleService: ICustomerModuleService = request.scope.resolve( + const customerModuleService = request.scope.resolve( Modules.CUSTOMER ) @@ -36,35 +51,17 @@ export async function GET(request: MedusaRequest, res: MedusaResponse) { - ```ts title="src/subscribers/custom-handler.ts" - import { SubscriberArgs } from "@medusajs/framework" - import { ICustomerModuleService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts title="src/subscribers/custom-handler.ts" +import { SubscriberArgs } from "@medusajs/framework" +import { Modules } from "@medusajs/framework/utils" export default async function subscriberHandler({ container }: SubscriberArgs) { - const customerModuleService: ICustomerModuleService = container.resolve( + const customerModuleService = container.resolve( Modules.CUSTOMER ) const customers = await customerModuleService.listCustomers() } -``` - - - - - ```ts title="src/workflows/hello-world/step1.ts" - import { createStep } from "@medusajs/framework/workflows-sdk" - import { ICustomerModuleService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" - -const step1 = createStep("step-1", async (_, { container }) => { - const customerModuleService: ICustomerModuleService = container.resolve( - Modules.CUSTOMER - ) - - const customers = await customerModuleService.listCustomers() -}) ``` @@ -76,7 +73,7 @@ const step1 = createStep("step-1", async (_, { container }) => { ### Customer Management -With the Customer Module, store and manage customers in your store. +With the Customer Module, store and manage customers. ```ts const customer = await customerModuleService.createCustomers({ @@ -88,7 +85,9 @@ const customer = await customerModuleService.createCustomers({ ### Customer Organization -You can organize customers into groups. This has a lot of benefits and supports more use cases, such as provide discounts for specific customer groups using the Promotion Module. +Organize customers into groups. + +This has a lot of benefits and supports many use cases, such as provide discounts for specific customer groups using the Promotion Module. ```ts const customerGroup = await customerModuleService.createCustomerGroups({ diff --git a/www/apps/resources/app/commerce-modules/customer/relations-to-other-modules/page.mdx b/www/apps/resources/app/commerce-modules/customer/relations-to-other-modules/page.mdx deleted file mode 100644 index e15c8529d1..0000000000 --- a/www/apps/resources/app/commerce-modules/customer/relations-to-other-modules/page.mdx +++ /dev/null @@ -1,22 +0,0 @@ -export const metadata = { - title: `Relations between Customer Module and Other Modules`, -} - -# {metadata.title} - -This document showcases the link modules defined between the Customer Module and other commerce modules. - -## Cart Module - -A customer has a cart to purchase items from the store. Medusa defines a link module that builds a relationship between the `Customer` and the `Cart` data models. - -![A diagram showcasing an example of how data models from the Customer and Cart modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1711537276/Medusa%20Resources/cart-customer_pnjvuw.jpg) - ---- - -## Order Module - -A customer is associated with the orders they place. Medusa defines a link module that builds a relationship between the `Customer` and the `Order` data models. - -![A diagram showcasing an example of how data models from the Customer and Order modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716545470/Medusa%20Resources/customer-order_pkla6f.jpg) - diff --git a/www/apps/resources/app/commerce-modules/fulfillment/fulfillment-provider/page.mdx b/www/apps/resources/app/commerce-modules/fulfillment/fulfillment-provider/page.mdx index 19cadad623..72334ef0e8 100644 --- a/www/apps/resources/app/commerce-modules/fulfillment/fulfillment-provider/page.mdx +++ b/www/apps/resources/app/commerce-modules/fulfillment/fulfillment-provider/page.mdx @@ -10,7 +10,7 @@ In this document, you’ll learn what a fulfillment module provider is. A fulfillment module provider handles fulfilling items, typically using a third-party integration. -Fulfillment module providers are stored and represented by the [FulfillmentProvider data model](/references/fulfillment/models/FulfillmentProvider). +Fulfillment module providers registered in the Fulfillment Module's [options](../module-options/page.mdx) are stored and represented by the [FulfillmentProvider data model](/references/fulfillment/models/FulfillmentProvider). --- diff --git a/www/apps/resources/app/commerce-modules/fulfillment/item-fulfillment/page.mdx b/www/apps/resources/app/commerce-modules/fulfillment/item-fulfillment/page.mdx index 645e01a44a..3eaeb0bf5c 100644 --- a/www/apps/resources/app/commerce-modules/fulfillment/item-fulfillment/page.mdx +++ b/www/apps/resources/app/commerce-modules/fulfillment/item-fulfillment/page.mdx @@ -12,7 +12,7 @@ A fulfillment is the shipping and delivery of one or more items to the customer. --- -## Fulfillment Processing +## Fulfillment Processing by a Fulfillment Provider A fulfillment is associated with a fulfillment provider that handles all its processing, such as creating a shipment for the fulfillment’s items. diff --git a/www/apps/resources/app/commerce-modules/fulfillment/links-to-other-modules/page.mdx b/www/apps/resources/app/commerce-modules/fulfillment/links-to-other-modules/page.mdx new file mode 100644 index 0000000000..461f244937 --- /dev/null +++ b/www/apps/resources/app/commerce-modules/fulfillment/links-to-other-modules/page.mdx @@ -0,0 +1,43 @@ +export const metadata = { + title: `Links between Fulfillment Module and Other Modules`, +} + +# {metadata.title} + +This document showcases the module links defined between the Fulfillment Module and other commerce modules. + +## Order Module + +The Order Module provides order-management functionalities. + +Medusa defines a link between the `Fulfillment` and `Order` data models. A fulfillment is created for an orders' items. + +![A diagram showcasing an example of how data models from the Fulfillment and Order modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716549903/Medusa%20Resources/order-fulfillment_h0vlps.jpg) + +A fulfillment is also created for a return's items. So, Medusa defines a link between the `Fulfillment` and `Return` data models. + +![A diagram showcasing an example of how data models from the Fulfillment and Order modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1728399052/Medusa%20Resources/Social_Media_Graphics_2024_Order_Return_vetimk.jpg) + +--- + +## Pricing Module + +The Pricing Module provides features to store, manage, and retrieve the best prices in a specified context. + +Medusa defines a link between the `PriceSet` and `ShippingOption` data models. A shipping option's price is stored as a price set. + +![A diagram showcasing an example of how data models from the Pricing and Fulfillment modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716561747/Medusa%20Resources/pricing-fulfillment_spywwa.jpg) + +--- + +## Stock Location Module + +The Stock Location Module provides features to manage stock locations in a store. + +Medusa defines a link between the `FulfillmentSet` and `StockLocation` data models. A fulfillment set can be conditioned to a specific stock location. + +![A diagram showcasing an example of how data models from the Fulfillment and Stock Location modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1712567101/Medusa%20Resources/fulfillment-stock-location_nlkf7e.jpg) + +Medusa also defines a link between the `FulfillmentProvider` and `StockLocation` data models to indicate the providers that can be used in a location. + +![A diagram showcasing an example of how data models from the Fulfillment and Stock Location modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1728399492/Medusa%20Resources/fulfillment-provider-stock-location_b0mulo.jpg) diff --git a/www/apps/resources/app/commerce-modules/fulfillment/page.mdx b/www/apps/resources/app/commerce-modules/fulfillment/page.mdx index b1d30724ff..aba253fb4e 100644 --- a/www/apps/resources/app/commerce-modules/fulfillment/page.mdx +++ b/www/apps/resources/app/commerce-modules/fulfillment/page.mdx @@ -6,7 +6,7 @@ export const metadata = { # {metadata.title} -The Fulfillment Module is the `@medusajs/medusa/fulfillment` NPM package that provides fulfillment-related features in your Medusa and Node.js applications. +The Fulfillment Module provides fulfillment-related features in your Medusa and Node.js applications. ## How to Use Fulfillment Module's Service @@ -15,18 +15,33 @@ You can use the Fulfillment Module's main service by resolving from the Medusa c For example: + + +```ts title="src/workflows/hello-world/step1.ts" +import { createStep } from "@medusajs/framework/workflows-sdk" +import { Modules } from "@medusajs/framework/utils" + +const step1 = createStep("step-1", async (_, { container }) => { + const fulfillmentModuleService = container.resolve( + Modules.FULFILLMENT + ) + + const fulfillments = await fulfillmentModuleService.listFulfillments() +}) +``` + + - ```ts title="src/api/store/custom/route.ts" - import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" - import { IFulfillmentModuleService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts title="src/api/store/custom/route.ts" +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" export async function GET( req: MedusaRequest, res: MedusaResponse ): Promise { - const fulfillmentModuleService: IFulfillmentModuleService = req.scope.resolve( + const fulfillmentModuleService = req.scope.resolve( Modules.FULFILLMENT ) @@ -39,35 +54,17 @@ export async function GET( - ```ts title="src/subscribers/custom-handler.ts" - import { SubscriberArgs } from "@medusajs/framework" - import { IFulfillmentModuleService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts title="src/subscribers/custom-handler.ts" +import { SubscriberArgs } from "@medusajs/framework" +import { Modules } from "@medusajs/framework/utils" export default async function subscriberHandler({ container }: SubscriberArgs) { - const fulfillmentModuleService: IFulfillmentModuleService = container.resolve( + const fulfillmentModuleService = container.resolve( Modules.FULFILLMENT ) const fulfillments = await fulfillmentModuleService.listFulfillments() } -``` - - - - - ```ts title="src/workflows/hello-world/step1.ts" - import { createStep } from "@medusajs/framework/workflows-sdk" - import { IFulfillmentModuleService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" - -const step1 = createStep("step-1", async (_, { container }) => { - const fulfillmentModuleService: IFulfillmentModuleService = container.resolve( - Modules.FULFILLMENT - ) - - const fulfillments = await fulfillmentModuleService.listFulfillments() -}) ``` diff --git a/www/apps/resources/app/commerce-modules/fulfillment/relations-to-other-modules/page.mdx b/www/apps/resources/app/commerce-modules/fulfillment/relations-to-other-modules/page.mdx deleted file mode 100644 index cce271f1da..0000000000 --- a/www/apps/resources/app/commerce-modules/fulfillment/relations-to-other-modules/page.mdx +++ /dev/null @@ -1,29 +0,0 @@ -export const metadata = { - title: `Relations between Fulfillment Module and Other Modules`, -} - -# {metadata.title} - -This document showcases the link modules defined between the Fulfillment Module and other commerce modules. - -## Order Module - -A fulfillment is created for an orders' items. Medusa defines a link module that builds a relationship between the `Fulfillment` and `Order` data models. - -![A diagram showcasing an example of how data models from the Fulfillment and Order modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716549903/Medusa%20Resources/order-fulfillment_h0vlps.jpg) - ---- - -## Pricing Module - -A shipping option's price is stored as a price set. Medusa defines a link module that builds a relationship between the `PriceSet` and `ShippingOption` data models. - -![A diagram showcasing an example of how data models from the Pricing and Fulfillment modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1716561747/Medusa%20Resources/pricing-fulfillment_spywwa.jpg) - ---- - -## Stock Location Module - -A fulfillment set can be conditioned to a specific stock location. Medusa defines a link module that builds a relationship between the `FulfillmentSet` and `StockLocation` data models. - -![A diagram showcasing an example of how data models from the Fulfillment and Stock Location modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1712567101/Medusa%20Resources/fulfillment-stock-location_nlkf7e.jpg) diff --git a/www/apps/resources/app/commerce-modules/fulfillment/shipping-option/page.mdx b/www/apps/resources/app/commerce-modules/fulfillment/shipping-option/page.mdx index 6ecfcd319b..225b1879da 100644 --- a/www/apps/resources/app/commerce-modules/fulfillment/shipping-option/page.mdx +++ b/www/apps/resources/app/commerce-modules/fulfillment/shipping-option/page.mdx @@ -45,7 +45,7 @@ These rules are represented by the [ShippingOptionRule data model](/references/f ![A diagram showcasing the relation between shipping option and shipping option rules.](https://res.cloudinary.com/dza7lstvk/image/upload/v1712331340/Medusa%20Resources/shipping-option-rule_oosopf.jpg) -A shipping option can have multiple rules. For example, a shipping option is available if the customer belongs to the VIP group and the total weight is less than 2000g. +A shipping option can have multiple rules. For example, you can add rules to a shipping option so that it's available if the customer belongs to the VIP group and the total weight is less than 2000g. ![A diagram showcasing how a shipping option can have multiple rules.](https://res.cloudinary.com/dza7lstvk/image/upload/v1712331462/Medusa%20Resources/shipping-option-rule-2_ylaqdb.jpg) diff --git a/www/apps/resources/app/commerce-modules/inventory/concepts/page.mdx b/www/apps/resources/app/commerce-modules/inventory/concepts/page.mdx index 3b907c56a1..558ad72d22 100644 --- a/www/apps/resources/app/commerce-modules/inventory/concepts/page.mdx +++ b/www/apps/resources/app/commerce-modules/inventory/concepts/page.mdx @@ -34,6 +34,6 @@ The inventory level's location is determined by the `location_id` property. Medu ## ReservationItem -A reservation item, represented by the `ReservationItem` data model, represents unavailable quantity of an inventory item in a location. It's used when an order is placed but not fulfilled yet. +A reservation item, represented by the [ReservationItem](/references/inventory-next/models/ReservationItem) data model, represents unavailable quantity of an inventory item in a location. It's used when an order is placed but not fulfilled yet. The reserved quantity is associated with a location, so it has a similar relation to that of the `InventoryLevel` with the Stock Location Module. diff --git a/www/apps/resources/app/commerce-modules/inventory/examples/page.mdx b/www/apps/resources/app/commerce-modules/inventory/examples/page.mdx index d01a02cae1..36d0c765db 100644 --- a/www/apps/resources/app/commerce-modules/inventory/examples/page.mdx +++ b/www/apps/resources/app/commerce-modules/inventory/examples/page.mdx @@ -13,16 +13,15 @@ In this document, you’ll find common examples of how you can use the Inventory - ```ts - import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" - import { IInventoryService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" export async function POST( request: MedusaRequest, res: MedusaResponse ): Promise { - const inventoryModuleService: IInventoryService = request.scope.resolve( + const inventoryModuleService = request.scope.resolve( Modules.INVENTORY ) @@ -68,16 +67,15 @@ export async function POST(request: Request) { - ```ts - import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" - import { IInventoryService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" export async function GET( request: MedusaRequest, res: MedusaResponse ): Promise { - const inventoryModuleService: IInventoryService = request.scope.resolve( + const inventoryModuleService = request.scope.resolve( Modules.INVENTORY ) @@ -114,16 +112,15 @@ export async function GET(request: Request) { - ```ts - import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" - import { IInventoryService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" export async function GET( request: MedusaRequest, res: MedusaResponse ): Promise { - const inventoryModuleService: IInventoryService = request.scope.resolve( + const inventoryModuleService = request.scope.resolve( Modules.INVENTORY ) @@ -170,16 +167,15 @@ export async function GET(request: Request, { params }: ContextType) { - ```ts - import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" - import { IInventoryService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" export async function POST( request: MedusaRequest, res: MedusaResponse ): Promise { - const inventoryModuleService: IInventoryService = request.scope.resolve( + const inventoryModuleService = request.scope.resolve( Modules.INVENTORY ) @@ -225,16 +221,15 @@ export async function POST(request: Request) { - ```ts - import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" - import { IInventoryService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" export async function POST( request: MedusaRequest, res: MedusaResponse ): Promise { - const inventoryModuleService: IInventoryService = request.scope.resolve( + const inventoryModuleService = request.scope.resolve( Modules.INVENTORY ) @@ -280,16 +275,15 @@ export async function POST(request: Request) { - ```ts - import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" - import { IInventoryService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" export async function POST( request: MedusaRequest, res: MedusaResponse ): Promise { - const inventoryModuleService: IInventoryService = request.scope.resolve( + const inventoryModuleService = request.scope.resolve( Modules.INVENTORY ) @@ -335,16 +329,15 @@ export async function POST(request: Request) { - ```ts - import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" - import { IInventoryService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" export async function POST( request: MedusaRequest, res: MedusaResponse ): Promise { - const inventoryModuleService: IInventoryService = request.scope.resolve( + const inventoryModuleService = request.scope.resolve( Modules.INVENTORY ) @@ -392,16 +385,15 @@ export async function POST(request: Request) { - ```ts - import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" - import { IInventoryService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" export async function GET( request: MedusaRequest, res: MedusaResponse ): Promise { - const inventoryModuleService: IInventoryService = request.scope.resolve( + const inventoryModuleService = request.scope.resolve( Modules.INVENTORY ) @@ -479,16 +471,15 @@ export async function POST(request: Request, { params }: ContextType) { - ```ts - import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" - import { IInventoryService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" export async function DELETE( request: MedusaRequest, res: MedusaResponse ): Promise { - const inventoryModuleService: IInventoryService = request.scope.resolve( + const inventoryModuleService = request.scope.resolve( Modules.INVENTORY ) diff --git a/www/apps/resources/app/commerce-modules/inventory/inventory-in-flows/page.mdx b/www/apps/resources/app/commerce-modules/inventory/inventory-in-flows/page.mdx index 4630fe05be..6a5abd7ac1 100644 --- a/www/apps/resources/app/commerce-modules/inventory/inventory-in-flows/page.mdx +++ b/www/apps/resources/app/commerce-modules/inventory/inventory-in-flows/page.mdx @@ -47,3 +47,7 @@ When an item in an order is fulfilled and the associated variant has its `manage When an item in an order is returned and the associated variant has its `manage_inventory` property set to `true`, the Medusa application increments the `stocked_quantity` of the inventory item's level with the returned quantity. ![A diagram showcasing how the Inventory Module is used in the order return flow](https://res.cloudinary.com/dza7lstvk/image/upload/v1709712457/Medusa%20Resources/inventory-order-return_ihftyk.jpg) + +### Dismissed Returned Items + +If a returned item is considered damanged or its dismissed, its quantity doesn't increment the `stocked_quantity` of the inventory item's level. \ No newline at end of file diff --git a/www/apps/resources/app/commerce-modules/inventory/links-to-other-modules/page.mdx b/www/apps/resources/app/commerce-modules/inventory/links-to-other-modules/page.mdx new file mode 100644 index 0000000000..56aed72916 --- /dev/null +++ b/www/apps/resources/app/commerce-modules/inventory/links-to-other-modules/page.mdx @@ -0,0 +1,15 @@ +export const metadata = { + title: `Links between Inventory Module and Other Modules`, +} + +# {metadata.title} + +This document showcases the module links defined between the Inventory Module and other commerce modules. + +## Product Module + +Each product variant has different inventory details. Medusa defines a link between the `ProductVariant` and `InventoryItem` data models. + +![A diagram showcasing an example of how data models from the Inventory and Product Module are linked.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709658720/Medusa%20Resources/inventory-product_ejnray.jpg) + +A product variant whose `manage_inventory` property is enabled has an associated inventory item. Through that inventory's items relations in the Inventory Module, you can manage and check the variant's inventory quantity. diff --git a/www/apps/resources/app/commerce-modules/inventory/page.mdx b/www/apps/resources/app/commerce-modules/inventory/page.mdx index 88d1389916..9e92821533 100644 --- a/www/apps/resources/app/commerce-modules/inventory/page.mdx +++ b/www/apps/resources/app/commerce-modules/inventory/page.mdx @@ -6,7 +6,7 @@ export const metadata = { # {metadata.title} -The Inventory Module is the `@medusajs/medusa/inventory-next` NPM package that provides inventory-related features in your Medusa and Node.js applications. +The Inventory Module provides inventory-related features in your Medusa and Node.js applications. ## How to Use Inventory Module's Service @@ -15,18 +15,33 @@ You can use the Inventory Module's main service by resolving from the Medusa con For example: + + +```ts title="src/workflows/hello-world/step1.ts" +import { createStep } from "@medusajs/framework/workflows-sdk" +import { Modules } from "@medusajs/framework/utils" + +const step1 = createStep("step-1", async (_, { container }) => { + const inventoryModuleService = container.resolve( + Modules.INVENTORY + ) + + const inventoryItems = await inventoryModuleService.listInventoryItems({}) +}) +``` + + - ```ts title="src/api/store/custom/route.ts" - import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" - import { IInventoryService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts title="src/api/store/custom/route.ts" +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" export async function GET( request: MedusaRequest, res: MedusaResponse ): Promise { - const inventoryModuleService: IInventoryService = request.scope.resolve( + const inventoryModuleService = request.scope.resolve( Modules.INVENTORY ) @@ -39,35 +54,17 @@ export async function GET( - ```ts title="src/subscribers/custom-handler.ts" - import { SubscriberArgs } from "@medusajs/framework" - import { IInventoryService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" +```ts title="src/subscribers/custom-handler.ts" +import { SubscriberArgs } from "@medusajs/framework" +import { Modules } from "@medusajs/framework/utils" export default async function subscriberHandler({ container }: SubscriberArgs) { - const inventoryModuleService: IInventoryService = container.resolve( + const inventoryModuleService = container.resolve( Modules.INVENTORY ) const inventoryItems = await inventoryModuleService.listInventoryItems({}) } -``` - - - - - ```ts title="src/workflows/hello-world/step1.ts" - import { createStep } from "@medusajs/framework/workflows-sdk" - import { IInventoryService } from "@medusajs/framework/types" - import { Modules } from "@medusajs/framework/utils" - -const step1 = createStep("step-1", async (_, { container }) => { - const inventoryModuleService: IInventoryService = container.resolve( - Modules.INVENTORY - ) - - const inventoryItems = await inventoryModuleService.listInventoryItems({}) -}) ``` @@ -93,7 +90,9 @@ const inventoryItem = await inventoryModuleService.createInventoryItems({ ### Inventory Across Locations -Inventory items' quantities are set per locations through inventory levels. This gives you more flexibility in managing the quantity of a stock-kept item across different locations, such as different warehouses. +Inventory items' quantities are set per locations through inventory levels. + +This gives you more flexibility in managing the quantity of a stock-kept item across different locations, such as different warehouses. ```ts const inventoryLevel = await inventoryModuleService.createInventoryLevels([ @@ -107,7 +106,9 @@ const inventoryLevel = await inventoryModuleService.createInventoryLevels([ ### Reservation Management -Reserve quantities of inventory items at specific locations for orders or other purposes. The reserved quantity isn't considered for purchase, but can be deleted to revert the reservation. +Reserve quantities of inventory items at specific locations for orders or other purposes. + +The reserved quantity isn't considered for purchase, but can be deleted to revert the reservation. ```ts const reservationItem = await inventoryModuleService.createReservationItems([ @@ -121,7 +122,9 @@ const reservationItem = await inventoryModuleService.createReservationItems([ ### Check Inventory Availability -Check whether an inventory item has the necessary quantity for purchase. Any reserved quantity is considered unavailable. +Check whether an inventory item has the necessary quantity for purchase. + +Any reserved quantity is considered unavailable. ```ts const isAvailable = await inventoryModuleService.confirmInventory( diff --git a/www/apps/resources/app/commerce-modules/inventory/relations-to-other-modules/page.mdx b/www/apps/resources/app/commerce-modules/inventory/relations-to-other-modules/page.mdx deleted file mode 100644 index ceaeddae9a..0000000000 --- a/www/apps/resources/app/commerce-modules/inventory/relations-to-other-modules/page.mdx +++ /dev/null @@ -1,25 +0,0 @@ -export const metadata = { - title: `Relations between Inventory Module and Other Modules`, -} - -# {metadata.title} - -This document showcases the link modules defined between the Inventory Module and other commerce modules. - -## Product Module - -Each product variant has different inventory details. Medusa defines a link module that builds a relationship between the `ProductVariant` and `InventoryItem` data models. - -![A diagram showcasing an example of how data models from the Inventory and Product Module are linked.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709658720/Medusa%20Resources/inventory-product_ejnray.jpg) - -A product variant, whose `manage_inventory` property is enabled, has an associated inventory item. Through that inventory's items relations in the Inventory Module, you can manage and check the variant's inventory quantity. - ---- - -## Stock Location Module - -Reservation items and inventory items are associated with a location. The Medusa application forms a relation between the `ReservationItem` and `StockLocation` data models, and the `InventoryLevel` and `StockLocation` data models. - -![A diagram showcasing an example of how data models from the Inventory and Stock Location modules are linked.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709660383/Medusa%20Resources/inventory-stock-location_yp26k3.jpg) - -The stock location provides address details of the location. diff --git a/www/apps/resources/generated/edit-dates.mjs b/www/apps/resources/generated/edit-dates.mjs index db6c03b9fa..88257c07c4 100644 --- a/www/apps/resources/generated/edit-dates.mjs +++ b/www/apps/resources/generated/edit-dates.mjs @@ -15,31 +15,27 @@ export const generatedEditDates = { "app/commerce-modules/cart/page.mdx": "2024-09-30T08:43:53.157Z", "app/commerce-modules/currency/_events/_events-table/page.mdx": "2024-07-03T19:27:13+03:00", "app/commerce-modules/currency/_events/page.mdx": "2024-07-03T19:27:13+03:00", - "app/commerce-modules/currency/examples/page.mdx": "2024-09-30T08:43:53.158Z", - "app/commerce-modules/currency/relations-to-other-modules/page.mdx": "2024-05-29T11:08:06+00:00", - "app/commerce-modules/currency/page.mdx": "2024-09-30T08:43:53.159Z", + "app/commerce-modules/currency/examples/page.mdx": "2024-10-08T15:06:26.492Z", + "app/commerce-modules/currency/page.mdx": "2024-10-08T15:03:00.907Z", "app/commerce-modules/customer/_events/_events-table/page.mdx": "2024-07-03T19:27:13+03:00", "app/commerce-modules/customer/_events/page.mdx": "2024-07-03T19:27:13+03:00", - "app/commerce-modules/customer/customer-accounts/page.mdx": "2024-06-26T07:55:59+00:00", - "app/commerce-modules/customer/examples/page.mdx": "2024-09-30T08:43:53.159Z", - "app/commerce-modules/customer/relations-to-other-modules/page.mdx": "2024-05-29T11:08:06+00:00", - "app/commerce-modules/customer/page.mdx": "2024-09-30T08:43:53.160Z", + "app/commerce-modules/customer/customer-accounts/page.mdx": "2024-10-08T12:20:44.769Z", + "app/commerce-modules/customer/examples/page.mdx": "2024-10-08T15:05:59.722Z", + "app/commerce-modules/customer/page.mdx": "2024-10-08T15:03:12.597Z", "app/commerce-modules/fulfillment/_events/_events-table/page.mdx": "2024-07-03T19:27:13+03:00", "app/commerce-modules/fulfillment/_events/page.mdx": "2024-07-03T19:27:13+03:00", "app/commerce-modules/fulfillment/concepts/page.mdx": "2024-06-19T13:02:16+00:00", - "app/commerce-modules/fulfillment/fulfillment-provider/page.mdx": "2024-07-01T10:21:19+03:00", - "app/commerce-modules/fulfillment/item-fulfillment/page.mdx": "2024-06-26T07:55:59+00:00", + "app/commerce-modules/fulfillment/fulfillment-provider/page.mdx": "2024-10-08T14:34:16.019Z", + "app/commerce-modules/fulfillment/item-fulfillment/page.mdx": "2024-10-08T14:38:15.496Z", "app/commerce-modules/fulfillment/module-options/page.mdx": "2024-09-30T08:43:53.160Z", - "app/commerce-modules/fulfillment/relations-to-other-modules/page.mdx": "2024-05-29T11:08:06+00:00", - "app/commerce-modules/fulfillment/shipping-option/page.mdx": "2024-06-26T07:55:59+00:00", - "app/commerce-modules/fulfillment/page.mdx": "2024-09-30T08:43:53.160Z", + "app/commerce-modules/fulfillment/shipping-option/page.mdx": "2024-10-08T14:36:02.660Z", + "app/commerce-modules/fulfillment/page.mdx": "2024-10-08T15:03:27.436Z", "app/commerce-modules/inventory/_events/_events-table/page.mdx": "2024-07-03T19:27:13+03:00", "app/commerce-modules/inventory/_events/page.mdx": "2024-07-03T19:27:13+03:00", - "app/commerce-modules/inventory/concepts/page.mdx": "2024-06-26T07:55:59+00:00", - "app/commerce-modules/inventory/examples/page.mdx": "2024-09-30T08:43:53.161Z", - "app/commerce-modules/inventory/inventory-in-flows/page.mdx": "2024-06-26T07:55:59+00:00", - "app/commerce-modules/inventory/relations-to-other-modules/page.mdx": "2024-06-26T07:55:59+00:00", - "app/commerce-modules/inventory/page.mdx": "2024-09-30T08:43:53.161Z", + "app/commerce-modules/inventory/concepts/page.mdx": "2024-10-08T15:11:27.634Z", + "app/commerce-modules/inventory/examples/page.mdx": "2024-10-08T15:05:30.943Z", + "app/commerce-modules/inventory/inventory-in-flows/page.mdx": "2024-10-08T15:14:07.327Z", + "app/commerce-modules/inventory/page.mdx": "2024-10-08T15:02:50.635Z", "app/commerce-modules/order/_events/_events-table/page.mdx": "2024-07-03T19:27:13+03:00", "app/commerce-modules/order/_events/page.mdx": "2024-07-03T19:27:13+03:00", "app/commerce-modules/order/claim/page.mdx": "2024-07-09T18:14:30+03:00", @@ -141,7 +137,7 @@ export const generatedEditDates = { "app/nextjs-starter/page.mdx": "2024-07-01T10:21:19+03:00", "app/recipes/b2b/page.mdx": "2024-10-03T13:07:44.153Z", "app/recipes/commerce-automation/page.mdx": "2024-10-03T13:07:44.147Z", - "app/recipes/digital-products/examples/standard/page.mdx": "2024-10-04T09:44:55.176Z", + "app/recipes/digital-products/examples/standard/page.mdx": "2024-10-04T09:44:55.176Z", "app/recipes/digital-products/page.mdx": "2024-10-03T13:07:44.147Z", "app/recipes/ecommerce/page.mdx": "2024-06-09T15:18:43+02:00", "app/recipes/integrate-ecommerce-stack/page.mdx": "2024-10-03T13:07:44.146Z", @@ -2225,5 +2221,8 @@ export const generatedEditDates = { "references/user/interfaces/user.MessageAggregatorFormat/page.mdx": "2024-10-03T00:12:20.662Z", "app/troubleshooting/dist-imports/page.mdx": "2024-10-03T09:19:37.639Z", "app/commerce-modules/auth/reset-password/page.mdx": "2024-09-25T09:36:26.592Z", - "app/storefront-development/customers/reset-password/page.mdx": "2024-09-25T10:21:46.647Z" + "app/storefront-development/customers/reset-password/page.mdx": "2024-09-25T10:21:46.647Z", + "app/commerce-modules/customer/extend/page.mdx": "2024-10-08T14:18:55.407Z", + "app/commerce-modules/fulfillment/links-to-other-modules/page.mdx": "2024-10-08T14:58:24.935Z", + "app/commerce-modules/inventory/links-to-other-modules/page.mdx": "2024-10-08T15:18:30.109Z" } \ No newline at end of file diff --git a/www/apps/resources/generated/files-map.mjs b/www/apps/resources/generated/files-map.mjs index e76c8a846f..32c6907195 100644 --- a/www/apps/resources/generated/files-map.mjs +++ b/www/apps/resources/generated/files-map.mjs @@ -175,10 +175,6 @@ export const filesMap = [ "filePath": "/www/apps/resources/app/commerce-modules/currency/page.mdx", "pathname": "/commerce-modules/currency" }, - { - "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/customer-accounts/page.mdx", "pathname": "/commerce-modules/customer/customer-accounts" @@ -188,12 +184,12 @@ export const filesMap = [ "pathname": "/commerce-modules/customer/examples" }, { - "filePath": "/www/apps/resources/app/commerce-modules/customer/page.mdx", - "pathname": "/commerce-modules/customer" + "filePath": "/www/apps/resources/app/commerce-modules/customer/extend/page.mdx", + "pathname": "/commerce-modules/customer/extend" }, { - "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/customer/page.mdx", + "pathname": "/commerce-modules/customer" }, { "filePath": "/www/apps/resources/app/commerce-modules/fulfillment/concepts/page.mdx", @@ -207,6 +203,10 @@ export const filesMap = [ "filePath": "/www/apps/resources/app/commerce-modules/fulfillment/item-fulfillment/page.mdx", "pathname": "/commerce-modules/fulfillment/item-fulfillment" }, + { + "filePath": "/www/apps/resources/app/commerce-modules/fulfillment/links-to-other-modules/page.mdx", + "pathname": "/commerce-modules/fulfillment/links-to-other-modules" + }, { "filePath": "/www/apps/resources/app/commerce-modules/fulfillment/module-options/page.mdx", "pathname": "/commerce-modules/fulfillment/module-options" @@ -215,10 +215,6 @@ export const filesMap = [ "filePath": "/www/apps/resources/app/commerce-modules/fulfillment/page.mdx", "pathname": "/commerce-modules/fulfillment" }, - { - "filePath": "/www/apps/resources/app/commerce-modules/fulfillment/relations-to-other-modules/page.mdx", - "pathname": "/commerce-modules/fulfillment/relations-to-other-modules" - }, { "filePath": "/www/apps/resources/app/commerce-modules/fulfillment/shipping-option/page.mdx", "pathname": "/commerce-modules/fulfillment/shipping-option" @@ -236,12 +232,12 @@ export const filesMap = [ "pathname": "/commerce-modules/inventory/inventory-in-flows" }, { - "filePath": "/www/apps/resources/app/commerce-modules/inventory/page.mdx", - "pathname": "/commerce-modules/inventory" + "filePath": "/www/apps/resources/app/commerce-modules/inventory/links-to-other-modules/page.mdx", + "pathname": "/commerce-modules/inventory/links-to-other-modules" }, { - "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/inventory/page.mdx", + "pathname": "/commerce-modules/inventory" }, { "filePath": "/www/apps/resources/app/commerce-modules/order/claim/page.mdx", diff --git a/www/apps/resources/generated/sidebar.mjs b/www/apps/resources/generated/sidebar.mjs index 57a79aabef..fb93aaab9a 100644 --- a/www/apps/resources/generated/sidebar.mjs +++ b/www/apps/resources/generated/sidebar.mjs @@ -1115,22 +1115,6 @@ export const generatedSidebar = [ "title": "Examples", "children": [] }, - { - "loaded": true, - "isPathHref": true, - "type": "sub-category", - "title": "Concepts", - "children": [ - { - "loaded": true, - "isPathHref": true, - "type": "link", - "path": "/commerce-modules/currency/relations-to-other-modules", - "title": "Relation to Modules", - "children": [] - } - ] - }, { "loaded": true, "isPathHref": true, @@ -1236,6 +1220,14 @@ export const generatedSidebar = [ "title": "Examples", "children": [] }, + { + "loaded": true, + "isPathHref": true, + "type": "link", + "path": "/commerce-modules/customer/extend", + "title": "Extend Module", + "children": [] + }, { "loaded": true, "isPathHref": true, @@ -1249,14 +1241,6 @@ export const generatedSidebar = [ "path": "/commerce-modules/customer/customer-accounts", "title": "Customer Accounts", "children": [] - }, - { - "loaded": true, - "isPathHref": true, - "type": "link", - "path": "/commerce-modules/customer/relations-to-other-modules", - "title": "Relations to Other Modules", - "children": [] } ] }, @@ -1599,8 +1583,8 @@ export const generatedSidebar = [ "loaded": true, "isPathHref": true, "type": "link", - "path": "/commerce-modules/fulfillment/relations-to-other-modules", - "title": "Relations to Other Modules", + "path": "/commerce-modules/fulfillment/links-to-other-modules", + "title": "Links to Other Modules", "children": [] } ] @@ -2337,8 +2321,8 @@ export const generatedSidebar = [ "loaded": true, "isPathHref": true, "type": "link", - "path": "/commerce-modules/inventory/relations-to-other-modules", - "title": "Relation to Modules", + "path": "/commerce-modules/inventory/links-to-other-modules", + "title": "Links to Modules", "children": [] } ] diff --git a/www/apps/resources/next.config.mjs b/www/apps/resources/next.config.mjs index a20f00859d..96eda38506 100644 --- a/www/apps/resources/next.config.mjs +++ b/www/apps/resources/next.config.mjs @@ -42,6 +42,20 @@ const nextConfig = { transpilePackages: ["docs-ui"], basePath: process.env.NEXT_PUBLIC_BASE_PATH || "/v2/resources", + async redirects() { + return [ + { + source: "/commerce-modules/fulfillment/relations-to-other-modules", + destination: "/commerce-modules/fulfillment/links-to-other-modules", + permanent: true, + }, + { + source: "/commerce-modules/inventory/relations-to-other-modules", + destination: "/commerce-modules/inventory/links-to-other-modules", + permanent: true, + }, + ] + }, // Redirects shouldn't be necessary anymore since we have remark / rehype // plugins that fix links. But leaving this here in case we need it again. // async redirects() { diff --git a/www/apps/resources/sidebar.mjs b/www/apps/resources/sidebar.mjs index 62e85e6352..d60f37c04c 100644 --- a/www/apps/resources/sidebar.mjs +++ b/www/apps/resources/sidebar.mjs @@ -301,17 +301,6 @@ export const sidebar = sidebarAttachHrefCommonOptions([ path: "/commerce-modules/currency/examples", title: "Examples", }, - { - type: "sub-category", - title: "Concepts", - children: [ - { - type: "link", - path: "/commerce-modules/currency/relations-to-other-modules", - title: "Relation to Modules", - }, - ], - }, { type: "sub-category", title: "References", @@ -364,6 +353,11 @@ export const sidebar = sidebarAttachHrefCommonOptions([ path: "/commerce-modules/customer/examples", title: "Examples", }, + { + type: "link", + path: "/commerce-modules/customer/extend", + title: "Extend Module", + }, { type: "sub-category", title: "Concepts", @@ -373,11 +367,6 @@ export const sidebar = sidebarAttachHrefCommonOptions([ path: "/commerce-modules/customer/customer-accounts", title: "Customer Accounts", }, - { - type: "link", - path: "/commerce-modules/customer/relations-to-other-modules", - title: "Relations to Other Modules", - }, ], }, { @@ -458,8 +447,8 @@ export const sidebar = sidebarAttachHrefCommonOptions([ }, { type: "link", - path: "/commerce-modules/fulfillment/relations-to-other-modules", - title: "Relations to Other Modules", + path: "/commerce-modules/fulfillment/links-to-other-modules", + title: "Links to Other Modules", }, ], }, @@ -544,8 +533,8 @@ export const sidebar = sidebarAttachHrefCommonOptions([ }, { type: "link", - path: "/commerce-modules/inventory/relations-to-other-modules", - title: "Relation to Modules", + path: "/commerce-modules/inventory/links-to-other-modules", + title: "Links to Modules", }, ], }, @@ -2157,8 +2146,8 @@ export const sidebar = sidebarAttachHrefCommonOptions([ { type: "link", path: "/troubleshooting/dist-imports", - title: "Importing from /dist" - } + title: "Importing from /dist", + }, ], }, {