diff --git a/www/apps/book/public/llms-full.txt b/www/apps/book/public/llms-full.txt index c2e974a0f9..32e2df8996 100644 --- a/www/apps/book/public/llms-full.txt +++ b/www/apps/book/public/llms-full.txt @@ -60,7 +60,7 @@ cd .medusa/server && npm install cp ../../.env .env.production ``` -When `NODE_ENV=production`, the Medusa application loads the environment variables from `.env.production`. Learn more about environment variables in [this guide](undefined/learn/fundamentals/environment-variables). +When `NODE_ENV=production`, the Medusa application loads the environment variables from `.env.production`. Learn more about environment variables in [this guide](https://docs.medusajs.com/learn/fundamentals/environment-variables/index.html.md). 3. Set `NODE_ENV` to `production` in the system environment variable: @@ -104,9 +104,7 @@ Make sure to remove the `projectConfig.cookieOptions` configuration once you're ## Deploying Production Build -The next chapter covers how you generally deploy the production build. - -You can also refer to the [deployment how-to guides](https://docs.medusajs.com/resources/deployment/index.html.md) for platform-specific how-to guides. +The next chapter covers how to deploy the production build. # Medusa Application Configuration @@ -148,7 +146,7 @@ The `defineConfig` utility accepts an object having the following properties: ### Using Environment Variables -Notice that you use the `loadEnv` utility to load environment variables. Learn more about it in the [Environment Variables chapter](undefined/learn/fundamentals/environment-variables). +Notice that you use the `loadEnv` utility to load environment variables. Learn more about it in the [Environment Variables chapter](https://docs.medusajs.com/learn/fundamentals/environment-variables/index.html.md). By using this utility, you can use environment variables as the values of your configurations. It's highly recommended that you use environment variables for secret values, such as API keys and database credentials, or for values that change based on the environment, such as the application's Cross Origin Resource Sharing (CORS) configurations. @@ -269,7 +267,7 @@ module.exports = defineConfig({ The `projectConfig.databaseName` configuration determines the name of the database to connect to. If the name is specified in the [databaseUrl](#databaseUrl) configuration, you don't have to use this configuration. -After setting the database credentials, you can create and setup the database using the [db:setup](undefined/resources/medusa-cli/commands/db#dbsetup) command of the Medusa CLI. +After setting the database credentials, you can create and setup the database using the [db:setup](https://docs.medusajs.com/resources/medusa-cli/commands/db#dbsetup/index.html.md) command of the Medusa CLI. #### Example @@ -302,7 +300,7 @@ Where: You can learn more about the connection URL format in [PostgreSQL’s documentation](https://www.postgresql.org/docs/current/libpq-connect.html). -After setting the database URL, you can create and setup the database using the [db:setup](undefined/resources/medusa-cli/commands/db#dbsetup) command of the Medusa CLI. +After setting the database URL, you can create and setup the database using the [db:setup](https://docs.medusajs.com/resources/medusa-cli/commands/db#dbsetup/index.html.md) command of the Medusa CLI. #### Example @@ -580,7 +578,7 @@ For example, you can allow Google login for `customers`, and allow email/passwor `authMethodsPerActor` is a an object whose key is the actor type (for example, `user`), and the value is an array of supported auth provider IDs (for example, `emailpass`). -Learn more about actor types in the [Auth Identity and Actor Type documentation](undefined/resources/commerce-modules/auth/auth-identity-and-actor-types). +Learn more about actor types in the [Auth Identity and Actor Type documentation](https://docs.medusajs.com/resources/commerce-modules/auth/auth-identity-and-actor-types/index.html.md). For example: @@ -603,7 +601,7 @@ The above configurations allow admin users to login using email/password, and cu #### http.restrictedFields -The `projectConfig.http.restrictedFields` configuration specifies the fields that can't be selected in API routes (using the `fields` query parameter) unless they're allowed in the [request's Query configurations](undefined/learn/fundamentals/module-links/query#request-query-configurations). This is useful to restrict sensitive fields from being exposed in the API. +The `projectConfig.http.restrictedFields` configuration specifies the fields that can't be selected in API routes (using the `fields` query parameter) unless they're allowed in the [request's Query configurations](https://docs.medusajs.com/learn/fundamentals/module-links/query#request-query-configurations/index.html.md). This is useful to restrict sensitive fields from being exposed in the API. For example, you can restrict selecting customers in store API routes: @@ -651,7 +649,7 @@ The `projectConfig.redisPrefix` configuration defines a prefix on all keys store The value of this configuration is prepended to `sess:`. For example, if you set it to `medusa:`, then a key stored in Redis is prefixed by `medusa:sess`. -This configuration is not used for modules that also connect to Redis, such as the [Redis Cache Module](undefined/resources/infrastructure-modules/cache/redis). +This configuration is not used for modules that also connect to Redis, such as the [Redis Cache Module](https://docs.medusajs.com/resources/infrastructure-modules/cache/redis/index.html.md). #### Example @@ -669,7 +667,7 @@ module.exports = defineConfig({ The `projectConfig.redisUrl` configuration specifies the connection URL to Redis to store the Medusa server session. When specified, the Medusa server uses Redis to store the session data. Otherwie, the session data is stored in-memory. -This configuration is not used for modules that also connect to Redis, such as the [Redis Cache Module](undefined/resources/infrastructure-modules/cache/redis). You'll have to configure the Redis connection for those modules separately. +This configuration is not used for modules that also connect to Redis, such as the [Redis Cache Module](https://docs.medusajs.com/resources/infrastructure-modules/cache/redis/index.html.md). You'll have to configure the Redis connection for those modules separately. You must first have Redis installed. You can refer to [Redis's installation guide](https://redis.io/docs/getting-started/installation/). @@ -706,7 +704,7 @@ module.exports = defineConfig({ The `projectConfig.sessionOptions` configuration defines additional options to pass to [express-session](https://www.npmjs.com/package/express-session), which is used to store the Medusa server session. -This configuration is not used for modules that also connect to Redis, such as the [Redis Cache Module](undefined/resources/infrastructure-modules/cache/redis). +This configuration is not used for modules that also connect to Redis, such as the [Redis Cache Module](https://docs.medusajs.com/resources/infrastructure-modules/cache/redis/index.html.md). #### Example @@ -733,7 +731,7 @@ module.exports = defineConfig({ ### workerMode -The `projectConfig.workerMode` configuration specifies the worker mode of the Medusa application. You can learn more about it in the [Worker Mode chapter](undefined/learn/production/worker-mode). +The `projectConfig.workerMode` configuration specifies the worker mode of the Medusa application. You can learn more about it in the [Worker Mode chapter](https://docs.medusajs.com/learn/production/worker-mode/index.html.md). The value for this configuration can be one of the following: @@ -863,12 +861,12 @@ module.exports = defineConfig({ ## Module Configurations (`modules`) -The `modules` configuration allows you to register and configure the [modules](undefined/learn/fundamentals/modules) registered in the Medusa application. Medusa's commerce and Infrastructure Modules are configured by default. So, you only need to pass your custom modules, or override the default configurations of the existing modules. +The `modules` configuration allows you to register and configure the [modules](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md) registered in the Medusa application. Medusa's commerce and Infrastructure Modules are configured by default. So, you only need to pass your custom modules, or override the default configurations of the existing modules. `modules` is an array of objects for the modules to register. Each object has the following properties: 1. `resolve`: a string indicating the path to the module, or the module's NPM package name. For example, `./src/modules/my-module`. -2. `options`: (optional) an object indicating the [options to pass to the module](undefined/learn/fundamentals/modules/options). This object is specific to the module and its configurations. For example, your module may require an API key option, which you can pass in this object. +2. `options`: (optional) an object indicating the [options to pass to the module](https://docs.medusajs.com/learn/fundamentals/modules/options/index.html.md). This object is specific to the module and its configurations. For example, your module may require an API key option, which you can pass in this object. For modules that are part of a plugin, learn about registering them in the [Register Modules in Plugins](#register-modules-in-plugins) section. @@ -929,7 +927,7 @@ module.exports = defineConfig({ ## Plugin Configurations (`plugins`) -The `plugins` configuration allows you to register and configure the [plugins](undefined/learn/fundamentals/plugins) registered in the Medusa application. Plugins include re-usable Medusa customizations, such as modules, workflows, API routes, and more. +The `plugins` configuration allows you to register and configure the [plugins](https://docs.medusajs.com/learn/fundamentals/plugins/index.html.md) registered in the Medusa application. Plugins include re-usable Medusa customizations, such as modules, workflows, API routes, and more. Aside from installing the plugin with NPM, you must also register it in the `medusa.config.ts` file. @@ -938,7 +936,7 @@ The `plugins` configuration is an array of objects for the plugins to register. - A string, which is the name of the plugin's package as specified in the plugin's `package.json` file. This is useful if the plugin doesn't require any options. - An object having the following properties: - `resolve`: The name of the plugin's package as specified in the plugin's `package.json` file. - - `options`: An object that includes [options to be passed to the modules](undefined/learn/fundamentals/modules/options#pass-options-to-a-module-in-a-plugin) within the plugin. + - `options`: An object that includes [options to be passed to the modules](https://docs.medusajs.com/learn/fundamentals/modules/options#pass-options-to-a-module-in-a-plugin/index.html.md) within the plugin. ### Example @@ -1002,7 +1000,7 @@ module.exports = { The `featureFlags` configuration allows you to manage enabled beta features in the Medusa application. -Learn more in the [Feature Flags](undefined/learn/debugging-and-testing/feature-flags) chapter. +Learn more in the [Feature Flags](https://docs.medusajs.com/learn/debugging-and-testing/feature-flags/index.html.md) chapter. ### Example @@ -1020,9 +1018,9 @@ module.exports = defineConfig({ ## Custom Logger (`logger`) -The `logger` configuration allows you to override the default [Logger](undefined/learn/debugging-and-testing/logging) used in the Medusa application with your custom implementation. +The `logger` configuration allows you to override the default [Logger](https://docs.medusajs.com/learn/debugging-and-testing/logging/index.html.md) used in the Medusa application with your custom implementation. -Learn more about creating a custom logger in the [Override Logger](undefined/learn/debugging-and-testing/logging/custom-logger) chapter. +Learn more about creating a custom logger in the [Override Logger](https://docs.medusajs.com/learn/debugging-and-testing/logging/custom-logger/index.html.md) chapter. The `logger` configuration accepts an instance of a class that extends the `Logger` interface. @@ -1148,7 +1146,7 @@ module.exports = defineConfig({ }) ``` -Learn more about the `vite` configuration in the [Medusa configuration](undefined/learn/configurations/medusa-config) chapter. +Learn more about the `vite` configuration in the [Medusa configuration](https://docs.medusajs.com/learn/configurations/medusa-config/index.html.md) chapter. ### Step 3: Use TypeScript Aliases in Admin Customizations @@ -1199,21 +1197,21 @@ module.exports = defineConfig({ # Guide: Create Brand API Route -In the previous two chapters, you created a [Brand Module](undefined/learn/customization/custom-features/module) that added the concepts of brands to your application, then created a [workflow to create a brand](undefined/learn/customization/custom-features/workflow). In this chapter, you'll expose an API route that allows admin users to create a brand using the workflow from the previous chapter. +In the previous two chapters, you created a [Brand Module](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md) that added the concepts of brands to your application, then created a [workflow to create a brand](https://docs.medusajs.com/learn/customization/custom-features/workflow/index.html.md). In this chapter, you'll expose an API route that allows admin users to create a brand using the workflow from the previous chapter. An API Route is an endpoint that acts as an entry point for other clients to interact with your Medusa customizations, such as the admin dashboard, storefronts, or third-party systems. -The Medusa core application provides a set of [admin](undefined/api/admin) and [store](undefined/api/store) API routes out-of-the-box. You can also create custom API routes to expose your custom functionalities. +The Medusa core application provides a set of [admin](https://docs.medusajs.com/api/admin) and [store](https://docs.medusajs.com/api/store) API routes out-of-the-box. You can also create custom API routes to expose your custom functionalities. ### Prerequisites -- [createBrandWorkflow](undefined/learn/customization/custom-features/workflow) +- [createBrandWorkflow](https://docs.medusajs.com/learn/customization/custom-features/workflow/index.html.md) ## 1. Create the API Route You create an API route in a `route.{ts,js}` file under a sub-directory of the `src/api` directory. The file exports API Route handler functions for at least one HTTP method (`GET`, `POST`, `DELETE`, etc…). -Learn more about API routes [in this guide](undefined/learn/fundamentals/api-routes). +Learn more about API routes [in this guide](https://docs.medusajs.com/learn/fundamentals/api-routes/index.html.md). The route's path is the path of `route.{ts,js}` relative to `src/api`. So, to create the API route at `/admin/brands`, create the file `src/api/admin/brands/route.ts` with the following content: @@ -1247,7 +1245,7 @@ export const POST = async ( You export a route handler function with its name (`POST`) being the HTTP method of the API route you're exposing. -The function receives two parameters: a `MedusaRequest` object to access request details, and `MedusaResponse` object to return or manipulate the response. The `MedusaRequest` object's `scope` property is the [Medusa container](undefined/learn/fundamentals/medusa-container) that holds Framework tools and custom and core modules' services. +The function receives two parameters: a `MedusaRequest` object to access request details, and `MedusaResponse` object to return or manipulate the response. The `MedusaRequest` object's `scope` property is the [Medusa container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md) that holds Framework tools and custom and core modules' services. `MedusaRequest` accepts the request body's type as a type argument. @@ -1263,7 +1261,7 @@ The API route you created accepts the brand's name in the request body. So, you' Medusa uses [Zod](https://zod.dev/) to create validation schemas. These schemas are then used to validate incoming request bodies or query parameters. -Learn more about API route validation in [this chapter](undefined/learn/fundamentals/api-routes/validation). +Learn more about API route validation in [this chapter](https://docs.medusajs.com/learn/fundamentals/api-routes/validation/index.html.md). You create a validation schema in a TypeScript or JavaScript file under a sub-directory of the `src/api` directory. So, create the file `src/api/admin/brands/validators.ts` with the following content: @@ -1297,7 +1295,7 @@ type PostAdminCreateBrandType = z.infer A middleware is a function executed before the route handler when a request is sent to an API Route. It's useful to guard API routes, parse custom request body types, and apply validation on an API route. -Learn more about middlewares in [this chapter](undefined/learn/fundamentals/api-routes/middlewares). +Learn more about middlewares in [this chapter](https://docs.medusajs.com/learn/fundamentals/api-routes/middlewares/index.html.md). Medusa provides a `validateAndTransformBody` middleware that accepts a Zod validation schema and returns a response error if a request is sent with body parameters that don't satisfy the validation schema. @@ -1360,7 +1358,7 @@ curl -X POST 'http://localhost:9000/auth/user/emailpass' \ Make sure to replace the email and password with your admin user's credentials. -Don't have an admin user? Refer to [this guide](undefined/learn/installation#create-medusa-admin-user). +Don't have an admin user? Refer to [this guide](https://docs.medusajs.com/learn/installation#create-medusa-admin-user/index.html.md). Then, send a `POST` request to `/admin/brands`, passing the token received from the previous request in the `Authorization` header: @@ -1400,7 +1398,7 @@ By following the previous example chapters, you implemented a custom feature tha ## Next Steps: Associate Brand with Product -Now that you have brands in your Medusa application, you want to associate a brand with a product, which is defined in the [Product Module](undefined/resources/commerce-modules/product). +Now that you have brands in your Medusa application, you want to associate a brand with a product, which is defined in the [Product Module](https://docs.medusajs.com/resources/commerce-modules/product/index.html.md). In the next chapters, you'll learn how to build associations between data models defined in different modules. @@ -1409,13 +1407,13 @@ In the next chapters, you'll learn how to build associations between data models In this chapter, you'll build a Brand Module that adds a `brand` table to the database and provides data-management features for it. -A module is a reusable package of functionalities related to a single domain or integration. Medusa comes with multiple pre-built modules for core commerce needs, such as the [Cart Module](undefined/resources/commerce-modules/cart) that holds the data models and business logic for cart operations. +A module is a reusable package of functionalities related to a single domain or integration. Medusa comes with multiple pre-built modules for core commerce needs, such as the [Cart Module](https://docs.medusajs.com/resources/commerce-modules/cart/index.html.md) that holds the data models and business logic for cart operations. In a module, you create data models and business logic to manage them. In the next chapters, you'll see how you use the module to build commerce features. ![Diagram showcasing an overview of the Brand Module](https://res.cloudinary.com/dza7lstvk/image/upload/v1746546820/Medusa%20Resources/brand-module_pg86gm.jpg) -Learn more about modules in [this chapter](undefined/learn/fundamentals/modules). +Learn more about modules in [this chapter](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md). ## 1. Create Module Directory @@ -1429,7 +1427,7 @@ Modules are created in a sub-directory of `src/modules`. So, start by creating t A data model represents a table in the database. You create data models using Medusa's Data Model Language (DML). It simplifies defining a table's columns, relations, and indexes with straightforward methods and configurations. -Learn more about data models in [this chapter](undefined/learn/fundamentals/modules#1-create-data-model). +Learn more about data models in [this chapter](https://docs.medusajs.com/learn/fundamentals/modules#1-create-data-model/index.html.md). You create a data model in a TypeScript or JavaScript file under the `models` directory of a module. So, to create a data model that represents a new `brand` table in the database, create the file `src/modules/brand/models/brand.ts` with the following content: @@ -1451,7 +1449,7 @@ You define the data model using the `define` method of the DML. It accepts two p 1. The first one is the name of the data model's table in the database. Use snake-case names. 2. The second is an object, which is the data model's schema. -Learn about other property types in [this chapter](undefined/learn/fundamentals/data-models/properties). +Learn about other property types in [this chapter](https://docs.medusajs.com/learn/fundamentals/data-models/properties/index.html.md). *** @@ -1461,7 +1459,7 @@ You perform database operations on your data models in a service, which is a cla In this step, you'll create the Brand Module's service that provides methods to manage the `Brand` data model. In the next chapters, you'll use this service when exposing custom features that involve managing brands. -Learn more about services in [this chapter](undefined/learn/fundamentals/modules#2-create-service). +Learn more about services in [this chapter](https://docs.medusajs.com/learn/fundamentals/modules#2-create-service/index.html.md). You define a service in a `service.ts` or `service.js` file at the root of your module's directory. So, create the file `src/modules/brand/service.ts` with the following content: @@ -1484,9 +1482,9 @@ The `BrandModuleService` extends a class returned by `MedusaService` from the Mo The `MedusaService` function receives an object of the module's data models as a parameter, and generates methods to manage those data models. So, the `BrandModuleService` now has methods like `createBrands` and `retrieveBrand` to manage the `Brand` data model. -You'll use these methods in the [next chapter](undefined/learn/customization/custom-features/workflow). +You'll use these methods in the [next chapter](https://docs.medusajs.com/learn/customization/custom-features/workflow/index.html.md). -Find a reference of all generated methods in [this guide](undefined/resources/service-factory-reference). +Find a reference of all generated methods in [this guide](https://docs.medusajs.com/resources/service-factory-reference/index.html.md). *** @@ -1535,7 +1533,7 @@ module.exports = defineConfig({ }) ``` -The Brand Module is now added to your Medusa application. You'll start using it in the [next chapter](undefined/learn/customization/custom-features/workflow). +The Brand Module is now added to your Medusa application. You'll start using it in the [next chapter](https://docs.medusajs.com/learn/customization/custom-features/workflow/index.html.md). *** @@ -1543,9 +1541,9 @@ The Brand Module is now added to your Medusa application. You'll start using it A migration is a TypeScript or JavaScript file that defines database changes made by a module. Migrations ensure that your module is re-usable and removes friction when working in a team, making it easy to reflect changes across team members' databases. -Learn more about migrations in [this chapter](undefined/learn/fundamentals/modules#5-generate-migrations). +Learn more about migrations in [this chapter](https://docs.medusajs.com/learn/fundamentals/modules#5-generate-migrations/index.html.md). -[Medusa's CLI tool](undefined/resources/medusa-cli) allows you to generate migration files for your module, then run those migrations to reflect the changes in the database. So, run the following commands in your Medusa application's directory: +[Medusa's CLI tool](https://docs.medusajs.com/resources/medusa-cli/index.html.md) allows you to generate migration files for your module, then run those migrations to reflect the changes in the database. So, run the following commands in your Medusa application's directory: ```bash npx medusa db:generate brand @@ -1569,11 +1567,11 @@ In the upcoming chapters, you'll follow step-by-step guides to build custom feat By following these guides, you'll add brands to the Medusa application that you can associate with products. -To build a custom feature in Medusa, you need three main [Framework](undefined/learn/fundamentals/framework) tools: +To build a custom feature in Medusa, you need three main [Framework](https://docs.medusajs.com/learn/fundamentals/framework/index.html.md) tools: -- [Module](undefined/learn/fundamentals/modules): a package with commerce logic for a single domain. It defines new tables to add to the database, and a class of methods to manage these tables. -- [Workflow](undefined/learn/fundamentals/workflows): a tool to perform an operation comprising multiple steps with built-in rollback and retry mechanisms. -- [API route](undefined/learn/fundamentals/api-routes): a REST endpoint that exposes commerce features to clients, such as the admin dashboard or a storefront. The API route executes a workflow that implements the commerce feature using modules. +- [Module](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md): a package with commerce logic for a single domain. It defines new tables to add to the database, and a class of methods to manage these tables. +- [Workflow](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md): a tool to perform an operation comprising multiple steps with built-in rollback and retry mechanisms. +- [API route](https://docs.medusajs.com/learn/fundamentals/api-routes/index.html.md): a REST endpoint that exposes commerce features to clients, such as the admin dashboard or a storefront. The API route executes a workflow that implements the commerce feature using modules. ![Diagram showcasing the flow of a custom developed feature](https://res.cloudinary.com/dza7lstvk/image/upload/v1725867628/Medusa%20Book/custom-development_nofvp6.jpg) @@ -1590,17 +1588,17 @@ The next chapters will guide you to: # Guide: Create Brand Workflow -This chapter builds on the work from the [previous chapter](undefined/learn/customization/custom-features/module) where you created a Brand Module. +This chapter builds on the work from the [previous chapter](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md) where you created a Brand Module. After adding custom modules to your application, you build commerce features around them using workflows. A workflow is a series of queries and actions, called steps, that complete a task spanning across modules. You construct a workflow similar to a regular function, but it's a special function that allows you to define roll-back logic, retry configurations, and more advanced features. -The workflow you'll create in this chapter will use the Brand Module's service to implement the feature of creating a brand. In the [next chapter](undefined/learn/customization/custom-features/api-route), you'll expose an API route that allows admin users to create a brand, and you'll use this workflow in the route's implementation. +The workflow you'll create in this chapter will use the Brand Module's service to implement the feature of creating a brand. In the [next chapter](https://docs.medusajs.com/learn/customization/custom-features/api-route/index.html.md), you'll expose an API route that allows admin users to create a brand, and you'll use this workflow in the route's implementation. -Learn more about workflows in [this chapter](undefined/learn/fundamentals/workflows). +Learn more about workflows in [this chapter](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md). ### Prerequisites -- [Brand Module](undefined/learn/customization/custom-features/module) +- [Brand Module](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md) *** @@ -1642,11 +1640,11 @@ You create a `createBrandStep` using the `createStep` function. It accepts the s The step function receives two parameters: input passed to the step when it's invoked, and an object of general context and configurations. This object has a `container` property, which is the Medusa container. -The [Medusa container](undefined/learn/fundamentals/medusa-container) is a registry of Framework and commerce tools accessible in your customizations, such as a workflow's step. The Medusa application registers the services of core and custom modules in the container, allowing you to resolve and use them. +The [Medusa container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md) is a registry of Framework and commerce tools accessible in your customizations, such as a workflow's step. The Medusa application registers the services of core and custom modules in the container, allowing you to resolve and use them. So, In the step function, you use the Medusa container to resolve the Brand Module's service and use its generated `createBrands` method, which accepts an object of brands to create. -Learn more about the generated `create` method's usage in [this reference](undefined/resources/service-factory-reference/methods/create). +Learn more about the generated `create` method's usage in [this reference](https://docs.medusajs.com/resources/service-factory-reference/methods/create/index.html.md). A step must return an instance of `StepResponse`. Its first parameter is the data returned by the step, and the second is the data passed to the compensation function, which you'll learn about next. @@ -1654,7 +1652,7 @@ A step must return an instance of `StepResponse`. Its first parameter is the dat You define for each step a compensation function that's executed when an error occurs in the workflow. The compensation function defines the logic to roll-back the changes made by the step. This ensures your data remains consistent if an error occurs, which is especially useful when you integrate third-party services. -Learn more about the compensation function in [this chapter](undefined/learn/fundamentals/workflows/compensation-function). +Learn more about the compensation function in [this chapter](https://docs.medusajs.com/learn/fundamentals/workflows/compensation-function/index.html.md). To add a compensation function to the `createBrandStep`, pass it as a third parameter to `createStep`: @@ -1675,7 +1673,7 @@ The compensation function's first parameter is the brand's ID which you passed a In the compensation function, you resolve the Brand Module's service from the Medusa container, then use its generated `deleteBrands` method to delete the brand created by the step. This method accepts the ID of the brand to delete. -Learn more about the generated `delete` method's usage in [this reference](undefined/resources/service-factory-reference/methods/delete). +Learn more about the generated `delete` method's usage in [this reference](https://docs.medusajs.com/resources/service-factory-reference/methods/delete/index.html.md). So, if an error occurs during the workflow's execution, the brand that was created by the step is deleted to maintain data consistency. @@ -1728,12 +1726,12 @@ In the next chapter, you'll add an API route that allows admin users to create a # Customize Medusa Admin Dashboard -In the previous chapters, you've customized your Medusa application to [add brands](undefined/learn/customization/custom-features/module), [expose an API route to create brands](undefined/learn/customization/custom-features/api-route), and [linked brands to products](undefined/learn/customization/extend-features/define-link). +In the previous chapters, you've customized your Medusa application to [add brands](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md), [expose an API route to create brands](https://docs.medusajs.com/learn/customization/custom-features/api-route/index.html.md), and [linked brands to products](https://docs.medusajs.com/learn/customization/extend-features/define-link/index.html.md). After customizing and extending your application with new features, you may need to provide an interface for admin users to utilize these features. The Medusa Admin dashboard is extendable, allowing you to: -- Insert components, called [widgets](undefined/learn/fundamentals/admin/widgets), into existing pages. For example, you can add a widget to the product details page that shows the product's brand. -- Add new pages, called [UI Routes](undefined/learn/fundamentals/admin/ui-routes). For example, you can create a new page in the dashboard that lists all brands in the store. +- Insert components, called [widgets](https://docs.medusajs.com/learn/fundamentals/admin/widgets/index.html.md), into existing pages. For example, you can add a widget to the product details page that shows the product's brand. +- Add new pages, called [UI Routes](https://docs.medusajs.com/learn/fundamentals/admin/ui-routes/index.html.md). For example, you can create a new page in the dashboard that lists all brands in the store. Within these customizations, you can send requests to custom API routes, allowing admin users to view and manage custom resources on the dashboard. @@ -1749,15 +1747,15 @@ In the next chapters, you'll continue with the brands example to: # Create Brands UI Route in Admin -In this chapter, you'll add a UI route to the admin dashboard that shows all [brands](undefined/learn/customization/custom-features/module) in a new page. You'll retrieve the brands from the server and display them in a table with pagination. +In this chapter, you'll add a UI route to the admin dashboard that shows all [brands](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md) in a new page. You'll retrieve the brands from the server and display them in a table with pagination. ### Prerequisites -- [Brands Module](undefined/learn/customization/custom-features/module) +- [Brands Module](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md) ## 1. Get Brands API Route -In a [previous chapter](undefined/learn/customization/extend-features/query-linked-records), you learned how to add an API route that retrieves brands and their products using [Query](undefined/learn/fundamentals/module-links/query). You'll expand that API route to support pagination, so that on the admin dashboard you can show the brands in a paginated table. +In a [previous chapter](https://docs.medusajs.com/learn/customization/extend-features/query-linked-records/index.html.md), you learned how to add an API route that retrieves brands and their products using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md). You'll expand that API route to support pagination, so that on the admin dashboard you can show the brands in a paginated table. Replace or create the `GET` API route at `src/api/admin/brands/route.ts` with the following: @@ -1807,7 +1805,7 @@ When you pass pagination configurations to the `graph` method, the returned obje You return in the response the retrieved brands and the pagination configurations. -Learn more about pagination with Query in [this chapter](undefined/learn/fundamentals/module-links/query#apply-pagination). +Learn more about pagination with Query in [this chapter](https://docs.medusajs.com/learn/fundamentals/module-links/query#apply-pagination/index.html.md). *** @@ -1858,22 +1856,22 @@ You apply the `validateAndTransformQuery` middleware on the `GET /admin/brands` - `fields`: A comma-separated string indicating the fields to retrieve. - `limit`: The maximum number of items to retrieve. - `offset`: The number of items to skip before retrieving the returned items. - - `order`: The name of the field to sort the items by. Learn more about sorting in [the API reference](undefined/api/admin#sort-order) + - `order`: The name of the field to sort the items by. Learn more about sorting in [the API reference](https://docs.medusajs.com/api/admin#sort-order) - An object of Query configurations having the following properties: - `defaults`: An array of default fields and relations to retrieve. - `isList`: Whether the API route returns a list of items. By applying the above middleware, you can pass pagination configurations to `GET /admin/brands`, which will return a paginated list of brands. You'll see how it works when you create the UI route. -Learn more about using the `validateAndTransformQuery` middleware to configure Query in [this chapter](undefined/learn/fundamentals/module-links/query#request-query-configurations). +Learn more about using the `validateAndTransformQuery` middleware to configure Query in [this chapter](https://docs.medusajs.com/learn/fundamentals/module-links/query#request-query-configurations/index.html.md). *** ## 3. Initialize JS SDK -In your custom UI route, you'll retrieve the brands by sending a request to the Medusa server. Medusa has a [JS SDK](undefined/resources/js-sdk) that simplifies sending requests to the core API route. +In your custom UI route, you'll retrieve the brands by sending a request to the Medusa server. Medusa has a [JS SDK](https://docs.medusajs.com/resources/js-sdk/index.html.md) that simplifies sending requests to the core API route. -If you didn't follow the [previous chapter](undefined/learn/customization/customize-admin/widget), create the file `src/admin/lib/sdk.ts` with the following content: +If you didn't follow the [previous chapter](https://docs.medusajs.com/learn/customization/customize-admin/widget/index.html.md), create the file `src/admin/lib/sdk.ts` with the following content: ![The directory structure of the Medusa application after adding the file](https://res.cloudinary.com/dza7lstvk/image/upload/v1733414606/Medusa%20Book/brands-admin-dir-overview-1_jleg0t.jpg) @@ -1895,11 +1893,11 @@ You initialize the SDK passing it the following options: - `debug`: Whether to enable logging debug messages. This should only be enabled in development. - `auth.type`: The authentication method used in the client application, which is `session` in the Medusa Admin dashboard. -Notice that you use `import.meta.env` to access environment variables in your customizations because the Medusa Admin is built on top of Vite. Learn more in [this chapter](undefined/learn/fundamentals/admin/environment-variables). +Notice that you use `import.meta.env` to access environment variables in your customizations because the Medusa Admin is built on top of Vite. Learn more in [this chapter](https://docs.medusajs.com/learn/fundamentals/admin/environment-variables/index.html.md). You can now use the SDK to send requests to the Medusa server. -Learn more about the JS SDK and its options in [this reference](undefined/resources/js-sdk). +Learn more about the JS SDK and its options in [this reference](https://docs.medusajs.com/resources/js-sdk/index.html.md). *** @@ -1907,7 +1905,7 @@ Learn more about the JS SDK and its options in [this reference](undefined/resour You'll now add the UI route that shows the paginated list of brands. A UI route is a React component created in a `page.tsx` file under a sub-directory of `src/admin/routes`. The file's path relative to src/admin/routes determines its path in the dashboard. -Learn more about UI routes in [this chapter](undefined/learn/fundamentals/admin/ui-routes). +Learn more about UI routes in [this chapter](https://docs.medusajs.com/learn/fundamentals/admin/ui-routes/index.html.md). So, to add the UI route at the `localhost:9000/app/brands` path, create the file `src/admin/routes/brands/page.tsx` with the following content: @@ -1943,7 +1941,7 @@ export default BrandsPage A route's file must export the React component that will be rendered in the new page. It must be the default export of the file. You can also export configurations that add a link in the sidebar for the UI route. You create these configurations using `defineRouteConfig` from the Admin Extension SDK. -So far, you only show a container. In admin customizations, use components from the [Medusa UI package](undefined/ui) to maintain a consistent user interface and design in the dashboard. +So far, you only show a container. In admin customizations, use components from the [Medusa UI package](https://docs.medusajs.com/ui/index.html.md) to maintain a consistent user interface and design in the dashboard. ### Retrieve Brands From API Route @@ -1966,7 +1964,7 @@ type BrandsResponse = { You define the type for a brand, and the type of expected response from the `GET /admin/brands` API route. -To display the brands, you'll use Medusa UI's [DataTable](undefined/ui/components/data-table) component. So, add the following imports in `src/admin/routes/brands/page.tsx`: +To display the brands, you'll use Medusa UI's [DataTable](https://docs.medusajs.com/ui/components/data-table/index.html.md) component. So, add the following imports in `src/admin/routes/brands/page.tsx`: ```tsx title="src/admin/routes/brands/page.tsx" import { @@ -2121,15 +2119,15 @@ In the next chapters, you'll learn about the concepts that facilitate integratin # Guide: Add Product's Brand Widget in Admin -In this chapter, you'll customize the product details page of the Medusa Admin dashboard to show the product's [brand](undefined/learn/customization/custom-features/module). You'll create a widget that is injected into a pre-defined zone in the page, and in the widget you'll retrieve the product's brand from the server and display it. +In this chapter, you'll customize the product details page of the Medusa Admin dashboard to show the product's [brand](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md). You'll create a widget that is injected into a pre-defined zone in the page, and in the widget you'll retrieve the product's brand from the server and display it. ### Prerequisites -- [Brands linked to products](undefined/learn/customization/extend-features/define-link) +- [Brands linked to products](https://docs.medusajs.com/learn/customization/extend-features/define-link/index.html.md) ## 1. Initialize JS SDK -In your custom widget, you'll retrieve the product's brand by sending a request to the Medusa server. Medusa has a [JS SDK](undefined/resources/js-sdk) that simplifies sending requests to the server's API routes. +In your custom widget, you'll retrieve the product's brand by sending a request to the Medusa server. Medusa has a [JS SDK](https://docs.medusajs.com/resources/js-sdk/index.html.md) that simplifies sending requests to the server's API routes. So, you'll start by configuring the JS SDK. Create the file `src/admin/lib/sdk.ts` with the following content: @@ -2153,11 +2151,11 @@ You initialize the SDK passing it the following options: - `debug`: Whether to enable logging debug messages. This should only be enabled in development. - `auth.type`: The authentication method used in the client application, which is `session` in the Medusa Admin dashboard. -Notice that you use `import.meta.env` to access environment variables in your customizations because the Medusa Admin is built on top of Vite. Learn more in [this chapter](undefined/learn/fundamentals/admin/environment-variables). +Notice that you use `import.meta.env` to access environment variables in your customizations because the Medusa Admin is built on top of Vite. Learn more in [this chapter](https://docs.medusajs.com/learn/fundamentals/admin/environment-variables/index.html.md). You can now use the SDK to send requests to the Medusa server. -Learn more about the JS SDK and its options in [this reference](undefined/resources/js-sdk). +Learn more about the JS SDK and its options in [this reference](https://docs.medusajs.com/resources/js-sdk/index.html.md). *** @@ -2165,7 +2163,7 @@ Learn more about the JS SDK and its options in [this reference](undefined/resour You'll now add a widget to the product-details page. A widget is a React component that's injected into pre-defined zones in the Medusa Admin dashboard. It's created in a `.tsx` file under the `src/admin/widgets` directory. -Learn more about widgets in [this documentation](undefined/learn/fundamentals/admin/widgets). +Learn more about widgets in [this documentation](https://docs.medusajs.com/learn/fundamentals/admin/widgets/index.html.md). To create a widget that shows a product's brand in its details page, create the file `src/admin/widgets/product-brand.tsx` with the following content: @@ -2238,11 +2236,11 @@ A widget's file must export: Since the widget is injected at the top of the product details page, the widget receives the product's details as a parameter. -In the widget, you use [Tanstack (React) Query](https://tanstack.com/query/latest) to query the Medusa server. Tanstack Query provides features like asynchronous state management and optimized caching. In the `queryFn` function that executes the query, you use the JS SDK to send a request to the [Get Product API Route](undefined/api/admin#products_getproductsid), passing `+brand.*` in the `fields` query parameter to retrieve the product's brand. +In the widget, you use [Tanstack (React) Query](https://tanstack.com/query/latest) to query the Medusa server. Tanstack Query provides features like asynchronous state management and optimized caching. In the `queryFn` function that executes the query, you use the JS SDK to send a request to the [Get Product API Route](https://docs.medusajs.com/api/admin#products_getproductsid), passing `+brand.*` in the `fields` query parameter to retrieve the product's brand. Do not install Tanstack Query as that will cause unexpected errors in your development. If you prefer installing it for better auto-completion in your code editor, make sure to install `v5.64.2` as a development dependency. -You then render a section that shows the brand's name. In admin customizations, use components from the [Medusa UI package](undefined/ui) to maintain a consistent user interface and design in the dashboard. +You then render a section that shows the brand's name. In admin customizations, use components from the [Medusa UI package](https://docs.medusajs.com/ui/index.html.md) to maintain a consistent user interface and design in the dashboard. *** @@ -2264,7 +2262,7 @@ Then, open the admin dashboard at `http://localhost:9000/app`. After you log in, When building your widget, you may need more complicated components. For example, you may add a form to the above widget to set the product's brand. -The [Admin Components guides](undefined/resources/admin-components) show you how to build and use common components in the Medusa Admin, such as forms, tables, JSON data viewer, and more. The components in the guides also follow the Medusa Admin's design convention. +The [Admin Components guides](https://docs.medusajs.com/resources/admin-components/index.html.md) show you how to build and use common components in the Medusa Admin, such as forms, tables, JSON data viewer, and more. The components in the guides also follow the Medusa Admin's design convention. *** @@ -2275,19 +2273,19 @@ In the next chapter, you'll add a UI route that displays the list of brands in y # Guide: Define Module Link Between Brand and Product -In this chapter, you'll learn how to define a module link between a brand defined in the [custom Brand Module](undefined/learn/customization/custom-features/module), and a product defined in the [Product Module](undefined/resources/commerce-modules/product) that's available in your Medusa application out-of-the-box. +In this chapter, you'll learn how to define a module link between a brand defined in the [custom Brand Module](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md), and a product defined in the [Product Module](https://docs.medusajs.com/resources/commerce-modules/product/index.html.md) that's available in your Medusa application out-of-the-box. -Modules are [isolated](undefined/learn/fundamentals/modules/isolation) from other resources, ensuring that they're integrated into the Medusa application without side effects. However, you may need to associate data models of different modules, or you're trying to extend data models from Commerce Modules with custom properties. To do that, you define module links. +Modules are [isolated](https://docs.medusajs.com/learn/fundamentals/modules/isolation/index.html.md) from other resources, ensuring that they're integrated into the Medusa application without side effects. However, you may need to associate data models of different modules, or you're trying to extend data models from Commerce Modules with custom properties. To do that, you define module links. A module link forms an association between two data models of different modules while maintaining module isolation. You can then manage and query linked records of the data models using Medusa's Modules SDK. In this chapter, you'll define a module link between the `Brand` data model of the Brand Module, and the `Product` data model of the Product Module. In later chapters, you'll manage and retrieve linked product and brand records. -Learn more about module links in [this chapters](undefined/learn/fundamentals/module-links). +Learn more about module links in [this chapters](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md). ### Prerequisites -- [Brand Module having a Brand data model](undefined/learn/customization/custom-features/module) +- [Brand Module having a Brand data model](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md) ## 1. Define Link @@ -2345,21 +2343,21 @@ In the next chapter, you'll extend Medusa's workflow and API route that create a # Guide: Extend Create Product Flow -After linking the [custom Brand data model](undefined/learn/customization/custom-features/module) and Medusa's [Product Module](undefined/resources/commerce-modules/product) in the [previous chapter](undefined/learn/customization/extend-features/define-link), you'll extend the create product workflow and API route to allow associating a brand with a product. +After linking the [custom Brand data model](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md) and Medusa's [Product Module](https://docs.medusajs.com/resources/commerce-modules/product/index.html.md) in the [previous chapter](https://docs.medusajs.com/learn/customization/extend-features/define-link/index.html.md), you'll extend the create product workflow and API route to allow associating a brand with a product. -Some API routes, including the [Create Product API route](undefined/api/admin#products_postproducts), accept an `additional_data` request body parameter. This parameter can hold custom data that's passed to the [hooks](undefined/learn/fundamentals/workflows/workflow-hooks) of the workflow executed in the API route, allowing you to consume those hooks and perform actions with the custom data. +Some API routes, including the [Create Product API route](https://docs.medusajs.com/api/admin#products_postproducts), accept an `additional_data` request body parameter. This parameter can hold custom data that's passed to the [hooks](https://docs.medusajs.com/learn/fundamentals/workflows/workflow-hooks/index.html.md) of the workflow executed in the API route, allowing you to consume those hooks and perform actions with the custom data. So, in this chapter, to extend the create product flow and associate a brand with a product, you will: -- Consume the [productsCreated](undefined/resources/references/medusa-workflows/createProductsWorkflow#productsCreated) hook of the [createProductsWorkflow](undefined/resources/references/medusa-workflows/createProductsWorkflow), which is executed within the workflow after the product is created. You'll link the product with the brand passed in the `additional_data` parameter. +- Consume the [productsCreated](https://docs.medusajs.com/resources/references/medusa-workflows/createProductsWorkflow#productsCreated/index.html.md) hook of the [createProductsWorkflow](https://docs.medusajs.com/resources/references/medusa-workflows/createProductsWorkflow/index.html.md), which is executed within the workflow after the product is created. You'll link the product with the brand passed in the `additional_data` parameter. - Extend the Create Product API route to allow passing a brand ID in `additional_data`. -To learn more about the `additional_data` property and the API routes that accept additional data, refer to [this chapter](undefined/learn/fundamentals/api-routes/additional-data). +To learn more about the `additional_data` property and the API routes that accept additional data, refer to [this chapter](https://docs.medusajs.com/learn/fundamentals/api-routes/additional-data/index.html.md). ### Prerequisites -- [Brand Module](undefined/learn/customization/custom-features/module) -- [Defined link between the Brand and Product data models.](undefined/learn/customization/extend-features/define-link) +- [Brand Module](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md) +- [Defined link between the Brand and Product data models.](https://docs.medusajs.com/learn/customization/extend-features/define-link/index.html.md) *** @@ -2367,9 +2365,9 @@ To learn more about the `additional_data` property and the API routes that accep A workflow hook is a point in a workflow where you can inject a step to perform a custom functionality. Consuming a workflow hook allows you to extend the features of a workflow and, consequently, the API route that uses it. -Learn more about the workflow hooks in [this chapter](undefined/learn/fundamentals/workflows/workflow-hooks). +Learn more about the workflow hooks in [this chapter](https://docs.medusajs.com/learn/fundamentals/workflows/workflow-hooks/index.html.md). -The [createProductsWorkflow](undefined/resources/references/medusa-workflows/createProductsWorkflow) used in the [Create Product API route](undefined/api/admin#products_postproducts) has a `productsCreated` hook that runs after the product is created. You'll consume this hook to link the created product with the brand specified in the request parameters. +The [createProductsWorkflow](https://docs.medusajs.com/resources/references/medusa-workflows/createProductsWorkflow/index.html.md) used in the [Create Product API route](https://docs.medusajs.com/api/admin#products_postproducts) has a `productsCreated` hook that runs after the product is created. You'll consume this hook to link the created product with the brand specified in the request parameters. To consume the `productsCreated` hook, create the file `src/workflows/hooks/created-product.ts` with the following content: @@ -2403,7 +2401,7 @@ createProductsWorkflow.hooks.productsCreated( Workflows have a special `hooks` property to access its hooks and consume them. Each hook, such as `productsCreated`, accepts a step function as a parameter. The step function accepts the following parameters: 1. An object having an `additional_data` property, which is the custom data passed in the request body under `additional_data`. The object will also have properties passed from the workflow to the hook, which in this case is the `products` property that holds an array of the created products. -2. An object of properties related to the step's context. It has a `container` property whose value is the [Medusa container](undefined/learn/fundamentals/medusa-container) to resolve Framework and commerce tools. +2. An object of properties related to the step's context. It has a `container` property whose value is the [Medusa container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md) to resolve Framework and commerce tools. In the step, if a brand ID is passed in `additional_data`, you resolve the Brand Module's service and use its generated `retrieveBrand` method to retrieve the brand by its ID. The `retrieveBrand` method will throw an error if the brand doesn't exist. @@ -2411,7 +2409,7 @@ In the step, if a brand ID is passed in `additional_data`, you resolve the Brand Next, you want to create a link between the created products and the brand. To do so, you use Link, which is a class from the Modules SDK that provides methods to manage linked records. -Learn more about Link in [this chapter](undefined/learn/fundamentals/module-links/link). +Learn more about Link in [this chapter](https://docs.medusajs.com/learn/fundamentals/module-links/link/index.html.md). To use Link in the `productsCreated` hook, replace the `TODO` with the following: @@ -2542,7 +2540,7 @@ curl -X POST 'http://localhost:9000/admin/products' \ }' ``` -Make sure to replace `{token}` with the token you received from the previous request, `shipping_profile_id` with the ID of a shipping profile in your application, and `{brand_id}` with the ID of a brand in your application. You can retrieve the ID of a shipping profile either from the Medusa Admin, or the [List Shipping Profiles API route](undefined/api/admin#shipping-profiles_getshippingprofiles). +Make sure to replace `{token}` with the token you received from the previous request, `shipping_profile_id` with the ID of a shipping profile in your application, and `{brand_id}` with the ID of a brand in your application. You can retrieve the ID of a shipping profile either from the Medusa Admin, or the [List Shipping Profiles API route](https://docs.medusajs.com/api/admin#shipping-profiles_getshippingprofiles). The request creates a product and returns it. @@ -2563,39 +2561,39 @@ In other commerce platforms, you extend core features and models through hacky w The Medusa Framework and orchestration tools mitigate these issues while supporting all your customization needs: -- [Module Links](undefined/learn/fundamentals/module-links): Link data models of different modules without building direct dependencies, ensuring that the Medusa application integrates your modules without side effects. -- [Workflow Hooks](undefined/learn/fundamentals/workflows/workflow-hooks): inject custom functionalities into a workflow at predefined points, called hooks. This allows you to perform custom actions as a part of a core workflow without hacky workarounds. -- [Additional Data in API Routes](undefined/learn/fundamentals/api-routes/additional-data): Configure core API routes to accept request parameters relevant to your customizations. These parameters are passed to the underlying workflow's hooks, where you can manage your custom data as part of an existing flow. +- [Module Links](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md): Link data models of different modules without building direct dependencies, ensuring that the Medusa application integrates your modules without side effects. +- [Workflow Hooks](https://docs.medusajs.com/learn/fundamentals/workflows/workflow-hooks/index.html.md): inject custom functionalities into a workflow at predefined points, called hooks. This allows you to perform custom actions as a part of a core workflow without hacky workarounds. +- [Additional Data in API Routes](https://docs.medusajs.com/learn/fundamentals/api-routes/additional-data/index.html.md): Configure core API routes to accept request parameters relevant to your customizations. These parameters are passed to the underlying workflow's hooks, where you can manage your custom data as part of an existing flow. *** ## Next Chapters: Link Brands to Products Example -The next chapters explain how to use the tools mentioned above with step-by-step guides. You'll continue with the [brands example from the previous chapters](undefined/learn/customization/custom-features) to: +The next chapters explain how to use the tools mentioned above with step-by-step guides. You'll continue with the [brands example from the previous chapters](https://docs.medusajs.com/learn/customization/custom-features/index.html.md) to: -- Link brands from the custom [Brand Module](undefined/learn/customization/custom-features/module) to products from Medusa's [Product Module](undefined/resources/commerce-modules/product). +- Link brands from the custom [Brand Module](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md) to products from Medusa's [Product Module](https://docs.medusajs.com/resources/commerce-modules/product/index.html.md). - Extend the core product-creation workflow and the API route that uses it to allow setting the brand of a newly created product. - Retrieve a product's associated brand's details. # Guide: Query Product's Brands -In the previous chapters, you [defined a link](undefined/learn/customization/extend-features/define-link) between the [custom Brand Module](undefined/learn/customization/custom-features/module) and Medusa's [Product Module](undefined/resources/commerce-modules/product), then [extended the create-product flow](undefined/learn/customization/extend-features/extend-create-product) to link a product to a brand. +In the previous chapters, you [defined a link](https://docs.medusajs.com/learn/customization/extend-features/define-link/index.html.md) between the [custom Brand Module](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md) and Medusa's [Product Module](https://docs.medusajs.com/resources/commerce-modules/product/index.html.md), then [extended the create-product flow](https://docs.medusajs.com/learn/customization/extend-features/extend-create-product/index.html.md) to link a product to a brand. In this chapter, you'll learn how to retrieve a product's brand (and vice-versa) in two ways: Using Medusa's existing API route, or in customizations, such as a custom API route. ### Prerequisites -- [Brand Module](undefined/learn/customization/custom-features/module) -- [Defined link between the Brand and Product data models.](undefined/learn/customization/extend-features/define-link) +- [Brand Module](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md) +- [Defined link between the Brand and Product data models.](https://docs.medusajs.com/learn/customization/extend-features/define-link/index.html.md) *** ## Approach 1: Retrieve Brands in Existing API Routes -Medusa's existing API routes accept a `fields` query parameter that allows you to specify the fields and relations of a model to retrieve. So, when you send a request to the [List Products](undefined/api/admin#products_getproducts), [Get Product](undefined/api/admin#products_getproductsid), or any product-related store or admin routes that accept a `fields` query parameter, you can specify in this parameter to return the product's brands. +Medusa's existing API routes accept a `fields` query parameter that allows you to specify the fields and relations of a model to retrieve. So, when you send a request to the [List Products](https://docs.medusajs.com/api/admin#products_getproducts), [Get Product](https://docs.medusajs.com/api/admin#products_getproductsid), or any product-related store or admin routes that accept a `fields` query parameter, you can specify in this parameter to return the product's brands. -Learn more about using the `fields` query parameter to retrieve custom linked data models in the [Retrieve Custom Linked Data Models from Medusa's API Routes](undefined/learn/fundamentals/api-routes/retrieve-custom-links) chapter. +Learn more about using the `fields` query parameter to retrieve custom linked data models in the [Retrieve Custom Linked Data Models from Medusa's API Routes](https://docs.medusajs.com/learn/fundamentals/api-routes/retrieve-custom-links/index.html.md) chapter. For example, send the following request to retrieve the list of products with their brands: @@ -2604,7 +2602,7 @@ curl 'http://localhost:9000/admin/products?fields=+brand.*' \ --header 'Authorization: Bearer {token}' ``` -Make sure to replace `{token}` with your admin user's authentication token. Learn how to retrieve it in the [API reference](undefined/api/store#authentication). +Make sure to replace `{token}` with your admin user's authentication token. Learn how to retrieve it in the [API reference](https://docs.medusajs.com/api/store#authentication). Any product that is linked to a brand will have a `brand` property in its object: @@ -2628,7 +2626,7 @@ By using the `fields` query parameter, you don't have to re-create existing API While you can retrieve linked records using the `fields` query parameter of an existing API route, you can't filter by linked records. -Instead, you'll have to create a custom API route that uses Query to retrieve linked records with filters, as explained in the [Query documentation](undefined/learn/fundamentals/module-links/query#apply-filters-and-pagination-on-linked-records). +Instead, you'll have to create a custom API route that uses Query to retrieve linked records with filters, as explained in the [Query documentation](https://docs.medusajs.com/learn/fundamentals/module-links/query#apply-filters-and-pagination-on-linked-records/index.html.md). *** @@ -2636,9 +2634,9 @@ Instead, you'll have to create a custom API route that uses Query to retrieve li You can also retrieve linked records using Query. Query allows you to retrieve data across modules with filters, pagination, and more. You can resolve Query from the Medusa container and use it in your API route or workflow. -Learn more about Query in [this chapter](undefined/learn/fundamentals/module-links/query). +Learn more about Query in [this chapter](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md). -For example, you can create an API route that retrieves brands and their products. If you followed the [Create Brands API route chapter](undefined/learn/customization/custom-features/api-route), you'll have the file `src/api/admin/brands/route.ts` with a `POST` API route. Add a new `GET` function to the same file: +For example, you can create an API route that retrieves brands and their products. If you followed the [Create Brands API route chapter](https://docs.medusajs.com/learn/customization/custom-features/api-route/index.html.md), you'll have the file `src/api/admin/brands/route.ts` with a `POST` API route. Add a new `GET` function to the same file: ```ts title="src/api/admin/brands/route.ts" highlights={highlights} // other imports... @@ -2680,7 +2678,7 @@ curl 'http://localhost:9000/admin/brands' \ -H 'Authorization: Bearer {token}' ``` -Make sure to replace `{token}` with your admin user's authentication token. Learn how to retrieve it in the [API reference](undefined/api/store#authentication). +Make sure to replace `{token}` with your admin user's authentication token. Learn how to retrieve it in the [API reference](https://docs.medusajs.com/api/store#authentication). This returns the brands in your store with their linked products. For example: @@ -2705,7 +2703,7 @@ This returns the brands in your store with their linked products. For example: While you can use Query to retrieve linked records, you can't filter by linked records. -For an alternative approach, refer to the [Query documentation](undefined/learn/fundamentals/module-links/query#apply-filters-and-pagination-on-linked-records). +For an alternative approach, refer to the [Query documentation](https://docs.medusajs.com/learn/fundamentals/module-links/query#apply-filters-and-pagination-on-linked-records/index.html.md). *** @@ -2728,20 +2726,20 @@ In the next chapters, you'll learn how to customize the Medusa Admin to show a p # Guide: Sync Brands from Medusa to Third-Party -In the [previous chapter](undefined/learn/customization/integrate-systems/service), you created a CMS Module that integrates a dummy third-party system. You can now perform actions using that module within your custom flows. +In the [previous chapter](https://docs.medusajs.com/learn/customization/integrate-systems/service/index.html.md), you created a CMS Module that integrates a dummy third-party system. You can now perform actions using that module within your custom flows. -In another previous chapter, you [added a workflow](undefined/learn/customization/custom-features/workflow) that creates a brand. After integrating the CMS, you want to sync that brand to the third-party system as well. +In another previous chapter, you [added a workflow](https://docs.medusajs.com/learn/customization/custom-features/workflow/index.html.md) that creates a brand. After integrating the CMS, you want to sync that brand to the third-party system as well. -Medusa has an event system that emits events when an operation is performed. It allows you to listen to those events and perform an asynchronous action in a function called a [subscriber](undefined/learn/fundamentals/events-and-subscribers). This is useful to perform actions that aren't integral to the original flow, such as syncing data to a third-party system. +Medusa has an event system that emits events when an operation is performed. It allows you to listen to those events and perform an asynchronous action in a function called a [subscriber](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/index.html.md). This is useful to perform actions that aren't integral to the original flow, such as syncing data to a third-party system. -Learn more about Medusa's event system and subscribers in [this chapter](undefined/learn/fundamentals/events-and-subscribers). +Learn more about Medusa's event system and subscribers in [this chapter](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/index.html.md). In this chapter, you'll modify the `createBrandWorkflow` you created before to emit a custom event that indicates a brand was created. Then, you'll listen to that event in a subscriber to sync the brand to the third-party CMS. You'll implement the sync logic within a workflow that you execute in the subscriber. ### Prerequisites -- [createBrandWorkflow](undefined/learn/customization/custom-features/workflow) -- [CMS Module](undefined/learn/customization/integrate-systems/service) +- [createBrandWorkflow](https://docs.medusajs.com/learn/customization/custom-features/workflow/index.html.md) +- [CMS Module](https://docs.medusajs.com/learn/customization/integrate-systems/service/index.html.md) ## 1. Emit Event in createBrandWorkflow @@ -2789,11 +2787,11 @@ The subscriber that will listen to the `brand.created` event will sync the creat Workflows have a built-in durable execution engine that helps you complete tasks spanning multiple systems. Also, their rollback mechanism ensures that data is consistent across systems even when errors occur during execution. -Learn more about workflows in [this chapter](undefined/learn/fundamentals/workflows). +Learn more about workflows in [this chapter](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md). You'll create a `syncBrandToSystemWorkflow` that has two steps: -- `useQueryGraphStep`: a step that Medusa provides to retrieve data using [Query](undefined/learn/fundamentals/module-links/query). You'll use this to retrieve the brand's details using its ID. +- `useQueryGraphStep`: a step that Medusa provides to retrieve data using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md). You'll use this to retrieve the brand's details using its ID. - `syncBrandToCmsStep`: a step that you'll create to sync the brand to the CMS. ### syncBrandToCmsStep @@ -2834,11 +2832,11 @@ const syncBrandToCmsStep = createStep( ) ``` -You create the `syncBrandToCmsStep` that accepts a brand as an input. In the step, you resolve the CMS Module's service from the [Medusa container](undefined/learn/fundamentals/medusa-container) and use its `createBrand` method. This method will create the brand in the third-party CMS. +You create the `syncBrandToCmsStep` that accepts a brand as an input. In the step, you resolve the CMS Module's service from the [Medusa container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md) and use its `createBrand` method. This method will create the brand in the third-party CMS. You also pass the brand's ID to the step's compensation function. In this function, you delete the brand in the third-party CMS if an error occurs during the workflow's execution. -Learn more about compensation functions in [this chapter](undefined/learn/fundamentals/workflows/compensation-function). +Learn more about compensation functions in [this chapter](https://docs.medusajs.com/learn/fundamentals/workflows/compensation-function/index.html.md). ### Create Workflow @@ -2889,7 +2887,7 @@ You create a `syncBrandToCmsWorkflow` that accepts the brand's ID as input. The You'll execute this workflow in the subscriber next. -Learn more about `useQueryGraphStep` in [this reference](undefined/resources/references/helper-steps/useQueryGraphStep). +Learn more about `useQueryGraphStep` in [this reference](https://docs.medusajs.com/resources/references/helper-steps/useQueryGraphStep/index.html.md). *** @@ -2934,13 +2932,13 @@ The subscriber function accepts an object parameter that has two properties: In the function, you execute the `syncBrandToCmsWorkflow`, passing it the data payload as an input. So, everytime a brand is created, Medusa will execute this function, which in turn executes the workflow to sync the brand to the CMS. -Learn more about subscribers in [this chapter](undefined/learn/fundamentals/events-and-subscribers). +Learn more about subscribers in [this chapter](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/index.html.md). *** ## Test it Out -To test the subscriber and workflow out, you'll use the [Create Brand API route](undefined/learn/customization/custom-features/api-route) you created in a previous chapter. +To test the subscriber and workflow out, you'll use the [Create Brand API route](https://docs.medusajs.com/learn/customization/custom-features/api-route/index.html.md) you created in a previous chapter. First, start the Medusa application: @@ -2961,7 +2959,7 @@ curl -X POST 'http://localhost:9000/auth/user/emailpass' \ Make sure to replace the email and password with your admin user's credentials. -Don't have an admin user? Refer to [this guide](undefined/learn/installation#create-medusa-admin-user). +Don't have an admin user? Refer to [this guide](https://docs.medusajs.com/learn/installation#create-medusa-admin-user/index.html.md). Then, send a `POST` request to `/admin/brands`, passing the token received from the previous request in the `Authorization` header: @@ -3007,13 +3005,13 @@ In Medusa, you integrate a third-party system by: 1. Creating a module whose service provides the methods to connect to and perform operations in the third-party system. 2. Building workflows that complete tasks spanning across systems. You use the module that integrates a third-party system in the workflow's steps. -3. Executing the workflows you built in an [API route](undefined/learn/fundamentals/api-routes), at a scheduled time, or when an event is emitted. +3. Executing the workflows you built in an [API route](https://docs.medusajs.com/learn/fundamentals/api-routes/index.html.md), at a scheduled time, or when an event is emitted. *** ## Next Chapters: Sync Brands Example -In the previous chapters, you've [added brands](undefined/learn/customization/custom-features/module) to your Medusa application. In the next chapters, you will: +In the previous chapters, you've [added brands](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md) to your Medusa application. In the next chapters, you will: 1. Integrate a dummy third-party CMS in the Brand Module. 2. Sync brands to the CMS when a brand is created. @@ -3022,19 +3020,19 @@ In the previous chapters, you've [added brands](undefined/learn/customization/cu # Guide: Schedule Syncing Brands from Third-Party -In the previous chapters, you've [integrated a third-party CMS](undefined/learn/customization/integrate-systems/service) and implemented the logic to [sync created brands](undefined/learn/customization/integrate-systems/handle-event) from Medusa to the CMS. +In the previous chapters, you've [integrated a third-party CMS](https://docs.medusajs.com/learn/customization/integrate-systems/service/index.html.md) and implemented the logic to [sync created brands](https://docs.medusajs.com/learn/customization/integrate-systems/handle-event/index.html.md) from Medusa to the CMS. However, when you integrate a third-party system, you want the data to be in sync between the Medusa application and the system. One way to do so is by automatically syncing the data once a day. You can create an action to be automatically executed at a specified interval using scheduled jobs. A scheduled job is an asynchronous function with a specified schedule of when the Medusa application should run it. Scheduled jobs are useful to automate repeated tasks. -Learn more about scheduled jobs in [this chapter](undefined/learn/fundamentals/scheduled-jobs). +Learn more about scheduled jobs in [this chapter](https://docs.medusajs.com/learn/fundamentals/scheduled-jobs/index.html.md). In this chapter, you'll create a scheduled job that triggers syncing the brands from the third-party CMS to Medusa once a day. You'll implement the syncing logic in a workflow, and execute that workflow in the scheduled job. ### Prerequisites -- [CMS Module](undefined/learn/customization/integrate-systems/service) +- [CMS Module](https://docs.medusajs.com/learn/customization/integrate-systems/service/index.html.md) *** @@ -3044,7 +3042,7 @@ You'll start by implementing the syncing logic in a workflow, then execute the w Workflows have a built-in durable execution engine that helps you complete tasks spanning multiple systems. Also, their rollback mechanism ensures that data is consistent across systems even when errors occur during execution. -Learn more about workflows in [this chapter](undefined/learn/fundamentals/workflows). +Learn more about workflows in [this chapter](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md). This workflow will have three steps: @@ -3126,11 +3124,11 @@ export const createBrandsStep = createStep( ) ``` -The `createBrandsStep` accepts the brands to create as an input. It resolves the [Brand Module](undefined/learn/customization/custom-features/module)'s service and uses the generated `createBrands` method to create the brands. +The `createBrandsStep` accepts the brands to create as an input. It resolves the [Brand Module](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md)'s service and uses the generated `createBrands` method to create the brands. The step passes the created brands to the compensation function, which deletes those brands if an error occurs during the workflow's execution. -Learn more about compensation functions in [this chapter](undefined/learn/fundamentals/workflows/compensation-function). +Learn more about compensation functions in [this chapter](https://docs.medusajs.com/learn/fundamentals/workflows/compensation-function/index.html.md). ### Update Brands Step @@ -3208,9 +3206,9 @@ export const syncBrandsFromCmsWorkflow = createWorkflow( In the workflow, you only use the `retrieveBrandsFromCmsStep` for now, which retrieves the brands from the third-party CMS. -Next, you need to identify which brands must be created or updated. Since workflows are constructed internally and are only evaluated during execution, you can't access values to perform data manipulation directly. Instead, use [transform](undefined/learn/fundamentals/workflows/variable-manipulation) from the Workflows SDK that gives you access to the real-time values of the data, allowing you to create new variables using those values. +Next, you need to identify which brands must be created or updated. Since workflows are constructed internally and are only evaluated during execution, you can't access values to perform data manipulation directly. Instead, use [transform](https://docs.medusajs.com/learn/fundamentals/workflows/variable-manipulation/index.html.md) from the Workflows SDK that gives you access to the real-time values of the data, allowing you to create new variables using those values. -Learn more about data manipulation using `transform` in [this chapter](undefined/learn/fundamentals/workflows/variable-manipulation). +Learn more about data manipulation using `transform` in [this chapter](https://docs.medusajs.com/learn/fundamentals/workflows/variable-manipulation/index.html.md). So, replace the `TODO` with the following: @@ -3304,7 +3302,7 @@ A scheduled job file must export: - `name`: A unique name for the scheduled job. - `schedule`: A string that holds a [cron expression](https://crontab.guru/) indicating the schedule to run the job. -The scheduled job function accepts as a parameter the [Medusa container](undefined/learn/fundamentals/medusa-container) used to resolve Framework and commerce tools. You then execute the `syncBrandsFromCmsWorkflow` and use its result to log how many brands were created or updated. +The scheduled job function accepts as a parameter the [Medusa container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md) used to resolve Framework and commerce tools. You then execute the `syncBrandsFromCmsWorkflow` and use its result to log how many brands were created or updated. Based on the cron expression specified in `config.schedule`, Medusa will run the scheduled job every day at midnight. You can also change it to `* * * * *` to run it every minute for easier debugging. @@ -3331,9 +3329,9 @@ With Medusa, you can integrate any service from your commerce ecosystem with eas # Guide: Integrate Third-Party Brand System -In the previous chapters, you've created a [Brand Module](undefined/learn/customization/custom-features/module) that adds brands to your application. In this chapter, you'll integrate a dummy Content-Management System (CMS) in a new module. The module's service will provide methods to retrieve and manage brands in the CMS. You'll later use this service to sync data from and to the CMS. +In the previous chapters, you've created a [Brand Module](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md) that adds brands to your application. In this chapter, you'll integrate a dummy Content-Management System (CMS) in a new module. The module's service will provide methods to retrieve and manage brands in the CMS. You'll later use this service to sync data from and to the CMS. -Learn more about modules in [this chapter](undefined/learn/fundamentals/modules). +Learn more about modules in [this chapter](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md). ## 1. Create Module Directory @@ -3380,7 +3378,7 @@ export default CmsModuleService You create a `CmsModuleService` that will hold the methods to connect to the third-party CMS. A service's constructor accepts two parameters: -1. The module's container. Since a module is [isolated](undefined/learn/fundamentals/modules/isolation), it has a [local container](undefined/learn/fundamentals/modules/container) different than the Medusa container you use in other customizations. This container holds Framework tools like the [Logger utility](undefined/learn/debugging-and-testing/logging) and resources within the module. +1. The module's container. Since a module is [isolated](https://docs.medusajs.com/learn/fundamentals/modules/isolation/index.html.md), it has a [local container](https://docs.medusajs.com/learn/fundamentals/modules/container/index.html.md) different than the Medusa container you use in other customizations. This container holds Framework tools like the [Logger utility](https://docs.medusajs.com/learn/debugging-and-testing/logging/index.html.md) and resources within the module. 2. Options passed to the module when it's later added in Medusa's configurations. These options are useful to pass secret keys or configurations that ensure your module is re-usable across applications. For the CMS Module, you accept the API key to connect to the dummy CMS as an option. When integrating a third-party system that has a Node.js SDK or client, you can initialize that client in the constructor to be used in the service's methods. @@ -3498,27 +3496,27 @@ The next chapters will cover each of these concepts in depth, with the different The following guides and references are useful for your development journey: -3. [Commerce Modules](undefined/resources/commerce-modules): Browse the list of Commerce Modules in Medusa and their references to learn how to use them. -4. [Service Factory Reference](undefined/resources/service-factory-reference): Learn about the methods generated by `MedusaService` with examples. -5. [Workflows Reference](undefined/resources/medusa-workflows-reference): Browse the list of core workflows and their hooks that are useful for your customizations. -6. [Admin Injection Zones](undefined/resources/admin-widget-injection-zones): Browse the injection zones in the Medusa Admin to learn where you can inject widgets. +3. [Commerce Modules](https://docs.medusajs.com/resources/commerce-modules/index.html.md): Browse the list of Commerce Modules in Medusa and their references to learn how to use them. +4. [Service Factory Reference](https://docs.medusajs.com/resources/service-factory-reference/index.html.md): Learn about the methods generated by `MedusaService` with examples. +5. [Workflows Reference](https://docs.medusajs.com/resources/medusa-workflows-reference/index.html.md): Browse the list of core workflows and their hooks that are useful for your customizations. +6. [Admin Injection Zones](https://docs.medusajs.com/resources/admin-widget-injection-zones/index.html.md): Browse the injection zones in the Medusa Admin to learn where you can inject widgets. *** ## More Examples in Recipes -In the [Recipes](undefined/resources/recipes) documentation, you'll also find step-by-step guides for different use cases, such as building a marketplace, digital products, and more. +In the [Recipes](https://docs.medusajs.com/resources/recipes/index.html.md) documentation, you'll also find step-by-step guides for different use cases, such as building a marketplace, digital products, and more. # Re-Use Customizations with Plugins -In the previous chapters, you've followed the [brand example](undefined/learn/customization/custom-features) to learn important concepts related to: +In the previous chapters, you've followed the [brand example](https://docs.medusajs.com/learn/customization/custom-features/index.html.md) to learn important concepts related to: -- [Creating modules](undefined/learn/customization/custom-features/module). -- [Implementing commerce features in workflows](undefined/learn/customization/custom-features/workflow). -- [Exposing those features in API routes](undefined/learn/customization/custom-features/api-route). -- [Customizing the Medusa Admin dashboard with Admin Extensions](undefined/learn/customization/customize-admin). -- [Integrating third-party systems](undefined/learn/customization/integrate-systems). +- [Creating modules](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md). +- [Implementing commerce features in workflows](https://docs.medusajs.com/learn/customization/custom-features/workflow/index.html.md). +- [Exposing those features in API routes](https://docs.medusajs.com/learn/customization/custom-features/api-route/index.html.md). +- [Customizing the Medusa Admin dashboard with Admin Extensions](https://docs.medusajs.com/learn/customization/customize-admin/index.html.md). +- [Integrating third-party systems](https://docs.medusajs.com/learn/customization/integrate-systems/index.html.md). You've implemented the brands example within a single Medusa application. However, this approach is not scalable. If you want to use the same brands feature in different Medusa applications, you would have to manually copy the code and maintain it across all projects. @@ -3528,7 +3526,7 @@ Instead, to reuse your customizations across multiple Medusa applications, you c Medusa provides the tooling to create a plugin package, test it in a local Medusa application, and publish it to NPM. -Refer to the [Plugins](undefined/learn/fundamentals/plugins) chapter to learn more about plugins and how to create them. +Refer to the [Plugins](https://docs.medusajs.com/learn/fundamentals/plugins/index.html.md) chapter to learn more about plugins and how to create them. # Debug Workflows @@ -3560,7 +3558,7 @@ It's recommended to always write integration tests for your workflows. This help ### How to Write Integration Tests for Workflows -Refer to the [Integration Tests](undefined/learn/debugging-and-testing/testing-tools/integration-tests) chapter to learn how to write integration tests for your workflows and find examples of testing workflows. +Refer to the [Integration Tests](https://docs.medusajs.com/learn/debugging-and-testing/testing-tools/integration-tests/index.html.md) chapter to learn how to write integration tests for your workflows and find examples of testing workflows. *** @@ -3574,7 +3572,7 @@ Use breakpoints when you need to debug specific steps in your workflow, rather t ### Where Can You Add Breakpoints -Since Medusa stores an internal representation of the workflow constructor on application startup, breakpoints within the workflow's constructor won't work during execution. Learn more in the [Data Manipulation](undefined/learn/fundamentals/workflows/variable-manipulation) chapter. +Since Medusa stores an internal representation of the workflow constructor on application startup, breakpoints within the workflow's constructor won't work during execution. Learn more in the [Data Manipulation](https://docs.medusajs.com/learn/fundamentals/workflows/variable-manipulation/index.html.md) chapter. Instead, you can add breakpoints in: @@ -3734,7 +3732,7 @@ Instead, you can log messages in: - A step's compensation function. - The `transform` callback function of a step. -You can log messages with `console.log`. In step and compensation functions, you can also use the [Logger](undefined/learn/debugging-and-testing/logging) to log messages with different log levels (info, warn, error). +You can log messages with `console.log`. In step and compensation functions, you can also use the [Logger](https://docs.medusajs.com/learn/debugging-and-testing/logging/index.html.md) to log messages with different log levels (info, warn, error). For example: @@ -3859,17 +3857,17 @@ export const myWorkflow = createWorkflow( If you execute the workflow, you'll see the logged message in your console. -Learn more about logging in the [Logger](undefined/learn/debugging-and-testing/logging) chapter. +Learn more about logging in the [Logger](https://docs.medusajs.com/learn/debugging-and-testing/logging/index.html.md) chapter. *** ## Approach 4: Monitor Workflow Executions in Medusa Admin -The Medusa Admin has a [Workflows](undefined/user-guide/settings/developer/workflows) settings page that provides a user-friendly interface to view stored workflow executions. +The Medusa Admin has a [Workflows](https://docs.medusajs.com/user-guide/settings/developer/workflows/index.html.md) settings page that provides a user-friendly interface to view stored workflow executions. ### When to Use Admin Monitoring -Use the Medusa Admin to monitor [stored workflow executions](undefined/learn/fundamentals/workflows/store-executions) when debugging unexpected issues and edge cases, especially in production environments and long-running workflows that run in the background. +Use the Medusa Admin to monitor [stored workflow executions](https://docs.medusajs.com/learn/fundamentals/workflows/store-executions/index.html.md) when debugging unexpected issues and edge cases, especially in production environments and long-running workflows that run in the background. By viewing the workflow executions through the Medusa Admin, you can: @@ -3879,13 +3877,13 @@ By viewing the workflow executions through the Medusa Admin, you can: ### How to Monitor Workflow Executions in the Admin -The Workflows settings page in the Medusa Admin shows you the history of stored workflow executions only. Workflow executions are stored if a workflow is [long-running](undefined/learn/fundamentals/workflows/long-running-workflow), or if the `store` and `retentionTime` options are set on the workflow. +The Workflows settings page in the Medusa Admin shows you the history of stored workflow executions only. Workflow executions are stored if a workflow is [long-running](https://docs.medusajs.com/learn/fundamentals/workflows/long-running-workflow/index.html.md), or if the `store` and `retentionTime` options are set on the workflow. For example, to store workflow executions: ### Prerequisites -- [Redis Workflow Engine must be installed and configured.](undefined/resources/infrastructure-modules/workflow-engine/redis) +- [Redis Workflow Engine must be installed and configured.](https://docs.medusajs.com/resources/infrastructure-modules/workflow-engine/redis/index.html.md) ```ts highlights={[["22"], ["23"]]} collapsibleLines="1-7" expandButtonLabel="Show Imports" import { @@ -3922,9 +3920,9 @@ export const myWorkflow = createWorkflow( ) ``` -Refer to the [Store Workflow Executions](undefined/learn/fundamentals/workflows/store-executions) chapter to learn more. +Refer to the [Store Workflow Executions](https://docs.medusajs.com/learn/fundamentals/workflows/store-executions/index.html.md) chapter to learn more. -You can view all executions of this workflow in the Medusa Admin under the [Workflows settings page](undefined/user-guide/settings/developer/workflows). Each execution will show you the status, input, and output data. +You can view all executions of this workflow in the Medusa Admin under the [Workflows settings page](https://docs.medusajs.com/user-guide/settings/developer/workflows/index.html.md). Each execution will show you the status, input, and output data. # Create Custom Feature Flag @@ -3933,7 +3931,7 @@ In this chapter, you'll learn how to create a custom feature flag in Medusa. ## Why Create a Custom Feature Flag? -As explained in the [Feature Flags](undefined/learn/debugging-and-testing/feature-flags) chapter, feature flags allow the Medusa team to ship new features that are still under development and testing, but not ready for production or wide use yet. +As explained in the [Feature Flags](https://docs.medusajs.com/learn/debugging-and-testing/feature-flags/index.html.md) chapter, feature flags allow the Medusa team to ship new features that are still under development and testing, but not ready for production or wide use yet. You can also create custom feature flags for your Medusa project or plugin to control the availability of experimental or in-development features. Feature flags allow you to test features in staging, and only enable them in production when they are ready. @@ -3973,10 +3971,10 @@ Next, you can build the features you want to hide behind the feature flag. To build backend customizations around feature flags, you can either: -- [Conditionally run code blocks](undefined/learn/debugging-and-testing/feature-flags#conditionally-run-code-blocks) based on the feature flag status; -- [Conditionally load files](undefined/learn/debugging-and-testing/feature-flags#conditionally-load-files) if the feature flag is not enabled. +- [Conditionally run code blocks](https://docs.medusajs.com/learn/debugging-and-testing/feature-flags#conditionally-run-code-blocks/index.html.md) based on the feature flag status; +- [Conditionally load files](https://docs.medusajs.com/learn/debugging-and-testing/feature-flags#conditionally-load-files/index.html.md) if the feature flag is not enabled. -For client customizations, such as admin widgets, you can use the [Feature Flags API route](undefined/learn/debugging-and-testing/feature-flags#feature-flags-api-route). +For client customizations, such as admin widgets, you can use the [Feature Flags API route](https://docs.medusajs.com/learn/debugging-and-testing/feature-flags#feature-flags-api-route/index.html.md). ### 3. Toggle Feature Flag @@ -3999,9 +3997,9 @@ Or set the environment variable for the feature flag: FF_BLOG_FEATURE=true ``` -Afterwards, make sure to [run migrations](undefined/learn/fundamentals/data-models/write-migration#run-the-migration) if your feature flag requires database changes. +Afterwards, make sure to [run migrations](https://docs.medusajs.com/learn/fundamentals/data-models/write-migration#run-the-migration/index.html.md) if your feature flag requires database changes. -If you're disabling a feature flag, make sure to [roll back any migrations](undefined/learn/fundamentals/data-models/write-migration#rollback-the-migration) that depend on it first. +If you're disabling a feature flag, make sure to [roll back any migrations](https://docs.medusajs.com/learn/fundamentals/data-models/write-migration#rollback-the-migration/index.html.md) that depend on it first. *** @@ -4056,7 +4054,7 @@ There are multiple ways to enable or disable feature flags in Medusa: The Medusa configurations in `medusa-config.ts` accept a `featureFlags` configuration to toggle feature flags. Its value is an object whose key is the feature flag key (defined in the feature flag's file), and the value is a boolean indicating whether the feature is enabled. -For example, to enable the [Index Module](undefined/learn/fundamentals/module-links/index-module)'s feature flag in `medusa-config.ts`: +For example, to enable the [Index Module](https://docs.medusajs.com/learn/fundamentals/module-links/index-module/index.html.md)'s feature flag in `medusa-config.ts`: ```ts title="medusa-config.ts" module.exports = defineConfig({ @@ -4067,9 +4065,9 @@ module.exports = defineConfig({ }) ``` -Make sure to [run migrations](undefined/learn/fundamentals/data-models/write-migration#run-the-migration) after enabling a feature flag, in case it requires database changes. +Make sure to [run migrations](https://docs.medusajs.com/learn/fundamentals/data-models/write-migration#run-the-migration/index.html.md) after enabling a feature flag, in case it requires database changes. -Before disabling a feature flag, make sure to [roll back the migrations](undefined/learn/fundamentals/data-models/write-migration#rollback-the-migration) that depend on it. +Before disabling a feature flag, make sure to [roll back the migrations](https://docs.medusajs.com/learn/fundamentals/data-models/write-migration#rollback-the-migration/index.html.md) that depend on it. ### 2. Using Environment Variables @@ -4077,15 +4075,15 @@ The feature flags can also be enabled or disabled using environment variables. T To toggle a feature flag using an environment variable, set an environment variable with its environment variable name (defined in the feature flag's file) and set its value to `true` or `false`. -For example, to enable the [Index Module](undefined/learn/fundamentals/module-links/index-module)'s feature flag using an environment variable: +For example, to enable the [Index Module](https://docs.medusajs.com/learn/fundamentals/module-links/index-module/index.html.md)'s feature flag using an environment variable: ```shell MEDUSA_FF_INDEX_ENGINE=true ``` -Make sure to [run migrations](undefined/learn/fundamentals/data-models/write-migration#run-the-migration) after enabling a feature flag, in case it requires database changes. +Make sure to [run migrations](https://docs.medusajs.com/learn/fundamentals/data-models/write-migration#run-the-migration/index.html.md) after enabling a feature flag, in case it requires database changes. -Before disabling a feature flag, make sure to [roll back the migrations](undefined/learn/fundamentals/data-models/write-migration#rollback-the-migration) that depend on it. +Before disabling a feature flag, make sure to [roll back the migrations](https://docs.medusajs.com/learn/fundamentals/data-models/write-migration#rollback-the-migration/index.html.md) that depend on it. *** @@ -4104,7 +4102,7 @@ For client customizations, you can use the [Feature Flags API Route](#feature-fl The `FeatureFlag` utility allows you to check whether a specific feature flag is enabled in your backend customizations, including scheduled jobs, subscribers, and workflow steps. -For example, to enable access to a route only if a feature flag is enabled, you can use the `FeatureFlag` utility in a [middleware](undefined/learn/fundamentals/api-routes/middlewares): +For example, to enable access to a route only if a feature flag is enabled, you can use the `FeatureFlag` utility in a [middleware](https://docs.medusajs.com/learn/fundamentals/api-routes/middlewares/index.html.md): ```ts title="src/api/middlewares.ts" highlights={middlewareHighlights} import { defineMiddlewares } from "@medusajs/framework/http" @@ -4164,9 +4162,9 @@ While both approaches can be used to disable API routes, a middleware is useful ### Feature Flags API Route -For client customizations, you can use the [List Feature Flags API Route](undefined/api/admin#feature-flags_getfeatureflags) to check the status of feature flags. +For client customizations, you can use the [List Feature Flags API Route](https://docs.medusajs.com/api/admin#feature-flags_getfeatureflags) to check the status of feature flags. -For example, you can show an [admin widget](undefined/learn/fundamentals/admin/widgets) only if a feature flag is enabled: +For example, you can show an [admin widget](https://docs.medusajs.com/learn/fundamentals/admin/widgets/index.html.md) only if a feature flag is enabled: ```tsx title="src/admin/widgets/product-details.tsx" highlights={widgetHighlights} import { defineWidgetConfig } from "@medusajs/admin-sdk" @@ -4324,12 +4322,12 @@ Trace span names start with the following keywords based on what it's reporting: ## Useful Links -- [Integrate Sentry with Medusa](undefined/resources/integrations/guides/sentry) +- [Integrate Sentry with Medusa](https://docs.medusajs.com/resources/integrations/guides/sentry/index.html.md) # Override Logger -In this guide, you'll learn how to override the default [Logger](undefined/learn/debugging-and-testing/logging) in Medusa with your custom implementation. +In this guide, you'll learn how to override the default [Logger](https://docs.medusajs.com/learn/debugging-and-testing/logging/index.html.md) in Medusa with your custom implementation. ## Why Override the Logger? @@ -4421,7 +4419,7 @@ You can implement the methods as per your requirements. For simplicity, the abov Notice that you must export an instance of your custom logger class to use it in the Medusa configurations. -You can learn more about the methods in the [Logger](undefined/learn/debugging-and-testing/logging) chapter. +You can learn more about the methods in the [Logger](https://docs.medusajs.com/learn/debugging-and-testing/logging/index.html.md) chapter. ### Step 2: Pass the Custom Logger in Medusa Configurations @@ -4462,7 +4460,7 @@ In this chapter, you’ll learn how to use Medusa’s logging utility. Medusa provides a `Logger` class with advanced logging functionalities. This includes configuring logging levels or saving logs to a file. -By default, the `Logger` class logs messages to the console. You can also override the default logger with your custom implementation, as explained in the [Override Logger](undefined/learn/debugging-and-testing/logging/custom-logger) guide. +By default, the `Logger` class logs messages to the console. You can also override the default logger with your custom implementation, as explained in the [Override Logger](https://docs.medusajs.com/learn/debugging-and-testing/logging/custom-logger/index.html.md) guide. The Medusa application registers the `Logger` class in the Medusa container and each module's container as `logger`. @@ -4600,11 +4598,11 @@ If you configured the `LOG_LEVEL` environment variable to a level higher than th # Example: Write Integration Tests for API Routes -In this chapter, you'll learn how to write integration tests for API routes using [medusaIntegrationTestRunner](undefined/learn/debugging-and-testing/testing-tools/integration-tests) from Medusa's Testing Framework. +In this chapter, you'll learn how to write integration tests for API routes using [medusaIntegrationTestRunner](https://docs.medusajs.com/learn/debugging-and-testing/testing-tools/integration-tests/index.html.md) from Medusa's Testing Framework. ### Prerequisites -- [Testing Tools Setup](undefined/learn/debugging-and-testing/testing-tools) +- [Testing Tools Setup](https://docs.medusajs.com/learn/debugging-and-testing/testing-tools/index.html.md) ## Test a GET API Route @@ -4665,7 +4663,7 @@ Run the following command to run your tests: npm run test:integration ``` -If you don't have a `test:integration` script in `package.json`, refer to the [Medusa Testing Tools chapter](undefined/learn/debugging-and-testing/testing-tools#add-test-commands). +If you don't have a `test:integration` script in `package.json`, refer to the [Medusa Testing Tools chapter](https://docs.medusajs.com/learn/debugging-and-testing/testing-tools#add-test-commands/index.html.md). This runs your Medusa application and runs the tests available under the `src/integrations/http` directory. @@ -4937,7 +4935,7 @@ medusaIntegrationTestRunner({ jest.setTimeout(60 * 1000) ``` -In your test suit, you add a `beforeAll` hook to create a publishable API key before the tests run. To create the API key, you can use the `createApiKeysWorkflow` or the [API Key Module's service](undefined/resources/commerce-modules/api-key). +In your test suit, you add a `beforeAll` hook to create a publishable API key before the tests run. To create the API key, you can use the `createApiKeysWorkflow` or the [API Key Module's service](https://docs.medusajs.com/resources/commerce-modules/api-key/index.html.md). Then, in the test, you pass an object as the last parameter to `api.get` with a `headers` property. The `headers` property is an object with the key `x-publishable-api-key` and the value of the API key's token. @@ -5196,7 +5194,7 @@ In this chapter, you'll learn about `medusaIntegrationTestRunner` from Medusa's ### Prerequisites -- [Testing Tools Setup](undefined/learn/debugging-and-testing/testing-tools) +- [Testing Tools Setup](https://docs.medusajs.com/learn/debugging-and-testing/testing-tools/index.html.md) ## medusaIntegrationTestRunner Utility @@ -5247,7 +5245,7 @@ Run the following command to run your tests: npm run test:integration ``` -If you don't have a `test:integration` script in `package.json`, refer to the [Medusa Testing Tools chapter](undefined/learn/debugging-and-testing/testing-tools#add-test-commands). +If you don't have a `test:integration` script in `package.json`, refer to the [Medusa Testing Tools chapter](https://docs.medusajs.com/learn/debugging-and-testing/testing-tools#add-test-commands/index.html.md). This runs your Medusa application and runs the tests available under the `src/integrations/http` directory. @@ -5255,7 +5253,7 @@ This runs your Medusa application and runs the tests available under the `src/in ## Other Options and Inputs -Refer to [the Test Tooling Reference](undefined/resources/test-tools-reference/medusaIntegrationTestRunner) for other available parameter options and inputs of the `testSuite` function. +Refer to [the Test Tooling Reference](https://docs.medusajs.com/resources/test-tools-reference/medusaIntegrationTestRunner/index.html.md) for other available parameter options and inputs of the `testSuite` function. *** @@ -5263,7 +5261,7 @@ Refer to [the Test Tooling Reference](undefined/resources/test-tools-reference/m The `medusaIntegrationTestRunner` function creates a database with a random name before running the tests. Then, it drops that database after all the tests end. -To manage that database, such as changing its name or perform operations on it in your tests, refer to [the Test Tooling Reference](undefined/resources/test-tools-reference/medusaIntegrationTestRunner). +To manage that database, such as changing its name or perform operations on it in your tests, refer to [the Test Tooling Reference](https://docs.medusajs.com/resources/test-tools-reference/medusaIntegrationTestRunner/index.html.md). *** @@ -5274,13 +5272,13 @@ The next chapters provide examples of writing integration tests for API routes a # Example: Write Integration Tests for Workflows -In this chapter, you'll learn how to write integration tests for workflows using [medusaIntegrationTestRunner](undefined/learn/debugging-and-testing/testing-tools/integration-tests) from Medusa's Testing Framework. +In this chapter, you'll learn how to write integration tests for workflows using [medusaIntegrationTestRunner](https://docs.medusajs.com/learn/debugging-and-testing/testing-tools/integration-tests/index.html.md) from Medusa's Testing Framework. -For other debugging approaches, refer to the [Debug Workflows](undefined/learn/debugging-and-testing/debug-workflows) chapter. +For other debugging approaches, refer to the [Debug Workflows](https://docs.medusajs.com/learn/debugging-and-testing/debug-workflows/index.html.md) chapter. ### Prerequisites -- [Testing Tools Setup](undefined/learn/debugging-and-testing/testing-tools) +- [Testing Tools Setup](https://docs.medusajs.com/learn/debugging-and-testing/testing-tools/index.html.md) ## Write Integration Test for a Workflow @@ -5351,7 +5349,7 @@ Run the following command to run your tests: npm run test:integration:http ``` -If you don't have a `test:integration:http` script in `package.json`, refer to the [Medusa Testing Tools chapter](undefined/learn/debugging-and-testing/testing-tools#add-test-commands). +If you don't have a `test:integration:http` script in `package.json`, refer to the [Medusa Testing Tools chapter](https://docs.medusajs.com/learn/debugging-and-testing/testing-tools#add-test-commands/index.html.md). This runs your Medusa application and runs the tests available under the `integration-tests/http` directory. @@ -5408,7 +5406,7 @@ If you threw a `MedusaError`, then you can check the error message in `errors[0] ## Test Long-Running Workflows -Since [long-running workflows](undefined/learn/fundamentals/workflows/long-running-workflow) run asynchronously, testing them requires a different approach than synchronous workflows. +Since [long-running workflows](https://docs.medusajs.com/learn/fundamentals/workflows/long-running-workflow/index.html.md) run asynchronously, testing them requires a different approach than synchronous workflows. When testing long-running workflows, you need to: @@ -5532,7 +5530,7 @@ jest.setTimeout(60 * 1000) In this test, you: 1. Execute the long-running workflow and get the transaction details from the `run` method's result. -2. Resolve the [Workflow Engine Module](undefined/resources/infrastructure-modules/workflow-engine)'s service from the Medusa container. +2. Resolve the [Workflow Engine Module](https://docs.medusajs.com/resources/infrastructure-modules/workflow-engine/index.html.md)'s service from the Medusa container. 3. Create a promise to wait for the workflow's completion. 4. Subscribe to the workflow's events using the Workflow Engine Module's `subscribe` method. - The `subscriber` function is called whenever an event related to the workflow occurs. On the `onFinish` event that indicates the workflow has completed, you resolve the promise with the workflow's result. @@ -5637,7 +5635,7 @@ This section provides examples of both scenarios. ### Verify Database Operations in Workflow Test -To retrieve data from the database after running a workflow, you can resolve and use either the module's service (for example, the Brand Module's service) or [Query](undefined/learn/fundamentals/module-links/query). +To retrieve data from the database after running a workflow, you can resolve and use either the module's service (for example, the Brand Module's service) or [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md). For example, the following test verifies that a brand was created by a workflow: @@ -5799,7 +5797,7 @@ In this chapter, you'll learn about `moduleIntegrationTestRunner` from Medusa's ### Prerequisites -- [Testing Tools Setup](undefined/learn/debugging-and-testing/testing-tools) +- [Testing Tools Setup](https://docs.medusajs.com/learn/debugging-and-testing/testing-tools/index.html.md) ## moduleIntegrationTestRunner Utility @@ -5871,7 +5869,7 @@ Run the following command to run your module integration tests: npm run test:integration:modules ``` -If you don't have a `test:integration:modules` script in `package.json`, refer to the [Medusa Testing Tools chapter](undefined/learn/debugging-and-testing/testing-tools#add-test-commands). +If you don't have a `test:integration:modules` script in `package.json`, refer to the [Medusa Testing Tools chapter](https://docs.medusajs.com/learn/debugging-and-testing/testing-tools#add-test-commands/index.html.md). This runs your Medusa application and runs the tests available in any `__tests__` directory under the `src/modules` directory. @@ -5926,7 +5924,7 @@ jest.setTimeout(60 * 1000) ## Inject Dependencies in Module Tests -Some modules have injected dependencies, such as the [Event Module's service](undefined/resources/infrastructure-modules/event). When writing tests for those modules, you need to inject the dependencies that the module's service requires to avoid errors. +Some modules have injected dependencies, such as the [Event Module's service](https://docs.medusajs.com/resources/infrastructure-modules/event/index.html.md). When writing tests for those modules, you need to inject the dependencies that the module's service requires to avoid errors. You can inject dependencies as mock dependencies that simulate the behavior of the original service. This way you avoid unexpected behavior or results, such as sending real events or making real API calls. @@ -5972,7 +5970,7 @@ For other modules, you can create a mock service that implements the same interf ### Other Options and Inputs -Refer to [the Test Tooling Reference](undefined/resources/test-tools-reference/moduleIntegrationTestRunner) for other available parameter options and inputs of the `testSuite` function. +Refer to [the Test Tooling Reference](https://docs.medusajs.com/resources/test-tools-reference/moduleIntegrationTestRunner/index.html.md) for other available parameter options and inputs of the `testSuite` function. *** @@ -5980,7 +5978,7 @@ Refer to [the Test Tooling Reference](undefined/resources/test-tools-reference/m The `moduleIntegrationTestRunner` function creates a database with a random name before running the tests. Then, it drops that database after all the tests end. -To manage that database, such as changing its name or perform operations on it in your tests, refer to [the Test Tooling Reference](undefined/resources/test-tools-reference/moduleIntegrationTestRunner). +To manage that database, such as changing its name or perform operations on it in your tests, refer to [the Test Tooling Reference](https://docs.medusajs.com/resources/test-tools-reference/moduleIntegrationTestRunner/index.html.md). # Medusa Testing Tools @@ -6084,11 +6082,7 @@ The next chapters explain how to use the testing tools provided by `@medusajs/te In this guide, you'll learn the general steps to deploy your Medusa application. How you apply these steps depend on your chosen hosting provider or platform. -Find how-to guides for specific platforms in [this documentation](https://docs.medusajs.com/resources/deployment/index.html.md). - -Want Medusa to manage and maintain your infrastructure? [Sign up and learn more about Cloud](https://docs.medusajs.com/cloud/index.html.md) - -Cloud is our managed services offering that makes deploying and operating Medusa applications possible without having to worry about configuring, scaling, and maintaining infrastructure. Cloud hosts your server, Admin dashboard, database, and Redis instance. +Before deciding to self-host your Medusa application, consider reading the [Cloud vs. Self-Hosting comparison guide](https://docs.medusajs.com/cloud/comparison/index.html.md). By using Cloud, you can avoid the complexities and challenges of self-hosting, while benefiting from automated deployment, scaling, and maintenance. With Cloud, you also maintain full customization control as you deploy your own modules and customizations directly from GitHub: @@ -6099,7 +6093,7 @@ With Cloud, you also maintain full customization control as you deploy your own ### Prerequisites -- [Medusa application’s codebase hosted on GitHub repository.](undefined/learn) +- [Medusa application’s codebase hosted on GitHub repository.](https://docs.medusajs.com/learn/index.html.md) ## What You'll Deploy @@ -6107,7 +6101,7 @@ When you deploy the Medusa application, you need to deploy the following resourc 1. PostgreSQL database: This is the database that will hold your Medusa application's details. 2. Redis database: This is the database that will store the Medusa server's session. -3. Medusa application in [server and worker mode](undefined/learn/production/worker-mode), where: +3. Medusa application in [server and worker mode](https://docs.medusajs.com/learn/production/worker-mode/index.html.md), where: - The server mode handles incoming API requests and serving the Medusa Admin dashboard. - The worker mode handles background tasks, such as scheduled jobs and subscribers. @@ -6121,7 +6115,7 @@ So, when choosing a hosting provider, make sure it supports deploying these reso The `workerMode` configuration determines which mode the Medusa application runs in. When you deploy the Medusa application, you deploy two instances: one in server mode, and one in worker mode. -Learn more about worker mode in the [Worker Module chapter](undefined/learn/production/worker-mode). +Learn more about worker mode in the [Worker Module chapter](https://docs.medusajs.com/learn/production/worker-mode/index.html.md). So, add the following configuration in `medusa-config.ts`: @@ -6157,7 +6151,7 @@ Later, you’ll set different values of the `DISABLE_MEDUSA_ADMIN` environment v The `redisUrl` configuration specifies the connection URL to Redis to store the Medusa server's session. -Learn more in the [Medusa Configuration documentation](undefined/learn/configurations/medusa-config#redisurl). +Learn more in the [Medusa Configuration documentation](https://docs.medusajs.com/learn/configurations/medusa-config#redisurl/index.html.md). So, add the following configuration in `medusa-config.ts` : @@ -6193,13 +6187,13 @@ By default, your Medusa application uses modules and providers useful for develo It’s highly recommended to instead use modules and providers suitable for production, including: -- [Redis Cache Module](undefined/resources/infrastructure-modules/cache/redis) -- [Redis Event Bus Module](undefined/resources/infrastructure-modules/event/redis) -- [Workflow Engine Redis Module](undefined/resources/infrastructure-modules/workflow-engine/redis) -- [Redis Locking Module Provider](undefined/resources/infrastructure-modules/locking/redis) -- [PostHog Analytics Module Provider](undefined/resources/infrastructure-modules/analytics/posthog) (If you're using analytics in your application. You can also use other analytics module providers that are production-ready). -- [S3 File Module Provider](undefined/resources/infrastructure-modules/file/s3) (or other file module providers that are production-ready). -- [SendGrid Notification Module Provider](undefined/resources/infrastructure-modules/notification/sendgrid) (or other notification module providers that are production-ready). +- [Redis Cache Module](https://docs.medusajs.com/resources/infrastructure-modules/cache/redis/index.html.md) +- [Redis Event Bus Module](https://docs.medusajs.com/resources/infrastructure-modules/event/redis/index.html.md) +- [Workflow Engine Redis Module](https://docs.medusajs.com/resources/infrastructure-modules/workflow-engine/redis/index.html.md) +- [Redis Locking Module Provider](https://docs.medusajs.com/resources/infrastructure-modules/locking/redis/index.html.md) +- [PostHog Analytics Module Provider](https://docs.medusajs.com/resources/infrastructure-modules/analytics/posthog/index.html.md) (If you're using analytics in your application. You can also use other analytics module providers that are production-ready). +- [S3 File Module Provider](https://docs.medusajs.com/resources/infrastructure-modules/file/s3/index.html.md) (or other file module providers that are production-ready). +- [SendGrid Notification Module Provider](https://docs.medusajs.com/resources/infrastructure-modules/notification/sendgrid/index.html.md) (or other notification module providers that are production-ready). Then, add these modules in `medusa-config.ts`: @@ -6249,7 +6243,7 @@ module.exports = defineConfig({ }) ``` -Check out the [Integrations](undefined/resources/integrations) and [Infrastructure Modules](undefined/resources/infrastructure-modules) documentation for other modules and providers to use. +Check out the [Integrations](https://docs.medusajs.com/resources/integrations/index.html.md) and [Infrastructure Modules](https://docs.medusajs.com/resources/infrastructure-modules/index.html.md) documentation for other modules and providers to use. *** @@ -6457,7 +6451,7 @@ Instead, you should deploy two instances: You don’t need to set up different projects for each instance. Instead, you can configure the Medusa application to run in different modes based on environment variables. -Learn more about worker modes and how to configure them in the [Worker Mode chapter](undefined/learn/production/worker-mode). +Learn more about worker modes and how to configure them in the [Worker Mode chapter](https://docs.medusajs.com/learn/production/worker-mode/index.html.md). ### How to Deploy Medusa? @@ -6470,9 +6464,9 @@ With Cloud, you maintain full customization control as you deploy your own modul - Preview environments for new PRs. - Test on production-like data. -[Sign up and learn more about Cloud](undefined/cloud) +[Sign up and learn more about Cloud](https://docs.medusajs.com/cloud/index.html.md) -To self-host Medusa, the [next chapter](undefined/learn/deployment/general) explains the general steps to deploy your Medusa application. Refer to [this reference](undefined/resources/deployment) to find how-to deployment guides for general and specific hosting providers. +To self-host Medusa, the [next chapter](https://docs.medusajs.com/learn/deployment/general/index.html.md) explains the general steps to deploy your Medusa application. Refer to [this reference](https://docs.medusajs.com/resources/deployment/index.html.md) to find how-to deployment guides for general and specific hosting providers. *** @@ -6484,7 +6478,7 @@ If you’re using the Next.js Starter storefront, you may deploy the storefront Per Vercel’s [license and plans](https://vercel.com/pricing), their free plan can only be used for personal, non-commercial projects. So, you can deploy the storefront on the free plan for development purposes, but for commercial projects, you must update your Vercel plan. -Refer to [this reference](undefined/resources/deployment) to find how-to deployment guides for specific hosting providers. +Refer to [this reference](https://docs.medusajs.com/resources/deployment/index.html.md) to find how-to deployment guides for specific hosting providers. # Admin Development Constraints @@ -6536,7 +6530,7 @@ export const config = defineWidgetConfig({ In this chapter, you'll learn how to use environment variables in your admin customizations. -To learn how environment variables are generally loaded in Medusa based on your application's environment, check out [this chapter](undefined/learn/fundamentals/environment-variables). +To learn how environment variables are generally loaded in Medusa based on your application's environment, check out [this chapter](https://docs.medusajs.com/learn/fundamentals/environment-variables/index.html.md). ## How to Set Environment Variables @@ -6595,7 +6589,7 @@ declare const __STOREFRONT_URL__: string This file tells TypeScript to recognize the `import.meta.env` object and enhances the types of your custom environment variables. -Note that the `__BASE__`, `__BACKEND_URL__`, and `__STOREFRONT_URL__` variables are global variables available in your admin customizations. Learn more in the [Tips for Admin Customizations](undefined/learn/fundamentals/admin/tips#global-variables-in-admin-customizations) chapter. +Note that the `__BASE__`, `__BACKEND_URL__`, and `__STOREFRONT_URL__` variables are global variables available in your admin customizations. Learn more in the [Tips for Admin Customizations](https://docs.medusajs.com/learn/fundamentals/admin/tips#global-variables-in-admin-customizations/index.html.md) chapter. *** @@ -6624,9 +6618,9 @@ As explained in the [previous section](#environment-variables-in-production), en Instead, only the following global variable is available in plugins: -- `__BACKEND_URL__`: The URL of the Medusa backend, as set in the [Medusa configurations](undefined/learn/configurations/medusa-config#backendurl). +- `__BACKEND_URL__`: The URL of the Medusa backend, as set in the [Medusa configurations](https://docs.medusajs.com/learn/configurations/medusa-config#backendurl/index.html.md). - `__BASE__`: The base path of the Medusa Admin. (For example, `/app`). -- `__STOREFRONT_URL__`: The URL of the Medusa Storefront, as set in the [Medusa configurations](undefined/learn/configurations/medusa-config#storefronturl). +- `__STOREFRONT_URL__`: The URL of the Medusa Storefront, as set in the [Medusa configurations](https://docs.medusajs.com/learn/configurations/medusa-config#storefronturl/index.html.md). You can use those variables in your Medusa Admin customizations of a plugin. For example: @@ -6666,15 +6660,15 @@ declare const __STOREFRONT_URL__: string In this chapter, you'll learn about the Medusa Admin dashboard and the possible ways to customize it. -To explore the Medusa Admin's commerce features, check out the [User Guide](undefined/user-guide). These user guides are designed for merchants and provide the steps to perform any task within the Medusa Admin. +To explore the Medusa Admin's commerce features, check out the [User Guide](https://docs.medusajs.com/user-guide/index.html.md). These user guides are designed for merchants and provide the steps to perform any task within the Medusa Admin. ## What is the Medusa Admin? The Medusa Admin is an intuitive dashboard that allows merchants to manage their ecommerce store. It provides management features related to products, orders, customers, and more. -The Medusa Admin is built with [Vite v5](https://v5.vite.dev/). When you [install the Medusa application](undefined/learn/installation), you also install the Medusa Admin. Then, when you start the Medusa application, you can access the Medusa Admin at `http://localhost:9000/app`. +The Medusa Admin is built with [Vite v5](https://v5.vite.dev/). When you [install the Medusa application](https://docs.medusajs.com/learn/installation/index.html.md), you also install the Medusa Admin. Then, when you start the Medusa application, you can access the Medusa Admin at `http://localhost:9000/app`. -If you don't have an admin user, use the [Medusa CLI](undefined/resources/medusa-cli/commands/user) to create one. +If you don't have an admin user, use the [Medusa CLI](https://docs.medusajs.com/resources/medusa-cli/commands/user/index.html.md) to create one. *** @@ -6682,8 +6676,8 @@ If you don't have an admin user, use the [Medusa CLI](undefined/resources/medusa You can customize the Medusa Admin dashboard by: -- Adding new sections to existing pages using [Widgets](undefined/learn/fundamentals/admin/widgets). -- Adding new pages using [UI Routes](undefined/learn/fundamentals/admin/ui-routes). +- Adding new sections to existing pages using [Widgets](https://docs.medusajs.com/learn/fundamentals/admin/widgets/index.html.md). +- Adding new pages using [UI Routes](https://docs.medusajs.com/learn/fundamentals/admin/ui-routes/index.html.md). The next chapters will cover these two topics in detail. @@ -6691,7 +6685,7 @@ The next chapters will cover these two topics in detail. You can't customize the admin dashboard's layout, design, or the content of the existing pages (aside from injecting widgets). You also can't customize the login page, the authentication flow, or change the Medusa logo used in the admin dashboard. -If your use case requires heavy customization of the admin dashboard, you can build a custom admin dashboard using Medusa's [Admin API routes](undefined/api/admin). +If your use case requires heavy customization of the admin dashboard, you can build a custom admin dashboard using Medusa's [Admin API routes](https://docs.medusajs.com/api/admin). *** @@ -6705,7 +6699,7 @@ Refer to the [Medusa UI documentation](https://docs.medusajs.com/ui/index.html.m ## Admin Components List -To build admin customizations that match the Medusa Admin's designs and layouts, refer to [this guide](undefined/resources/admin-components) to find common components. +To build admin customizations that match the Medusa Admin's designs and layouts, refer to [this guide](https://docs.medusajs.com/resources/admin-components/index.html.md) to find common components. # Admin Routing Customizations @@ -6752,9 +6746,9 @@ Route loaders are available starting from Medusa v2.5.1. In your UI routes and settings pages, you may need to retrieve data to use in your route component. For example, you may want to fetch a list of products to display on a custom page. -The recommended approach is to fetch data within the UI route component asynchronously using the JS SDK with Tanstack (React) Query as explained in [this chapter](undefined/learn/fundamentals/admin/tips#send-requests-to-api-routes). +The recommended approach is to fetch data within the UI route component asynchronously using the JS SDK with Tanstack (React) Query as explained in [this chapter](https://docs.medusajs.com/learn/fundamentals/admin/tips#send-requests-to-api-routes/index.html.md). -However, if you need the data to be fetched before the route is rendered, such as if you're [setting breadcrumbs dynamically](undefined/learn/fundamentals/admin/ui-routes#set-breadcrumbs-dynamically), you can use a route loader. +However, if you need the data to be fetched before the route is rendered, such as if you're [setting breadcrumbs dynamically](https://docs.medusajs.com/learn/fundamentals/admin/ui-routes#set-breadcrumbs-dynamically/index.html.md), you can use a route loader. To fetch data with a route loader: @@ -6802,7 +6796,7 @@ Then, in the `CustomPage` route component, you use the `useLoaderData` hook from Route loaders block the rendering of your UI route until the data is fetched, which may negatively impact the user experience. So, only use route loaders when the route component needs essential data before rendering, or if you're preparing data that doesn't require sending API requests. -Otherwise, use the JS SDK with Tanstack (React) Query in the UI route component as explained in the [Tips](undefined/learn/fundamentals/admin/tips#send-requests-to-api-routes) chapter to fetch data asynchronously and update the UI when the data is available. +Otherwise, use the JS SDK with Tanstack (React) Query in the UI route component as explained in the [Tips](https://docs.medusajs.com/learn/fundamentals/admin/tips#send-requests-to-api-routes/index.html.md) chapter to fetch data asynchronously and update the UI when the data is available. ![Timeline comparison of a UI route with and without a route loader](https://res.cloudinary.com/dza7lstvk/image/upload/v1753428567/Medusa%20Book/ui-route-loading_vycev8.jpg) @@ -6865,7 +6859,7 @@ export const handle = { } ``` -You can also use the `handle` object to define a breadcrumb for the route. Learn more in the [UI Route](undefined/learn/fundamentals/admin/ui-routes) chapter. +You can also use the `handle` object to define a breadcrumb for the route. Learn more in the [UI Route](https://docs.medusajs.com/learn/fundamentals/admin/ui-routes/index.html.md) chapter. ### React Router Components and Hooks @@ -6878,7 +6872,7 @@ In this chapter, you'll find some tips for developing your admin. ## Send Requests to API Routes -To send a request to an API route in the Medusa Application, use Medusa's [JS SDK](undefined/resources/js-sdk) with [Tanstack Query](https://tanstack.com/query/latest). Both of these tools are installed in your project by default. +To send a request to an API route in the Medusa Application, use Medusa's [JS SDK](https://docs.medusajs.com/resources/js-sdk/index.html.md) with [Tanstack Query](https://tanstack.com/query/latest). Both of these tools are installed in your project by default. Do not install Tanstack Query as that will cause unexpected errors in your development. If you prefer installing it for better auto-completion in your code editor, make sure to install `v5.64.2` as a development dependency. @@ -6911,9 +6905,9 @@ export const sdk = new Medusa({ }) ``` -Notice that in a Medusa project, you use `import.meta.env` to access environment variables in your customizations, whereas in a plugin you use the global variable `__BACKEND_URL__` to access the backend URL. You can learn more in the [Admin Environment Variables](undefined/learn/fundamentals/admin/environment-variables) chapter. +Notice that in a Medusa project, you use `import.meta.env` to access environment variables in your customizations, whereas in a plugin you use the global variable `__BACKEND_URL__` to access the backend URL. You can learn more in the [Admin Environment Variables](https://docs.medusajs.com/learn/fundamentals/admin/environment-variables/index.html.md) chapter. -Refer to the [JS SDK](undefined/resources/js-sdk#js-sdk-configurations) reference for more details on the SDK's configurations. +Refer to the [JS SDK](https://docs.medusajs.com/resources/js-sdk#js-sdk-configurations/index.html.md) reference for more details on the SDK's configurations. Then, use the configured SDK with the `useQuery` Tanstack Query hook to send `GET` requests, and the `useMutation` hook to send `POST` or `DELETE` requests. @@ -6992,11 +6986,11 @@ export const config = defineWidgetConfig({ export default ProductWidget ``` -You can also send requests to custom routes, as explained in the [JS SDK reference](undefined/resources/js-sdk). +You can also send requests to custom routes, as explained in the [JS SDK reference](https://docs.medusajs.com/resources/js-sdk/index.html.md). ### Use Route Loaders for Initial Data -You may need to retrieve data before your component is rendered, or you may need to pass some initial data to your component to be used while data is being fetched. In those cases, you can use a [route loader](undefined/learn/fundamentals/admin/routing). +You may need to retrieve data before your component is rendered, or you may need to pass some initial data to your component to be used while data is being fetched. In those cases, you can use a [route loader](https://docs.medusajs.com/learn/fundamentals/admin/routing/index.html.md). ### Troubleshooting @@ -7018,9 +7012,9 @@ Learn more in the [Errors with pnpm](https://docs.medusajs.com/resources/trouble In your admin customizations, you can use the following global variables: -- `__BASE__`: The base path of the Medusa Admin, as set in the [admin.path](undefined/learn/configurations/medusa-config#path) configuration in `medusa-config.ts`. -- `__BACKEND_URL__`: The URL to the Medusa backend, as set in the [admin.backendUrl](undefined/learn/configurations/medusa-config#backendurl) configuration in `medusa-config.ts`. -- `__STOREFRONT_URL__`: The URL to the storefront, as set in the [admin.storefrontUrl](undefined/learn/configurations/medusa-config#storefrontUrl) configuration in `medusa-config.ts`. +- `__BASE__`: The base path of the Medusa Admin, as set in the [admin.path](https://docs.medusajs.com/learn/configurations/medusa-config#path/index.html.md) configuration in `medusa-config.ts`. +- `__BACKEND_URL__`: The URL to the Medusa backend, as set in the [admin.backendUrl](https://docs.medusajs.com/learn/configurations/medusa-config#backendurl/index.html.md) configuration in `medusa-config.ts`. +- `__STOREFRONT_URL__`: The URL to the storefront, as set in the [admin.storefrontUrl](https://docs.medusajs.com/learn/configurations/medusa-config#storefrontUrl/index.html.md) configuration in `medusa-config.ts`. If you get type errors while using these variables, create the file `src/admin/vite-env.d.ts` with the following content: @@ -7038,7 +7032,7 @@ declare const __STOREFRONT_URL__: string The Medusa Admin dashboard can be displayed in languages other than English, which is the default. Other languages are added through community contributions. -Learn how to add a new language translation for the Medusa Admin in [this guide](undefined/learn/resources/contribution-guidelines/admin-translations). +Learn how to add a new language translation for the Medusa Admin in [this guide](https://docs.medusajs.com/learn/resources/contribution-guidelines/admin-translations/index.html.md). # Admin UI Routes @@ -7051,7 +7045,7 @@ The Medusa Admin dashboard is customizable, allowing you to add new pages, calle For example, you can add a new page to show and manage product reviews, which aren't available natively in Medusa. -You can create a UI route directly in your Medusa application, or in a [plugin](undefined/learn/fundamentals/plugins) if you want to share the UI route across multiple Medusa applications. +You can create a UI route directly in your Medusa application, or in a [plugin](https://docs.medusajs.com/learn/fundamentals/plugins/index.html.md) if you want to share the UI route across multiple Medusa applications. *** @@ -7059,7 +7053,7 @@ You can create a UI route directly in your Medusa application, or in a [plugin]( ### Prerequisites -- [Medusa application installed](undefined/learn/installation) +- [Medusa application installed](https://docs.medusajs.com/learn/installation/index.html.md) You create a UI route in a `page.tsx` file under a sub-directory of `src/admin/routes` directory. The file's path relative to `src/admin/routes` determines its path in the dashboard. The file’s default export must be the UI route’s React component. @@ -7085,7 +7079,7 @@ export default CustomPage You add a new route at `http://localhost:9000/app/custom`. The `CustomPage` component holds the page's content, which currently only shows a heading. -In the route, you use [Medusa UI](undefined/ui), a package that Medusa maintains to allow you to customize the dashboard with the same components used to build it. +In the route, you use [Medusa UI](https://docs.medusajs.com/ui/index.html.md), a package that Medusa maintains to allow you to customize the dashboard with the same components used to build it. The UI route component must be created as an arrow function. @@ -7133,7 +7127,7 @@ The configuration object is created using `defineRouteConfig` from the Medusa Fr - `label`: the sidebar item’s label. - `icon`: an optional React component used as an icon in the sidebar. -The above example adds a new sidebar item with the label `Custom Route` and an icon from the [Medusa UI Icons package](undefined/ui/icons/overview). +The above example adds a new sidebar item with the label `Custom Route` and an icon from the [Medusa UI Icons package](https://docs.medusajs.com/ui/icons/overview/index.html.md). ### Nested UI Routes @@ -7382,19 +7376,19 @@ Then, in the `handle.breadcrumb` function, you receive `data` prop containing th When you open the UI route at `http://localhost:9000/app/brands/123`, the breadcrumb will show the brand's name, such as `Acme`. -You also use the `useLoaderData` hook to access the data returned by the `loader` function in the UI route component. Learn more in the [Routing Customizations](undefined/learn/fundamentals/admin/routing#fetch-data-with-route-loaders) chapter. +You also use the `useLoaderData` hook to access the data returned by the `loader` function in the UI route component. Learn more in the [Routing Customizations](https://docs.medusajs.com/learn/fundamentals/admin/routing#fetch-data-with-route-loaders/index.html.md) chapter. *** ## Admin Components List -To build admin customizations that match the Medusa Admin's designs and layouts, refer to [this guide](undefined/resources/admin-components) to find common components. +To build admin customizations that match the Medusa Admin's designs and layouts, refer to [this guide](https://docs.medusajs.com/resources/admin-components/index.html.md) to find common components. *** ## More Routes Customizations -For more customizations related to routes, refer to the [Routing Customizations chapter](undefined/learn/fundamentals/admin/routing). +For more customizations related to routes, refer to the [Routing Customizations chapter](https://docs.medusajs.com/learn/fundamentals/admin/routing/index.html.md). # Admin Widgets @@ -7407,7 +7401,7 @@ The Medusa Admin's pages are customizable for inserting widgets of custom conten You create these widgets as React components that render the content and functionality of the widget. -You can create an admin widget directly in your Medusa application, or in a [plugin](undefined/learn/fundamentals/plugins) if you want to share the widget across multiple Medusa applications. +You can create an admin widget directly in your Medusa application, or in a [plugin](https://docs.medusajs.com/learn/fundamentals/plugins/index.html.md) if you want to share the widget across multiple Medusa applications. *** @@ -7415,7 +7409,7 @@ You can create an admin widget directly in your Medusa application, or in a [plu ### Prerequisites -- [Medusa application installed](undefined/learn/installation) +- [Medusa application installed](https://docs.medusajs.com/learn/installation/index.html.md) You create a widget in a `.tsx` file under the `src/admin/widgets` directory. The file must export: @@ -7451,7 +7445,7 @@ export default ProductWidget In the example above, the widget is injected at the top of a product’s details. -You export the `ProductWidget` component, which displays the heading `Product Widget`. In the widget, you use [Medusa UI](undefined/ui) to customize the dashboard with the same components used to build it. +You export the `ProductWidget` component, which displays the heading `Product Widget`. In the widget, you use [Medusa UI](https://docs.medusajs.com/ui/index.html.md) to customize the dashboard with the same components used to build it. To export the widget's configuration, you use `defineWidgetConfig` from the Admin Extension SDK. It accepts an object as a parameter with the `zone` property, whose value is a string or an array of strings, each being the name of the zone to inject the widget into. @@ -7512,15 +7506,15 @@ The props type is `DetailWidgetProps`, and it accepts as a type argument the exp ## Injection Zones List -Refer to the [Admin Widget Injection Zones](undefined/resources/admin-widget-injection-zones) reference for the full list of injection zones and their props. +Refer to the [Admin Widget Injection Zones](https://docs.medusajs.com/resources/admin-widget-injection-zones/index.html.md) reference for the full list of injection zones and their props. *** ## Admin Components List -While the Medusa Admin uses the [Medusa UI](undefined/ui) components, it also expands on them for styling and design purposes. +While the Medusa Admin uses the [Medusa UI](https://docs.medusajs.com/ui/index.html.md) components, it also expands on them for styling and design purposes. -To build admin customizations that match the Medusa Admin's designs and layouts, refer to the [Admin Components](undefined/resources/admin-components) guide. You'll find components like `Header`, `JSON View`, and more that match the Medusa Admin's design. +To build admin customizations that match the Medusa Admin's designs and layouts, refer to the [Admin Components](https://docs.medusajs.com/resources/admin-components/index.html.md) guide. You'll find components like `Header`, `JSON View`, and more that match the Medusa Admin's design. *** @@ -7578,40 +7572,40 @@ Some of Medusa's API Routes accept an `additional_data` parameter whose type is This is useful when you have a link from your custom module to a Commerce Module, and you want to perform an additional action when a request is sent to an existing API route. -For example, the [Create Product API Route](undefined/api/admin#products_postproducts) accepts an `additional_data` parameter. If you have a data model linked to it, you consume the `productsCreated` hook to create a record of the data model using the custom data and link it to the product. +For example, the [Create Product API Route](https://docs.medusajs.com/api/admin#products_postproducts) accepts an `additional_data` parameter. If you have a data model linked to it, you consume the `productsCreated` hook to create a record of the data model using the custom data and link it to the product. ### API Routes Accepting Additional Data ### API Routes List - Campaigns - - [Create Campaign](undefined/api/admin#campaigns_postcampaigns) - - [Update Campaign](undefined/api/admin#campaigns_postcampaignsid) + - [Create Campaign](https://docs.medusajs.com/api/admin#campaigns_postcampaigns) + - [Update Campaign](https://docs.medusajs.com/api/admin#campaigns_postcampaignsid) - Cart - - [Create Cart](undefined/api/store#carts_postcarts) - - [Update Cart](undefined/api/store#carts_postcartsid) + - [Create Cart](https://docs.medusajs.com/api/store#carts_postcarts) + - [Update Cart](https://docs.medusajs.com/api/store#carts_postcartsid) - Collections - [Create Collection](https://docs.medusajs.com/api/admin#collections_postcollections) - [Update Collection](https://docs.medusajs.com/api/admin#collections_postcollectionsid) - Customers - - [Create Customer](undefined/api/admin#customers_postcustomers) - - [Update Customer](undefined/api/admin#customers_postcustomersid) - - [Create Address](undefined/api/admin#customers_postcustomersidaddresses) - - [Update Address](undefined/api/admin#customers_postcustomersidaddressesaddress_id) + - [Create Customer](https://docs.medusajs.com/api/admin#customers_postcustomers) + - [Update Customer](https://docs.medusajs.com/api/admin#customers_postcustomersid) + - [Create Address](https://docs.medusajs.com/api/admin#customers_postcustomersidaddresses) + - [Update Address](https://docs.medusajs.com/api/admin#customers_postcustomersidaddressesaddress_id) - Draft Orders - - [Create Draft Order](undefined/api/admin#draft-orders_postdraftorders) + - [Create Draft Order](https://docs.medusajs.com/api/admin#draft-orders_postdraftorders) - Orders - - [Complete Orders](undefined/api/admin#orders_postordersidcomplete) - - [Cancel Order's Fulfillment](undefined/api/admin#orders_postordersidfulfillmentsfulfillment_idcancel) - - [Create Shipment](undefined/api/admin#orders_postordersidfulfillmentsfulfillment_idshipments) - - [Create Fulfillment](undefined/api/admin#orders_postordersidfulfillments) + - [Complete Orders](https://docs.medusajs.com/api/admin#orders_postordersidcomplete) + - [Cancel Order's Fulfillment](https://docs.medusajs.com/api/admin#orders_postordersidfulfillmentsfulfillment_idcancel) + - [Create Shipment](https://docs.medusajs.com/api/admin#orders_postordersidfulfillmentsfulfillment_idshipments) + - [Create Fulfillment](https://docs.medusajs.com/api/admin#orders_postordersidfulfillments) - Products - - [Create Product](undefined/api/admin#products_postproducts) - - [Update Product](undefined/api/admin#products_postproductsid) - - [Create Product Variant](undefined/api/admin#products_postproductsidvariants) - - [Update Product Variant](undefined/api/admin#products_postproductsidvariantsvariant_id) - - [Create Product Option](undefined/api/admin#products_postproductsidoptions) - - [Update Product Option](undefined/api/admin#products_postproductsidoptionsoption_id) + - [Create Product](https://docs.medusajs.com/api/admin#products_postproducts) + - [Update Product](https://docs.medusajs.com/api/admin#products_postproductsid) + - [Create Product Variant](https://docs.medusajs.com/api/admin#products_postproductsidvariants) + - [Update Product Variant](https://docs.medusajs.com/api/admin#products_postproductsidvariantsvariant_id) + - [Create Product Option](https://docs.medusajs.com/api/admin#products_postproductsidoptions) + - [Update Product Option](https://docs.medusajs.com/api/admin#products_postproductsidoptionsoption_id) - Product Tags - [Create Product Tag](https://docs.medusajs.com/api/admin#product-tags_postproducttags) - [Update Product Tag](https://docs.medusajs.com/api/admin#product-tags_postproducttagsid) @@ -7619,8 +7613,8 @@ For example, the [Create Product API Route](undefined/api/admin#products_postpro - [Create Product Type](https://docs.medusajs.com/api/admin#product-types_postproducttypes) - [Update Product Type](https://docs.medusajs.com/api/admin#product-types_postproducttypesid) - Promotions - - [Create Promotion](undefined/api/admin#promotions_postpromotions) - - [Update Promotion](undefined/api/admin#promotions_postpromotionsid) + - [Create Promotion](https://docs.medusajs.com/api/admin#promotions_postpromotions) + - [Update Promotion](https://docs.medusajs.com/api/admin#promotions_postpromotionsid) *** @@ -7692,7 +7686,7 @@ The `additional_data` is then passed to hooks in the `createProductsWorkflow` us ## Use Additional Data in a Hook -Learn about workflow hooks in [this guide](undefined/learn/fundamentals/workflows/workflow-hooks). +Learn about workflow hooks in [this guide](https://docs.medusajs.com/learn/fundamentals/workflows/workflow-hooks/index.html.md). Step functions consuming the workflow hook can access the `additional_data` in the first parameter. @@ -7799,7 +7793,7 @@ module.exports = defineConfig({ This allows the `http://localhost:7001` origin to access the Admin API Routes, and the `http://localhost:8000` origin to access Store API Routes. -Learn more about the CORS configurations in [this resource guide](undefined/learn/configurations/medusa-config#http). +Learn more about the CORS configurations in [this resource guide](https://docs.medusajs.com/learn/configurations/medusa-config#http/index.html.md). *** @@ -8192,10 +8186,10 @@ Received a request! Middlewares are useful for: -- [Protecting API routes](undefined/learn/fundamentals/api-routes/protected-routes) to ensure that only authenticated users can access them. -- [Validating](undefined/learn/fundamentals/api-routes/validation) request query and body parameters. -- [Parsing](undefined/learn/fundamentals/api-routes/parse-body) request content types other than `application/json`. -- [Applying CORS](undefined/learn/fundamentals/api-routes/cors) configurations to custom API routes. +- [Protecting API routes](https://docs.medusajs.com/learn/fundamentals/api-routes/protected-routes/index.html.md) to ensure that only authenticated users can access them. +- [Validating](https://docs.medusajs.com/learn/fundamentals/api-routes/validation/index.html.md) request query and body parameters. +- [Parsing](https://docs.medusajs.com/learn/fundamentals/api-routes/parse-body/index.html.md) request content types other than `application/json`. +- [Applying CORS](https://docs.medusajs.com/learn/fundamentals/api-routes/cors/index.html.md) configurations to custom API routes. *** @@ -8440,13 +8434,13 @@ A middleware can not override an existing middleware. Instead, middlewares are a For example, if you define a custom validation middleware, such as `validateAndTransformBody`, on an existing route, then both the original and the custom validation middleware will run. -Similarly, if you add an [authenticate](undefined/learn/fundamentals/api-routes/protected-routes#protect-custom-api-routes) middleware to an existing route, both the original and the custom authentication middleware will run. So, you can't override the original authentication middleware. +Similarly, if you add an [authenticate](https://docs.medusajs.com/learn/fundamentals/api-routes/protected-routes#protect-custom-api-routes/index.html.md) middleware to an existing route, both the original and the custom authentication middleware will run. So, you can't override the original authentication middleware. ### Alternative Solution to Overriding Middlewares -If you need to change the middlewares applied to a route, you can create a custom [API route](undefined/learn/fundamentals/api-routes) that executes the same functionality as the original route, but with the middlewares you want. +If you need to change the middlewares applied to a route, you can create a custom [API route](https://docs.medusajs.com/learn/fundamentals/api-routes/index.html.md) that executes the same functionality as the original route, but with the middlewares you want. -Learn more in the [Override API Routes](undefined/learn/fundamentals/api-routes/override) chapter. +Learn more in the [Override API Routes](https://docs.medusajs.com/learn/fundamentals/api-routes/override/index.html.md) chapter. # Override API Routes @@ -8480,7 +8474,7 @@ By replicating instead of overriding, the original API route remains intact, all ## How to Replicate an API Route? -Medusa's API routes are generally slim and use logic contained in [workflows](undefined/learn/fundamentals/workflows). So, creating a custom route based on the original route is straightforward. +Medusa's API routes are generally slim and use logic contained in [workflows](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md). So, creating a custom route based on the original route is straightforward. You can view the source code for Medusa's API routes in the [Medusa GitHub repository](https://github.com/medusajs/medusa/tree/develop/packages/medusa/src/api). @@ -8508,7 +8502,7 @@ In this chapter, you’ll learn what API routes are and how to create them. An API route is a REST endpoint that exposes commerce features to external applications, such as storefronts, the admin dashboard, or third-party systems. -The Medusa core application provides a set of [admin](undefined/api/admin) and [store](undefined/api/store) API routes out-of-the-box. You can also create custom API routes to expose your custom functionalities. +The Medusa core application provides a set of [admin](https://docs.medusajs.com/api/admin) and [store](https://docs.medusajs.com/api/store) API routes out-of-the-box. You can also create custom API routes to expose your custom functionalities. *** @@ -8651,7 +8645,7 @@ The value of `req.query.name` is the value passed in `?name=John`, for example. You can apply validation rules on received query parameters to ensure they match specified rules and types. -Learn more in the [API Route Validation](undefined/learn/fundamentals/api-routes/validation#how-to-validate-request-query-parameters) chapter. +Learn more in the [API Route Validation](https://docs.medusajs.com/learn/fundamentals/api-routes/validation#how-to-validate-request-query-parameters/index.html.md) chapter. *** @@ -8659,7 +8653,7 @@ Learn more in the [API Route Validation](undefined/learn/fundamentals/api-routes The Medusa application parses the body of any request with JSON, URL-encoded, or text content types. The request body parameters are set in the `MedusaRequest`'s `body` property. -Learn more about configuring body parsing in the [Body Parsing](undefined/learn/fundamentals/api-routes/parse-body) chapter. +Learn more about configuring body parsing in the [Body Parsing](https://docs.medusajs.com/learn/fundamentals/api-routes/parse-body/index.html.md) chapter. For example: @@ -8709,7 +8703,7 @@ This returns the following JSON object: You can apply validation rules on received body parameters to ensure they match specified rules and types. -Learn more in the [Body Validation](undefined/learn/fundamentals/api-routes/validation#how-to-validate-request-body) chapter. +Learn more in the [Body Validation](https://docs.medusajs.com/learn/fundamentals/api-routes/validation#how-to-validate-request-body/index.html.md) chapter. # Configure Request Body Parser @@ -8746,7 +8740,7 @@ export default defineMiddlewares({ The middleware route object passed to `routes` accepts a `bodyParser` property, whose value is a configuration object for the default body parser. By enabling the `preserveRawBody` property, the raw body data is preserved and stored in the `req.rawBody` property. -Learn more about [middlewares](undefined/learn/fundamentals/api-routes/middlewares). +Learn more about [middlewares](https://docs.medusajs.com/learn/fundamentals/api-routes/middlewares/index.html.md). You can then access the raw body data in your API route handler: @@ -8792,11 +8786,11 @@ The `sizeLimit` property accepts one of the following types of values: ### Overriding Request Body Size Limit -You can't override the request body size limit for existing routes, such as Medusa's Store and Admin API routes, due to how [middlewares are applied](undefined/learn/fundamentals/api-routes/middlewares#how-are-middlewares-ordered-and-applied). +You can't override the request body size limit for existing routes, such as Medusa's Store and Admin API routes, due to how [middlewares are applied](https://docs.medusajs.com/learn/fundamentals/api-routes/middlewares#how-are-middlewares-ordered-and-applied/index.html.md). -If you need to override the request body size limit for a specific route, you can create a custom [API route](undefined/learn/fundamentals/api-routes) that executes the same functionality as the original route, but with the body size limit you need. +If you need to override the request body size limit for a specific route, you can create a custom [API route](https://docs.medusajs.com/learn/fundamentals/api-routes/index.html.md) that executes the same functionality as the original route, but with the body size limit you need. -Learn more in the [Override API Routes](undefined/learn/fundamentals/api-routes/override) chapter. +Learn more in the [Override API Routes](https://docs.medusajs.com/learn/fundamentals/api-routes/override/index.html.md) chapter. *** @@ -8873,7 +8867,7 @@ export async function POST( The uploaded files are stored in the `req.files` property as an array of Multer file objects that have properties like `filename` and `mimetype`. -To upload the files, you can use the [uploadFilesWorkflow](undefined/resources/references/medusa-workflows/uploadFilesWorkflow), which uploads the files using the configured [File Module Provider](undefined/resources/infrastructure-modules/file). +To upload the files, you can use the [uploadFilesWorkflow](https://docs.medusajs.com/resources/references/medusa-workflows/uploadFilesWorkflow/index.html.md), which uploads the files using the configured [File Module Provider](https://docs.medusajs.com/resources/infrastructure-modules/file/index.html.md). ### Test API Route @@ -8912,7 +8906,7 @@ A protected API route is an API route that requires requests to be user-authenti Protected API routes are useful for routes that require user authentication, such as creating a product or managing an order. These routes must only be accessed by authenticated admin users. -Refer to the API Reference for [Admin](undefined/api/admin#authentication) and [Store](undefined/api/store#authentication) to learn how to send authenticated requests. +Refer to the API Reference for [Admin](https://docs.medusajs.com/api/admin#authentication) and [Store](https://docs.medusajs.com/api/store#authentication) to learn how to send authenticated requests. *** @@ -8925,7 +8919,7 @@ Any API route, including your custom API routes, are protected if they start wit |\`/admin\`|Only authenticated admin users can access.| |\`/store/customers/me\`|Only authenticated customers can access.| -Refer to the API Reference for [Admin](undefined/api/admin#authentication) and [Store](undefined/api/store#authentication) to learn how to send authenticated requests. +Refer to the API Reference for [Admin](https://docs.medusajs.com/api/admin#authentication) and [Store](https://docs.medusajs.com/api/store#authentication) to learn how to send authenticated requests. ### Opt-Out of Default Authentication Requirement @@ -8957,7 +8951,7 @@ Now, any request sent to the `/admin/custom` API route is allowed, regardless if ## Protect Custom API Routes -You can protect API routes using the `authenticate` [middleware](undefined/learn/fundamentals/api-routes/middlewares) from the Medusa Framework. When applied to a route, the middleware checks that: +You can protect API routes using the `authenticate` [middleware](https://docs.medusajs.com/learn/fundamentals/api-routes/middlewares/index.html.md) from the Medusa Framework. When applied to a route, the middleware checks that: - The correct actor type (for example, `user`, `customer`, or a custom actor type) is authenticated. - The correct authentication method is used (for example, `session`, `bearer`, or `api-key`). @@ -8990,7 +8984,7 @@ The `authenticate` middleware function accepts three parameters: 2. An array of types of authentication methods allowed. Both `user` and `customer` scopes support `session` and `bearer`. The `admin` scope also supports the `api-key` authentication method. 3. An optional object of configurations accepting the following properties: - `allowUnauthenticated`: (default: `false`) A boolean indicating whether authentication is required. For example, you may have an API route where you want to access the logged-in customer if available, but guest customers can still access it too. - - `allowUnregistered` (default: `false`): A boolean indicating whether users can access this route with a registration token, instead of an authentication token. This is useful if you have a custom actor type, such as `manager`, and you're creating an API route that allows these users to register themselves. Learn more in the [Custom Actor-Type Guide](undefined/resources/commerce-modules/auth/create-actor-type). + - `allowUnregistered` (default: `false`): A boolean indicating whether users can access this route with a registration token, instead of an authentication token. This is useful if you have a custom actor type, such as `manager`, and you're creating an API route that allows these users to register themselves. Learn more in the [Custom Actor-Type Guide](https://docs.medusajs.com/resources/commerce-modules/auth/create-actor-type/index.html.md). ### Example: Custom Actor Type @@ -9012,7 +9006,7 @@ export default defineMiddlewares({ }) ``` -Refer to the [Custom Actor-Type Guide](undefined/resources/commerce-modules/auth/create-actor-type) for detailed explanation on how to create a custom actor type and apply authentication middlewares. +Refer to the [Custom Actor-Type Guide](https://docs.medusajs.com/resources/commerce-modules/auth/create-actor-type/index.html.md) for detailed explanation on how to create a custom actor type and apply authentication middlewares. ### Example: Allow Multiple Actor Types @@ -9038,9 +9032,9 @@ export default defineMiddlewares({ In some cases, you may want to override the authentication requirement for Medusa's API routes. For example, you may want to allow custom actor types to access existing protected API routes. -It's not possible to change the [authentication middleware](undefined/learn/fundamentals/api-routes/middlewares) applied to an existing API route. Instead, you need to replicate the API route and apply the authentication middleware to it. +It's not possible to change the [authentication middleware](https://docs.medusajs.com/learn/fundamentals/api-routes/middlewares/index.html.md) applied to an existing API route. Instead, you need to replicate the API route and apply the authentication middleware to it. -Learn more in the [Override API Routes](undefined/learn/fundamentals/api-routes/override) chapter. +Learn more in the [Override API Routes](https://docs.medusajs.com/learn/fundamentals/api-routes/override/index.html.md) chapter. *** @@ -9088,7 +9082,7 @@ If you opt-out of authentication in a route as mentioned in the [Opt-Out section ### Retrieve Logged-In Customer's Details -You can access the logged-in customer’s ID in all API routes starting with `/store` using the `auth_context.actor_id` property of the `AuthenticatedMedusaRequest` object. You can then use [Query](undefined/learn/fundamentals/module-links/query) to retrieve the customer details, or pass the ID to a [workflow](undefined/learn/fundamentals/workflows) that performs business logic. +You can access the logged-in customer’s ID in all API routes starting with `/store` using the `auth_context.actor_id` property of the `AuthenticatedMedusaRequest` object. You can then use [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md) to retrieve the customer details, or pass the ID to a [workflow](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) that performs business logic. For example: @@ -9119,7 +9113,7 @@ export const GET = async ( } ``` -In this example, you retrieve the customer's ID and resolve Query from the [Medusa container](undefined/learn/fundamentals/medusa-container). +In this example, you retrieve the customer's ID and resolve Query from the [Medusa container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md). Then, you use Query to retrieve the customer details. The `throwIfKeyNotFound` option throws an error if the customer with the specified ID is not found. @@ -9127,7 +9121,7 @@ After that, you can use the customer's details in your API route. ### Retrieve Logged-In Admin User's Details -You can access the logged-in admin user’s ID in all API routes starting with `/admin` using the `auth_context.actor_id` property of the `AuthenticatedMedusaRequest` object. You can then use [Query](undefined/learn/fundamentals/module-links/query) to retrieve the user details, or pass the ID to a [workflow](undefined/learn/fundamentals/workflows) that performs business logic. +You can access the logged-in admin user’s ID in all API routes starting with `/admin` using the `auth_context.actor_id` property of the `AuthenticatedMedusaRequest` object. You can then use [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md) to retrieve the user details, or pass the ID to a [workflow](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) that performs business logic. For example: @@ -9158,7 +9152,7 @@ export const GET = async ( } ``` -In this example, you retrieve the admin user's ID and resolve Query from the [Medusa container](undefined/learn/fundamentals/medusa-container). +In this example, you retrieve the admin user's ID and resolve Query from the [Medusa container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md). Then, you use Query to retrieve the user details. The `throwIfKeyNotFound` option throws an error if the user with the specified ID is not found. @@ -9313,7 +9307,7 @@ This API route opens a stream by setting the `Content-Type` to `text/event-strea The JS SDK has a `fetchStream` method that you can use to fetch data from an API route that returns a stream. -Learn more in the [JS SDK](undefined/resources/js-sdk) documentation. +Learn more in the [JS SDK](https://docs.medusajs.com/resources/js-sdk/index.html.md) documentation. *** @@ -9330,9 +9324,9 @@ In this chapter, you'll learn how to retrieve custom data models linked to exist Often, you'll link custom data models to existing Medusa data models to implement custom features or expand on existing ones. -For example, to add brands for products, you can create a `Brand` data model in a Brand Module, then [define a link](undefined/learn/fundamentals/module-links) to the [Product Module](undefined/resources/commerce-modules/product)'s `Product` data model. +For example, to add brands for products, you can create a `Brand` data model in a Brand Module, then [define a link](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md) to the [Product Module](https://docs.medusajs.com/resources/commerce-modules/product/index.html.md)'s `Product` data model. -When you implement this customization, you might need to retrieve the brand of a product using the existing [Get Product API Route](undefined/api/admin#products_getproductsid). You can do this by passing the linked data model's name in the `fields` query parameter of the API route. +When you implement this customization, you might need to retrieve the brand of a product using the existing [Get Product API Route](https://docs.medusajs.com/api/admin#products_getproductsid). You can do this by passing the linked data model's name in the `fields` query parameter of the API route. *** @@ -9340,14 +9334,14 @@ When you implement this customization, you might need to retrieve the brand of a Most of Medusa's API routes accept a `fields` query parameter that allows you to specify the fields and relations to retrieve in the resource, such as a product. -For example, to retrieve the brand of a product, you can pass the `brand` field in the `fields` query parameter of the [Get Product API Route](undefined/api/admin#products_getproductsid): +For example, to retrieve the brand of a product, you can pass the `brand` field in the `fields` query parameter of the [Get Product API Route](https://docs.medusajs.com/api/admin#products_getproductsid): ```bash curl 'http://localhost:9000/admin/products/{id}?fields=*brand' \ -H 'Authorization: Bearer {access_token}' ``` -The `fields` query parameter accepts a comma-separated list of fields and relations to retrieve. To learn more about using the `fields` query parameter, refer to the [API Reference](undefined/api/store#select-fields-and-relations). +The `fields` query parameter accepts a comma-separated list of fields and relations to retrieve. To learn more about using the `fields` query parameter, refer to the [API Reference](https://docs.medusajs.com/api/store#select-fields-and-relations). By prefixing `brand` with an asterisk (`*`), you retrieve all the default fields of the product, including the `brand` field. If you don't include the `*` prefix, the response will only include the product's brand. @@ -9359,17 +9353,17 @@ Some of Medusa's API routes restrict the fields and relations you can retrieve, The API routes that restrict the fields and relations you can retrieve are: -- [Customer Store API Routes](undefined/api/store#customers) -- [Customer Admin API Routes](undefined/api/admin#customers) -- [Product Category Admin API Routes](undefined/api/admin#product-categories) +- [Customer Store API Routes](https://docs.medusajs.com/api/store#customers) +- [Customer Admin API Routes](https://docs.medusajs.com/api/admin#customers) +- [Product Category Admin API Routes](https://docs.medusajs.com/api/admin#product-categories) ### How to Override Allowed Fields and Relations -For these routes, you need to override the allowed fields and relations to be retrieved. You can do this by applying a [global middleware](undefined/learn/fundamentals/api-routes/middlewares) to those routes. +For these routes, you need to override the allowed fields and relations to be retrieved. You can do this by applying a [global middleware](https://docs.medusajs.com/learn/fundamentals/api-routes/middlewares/index.html.md) to those routes. -For example, to allow retrieving the `b2b_company` of a customer using the [Get Customer Admin API Route](undefined/api/admin#customers_getcustomersid), create the file `src/api/middlewares.ts` with the following content: +For example, to allow retrieving the `b2b_company` of a customer using the [Get Customer Admin API Route](https://docs.medusajs.com/api/admin#customers_getcustomersid), create the file `src/api/middlewares.ts` with the following content: -Learn how to create a middleware in the [Middlewares](undefined/learn/fundamentals/api-routes/middlewares) chapter. +Learn how to create a middleware in the [Middlewares](https://docs.medusajs.com/learn/fundamentals/api-routes/middlewares/index.html.md) chapter. ```ts title="src/api/middlewares.ts" highlights={highlights} import { defineMiddlewares } from "@medusajs/medusa" @@ -9389,11 +9383,11 @@ export default defineMiddlewares({ }) ``` -In this example, you apply a middleware to the [Get Customer Admin API Route](undefined/api/admin#customers_getcustomersid). +In this example, you apply a middleware to the [Get Customer Admin API Route](https://docs.medusajs.com/api/admin#customers_getcustomersid). The request object passed to middlewares has an `allowed` property that contains the fields and relations that can be retrieved. So, you modify the `allowed` array to include the `b2b_company` field. -You can now retrieve the `b2b_company` field using the `fields` query parameter of the [Get Customer Admin API Route](undefined/api/admin#customers_getcustomersid): +You can now retrieve the `b2b_company` field using the `fields` query parameter of the [Get Customer Admin API Route](https://docs.medusajs.com/api/admin#customers_getcustomersid): ```bash curl 'http://localhost:9000/admin/customers/{id}?fields=*b2b_company' \ @@ -9602,7 +9596,7 @@ export default defineMiddlewares({ The `validateAndTransformQuery` accepts two parameters: - The first one is the Zod schema to validate the query parameters against. -- The second one is an object of options for retrieving data using Query, which you can learn more about in [this chapter](undefined/learn/fundamentals/module-links/query). +- The second one is an object of options for retrieving data using Query, which you can learn more about in [this chapter](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md). #### How the Validation Works @@ -9660,11 +9654,11 @@ In this chapter, you'll learn how to create and execute custom scripts using Med ## What is a Custom CLI Script? -A custom CLI script is a function that you can execute using Medusa's CLI tool. It is useful when you need a script that has access to the [Medusa container](undefined/learn/fundamentals/medusa-container) and can be executed using Medusa's CLI. +A custom CLI script is a function that you can execute using Medusa's CLI tool. It is useful when you need a script that has access to the [Medusa container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md) and can be executed using Medusa's CLI. For example, you can create a custom CLI script that: -- [Seeds data into the database](undefined/learn/fundamentals/custom-cli-scripts/seed-data). +- [Seeds data into the database](https://docs.medusajs.com/learn/fundamentals/custom-cli-scripts/seed-data/index.html.md). - Runs a script before starting the Medusa application. *** @@ -9734,7 +9728,7 @@ npx medusa exec ./src/scripts/my-script.ts arg1 arg2 In some cases, you may need to perform an action when the Medusa application starts. -If the action is related to a module, you should use a [loader](undefined/learn/fundamentals/modules/loaders). Otherwise, you can create a custom CLI script and run it before starting the Medusa application. +If the action is related to a module, you should use a [loader](https://docs.medusajs.com/learn/fundamentals/modules/loaders/index.html.md). Otherwise, you can create a custom CLI script and run it before starting the Medusa application. To run a custom script on application startup, modify the `dev` and `start` commands in `package.json` to execute your script first. @@ -9755,13 +9749,13 @@ The `startup` script will run every time you run the Medusa application. # Seed Data with Custom CLI Script -In this chapter, you'll learn how to seed data using a [custom CLI script](undefined/learn/fundamentals/custom-cli-scripts). +In this chapter, you'll learn how to seed data using a [custom CLI script](https://docs.medusajs.com/learn/fundamentals/custom-cli-scripts/index.html.md). ## How to Seed Data To seed dummy data for development or demo purposes, use a custom CLI script. -In the CLI script, use your custom workflows or Medusa's existing workflows, which you can browse in [this reference](undefined/resources/medusa-workflows-reference), to seed data. +In the CLI script, use your custom workflows or Medusa's existing workflows, which you can browse in [this reference](https://docs.medusajs.com/resources/medusa-workflows-reference/index.html.md), to seed data. *** @@ -9819,8 +9813,8 @@ export default async function seedDummyProducts({ So far, in the script, you: -- Resolve the [Sales Channel Module](undefined/resources/commerce-modules/sales-channel)'s service to retrieve the application's default sales channel. This is the sales channel the dummy products will be available in. -- Resolve the [Logger](undefined/learn/debugging-and-testing/logging) to log messages in the terminal, and Query to later retrieve data useful for the seeded products. +- Resolve the [Sales Channel Module](https://docs.medusajs.com/resources/commerce-modules/sales-channel/index.html.md)'s service to retrieve the application's default sales channel. This is the sales channel the dummy products will be available in. +- Resolve the [Logger](https://docs.medusajs.com/learn/debugging-and-testing/logging/index.html.md) to log messages in the terminal, and Query to later retrieve data useful for the seeded products. - Initialize some default data to use when seeding the products next. Next, replace the `TODO` with the following: @@ -9896,7 +9890,7 @@ logger.info(`Seeded ${products.length} products.`) You create the generated products using the `createProductsWorkflow` imported previously from `@medusajs/medusa/core-flows`. It accepts the product data as input, and returns the created products. -The only thing left is to create [inventory levels](undefined/resources/commerce-modules/inventory/concepts#inventorylevel) for the product variants. So, replace the last `TODO` with the following: +The only thing left is to create [inventory levels](https://docs.medusajs.com/resources/commerce-modules/inventory/concepts#inventorylevel/index.html.md) for the product variants. So, replace the last `TODO` with the following: ```ts title="src/scripts/demo-products.ts" logger.info("Seeding inventory levels.") @@ -9926,7 +9920,7 @@ await createInventoryLevelsWorkflow(container).run({ logger.info("Finished seeding inventory levels data.") ``` -You use [Query](undefined/learn/fundamentals/module-links/query) to retrieve the first stock location in the application and the inventory items. +You use [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md) to retrieve the first stock location in the application and the inventory items. Then, you generate inventory levels for each inventory item, associating it with the first stock location. @@ -10081,7 +10075,7 @@ In the above example, the check constraint fails if the `end_date` is earlier th In this chapter, you’ll learn how to define a database index on a data model. -You can also define an index on a property as explained in the [Properties chapter](undefined/learn/fundamentals/data-models/properties#define-database-index-on-property). +You can also define an index on a property as explained in the [Properties chapter](https://docs.medusajs.com/learn/fundamentals/data-models/properties#define-database-index-on-property/index.html.md). ## Define Database Index on Data Model @@ -10231,7 +10225,7 @@ class BlogModuleService extends MedusaService({ Post }) { # JSON Properties in Data Models -In this chapter, you'll learn how to use and manage [JSON properties](undefined/learn/fundamentals/data-models/properties#json) in data models. +In this chapter, you'll learn how to use and manage [JSON properties](https://docs.medusajs.com/learn/fundamentals/data-models/properties#json/index.html.md) in data models. ## What is a JSON Property? @@ -10291,7 +10285,7 @@ Some examples of data to store in JSON properties: JSON properties are not suitable for structured data that requires strict validation or relationships with other data models. -For example, if you want to re-use brands across different products, it's better to create a `Brand` data model and [define a link](undefined/learn/fundamentals/module-links) to the `Product` data model instead of storing brand information in the product's `metadata` JSON property. +For example, if you want to re-use brands across different products, it's better to create a `Brand` data model and [define a link](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md) to the `Product` data model instead of storing brand information in the product's `metadata` JSON property. *** @@ -10299,13 +10293,13 @@ For example, if you want to re-use brands across different products, it's better ### How Medusa Updates JSON Properties -Consider a Brand Module with a `Brand` data model as shown [in the previous section](#what-is-a-json-property). The [module's service](undefined/learn/fundamentals/modules#2-create-service) will extend `MedusaService`, which generates methods like [updateBrands](undefined/resources/service-factory-reference/methods/update) to update a brand. +Consider a Brand Module with a `Brand` data model as shown [in the previous section](#what-is-a-json-property). The [module's service](https://docs.medusajs.com/learn/fundamentals/modules#2-create-service/index.html.md) will extend `MedusaService`, which generates methods like [updateBrands](https://docs.medusajs.com/resources/service-factory-reference/methods/update/index.html.md) to update a brand. When you pass a JSON property in the `updateBrands` method, Medusa will merge the provided JSON object with the existing one in the database. So, only the properties you pass will be updated, and the rest will remain unchanged. The following sections show examples of how to add, update, and remove properties in a JSON property. -The following examples assume you have a `brandModuleService` that is resolved from the [Medusa container](undefined/learn/fundamentals/medusa-container). For example: +The following examples assume you have a `brandModuleService` that is resolved from the [Medusa container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md). For example: ```ts const brandModuleService = container.resolve(BRAND_MODULE) @@ -10463,14 +10457,14 @@ The brand record will now have the `metadata` property updated to remove the `is The instructions above also apply when managing JSON properties in API routes, since they typically use a service's `update` method under the hood. -Refer to the [API reference](undefined/api/store#manage-metadata) to learn more about managing JSON properties, such as `metadata`, in API routes. +Refer to the [API reference](https://docs.medusajs.com/api/store#manage-metadata) to learn more about managing JSON properties, such as `metadata`, in API routes. # Manage Relationships In this chapter, you'll learn how to manage relationships between data models when creating, updating, or retrieving records using the module's main service. -This chapter applies to data model relationships within the same module. To manage linked data models across modules, check out [Links](undefined/learn/fundamentals/module-links) and [Query](undefined/learn/fundamentals/module-links/query). +This chapter applies to data model relationships within the same module. To manage linked data models across modules, check out [Links](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md) and [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md). ## Manage One-to-One Relationship @@ -10478,7 +10472,7 @@ This chapter applies to data model relationships within the same module. To mana When you create a record of a data model that belongs to another through a one-to-one relation, pass the ID of the other data model's record in the `{relation}_id` property, where `{relation}` is the name of the relation property. -For example, assuming you have the [User and Email data models from the previous chapter](undefined/learn/fundamentals/data-models/relationships#one-to-one-relationship), set an email's user ID as follows: +For example, assuming you have the [User and Email data models from the previous chapter](https://docs.medusajs.com/learn/fundamentals/data-models/relationships#one-to-one-relationship/index.html.md), set an email's user ID as follows: ```ts highlights={belongsHighlights} // when creating an email @@ -10501,7 +10495,7 @@ In the example above, you pass the `user_id` property when creating or updating When you create a record of a data model that has one of another, pass the ID of the other data model's record in the relation property. -For example, assuming you have the [User and Email data models from the previous chapter](undefined/learn/fundamentals/data-models/relationships#one-to-one-relationship), set a user's email ID as follows: +For example, assuming you have the [User and Email data models from the previous chapter](https://docs.medusajs.com/learn/fundamentals/data-models/relationships#one-to-one-relationship/index.html.md), set a user's email ID as follows: ```ts highlights={hasOneHighlights} // when creating a user @@ -10528,7 +10522,7 @@ In a one-to-many relationship, you can only manage the associations from the `be When you create a record of the data model on the `belongsTo` side, pass the ID of the other data model's record in the `{relation}_id` property, where `{relation}` is the name of the relation property. -For example, assuming you have the [Product and Store data models from the previous chapter](undefined/learn/fundamentals/data-models/relationships#one-to-many-relationship), set a product's store ID as follows: +For example, assuming you have the [Product and Store data models from the previous chapter](https://docs.medusajs.com/learn/fundamentals/data-models/relationships#one-to-many-relationship/index.html.md), set a product's store ID as follows: ```ts highlights={manyBelongsHighlights} // when creating a product @@ -10551,13 +10545,13 @@ In the example above, you pass the `store_id` property when creating or updating ## Manage Many-to-Many Relationship -If your many-to-many relation is represented with a [pivotEntity](undefined/learn/fundamentals/data-models/relationships#many-to-many-with-custom-columns), refer to [this section](#manage-many-to-many-relationship-with-pivotentity) instead. +If your many-to-many relation is represented with a [pivotEntity](https://docs.medusajs.com/learn/fundamentals/data-models/relationships#many-to-many-with-custom-columns/index.html.md), refer to [this section](#manage-many-to-many-relationship-with-pivotentity) instead. ### Create Associations When you create a record of a data model that has a many-to-many relationship to another data model, pass an array of IDs of the other data model's records in the relation property. -For example, assuming you have the [Order and Product data models from the previous chapter](undefined/learn/fundamentals/data-models/relationships#many-to-many-relationship), set the association between products and orders as follows: +For example, assuming you have the [Order and Product data models from the previous chapter](https://docs.medusajs.com/learn/fundamentals/data-models/relationships#many-to-many-relationship/index.html.md), set the association between products and orders as follows: ```ts highlights={manyHighlights} // when creating a product @@ -10582,7 +10576,7 @@ When you use the `update` methods generated by the service factory, you also pas However, this removes any existing associations to records whose IDs aren't included in the array. -For example, assuming you have the [Order and Product data models from the previous chapter](undefined/learn/fundamentals/data-models/relationships#many-to-many-relationship), you update the product's related orders as so: +For example, assuming you have the [Order and Product data models from the previous chapter](https://docs.medusajs.com/learn/fundamentals/data-models/relationships#many-to-many-relationship/index.html.md), you update the product's related orders as so: ```ts const product = await helloModuleService.updateProducts({ @@ -10620,11 +10614,11 @@ This keeps existing associations between the product and orders, and adds a new ## Manage Many-to-Many Relationship with pivotEntity -If your many-to-many relation is represented without a [pivotEntity](undefined/learn/fundamentals/data-models/relationships#many-to-many-with-custom-columns), refer to [this section](#manage-many-to-many-relationship) instead. +If your many-to-many relation is represented without a [pivotEntity](https://docs.medusajs.com/learn/fundamentals/data-models/relationships#many-to-many-with-custom-columns/index.html.md), refer to [this section](#manage-many-to-many-relationship) instead. -If you have a many-to-many relation with a `pivotEntity` specified, make sure to pass the data model representing the pivot table to [MedusaService](undefined/learn/fundamentals/modules/service-factory) that your module's service extends. +If you have a many-to-many relation with a `pivotEntity` specified, make sure to pass the data model representing the pivot table to [MedusaService](https://docs.medusajs.com/learn/fundamentals/modules/service-factory/index.html.md) that your module's service extends. -For example, assuming you have the [Order, Product, and OrderProduct models from the previous chapter](undefined/learn/fundamentals/data-models/relationships#many-to-many-with-custom-columns), add `OrderProduct` to `MedusaService`'s object parameter: +For example, assuming you have the [Order, Product, and OrderProduct models from the previous chapter](https://docs.medusajs.com/learn/fundamentals/data-models/relationships#many-to-many-with-custom-columns/index.html.md), add `OrderProduct` to `MedusaService`'s object parameter: ```ts highlights={["4"]} class BlogModuleService extends MedusaService({ @@ -10662,7 +10656,7 @@ await blogModuleService.deleteOrderProducts("123") Since the `OrderProduct` data model belongs to the `Order` and `Product` data models, you can set its order and product as explained in the [one-to-many relationship section](#manage-one-to-many-relationship) using `order_id` and `product_id`. -Refer to the [service factory reference](undefined/resources/service-factory-reference) for a full list of generated methods and their usages. +Refer to the [service factory reference](https://docs.medusajs.com/resources/service-factory-reference/index.html.md) for a full list of generated methods and their usages. *** @@ -10672,7 +10666,7 @@ The `list`, `listAndCount`, and `retrieve` methods of a module's main service ac To retrieve the records associated with a data model's records through a relationship, pass in the second parameter object a `relations` property whose value is an array of relationship names. -For example, assuming you have the [Order and Product data models from the previous chapter](undefined/learn/fundamentals/data-models/relationships#many-to-many-relationship), you retrieve a product's orders as follows: +For example, assuming you have the [Order and Product data models from the previous chapter](https://docs.medusajs.com/learn/fundamentals/data-models/relationships#many-to-many-relationship/index.html.md), you retrieve a product's orders as follows: ```ts highlights={retrieveHighlights} const product = await blogModuleService.retrieveProducts( @@ -10694,7 +10688,7 @@ In this chapter, you'll learn what a data model is and how to create a data mode A data model represents a table in the database. You create data models using Medusa's data modeling language (DML). It simplifies defining a table's columns, relations, and indexes with straightforward methods and configurations. -You create a data model in a [module](undefined/learn/fundamentals/modules). The module's service provides the methods to store and manage those data models. Then, you can resolve the module's service in other customizations, such as a [workflow](undefined/learn/fundamentals/workflows), to manage the data models' records. +You create a data model in a [module](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md). The module's service provides the methods to store and manage those data models. Then, you can resolve the module's service in other customizations, such as a [workflow](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md), to manage the data models' records. *** @@ -10729,13 +10723,13 @@ The code snippet above defines a `Post` data model with `id` and `title` propert ## Generate Migrations -After you create a data model in a module, then [register that module in your Medusa configurations](undefined/learn/fundamentals/modules#4-add-module-to-medusas-configurations), you must generate a migration to create the data model's table in the database. +After you create a data model in a module, then [register that module in your Medusa configurations](https://docs.medusajs.com/learn/fundamentals/modules#4-add-module-to-medusas-configurations/index.html.md), you must generate a migration to create the data model's table in the database. A migration is a TypeScript or JavaScript file that defines database changes made by a module. Migrations are useful when you re-use a module or you're working in a team, so that when one member of a team makes a database change, everyone else can reflect it on their side by running the migrations. For example, to generate a migration for the Blog Module, run the following command in your Medusa application's directory: -If you're creating the module in a plugin, use the [plugin:db:generate command](undefined/resources/medusa-cli/commands/plugin#plugindbgenerate) instead. +If you're creating the module in a plugin, use the [plugin:db:generate command](https://docs.medusajs.com/resources/medusa-cli/commands/plugin#plugindbgenerate/index.html.md) instead. ```bash npx medusa db:generate blog @@ -10783,11 +10777,11 @@ For example, if you add a new column to the `Post` data model, you must generate ## Manage Data Models -Your module's service should extend the [service factory](undefined/learn/fundamentals/modules/service-factory), which generates data-management methods for your module's data models. +Your module's service should extend the [service factory](https://docs.medusajs.com/learn/fundamentals/modules/service-factory/index.html.md), which generates data-management methods for your module's data models. For example, the Blog Module's service would have methods like `retrievePost` and `createPosts`. -Refer to the [Service Factory](undefined/learn/fundamentals/modules/service-factory) chapter to learn more about how to extend the service factory and manage data models, and refer to the [Service Factory Reference](undefined/resources/service-factory-reference) for the full list of generated methods and how to use them. +Refer to the [Service Factory](https://docs.medusajs.com/learn/fundamentals/modules/service-factory/index.html.md) chapter to learn more about how to extend the service factory and manage data models, and refer to the [Service Factory Reference](https://docs.medusajs.com/resources/service-factory-reference/index.html.md) for the full list of generated methods and how to use them. # Data Model Properties @@ -10844,7 +10838,7 @@ export default Post #### Limit Text Length -To limit the allowed length of a `text` property, use the [checks method](undefined/learn/fundamentals/data-models/check-constraints). +To limit the allowed length of a `text` property, use the [checks method](https://docs.medusajs.com/learn/fundamentals/data-models/check-constraints/index.html.md). For example, to limit the `name` property to a maximum of 50 characters: @@ -10991,7 +10985,7 @@ const Post = model.define("post", { export default Post ``` -Learn more in the [JSON Properties](undefined/learn/fundamentals/data-models/json-properties) chapter. +Learn more in the [JSON Properties](https://docs.medusajs.com/learn/fundamentals/data-models/json-properties/index.html.md) chapter. ### array @@ -11012,7 +11006,7 @@ export default Post ### Properties Reference -Refer to the [Data Model Language (DML) reference](undefined/resources/references/data-model) for a full reference of the properties. +Refer to the [Data Model Language (DML) reference](https://docs.medusajs.com/resources/references/data-model/index.html.md) for a full reference of the properties. *** @@ -11132,7 +11126,7 @@ In this example, you define an index on the `name` property. ## Define a Searchable Property -Methods generated by the [service factory](undefined/learn/fundamentals/modules/service-factory) that accept filters, such as `list{ModelName}s`, accept a `q` property as part of the filters. +Methods generated by the [service factory](https://docs.medusajs.com/learn/fundamentals/modules/service-factory/index.html.md) that accept filters, such as `list{ModelName}s`, accept a `q` property as part of the filters. When the `q` filter is passed, the data model's searchable properties are queried to find matching records. @@ -11219,7 +11213,7 @@ Both methods also accept a second parameter object with the property `mappedBy`. ### Optional Relationship -To make the relationship optional on the `hasOne` or `belongsTo` side, use the `nullable` method on either property as explained in [this chapter](undefined/learn/fundamentals/data-models/properties#make-property-optional). +To make the relationship optional on the `hasOne` or `belongsTo` side, use the `nullable` method on either property as explained in [this chapter](https://docs.medusajs.com/learn/fundamentals/data-models/properties#make-property-optional/index.html.md). ### One-to-One Relationship in the Database @@ -11327,7 +11321,7 @@ In this example, a store has many products, but a product belongs to one store. ### Optional Relationship -To make the relationship optional on the `belongsTo` side, use the `nullable` method on the property as explained in [this chapter](undefined/learn/fundamentals/data-models/properties#make-property-optional). +To make the relationship optional on the `belongsTo` side, use the `nullable` method on the property as explained in [this chapter](https://docs.medusajs.com/learn/fundamentals/data-models/properties#make-property-optional/index.html.md). ### One-to-Many Relationship in the Database @@ -11491,7 +11485,7 @@ The migration's file has a class with two methods: ## Generate Migration -Instead of you writing the migration manually, the Medusa CLI tool provides a [db:generate](undefined/resources/medusa-cli/commands/db#dbgenerate) command to generate a migration for a modules' data models. +Instead of you writing the migration manually, the Medusa CLI tool provides a [db:generate](https://docs.medusajs.com/resources/medusa-cli/commands/db#dbgenerate/index.html.md) command to generate a migration for a modules' data models. For example, assuming you have a `blog` Module, you can generate a migration for it by running the following command: @@ -11575,7 +11569,7 @@ So, always rollback the migration before deleting it. ## More Database Commands -To learn more about the Medusa CLI's database commands, refer to [this CLI reference](undefined/resources/medusa-cli/commands/db). +To learn more about the Medusa CLI's database commands, refer to [this CLI reference](https://docs.medusajs.com/resources/medusa-cli/commands/db/index.html.md). *** @@ -11617,7 +11611,7 @@ const migrateBlogDataWorkflow = createWorkflow( ) ``` -In the above example, you default export an asynchronous function that receives an object parameter with the [Medusa Container](undefined/learn/fundamentals/medusa-container) property. +In the above example, you default export an asynchronous function that receives an object parameter with the [Medusa Container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md) property. In the function, you first ensure that the Blog Module is installed to avoid errors otherwise. Then, you run a workflow that you've created in the same file that performs the necessary data migration. @@ -11679,7 +11673,7 @@ To ensure that the correct `.env` file is loaded as shown in the table above, on Since the Medusa Admin is built on top of [Vite](https://vite.dev/), you prefix the environment variables you want to use in a widget or UI route with `VITE_`. Then, you can access or use them with the `import.meta.env` object. -Learn more in the [Admin Environment Variables](undefined/learn/fundamentals/admin/environment-variables) chapter. +Learn more in the [Admin Environment Variables](https://docs.medusajs.com/learn/fundamentals/admin/environment-variables/index.html.md) chapter. *** @@ -11687,7 +11681,7 @@ Learn more in the [Admin Environment Variables](undefined/learn/fundamentals/adm The Medusa application uses the following predefined environment variables that you can set: -You should opt for setting configurations in `medusa-config.ts` where possible. For a full list of Medusa configurations, refer to the [Medusa Configurations chapter](undefined/learn/configurations/medusa-config). +You should opt for setting configurations in `medusa-config.ts` where possible. For a full list of Medusa configurations, refer to the [Medusa Configurations chapter](https://docs.medusajs.com/learn/configurations/medusa-config/index.html.md). |Environment Variable|Description|Default| |---|---|---| @@ -11969,11 +11963,11 @@ You listen to an event in a subscriber, which is an asynchronous function that's Subscribers are useful to perform actions that aren't integral to the original flow. For example, you can handle the `order.placed` event in a subscriber that sends a confirmation email to the customer. The subscriber has no impact on the original order-placement flow, as it's executed outside of it. -If the action you're performing is integral to the main flow of the core commerce feature, use [workflow hooks](undefined/learn/fundamentals/workflows/workflow-hooks) instead. +If the action you're performing is integral to the main flow of the core commerce feature, use [workflow hooks](https://docs.medusajs.com/learn/fundamentals/workflows/workflow-hooks/index.html.md) instead. ### List of Emitted Events -Find a list of all emitted events in [this reference](undefined/resources/references/events). +Find a list of all emitted events in [this reference](https://docs.medusajs.com/resources/references/events/index.html.md). *** @@ -12018,9 +12012,9 @@ This subscriber file exports: The subscriber function receives an object as a parameter that has the following properties: - `event`: An object with the event's details. The `data` property contains the data payload of the event emitted, which is the order's ID in this case. -- `container`: The [Medusa container](undefined/learn/fundamentals/medusa-container) that you can use to resolve registered resources. +- `container`: The [Medusa container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md) that you can use to resolve registered resources. -In the subscriber function, you use the container to resolve the Logger utility and log a message in the console. Also, assuming you have a [workflow](undefined/learn/fundamentals/workflows) that sends an order confirmation email, you execute it in the subscriber. +In the subscriber function, you use the container to resolve the Logger utility and log a message in the console. Also, assuming you have a [workflow](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) that sends an order confirmation email, you execute it in the subscriber. *** @@ -12032,7 +12026,7 @@ To test the subscriber, start the Medusa application: npm run dev ``` -Then, try placing an order either using Medusa's API routes or the [Next.js Starter Storefront](undefined/resources/nextjs-starter). You'll see the following message in the terminal: +Then, try placing an order either using Medusa's API routes or the [Next.js Starter Storefront](https://docs.medusajs.com/resources/nextjs-starter/index.html.md). You'll see the following message in the terminal: ```bash info: Processing order.placed which has 1 subscribers @@ -12049,10 +12043,10 @@ The subscription and emitting of events is handled by an Event Module, an Infras Medusa provides two Event Modules out of the box: -- [Local Event Module](undefined/resources/infrastructure-modules/event/local), used by default. It's useful for development, as you don't need additional setup to use it. -- [Redis Event Module](undefined/resources/infrastructure-modules/event/redis), which is useful in production. It uses [Redis](https://redis.io/) to implement Medusa's pub/sub events system. +- [Local Event Module](https://docs.medusajs.com/resources/infrastructure-modules/event/local/index.html.md), used by default. It's useful for development, as you don't need additional setup to use it. +- [Redis Event Module](https://docs.medusajs.com/resources/infrastructure-modules/event/redis/index.html.md), which is useful in production. It uses [Redis](https://redis.io/) to implement Medusa's pub/sub events system. -Medusa's [architecture](undefined/learn/introduction/architecture) also allows you to build a custom Event Module that uses a different service or logic to implement the pub/sub system. Learn how to build an Event Module in [this guide](undefined/resources/infrastructure-modules/event/create). +Medusa's [architecture](https://docs.medusajs.com/learn/introduction/architecture/index.html.md) also allows you to build a custom Event Module that uses a different service or logic to implement the pub/sub system. Learn how to build an Event Module in [this guide](https://docs.medusajs.com/resources/infrastructure-modules/event/create/index.html.md). # Framework Overview @@ -12071,25 +12065,25 @@ With the Medusa Framework, you can focus your efforts on building meaningful bus Using the Medusa Framework, you can build customizations like: -- [Product Reviews](undefined/resources/how-to-tutorials/tutorials/product-reviews) -- [Deep integration with an ERP system](undefined/resources/recipes/erp) -- [CMS integration with seamless content retrieval](undefined/resources/integrations/guides/sanity) -- [Custom item pricing in the cart](undefined/resources/examples/guides/custom-item-price) -- [Automated restock notifications](undefined/resources/recipes/commerce-automation/restock-notification) -- [Re-usable payment provider integrations](undefined/resources/references/payment/provider) +- [Product Reviews](https://docs.medusajs.com/resources/how-to-tutorials/tutorials/product-reviews/index.html.md) +- [Deep integration with an ERP system](https://docs.medusajs.com/resources/recipes/erp/index.html.md) +- [CMS integration with seamless content retrieval](https://docs.medusajs.com/resources/integrations/guides/sanity/index.html.md) +- [Custom item pricing in the cart](https://docs.medusajs.com/resources/examples/guides/custom-item-price/index.html.md) +- [Automated restock notifications](https://docs.medusajs.com/resources/recipes/commerce-automation/restock-notification/index.html.md) +- [Re-usable payment provider integrations](https://docs.medusajs.com/resources/references/payment/provider/index.html.md) ### Framework Concepts and Tools -- [Medusa Container](undefined/learn/fundamentals/medusa-container) -- [Modules](undefined/learn/fundamentals/modules) -- [Module Links](undefined/learn/fundamentals/module-links) -- [Query](undefined/learn/fundamentals/module-links/query) -- [Data Models](undefined/learn/fundamentals/data-models) -- [Workflows](undefined/learn/fundamentals/workflows) -- [API Routes](undefined/learn/fundamentals/api-routes) -- [Events and Subscribers](undefined/learn/fundamentals/events-and-subscribers) -- [Scheduled Jobs](undefined/learn/fundamentals/scheduled-jobs) -- [Plugins](undefined/learn/fundamentals/plugins) +- [Medusa Container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md) +- [Modules](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md) +- [Module Links](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md) +- [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md) +- [Data Models](https://docs.medusajs.com/learn/fundamentals/data-models/index.html.md) +- [Workflows](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) +- [API Routes](https://docs.medusajs.com/learn/fundamentals/api-routes/index.html.md) +- [Events and Subscribers](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/index.html.md) +- [Scheduled Jobs](https://docs.medusajs.com/learn/fundamentals/scheduled-jobs/index.html.md) +- [Plugins](https://docs.medusajs.com/learn/fundamentals/plugins/index.html.md) *** @@ -12097,7 +12091,7 @@ Using the Medusa Framework, you can build customizations like: The Medusa Framework allows you to build custom features tailored to your business needs. -To create a custom feature, you can create a [module](undefined/learn/fundamentals/modules) that contains your feature's data models and the logic to manage them. A module is integrated into your Medusa application without side effects. +To create a custom feature, you can create a [module](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md) that contains your feature's data models and the logic to manage them. A module is integrated into your Medusa application without side effects. ### Data Model @@ -12136,7 +12130,7 @@ export default Module(BLOG_MODULE, { }) ``` -Then, you can build commerce features and flows in [workflows](undefined/learn/fundamentals/workflows) that use your module. By using workflows, you benefit from features like [rollback mechanism](undefined/learn/fundamentals/workflows/compensation-function) and [retry configuration](undefined/learn/fundamentals/workflows/retry-failed-steps). +Then, you can build commerce features and flows in [workflows](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) that use your module. By using workflows, you benefit from features like [rollback mechanism](https://docs.medusajs.com/learn/fundamentals/workflows/compensation-function/index.html.md) and [retry configuration](https://docs.medusajs.com/learn/fundamentals/workflows/retry-failed-steps/index.html.md). ### Step @@ -12193,7 +12187,7 @@ export const createPostWorkflow = createWorkflow( ) ``` -Finally, you can expose your custom feature with [API routes](undefined/learn/fundamentals/api-routes) that are built on top of your module and workflows. +Finally, you can expose your custom feature with [API routes](https://docs.medusajs.com/learn/fundamentals/api-routes/index.html.md) that are built on top of your module and workflows. ```ts title="API Route Example" import type { @@ -12223,16 +12217,16 @@ export const POST = async ( The following tutorials are step-by-step guides that show you how to build custom features using the Medusa Framework. -- [Product Reviews](undefined/resources/how-to-tutorials/tutorials/product-reviews): Build a product reviews feature in your Medusa application. -- [Wishlist](undefined/resources/plugins/guides/wishlist): Build a wishlist feature in your Medusa application. +- [Product Reviews](https://docs.medusajs.com/resources/how-to-tutorials/tutorials/product-reviews/index.html.md): Build a product reviews feature in your Medusa application. +- [Wishlist](https://docs.medusajs.com/resources/plugins/guides/wishlist/index.html.md): Build a wishlist feature in your Medusa application. ### Start Learning To learn more about the different concepts useful for building custom features, check out the following chapters: -- [Modules](undefined/learn/fundamentals/modules) -- [Workflows](undefined/learn/fundamentals/workflows) -- [API Routes](undefined/learn/fundamentals/api-routes) +- [Modules](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md) +- [Workflows](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) +- [API Routes](https://docs.medusajs.com/learn/fundamentals/api-routes/index.html.md) *** @@ -12240,7 +12234,7 @@ To learn more about the different concepts useful for building custom features, The Medusa Framework is flexible and extensible, allowing you to extend and build on top of existing models and features. -To associate new properties and relations with an existing model, you can create a [module](undefined/learn/fundamentals/modules) with data models that define these additions. Then, you can define a [module link](undefined/learn/fundamentals/module-links) that associates two data models from separate modules. +To associate new properties and relations with an existing model, you can create a [module](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md) with data models that define these additions. Then, you can define a [module link](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md) that associates two data models from separate modules. ### Module Link @@ -12297,7 +12291,7 @@ export default Module(BRAND_MODULE, { }) ``` -Then, you can [hook into existing workflows](undefined/learn/fundamentals/workflows/workflow-hooks) to perform custom actions as part of existing features and flows. For example, you can create a brand when a product is created. +Then, you can [hook into existing workflows](https://docs.medusajs.com/learn/fundamentals/workflows/workflow-hooks/index.html.md) to perform custom actions as part of existing features and flows. For example, you can create a brand when a product is created. ```ts title="Workflow Hook Example" highlights={hookHighlights} import { createProductsWorkflow } from "@medusajs/medusa/core-flows" @@ -12324,22 +12318,22 @@ createProductsWorkflow.hooks.productsCreated( ) ``` -You can also build custom workflows using your custom module and Medusa's modules, and use [existing workflows and steps](undefined/resources/medusa-workflows-reference) within your custom workflows. +You can also build custom workflows using your custom module and Medusa's modules, and use [existing workflows and steps](https://docs.medusajs.com/resources/medusa-workflows-reference/index.html.md) within your custom workflows. ### Examples The following tutorials are step-by-step guides that show you how to extend existing features using the Medusa Framework. -- [Custom Item Pricing](undefined/resources/examples/guides/custom-item-price): Add products with custom items to the cart. -- [Loyalty Points System](undefined/resources/how-to-tutorials/tutorials/loyalty-points): Reward and allow customers to redeem loyalty points. +- [Custom Item Pricing](https://docs.medusajs.com/resources/examples/guides/custom-item-price/index.html.md): Add products with custom items to the cart. +- [Loyalty Points System](https://docs.medusajs.com/resources/how-to-tutorials/tutorials/loyalty-points/index.html.md): Reward and allow customers to redeem loyalty points. ### Start Learning To learn more about the different concepts useful for extending features, check out the following chapters: -- [Modules](undefined/learn/fundamentals/modules) -- [Module Links](undefined/learn/fundamentals/module-links) -- [Workflow Hooks](undefined/learn/fundamentals/workflows/workflow-hooks) +- [Modules](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md) +- [Module Links](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md) +- [Workflow Hooks](https://docs.medusajs.com/learn/fundamentals/workflows/workflow-hooks/index.html.md) *** @@ -12351,7 +12345,7 @@ The Medusa Framework provides the tools and infrastructure to build a middleware The Medusa Framework solves one of the biggest hurdles for ecommerce platforms: orchestrating operations across systems. Medusa has a built-in durable execution engine to help complete tasks that span multiple systems. -You can integrate a third-party service in a [module](undefined/learn/fundamentals/modules). This module provides an interface to perform operations with the third-party service. +You can integrate a third-party service in a [module](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md). This module provides an interface to perform operations with the third-party service. ### Service @@ -12391,7 +12385,7 @@ export default Module(ERP_MODULE, { }) ``` -Then, you can build [workflows](undefined/learn/fundamentals/workflows) that perform operations across systems. In the workflow, you can use your module to interact with the integrated third-party service. +Then, you can build [workflows](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) that perform operations across systems. In the workflow, you can use your module to interact with the integrated third-party service. For example, you can create a workflow that syncs products from your ERP system to your Medusa application. @@ -12463,9 +12457,9 @@ const getProductsFromErpStep = createStep( ) ``` -By using a workflow to manage operations across systems, you benefit from features like [rollback mechanism](undefined/learn/fundamentals/workflows/compensation-function), [background long-running execution](undefined/learn/fundamentals/workflows/long-running-workflow), [retry configuration](undefined/learn/fundamentals/workflows/retry-failed-steps), and more. This is essential for building a middleware solution that performs operations across systems, as you don't have to worry about data inconsistencies or failures. +By using a workflow to manage operations across systems, you benefit from features like [rollback mechanism](https://docs.medusajs.com/learn/fundamentals/workflows/compensation-function/index.html.md), [background long-running execution](https://docs.medusajs.com/learn/fundamentals/workflows/long-running-workflow/index.html.md), [retry configuration](https://docs.medusajs.com/learn/fundamentals/workflows/retry-failed-steps/index.html.md), and more. This is essential for building a middleware solution that performs operations across systems, as you don't have to worry about data inconsistencies or failures. -You can then execute this workflow at a specific interval using [scheduled jobs](undefined/learn/fundamentals/scheduled-jobs) or when an event occurs using [events and subscribers](undefined/learn/fundamentals/events-and-subscribers). You can also expose its features to client applications using an [API route](undefined/learn/fundamentals/api-routes). +You can then execute this workflow at a specific interval using [scheduled jobs](https://docs.medusajs.com/learn/fundamentals/scheduled-jobs/index.html.md) or when an event occurs using [events and subscribers](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/index.html.md). You can also expose its features to client applications using an [API route](https://docs.medusajs.com/learn/fundamentals/api-routes/index.html.md). ### Scheduled Job @@ -12526,24 +12520,24 @@ export const POST = async ( The following tutorials are step-by-step guides that show you how to orchestrate operations across third-party services using the Medusa Framework. -- [Migrate Data from Magento](undefined/resources/integrations/guides/magento): Migrate data from Magento to your Medusa application. -- [Integrate Third-Party Services](undefined/resources/integrations): Integrate CMS, Fulfillment, Payment, and other third-party services. +- [Migrate Data from Magento](https://docs.medusajs.com/resources/integrations/guides/magento/index.html.md): Migrate data from Magento to your Medusa application. +- [Integrate Third-Party Services](https://docs.medusajs.com/resources/integrations/index.html.md): Integrate CMS, Fulfillment, Payment, and other third-party services. #### Start Learning To learn more about the different concepts useful for integrating third-party services, check out the following chapters: -- [Modules](undefined/learn/fundamentals/modules) -- [Workflows](undefined/learn/fundamentals/workflows) -- [API Routes](undefined/learn/fundamentals/api-routes) -- [Events and Subscribers](undefined/learn/fundamentals/events-and-subscribers) -- [Scheduled Jobs](undefined/learn/fundamentals/scheduled-jobs) +- [Modules](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md) +- [Workflows](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) +- [API Routes](https://docs.medusajs.com/learn/fundamentals/api-routes/index.html.md) +- [Events and Subscribers](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/index.html.md) +- [Scheduled Jobs](https://docs.medusajs.com/learn/fundamentals/scheduled-jobs/index.html.md) ### Query Data Across Systems Another essential feature for integrating third-party services is querying data across those systems efficiently. -The Framework allows you to build links not only between Medusa data models, but also virtual data models using [read-only module links](undefined/learn/fundamentals/module-links/read-only). You can build a [module](undefined/learn/fundamentals/modules) that provides the logic to query data from a third-party service, then create a read-only link between an existing data model and a virtual one from the third-party service. +The Framework allows you to build links not only between Medusa data models, but also virtual data models using [read-only module links](https://docs.medusajs.com/learn/fundamentals/module-links/read-only/index.html.md). You can build a [module](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md) that provides the logic to query data from a third-party service, then create a read-only link between an existing data model and a virtual one from the third-party service. ### Read-Only Link @@ -12620,7 +12614,7 @@ export default Module(BRAND_MODULE, { }) ``` -Then, you can use [Query](undefined/learn/fundamentals/module-links/query) to retrieve a product and its brand from the third-party service in a single query. +Then, you can use [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md) to retrieve a product and its brand from the third-party service in a single query. ```ts title="Query Example" highlights={queryHighlights} const { result } = await query.graph({ @@ -12648,15 +12642,15 @@ Query simplifies the process of retrieving data across systems, as you can retri The following tutorials are step-by-step guides that show you how to query data across systems using the Medusa Framework. -- [Integrate Sanity CMS](undefined/resources/integrations/guides/sanity): Query data from third-party services using read-only links. +- [Integrate Sanity CMS](https://docs.medusajs.com/resources/integrations/guides/sanity/index.html.md): Query data from third-party services using read-only links. #### Start Learning To learn more about the different concepts useful for querying data across systems, check out the following chapters: -- [Modules](undefined/learn/fundamentals/modules) -- [Read-Only Links](undefined/learn/fundamentals/module-links/read-only) -- [Query](undefined/learn/fundamentals/module-links/query) +- [Modules](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md) +- [Read-Only Links](https://docs.medusajs.com/learn/fundamentals/module-links/read-only/index.html.md) +- [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md) *** @@ -12664,7 +12658,7 @@ To learn more about the different concepts useful for querying data across syste The Medusa Framework provides the tools to automate tasks in your Medusa application. Automation is useful when you want to perform a task periodically, such as syncing data, or when an event occurs, such as sending a confirmation email when an order is placed. -To build the task to be automated, you first create a [workflow](undefined/learn/fundamentals/workflows) that contains the task's logic, such as syncing data or sending an email. +To build the task to be automated, you first create a [workflow](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) that contains the task's logic, such as syncing data or sending an email. ### Step @@ -12732,7 +12726,7 @@ export const sendOrderConfirmationWorkflow = createWorkflow( ) ``` -Then, you can execute this workflow when an event occurs using a [subscriber](undefined/learn/fundamentals/events-and-subscribers), or at a specific interval using a [scheduled job](undefined/learn/fundamentals/scheduled-jobs). +Then, you can execute this workflow when an event occurs using a [subscriber](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/index.html.md), or at a specific interval using a [scheduled job](https://docs.medusajs.com/learn/fundamentals/scheduled-jobs/index.html.md). ### Event Subscriber @@ -12787,24 +12781,24 @@ export const config = { The following guides are step-by-step guides that show you how to automate tasks using the Medusa Framework. -- [Restock Notifications](undefined/resources/recipes/commerce-automation/restock-notification): Send restock notifications to customers when a product is back in stock. -- [Sync Data from and to ERP](undefined/resources/recipes/erp#sync-products-from-erp): Sync data between your Medusa application and an ERP system. +- [Restock Notifications](https://docs.medusajs.com/resources/recipes/commerce-automation/restock-notification/index.html.md): Send restock notifications to customers when a product is back in stock. +- [Sync Data from and to ERP](https://docs.medusajs.com/resources/recipes/erp#sync-products-from-erp/index.html.md): Sync data between your Medusa application and an ERP system. ### Start Learning To learn more about the different concepts useful for automating tasks, check out the following chapters: -- [Workflows](undefined/learn/fundamentals/workflows) -- [Events and Subscribers](undefined/learn/fundamentals/events-and-subscribers) -- [Scheduled Jobs](undefined/learn/fundamentals/scheduled-jobs) +- [Workflows](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) +- [Events and Subscribers](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/index.html.md) +- [Scheduled Jobs](https://docs.medusajs.com/learn/fundamentals/scheduled-jobs/index.html.md) *** ## Re-Use Customizations Across Applications -If you have custom features that you want to re-use across multiple Medusa applications, or you want to publish your customizations for the community to use, you can build a [plugin](undefined/learn/fundamentals/plugins). +If you have custom features that you want to re-use across multiple Medusa applications, or you want to publish your customizations for the community to use, you can build a [plugin](https://docs.medusajs.com/learn/fundamentals/plugins/index.html.md). -A plugin encapsulates your customizations in a single package. The customizations include [modules](undefined/learn/fundamentals/modules), [workflows](undefined/learn/fundamentals/workflows), [API routes](undefined/learn/fundamentals/api-routes), and more. +A plugin encapsulates your customizations in a single package. The customizations include [modules](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md), [workflows](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md), [API routes](https://docs.medusajs.com/learn/fundamentals/api-routes/index.html.md), and more. ![Diagram showcasing a wishlist plugin installed in a Medusa application](https://res.cloudinary.com/dza7lstvk/image/upload/v1737540762/Medusa%20Book/plugin-diagram_oepiis.jpg) @@ -12814,14 +12808,14 @@ You can then publish that plugin to NPM and install it in any Medusa application The following tutorials are step-by-step guides that show you how to build plugins using the Medusa Framework. -- [Wishlist Plugin](undefined/resources/plugins/guides/wishlist): Build a wishlist plugin for your Medusa application. -- [Migrate Data from Magento Plugin](undefined/resources/integrations/guides/magento): Build a plugin that migrates data from Magento to your Medusa application. +- [Wishlist Plugin](https://docs.medusajs.com/resources/plugins/guides/wishlist/index.html.md): Build a wishlist plugin for your Medusa application. +- [Migrate Data from Magento Plugin](https://docs.medusajs.com/resources/integrations/guides/magento/index.html.md): Build a plugin that migrates data from Magento to your Medusa application. ### Start Learning To learn more about the different concepts useful for building plugins, check out the following chapters: -- [Plugins](undefined/learn/fundamentals/plugins) +- [Plugins](https://docs.medusajs.com/learn/fundamentals/plugins/index.html.md) # Automatically Generated Types @@ -12832,9 +12826,9 @@ In this chapter, you'll learn about the types Medusa automatically generates und Medusa automatically generates TypeScript types for: -1. Data models collected in the [Query's graph](undefined/learn/fundamentals/module-links/query#querying-the-graph). These types provide you with auto-completion and type checking when using Query. +1. Data models collected in the [Query's graph](https://docs.medusajs.com/learn/fundamentals/module-links/query#querying-the-graph/index.html.md). These types provide you with auto-completion and type checking when using Query. - Generated data model types are located in the `.medusa/types/query-entry-points.d.ts` file. -2. Modules registered in the [Medusa container](undefined/learn/fundamentals/medusa-container). These types provide you with auto-completion and type checking when resolving modules from the container. +2. Modules registered in the [Medusa container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md). These types provide you with auto-completion and type checking when resolving modules from the container. - Generated module registration names are located in the `.medusa/types/modules-bindings.d.ts` file. ![Diagram showcasing the directory structure of the .medusa directory, highlighting the types folder and its contents.](https://res.cloudinary.com/dza7lstvk/image/upload/v1753448927/Medusa%20Book/generated-types-dir_bmvdts.jpg) @@ -12889,7 +12883,7 @@ The generated types are only meant to help you in your development process by pr Since you don't commit the `.medusa` directory to your version control system or your production environment, importing these types may lead to build errors. -Instead, if you need to use a data model's type in your customizations, you can use the [InferTypeOf](undefined/learn/fundamentals/data-models/infer-type) utility function, which infers the type of a data model based on its properties. +Instead, if you need to use a data model's type in your customizations, you can use the [InferTypeOf](https://docs.medusajs.com/learn/fundamentals/data-models/infer-type/index.html.md) utility function, which infers the type of a data model based on its properties. For example, if you want to use the `Brand` data model's type in your customizations, you can do the following: @@ -12915,7 +12909,7 @@ In other platforms, if you have a resource A (for example, a class) that depends Medusa simplifies this process by giving you access to the container, with the tools or resources already registered, at all times in your customizations. When you reach a point in your code where you need a tool, you resolve it from the container and use it. -For example, consider you're creating an API route that retrieves products based on filters using [Query](undefined/learn/fundamentals/module-links/query), a tool that fetches data across the application. In the API route's function, you can resolve Query from the container passed to the API route and use it: +For example, consider you're creating an API route that retrieves products based on filters using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md), a tool that fetches data across the application. In the API route's function, you can resolve Query from the container passed to the API route and use it: ```ts highlights={highlights} import { MedusaRequest, MedusaResponse } from "@medusajs/framework" @@ -12943,13 +12937,13 @@ export async function GET( The API route accepts as a first parameter a request object that has a `scope` property, which is the Medusa container. It has a `resolve` method that resolves a resource from the container by the key it's registered with. -You can learn more about how Query works in [this chapter](undefined/learn/fundamentals/module-links/query). +You can learn more about how Query works in [this chapter](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md). *** ## List of Resources Registered in the Medusa Container -Find a full list of the registered resources and their registration key in [this reference](undefined/resources/medusa-container-resources) +Find a full list of the registered resources and their registration key in [this reference](https://docs.medusajs.com/resources/medusa-container-resources/index.html.md) *** @@ -12959,7 +12953,7 @@ This section gives quick examples of how to resolve resources from the Medusa co ### Subscriber -A [subscriber](undefined/learn/fundamentals/events-and-subscribers) function, which is executed when an event is emitted, accepts as a parameter an object with a `container` property, whose value is the Medusa container. Use its `resolve` method to resolve a resource by its registration key: +A [subscriber](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/index.html.md) function, which is executed when an event is emitted, accepts as a parameter an object with a `container` property, whose value is the Medusa container. Use its `resolve` method to resolve a resource by its registration key: ```ts highlights={subscriberHighlights} import { SubscriberArgs, type SubscriberConfig } from "@medusajs/framework" @@ -12989,7 +12983,7 @@ export const config: SubscriberConfig = { ### Scheduled Job -A [scheduled job](undefined/learn/fundamentals/scheduled-jobs) function, which is executed at a specified interval, accepts the Medusa container as a parameter. Use its `resolve` method to resolve a resource by its registration key: +A [scheduled job](https://docs.medusajs.com/learn/fundamentals/scheduled-jobs/index.html.md) function, which is executed at a specified interval, accepts the Medusa container as a parameter. Use its `resolve` method to resolve a resource by its registration key: ```ts highlights={scheduledJobHighlights} import { MedusaContainer } from "@medusajs/framework/types" @@ -13022,7 +13016,7 @@ export const config = { ### Workflow Step -A [step in a workflow](undefined/learn/fundamentals/workflows), which is a special function where you build durable execution logic across multiple modules, accepts in its second parameter a `container` property, whose value is the Medusa container. Use its `resolve` method to resolve a resource by its registration key: +A [step in a workflow](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md), which is a special function where you build durable execution logic across multiple modules, accepts in its second parameter a `container` property, whose value is the Medusa container. Use its `resolve` method to resolve a resource by its registration key: ```ts highlights={workflowStepsHighlight} import { @@ -13048,9 +13042,9 @@ const step1 = createStep("step-1", async (_, { container }) => { ### Module Services and Loaders -A [module](undefined/learn/fundamentals/modules), which is a package of functionalities for a single feature or domain, has its own container, so it can't resolve resources from the Medusa container. +A [module](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md), which is a package of functionalities for a single feature or domain, has its own container, so it can't resolve resources from the Medusa container. -Learn more about the module's container in [this chapter](undefined/learn/fundamentals/modules/container). +Learn more about the module's container in [this chapter](https://docs.medusajs.com/learn/fundamentals/modules/container/index.html.md). *** @@ -13060,7 +13054,7 @@ When you resolve a resource from the Medusa container, you can use auto-completi This is possible due to Medusa's auto-generated types, which are generated in the `.medusa` directory when you run the `dev` command. -Learn more in the [Auto-Generated Types](undefined/learn/fundamentals/generated-types) chapter. +Learn more in the [Auto-Generated Types](https://docs.medusajs.com/learn/fundamentals/generated-types/index.html.md) chapter. # Add Columns to a Link Table @@ -13069,7 +13063,7 @@ In this chapter, you'll learn how to add custom columns to a link definition's t ## Link Table's Default Columns -When you define a link between two data models, Medusa creates a link table in the database to store the IDs of the linked records. You can learn more about the created table in the [Module Links chapter](undefined/learn/fundamentals/module-links). +When you define a link between two data models, Medusa creates a link table in the database to store the IDs of the linked records. You can learn more about the created table in the [Module Links chapter](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md). In various cases, you might need to store additional data in the link table. For example, if you define a link between a `product` and a `post`, you might want to store the publish date of the product's post in the link table. @@ -13150,7 +13144,7 @@ The object you pass to Link's `create` method accepts a `data` property. Its val For example: -Learn more about Link, how to resolve it, and its methods in [this chapter](undefined/learn/fundamentals/module-links/link). +Learn more about Link, how to resolve it, and its methods in [this chapter](https://docs.medusajs.com/learn/fundamentals/module-links/link/index.html.md). ```ts await link.create({ @@ -13172,7 +13166,31 @@ await link.create({ ## Retrieve Custom Column with Link -To retrieve linked records with their custom columns, use [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md). A module link's definition, exported by a file under `src/links`, has a special `entryPoint` property. Use this property when specifying the `entity` property in Query's `graph` method. +To retrieve linked records with their custom columns, use [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md). This section explores two methods to retrieve a link's custom columns. + +### Method 1: Using Special Link Field + +A data model will have a special field for all its link tables. The field's name is in the `{camel_case_data_model_name}_link` format, where `{camel_case_data_model_name}` is the name of the linked data model in camel case. + +For example: + +```ts highlights={method1Highlights} +const { data } = await query.graph({ + entity: "product", + fields: ["id", "title", "post_link.metadata", "post.*"], + filters: { + id: "prod_123", + }, +}) +``` + +In this example, you retrieve a product and the `metadata` custom column in the link table between `product` and `post` using the `post_link.metadata` field. + +You can also retrieve all custom columns in the link table using the `post_link.*` field. + +### Method 2: Using Entry Point + +A module link's definition, exported by a file under `src/links`, has a special `entryPoint` property. Use this property when specifying the `entity` property in Query's `graph` method. For example: @@ -13225,7 +13243,7 @@ await link.create({ In this chapter, you'll learn about the difference in module link directions, and which to use based on your use case. -The details in this chapter don't apply to [Read-Only Module Links](undefined/learn/fundamentals/module-links/read-only). Refer to the [Read-Only Module Links chapter](undefined/learn/fundamentals/module-links/read-only) for more information on read-only links and their direction. +The details in this chapter don't apply to [Read-Only Module Links](https://docs.medusajs.com/learn/fundamentals/module-links/read-only/index.html.md). Refer to the [Read-Only Module Links chapter](https://docs.medusajs.com/learn/fundamentals/module-links/read-only/index.html.md) for more information on read-only links and their direction. ## Link Direction @@ -13292,7 +13310,7 @@ The Index Module is experimental and still in development, so it is subject to c The Index Module is a tool to perform high-performance queries across modules, for example, to filter linked modules. -While modules share the same database by default, Medusa [isolates modules](undefined/learn/fundamentals/modules/isolation) to allow using external data sources or different database types. +While modules share the same database by default, Medusa [isolates modules](https://docs.medusajs.com/learn/fundamentals/modules/isolation/index.html.md) to allow using external data sources or different database types. So, when you retrieve data across modules using Query, Medusa aggregates the data coming from different modules to create the end result. This approach limits your ability to filter data by linked modules. For example, you can't filter products (created in the Product Module) by their brand (created in the Brand Module). @@ -13401,7 +13419,7 @@ Notice the `estimate_count` property, which is the estimated total number of pro ## How to Use the Index Module -The Index Module adds a new `index` method to [Query](undefined/learn/fundamentals/module-links/query) and it has the same API as the `graph` method. +The Index Module adds a new `index` method to [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md) and it has the same API as the `graph` method. For example, to filter products by a sales channel ID: @@ -13447,7 +13465,7 @@ Aside from the [core data models](#ingested-data-models), you can also ingest yo Read-only links are not supported by the Index Module. -For example, assuming you have a Brand Module with a Brand data model (as explained in the [Customizations](undefined/learn/customization/custom-features/module)), you can ingest it into the Index Module using the `filterable` property in its link definition to the Product data model: +For example, assuming you have a Brand Module with a Brand data model (as explained in the [Customizations](https://docs.medusajs.com/learn/customization/custom-features/module/index.html.md)), you can ingest it into the Index Module using the `filterable` property in its link definition to the Product data model: ```ts title="src/links/product-brand.ts" highlights={filterableHighlights} import BrandModule from "../modules/brand" @@ -13617,7 +13635,7 @@ This will return all products with their linked brand data model. ### Use Advanced Filters -When setting filters on properties, you can use advanced filters like `$ne` and `$gt`. These are the same advanced filters accepted by the [listing methods generated by the Service Factory](undefined/resources/service-factory-reference/tips/filtering). +When setting filters on properties, you can use advanced filters like `$ne` and `$gt`. These are the same advanced filters accepted by the [listing methods generated by the Service Factory](https://docs.medusajs.com/resources/service-factory-reference/tips/filtering/index.html.md). For example, to only retrieve products linked to a brand: @@ -13661,9 +13679,9 @@ This will return all products whose brand name starts with `Acme`. ### Use Request Query Configurations -API routes using the `graph` method can configure default [query configurations](undefined/learn/fundamentals/module-links/query#request-query-configurations), such as which fields to retrieve, while also allowing clients to override them using query parameters. +API routes using the `graph` method can configure default [query configurations](https://docs.medusajs.com/learn/fundamentals/module-links/query#request-query-configurations/index.html.md), such as which fields to retrieve, while also allowing clients to override them using query parameters. -The `index` method supports the same configurations. For example, if you add the request query configuration as explained in the [Query documentation](undefined/learn/fundamentals/module-links/query#request-query-configurations), you can use those configurations in the `index` method: +The `index` method supports the same configurations. For example, if you add the request query configuration as explained in the [Query documentation](https://docs.medusajs.com/learn/fundamentals/module-links/query#request-query-configurations/index.html.md), you can use those configurations in the `index` method: ```ts title="src/api/custom/products/route.ts" highlights={[["17"]]} import { @@ -13804,7 +13822,7 @@ await link.create({ The `create` method accepts as a parameter an object. The object’s keys are the names of the linked modules. -The keys (names of linked modules) must be in the same [direction](undefined/learn/fundamentals/module-links/directions) of the link definition. +The keys (names of linked modules) must be in the same [direction](https://docs.medusajs.com/learn/fundamentals/module-links/directions/index.html.md) of the link definition. The value of each module’s property is an object, whose keys are of the format `{data_model_snake_name}_id`, and values are the IDs of the linked record. @@ -13899,7 +13917,7 @@ await link.dismiss({ The `dismiss` method accepts the same parameter type as the [create method](#create-link). -The keys (names of linked modules) must be in the same [direction](undefined/learn/fundamentals/module-links/directions) of the link definition. +The keys (names of linked modules) must be in the same [direction](https://docs.medusajs.com/learn/fundamentals/module-links/directions/index.html.md) of the link definition. *** @@ -13954,11 +13972,11 @@ In this chapter, you’ll learn what a module link is and how to define one. ## What is a Module Link? -Medusa's modular architecture isolates modules from one another to ensure they can be integrated into your application without side effects. Module isolation has other benefits, which you can learn about in the [Module Isolation chapter](undefined/learn/fundamentals/modules/isolation). Since modules are isolated, you can't access another module's data models to add a relation to it or extend it. Instead, you use a module link. +Medusa's modular architecture isolates modules from one another to ensure they can be integrated into your application without side effects. Module isolation has other benefits, which you can learn about in the [Module Isolation chapter](https://docs.medusajs.com/learn/fundamentals/modules/isolation/index.html.md). Since modules are isolated, you can't access another module's data models to add a relation to it or extend it. Instead, you use a module link. A module link forms an association between two data models of different modules while maintaining module isolation. Using module links, you can build virtual relations between your custom data models and data models in the Commerce Modules, which is useful as you extend the features provided by the Commerce Modules. Then, Medusa creates a link table in the database to store the IDs of the linked records. You'll learn more about link tables later in this chapter. -For example, the [Brand Customizations Tutorial](undefined/learn/customization/extend-features) shows how to create a Brand Module that adds the concept of brands to your application, then link those brands to a product. +For example, the [Brand Customizations Tutorial](https://docs.medusajs.com/learn/customization/extend-features/index.html.md) shows how to create a Brand Module that adds the concept of brands to your application, then link those brands to a product. *** @@ -14008,13 +14026,13 @@ When you define a module link, the Medusa application creates a table in the dat - `module1` and `module2` are the names of the modules. - `table1` and `table2` are the table names of the data models. -For example, if you define a link between the `Product` data model from the [Product Module](undefined/resources/commerce-modules/product) and a `Post` data model from a Blog Module, the table name would be `product_product_blog_post`. +For example, if you define a link between the `Product` data model from the [Product Module](https://docs.medusajs.com/resources/commerce-modules/product/index.html.md) and a `Post` data model from a Blog Module, the table name would be `product_product_blog_post`. The table has two columns, each storing the ID of a record from the linked data models. For example, the `product_product_blog_post` table would have columns `product_id` and `post_id`. These columns store only the IDs of the linked records and do not hold a foreign key constraint. Then, when you create links between records of the data models, the IDs of these data models are stored as a new record in the link's table. -You can also add custom columns in the link table as explained in the [Add Columns to Link Table chapter](undefined/learn/fundamentals/module-links/custom-columns). +You can also add custom columns in the link table as explained in the [Add Columns to Link Table chapter](https://docs.medusajs.com/learn/fundamentals/module-links/custom-columns/index.html.md). ![Diagram illustration for module links](https://res.cloudinary.com/dza7lstvk/image/upload/v1741696766/Medusa%20Book/custom-links_vezsx8.jpg) @@ -14165,7 +14183,7 @@ npx medusa db:migrate # Query Context -In this chapter, you'll learn how to pass context when retrieving data with [Query](undefined/learn/fundamentals/module-links/query). +In this chapter, you'll learn how to pass context when retrieving data with [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md). ## What is Query Context? @@ -14173,7 +14191,7 @@ Query context is additional information you pass to Query when retrieving data. For example, consider a Blog Module with posts and authors. You can send the user's language as context to Query to retrieve posts in the user's language. -Medusa also uses Query Context to [retrieve product variants' prices based on the customer's currency](undefined/resources/commerce-modules/product/guides/price). +Medusa also uses Query Context to [retrieve product variants' prices based on the customer's currency](https://docs.medusajs.com/resources/commerce-modules/product/guides/price/index.html.md). *** @@ -14203,7 +14221,7 @@ In this example, you pass a `lang` property with the value `es` in the context. ### How to Handle Query Context -To handle the Query context passed while retrieving records of your data models, override the [generated list method](undefined/resources/service-factory-reference/methods/list) of the associated module's service. +To handle the Query context passed while retrieving records of your data models, override the [generated list method](https://docs.medusajs.com/resources/service-factory-reference/methods/list/index.html.md) of the associated module's service. For example, continuing the example above, you can override the `listPosts` method of the Blog Module's service to handle the Query context: @@ -14252,7 +14270,7 @@ All posts returned will now have their titles appended with "en español". ### Using Pagination with Query -If you pass pagination fields to `query.graph`, you must also override the [generated listAndCount method](undefined/resources/service-factory-reference/methods/listAndCount) in the service. +If you pass pagination fields to `query.graph`, you must also override the [generated listAndCount method](https://docs.medusajs.com/resources/service-factory-reference/methods/listAndCount/index.html.md) in the service. For example, following the previous example, you must override the `listAndCountPosts` method of the Blog Module's service: @@ -14403,7 +14421,7 @@ In this chapter, you’ll learn about Query and how to use it to fetch data from Query fetches data across modules. It’s a set of methods registered in the Medusa container under the `query` key. -In all resources that can access the [Medusa Container](undefined/learn/fundamentals/medusa-container), such as API routes or workflows, you can resolve Query to fetch data across custom modules and Medusa’s Commerce Modules. +In all resources that can access the [Medusa Container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md), such as API routes or workflows, you can resolve Query to fetch data across custom modules and Medusa’s Commerce Modules. *** @@ -14457,7 +14475,7 @@ The method returns an object that has a `data` property, which holds an array of ### Query Usage in Workflows -To retrieve data with Query in a [workflow](undefined/learn/fundamentals/workflows), use the [useQueryGraphStep](undefined/resources/references/helper-steps/useQueryGraphStep). +To retrieve data with Query in a [workflow](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md), use the [useQueryGraphStep](https://docs.medusajs.com/resources/references/helper-steps/useQueryGraphStep/index.html.md). For example: @@ -14480,7 +14498,7 @@ const myWorkflow = createWorkflow( ) ``` -You can learn more about this step in the [useQueryGraphStep](undefined/resources/references/helper-steps/useQueryGraphStep) reference. +You can learn more about this step in the [useQueryGraphStep](https://docs.medusajs.com/resources/references/helper-steps/useQueryGraphStep/index.html.md) reference. The rest of this chapter uses the `graph` method to explain the different usages of Query, but the same principles apply to `useQueryGraphStep`. @@ -14552,7 +14570,7 @@ In the example above, you retrieve all products linked to a post. Consider that you want to apply filters or pagination configurations on the product(s) linked to a `post`. To do that, you must query the module link's table instead. -As mentioned in the [Module Link](undefined/learn/fundamentals/module-links) documentation, Medusa creates a table for your module link. So, not only can you retrieve linked records, but you can also retrieve the records in a module link's table. +As mentioned in the [Module Link](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md) documentation, Medusa creates a table for your module link. So, not only can you retrieve linked records, but you can also retrieve the records in a module link's table. A module link's definition, exported by a file under `src/links`, has a special `entryPoint` property. Use this property when specifying the `entity` property in Query's `graph` method. @@ -14577,7 +14595,7 @@ In the object passed to the `graph` method: - You pass the `entryPoint` property of the link definition as the value for `entity`. So, Query will retrieve records from the module link's table. - You pass three items to the `fields` property: - - `*` to retrieve the link table's fields. This is useful if the link table has [custom columns](undefined/learn/fundamentals/module-links/custom-columns). + - `*` to retrieve the link table's fields. This is useful if the link table has [custom columns](https://docs.medusajs.com/learn/fundamentals/module-links/custom-columns/index.html.md). - `product.*` to retrieve the fields of a product record linked to a `Post` record. - `post.*` to retrieve the fields of a `Post` record linked to a product record. @@ -14649,7 +14667,7 @@ Both methods accept a filter object that can be used to filter records. Those filters don't just allow you to filter by exact values. You can also filter by properties that don't match a value, match multiple values, and other filter types. -Refer to the [Service Factory Reference](undefined/resources/service-factory-reference/tips/filtering) for examples of advanced filters. The following sections provide some quick examples. +Refer to the [Service Factory Reference](https://docs.medusajs.com/resources/service-factory-reference/tips/filtering/index.html.md) for examples of advanced filters. The following sections provide some quick examples. #### Filter by Not Matching a Value @@ -14939,7 +14957,7 @@ In the example above, Query throws an error if no author is found with the ID `a For API routes that retrieve a single or list of resources, Medusa provides a `validateAndTransformQuery` middleware that: -- Validates accepted query parameters, as explained in [this documentation](undefined/learn/fundamentals/api-routes/validation). +- Validates accepted query parameters, as explained in [this documentation](https://docs.medusajs.com/learn/fundamentals/api-routes/validation/index.html.md). - Parses configurations that are received as query parameters to be passed to Query. Using this middleware allows you to have default configurations for retrieved fields and relations or pagination, while allowing clients to customize them per request. @@ -14982,7 +15000,7 @@ export default defineMiddlewares({ The `validateAndTransformQuery` accepts two parameters: -1. A Zod validation schema for the query parameters, which you can learn more about in the [API Route Validation documentation](undefined/learn/fundamentals/api-routes/validation). Medusa has a `createFindParams` utility that generates a Zod schema that accepts four query parameters: +1. A Zod validation schema for the query parameters, which you can learn more about in the [API Route Validation documentation](https://docs.medusajs.com/learn/fundamentals/api-routes/validation/index.html.md). Medusa has a `createFindParams` utility that generates a Zod schema that accepts four query parameters: 1. `fields`: The fields and relations to retrieve in the returned resources. 2. `offset`: The number of items to skip before retrieving the returned items. 3. `limit`: The maximum number of items to return. @@ -15048,7 +15066,7 @@ To test it out, start your Medusa application and send a `GET` request to the `/ Try passing one of the Query configuration parameters, like `fields` or `limit`, and you'll see its impact on the returned result. -Learn more about [specifying fields and relations](undefined/api/store#select-fields-and-relations) and [pagination](undefined/api/store#pagination) in the API reference. +Learn more about [specifying fields and relations](https://docs.medusajs.com/api/store#select-fields-and-relations) and [pagination](https://docs.medusajs.com/api/store#pagination) in the API reference. # Read-Only Module Link @@ -15059,9 +15077,9 @@ In this chapter, you’ll learn what a read-only module link is and how to defin Consider a scenario where you need to access related records from another module, but don't want the overhead of managing or storing the links between them. This can include cases where you're working with external data models not stored in your Medusa database, such as third-party systems. -In those cases, instead of defining a [Module Link](undefined/learn/fundamentals/module-links) whose linked records must be stored in a link table in the database, you can use a read-only module link. A read-only module link builds a virtual relation from one data model to another in a different module without creating a link table in the database. Instead, the linked record's ID is stored in the first data model's field. +In those cases, instead of defining a [Module Link](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md) whose linked records must be stored in a link table in the database, you can use a read-only module link. A read-only module link builds a virtual relation from one data model to another in a different module without creating a link table in the database. Instead, the linked record's ID is stored in the first data model's field. -For example, Medusa creates a read-only module link from the `Cart` data model of the [Cart Module](undefined/resources/commerce-modules/cart) to the `Customer` data model of the [Customer Module](undefined/resources/commerce-modules/customer). This link allows you to access the details of the cart's customer without managing the link. Instead, the customer's ID is stored in the `Cart` data model. +For example, Medusa creates a read-only module link from the `Cart` data model of the [Cart Module](https://docs.medusajs.com/resources/commerce-modules/cart/index.html.md) to the `Customer` data model of the [Customer Module](https://docs.medusajs.com/resources/commerce-modules/customer/index.html.md). This link allows you to access the details of the cart's customer without managing the link. Instead, the customer's ID is stored in the `Cart` data model. ![Diagram illustrating the read-only module link from cart to customer](https://res.cloudinary.com/dza7lstvk/image/upload/v1742212508/Medusa%20Book/cart-customer_w6vk59.jpg) @@ -15071,7 +15089,7 @@ For example, Medusa creates a read-only module link from the `Cart` data model o The `defineLink` function accepts an optional third-parameter object that can hold additional configurations for the module link. -If you're not familiar with the `defineLink` function, refer to the [Module Links chapter](undefined/learn/fundamentals/module-links) for more information. +If you're not familiar with the `defineLink` function, refer to the [Module Links chapter](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md) for more information. To make the module link read-only, pass the `readOnly` property as `true`. You must also set in the link configuration of the first data model a `field` property that specifies the data model's field where the linked record's ID is stored. @@ -15105,7 +15123,7 @@ Unlike the stored module link, Medusa will not create a table in the database fo ## Retrieve Read-Only Linked Record -[Query](undefined/learn/fundamentals/module-links/query) allows you to retrieve records linked through a read-only module link. +[Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md) allows you to retrieve records linked through a read-only module link. For example, assuming you have the module link created in [the above section](#how-to-define-a-read-only-module-link), you can retrieve a post and its linked product as follows: @@ -15430,7 +15448,7 @@ To define the read-only module link, you must pass to `defineLink`: 1. An object with the linkable configuration of the data model in Medusa, and the fields that will be passed as a filter to the CMS service. - For example, if you want to filter by product title instead, you can pass `title` instead of `id`. 2. An object with the linkable configuration of the virtual data model in the CMS. This object must have the following properties: - - `serviceName`: The name of the service, which is the CMS Module's name. Medusa uses this name to resolve the module's service from the [Medusa container](undefined/learn/fundamentals/medusa-container). + - `serviceName`: The name of the service, which is the CMS Module's name. Medusa uses this name to resolve the module's service from the [Medusa container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md). - `alias`: The alias to use when querying the linked records. You'll see how that works in a bit. - `primaryKey`: The field in the CMS data model that holds the ID of a product. 3. The third parameter: an object with the `readOnly` property set to `true`. @@ -15506,7 +15524,7 @@ The `list` method accepts an object of filters holding the ID(s) of the products The returned posts must include the product's ID in a field with the same name as the `primary_key` option in the link configurations, which is `product_id` in this case. -You can also create a `listAndCount` method to retrieve the posts with pagination. This method is called if you pass [pagination parameters to Query](undefined/learn/fundamentals/module-links/query#apply-pagination). +You can also create a `listAndCount` method to retrieve the posts with pagination. This method is called if you pass [pagination parameters to Query](https://docs.medusajs.com/learn/fundamentals/module-links/query#apply-pagination/index.html.md). ### c. Query Linked Records @@ -15558,7 +15576,7 @@ If multiple posts have their `product_id` set to a product's ID, an array of pos ] ``` -[Sanity Integration Tutorial](undefined/resources/integrations/guides/sanity). +[Sanity Integration Tutorial](https://docs.medusajs.com/resources/integrations/guides/sanity/index.html.md). # Commerce Modules @@ -15567,25 +15585,25 @@ In this chapter, you'll learn about Medusa's Commerce Modules. ## What is a Commerce Module? -Commerce Modules are built-in [modules](undefined/learn/fundamentals/modules) of Medusa that provide core commerce logic specific to domains like Products, Orders, Customers, Fulfillment, and much more. +Commerce Modules are built-in [modules](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md) of Medusa that provide core commerce logic specific to domains like Products, Orders, Customers, Fulfillment, and much more. -Medusa's Commerce Modules are used to form Medusa's default [workflows](undefined/resources/medusa-workflows-reference) and [APIs](undefined/api/store). For example, when you call the add to cart endpoint. the add to cart workflow runs which uses the Product Module to check if the product exists, the Inventory Module to ensure the product is available in the inventory, and the Cart Module to finally add the product to the cart. +Medusa's Commerce Modules are used to form Medusa's default [workflows](https://docs.medusajs.com/resources/medusa-workflows-reference/index.html.md) and [APIs](https://docs.medusajs.com/api/store). For example, when you call the add to cart endpoint. the add to cart workflow runs which uses the Product Module to check if the product exists, the Inventory Module to ensure the product is available in the inventory, and the Cart Module to finally add the product to the cart. -You'll find the details and steps of the add-to-cart workflow in [this workflow reference](undefined/resources/references/medusa-workflows/addToCartWorkflow) +You'll find the details and steps of the add-to-cart workflow in [this workflow reference](https://docs.medusajs.com/resources/references/medusa-workflows/addToCartWorkflow/index.html.md) The core commerce logic contained in Commerce Modules is also available directly when you are building customizations. This granular access to commerce functionality is unique and expands what's possible to build with Medusa drastically. ### List of Medusa's Commerce Modules -Refer to [this reference](undefined/resources/commerce-modules) for a full list of Commerce Modules in Medusa. +Refer to [this reference](https://docs.medusajs.com/resources/commerce-modules/index.html.md) for a full list of Commerce Modules in Medusa. *** ## Use Commerce Modules in Custom Flows -Similar to your [custom modules](undefined/learn/fundamentals/modules), the Medusa application registers a Commerce Module's service in the [container](undefined/learn/fundamentals/medusa-container). So, you can resolve it in your custom flows. This is useful as you build unique requirements extending core commerce features. +Similar to your [custom modules](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md), the Medusa application registers a Commerce Module's service in the [container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md). So, you can resolve it in your custom flows. This is useful as you build unique requirements extending core commerce features. -For example, consider you have a [workflow](undefined/learn/fundamentals/workflows) (a special function that performs a task in a series of steps with rollback mechanism) that needs a step to retrieve the total number of products. You can create a step in the workflow that resolves the Product Module's service from the container to use its methods: +For example, consider you have a [workflow](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) (a special function that performs a task in a series of steps with rollback mechanism) that needs a step to retrieve the total number of products. You can create a step in the workflow that resolves the Product Module's service from the container to use its methods: ```ts highlights={highlights} import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk" @@ -15609,13 +15627,13 @@ Your workflow can use services of both custom and Commerce Modules, supporting y In this chapter, you'll learn about the module container and how to resolve resources from it. -Since modules are [isolated](undefined/learn/fundamentals/modules/isolation), each module has a local container used only by the resources of that module. +Since modules are [isolated](https://docs.medusajs.com/learn/fundamentals/modules/isolation/index.html.md), each module has a local container used only by the resources of that module. So, resources in the module, such as services or loaders, can only resolve other resources registered in the module's container, and some Framework tools that the Medusa application registers in the module's container. ### List of Registered Resources -Find a list of resources or dependencies registered in a module's container in [the Container Resources reference](undefined/resources/medusa-container-resources). +Find a list of resources or dependencies registered in a module's container in [the Container Resources reference](https://docs.medusajs.com/resources/medusa-container-resources/index.html.md). *** @@ -15625,7 +15643,7 @@ Find a list of resources or dependencies registered in a module's container in [ A service's constructor accepts as a first parameter an object used to resolve resources registered in the module's container. To resolve a resource, add the resource's registration name as a property of the object. -For example, to resolve the [Logger](undefined/learn/debugging-and-testing/logging) from the container: +For example, to resolve the [Logger](https://docs.medusajs.com/learn/debugging-and-testing/logging/index.html.md) from the container: ```ts highlights={[["4"], ["10"]]} import { Logger } from "@medusajs/framework/types" @@ -15651,9 +15669,9 @@ You can then use the logger in the service's methods. ### Resolve in Loaders -[Loaders](undefined/learn/fundamentals/modules/loaders) accept an object parameter with the property `container`. Its value is the module's container that can be used to resolve resources using its `resolve` method. +[Loaders](https://docs.medusajs.com/learn/fundamentals/modules/loaders/index.html.md) accept an object parameter with the property `container`. Its value is the module's container that can be used to resolve resources using its `resolve` method. -For example, to resolve the [Logger](undefined/learn/debugging-and-testing/logging) in a loader: +For example, to resolve the [Logger](https://docs.medusajs.com/learn/debugging-and-testing/logging/index.html.md) in a loader: ```ts highlights={[["9"]]} import { @@ -15682,7 +15700,7 @@ Consider a module that has a main service `BrandModuleService`, and an internal However, loaders are executed before any services are initialized and registered in the module's container. So, you can't resolve the `BrandModuleService` and `CmsService` in a loader. -Instead, if your main service extends the `MedusaService` [service factory](undefined/learn/fundamentals/modules/service-factory), you can resolve the internal services generated for each data model passed to the `MedusaService` function. +Instead, if your main service extends the `MedusaService` [service factory](https://docs.medusajs.com/learn/fundamentals/modules/service-factory/index.html.md), you can resolve the internal services generated for each data model passed to the `MedusaService` function. For example, if the `BrandModuleService` is defined as follows: @@ -15716,19 +15734,19 @@ export default async function helloWorldLoader({ } ``` -Refer to the [Service Factory reference](undefined/resources/service-factory-reference) for details on the available methods in the generated services. +Refer to the [Service Factory reference](https://docs.medusajs.com/resources/service-factory-reference/index.html.md) for details on the available methods in the generated services. *** ## Alternative to Resolving Other Modules' Services -Since modules are [isolated](undefined/learn/fundamentals/modules/isolation), you can't resolve resources that belong to other modules from the module's container. For example, you can't resolve the Product Module's service in the Blog Module's service. +Since modules are [isolated](https://docs.medusajs.com/learn/fundamentals/modules/isolation/index.html.md), you can't resolve resources that belong to other modules from the module's container. For example, you can't resolve the Product Module's service in the Blog Module's service. -Instead, to build commerce features that span multiple modules, you can create [workflows](undefined/learn/fundamentals/workflows). In those workflows, you can resolve services of all modules registered in the Medusa application, including the services of the Product and Blog modules. +Instead, to build commerce features that span multiple modules, you can create [workflows](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md). In those workflows, you can resolve services of all modules registered in the Medusa application, including the services of the Product and Blog modules. -Then, you can execute the workflows in [API routes](undefined/learn/fundamentals/api-routes), [subscribers](undefined/learn/fundamentals/events-and-subscribers), or [scheduled jobs](undefined/learn/fundamentals/scheduled-jobs). +Then, you can execute the workflows in [API routes](https://docs.medusajs.com/learn/fundamentals/api-routes/index.html.md), [subscribers](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/index.html.md), or [scheduled jobs](https://docs.medusajs.com/learn/fundamentals/scheduled-jobs/index.html.md). -Learn more and find examples in the [Module Isolation](undefined/learn/fundamentals/modules/isolation) chapter. +Learn more and find examples in the [Module Isolation](https://docs.medusajs.com/learn/fundamentals/modules/isolation/index.html.md) chapter. *** @@ -15743,7 +15761,7 @@ Instead, you should generally only resolve services within the main service. For In this chapter, you'll learn how to perform database operations in a module's service. -This chapter is intended for more advanced database use-cases where you need more control over queries and operations. For basic database operations, such as creating or retrieving data of a model, use the [Service Factory](undefined/learn/fundamentals/modules/service-factory) instead. +This chapter is intended for more advanced database use-cases where you need more control over queries and operations. For basic database operations, such as creating or retrieving data of a model, use the [Service Factory](https://docs.medusajs.com/learn/fundamentals/modules/service-factory/index.html.md) instead. ## Run Queries @@ -15811,7 +15829,7 @@ For both approaches, you must wrap the method performing the database operations ### Wrap Database Operations in Transactions -When performing database operations without using the [Service Factory](undefined/learn/fundamentals/modules/service-factory), you must wrap the method performing the database operations in a transaction. +When performing database operations without using the [Service Factory](https://docs.medusajs.com/learn/fundamentals/modules/service-factory/index.html.md), you must wrap the method performing the database operations in a transaction. To wrap database operations in a transaction, you create two methods: @@ -16045,7 +16063,7 @@ You can then use the data model repository in your service to perform database o A data model repository has methods that allows you to create, update, and delete records, among other operations. -To learn about the methods available in a data model repository, refer to the [Data Model Repository](undefined/resources/data-model-repository-reference) reference. +To learn about the methods available in a data model repository, refer to the [Data Model Repository](https://docs.medusajs.com/resources/data-model-repository-reference/index.html.md) reference. ### Perform Database Operations with the Transactional Entity Manager @@ -16376,7 +16394,7 @@ There are different Infrastructure Module types including: ## Infrastructure Modules List -Refer to the [Infrastructure Modules reference](undefined/resources/infrastructure-modules) for a list of Medusa’s Infrastructure Modules, available modules to install, and how to create an Infrastructure Module. +Refer to the [Infrastructure Modules reference](https://docs.medusajs.com/resources/infrastructure-modules/index.html.md) for a list of Medusa’s Infrastructure Modules, available modules to install, and how to create an Infrastructure Module. # Module Isolation @@ -16384,8 +16402,8 @@ Refer to the [Infrastructure Modules reference](undefined/resources/infrastructu In this chapter, you'll learn how modules are isolated, and what that means for your custom development. - Modules can't access resources, such as services or data models, from other modules. -- Use [Module Links](undefined/learn/fundamentals/module-links) to extend an existing module's data models, and [Query](undefined/learn/fundamentals/module-links/query) to retrieve data across modules. -- Use [workflows](undefined/learn/fundamentals/workflows) to build features that depend on functionalities from different modules. +- Use [Module Links](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md) to extend an existing module's data models, and [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md) to retrieve data across modules. +- Use [workflows](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) to build features that depend on functionalities from different modules. ## How are Modules Isolated? @@ -16393,9 +16411,9 @@ A module is unaware of any resources other than its own, such as services or dat For example, your custom module can't resolve the Product Module's main service or have direct relationships from its data model to the Product Module's data models. -A module has its own container, as explained in the [Module Container](undefined/learn/fundamentals/modules/container) chapter. This container includes the module's resources, such as services and data models, and some Framework resources that the Medusa application provides. +A module has its own container, as explained in the [Module Container](https://docs.medusajs.com/learn/fundamentals/modules/container/index.html.md) chapter. This container includes the module's resources, such as services and data models, and some Framework resources that the Medusa application provides. -Refer to the [Module Container Resources](undefined/resources/medusa-container-resources) for a list of resources registered in a module's container. +Refer to the [Module Container Resources](https://docs.medusajs.com/resources/medusa-container-resources/index.html.md) for a list of resources registered in a module's container. *** @@ -16411,9 +16429,9 @@ Some of the module isolation's benefits include: ## How to Extend Data Model of Another Module? -To extend the data model of another module, such as the `Product` data model of the Product Module, use [Module Links](undefined/learn/fundamentals/module-links). Module Links allow you to build associations between data models of different modules without breaking the module isolation. +To extend the data model of another module, such as the `Product` data model of the Product Module, use [Module Links](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md). Module Links allow you to build associations between data models of different modules without breaking the module isolation. -Then, you can retrieve data across modules using [Query](undefined/learn/fundamentals/module-links/query). +Then, you can retrieve data across modules using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md). *** @@ -16421,7 +16439,7 @@ Then, you can retrieve data across modules using [Query](undefined/learn/fundame You'll often build feature that uses functionalities from different modules. For example, if you may need to retrieve brands, then sync them to a third-party service. -To build functionalities spanning across modules and systems, create a [workflow](undefined/learn/fundamentals/workflows) whose steps resolve the modules' services to perform these functionalities. +To build functionalities spanning across modules and systems, create a [workflow](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) whose steps resolve the modules' services to perform these functionalities. Workflows ensure data consistency through their roll-back mechanism and tracking of each execution's status, steps, input, and output. @@ -16494,7 +16512,7 @@ You can then use this workflow in an API route, scheduled job, or other resource ### Framework Tools in Module Container -A module has in its container some Framework APIs and tools, such as [Logger](undefined/learn/debugging-and-testing/logging). You can refer to the [Module Container Resources](undefined/resources/medusa-container-resources) for a list of resources registered in a module's container. +A module has in its container some Framework APIs and tools, such as [Logger](https://docs.medusajs.com/learn/debugging-and-testing/logging/index.html.md). You can refer to the [Module Container Resources](https://docs.medusajs.com/resources/medusa-container-resources/index.html.md) for a list of resources registered in a module's container. You can resolve those resources in the module's services and loaders. @@ -16524,7 +16542,7 @@ In this example, the `BlogModuleService` class resolves the `Logger` service fro ### Using Framework Tools in Workflows -Some Framework APIs and tools are not registered in the module's container. For example, [Query](undefined/learn/fundamentals/module-links/query) is only registered in the Medusa container. +Some Framework APIs and tools are not registered in the module's container. For example, [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md) is only registered in the Medusa container. You should, instead, build workflows that use these APIs and tools along with your module's service. @@ -16578,8 +16596,8 @@ In the `createBrandsInCmsStep`, you resolve the CMS Module's service from the mo ### Injecting Dependencies to Module -Some cases still require you to access external resources, mainly [Infrastructure Modules](undefined/resources/infrastructure-modules) or Framework tools, in your module. -For example, you may need the [Event Module](undefined/resources/infrastructure-modules/event) to emit events from your module's service. +Some cases still require you to access external resources, mainly [Infrastructure Modules](https://docs.medusajs.com/resources/infrastructure-modules/index.html.md) or Framework tools, in your module. +For example, you may need the [Event Module](https://docs.medusajs.com/resources/infrastructure-modules/event/index.html.md) to emit events from your module's service. In those cases, you can inject the dependencies to your module's service in `medusa-config.ts` using the `dependencies` property of the module's configuration. @@ -16640,11 +16658,11 @@ In this chapter, you’ll learn about loaders and how to use them. When building a commerce application, you'll often need to execute an action the first time the application starts. For example, if your application needs to connect to databases other than Medusa's PostgreSQL database, you might need to establish a connection on application startup. -In Medusa, you can execute an action when the application starts using a loader. A loader is a function exported by a [module](undefined/learn/fundamentals/modules), which is a package of business logic for a single domain. When the Medusa application starts, it executes all loaders exported by configured modules. +In Medusa, you can execute an action when the application starts using a loader. A loader is a function exported by a [module](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md), which is a package of business logic for a single domain. When the Medusa application starts, it executes all loaders exported by configured modules. -Loaders are useful to register custom resources, such as database connections, in the [module's container](undefined/learn/fundamentals/modules/container), which is similar to the [Medusa container](undefined/learn/fundamentals/medusa-container) but includes only [resources available to the module](undefined/resources/medusa-container-resources#module-container-resources). Modules are isolated, so they can't access resources outside of them, such as a service in another module. +Loaders are useful to register custom resources, such as database connections, in the [module's container](https://docs.medusajs.com/learn/fundamentals/modules/container/index.html.md), which is similar to the [Medusa container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md) but includes only [resources available to the module](https://docs.medusajs.com/resources/medusa-container-resources#module-container-resources/index.html.md). Modules are isolated, so they can't access resources outside of them, such as a service in another module. -Medusa isolates modules to ensure that they're re-usable across applications, aren't tightly coupled to other resources, and don't have implications when integrated into the Medusa application. Learn more about why modules are isolated in [this chapter](undefined/learn/fundamentals/modules/isolation), and check out [this reference for the list of resources in the module's container](undefined/resources/medusa-container-resources#module-container-resources). +Medusa isolates modules to ensure that they're re-usable across applications, aren't tightly coupled to other resources, and don't have implications when integrated into the Medusa application. Learn more about why modules are isolated in [this chapter](https://docs.medusajs.com/learn/fundamentals/modules/isolation/index.html.md), and check out [this reference for the list of resources in the module's container](https://docs.medusajs.com/resources/medusa-container-resources#module-container-resources/index.html.md). *** @@ -16658,7 +16676,7 @@ For example, consider you have a `hello` module, you can create a loader at `src ![Example of loader file in the application's directory structure](https://res.cloudinary.com/dza7lstvk/image/upload/v1732865671/Medusa%20Book/loader-dir-overview_eg6vtu.jpg) -Learn how to create a module in [this chapter](undefined/learn/fundamentals/modules). +Learn how to create a module in [this chapter](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md). ```ts title="src/modules/hello/loaders/hello-world.ts" import { @@ -16678,7 +16696,7 @@ The loader file exports an async function, which is the function executed when t The function receives an object parameter that has a `container` property, which is the module's container that you can use to resolve resources from. In this example, you resolve the Logger utility to log a message in the terminal. -Find the list of resources in the module's container in [this reference](undefined/resources/medusa-container-resources#module-container-resources). +Find the list of resources in the module's container in [this reference](https://docs.medusajs.com/resources/medusa-container-resources#module-container-resources/index.html.md). ### 2. Export Loader in Module Definition @@ -16700,7 +16718,7 @@ The second parameter of the `Module` function accepts a `loaders` property whose ### Test the Loader -Assuming your module is [added to Medusa's configuration](undefined/learn/fundamentals/modules#4-add-module-to-medusas-configurations), you can test the loader by starting the Medusa application: +Assuming your module is [added to Medusa's configuration](https://docs.medusajs.com/learn/fundamentals/modules#4-add-module-to-medusas-configurations/index.html.md), you can test the loader by starting the Medusa application: ```bash npm2yarn npm run dev @@ -16728,7 +16746,7 @@ Loaders are also useful to only load a module if a certain condition is met. For ### Loaders Executed with Migrations -Loaders are also executed when you run [migrations](undefined/learn/fundamentals/data-models/write-migration). This can be useful if you need to run some task before the migrations, or you want to migrate some data to an integrated third-party system as part of the migration process. +Loaders are also executed when you run [migrations](https://docs.medusajs.com/learn/fundamentals/data-models/write-migration/index.html.md). This can be useful if you need to run some task before the migrations, or you want to migrate some data to an integrated third-party system as part of the migration process. *** @@ -16742,8 +16760,8 @@ So, avoid operations that take a long time to complete, such as fetching a large Instead of performing heavy operations in loaders, consider one of the following solutions: -- Use a [scheduled job](undefined/learn/fundamentals/scheduled-jobs) to perform the operation at specified intervals. This way, the operation is performed asynchronously and doesn't block the application startup. -- [Emit custom events](undefined/learn/fundamentals/events-and-subscribers/emit-event) in an [API route](undefined/learn/fundamentals/api-routes), then handle the event in a [subscriber](undefined/learn/fundamentals/events-and-subscribers) to perform the operation asynchronously. You can then send a request to the API route to trigger the operation when needed. +- Use a [scheduled job](https://docs.medusajs.com/learn/fundamentals/scheduled-jobs/index.html.md) to perform the operation at specified intervals. This way, the operation is performed asynchronously and doesn't block the application startup. +- [Emit custom events](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/emit-event/index.html.md) in an [API route](https://docs.medusajs.com/learn/fundamentals/api-routes/index.html.md), then handle the event in a [subscriber](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/index.html.md) to perform the operation asynchronously. You can then send a request to the API route to trigger the operation when needed. *** @@ -16914,13 +16932,13 @@ In this chapter, you'll learn about the expected files and directories in your m ## index.ts -The `index.ts` file is in the root of your module's directory and exports the module's definition as explained in the [Modules](undefined/learn/fundamentals/modules) chapter. +The `index.ts` file is in the root of your module's directory and exports the module's definition as explained in the [Modules](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md) chapter. *** ## service.ts -A module must have a main service that contains the module's business logic. It's created in the `service.ts` file at the root of your module directory as explained in the [Modules](undefined/learn/fundamentals/modules) chapter. +A module must have a main service that contains the module's business logic. It's created in the `service.ts` file at the root of your module directory as explained in the [Modules](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md) chapter. *** @@ -16928,9 +16946,9 @@ A module must have a main service that contains the module's business logic. It' The following directories are optional and you can choose to create them based on your module's functionality: -- `models`: Holds the [data models](undefined/learn/fundamentals/data-models) representing tables in the database. -- `migrations`: Holds the [migration](undefined/learn/fundamentals/data-models/write-migration) files used to reflect changes on the database. -- `loaders`: Holds the [script files to run on the application's startup](undefined/learn/fundamentals/modules/loaders) when Medusa loads the module. +- `models`: Holds the [data models](https://docs.medusajs.com/learn/fundamentals/data-models/index.html.md) representing tables in the database. +- `migrations`: Holds the [migration](https://docs.medusajs.com/learn/fundamentals/data-models/write-migration/index.html.md) files used to reflect changes on the database. +- `loaders`: Holds the [script files to run on the application's startup](https://docs.medusajs.com/learn/fundamentals/modules/loaders/index.html.md) when Medusa loads the module. # Multiple Services in a Module @@ -17209,7 +17227,7 @@ export default async function validationLoader({ } ``` -Then, export the loader in the module's definition file, as explained in [this chapter](undefined/learn/fundamentals/modules/loaders): +Then, export the loader in the module's definition file, as explained in [this chapter](https://docs.medusajs.com/learn/fundamentals/modules/loaders/index.html.md): ```ts title="src/modules/blog/index.ts" // other imports... @@ -17232,7 +17250,7 @@ In this chapter, you’ll learn about modules and how to create them. ## What is a Module? -A module is a reusable package of functionalities related to a single domain or integration. Medusa comes with multiple pre-built modules for core commerce needs, such as the [Cart Module](undefined/resources/commerce-modules/cart) that holds the data models and business logic for cart operations. +A module is a reusable package of functionalities related to a single domain or integration. Medusa comes with multiple pre-built modules for core commerce needs, such as the [Cart Module](https://docs.medusajs.com/resources/commerce-modules/cart/index.html.md) that holds the data models and business logic for cart operations. When building a commerce application, you often need to introduce custom behavior specific to your products, tech stack, or your general ways of working. In other commerce platforms, introducing custom business logic and data models requires setting up separate applications to manage these customizations. @@ -17242,13 +17260,13 @@ As you learn more about Medusa, you will see that modules are central to customi - You want to build a custom feature related to a single domain or integrate a third-party service. -- You want to create a reusable package of customizations that include not only modules, but also API routes, workflows, and other customizations. Instead, use a [plugin](undefined/learn/fundamentals/plugins). +- You want to create a reusable package of customizations that include not only modules, but also API routes, workflows, and other customizations. Instead, use a [plugin](https://docs.medusajs.com/learn/fundamentals/plugins/index.html.md). *** ## How to Create a Module? -In a module, you define data models that represent new tables in the database, and you manage these models in a class called a service. Then, the Medusa application registers the module's service in the [Medusa container](undefined/learn/fundamentals/medusa-container) so that you can build commerce flows and features around the functionalities provided by the module. +In a module, you define data models that represent new tables in the database, and you manage these models in a class called a service. Then, the Medusa application registers the module's service in the [Medusa container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md) so that you can build commerce flows and features around the functionalities provided by the module. In this section, you'll build a Blog Module that has a `Post` data model and a service to manage that data model. You'll also expose an API endpoint to create a blog post. @@ -17279,13 +17297,13 @@ You define the data model using the `define` method of the DML. It accepts two p 2. The second is an object, which is the data model's schema. The schema's properties are defined using the `model`'s methods, such as `text` and `id`. - Data models automatically have the date properties `created_at`, `updated_at`, and `deleted_at`, so you don't need to add them manually. -Learn about other property types in [this chapter](undefined/learn/fundamentals/data-models/properties#property-types). +Learn about other property types in [this chapter](https://docs.medusajs.com/learn/fundamentals/data-models/properties#property-types/index.html.md). The code snippet above defines a `Post` data model with `id` and `title` properties. ### 2. Create Service -You perform database operations on your data models in a service, which is a class exported by the module and acts like an interface to its functionalities. Medusa registers the service in its [container](undefined/learn/fundamentals/medusa-container), allowing you to resolve and use it when building custom commerce flows. +You perform database operations on your data models in a service, which is a class exported by the module and acts like an interface to its functionalities. Medusa registers the service in its [container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md), allowing you to resolve and use it when building custom commerce flows. You define a service in a `service.ts` or `service.js` file at the root of your module's directory. So, to create the Blog Module's service, create the file `src/modules/blog/service.ts` with the following content: @@ -17309,7 +17327,7 @@ The `MedusaService` function accepts an object of data models to generate method For example, the `BlogModuleService` now has a `createPosts` method to create post records, and a `retrievePost` method to retrieve a post record. The suffix of each method (except for `retrieve`) is the pluralized name of the data model. -Find all methods generated by the `MedusaService` in [this reference](undefined/resources/service-factory-reference) +Find all methods generated by the `MedusaService` in [this reference](https://docs.medusajs.com/resources/service-factory-reference/index.html.md) If a module doesn't have data models, such as when it's integrating a third-party service, it doesn't need to extend `MedusaService`. @@ -17341,7 +17359,7 @@ You export `BLOG_MODULE` to reference the module's name more reliably when resol ### 4. Add Module to Medusa's Configurations -If you're creating the module in a plugin, this step isn't required as the module is registered when the plugin is registered. Learn more about plugins in [this documentation](undefined/learn/fundamentals/plugins). +If you're creating the module in a plugin, this step isn't required as the module is registered when the plugin is registered. Learn more about plugins in [this documentation](https://docs.medusajs.com/learn/fundamentals/plugins/index.html.md). Once you finish building the module, add it to Medusa's configurations to start using it. Medusa will then register the module's main service in the Medusa container, allowing you to resolve and use it in other customizations. @@ -17372,7 +17390,7 @@ You don't have to write migrations yourself. Medusa's CLI tool has a command tha To generate a migration for the Blog Module, run the following command in your Medusa application's directory: -If you're creating the module in a plugin, use the [plugin:db:generate command](undefined/resources/medusa-cli/commands/plugin#plugindbgenerate) instead. +If you're creating the module in a plugin, use the [plugin:db:generate command](https://docs.medusajs.com/resources/medusa-cli/commands/plugin#plugindbgenerate/index.html.md) instead. ```bash npx medusa db:generate blog @@ -17416,9 +17434,9 @@ This creates the `post` table in the database. Since the module's main service is registered in the Medusa container, you can resolve it in other customizations to use its methods. -To test out the Blog Module, you'll add the functionality to create a post in a [workflow](undefined/learn/fundamentals/workflows), which is a special function that performs a task in a series of steps with rollback logic. Then, you'll expose an [API route](undefined/learn/fundamentals/api-routes) that creates a blog post by executing the workflow. +To test out the Blog Module, you'll add the functionality to create a post in a [workflow](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md), which is a special function that performs a task in a series of steps with rollback logic. Then, you'll expose an [API route](https://docs.medusajs.com/learn/fundamentals/api-routes/index.html.md) that creates a blog post by executing the workflow. -By building a commerce feature in a workflow, you can execute it in other customizations while ensuring data consistency across systems. If an error occurs during execution, every step has its own rollback logic to undo its actions. Workflows have other special features which you can learn about in [this chapter](undefined/learn/fundamentals/workflows). +By building a commerce feature in a workflow, you can execute it in other customizations while ensuring data consistency across systems. If an error occurs during execution, every step has its own rollback logic to undo its actions. Workflows have other special features which you can learn about in [this chapter](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md). To create the workflow, create the file `src/workflows/create-post.ts` with the following content: @@ -17523,7 +17541,7 @@ This will create a post and return it in the response: } ``` -You can also execute the workflow from a [subscriber](undefined/learn/fundamentals/events-and-subscribers) when an event occurs, or from a [scheduled job](undefined/learn/fundamentals/scheduled-jobs) to run it at a specified interval. +You can also execute the workflow from a [subscriber](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/index.html.md) when an event occurs, or from a [scheduled job](https://docs.medusajs.com/learn/fundamentals/scheduled-jobs/index.html.md) to run it at a specified interval. # Service Constraints @@ -17611,7 +17629,7 @@ The method names are the operation name, suffixed by the data model's key in the For example, the following methods are generated for the service above: -Find a complete reference of each of the methods in [this documentation](undefined/resources/service-factory-reference) +Find a complete reference of each of the methods in [this documentation](https://docs.medusajs.com/resources/service-factory-reference/index.html.md) ### listPosts @@ -17762,7 +17780,7 @@ Then, you'll have a `postService` registered in the module's container that allo Generated internal services have the same methods as the `BlogModuleService`, such as `create`, `retrieve`, `update`, and `delete`, but without the data model name suffix. -These services are useful when you need to perform database operations in loaders, as they are executed before the module's services are registered. Learn more in the [Module Container](undefined/learn/fundamentals/modules/container) documentation. +These services are useful when you need to perform database operations in loaders, as they are executed before the module's services are registered. Learn more in the [Module Container](https://docs.medusajs.com/learn/fundamentals/modules/container/index.html.md) documentation. For example, you can create a loader that logs the number of posts in the database: @@ -17785,7 +17803,7 @@ export default async function helloWorldLoader({ In this chapter, you'll learn how to create a Medusa plugin and publish it. -A [plugin](undefined/learn/fundamentals/plugins) is a package of reusable Medusa customizations that you can install in any Medusa application. By creating and publishing a plugin, you can reuse your Medusa customizations across multiple projects or share them with the community. +A [plugin](https://docs.medusajs.com/learn/fundamentals/plugins/index.html.md) is a package of reusable Medusa customizations that you can install in any Medusa application. By creating and publishing a plugin, you can reuse your Medusa customizations across multiple projects or share them with the community. Plugins are available starting from [Medusa v2.3.0](https://github.com/medusajs/medusa/releases/tag/v2.3.0). @@ -17808,14 +17826,14 @@ After the installation is done, the plugin structure will look like this: ![Directory structure of a plugin project](https://res.cloudinary.com/dza7lstvk/image/upload/v1737019441/Medusa%20Book/project-dir_q4xtri.jpg) - `src/`: Contains the Medusa customizations. -- `src/admin`: Contains [admin extensions](undefined/learn/fundamentals/admin). -- `src/api`: Contains [API routes](undefined/learn/fundamentals/api-routes) and [middlewares](undefined/learn/fundamentals/api-routes/middlewares). You can add store, admin, or any custom API routes. -- `src/jobs`: Contains [scheduled jobs](undefined/learn/fundamentals/scheduled-jobs). -- `src/links`: Contains [module links](undefined/learn/fundamentals/module-links). -- `src/modules`: Contains [modules](undefined/learn/fundamentals/modules). +- `src/admin`: Contains [admin extensions](https://docs.medusajs.com/learn/fundamentals/admin/index.html.md). +- `src/api`: Contains [API routes](https://docs.medusajs.com/learn/fundamentals/api-routes/index.html.md) and [middlewares](https://docs.medusajs.com/learn/fundamentals/api-routes/middlewares/index.html.md). You can add store, admin, or any custom API routes. +- `src/jobs`: Contains [scheduled jobs](https://docs.medusajs.com/learn/fundamentals/scheduled-jobs/index.html.md). +- `src/links`: Contains [module links](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md). +- `src/modules`: Contains [modules](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md). - `src/provider`: Contains [module providers](#create-module-providers). -- `src/subscribers`: Contains [subscribers](undefined/learn/fundamentals/events-and-subscribers). -- `src/workflows`: Contains [workflows](undefined/learn/fundamentals/workflows). You can also add [hooks](undefined/learn/fundamentals/workflows/add-workflow-hook) under `src/workflows/hooks`. +- `src/subscribers`: Contains [subscribers](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/index.html.md). +- `src/workflows`: Contains [workflows](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md). You can also add [hooks](https://docs.medusajs.com/learn/fundamentals/workflows/add-workflow-hook/index.html.md) under `src/workflows/hooks`. - `package.json`: Contains the plugin's package information, including general information and dependencies. - `tsconfig.json`: Contains the TypeScript configuration for the plugin. @@ -17941,7 +17959,7 @@ Medusa's CLI tool provides commands to simplify developing and testing your plug ### Prerequisites -- [Medusa application installed.](undefined/learn/installation) +- [Medusa application installed.](https://docs.medusajs.com/learn/installation/index.html.md) The first time you create your plugin, you need to publish the package into a local package registry, then install it in your Medusa application. This is a one-time only process. @@ -18015,7 +18033,7 @@ module.exports = defineConfig({ }) ``` -The `options` property in the plugin configuration is passed to all modules in the plugin. Learn more about module options in [this chapter](undefined/learn/fundamentals/modules/options). +The `options` property in the plugin configuration is passed to all modules in the plugin. Learn more about module options in [this chapter](https://docs.medusajs.com/learn/fundamentals/modules/options/index.html.md). ### Watch Plugin Changes During Development @@ -18048,15 +18066,15 @@ While your Medusa application is running and the plugin is being watched, you ca You can now build your plugin's customizations. The following guide explains how to build different customizations in your plugin. -- [Create a module](undefined/learn/fundamentals/modules) -- [Create a module link](undefined/learn/fundamentals/module-links) -- [Create a workflow](undefined/learn/fundamentals/workflows) -- [Add a workflow hook](undefined/learn/fundamentals/workflows/add-workflow-hook) -- [Create an API route](undefined/learn/fundamentals/api-routes) -- [Add a subscriber](undefined/learn/fundamentals/events-and-subscribers) -- [Add a scheduled job](undefined/learn/fundamentals/scheduled-jobs) -- [Add an admin widget](undefined/learn/fundamentals/admin/widgets) -- [Add an admin UI route](undefined/learn/fundamentals/admin/ui-routes) +- [Create a module](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md) +- [Create a module link](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md) +- [Create a workflow](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) +- [Add a workflow hook](https://docs.medusajs.com/learn/fundamentals/workflows/add-workflow-hook/index.html.md) +- [Create an API route](https://docs.medusajs.com/learn/fundamentals/api-routes/index.html.md) +- [Add a subscriber](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/index.html.md) +- [Add a scheduled job](https://docs.medusajs.com/learn/fundamentals/scheduled-jobs/index.html.md) +- [Add an admin widget](https://docs.medusajs.com/learn/fundamentals/admin/widgets/index.html.md) +- [Add an admin UI route](https://docs.medusajs.com/learn/fundamentals/admin/ui-routes/index.html.md) While building those customizations, you can test them in your Medusa application by [watching the plugin changes](#watch-plugin-changes-during-development) and [starting the Medusa application](#start-medusa-application). @@ -18117,7 +18135,7 @@ import BlogType from "@myorg/plugin-name/types/blog" The [exported resources](#package-exports) also allow you to import module providers in your plugin and register them in the Medusa application's configuration. A module provider is a module that provides the underlying logic or integration related to a commerce or Infrastructure Module. -For example, assuming your plugin has a [Notification Module Provider](undefined/resources/infrastructure-modules/notification) called `my-notification`, you can register it in your Medusa application's configuration like this: +For example, assuming your plugin has a [Notification Module Provider](https://docs.medusajs.com/resources/infrastructure-modules/notification/index.html.md) called `my-notification`, you can register it in your Medusa application's configuration like this: `@myorg/plugin-name` is the plugin package's name. @@ -18148,12 +18166,12 @@ You pass to `resolve` the path to the provider relative to the plugin package. S To learn how to create module providers, refer to the following guides: -- [File Module Provider](undefined/resources/references/file-provider-module) -- [Notification Module Provider](undefined/resources/references/notification-provider-module) -- [Auth Module Provider](undefined/resources/references/auth/provider) -- [Payment Module Provider](undefined/resources/references/payment/provider) -- [Fulfillment Module Provider](undefined/resources/references/fulfillment/provider) -- [Tax Module Provider](undefined/resources/references/tax/provider) +- [File Module Provider](https://docs.medusajs.com/resources/references/file-provider-module/index.html.md) +- [Notification Module Provider](https://docs.medusajs.com/resources/references/notification-provider-module/index.html.md) +- [Auth Module Provider](https://docs.medusajs.com/resources/references/auth/provider/index.html.md) +- [Payment Module Provider](https://docs.medusajs.com/resources/references/payment/provider/index.html.md) +- [Fulfillment Module Provider](https://docs.medusajs.com/resources/references/fulfillment/provider/index.html.md) +- [Tax Module Provider](https://docs.medusajs.com/resources/references/tax/provider/index.html.md) *** @@ -18193,7 +18211,7 @@ Then, register the plugin in your Medusa application's configurations as explain ## Update a Published Plugin -To update the Medusa dependencies in a plugin, refer to [this documentation](undefined/learn/update#update-plugin-project). +To update the Medusa dependencies in a plugin, refer to [this documentation](https://docs.medusajs.com/learn/update#update-plugin-project/index.html.md). If you've published a plugin and you've made changes to it, you'll have to publish the update to NPM again. @@ -18223,19 +18241,19 @@ Plugins are available starting from [Medusa v2.3.0](https://github.com/medusajs/ ## What is a Plugin? -A plugin is a package of reusable Medusa customizations that you can install in any Medusa application. The supported customizations are [Modules](undefined/learn/fundamentals/modules), [API Routes](undefined/learn/fundamentals/api-routes), [Workflows](undefined/learn/fundamentals/workflows), [Workflow Hooks](undefined/learn/fundamentals/workflows/workflow-hooks), [Links](undefined/learn/fundamentals/module-links), [Subscribers](undefined/learn/fundamentals/events-and-subscribers), [Scheduled Jobs](undefined/learn/fundamentals/scheduled-jobs), and [Admin Extensions](undefined/learn/fundamentals/admin). +A plugin is a package of reusable Medusa customizations that you can install in any Medusa application. The supported customizations are [Modules](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md), [API Routes](https://docs.medusajs.com/learn/fundamentals/api-routes/index.html.md), [Workflows](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md), [Workflow Hooks](https://docs.medusajs.com/learn/fundamentals/workflows/workflow-hooks/index.html.md), [Links](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md), [Subscribers](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/index.html.md), [Scheduled Jobs](https://docs.medusajs.com/learn/fundamentals/scheduled-jobs/index.html.md), and [Admin Extensions](https://docs.medusajs.com/learn/fundamentals/admin/index.html.md). Plugins allow you to reuse your Medusa customizations across multiple projects or share them with the community. They can be published to npm and installed in any Medusa project. ![Diagram showcasing a wishlist plugin installed in a Medusa application](https://res.cloudinary.com/dza7lstvk/image/upload/v1737540762/Medusa%20Book/plugin-diagram_oepiis.jpg) -Learn how to create a wishlist plugin in [this guide](undefined/resources/plugins/guides/wishlist). +Learn how to create a wishlist plugin in [this guide](https://docs.medusajs.com/resources/plugins/guides/wishlist/index.html.md). *** ## Plugin vs Module -A [module](undefined/learn/fundamentals/modules) is an isolated package related to a single domain or functionality, such as product reviews or integrating a Content Management System. A module can't access any resources in the Medusa application that are outside its codebase. +A [module](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md) is an isolated package related to a single domain or functionality, such as product reviews or integrating a Content Management System. A module can't access any resources in the Medusa application that are outside its codebase. A plugin, on the other hand, can contain multiple Medusa customizations, including modules. Your plugin can define a module, then build flows around it. @@ -18244,7 +18262,7 @@ For example, in a plugin, you can define a module that integrates a third-party - You want to reuse your Medusa customizations across multiple projects. - You want to share your Medusa customizations with the community. -- You want to build a custom feature related to a single domain or integrate a third-party service. Instead, use a [module](undefined/learn/fundamentals/modules). You can wrap that module in a plugin if it's used in other customizations, such as if it has a module link or it's used in a workflow. +- You want to build a custom feature related to a single domain or integrate a third-party service. Instead, use a [module](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md). You can wrap that module in a plugin if it's used in other customizations, such as if it has a module link or it's used in a workflow. *** @@ -18348,7 +18366,7 @@ info: Greeting! ## Scheduled Job Interval vs. Scheduled Job Cron -In the [Scheduled Jobs](undefined/learn/fundamentals/scheduled-jobs) chapter, you learned about using the `schedule` configuration to set the schedule for a job using a cron expression. For example, `*/5 * * * *` would run a job every 5 minutes. +In the [Scheduled Jobs](https://docs.medusajs.com/learn/fundamentals/scheduled-jobs/index.html.md) chapter, you learned about using the `schedule` configuration to set the schedule for a job using a cron expression. For example, `*/5 * * * *` would run a job every 5 minutes. |Comparison Aspect|Cron Expression|Interval| |---|---|---| @@ -18380,9 +18398,9 @@ In other commerce platforms, this feature isn't natively supported. Instead, you Medusa removes this overhead by supporting this feature natively with scheduled jobs. A scheduled job is an asynchronous function that the Medusa application runs at the interval you specify during the Medusa application's runtime. Your efforts are only spent on implementing the functionality performed by the job, such as syncing products to an ERP. -- You want the action to execute at a specified schedule while the Medusa application **isn't** running. Instead, create a [custom CLI script](undefined/learn/fundamentals/custom-cli-scripts) and execute it using the operating system's equivalent of a cron job. -- You want to execute the action once when the application loads. Use [loaders](undefined/learn/fundamentals/modules/loaders) or [custom CLI scripts](undefined/learn/fundamentals/custom-cli-scripts#run-custom-script-on-application-startup) instead. -- You want to execute the action if an event occurs. Use [subscribers](undefined/learn/fundamentals/events-and-subscribers) instead. +- You want the action to execute at a specified schedule while the Medusa application **isn't** running. Instead, create a [custom CLI script](https://docs.medusajs.com/learn/fundamentals/custom-cli-scripts/index.html.md) and execute it using the operating system's equivalent of a cron job. +- You want to execute the action once when the application loads. Use [loaders](https://docs.medusajs.com/learn/fundamentals/modules/loaders/index.html.md) or [custom CLI scripts](https://docs.medusajs.com/learn/fundamentals/custom-cli-scripts#run-custom-script-on-application-startup/index.html.md) instead. +- You want to execute the action if an event occurs. Use [subscribers](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/index.html.md) instead. *** @@ -18409,7 +18427,7 @@ export const config = { } ``` -You export an asynchronous function that receives the [Medusa container](undefined/learn/fundamentals/medusa-container) as a parameter. In the function, you resolve the [Logger utility](undefined/learn/debugging-and-testing/logging) from the Medusa container and log a message. +You export an asynchronous function that receives the [Medusa container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md) as a parameter. In the function, you resolve the [Logger utility](https://docs.medusajs.com/learn/debugging-and-testing/logging/index.html.md) from the Medusa container and log a message. You also export a `config` object that has the following properties: @@ -18436,11 +18454,11 @@ info: Greeting! ## Example: Sync Products Once a Day -In a realistic scenario like syncing products to an ERP once a day, you should create a [workflow](undefined/learn/fundamentals/workflows) and execute it in a scheduled job. +In a realistic scenario like syncing products to an ERP once a day, you should create a [workflow](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) and execute it in a scheduled job. A workflow is a task made up of a series of steps, and you construct it like you would a regular function, but it's a special function that supports rollback mechanism in case of errors, background execution, and more. -You can learn how to create a workflow in the [Workflows](undefined/learn/fundamentals/workflows) chapter, but this example assumes you already have a `syncProductToErpWorkflow` implemented. To execute this workflow once a day, create a scheduled job at `src/jobs/sync-products.ts` with the following content: +You can learn how to create a workflow in the [Workflows](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) chapter, but this example assumes you already have a `syncProductToErpWorkflow` implemented. To execute this workflow once a day, create a scheduled job at `src/jobs/sync-products.ts` with the following content: ```ts title="src/jobs/sync-products.ts" import { MedusaContainer } from "@medusajs/framework/types" @@ -18466,13 +18484,13 @@ The next time you start the Medusa application, it will run this job every day a In this chapter, you'll learn how to expose a hook in your workflow. -Refer to the [Workflow Hooks](undefined/learn/fundamentals/workflows/workflow-hooks) chapter to learn what a workflow hook is and how to consume Medusa's workflow hooks. +Refer to the [Workflow Hooks](https://docs.medusajs.com/learn/fundamentals/workflows/workflow-hooks/index.html.md) chapter to learn what a workflow hook is and how to consume Medusa's workflow hooks. ## When to Expose a Hook? Medusa exposes hooks in many of its workflows to allow you to inject custom functionality. -You can also expose your own hooks in your workflows to allow other developers to consume them. This is useful when you're creating a workflow in a [plugin](undefined/learn/fundamentals/plugins) and you want plugin users to extend the workflow's functionality. +You can also expose your own hooks in your workflows to allow other developers to consume them. This is useful when you're creating a workflow in a [plugin](https://docs.medusajs.com/learn/fundamentals/plugins/index.html.md) and you want plugin users to extend the workflow's functionality. For example, you are creating a blog plugin and you want to allow developers to perform custom validation before a blog post is created. You can expose a hook in your workflow that developers can consume to perform their custom validation. @@ -18566,7 +18584,7 @@ createBlogPostWorkflow.hooks.validate( ) ``` -Learn more about the hook handler in the [Workflow Hooks](undefined/learn/fundamentals/workflows/workflow-hooks) chapter. +Learn more about the hook handler in the [Workflow Hooks](https://docs.medusajs.com/learn/fundamentals/workflows/workflow-hooks/index.html.md) chapter. # Compensation Function @@ -18822,7 +18840,7 @@ The `StepResponse.permanentFailure` fails the step and its workflow, triggering So, if an error occurs during the loop, the compensation function will still receive the `prevData` variable to undo the changes made before the step failed. -For more details on error handling in workflows and steps, check the [Handling Errors chapter](undefined/learn/fundamentals/workflows/errors). +For more details on error handling in workflows and steps, check the [Handling Errors chapter](https://docs.medusajs.com/learn/fundamentals/workflows/errors/index.html.md). # Conditions in Workflows with When-Then @@ -18898,10 +18916,10 @@ To specify the action to perform if the condition is satisfied, chain a `then` f The callback function passed to `then` is treated the same as the workflow's definition function. That means: - You can execute steps in the callback function. -- You can't [transform data and variables](undefined/learn/fundamentals/workflows/variable-manipulation) in the callback function. Instead, use `transform`. +- You can't [transform data and variables](https://docs.medusajs.com/learn/fundamentals/workflows/variable-manipulation/index.html.md) in the callback function. Instead, use `transform`. - You can't use if-else conditions in the callback function. - You can't use loops in the callback function. -- You should keep in mind the [workflow constructor constraints](undefined/learn/fundamentals/workflows/constructor-constraints) in the callback function. +- You should keep in mind the [workflow constructor constraints](https://docs.medusajs.com/learn/fundamentals/workflows/constructor-constraints/index.html.md) in the callback function. *** @@ -19031,7 +19049,7 @@ const myWorkflow = createWorkflow( You can’t directly manipulate variables within the workflow's constructor function. -Learn more about why you can't manipulate variables [in this chapter](undefined/learn/fundamentals/workflows/variable-manipulation) +Learn more about why you can't manipulate variables [in this chapter](https://docs.medusajs.com/learn/fundamentals/workflows/variable-manipulation/index.html.md) Instead, use `transform` from the Workflows SDK: @@ -19075,7 +19093,7 @@ When you use `new Date()` in a workflow's constructor function, the date is eval Instead, create the date using `transform`. -Learn more about how Medusa creates an internal representation of a workflow [in this chapter](undefined/learn/fundamentals/workflows/variable-manipulation). +Learn more about how Medusa creates an internal representation of a workflow [in this chapter](https://docs.medusajs.com/learn/fundamentals/workflows/variable-manipulation/index.html.md). For example: @@ -19107,7 +19125,7 @@ const myWorkflow = createWorkflow( You can't use if-conditions in a workflow. -Learn more about why you can't use if-conditions [in this chapter](undefined/learn/fundamentals/workflows/conditions#why-if-conditions-arent-allowed-in-workflows) +Learn more about why you can't use if-conditions [in this chapter](https://docs.medusajs.com/learn/fundamentals/workflows/conditions#why-if-conditions-arent-allowed-in-workflows/index.html.md) Instead, use when-then from the Workflows SDK: @@ -19134,13 +19152,13 @@ const myWorkflow = createWorkflow( }) ``` -You can also pair multiple `when-then` blocks to implement an `if-else` condition as explained in [this chapter](undefined/learn/fundamentals/workflows/conditions). +You can also pair multiple `when-then` blocks to implement an `if-else` condition as explained in [this chapter](https://docs.medusajs.com/learn/fundamentals/workflows/conditions/index.html.md). ### No Conditional Operators You can't use conditional operators in a workflow, such as `??` or `||`. -Learn more about why you can't use conditional operators [in this chapter](undefined/learn/fundamentals/workflows/conditions#why-if-conditions-arent-allowed-in-workflows) +Learn more about why you can't use conditional operators [in this chapter](https://docs.medusajs.com/learn/fundamentals/workflows/conditions#why-if-conditions-arent-allowed-in-workflows/index.html.md) Instead, use `transform` to store the desired value in a variable. @@ -19298,7 +19316,7 @@ const myWorkflow = createWorkflow( In a workflow, don't use try-catch blocks to handle errors. -Instead, refer to the [Error Handling](undefined/learn/fundamentals/workflows/errors) chapter for alternative ways to handle errors. +Instead, refer to the [Error Handling](https://docs.medusajs.com/learn/fundamentals/workflows/errors/index.html.md) chapter for alternative ways to handle errors. *** @@ -19418,11 +19436,11 @@ In this chapter, you’ll learn about what happens when an error occurs in a wor ## Default Behavior of Errors in Workflows -When an error occurs in a workflow, such as when a step throws an error, the workflow execution stops. Then, [the compensation function](undefined/learn/fundamentals/workflows/compensation-function) of every step in the workflow is called to undo the actions performed by their respective steps. +When an error occurs in a workflow, such as when a step throws an error, the workflow execution stops. Then, [the compensation function](https://docs.medusajs.com/learn/fundamentals/workflows/compensation-function/index.html.md) of every step in the workflow is called to undo the actions performed by their respective steps. The workflow's caller, such as an API route, subscriber, or scheduled job, will also fail and stop execution. Medusa then logs the error in the console. For API routes, an appropriate error is returned to the client based on the thrown error. -Learn more about error handling in API routes in the [Errors chapter](undefined/learn/fundamentals/api-routes/errors). +Learn more about error handling in API routes in the [Errors chapter](https://docs.medusajs.com/learn/fundamentals/api-routes/errors/index.html.md). This is the default behavior of errors in workflows. However, you can configure workflows to not throw errors, or you can configure a step's internal error handling mechanism to change the default behavior. @@ -19479,7 +19497,7 @@ An error object has the following properties: ## Try-Catch Alternatives in Workflow Definition -If you want to use try-catch mechanism in a workflow to undo step actions, use a [compensation function](undefined/learn/fundamentals/workflows/compensation-function) instead. +If you want to use try-catch mechanism in a workflow to undo step actions, use a [compensation function](https://docs.medusajs.com/learn/fundamentals/workflows/compensation-function/index.html.md) instead. ### Why You Can't Use Try-Catch in Workflow Definitions @@ -19663,11 +19681,11 @@ In this chapter, you'll learn how to execute a workflow in another workflow. ## How to Execute a Workflow in Another? -In many cases, you may have a workflow that you want to re-use in another workflow. This is most common when you build custom workflows and you want to utilize Medusa's [existing workflows](undefined/resources/medusa-workflows-reference). +In many cases, you may have a workflow that you want to re-use in another workflow. This is most common when you build custom workflows and you want to utilize Medusa's [existing workflows](https://docs.medusajs.com/resources/medusa-workflows-reference/index.html.md). Executing a workflow within another is slightly different from how you usually execute a workflow. Instead of invoking the workflow, passing it the container, then running its `run` method, you use the `runAsStep` method of the workflow. This will pass the Medusa container and workflow context to the nested workflow. -For example, to execute the [createProductsWorkflow](undefined/resources/references/medusa-workflows/createProductsWorkflow) in your custom workflow: +For example, to execute the [createProductsWorkflow](https://docs.medusajs.com/resources/references/medusa-workflows/createProductsWorkflow/index.html.md) in your custom workflow: ```ts highlights={workflowsHighlights} collapsibleLines="1-7" expandMoreButton="Show Imports" import { @@ -19705,7 +19723,7 @@ You also receive the workflow's output as a return value from the `runAsStep` me ## Prepare Input Data -Since Medusa creates an internal representation of your workflow's constructor function, you can't manipulate data directly in the workflow constructor. You can learn more about this in the [Data Manipulation](undefined/learn/fundamentals/workflows/variable-manipulation) chapter. +Since Medusa creates an internal representation of your workflow's constructor function, you can't manipulate data directly in the workflow constructor. You can learn more about this in the [Data Manipulation](https://docs.medusajs.com/learn/fundamentals/workflows/variable-manipulation/index.html.md) chapter. If you need to perform some data manipulation to prepare the nested workflow's input data, use `transform` from the Workflows SDK. @@ -19748,7 +19766,7 @@ const workflow = createWorkflow( In this example, you use the `transform` function to prepend `Hello` to the title of the product. Then, you pass the result as input to the `createProductsWorkflow`. -Learn more about `transform` in the [Data Manipulation](undefined/learn/fundamentals/workflows/variable-manipulation) chapter. +Learn more about `transform` in the [Data Manipulation](https://docs.medusajs.com/learn/fundamentals/workflows/variable-manipulation/index.html.md) chapter. *** @@ -19792,7 +19810,7 @@ const workflow = createWorkflow( In this example, you use `when-then` to run the `createProductsWorkflow` only if `should_create` (passed in the `input`) is enabled. -Learn more about `when-then` in the [When-Then Conditions](undefined/learn/fundamentals/workflows/conditions) chapter. +Learn more about `when-then` in the [When-Then Conditions](https://docs.medusajs.com/learn/fundamentals/workflows/conditions/index.html.md) chapter. *** @@ -19802,7 +19820,7 @@ A nested workflow behaves similarly to a step in a workflow. So, if the nested w In addition, if another step fails after the nested workflow, the nested workflow's steps will be compensated as part of the compensation process. -Learn more about handling errors in workflows in the [Error Handling](undefined/learn/fundamentals/workflows/errors) chapter. +Learn more about handling errors in workflows in the [Error Handling](https://docs.medusajs.com/learn/fundamentals/workflows/errors/index.html.md) chapter. *** @@ -19812,7 +19830,7 @@ When you execute a long-running workflow within another workflow, the parent wor So, the parent workflow will wait for the nested workflow to finish before continuing its execution. -Refer to the [Long-Running Workflows](undefined/learn/fundamentals/workflows/long-running-workflow) chapter for more information on how to handle long-running workflows. +Refer to the [Long-Running Workflows](https://docs.medusajs.com/learn/fundamentals/workflows/long-running-workflow/index.html.md) chapter for more information on how to handle long-running workflows. # Locking Operations in Workflows @@ -19825,7 +19843,7 @@ A lock is a mechanism that restricts multiple accesses to a resource or a piece Locks are particularly useful in workflows where concurrent executions may lead to commerce risks. For example, Medusa uses locks in its cart workflows to prevent issues like overselling products or double charging customers. -The [Locking Module](undefined/resources/infrastructure-modules/locking) handles the locking mechanism using the underlying provider. You can use the Locking Module's service in your workflows to create locks around critical sections of your code. +The [Locking Module](https://docs.medusajs.com/resources/infrastructure-modules/locking/index.html.md) handles the locking mechanism using the underlying provider. You can use the Locking Module's service in your workflows to create locks around critical sections of your code. *** @@ -19880,7 +19898,7 @@ If an error occurs in the workflow after a lock is acquired with `acquireLockSte ### Locking Steps API -Refer to the [acquireLockStep](undefined/resources/references/medusa-workflows/steps/acquireLockStep) and [releaseLockStep](undefined/resources/references/medusa-workflows/steps/releaseLockStep) for more information on the inputs of these steps. +Refer to the [acquireLockStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/acquireLockStep/index.html.md) and [releaseLockStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/releaseLockStep/index.html.md) for more information on the inputs of these steps. *** @@ -19919,11 +19937,11 @@ export const chargeCustomerStep = createStep( In this example, the `chargeCustomerStep` step acquires a lock on the order using the `order_id` as the lock key. After performing the operation, it releases the lock. -The step will wait until the lock is acquired based on the configured Locking Module Provider's options. For example, the [Redis Locking Module Provider](undefined/resources/infrastructure-modules/locking/redis) will wait five seconds before timing out. +The step will wait until the lock is acquired based on the configured Locking Module Provider's options. For example, the [Redis Locking Module Provider](https://docs.medusajs.com/resources/infrastructure-modules/locking/redis/index.html.md) will wait five seconds before timing out. ### Locking Module Service API -Refer to the [Locking Module reference](undefined/resources/references/locking-service) for more information on the Locking Module's service methods. +Refer to the [Locking Module reference](https://docs.medusajs.com/resources/references/locking-service/index.html.md) for more information on the Locking Module's service methods. # Long-Running Workflows @@ -19943,7 +19961,7 @@ Long-running workflows are useful if: - A task takes too long. For example, you're importing data from a CSV file. - The workflow's steps wait for an external action to finish before resuming execution. For example, before you import the data from the CSV file, you wait until the import is confirmed by the user. - You want to retry workflow steps after a long period of time. For example, you want to retry a step that processes a payment every day until the payment is successful. - - Refer to the [Retry Failed Steps chapter](undefined/learn/fundamentals/workflows/retry-failed-steps) for more information. + - Refer to the [Retry Failed Steps chapter](https://docs.medusajs.com/learn/fundamentals/workflows/retry-failed-steps/index.html.md) for more information. *** @@ -20003,8 +20021,8 @@ So, when you execute the `hello-world` workflow, it continues its execution in t A workflow is also considered long-running if: - One of its steps has its `async` configuration set to `true` and doesn't return a step response. -- One of its steps has its `retryInterval` option set as explained in the [Retry Failed Steps chapter](undefined/learn/fundamentals/workflows/retry-failed-steps). -- One of its [nested workflows](undefined/learn/fundamentals/workflows/execute-another-workflow) is a long-running workflow. +- One of its steps has its `retryInterval` option set as explained in the [Retry Failed Steps chapter](https://docs.medusajs.com/learn/fundamentals/workflows/retry-failed-steps/index.html.md). +- One of its [nested workflows](https://docs.medusajs.com/learn/fundamentals/workflows/execute-another-workflow/index.html.md) is a long-running workflow. *** @@ -20138,7 +20156,7 @@ You use this step in another workflow that changes the status of an async step i To access the status and result of a long-running workflow execution, use the `subscribe` and `unsubscribe` methods of the Workflow Engine Module's main service. -To retrieve the workflow execution's details at a later point, you must enable [storing the workflow's executions](undefined/learn/fundamentals/workflows/store-executions). +To retrieve the workflow execution's details at a later point, you must enable [storing the workflow's executions](https://docs.medusajs.com/learn/fundamentals/workflows/store-executions/index.html.md). For example: @@ -20208,7 +20226,7 @@ However, instead of the `subscriber` property, it requires a `subscriberOrId` pr ## Example: Restaurant-Delivery Recipe -To find a full example of a long-running workflow, refer to the [restaurant-delivery recipe](undefined/resources/recipes/marketplace/examples/restaurant-delivery). +To find a full example of a long-running workflow, refer to the [restaurant-delivery recipe](https://docs.medusajs.com/resources/recipes/marketplace/examples/restaurant-delivery/index.html.md). In the recipe, you use a long-running workflow that moves an order from placed to completed. The workflow waits for the restaurant to accept the order, the driver to pick up the order, and other external actions. @@ -20305,7 +20323,7 @@ However, unlike regular functions, workflows: - Support defining roll-back logic for each step, so that you can handle errors gracefully and your data remain consistent across systems. - Perform long actions asynchronously, giving you control over when a step starts and finishes. -You implement all custom flows within workflows, then execute them from [API routes](undefined/learn/fundamentals/api-routes), [subscribers](undefined/learn/fundamentals/events-and-subscribers), and [scheduled jobs](undefined/learn/fundamentals/scheduled-jobs). +You implement all custom flows within workflows, then execute them from [API routes](https://docs.medusajs.com/learn/fundamentals/api-routes/index.html.md), [subscribers](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/index.html.md), and [scheduled jobs](https://docs.medusajs.com/learn/fundamentals/scheduled-jobs/index.html.md). *** @@ -20392,7 +20410,7 @@ You can execute a workflow from different customizations: - Execute in a subscriber to use the workflow's functionalities when a commerce operation is performed. - Execute in a scheduled job to run the workflow's functionalities automatically at a specified repeated interval. -To execute the workflow, invoke it passing the [Medusa container](undefined/learn/fundamentals/medusa-container) as a parameter. Then, use its `run` method: +To execute the workflow, invoke it passing the [Medusa container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md) as a parameter. Then, use its `run` method: ### API Route @@ -20497,7 +20515,7 @@ You’ll receive the following response: ## Access Medusa Container in Workflow Steps -A step receives an object as a second parameter with configurations and context-related properties. One of these properties is the `container` property, which is the [Medusa container](undefined/learn/fundamentals/medusa-container) to allow you to resolve Framework and commerce tools in your application. +A step receives an object as a second parameter with configurations and context-related properties. One of these properties is the `container` property, which is the [Medusa container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md) to allow you to resolve Framework and commerce tools in your application. For example, consider you want to implement a workflow that returns the total products in your application. Create the file `src/workflows/product-count.ts` with the following content: @@ -20538,7 +20556,7 @@ In `getProductCountStep`, you use the `container` to resolve the Product Module' You can now execute this workflow in a custom API route, scheduled job, or subscriber to get the total count of products. -Find a full list of the registered resources in the Medusa container and their registration key in [this reference](undefined/resources/medusa-container-resources). You can use these resources in your custom workflows. +Find a full list of the registered resources in the Medusa container and their registration key in [this reference](https://docs.medusajs.com/resources/medusa-container-resources/index.html.md). You can use these resources in your custom workflows. # Run Workflow Steps in Parallel @@ -20670,7 +20688,7 @@ The first line indicates the first time the step was executed, and the next two By default, a step configured with the `maxRetries` property will be retried automatically when it fails. -You can disable automatic retries by setting the `autoRetry` property to `false` in the step's configuration object. Then, when the step fails, its status will be set to temporary failure, and you'll need to manually retry it using the [Workflow Engine Module Service](undefined/resources/infrastructure-modules/workflow-engine). +You can disable automatic retries by setting the `autoRetry` property to `false` in the step's configuration object. Then, when the step fails, its status will be set to temporary failure, and you'll need to manually retry it using the [Workflow Engine Module Service](https://docs.medusajs.com/resources/infrastructure-modules/workflow-engine/index.html.md). The `autoRetry` property is available since [Medusa v2.10.2](https://github.com/medusajs/medusa/releases/tag/v2.10.2). @@ -20743,11 +20761,11 @@ In this example, if the step fails, it will be retried after `86400` seconds (on ### Interval Changes Workflow to Long-Running -By setting `retryInterval` on a step, a workflow that uses that step becomes a [long-running workflow](undefined/learn/fundamentals/workflows/long-running-workflow) that runs asynchronously in the background. This is useful when creating workflows that may fail and should run for a long time until they succeed, such as waiting for a payment to be captured or a shipment to be delivered. +By setting `retryInterval` on a step, a workflow that uses that step becomes a [long-running workflow](https://docs.medusajs.com/learn/fundamentals/workflows/long-running-workflow/index.html.md) that runs asynchronously in the background. This is useful when creating workflows that may fail and should run for a long time until they succeed, such as waiting for a payment to be captured or a shipment to be delivered. However, since the long-running workflow runs in the background, you won't receive its result or errors immediately when you execute the workflow. -Instead, you must subscribe to the workflow's execution using the Workflow Engine Module's service. Learn more about this in the [Long-Running Workflows](undefined/learn/fundamentals/workflows/long-running-workflow#access-long-running-workflow-status-and-result) chapter. +Instead, you must subscribe to the workflow's execution using the Workflow Engine Module's service. Learn more about this in the [Long-Running Workflows](https://docs.medusajs.com/learn/fundamentals/workflows/long-running-workflow#access-long-running-workflow-status-and-result/index.html.md) chapter. *** @@ -20756,7 +20774,7 @@ Instead, you must subscribe to the workflow's execution using the Workflow Engin In some cases, you may need to manually retry a step. For example: - If a step's `autoRetry` property is set to `false`. -- If the machine running the Medusa application in development or [worker mode](undefined/learn/configurations/medusa-config#workermode) dies or shuts down. +- If the machine running the Medusa application in development or [worker mode](https://docs.medusajs.com/learn/configurations/medusa-config#workermode/index.html.md) dies or shuts down. - If the step takes longer than expected to complete. To retry a step manually, resolve the Workflow Engine Module's service from the Medusa container and call its `retryStep` method. @@ -20790,7 +20808,7 @@ export async function GET( When you send a request to the API route, the workflow execution will resume, retrying the specified step. -Learn more about the `retryStep` method in the [Workflow Engine Module Service reference](undefined/resources/infrastructure-modules/workflow-engine/how-to-use#retryStep). +Learn more about the `retryStep` method in the [Workflow Engine Module Service reference](https://docs.medusajs.com/resources/infrastructure-modules/workflow-engine/how-to-use#retryStep/index.html.md). # Store Workflow Executions @@ -20811,11 +20829,11 @@ You can view stored workflow executions from the Medusa Admin dashboard by going ### Prerequisites -- [Redis Workflow Engine must be installed and configured.](undefined/resources/infrastructure-modules/workflow-engine/redis) +- [Redis Workflow Engine must be installed and configured.](https://docs.medusajs.com/resources/infrastructure-modules/workflow-engine/redis/index.html.md) `createWorkflow` from the Workflows SDK can accept an object as a first parameter to set the workflow's configuration. To enable storing a workflow's executions: -- Enable the `store` option. If your workflow is a [Long-Running Workflow](undefined/learn/fundamentals/workflows/long-running-workflow), this option is enabled by default. +- Enable the `store` option. If your workflow is a [Long-Running Workflow](https://docs.medusajs.com/learn/fundamentals/workflows/long-running-workflow/index.html.md), this option is enabled by default. - Set the `retentionTime` option to the number of seconds that the workflow execution should be stored in the database. For example: @@ -21099,7 +21117,7 @@ Since `str`'s value isn't used as a step's input or passed to `WorkflowResponse` `transform` should only be used to perform variable or data manipulation. -If you want to perform some validation on the data, use a step or [when-then](undefined/learn/fundamentals/workflows/conditions) instead. +If you want to perform some validation on the data, use a step or [when-then](https://docs.medusajs.com/learn/fundamentals/workflows/conditions/index.html.md) instead. For example: @@ -21153,7 +21171,7 @@ A workflow hook is a specific point in a workflow where you can inject custom fu Medusa exposes hooks in many of its workflows that are used in its API routes. You can consume those hooks to add your custom logic. -Refer to the [Workflows Reference](undefined/resources/medusa-workflows-reference) to view all workflows and their hooks. +Refer to the [Workflows Reference](https://docs.medusajs.com/resources/medusa-workflows-reference/index.html.md) to view all workflows and their hooks. You want to perform a custom action during a workflow's execution, such as when a product is created. @@ -21185,11 +21203,11 @@ The `productsCreated` hook is available in the workflow's `hooks` property. You call the hook and pass a step function (the hook handler) as a parameter. -Now, when a product is created using the [Create Product API route](undefined/api/admin#products_postproducts), your hook handler runs after the product is created. +Now, when a product is created using the [Create Product API route](https://docs.medusajs.com/api/admin#products_postproducts), your hook handler runs after the product is created. A hook can have only one handler. So, you can't consume the same hook multiple times. -Refer to the [createProductsWorkflow reference](undefined/resources/references/medusa-workflows/createProductsWorkflow) to see at which point the hook handler is executed. +Refer to the [createProductsWorkflow reference](https://docs.medusajs.com/resources/references/medusa-workflows/createProductsWorkflow/index.html.md) to see at which point the hook handler is executed. ### Hook Handler Parameter @@ -21197,7 +21215,7 @@ Since a hook handler is essentially a step function, it receives the hook's inpu Each hook has different input. For example, the `productsCreated` hook receives an object with a `products` property that contains the created product. -You can find the input for each workflow's hooks in the [Core Workflows Reference](undefined/resources/medusa-workflows-reference). +You can find the input for each workflow's hooks in the [Core Workflows Reference](https://docs.medusajs.com/resources/medusa-workflows-reference/index.html.md). ### Hook Handler Compensation @@ -21242,7 +21260,7 @@ createProductsWorkflow.hooks.productsCreated( This property is an object that contains additional data passed to the workflow through the request sent to the API route. -Learn how to pass `additional_data` in requests to API routes in the [Additional Data](undefined/learn/fundamentals/api-routes/additional-data) chapter. +Learn how to pass `additional_data` in requests to API routes in the [Additional Data](https://docs.medusajs.com/learn/fundamentals/api-routes/additional-data/index.html.md) chapter. ### Pass Additional Data to Workflow @@ -21324,7 +21342,7 @@ export default myWorkflow This workflow's executions fail if they run longer than two seconds. -A workflow’s timeout error is returned in the `errors` property of the workflow’s execution, as explained in [this chapter](undefined/learn/fundamentals/workflows/errors). The error’s name is `TransactionTimeoutError`. +A workflow’s timeout error is returned in the `errors` property of the workflow’s execution, as explained in [this chapter](https://docs.medusajs.com/learn/fundamentals/workflows/errors/index.html.md). The error’s name is `TransactionTimeoutError`. *** @@ -21352,14 +21370,14 @@ const step1 = createStep( This step's executions fail if they run longer than two seconds. -A step’s timeout error is returned in the `errors` property of the workflow’s execution, as explained in [this chapter](undefined/learn/fundamentals/workflows/errors). The error’s name is `TransactionStepTimeoutError`. +A step’s timeout error is returned in the `errors` property of the workflow’s execution, as explained in [this chapter](https://docs.medusajs.com/learn/fundamentals/workflows/errors/index.html.md). The error’s name is `TransactionStepTimeoutError`. # Install Medusa with Docker In this chapter, you'll learn how to install and run a Medusa application using Docker. -The main supported installation method is using [create-medusa-app](undefined/learn/installation). However, since it requires prerequisites like PostgreSQL, Docker may be a preferred and easier option for some users. You can follow this guide to set up a Medusa application with Docker in this case. +The main supported installation method is using [create-medusa-app](https://docs.medusajs.com/learn/installation/index.html.md). However, since it requires prerequisites like PostgreSQL, Docker may be a preferred and easier option for some users. You can follow this guide to set up a Medusa application with Docker in this case. You can follow this guide on any operating system that supports Docker, including Windows, macOS, and Linux. @@ -21473,10 +21491,12 @@ If this isn't the first Medusa project you're setting up with Docker on your mac ## 3. Create `start.sh` -Next, you need to create a script file that [runs database migrations](undefined/learn/fundamentals/data-models/write-migration) and starts the Medusa development server. +Next, you need to create a script file that [runs database migrations](https://docs.medusajs.com/learn/fundamentals/data-models/write-migration/index.html.md) and starts the Medusa development server. Create the file `start.sh` with the following content: +Ensure that the `start.sh` file uses LF line endings instead of CRLF. Git on Windows can sometimes automatically convert line endings, which causes errors when running the script inside the Linux-based Docker container. Learn how to configure your environment to maintain LF line endings in [this guide from GitHub](https://docs.github.com/en/get-started/git-basics/configuring-git-to-handle-line-endings). + ### Yarn ```shell title="start.sh" @@ -21579,7 +21599,7 @@ In the `Dockerfile`, you use the `node:20-alpine` image as the base since Medusa Then, you set the working directory to `/server`, copy the necessary files, install dependencies, expose the `9000` port that Medusa uses, and run the `start.sh` script to start the server. -While it's more common to use `/app` as the working directory, it's highly recommended to use `/server` for the Medusa service to avoid conflicts with Medusa Admin customizations. Learn more in [this troubleshooting guide](undefined/resources/troubleshooting/medusa-admin/no-widget-route#errors-in-docker). +While it's more common to use `/app` as the working directory, it's highly recommended to use `/server` for the Medusa service to avoid conflicts with Medusa Admin customizations. Learn more in [this troubleshooting guide](https://docs.medusajs.com/resources/troubleshooting/medusa-admin/no-widget-route#errors-in-docker/index.html.md). *** @@ -21644,7 +21664,7 @@ module.exports = defineConfig({ }) ``` -You add the [projectConfig.databaseDriverOptions](undefined/learn/configurations/medusa-config#databasedriveroptions) to disable SSL for the PostgreSQL database connection. +You add the [projectConfig.databaseDriverOptions](https://docs.medusajs.com/learn/configurations/medusa-config#databasedriveroptions/index.html.md) to disable SSL for the PostgreSQL database connection. *** @@ -21750,7 +21770,7 @@ This command shows the logs of the `medusa` service, allowing you to see any err ## Learn More about your Medusa Application -You can learn more about your Medusa application and its setup in the [Installation chapter](undefined/learn/installation). +You can learn more about your Medusa application and its setup in the [Installation chapter](https://docs.medusajs.com/learn/installation/index.html.md). # Install Medusa @@ -21759,9 +21779,9 @@ In this chapter, you'll learn how to install and run a Medusa application. ## Create Medusa Application -A Medusa application is made up of a Node.js server and an admin dashboard. You can optionally install the [Next.js Starter Storefront](undefined/resources/nextjs-starter) separately either while installing the Medusa application or at a later point. +A Medusa application is made up of a Node.js server and an admin dashboard. You can optionally install the [Next.js Starter Storefront](https://docs.medusajs.com/resources/nextjs-starter/index.html.md) separately either while installing the Medusa application or at a later point. -While this is the recommended way to create a Medusa application, you can alternatively [install a Medusa application with Docker](undefined/learn/installation/docker). +While this is the recommended way to create a Medusa application, you can alternatively [install a Medusa application with Docker](https://docs.medusajs.com/learn/installation/docker/index.html.md). ### Prerequisites @@ -21777,7 +21797,7 @@ npx create-medusa-app@latest my-medusa-store Where `my-medusa-store` is the name of the project's directory and PostgreSQL database created for the project. When you run the command, you'll be asked whether you want to install the Next.js Starter Storefront. -To customize the default installation behavior, such as specify a database URL, refer to the [create-medusa-app reference](undefined/resources/create-medusa-app). +To customize the default installation behavior, such as specify a database URL, refer to the [create-medusa-app reference](https://docs.medusajs.com/resources/create-medusa-app/index.html.md). After answering the prompts, the command installs the Medusa application in a directory with your project name, and sets up a PostgreSQL database that the application connects to. @@ -21822,7 +21842,7 @@ This runs your Medusa server at `http://localhost:9000`, and the Medusa Admin da ![Diagram showcasing the server and application running when you start the Medusa application](https://res.cloudinary.com/dza7lstvk/image/upload/v1745856966/Medusa%20Resources/start-overview_aetplx.jpg) -For details on starting and configuring the Next.js Starter Storefront, refer to [this documentation](undefined/resources/nextjs-starter). +For details on starting and configuring the Next.js Starter Storefront, refer to [this documentation](https://docs.medusajs.com/resources/nextjs-starter/index.html.md). The application will restart if you make any changes to code under the `src` directory, except for admin customizations which are hot reloaded, providing you with a seamless developer experience without having to refresh your browser to see the changes. @@ -21854,18 +21874,18 @@ Your Medusa application's project will have the following files and directories: This directory is the central place for your custom development. It includes the following sub-directories: -- `admin`: Holds your admin dashboard's custom [widgets](undefined/learn/fundamentals/admin/widgets) and [UI routes](undefined/learn/fundamentals/admin/ui-routes). -- `api`: Holds your custom [API routes](undefined/learn/fundamentals/api-routes) that are added as endpoints in your Medusa application. -- `jobs`: Holds your [scheduled jobs](undefined/learn/fundamentals/scheduled-jobs) that run at a specified interval during your Medusa application's runtime. -- `links`: Holds your [module links](undefined/learn/fundamentals/module-links) that build associations between data models of different modules. -- `modules`: Holds your custom [modules](undefined/learn/fundamentals/modules) that implement custom business logic. -- `scripts`: Holds your custom [scripts](undefined/learn/fundamentals/custom-cli-scripts) to be executed using Medusa's CLI tool. -- `subscribers`: Holds your [event listeners](undefined/learn/fundamentals/events-and-subscribers) that are executed asynchronously whenever an event is emitted. -- `workflows`: Holds your custom [flows](undefined/learn/fundamentals/workflows) that can be executed from anywhere in your application. +- `admin`: Holds your admin dashboard's custom [widgets](https://docs.medusajs.com/learn/fundamentals/admin/widgets/index.html.md) and [UI routes](https://docs.medusajs.com/learn/fundamentals/admin/ui-routes/index.html.md). +- `api`: Holds your custom [API routes](https://docs.medusajs.com/learn/fundamentals/api-routes/index.html.md) that are added as endpoints in your Medusa application. +- `jobs`: Holds your [scheduled jobs](https://docs.medusajs.com/learn/fundamentals/scheduled-jobs/index.html.md) that run at a specified interval during your Medusa application's runtime. +- `links`: Holds your [module links](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md) that build associations between data models of different modules. +- `modules`: Holds your custom [modules](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md) that implement custom business logic. +- `scripts`: Holds your custom [scripts](https://docs.medusajs.com/learn/fundamentals/custom-cli-scripts/index.html.md) to be executed using Medusa's CLI tool. +- `subscribers`: Holds your [event listeners](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/index.html.md) that are executed asynchronously whenever an event is emitted. +- `workflows`: Holds your custom [flows](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) that can be executed from anywhere in your application. ### medusa-config.ts -This file holds your [Medusa configurations](undefined/learn/configurations/medusa-config), such as your PostgreSQL database configurations. +This file holds your [Medusa configurations](https://docs.medusajs.com/learn/configurations/medusa-config/index.html.md), such as your PostgreSQL database configurations. ### .medusa @@ -21877,13 +21897,13 @@ The `.medusa` directory holds types and other files that are generated by Medusa By default, your Medusa application is equipped with the basic configuration to start your development. -If you run into issues with configurations, such as CORS configurations, or need to make changes to the default configuration, refer to [this guide on all available configurations](undefined/learn/configurations/medusa-config). +If you run into issues with configurations, such as CORS configurations, or need to make changes to the default configuration, refer to [this guide on all available configurations](https://docs.medusajs.com/learn/configurations/medusa-config/index.html.md). *** ## Update Medusa Application -Refer to [this documentation](undefined/learn/update) to learn how to update your Medusa project. +Refer to [this documentation](https://docs.medusajs.com/learn/update/index.html.md) to learn how to update your Medusa project. *** @@ -21909,7 +21929,7 @@ In a common Medusa application, requests go through four layers in the stack. In 3. Modules: Workflows use domain-specific modules for resource management. 4. Data store: Modules query the underlying datastore, which is a PostgreSQL database in common cases. -These layers of stack can be implemented within [plugins](undefined/learn/fundamentals/plugins). +These layers of stack can be implemented within [plugins](https://docs.medusajs.com/learn/fundamentals/plugins/index.html.md). ![Medusa application architecture diagram illustrating the HTTP layer flow: External clients (storefront and admin) send requests to API routes, which execute workflows containing business logic, which then interact with modules to perform data operations on PostgreSQL databases](https://res.cloudinary.com/dza7lstvk/image/upload/v1727175296/Medusa%20Book/http-layer_sroafr.jpg) @@ -21917,9 +21937,9 @@ These layers of stack can be implemented within [plugins](undefined/learn/fundam ## Database Layer -The Medusa application injects into each module, including your [custom modules](undefined/learn/fundamentals/modules), a connection to the configured PostgreSQL database. Modules use that connection to read and write data to the database. +The Medusa application injects into each module, including your [custom modules](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md), a connection to the configured PostgreSQL database. Modules use that connection to read and write data to the database. -Modules can be implemented within [plugins](undefined/learn/fundamentals/plugins). +Modules can be implemented within [plugins](https://docs.medusajs.com/learn/fundamentals/plugins/index.html.md). ![Database layer architecture diagram showing how Medusa modules establish connections to PostgreSQL databases through injected database connections, enabling data persistence and retrieval operations](https://res.cloudinary.com/dza7lstvk/image/upload/v1727175379/Medusa%20Book/db-layer_pi7tix.jpg) @@ -21927,15 +21947,15 @@ Modules can be implemented within [plugins](undefined/learn/fundamentals/plugins ## Third-Party Integrations Layer -Third-party services and systems are integrated through Medusa's Commerce and Infrastructure Modules. You also create custom third-party integrations through a [custom module](undefined/learn/fundamentals/modules). +Third-party services and systems are integrated through Medusa's Commerce and Infrastructure Modules. You also create custom third-party integrations through a [custom module](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md). -Modules can be implemented within [plugins](undefined/learn/fundamentals/plugins). +Modules can be implemented within [plugins](https://docs.medusajs.com/learn/fundamentals/plugins/index.html.md). ### Commerce Modules -[Commerce Modules](undefined/resources/commerce-modules) integrate third-party services relevant for commerce or user-facing features. For example, you can integrate [Stripe](undefined/resources/commerce-modules/payment/payment-provider/stripe) through a Payment Module Provider, or [ShipStation](undefined/resources/integrations/guides/shipstation) through a Fulfillment Module Provider. +[Commerce Modules](https://docs.medusajs.com/resources/commerce-modules/index.html.md) integrate third-party services relevant for commerce or user-facing features. For example, you can integrate [Stripe](https://docs.medusajs.com/resources/commerce-modules/payment/payment-provider/stripe/index.html.md) through a Payment Module Provider, or [ShipStation](https://docs.medusajs.com/resources/integrations/guides/shipstation/index.html.md) through a Fulfillment Module Provider. -You can also integrate third-party services for custom functionalities. For example, you can integrate [Sanity](undefined/resources/integrations/guides/sanity) for rich CMS capabilities, or [Odoo](undefined/resources/recipes/erp/odoo) to sync your Medusa application with your ERP system. +You can also integrate third-party services for custom functionalities. For example, you can integrate [Sanity](https://docs.medusajs.com/resources/integrations/guides/sanity/index.html.md) for rich CMS capabilities, or [Odoo](https://docs.medusajs.com/resources/recipes/erp/odoo/index.html.md) to sync your Medusa application with your ERP system. You can replace any of the third-party services mentioned above to build your preferred commerce ecosystem. @@ -21943,15 +21963,15 @@ You can replace any of the third-party services mentioned above to build your pr ### Infrastructure Modules -[Infrastructure Modules](undefined/resources/infrastructure-modules) integrate third-party services and systems that customize Medusa's infrastructure. Medusa has the following Infrastructure Modules: +[Infrastructure Modules](https://docs.medusajs.com/resources/infrastructure-modules/index.html.md) integrate third-party services and systems that customize Medusa's infrastructure. Medusa has the following Infrastructure Modules: -- [Analytics Module](undefined/resources/infrastructure-modules/analytics): Tracks and analyzes user interactions and system events with third-party analytic providers. You can integrate [PostHog](undefined/resources/infrastructure-modules/analytics/posthog) as the analytics provider. -- [Cache Module](undefined/resources/infrastructure-modules/cache): Caches data that require heavy computation. You can integrate a custom module to handle the caching with services like Memcached, or use the existing [Redis Cache Module](undefined/resources/infrastructure-modules/cache/redis). -- [Event Module](undefined/resources/infrastructure-modules/event): A pub/sub system that allows you to subscribe to events and trigger them. You can integrate [Redis](undefined/resources/infrastructure-modules/event/redis) as the pub/sub system. -- [File Module](undefined/resources/infrastructure-modules/file): Manages file uploads and storage, such as upload of product images. You can integrate [AWS S3](undefined/resources/infrastructure-modules/file/s3) for file storage. -- [Locking Module](undefined/resources/infrastructure-modules/locking): Manages access to shared resources by multiple processes or threads, preventing conflict between processes and ensuring data consistency. You can integrate [Redis](undefined/resources/infrastructure-modules/locking/redis) for locking. -- [Notification Module](undefined/resources/infrastructure-modules/notification): Sends notifications to customers and users, such as for order updates or newsletters. You can integrate [SendGrid](undefined/resources/infrastructure-modules/notification/sendgrid) for sending emails. -- [Workflow Engine Module](undefined/resources/infrastructure-modules/workflow-engine): Orchestrates workflows that hold the business logic of your application. You can integrate [Redis](undefined/resources/infrastructure-modules/workflow-engine/redis) to orchestrate workflows. +- [Analytics Module](https://docs.medusajs.com/resources/infrastructure-modules/analytics/index.html.md): Tracks and analyzes user interactions and system events with third-party analytic providers. You can integrate [PostHog](https://docs.medusajs.com/resources/infrastructure-modules/analytics/posthog/index.html.md) as the analytics provider. +- [Cache Module](https://docs.medusajs.com/resources/infrastructure-modules/cache/index.html.md): Caches data that require heavy computation. You can integrate a custom module to handle the caching with services like Memcached, or use the existing [Redis Cache Module](https://docs.medusajs.com/resources/infrastructure-modules/cache/redis/index.html.md). +- [Event Module](https://docs.medusajs.com/resources/infrastructure-modules/event/index.html.md): A pub/sub system that allows you to subscribe to events and trigger them. You can integrate [Redis](https://docs.medusajs.com/resources/infrastructure-modules/event/redis/index.html.md) as the pub/sub system. +- [File Module](https://docs.medusajs.com/resources/infrastructure-modules/file/index.html.md): Manages file uploads and storage, such as upload of product images. You can integrate [AWS S3](https://docs.medusajs.com/resources/infrastructure-modules/file/s3/index.html.md) for file storage. +- [Locking Module](https://docs.medusajs.com/resources/infrastructure-modules/locking/index.html.md): Manages access to shared resources by multiple processes or threads, preventing conflict between processes and ensuring data consistency. You can integrate [Redis](https://docs.medusajs.com/resources/infrastructure-modules/locking/redis/index.html.md) for locking. +- [Notification Module](https://docs.medusajs.com/resources/infrastructure-modules/notification/index.html.md): Sends notifications to customers and users, such as for order updates or newsletters. You can integrate [SendGrid](https://docs.medusajs.com/resources/infrastructure-modules/notification/sendgrid/index.html.md) for sending emails. +- [Workflow Engine Module](https://docs.medusajs.com/resources/infrastructure-modules/workflow-engine/index.html.md): Orchestrates workflows that hold the business logic of your application. You can integrate [Redis](https://docs.medusajs.com/resources/infrastructure-modules/workflow-engine/redis/index.html.md) to orchestrate workflows. All of the third-party services mentioned above can be replaced to help you build your preferred architecture and ecosystem. @@ -22093,9 +22113,9 @@ Refer to the [Node.js documentation](https://nodejs.org/en/docs/) for instructio Medusa v2 makes big changes to the database. So, your existing database will not be compatible with the database for your v2 project. -If you want to keep your product catalog, you should export the products from the admin dashboard, as explained in [this V1 User Guide](https://docs.medusajs.com/v1/user-guide/products/export/index.html.md). Then, you can import them into your new v2 project from the [Medusa Admin](undefined/user-guide/products/import). +If you want to keep your product catalog, you should export the products from the admin dashboard, as explained in [this V1 User Guide](https://docs.medusajs.com/v1/user-guide/products/export/index.html.md). Then, you can import them into your new v2 project from the [Medusa Admin](https://docs.medusajs.com/user-guide/products/import/index.html.md). -For other data types, you'll probably need to migrate them manually through custom scripts. [Custom CLI scripts](undefined/learn/fundamentals/custom-cli-scripts) may be useful for this. +For other data types, you'll probably need to migrate them manually through custom scripts. [Custom CLI scripts](https://docs.medusajs.com/learn/fundamentals/custom-cli-scripts/index.html.md) may be useful for this. *** @@ -22103,7 +22123,7 @@ For other data types, you'll probably need to migrate them manually through cust In this section, you'll learn how to upgrade your Medusa project from v1 to v2. -To create a fresh new Medusa v2 project, check out the [Installation chapter](undefined/learn/installation). +To create a fresh new Medusa v2 project, check out the [Installation chapter](https://docs.medusajs.com/learn/installation/index.html.md). It's highly recommended to fully go through this chapter before you actually update your application, as some v1 features may have been removed or heavily changed in v2. By doing so, you'll formulate a clearer plan for your migration process and its feasibility. @@ -22219,9 +22239,9 @@ Where: You'll learn more about the [changes in the CLI tool later in this chapter](#medusa-cli-changes). You can also refer to the following documents to learn more about these changes: -- [Medusa CLI reference](undefined/resources/medusa-cli) -- [Build Medusa Application](undefined/learn/build) -- [Integration and Module Tests](undefined/learn/debugging-and-testing/testing-tools). +- [Medusa CLI reference](https://docs.medusajs.com/resources/medusa-cli/index.html.md) +- [Build Medusa Application](https://docs.medusajs.com/learn/build/index.html.md) +- [Integration and Module Tests](https://docs.medusajs.com/learn/debugging-and-testing/testing-tools/index.html.md). ### 3. TSConfig Changes @@ -22233,7 +22253,7 @@ In Medusa v2, you only need one [root tsconfig.json](https://github.com/medusajs In Medusa v1, you configured your application in the `medusa-config.js` file. Medusa v2 supports this file as `medusa-config.ts`, so make sure to rename it. -`medusa-config.ts` now exports configurations created with the `defineConfig` utility. It also uses the [loadEnv](undefined/learn/fundamentals/environment-variables) utility to load environment variables based on the current environment. +`medusa-config.ts` now exports configurations created with the `defineConfig` utility. It also uses the [loadEnv](https://docs.medusajs.com/learn/fundamentals/environment-variables/index.html.md) utility to load environment variables based on the current environment. For example, this is the configuration file for a basic Medusa v2 project: @@ -22256,7 +22276,7 @@ module.exports = defineConfig({ }) ``` -You can refer to the full list of configurations in the [Medusa Configurations](undefined/learn/configurations/medusa-config) chapter. The following table highlights the main changes between v1 and v2: +You can refer to the full list of configurations in the [Medusa Configurations](https://docs.medusajs.com/learn/configurations/medusa-config/index.html.md) chapter. The following table highlights the main changes between v1 and v2: |Medusa v1|Medusa v2| |---|---| @@ -22288,7 +22308,7 @@ While the `plugins` configuration hasn't changed, plugins available in Medusa v1 In Medusa v1, you had to configure modules like Inventory, Stock Location, Pricing, and Product. These modules are now available out of the box, and you don't need to install or configure them separately. -For the Cache and Event modules, refer to the [Redis Cache Module](undefined/resources/infrastructure-modules/cache/redis) and [Redis Event Module](undefined/resources/infrastructure-modules/event/redis) documentations to learn how to configure them in v2 if you had them configured in v1. +For the Cache and Event modules, refer to the [Redis Cache Module](https://docs.medusajs.com/resources/infrastructure-modules/cache/redis/index.html.md) and [Redis Event Module](https://docs.medusajs.com/resources/infrastructure-modules/event/redis/index.html.md) documentations to learn how to configure them in v2 if you had them configured in v1. #### Feature Flags @@ -22364,7 +22384,7 @@ module.exports = defineConfig({ }) ``` -You can refer to the [Medusa Configuration](undefined/learn/configurations/medusa-config#admin-configurations-admin) chapter to learn about all the admin configurations. The following table highlights the main changes between v1 and v2: +You can refer to the [Medusa Configuration](https://docs.medusajs.com/learn/configurations/medusa-config#admin-configurations-admin/index.html.md) chapter to learn about all the admin configurations. The following table highlights the main changes between v1 and v2: |Medusa v1|Medusa v2| |---|---| @@ -22378,7 +22398,7 @@ You can refer to the [Medusa Configuration](undefined/learn/configurations/medus In v1, you were able to modify Webpack configurations of the admin dashboard. -Since Medusa Admin is now built with Vite, you can modify the Vite configurations with the `admin.vite` configuration. Learn more in the [Medusa Configuration](undefined/learn/configurations/medusa-config#vite) chapter. +Since Medusa Admin is now built with Vite, you can modify the Vite configurations with the `admin.vite` configuration. Learn more in the [Medusa Configuration](https://docs.medusajs.com/learn/configurations/medusa-config#vite/index.html.md) chapter. ### Admin CLI Tool @@ -22386,7 +22406,7 @@ In Medusa v1, you used the `medusa-admin` CLI tool to build and run the admin da In Medusa v2, the Medusa Admin doesn't have a CLI tool. Instead, running `medusa build` and `medusa develop` also builds and runs the Medusa Admin, respectively. -In addition, you can build the Medusa Admin separately from the Medusa application using the `--admin-only` option. Learn more in the [Build Medusa Application](undefined/learn/build#separate-admin-build) chapter. +In addition, you can build the Medusa Admin separately from the Medusa application using the `--admin-only` option. Learn more in the [Build Medusa Application](https://docs.medusajs.com/learn/build#separate-admin-build/index.html.md) chapter. *** @@ -22394,7 +22414,7 @@ In addition, you can build the Medusa Admin separately from the Medusa applicati The Medusa CLI for v2 is now in the `@medusajs/cli` package. However, you don't need to install it globally. You can just use `npx medusa` in your Medusa projects. -Refer to the [Medusa CLI reference](undefined/resources/medusa-cli) for the full list of commands and options. The following table highlights the main changes between v1 and v2: +Refer to the [Medusa CLI reference](https://docs.medusajs.com/resources/medusa-cli/index.html.md) for the full list of commands and options. The following table highlights the main changes between v1 and v2: |Medusa v1|Medusa v2| |---|---| @@ -22414,7 +22434,7 @@ In Medusa v1, you created plugins that contained customizations like services th In Medusa v2, a plugin can contain customizations like modules that integrate third-party providers, custom API routes, workflows, and more. The plugin development experience has also been improved to resolve big pain points that developers faced in v1. -Refer to the [Plugins](undefined/learn/fundamentals/plugins) chapter to learn more about plugins in Medusa v2. +Refer to the [Plugins](https://docs.medusajs.com/learn/fundamentals/plugins/index.html.md) chapter to learn more about plugins in Medusa v2. The rest of this section will cover some of the main changes in plugins between v1 and v2. @@ -22482,7 +22502,7 @@ export const config: SubscriberConfig = { } ``` -Learn more in the [Create Plugin](undefined/learn/fundamentals/plugins/create) chapter. +Learn more in the [Create Plugin](https://docs.medusajs.com/learn/fundamentals/plugins/create/index.html.md) chapter. #### enableUI Option @@ -22519,7 +22539,7 @@ In Medusa v1, entities, services, and modules were created separately: In Medusa v2, you create entities (now called data models) and services in a module. You can't create them separately anymore. The data models define new tables to add to the database, and the service provides data-management features for those data models. -In this section, you'll learn about the most important changes related to these concepts. You can also learn more in the [Modules](undefined/learn/fundamentals/modules) chapter. +In this section, you'll learn about the most important changes related to these concepts. You can also learn more in the [Modules](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md) chapter. #### Modules @@ -22527,7 +22547,7 @@ A module is a reusable package of functionalities related to a single domain or So, if in Medusa v1 you had a `Brand` entity and a service to manage it, in v2, you create a Brand Module that defines a `Brand` data model and a service to manage it. -To learn how to create a module, refer to the [Modules](undefined/learn/fundamentals/modules) chapter. +To learn how to create a module, refer to the [Modules](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md) chapter. ![Diagram showcasing the directory structure difference between Medusa v1 and v2](https://res.cloudinary.com/dza7lstvk/image/upload/v1748277500/Medusa%20Book/modules-v1-v2_dsnzyl.jpg) @@ -22548,7 +22568,7 @@ export const Brand = model.define("brand", { }) ``` -Learn more about data models in the [Data Models](undefined/learn/fundamentals/data-models) chapters. +Learn more about data models in the [Data Models](https://docs.medusajs.com/learn/fundamentals/data-models/index.html.md) chapters. #### Migrations @@ -22560,7 +22580,7 @@ In Medusa v2, you can use the Medusa CLI to generate migrations based on MikroOR npx medusa db:generate brand ``` -This generates migrations for data models in the Brand Module. Learn more in the [Migrations](undefined/learn/fundamentals/data-models/write-migration) chapter. +This generates migrations for data models in the Brand Module. Learn more in the [Migrations](https://docs.medusajs.com/learn/fundamentals/data-models/write-migration/index.html.md) chapter. #### Services @@ -22585,9 +22605,9 @@ export default BrandModuleService The service has automatically generated data-management methods by extending `MedusaService` from the Modules SDK. So, you now have methods like `retrieveBrand` and `createBrands` available in the service. -Learn more in the [Service Factory](undefined/learn/fundamentals/modules/service-factory) chapter. +Learn more in the [Service Factory](https://docs.medusajs.com/learn/fundamentals/modules/service-factory/index.html.md) chapter. -When you register the module in the Medusa application, the service is registered in the [Medusa container](undefined/learn/fundamentals/medusa-container), allowing you to use its methods in workflows, subscribers, scheduled jobs, and API routes. +When you register the module in the Medusa application, the service is registered in the [Medusa container](https://docs.medusajs.com/learn/fundamentals/medusa-container/index.html.md), allowing you to use its methods in workflows, subscribers, scheduled jobs, and API routes. #### Repositories @@ -22621,7 +22641,7 @@ class BlogModuleService { export default BlogModuleService ``` -Learn more in the [Database Operations](undefined/learn/fundamentals/modules/db-operations) chapter. +Learn more in the [Database Operations](https://docs.medusajs.com/learn/fundamentals/modules/db-operations/index.html.md) chapter. #### Module Isolation @@ -22629,13 +22649,13 @@ In Medusa v1, you had access to all entities and services in the Medusa applicat In Medusa v2, modules are isolated. This means that you can only access entities and services within the module. This isolation allows you to integrate modules into your application without side effects, while still providing you with the necessary flexibility to build your use cases. -The [Module Isolation](undefined/learn/fundamentals/modules/isolation) chapter explains this concept in detail. The rest of this section gives a general overview of how module isolation affects your Medusa v1 customizations. +The [Module Isolation](https://docs.medusajs.com/learn/fundamentals/modules/isolation/index.html.md) chapter explains this concept in detail. The rest of this section gives a general overview of how module isolation affects your Medusa v1 customizations. #### Extending Entities In Medusa v1, you were able to extend entities by creating a new entity that extended the original one. For example, you could create a custom `Product` entity that extended the original `Product` entity to add a `brand` column. -In Medusa v2, you can no longer extend entities. Instead, you need to create a new data model that contains the columns you want to add. Then, you can create a [Module Link](undefined/learn/fundamentals/module-links) that links your data model to the one you want to extend. +In Medusa v2, you can no longer extend entities. Instead, you need to create a new data model that contains the columns you want to add. Then, you can create a [Module Link](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md) that links your data model to the one you want to extend. For example, you create a Brand Module that has a `Brand` data model. Then, you create a Module Link that links the `Brand` data model to the `Product` data model in the Product Module: @@ -22655,16 +22675,16 @@ export default defineLink( You can then associate brands with a product, retrieve them in API routes and custom functionalities, and more. -Learn more in the [Module Links](undefined/learn/fundamentals/module-links) chapter. +Learn more in the [Module Links](https://docs.medusajs.com/learn/fundamentals/module-links/index.html.md) chapter. #### Extending Services In Medusa v1, you were able to extend services by creating a new service that extended the original one. For example, you could create a custom `ProductService` that extended the original `ProductService` to add a new method. -In Medusa v2, you can no longer extend services. Instead, you need to [create a module](undefined/learn/fundamentals/modules) with a service that contains the methods you want to add. Then, you can: +In Medusa v2, you can no longer extend services. Instead, you need to [create a module](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md) with a service that contains the methods you want to add. Then, you can: -- Build [workflows](undefined/learn/fundamentals/workflows) that use both services to achieve a custom feature. -- Consume [Workflow Hooks](undefined/learn/fundamentals/workflows/workflow-hooks) to run custom actions in existing workflows. +- Build [workflows](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) that use both services to achieve a custom feature. +- Consume [Workflow Hooks](https://docs.medusajs.com/learn/fundamentals/workflows/workflow-hooks/index.html.md) to run custom actions in existing workflows. - For more complex use cases, you can re-create an existing workflow and use your custom module's service in it. For example, if you extended the `CartService` in v1 to add items with custom prices to the cart, you can instead build a custom workflow that uses your custom module to retrieve an item's price, then add it to the cart using the existing `addToCartWorkflow`: @@ -22719,13 +22739,13 @@ export const addCustomToCartWorkflow = createWorkflow( ) ``` -Refer to the [Workflows](undefined/learn/fundamentals/workflows) chapters to learn more about workflows in Medusa v2. +Refer to the [Workflows](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) chapters to learn more about workflows in Medusa v2. #### Integrating Third-Party Services In Medusa v1, you integrated third-party services by creating a service under `src/services` and using it in your customizations. -In Medusa v2, you can integrate third-party services by creating a module with a service that contains the methods to interact with the third-party service. You can then use the module's service in a [workflow](undefined/learn/fundamentals/workflows) to build custom features. +In Medusa v2, you can integrate third-party services by creating a module with a service that contains the methods to interact with the third-party service. You can then use the module's service in a [workflow](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) to build custom features. ![Directory structure change between v1 and v2](https://res.cloudinary.com/dza7lstvk/image/upload/v1748278103/Medusa%20Book/integrations-v1-v2_cjzkus.jpg) @@ -22742,7 +22762,7 @@ In Medusa v2, there are two containers: |Medusa container|Main container that contains Framework and commerce resources, such as services of registered modules.|| |Module container|Container of a module. It contains some resources from the Framework, and resources implemented in the module.|Services and loaders in the module.| -You can view the list of resources in each container in the [Container Resources](undefined/resources/medusa-container-resources) reference. +You can view the list of resources in each container in the [Container Resources](https://docs.medusajs.com/resources/medusa-container-resources/index.html.md) reference. *** @@ -22750,7 +22770,7 @@ You can view the list of resources in each container in the [Container Resources In Medusa v2, workflows are the main way to implement custom features spanning across modules and systems. -Workflows have been optimized for data reliability, flexibility, and orchestration across systems. You can learn more in the [Workflows](undefined/learn/fundamentals/workflows) chapters. +Workflows have been optimized for data reliability, flexibility, and orchestration across systems. You can learn more in the [Workflows](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) chapters. This section highlights the main changes in workflows between v1 and v2. @@ -22807,9 +22827,9 @@ export const GET = ( #### New Workflow Features -- [Use when-then in workflows to run steps if a condition is satisfied](undefined/learn/fundamentals/workflows/conditions). -- [Consume hooks to run custom steps in existing workflows](undefined/learn/fundamentals/workflows/workflow-hooks). -- [Create long-running workflows that run asynchronously in the background](undefined/learn/fundamentals/workflows/long-running-workflow). +- [Use when-then in workflows to run steps if a condition is satisfied](https://docs.medusajs.com/learn/fundamentals/workflows/conditions/index.html.md). +- [Consume hooks to run custom steps in existing workflows](https://docs.medusajs.com/learn/fundamentals/workflows/workflow-hooks/index.html.md). +- [Create long-running workflows that run asynchronously in the background](https://docs.medusajs.com/learn/fundamentals/workflows/long-running-workflow/index.html.md). *** @@ -22817,7 +22837,7 @@ export const GET = ( API routes are generally similar in Medusa v1 and v2, but with minor changes. -You can learn more about creating API routes in the [API Routes](undefined/learn/fundamentals/api-routes) chapters. This section highlights the main changes in API routes between v1 and v2. +You can learn more about creating API routes in the [API Routes](https://docs.medusajs.com/learn/fundamentals/api-routes/index.html.md) chapters. This section highlights the main changes in API routes between v1 and v2. #### HTTP Imports @@ -22856,7 +22876,7 @@ export const GET = async ( } ``` -Learn more in the [Protected API Routes](undefined/learn/fundamentals/api-routes/protected-routes) chapter. +Learn more in the [Protected API Routes](https://docs.medusajs.com/learn/fundamentals/api-routes/protected-routes/index.html.md) chapter. #### Authentication Middlewares @@ -22896,7 +22916,7 @@ export default defineMiddlewares({ }) ``` -Learn more in the [Protected API Routes](undefined/learn/fundamentals/api-routes/protected-routes) chapter. +Learn more in the [Protected API Routes](https://docs.medusajs.com/learn/fundamentals/api-routes/protected-routes/index.html.md) chapter. #### Middlewares @@ -22932,7 +22952,7 @@ export default defineMiddlewares({ }) ``` -Learn more in the [Middlewares](undefined/learn/fundamentals/api-routes/middlewares) chapter. +Learn more in the [Middlewares](https://docs.medusajs.com/learn/fundamentals/api-routes/middlewares/index.html.md) chapter. #### Disable Body Parser @@ -22954,7 +22974,7 @@ export default defineMiddlewares({ }) ``` -Learn more in the [Body Parser](undefined/learn/fundamentals/api-routes/parse-body) chapter. +Learn more in the [Body Parser](https://docs.medusajs.com/learn/fundamentals/api-routes/parse-body/index.html.md) chapter. #### Extending Validators @@ -22983,9 +23003,9 @@ export default defineMiddlewares({ In this example, you allow passing a `brand` property as additional data to the `/admin/products` API route. -You can learn more in the [Additional Data](undefined/learn/fundamentals/api-routes/additional-data) chapter. +You can learn more in the [Additional Data](https://docs.medusajs.com/learn/fundamentals/api-routes/additional-data/index.html.md) chapter. -If a route doesn't support passing additional data, you need to [replicate it](undefined/learn/fundamentals/api-routes/override) to support your custom use case. +If a route doesn't support passing additional data, you need to [replicate it](https://docs.medusajs.com/learn/fundamentals/api-routes/override/index.html.md) to support your custom use case. *** @@ -22993,11 +23013,11 @@ If a route doesn't support passing additional data, you need to [replicate it](u Events and subscribers are similar in Medusa v1 and v2, but with minor changes. -You can learn more in the [Events and Subscribers](undefined/learn/fundamentals/events-and-subscribers) chapters. This section highlights the main changes in events and subscribers between v1 and v2. +You can learn more in the [Events and Subscribers](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/index.html.md) chapters. This section highlights the main changes in events and subscribers between v1 and v2. #### Emitted Events -Medusa v2 doesn't emit the same events as v1. Refer to the [Events Reference](undefined/resources/references/events) for the full list of events emitted in v2. +Medusa v2 doesn't emit the same events as v1. Refer to the [Events Reference](https://docs.medusajs.com/resources/references/events/index.html.md) for the full list of events emitted in v2. #### Subscriber Type Imports @@ -23032,13 +23052,13 @@ export const config: SubscriberConfig = { Also, the `pluginOptions` property is no longer passed in the subscriber's parameter. Instead, you can access the options passed to a plugin within its modules' services, which you can resolve in a subscriber. -Learn more in the [Events and Subscribers](undefined/learn/fundamentals/events-and-subscribers) chapter. +Learn more in the [Events and Subscribers](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/index.html.md) chapter. #### Subscriber Implementation Change In Medusa v1, you implemented functionalities, such as sending confirmation email, directly within a subscriber. -In Medusa v2, you should implement these functionalities in a [workflow](undefined/learn/fundamentals/workflows) and call the workflow in the subscriber. By using workflows, you benefit from rollback mechanism, among other features. +In Medusa v2, you should implement these functionalities in a [workflow](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) and call the workflow in the subscriber. By using workflows, you benefit from rollback mechanism, among other features. For example: @@ -23097,7 +23117,7 @@ const helloWorldWorkflow = createWorkflow( If you need to emit events in a service, you can add the Event Module as a dependency of your module. Then, you can resolve the Event Module's service from the module container and emit the event. This approach is only recommended for events related to under-the-hood processes. -Learn more in the [Emit Events](undefined/learn/fundamentals/events-and-subscribers/emit-event) chapter. +Learn more in the [Emit Events](https://docs.medusajs.com/learn/fundamentals/events-and-subscribers/emit-event/index.html.md) chapter. *** @@ -23107,7 +23127,7 @@ In Medusa v1, you created loaders in the `src/loaders` directory to perform task In Medusa v2, loaders can only be created in a module. You can create loaders in the `src/modules//loaders` directory. That also means the loader can only access resources in the module's container. -Learn more in the [Loaders](undefined/learn/fundamentals/modules/loaders) chapter. +Learn more in the [Loaders](https://docs.medusajs.com/learn/fundamentals/modules/loaders/index.html.md) chapter. #### Loader Parameter Changes @@ -23138,7 +23158,7 @@ export default async function helloWorldLoader({ Scheduled jobs are similar in Medusa v1 and v2, but with minor changes. -You can learn more about scheduled jobs in the [Scheduled Jobs](undefined/learn/fundamentals/scheduled-jobs) chapters. This section highlights the main changes in scheduled jobs between v1 and v2. +You can learn more about scheduled jobs in the [Scheduled Jobs](https://docs.medusajs.com/learn/fundamentals/scheduled-jobs/index.html.md) chapters. This section highlights the main changes in scheduled jobs between v1 and v2. #### Scheduled Job Parameter Changes @@ -23173,7 +23193,7 @@ In Medusa v2, the `data` property is removed from the scheduled job's configurat In Medusa v1, you implemented functionalities directly in the job function. -In Medusa v2, you should implement these functionalities in a [workflow](undefined/learn/fundamentals/workflows) and call the workflow in the scheduled job. By using workflows, you benefit from rollback mechanism, among other features. +In Medusa v2, you should implement these functionalities in a [workflow](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md) and call the workflow in the scheduled job. By using workflows, you benefit from rollback mechanism, among other features. For example: @@ -23215,11 +23235,11 @@ This section covers changes to the admin customizations between Medusa v1 and v2 In Medusa v1, you set custom environment variables to be passed to the admin dashboard by prefixing them with `MEDUSA_ADMIN_`. -In Medusa v2, you can set custom environment variables to be passed to the admin dashboard by prefixing them with `VITE_`. Learn more in the [Admin Environment Variables](undefined/learn/fundamentals/admin/environment-variables) chapter. +In Medusa v2, you can set custom environment variables to be passed to the admin dashboard by prefixing them with `VITE_`. Learn more in the [Admin Environment Variables](https://docs.medusajs.com/learn/fundamentals/admin/environment-variables/index.html.md) chapter. #### Admin Widgets -Due to design changes in the Medusa Admin, some widget injection zones may have been changed or removed. Refer to the [Admin Widgets Injection Zones](undefined/resources/admin-widget-injection-zones) reference for the full list of injection zones in v2. +Due to design changes in the Medusa Admin, some widget injection zones may have been changed or removed. Refer to the [Admin Widgets Injection Zones](https://docs.medusajs.com/resources/admin-widget-injection-zones/index.html.md) reference for the full list of injection zones in v2. Also, In Medusa v1, you exported in the widget's file a `config` object with the widget's configurations, such as its injection zone. @@ -23243,7 +23263,7 @@ export default ProductWidget The function accepts an object with a `zone` property, indicating the zone to inject the widget. -Refer to the [Admin Widgets](undefined/learn/fundamentals/admin/widgets) chapter to learn more about creating widgets in Medusa v2. +Refer to the [Admin Widgets](https://docs.medusajs.com/learn/fundamentals/admin/widgets/index.html.md) chapter to learn more about creating widgets in Medusa v2. ### Admin UI Routes @@ -23276,7 +23296,7 @@ The `defineRouteConfig` function accepts an object with the following properties - `label`: The label of the route to show in the sidebar. - `icon`: The icon to use in the sidebar for the route. -Refer to the [Admin UI Routes](undefined/learn/fundamentals/admin/ui-routes) chapter to learn more about creating UI routes in Medusa v2. +Refer to the [Admin UI Routes](https://docs.medusajs.com/learn/fundamentals/admin/ui-routes/index.html.md) chapter to learn more about creating UI routes in Medusa v2. ### Admin Setting Routes @@ -23311,13 +23331,13 @@ export default CustomSettingPage In v1, you exported a `config` object that showed a setting page as a card in the settings page. In v2, you export the same configuration object as a UI route. -Learn more about creating setting pages in the [Admin UI Routes](undefined/learn/fundamentals/admin/ui-routes#create-settings-page) chapter. +Learn more about creating setting pages in the [Admin UI Routes](https://docs.medusajs.com/learn/fundamentals/admin/ui-routes#create-settings-page/index.html.md) chapter. ### notify Props in Widgets, UI Routes, and Settings In Medusa v1, admin widgets, UI routes, and setting pages received a `notify` prop to show notifications in the admin dashboard. -This prop is no longer passed in v2. Instead, use the [toast utility from Medusa UI](undefined/ui/components/toast) to show notifications. +This prop is no longer passed in v2. Instead, use the [toast utility from Medusa UI](https://docs.medusajs.com/ui/components/toast/index.html.md) to show notifications. For example: @@ -23343,7 +23363,7 @@ export const config = defineWidgetConfig({ export default ProductWidget ``` -Learn more about the `toast` utility in the [Medusa UI Toasts](undefined/ui/components/toast) documentation. +Learn more about the `toast` utility in the [Medusa UI Toasts](https://docs.medusajs.com/ui/components/toast/index.html.md) documentation. ### Sending Requests to Medusa Server @@ -23351,23 +23371,23 @@ In Medusa v1, you used Medusa React to send requests to the Medusa server. Medusa v2 no longer supports Medusa React. Instead, you can use the JS SDK with Tanstack Query to send requests from your admin customizations to the Medusa server. -Learn more in the [Admin Development Tips](undefined/learn/fundamentals/admin/tips#send-requests-to-api-routes) chapter. +Learn more in the [Admin Development Tips](https://docs.medusajs.com/learn/fundamentals/admin/tips#send-requests-to-api-routes/index.html.md) chapter. ### Admin Languages Medusa Admin v2 supports different languages out-of-the-box, and you can contribute with new translations. -Refer to the [User Guide](undefined/user-guide/tips/languages) for the list of languages supported in the Medusa Admin. +Refer to the [User Guide](https://docs.medusajs.com/user-guide/tips/languages/index.html.md) for the list of languages supported in the Medusa Admin. *** ## Commerce Features Changes -In Medusa v2, commerce features are implemented as [Commerce Modules](undefined/resources/commerce-modules). For example, the [Product Module](undefined/resources/commerce-modules/product) implements the product-related features, whereas the [Cart Module](undefined/resources/commerce-modules/cart) implements the cart-related features. +In Medusa v2, commerce features are implemented as [Commerce Modules](https://docs.medusajs.com/resources/commerce-modules/index.html.md). For example, the [Product Module](https://docs.medusajs.com/resources/commerce-modules/product/index.html.md) implements the product-related features, whereas the [Cart Module](https://docs.medusajs.com/resources/commerce-modules/cart/index.html.md) implements the cart-related features. So, it's difficult to cover all changes in commerce features between v1 and v2. Instead, this section will highlight changes to customizations that were documented in the Medusa v1 documentation. -To learn about all commerce features in Medusa v2, refer to the [Commerce Modules](undefined/resources/commerce-modules) documentation. +To learn about all commerce features in Medusa v2, refer to the [Commerce Modules](https://docs.medusajs.com/resources/commerce-modules/index.html.md) documentation. ### Providers are now Module Providers @@ -23377,33 +23397,33 @@ In Medusa v2, you create these providers as module providers that belong to the Refer to the following guides to learn how to create these module providers: -- [Payment Module Provider](undefined/resources/commerce-modules/payment/payment-provider) -- [Fulfillment Module Provider](undefined/resources/commerce-modules/fulfillment/fulfillment-provider) -- [Tax Module Provider](undefined/resources/commerce-modules/tax/tax-provider) +- [Payment Module Provider](https://docs.medusajs.com/resources/commerce-modules/payment/payment-provider/index.html.md) +- [Fulfillment Module Provider](https://docs.medusajs.com/resources/commerce-modules/fulfillment/fulfillment-provider/index.html.md) +- [Tax Module Provider](https://docs.medusajs.com/resources/commerce-modules/tax/tax-provider/index.html.md) ### Overridden Cart Completion In Medusa v1, you were able to override the cart completion strategy to customize the cart completion process. -In Medusa v2, the cart completion process is now implemented in the [completeCartWorkflow](undefined/resources/references/medusa-workflows/completeCartWorkflow). There are two ways you can customize the completion process: +In Medusa v2, the cart completion process is now implemented in the [completeCartWorkflow](https://docs.medusajs.com/resources/references/medusa-workflows/completeCartWorkflow/index.html.md). There are two ways you can customize the completion process: -- [Consuming hooks](undefined/learn/fundamentals/workflows/workflow-hooks) like the [validate](undefined/resources/references/medusa-workflows/completeCartWorkflow#validate) hook. This is useful if you only want to make changes in key points of the cart completion process. - - You can view available hooks in the [completeCartWorkflow reference](undefined/resources/references/medusa-workflows/completeCartWorkflow#hooks) -- For more complex use cases, you can create a new workflow with the desired functionality. Then, you can [replicate the complete cart API route](undefined/learn/fundamentals/api-routes/override) and use it in your storefront. +- [Consuming hooks](https://docs.medusajs.com/learn/fundamentals/workflows/workflow-hooks/index.html.md) like the [validate](https://docs.medusajs.com/resources/references/medusa-workflows/completeCartWorkflow#validate/index.html.md) hook. This is useful if you only want to make changes in key points of the cart completion process. + - You can view available hooks in the [completeCartWorkflow reference](https://docs.medusajs.com/resources/references/medusa-workflows/completeCartWorkflow#hooks/index.html.md) +- For more complex use cases, you can create a new workflow with the desired functionality. Then, you can [replicate the complete cart API route](https://docs.medusajs.com/learn/fundamentals/api-routes/override/index.html.md) and use it in your storefront. ### Overridden Tax Calculation In Medusa v1, you were able to override the tax calculation strategy to customize the tax calculation process. -In Medusa v2, the tax calculation process is now implemented in a [Tax Module Provider](undefined/resources/commerce-modules/tax/tax-provider). So, you can [create a custom tax provider](undefined/resources/references/tax/provider) with the calculation logic you want, then [use it in a tax region](undefined/user-guide/settings/tax-regions#edit-tax-region). +In Medusa v2, the tax calculation process is now implemented in a [Tax Module Provider](https://docs.medusajs.com/resources/commerce-modules/tax/tax-provider/index.html.md). So, you can [create a custom tax provider](https://docs.medusajs.com/resources/references/tax/provider/index.html.md) with the calculation logic you want, then [use it in a tax region](https://docs.medusajs.com/user-guide/settings/tax-regions#edit-tax-region/index.html.md). ### Overridden Price Selection In Medusa v1, you were able to override the price selection strategy to customize the price selection process. -In Medusa v2, the price selection process is now implemented in the [Pricing Module's calculate method](undefined/resources/commerce-modules/pricing/price-calculation). The Pricing Module allows you to set [flexible rules and tiers](undefined/resources/commerce-modules/pricing/price-rules) to support your use case. +In Medusa v2, the price selection process is now implemented in the [Pricing Module's calculate method](https://docs.medusajs.com/resources/commerce-modules/pricing/price-calculation/index.html.md). The Pricing Module allows you to set [flexible rules and tiers](https://docs.medusajs.com/resources/commerce-modules/pricing/price-rules/index.html.md) to support your use case. -If your use case is complex and these rules are not enough, you can create a new [module](undefined/learn/fundamentals/modules) with the necessary logic, then use that module in your custom workflows. +If your use case is complex and these rules are not enough, you can create a new [module](https://docs.medusajs.com/learn/fundamentals/modules/index.html.md) with the necessary logic, then use that module in your custom workflows. ## Prices are Stored in Base Units @@ -23411,7 +23431,7 @@ In Medusa v1, prices were stored in the smallest currency unit. For example, a p In Medusa v2, prices are stored in the base unit. For example, a price of $10.00 is stored as `10` (dollars). -Learn more in the [Pricing Concepts](undefined/resources/commerce-modules/pricing/concepts) guide. +Learn more in the [Pricing Concepts](https://docs.medusajs.com/resources/commerce-modules/pricing/concepts/index.html.md) guide. ### Gift Card Features @@ -23427,7 +23447,7 @@ The deployment process in Medusa v2 is similar to v1, but with some changes. For Medusa also provides [Cloud](https://medusajs.com/cloud/), a managed services offering that makes deploying and operating Medusa applications possible without having to worry about configuring, scaling, and maintaining infrastructure. -Refer to the [Deployment](undefined/resources/deployment) documentation to learn about the deployment process for Medusa applications and Next.js Starter Storefront. +Refer to the [Deployment](https://docs.medusajs.com/resources/deployment/index.html.md) documentation to learn about the deployment process for Medusa applications and Next.js Starter Storefront. # Introduction @@ -23436,8 +23456,8 @@ Medusa is a digital commerce platform with a built-in Framework for customizatio Medusa ships with three main tools: -1. A suite of [Commerce Modules](undefined/resources/commerce-modules) with core commerce functionalities, such as tracking inventory, calculating cart totals, accepting payments, managing orders, and much more. -2. A [Framework](undefined/learn/fundamentals/framework) for building custom functionalities specific to your business, product, or industry. This includes tools for introducing custom API endpoints, business logic, and data models; building workflows and automations; and integrating with third-party services. +1. A suite of [Commerce Modules](https://docs.medusajs.com/resources/commerce-modules/index.html.md) with core commerce functionalities, such as tracking inventory, calculating cart totals, accepting payments, managing orders, and much more. +2. A [Framework](https://docs.medusajs.com/learn/fundamentals/framework/index.html.md) for building custom functionalities specific to your business, product, or industry. This includes tools for introducing custom API endpoints, business logic, and data models; building workflows and automations; and integrating with third-party services. 3. A customizable admin dashboard for merchants to configure and operate their store. When you install Medusa, you get a fully fledged commerce platform with all the features you need to get off the ground. However, unlike other platforms, Medusa is built with customization in mind. You don't need to build hacky workarounds that are difficult to maintain and scale. Your efforts go into building features that bring your business's vision to life. @@ -23482,7 +23502,7 @@ This documentation is split into the following sections: |User Guide|Guides that introduce merchants and store managers to the Medusa Admin dashboard and helps them understand how to use the dashboard to manage their store.| |Cloud|Learn about Cloud, our managed services offering for Medusa applications. Find guides on how to deploy your Medusa application, manage organizations, and more.| -To get started, check out the [Installation chapter](undefined/learn/installation). +To get started, check out the [Installation chapter](https://docs.medusajs.com/learn/installation/index.html.md). *** @@ -23491,7 +23511,7 @@ To get started, check out the [Installation chapter](undefined/learn/installatio - Need Help? Refer to our [GitHub repository](https://github.com/medusajs/medusa) for [issues](https://github.com/medusajs/medusa/issues) and [discussions](https://github.com/medusajs/medusa/discussions). - [Join the community on Discord](https://discord.gg/medusajs). - Have questions or need more support? Contact our [sales team](https://medusajs.com/contact/). -- Facing issues in your development? Refer to our [troubleshooting guides](undefined/resources/troubleshooting). +- Facing issues in your development? Refer to our [troubleshooting guides](https://docs.medusajs.com/resources/troubleshooting/index.html.md). # Worker Mode of Medusa Instance @@ -23705,11 +23725,13 @@ Medusa's documentation projects are all part of the documentation `yarn` workspa The workspace has the following two directories: -- `apps`: this directory holds the different documentation websites and projects. - - `book`: includes the codebase for the [main Medusa documentation](https://docs.medusajs.com//index.html.md). It's built with [Next.js 15](https://nextjs.org/). - - `resources`: includes the codebase for the resources documentation, which powers different sections of the docs such as the [Integrations](https://docs.medusajs.com/resources/integrations/index.html.md) or [How-to & Tutorials](https://docs.medusajs.com/resources/how-to-tutorials/index.html.md) sections. It's built with [Next.js 15](https://nextjs.org/). - - `api-reference`: includes the codebase for the API reference website. It's built with [Next.js 15](https://nextjs.org/). - - `ui`: includes the codebase for the Medusa UI documentation website. It's built with [Next.js 15](https://nextjs.org/). +- `apps`: this directory holds the different documentation websites and projects. All projects are built with [Next.js 15](https://nextjs.org/). + - `book`: includes the codebase and content for the [main Medusa documentation](https://docs.medusajs.com/learn/index.html.md). + - `resources`: includes the codebase and content for the resources documentation, which powers different sections of the docs such as the [Integrations](https://docs.medusajs.com/resources/integrations/index.html.md) or [How-to & Tutorials](https://docs.medusajs.com/resources/how-to-tutorials/index.html.md) sections. + - `api-reference`: includes the codebase and content for the [API reference](https://docs.medusajs.com/api/store). + - `ui`: includes the codebase and content for the [Medusa UI documentation](https://docs.medusajs.com/ui/index.html.md). + - `user-guide`: includes the codebase and content for the [user guide documentation](https://docs.medusajs.com/user-guide/index.html.md). + - `cloud`: includes the codebase and content for the [Medusa Cloud documentation](https://docs.medusajs.com/cloud/index.html.md). - `packages`: this directory holds the shared packages and components necessary for the development of the projects in the `apps` directory. - `docs-ui` includes the shared React components between the different apps. - `remark-rehype-plugins` includes Remark and Rehype plugins used by the documentation projects. @@ -24124,12 +24146,12 @@ In this chapter, you'll learn about storefronts and how to build one. The Medusa application includes a Node.js server and an admin dashboard. Storefronts are separate applications that you install, build, and host independently from Medusa. This gives you the flexibility to choose your preferred frontend tech stack and implement unique designs and user experiences. -In your storefront, you can retrieve data and perform commerce operations by sending requests to the Medusa application's [Store API routes](undefined/api/store) and your custom API routes. +In your storefront, you can retrieve data and perform commerce operations by sending requests to the Medusa application's [Store API routes](https://docs.medusajs.com/api/store) and your custom API routes. You can build your storefront from scratch with your preferred tech stack, or start with our Next.js Starter storefront. The Next.js Starter storefront provides rich commerce features and a modern design. You can use it as-is or customize it to match your business needs, design requirements, and customer experience goals. -- [Install Next.js Starter Storefront](undefined/resources/nextjs-starter) -- [Build Custom Storefront](undefined/resources/storefront-development) +- [Install Next.js Starter Storefront](https://docs.medusajs.com/resources/nextjs-starter/index.html.md) +- [Build Custom Storefront](https://docs.medusajs.com/resources/storefront-development/index.html.md) *** @@ -24141,7 +24163,7 @@ A publishable API key sets the scope of your request to one or more sales channe When you retrieve products, only products from those sales channels are returned. This also ensures you get correct inventory data and associate created orders with the right sales channel. -Learn more about using the publishable API key in the [Storefront Development guide](undefined/resources/storefront-development/publishable-api-keys). +Learn more about using the publishable API key in the [Storefront Development guide](https://docs.medusajs.com/resources/storefront-development/publishable-api-keys/index.html.md). # Updating Medusa @@ -24154,7 +24176,7 @@ Medusa's current version is v{config.version.number}. {releaseNoteText} When Medusa puts out a new release, all packages are updated to the same version. This ensures that all packages are compatible with each other, and makes it easier for you to switch between versions. -This doesn't apply to the design-system packages, including `@medusajs/ui`, `@medusajs/ui-presets`, and `@medusajs/ui-icons`. These packages are versioned independently. However, you don't need to install and manage them separately in your Medusa application, as they are included in the `@medusajs/admin-sdk`. If you're using them in a standalone project, such as a storefront or custom admin dashboard, refer to [this section in the Medusa UI documentation](undefined/ui/installation/standalone-project#updating-ui-packages) for update instructions. +This doesn't apply to the design-system packages, including `@medusajs/ui`, `@medusajs/ui-presets`, and `@medusajs/ui-icons`. These packages are versioned independently. However, you don't need to install and manage them separately in your Medusa application, as they are included in the `@medusajs/admin-sdk`. If you're using them in a standalone project, such as a storefront or custom admin dashboard, refer to [this section in the Medusa UI documentation](https://docs.medusajs.com/ui/installation/standalone-project#updating-ui-packages/index.html.md) for update instructions. Medusa updates the version number `major.minor.patch` according to the following rules: @@ -24172,7 +24194,7 @@ To check the currently installed version of Medusa in your project, run the foll npx medusa -v ``` -This will show you the installed version of Medusa and the [Medusa CLI tool](undefined/resources/medusa-cli), which should be the same. +This will show you the installed version of Medusa and the [Medusa CLI tool](https://docs.medusajs.com/resources/medusa-cli/index.html.md), which should be the same. *** @@ -24263,21 +24285,21 @@ There are two types of API keys: - `secret`: A secret key used for authentication and verification purposes, such as an admin user’s authentication token or a password reset token. - This API key is useful for operations that require authentication, such as creating orders or managing products as an admin user. -The API key’s type is stored in the `type` property of the [ApiKey data model](undefined/references/api-key/models/ApiKey). +The API key’s type is stored in the `type` property of the [ApiKey data model](https://docs.medusajs.com/references/api-key/models/ApiKey/index.html.md). ### Default Scopes and Permissions -In your Medusa application, a `publishable` API key is only useful to send requests to the [Store API routes](undefined/api/store). Learn more about it in the [Publishable API Keys](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/sales-channel/publishable-api-keys) guide. +In your Medusa application, a `publishable` API key is only useful to send requests to the [Store API routes](https://docs.medusajs.com/api/store). Learn more about it in the [Publishable API Keys](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/sales-channel/publishable-api-keys/index.html.md) guide. -In addition, a `secret` API key allows you to access the [Admin API routes](undefined/api/admin) and perform actions as the admin user that the key was created for. The `created_by` property of the [ApiKey data model](undefined/references/api-key/models/ApiKey) indicates the ID of the associated admin user. +In addition, a `secret` API key allows you to access the [Admin API routes](https://docs.medusajs.com/api/admin) and perform actions as the admin user that the key was created for. The `created_by` property of the [ApiKey data model](https://docs.medusajs.com/references/api-key/models/ApiKey/index.html.md) indicates the ID of the associated admin user. *** ## API Key Creation -When using the [Medusa Admin](undefined/user-guide/settings/developer) or [API routes](undefined/api/admin#api-keys), only admin users can create API keys. +When using the [Medusa Admin](https://docs.medusajs.com/user-guide/settings/developer/index.html.md) or [API routes](https://docs.medusajs.com/api/admin#api-keys), only admin users can create API keys. -You can also create API keys in your customizations using the [createApiKeysWorkflow](undefined/references/medusa-workflows/createApiKeysWorkflow). +You can also create API keys in your customizations using the [createApiKeysWorkflow](https://docs.medusajs.com/references/medusa-workflows/createApiKeysWorkflow/index.html.md). *** @@ -24293,7 +24315,7 @@ For display purposes, the API key data model also has a `redacted` property that ## API Key Expiration -An API key expires when it’s revoked using the [revokeApiKeysWorkflow](undefined/references/medusa-workflows/revokeApiKeysWorkflow). This method will set the following properties in the API key: +An API key expires when it’s revoked using the [revokeApiKeysWorkflow](https://docs.medusajs.com/references/medusa-workflows/revokeApiKeysWorkflow/index.html.md). This method will set the following properties in the API key: - `revoked_at`: The date and time when the API key was revoked. - `revoked_by`: The ID of the user who revoked the API key. @@ -24304,7 +24326,7 @@ The associated token is no longer usable or verifiable. ## Token Verification -To verify a token received as an input or in a request, use the [authenticate method of the module’s main service](undefined/references/api-key/authenticate) which validates the token against all non-expired tokens. +To verify a token received as an input or in a request, use the [authenticate method of the module’s main service](https://docs.medusajs.com/references/api-key/authenticate/index.html.md) which validates the token against all non-expired tokens. # Links between API Key Module and Other Modules @@ -24329,11 +24351,11 @@ You can create a publishable API key and associate it with a sales channel. Medu This is useful to avoid passing the sales channel's ID as a parameter of every request, and instead pass the publishable API key in the header of any request to the Store API route. -Learn more about this in the [Sales Channel Module's documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/sales-channel/publishable-api-keys). +Learn more about this in the [Sales Channel Module's documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/sales-channel/publishable-api-keys/index.html.md). ### Retrieve with Query -To retrieve the sales channels of an API key with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `sales_channels.*` in `fields`: +To retrieve the sales channels of an API key with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `sales_channels.*` in `fields`: ### query.graph @@ -24367,7 +24389,7 @@ const { data: apiKeys } = useQueryGraphStep({ ### Manage with Link -To manage the sales channels of an API key, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the sales channels of an API key, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -24409,24 +24431,24 @@ createRemoteLinkStep({ In this section of the documentation, you will find resources to learn more about the API Key Module and how to use it in your application. -Refer to the [Medusa Admin User Guide](undefined/user-guide/settings/developer) to learn how to manage publishable and secret API keys using the dashboard. +Refer to the [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/settings/developer/index.html.md) to learn how to manage publishable and secret API keys using the dashboard. -Medusa has API-key related features available out-of-the-box through the API Key Module. A [module](undefined/docs/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this API Key Module. +Medusa has API-key related features available out-of-the-box through the API Key Module. A [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this API Key Module. -Learn more about why modules are isolated in [this documentation](undefined/docs/learn/fundamentals/modules/isolation). +Learn more about why modules are isolated in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md). ## API Key Features -- [API Key Types and Management](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/api-key/concepts): Manage API keys in your store. You can create both publishable and secret API keys for different use cases. -- [Token Verification](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/api-key/concepts#token-verification): Verify tokens of secret API keys to authenticate users or actions. -- [Revoke Keys](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/api-key/concepts#api-key-expiration): Revoke keys to disable their use permanently. -- Roll API Keys: Roll API keys by [revoking](undefined/references/api-key/revoke) a key then [re-creating it](undefined/references/api-key/createApiKeys). +- [API Key Types and Management](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/api-key/concepts/index.html.md): Manage API keys in your store. You can create both publishable and secret API keys for different use cases. +- [Token Verification](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/api-key/concepts#token-verification/index.html.md): Verify tokens of secret API keys to authenticate users or actions. +- [Revoke Keys](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/api-key/concepts#api-key-expiration/index.html.md): Revoke keys to disable their use permanently. +- Roll API Keys: Roll API keys by [revoking](https://docs.medusajs.com/references/api-key/revoke/index.html.md) a key then [re-creating it](https://docs.medusajs.com/references/api-key/createApiKeys/index.html.md). *** ## How to Use the API Key Module -In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](undefined/docs/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package. @@ -24540,7 +24562,7 @@ export const config = { } ``` -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). *** @@ -24549,13 +24571,13 @@ Learn more about workflows in [this documentation](undefined/docs/learn/fundamen In this guide, you'll learn how to use the methods of the Auth Module's service to implement authentication flows and reset a user's password. -This guide is only recommended for complex cases, where you may need to heavily customize the authentication flows and need to use the Auth Module's service methods directly. For most use cases, you should use the [auth routes](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route) instead. +This guide is only recommended for complex cases, where you may need to heavily customize the authentication flows and need to use the Auth Module's service methods directly. For most use cases, you should use the [auth routes](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route/index.html.md) instead. ## Authentication Methods ### Register -The [register method of the Auth Module's service](undefined/references/auth/register) creates an auth identity that can be authenticated later. +The [register method of the Auth Module's service](https://docs.medusajs.com/references/auth/register/index.html.md) creates an auth identity that can be authenticated later. For example: @@ -24585,7 +24607,7 @@ Based on the returned data, you can determine if the registration was successful ### Authenticate -To authenticate or log in a user, you use the [authenticate method of the Auth Module's service](undefined/references/auth/authenticate). For example: +To authenticate or log in a user, you use the [authenticate method of the Auth Module's service](https://docs.medusajs.com/references/auth/authenticate/index.html.md). For example: ```ts const data = await authModuleService.authenticate( @@ -24655,7 +24677,7 @@ If the `register` method returns an `error` property, the registration failed, a Otherwise, if the `success` property is `true`, the registration was successful, and the user's authentication details are available within the `authIdentity` object. -Check out the [AuthIdentity](undefined/references/auth/models/AuthIdentity) reference for the received properties in `authIdentity`. +Check out the [AuthIdentity](https://docs.medusajs.com/references/auth/models/AuthIdentity/index.html.md) reference for the received properties in `authIdentity`. #### Registering Auth Identities with Same Identifier @@ -24761,7 +24783,7 @@ const { Providers handling this authentication flow must implement the `validateCallback` method. It implements the logic to validate the authentication with the third-party service. -So, once the user performs the required action with the third-party service (for example, log in with Google), the frontend must redirect to an API route that uses the [validateCallback method of the Auth Module's service](undefined/references/auth/validateCallback). +So, once the user performs the required action with the third-party service (for example, log in with Google), the frontend must redirect to an API route that uses the [validateCallback method of the Auth Module's service](https://docs.medusajs.com/references/auth/validateCallback/index.html.md). The method calls the specified provider’s `validateCallback` method passing it the authentication details it received in the second parameter: @@ -24794,7 +24816,7 @@ If the returned `success` property is `true`, the authentication with the third- ## Reset Password -To update a user's password or other authentication details, use the [updateProvider method of the Auth Module's service](undefined/references/auth/updateProvider). It calls the `update` method of the specified authentication provider. +To update a user's password or other authentication details, use the [updateProvider method of the Auth Module's service](https://docs.medusajs.com/references/auth/updateProvider/index.html.md). It calls the `update` method of the specified authentication provider. For example: @@ -24826,7 +24848,7 @@ In this guide, you’ll learn about concepts related to identity and actors in t ## What is an Auth Identity? -The [AuthIdentity data model](undefined/references/auth/models/AuthIdentity) represents a user registered by an [authentication provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/auth-providers). When a user is registered using an authentication provider, the provider creates a record of `AuthIdentity`. +The [AuthIdentity data model](https://docs.medusajs.com/references/auth/models/AuthIdentity/index.html.md) represents a user registered by an [authentication provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/auth-providers/index.html.md). When a user is registered using an authentication provider, the provider creates a record of `AuthIdentity`. Then, when the user logs in with the same authentication provider, the associated auth identity is used to validate their credentials. @@ -24834,7 +24856,7 @@ Then, when the user logs in with the same authentication provider, the associate ## Actor Types -An actor type is a type of user that can be authenticated. The Auth Module doesn't store or manage any user-like models, such as for customers or users. Instead, the user types are created and managed by other modules. For example, a customer is managed by the [Customer Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/customer). +An actor type is a type of user that can be authenticated. The Auth Module doesn't store or manage any user-like models, such as for customers or users. Instead, the user types are created and managed by other modules. For example, a customer is managed by the [Customer Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/customer/index.html.md). When an auth identity is created for an actor type, the ID of the user is stored in the `app_metadata` property of the auth identity. @@ -24854,7 +24876,7 @@ The ID of the user is stored in the key `{actor_type}_id` of the `app_metadata` ## Protect Routes by Actor Type -When you protect routes with the [authenticate middleware](undefined/docs/learn/fundamentals/api-routes/protected-routes), you specify in its first parameter the actor type that must be authenticated to access the API routes. +When you protect routes with the [authenticate middleware](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/protected-routes/index.html.md), you specify in its first parameter the actor type that must be authenticated to access the API routes. For example: @@ -24886,7 +24908,7 @@ You can define custom actor types that allow a custom user, managed by your cust For example, if you have a custom module with a `Manager` data model, you can authenticate managers with the `manager` actor type. -Learn how to create a custom actor type in the [Create Manager Actor Type guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/create-actor-type). +Learn how to create a custom actor type in the [Create Manager Actor Type guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/create-actor-type/index.html.md). # Emailpass Auth Module Provider @@ -24946,7 +24968,7 @@ const hashConfig = \{ ## Related Guides -- [How to register a customer using email and password](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development/customers/register) +- [How to register a customer using email and password](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/customers/register/index.html.md) # GitHub Auth Module Provider @@ -25018,13 +25040,13 @@ GITHUB_CALLBACK_URL= In many cases, you may have different callback URLs for actor types. For example, you may redirect admin users to a different URL than customers after authentication. -The [Authenticate or Login API Route](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route#login-route) accepts a `callback_url` body parameter to override the provider's `callbackUrl` option. Learn more in the [Auth Flows with Routes guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route#login-route). +The [Authenticate or Login API Route](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route#login-route/index.html.md) accepts a `callback_url` body parameter to override the provider's `callbackUrl` option. Learn more in the [Auth Flows with Routes guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route#login-route/index.html.md). *** ## Examples -- [How to implement third-party / social login in the storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development/customers/third-party-login) +- [How to implement third-party / social login in the storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/customers/third-party-login/index.html.md) # Google Auth Module Provider @@ -25101,13 +25123,13 @@ GOOGLE_CALLBACK_URL= In many cases, you may have different callback URLs for actor types. For example, you may redirect admin users to a different URL than customers after authentication. -The [Authenticate or Login API Route](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route#login-route) can accept a `callback_url` body parameter to override the provider's `callbackUrl` option. Learn more in [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route#login-route). +The [Authenticate or Login API Route](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route#login-route/index.html.md) can accept a `callback_url` body parameter to override the provider's `callbackUrl` option. Learn more in [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route#login-route/index.html.md). *** ## Examples -- [How to implement Google social login in the storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development/customers/third-party-login) +- [How to implement Google social login in the storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/customers/third-party-login/index.html.md) # Auth Module Provider @@ -25122,9 +25144,9 @@ For example, the EmailPass Auth Module Provider authenticates a user using their ### Auth Providers List -- [Emailpass](undefined/commerce-modules/auth/auth-providers/emailpass) -- [Google](undefined/commerce-modules/auth/auth-providers/google) -- [GitHub](undefined/commerce-modules/auth/auth-providers/github) +- [Emailpass](https://docs.medusajs.com/commerce-modules/auth/auth-providers/emailpass/index.html.md) +- [Google](https://docs.medusajs.com/commerce-modules/auth/auth-providers/google/index.html.md) +- [GitHub](https://docs.medusajs.com/commerce-modules/auth/auth-providers/github/index.html.md) *** @@ -25134,7 +25156,7 @@ An Auth Module Provider is a module whose service extends the `AbstractAuthModul The module can have multiple auth provider services, where each is registered as a separate auth provider. -Refer to the [Create Auth Module Provider](undefined/references/auth/provider) guide to learn how to create an Auth Module Provider. +Refer to the [Create Auth Module Provider](https://docs.medusajs.com/references/auth/provider/index.html.md) guide to learn how to create an Auth Module Provider. *** @@ -25142,7 +25164,7 @@ Refer to the [Create Auth Module Provider](undefined/references/auth/provider) g By default, users of all actor types can authenticate with all installed Auth Module Providers. -To restrict the auth providers used for actor types, use the [authMethodsPerActor option](undefined/docs/learn/configurations/medusa-config#httpauthMethodsPerActor) in Medusa's configurations: +To restrict the auth providers used for actor types, use the [authMethodsPerActor option](https://docs.medusajs.com/docs/learn/configurations/medusa-config#httpauthMethodsPerActor/index.html.md) in Medusa's configurations: ```ts title="medusa-config.ts" module.exports = defineConfig({ @@ -25174,7 +25196,7 @@ These routes are added by Medusa's HTTP layer, not the Auth Module. This authentication flow doesn't require validation with third-party services. -[How to register customer in storefront using basic authentication flow](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development/customers/register). +[How to register customer in storefront using basic authentication flow](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/customers/register/index.html.md). The steps are: @@ -25182,8 +25204,8 @@ The steps are: 1. Register the user with the [Register Route](#register-route). 2. Use the authentication token to create the user with their respective API route. - - For example, for customers you would use the [Create Customer API route](undefined/api/store#customers_postcustomers). - - For admin users, you accept an invite using the [Accept Invite API route](undefined/api/admin#invites_postinvitesaccept) + - For example, for customers you would use the [Create Customer API route](https://docs.medusajs.com/api/store#customers_postcustomers). + - For admin users, you accept an invite using the [Accept Invite API route](https://docs.medusajs.com/api/admin#invites_postinvitesaccept) 3. Authenticate the user with the [Auth Route](#login-route). After registration, you only use the [Auth Route](#login-route) for subsequent authentication. @@ -25194,7 +25216,7 @@ To handle errors related to existing identities, refer to [this section](#handli This authentication flow authenticates the user with a third-party service, such as Google. -[How to authenticate customer with a third-party provider in the storefront.](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development/customers/third-party-login). +[How to authenticate customer with a third-party provider in the storefront.](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/customers/third-party-login/index.html.md). It requires the following steps: @@ -25209,8 +25231,8 @@ It requires the following steps: - If the decoded data has an `actor_id` property, then the user is already registered. So, use this token for subsequent authenticated requests. - If not, follow the rest of the steps. 7. The frontend uses the authentication token to create the user with their respective API route. - - For example, for customers you would use the [Create Customer API route](undefined/api/store#customers_postcustomers). - - For admin users, you accept an invite using the [Accept Invite API route](undefined/api/admin#invites_postinvitesaccept) + - For example, for customers you would use the [Create Customer API route](https://docs.medusajs.com/api/store#customers_postcustomers). + - For admin users, you accept an invite using the [Accept Invite API route](https://docs.medusajs.com/api/admin#invites_postinvitesaccept) 8. The frontend sends a request to the [Refresh Token Route](#refresh-token-route) to retrieve a new token with the user information populated. *** @@ -25233,7 +25255,7 @@ This API route is useful for providers like `emailpass` that uses custom logic t For example, if you're registering a customer, you: 1. Send a request to `/auth/customer/emailpass/register` to retrieve the registration JWT token. -2. Send a request to the [Create Customer API route](undefined/api/store#customers_postcustomers) to create the customer, passing the [JWT token in the header](undefined/api/store#authentication). +2. Send a request to the [Create Customer API route](https://docs.medusajs.com/api/store#customers_postcustomers) to create the customer, passing the [JWT token in the header](https://docs.medusajs.com/api/store#authentication). ### Path Parameters @@ -25293,7 +25315,7 @@ You can show that error message to the customer. ## Login Route -The Medusa application defines an API route at `/auth/{actor_type}/{provider}` that authenticates a user of an actor type. It returns a JWT token that can be passed in [the header of subsequent requests](undefined/api/store#authentication) to send authenticated requests. +The Medusa application defines an API route at `/auth/{actor_type}/{provider}` that authenticates a user of an actor type. It returns a JWT token that can be passed in [the header of subsequent requests](https://docs.medusajs.com/api/store#authentication) to send authenticated requests. ```bash curl -X POST http://localhost:9000/auth/{actor_type}/{providers} @@ -25321,7 +25343,7 @@ For example, the EmailPass provider requires an `email` and `password` fields in #### Overriding Callback URL -For the [GitHub](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/auth-providers/github) and [Google](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/auth-providers/google) providers, you can pass a `callback_url` body parameter that overrides the `callbackUrl` set in the provider's configurations. +For the [GitHub](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/auth-providers/github/index.html.md) and [Google](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/auth-providers/google/index.html.md) providers, you can pass a `callback_url` body parameter that overrides the `callbackUrl` set in the provider's configurations. This is useful if you want to redirect the user to a different URL after authentication based on their actor type. For example, you can set different `callback_url` for admin users and customers. @@ -25347,7 +25369,7 @@ If the authentication requires more action with a third-party service, you'll re Redirect to that URL in the frontend to continue the authentication process with the third-party service. -[How to login Customers using the authentication route](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development/customers/login). +[How to login Customers using the authentication route](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/customers/login/index.html.md). *** @@ -25385,7 +25407,7 @@ If the authentication is successful, you'll receive a `token` field in the respo In your frontend, decode the token using tools like [react-jwt](https://www.npmjs.com/package/react-jwt): - If the decoded data has an `actor_id` property, the user is already registered. So, use this token for subsequent authenticated requests. -- If not, use the token in the header of a request that creates the user, such as the [Create Customer API route](undefined/api/store#customers_postcustomers). +- If not, use the token in the header of a request that creates the user, such as the [Create Customer API route](https://docs.medusajs.com/api/store#customers_postcustomers). *** @@ -25420,11 +25442,11 @@ To reset a user's password: 1. Generate a token using the [Generate Reset Password Token API route](#generate-reset-password-token-route). - The API route emits the `auth.password_reset` event, passing the token in the payload. - - You can create a subscriber, as seen in [this guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/reset-password), that listens to the event and send a notification to the user. + - You can create a subscriber, as seen in [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/reset-password/index.html.md), that listens to the event and send a notification to the user. 2. Pass the token to the [Reset Password API route](#reset-password-route) to reset the password. - The URL in the user's notification should direct them to a frontend URL, which sends a request to this route. -[Storefront Development: How to Reset a Customer's Password.](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development/customers/reset-password) +[Storefront Development: How to Reset a Customer's Password.](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/customers/reset-password/index.html.md) ### Generate Reset Password Token Route @@ -25514,7 +25536,7 @@ In this document, learn how to create an actor type and authenticate its associa Before creating an actor type, you must have a module with a data model representing the actor type. -Learn how to create a module in [this guide](undefined/docs/learn/fundamentals/modules). +Learn how to create a module in [this guide](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). The rest of this guide uses this `Manager` data model as an example: @@ -25656,7 +25678,7 @@ export async function POST( Since the manager must be associated with an `AuthIdentity` record, the request is expected to be authenticated, even if the manager isn’t created yet. This can be achieved by: -1. Obtaining a token usng the [/auth route](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route). +1. Obtaining a token usng the [/auth route](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route/index.html.md). 2. Passing the token in the bearer header of the request to this route. In the API route, you create the manager using the workflow from the previous section and return it in the response. @@ -25960,7 +25982,7 @@ The Medusa application's authentication API routes are defined under the `/auth` By default, the Medusa application you created will have an `AUTH_CORS` environment variable, which is used as the value of `authCors`. -Refer to [Medusa's configuration guide](undefined/docs/learn/configurations/medusa-config#httpauthCors) to learn more about the `authCors` configuration. +Refer to [Medusa's configuration guide](https://docs.medusajs.com/docs/learn/configurations/medusa-config#httpauthCors/index.html.md) to learn more about the `authCors` configuration. *** @@ -25968,29 +25990,29 @@ Refer to [Medusa's configuration guide](undefined/docs/learn/configurations/medu The Medusa application's configuration accept an `authMethodsPerActor` configuration which restricts the allowed auth providers used with an actor type. -Learn more about the `authMethodsPerActor` configuration in [this guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/auth-providers#configure-allowed-auth-providers-of-actor-types). +Learn more about the `authMethodsPerActor` configuration in [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/auth-providers#configure-allowed-auth-providers-of-actor-types/index.html.md). # Auth Module In this section of the documentation, you will find resources to learn more about the Auth Module and how to use it in your application. -Medusa has auth related features available out-of-the-box through the Auth Module. A [module](undefined/docs/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Auth Module. +Medusa has auth related features available out-of-the-box through the Auth Module. A [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Auth Module. -Learn more about why modules are isolated in [this documentation](undefined/docs/learn/fundamentals/modules/isolation). +Learn more about why modules are isolated in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md). ## Auth Features -- [Basic User Authentication](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route#1-basic-authentication-flow): Authenticate users using their email and password credentials. -- [Third-Party and Social Authentication](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route#2-third-party-service-authenticate-flow): Authenticate users using third-party services and social platforms, such as [Google](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/auth-providers/google) and [GitHub](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/auth-providers/github). -- [Authenticate Custom Actor Types](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/create-actor-type): Create custom user or actor types, such as managers, authenticate them in your application, and guard routes based on the custom user types. -- [Custom Authentication Providers](undefined/references/auth/provider): Integrate third-party services with custom authentication providors. +- [Basic User Authentication](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route#1-basic-authentication-flow/index.html.md): Authenticate users using their email and password credentials. +- [Third-Party and Social Authentication](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route#2-third-party-service-authenticate-flow/index.html.md): Authenticate users using third-party services and social platforms, such as [Google](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/auth-providers/google/index.html.md) and [GitHub](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/auth-providers/github/index.html.md). +- [Authenticate Custom Actor Types](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/create-actor-type/index.html.md): Create custom user or actor types, such as managers, authenticate them in your application, and guard routes based on the custom user types. +- [Custom Authentication Providers](https://docs.medusajs.com/references/auth/provider/index.html.md): Integrate third-party services with custom authentication providors. *** ## How to Use the Auth Module -In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](undefined/docs/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package. @@ -26084,13 +26106,13 @@ export async function GET( } ``` -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). *** ## Configure Auth Module -The Auth Module accepts options for further configurations. Refer to [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/module-options) for details on the module's options. +The Auth Module accepts options for further configurations. Refer to [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/module-options/index.html.md) for details on the module's options. *** @@ -26105,7 +26127,7 @@ Medusa provides the following authentication providers out-of-the-box. You can u In this guide, you'll learn how to handle the `auth.password_reset` event to send a reset password email (or other notification type) to users. -Refer to this [Medusa Admin User Guide](undefined/user-guide/reset-password) to learn how to reset your user admin password using the dashboard. +Refer to this [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/reset-password/index.html.md) to learn how to reset your user admin password using the dashboard. ## Reset Password Flow Overview @@ -26113,11 +26135,11 @@ Refer to this [Medusa Admin User Guide](undefined/user-guide/reset-password) to Users of any actor type (admin, customer, or custom actor type) can request to reset their password. The flow for resetting a password is as follows: -1. The user requests to reset their password either through the frontend (for example, [Medusa Admin](undefined/user-guide/reset-password)) or the [Generate Reset Password Token API route](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route#generate-reset-password-token-route). +1. The user requests to reset their password either through the frontend (for example, [Medusa Admin](https://docs.medusajs.com/user-guide/reset-password/index.html.md)) or the [Generate Reset Password Token API route](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route#generate-reset-password-token-route/index.html.md). 2. The Medusa application generates a password reset token and emits the `auth.password_reset` event. - At this point, you can handle the event to send a notification to the user with instructions on how to reset their password. 3. The user receives the notification and clicks on the link to reset their password. - - The user can reset their password either through the frontend (for example, [Medusa Admin](undefined/user-guide/reset-password)) or the [Reset Password API route](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route#reset-password-route). + - The user can reset their password either through the frontend (for example, [Medusa Admin](https://docs.medusajs.com/user-guide/reset-password/index.html.md)) or the [Reset Password API route](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route#reset-password-route/index.html.md). In this guide, you'll implement a subscriber that handles the `auth.password_reset` event to send an email notification to the user with instructions on how to reset their password. @@ -26129,13 +26151,13 @@ After adding the subscriber, you will have a complete reset password flow you ca To send an email or notification to the user, you must have a Notification Module Provider set up. -Medusa provides providers like [SendGrid](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid) and [Resend](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/integrations/guides/resend), and you can also [create your own custom provider](undefined/references/notification-provider-module). +Medusa provides providers like [SendGrid](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid/index.html.md) and [Resend](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/integrations/guides/resend/index.html.md), and you can also [create your own custom provider](https://docs.medusajs.com/references/notification-provider-module/index.html.md). -Refer to the [Notification Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification#what-is-a-notification-module-provider) documentation for a list of available providers and how to set them up. +Refer to the [Notification Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification#what-is-a-notification-module-provider/index.html.md) documentation for a list of available providers and how to set them up. ### Testing with the Local Notification Module Provider -For testing purposes, you can use the [Local Notification Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification/local) by adding this to your `medusa-config.ts`: +For testing purposes, you can use the [Local Notification Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/local/index.html.md) by adding this to your `medusa-config.ts`: ```ts title="medusa-config.ts" module.exports = defineConfig({ @@ -26166,7 +26188,7 @@ The Local provider logs email details to your terminal instead of sending actual ## Create the Reset Password Subscriber -To create a [subscriber](undefined/docs/learn/fundamentals/events-and-subscribers) that handles the `auth.password_reset` event, create the file `src/subscribers/password-reset.ts` with the following content: +To create a [subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md) that handles the `auth.password_reset` event, create the file `src/subscribers/password-reset.ts` with the following content: ```ts title="src/subscribers/handle-reset.ts" highlights={highlights} collapsibleLines="1-6" expandMoreLabel="Show Imports" import { @@ -26271,13 +26293,13 @@ If you're using the Local provider, check your terminal for the logged email det In your frontend, you must have a page that accepts `token` and `email` query parameters. -The page shows the user password fields to enter their new password, then submits the new password, token, and email to the [Reset Password Route](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route#reset-password-route). +The page shows the user password fields to enter their new password, then submits the new password, token, and email to the [Reset Password Route](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route#reset-password-route/index.html.md). The Medusa Admin already has a reset password page at `/reset-password?token={token}&email={email}`. So, you only need to implement this page in your storefront or custom admin dashboard. ### Examples -- [Storefront Guide: Reset Customer Password](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development/customers/reset-password) +- [Storefront Guide: Reset Customer Password](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/customers/reset-password/index.html.md) *** @@ -26287,7 +26309,7 @@ The following section provides example notification templates for some Notificat ### SendGrid -Refer to the [SendGrid Notification Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid) documentation for more details on how to set up SendGrid. +Refer to the [SendGrid Notification Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid/index.html.md) documentation for more details on how to set up SendGrid. The following HTML template can be used with SendGrid to send a reset password email: @@ -26436,7 +26458,7 @@ You can also customize the template further to show other information. ### Resend -If you've integrated Resend as explained in the [Resend Integration Guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/integrations/guides/resend), you can add a new template for password reset emails at `src/modules/resend/emails/password-reset.tsx`: +If you've integrated Resend as explained in the [Resend Integration Guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/integrations/guides/resend/index.html.md), you can add a new template for password reset emails at `src/modules/resend/emails/password-reset.tsx`: ```tsx title="src/modules/resend/emails/password-reset.tsx" import { @@ -26575,11 +26597,11 @@ class ResendNotificationProviderService extends AbstractNotificationProviderServ # Retrieve Cart Totals using Query -In this guide, you'll learn how to retrieve cart totals in your Medusa application using [Query](undefined/docs/learn/fundamentals/module-links/query). +In this guide, you'll learn how to retrieve cart totals in your Medusa application using [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md). You may need to retrieve cart totals in your Medusa customizations, such as workflows or custom API routes, to perform custom actions with them. The ideal way to retrieve totals is with Query. -Refer to the [Retrieve Cart Totals in Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development/cart/totals) guide for a storefront-specific approach. +Refer to the [Retrieve Cart Totals in Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/cart/totals/index.html.md) guide for a storefront-specific approach. ## How to Retrieve Cart Totals with Query @@ -26880,7 +26902,7 @@ In this document, you’ll learn about the main concepts related to carts in Med ## Cart -A cart is the selection of product variants that a customer intends to purchase. It is represented by the [Cart data model](undefined/references/cart/models/Cart). +A cart is the selection of product variants that a customer intends to purchase. It is represented by the [Cart data model](https://docs.medusajs.com/references/cart/models/Cart/index.html.md). A cart holds informations about: @@ -26888,15 +26910,15 @@ A cart holds informations about: - The customer's shipping and billing addresses. - The shipping methods used to fulfill the items after purchase. - The payment method and information necessary to complete the purchase. - - These are stored and handled by the [Payment Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment). + - These are stored and handled by the [Payment Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/index.html.md). *** ## Line Items -A line item, represented by the [LineItem](undefined/references/cart/models/LineItem) data model, is a quantity of a product variant added to the cart. A cart has multiple line items. +A line item, represented by the [LineItem](https://docs.medusajs.com/references/cart/models/LineItem/index.html.md) data model, is a quantity of a product variant added to the cart. A cart has multiple line items. -In the Medusa application, a product variant is implemented in the [Product Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product). +In the Medusa application, a product variant is implemented in the [Product Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/index.html.md). A line item stores some of the product variant’s properties, such as the `product_title` and `product_description`. It also stores data related to the item’s quantity and price. @@ -26904,7 +26926,7 @@ A line item stores some of the product variant’s properties, such as the `prod ## Shipping and Billing Addresses -A cart has a shipping and billing address. Both of these addresses are represented by the [Address data model](undefined/references/cart/models/Address). +A cart has a shipping and billing address. Both of these addresses are represented by the [Address data model](https://docs.medusajs.com/references/cart/models/Address/index.html.md). ![A diagram showcasing the relation between the Cart and Address data models](https://res.cloudinary.com/dza7lstvk/image/upload/v1711532392/Medusa%20Resources/cart-addresses_ls6qmv.jpg) @@ -26912,9 +26934,9 @@ A cart has a shipping and billing address. Both of these addresses are represent ## Shipping Methods -A shipping method, represented by the [ShippingMethod data model](undefined/references/cart/models/ShippingMethod), is used to fulfill the items in the cart after the order is placed. A cart can have more than one shipping method. +A shipping method, represented by the [ShippingMethod data model](https://docs.medusajs.com/references/cart/models/ShippingMethod/index.html.md), is used to fulfill the items in the cart after the order is placed. A cart can have more than one shipping method. -In the Medusa application, the shipping method is created from a shipping option, available through the [Fulfillment Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/fulfillment). Its ID is stored in the `shipping_option_id` property of the method. +In the Medusa application, the shipping method is created from a shipping option, available through the [Fulfillment Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/fulfillment/index.html.md). Its ID is stored in the `shipping_option_id` property of the method. ### data Property @@ -26951,11 +26973,11 @@ Read-only links are used to query data across modules, but the relations aren't ## Customer Module -Medusa defines a read-only link between the `Cart` data model and the [Customer Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/customer)'s `Customer` data model. This means you can retrieve the details of a cart's customer, but you don't manage the links in a pivot table in the database. The customer of a cart is determined by the `customer_id` property of the `Cart` data model. +Medusa defines a read-only link between the `Cart` data model and the [Customer Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/customer/index.html.md)'s `Customer` data model. This means you can retrieve the details of a cart's customer, but you don't manage the links in a pivot table in the database. The customer of a cart is determined by the `customer_id` property of the `Cart` data model. ### Retrieve with Query -To retrieve the customer of a cart with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `customer.*` in `fields`: +To retrieve the customer of a cart with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `customer.*` in `fields`: ### query.graph @@ -26991,7 +27013,7 @@ const { data: carts } = useQueryGraphStep({ ## Fulfillment Module -Medusa defines a read-only link between the `ShippingMethod` data model and the [Fulfillment Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/fulfillment)'s `ShippingOption` data model. This means you can retrieve the details of a shipping method's shipping option, but you don't manage the links in a pivot table in the database. The shipping option of a shipping method is determined by the `shipping_option_id` property of the `ShippingMethod` data model. +Medusa defines a read-only link between the `ShippingMethod` data model and the [Fulfillment Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/fulfillment/index.html.md)'s `ShippingOption` data model. This means you can retrieve the details of a shipping method's shipping option, but you don't manage the links in a pivot table in the database. The shipping option of a shipping method is determined by the `shipping_option_id` property of the `ShippingMethod` data model. This link allows you to retrieve the shipping option that a shipping method was created from. @@ -26999,7 +27021,7 @@ This read-only link was added in [Medusa v2.10.0](https://github.com/medusajs/me ### Retrieve with Query -To retrieve the shipping option of a shipping method with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `shipping_option.*` in `fields`: +To retrieve the shipping option of a shipping method with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `shipping_option.*` in `fields`: ### query.graph @@ -27033,7 +27055,7 @@ const { data: shippingMethods } = useQueryGraphStep({ ## Order Module -The [Order Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order) provides order-management features. +The [Order Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/index.html.md) provides order-management features. Medusa defines a link between the `Cart` and `Order` data models. The cart is linked to the order created once the cart is completed. @@ -27041,7 +27063,7 @@ Medusa defines a link between the `Cart` and `Order` data models. The cart is li ### Retrieve with Query -To retrieve the order of a cart with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `order.*` in `fields`: +To retrieve the order of a cart with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `order.*` in `fields`: ### query.graph @@ -27075,7 +27097,7 @@ const { data: carts } = useQueryGraphStep({ ### Manage with Link -To manage the order of a cart, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the order of a cart, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -27116,7 +27138,7 @@ createRemoteLinkStep({ ## Payment Module -The [Payment Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment) handles payment processing and management. +The [Payment Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/index.html.md) handles payment processing and management. Medusa defines a link between the `Cart` and `PaymentCollection` data models. A cart has a payment collection which holds all the authorized payment sessions and payments made related to the cart. @@ -27124,7 +27146,7 @@ Medusa defines a link between the `Cart` and `PaymentCollection` data models. A ### Retrieve with Query -To retrieve the payment collection of a cart with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `payment_collection.*` in `fields`: +To retrieve the payment collection of a cart with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `payment_collection.*` in `fields`: ### query.graph @@ -27158,7 +27180,7 @@ const { data: carts } = useQueryGraphStep({ ### Manage with Link -To manage the payment collection of a cart, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the payment collection of a cart, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -27200,12 +27222,12 @@ createRemoteLinkStep({ Medusa defines read-only links between: -- the `LineItem` data model and the [Product Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product)'s `Product` data model. This means you can retrieve the details of a line item's product, but you don't manage the links in a pivot table in the database. The product of a line item is determined by the `product_id` property of the `LineItem` data model. -- the `LineItem` data model and the [Product Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product)'s `ProductVariant` data model. This means you can retrieve the details of a line item's variant, but you don't manage the links in a pivot table in the database. The variant of a line item is determined by the `variant_id` property of the `LineItem` data model. +- the `LineItem` data model and the [Product Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/index.html.md)'s `Product` data model. This means you can retrieve the details of a line item's product, but you don't manage the links in a pivot table in the database. The product of a line item is determined by the `product_id` property of the `LineItem` data model. +- the `LineItem` data model and the [Product Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/index.html.md)'s `ProductVariant` data model. This means you can retrieve the details of a line item's variant, but you don't manage the links in a pivot table in the database. The variant of a line item is determined by the `variant_id` property of the `LineItem` data model. ### Retrieve with Query -To retrieve the variant of a line item with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `variant.*` in `fields`: +To retrieve the variant of a line item with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `variant.*` in `fields`: To retrieve the product, pass `product.*` in `fields`. @@ -27243,7 +27265,7 @@ const { data: lineItems } = useQueryGraphStep({ ## Promotion Module -The [Promotion Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/promotion) provides discount features. +The [Promotion Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/promotion/index.html.md) provides discount features. Medusa defines a link between the `Cart` and `Promotion` data models. This indicates the promotions applied on a cart. @@ -27253,7 +27275,7 @@ Medusa also defines a read-only link between the `LineItemAdjustment` and `Promo ### Retrieve with Query -To retrieve the promotions of a cart with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `promotions.*` in `fields`: +To retrieve the promotions of a cart with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `promotions.*` in `fields`: To retrieve the promotion of a line item adjustment, pass `promotion.*` in `fields`. @@ -27289,7 +27311,7 @@ const { data: carts } = useQueryGraphStep({ ### Manage with Link -To manage the promotions of a cart, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the promotions of a cart, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -27330,11 +27352,11 @@ createRemoteLinkStep({ ## Region Module -Medusa defines a read-only link between the `Cart` data model and the [Region Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/region)'s `Region` data model. This means you can retrieve the details of a cart's region, but you don't manage the links in a pivot table in the database. The region of a cart is determined by the `region_id` property of the `Cart` data model. +Medusa defines a read-only link between the `Cart` data model and the [Region Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/region/index.html.md)'s `Region` data model. This means you can retrieve the details of a cart's region, but you don't manage the links in a pivot table in the database. The region of a cart is determined by the `region_id` property of the `Cart` data model. ### Retrieve with Query -To retrieve the region of a cart with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `region.*` in `fields`: +To retrieve the region of a cart with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `region.*` in `fields`: ### query.graph @@ -27370,11 +27392,11 @@ const { data: carts } = useQueryGraphStep({ ## Sales Channel Module -Medusa defines a read-only link between the `Cart` data model and the [Sales Channel Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/sales-channel)'s `SalesChannel` data model. This means you can retrieve the details of a cart's sales channel, but you don't manage the links in a pivot table in the database. The sales channel of a cart is determined by the `sales_channel_id` property of the `Cart` data model. +Medusa defines a read-only link between the `Cart` data model and the [Sales Channel Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/sales-channel/index.html.md)'s `SalesChannel` data model. This means you can retrieve the details of a cart's sales channel, but you don't manage the links in a pivot table in the database. The sales channel of a cart is determined by the `sales_channel_id` property of the `Cart` data model. ### Retrieve with Query -To retrieve the sales channel of a cart with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `sales_channel.*` in `fields`: +To retrieve the sales channel of a cart with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `sales_channel.*` in `fields`: ### query.graph @@ -27411,22 +27433,22 @@ const { data: carts } = useQueryGraphStep({ In this section of the documentation, you will find resources to learn more about the Cart Module and how to use it in your application. -Medusa has cart related features available out-of-the-box through the Cart Module. A [module](undefined/docs/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Cart Module. +Medusa has cart related features available out-of-the-box through the Cart Module. A [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Cart Module. -Learn more about why modules are isolated in [this documentation](undefined/docs/learn/fundamentals/modules/isolation). +Learn more about why modules are isolated in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md). ## Cart Features -- [Cart Management](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/cart/concepts): Store and manage carts, including their addresses, line items, shipping methods, and more. -- [Apply Promotion Adjustments](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/cart/promotions): Apply promotions or discounts to line items and shipping methods by adding adjustment lines that are factored into their subtotals. -- [Apply Tax Lines](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/cart/tax-lines): Apply tax lines to line items and shipping methods. -- [Cart Scoping](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/cart/links-to-other-modules): When used in the Medusa application, Medusa creates links to other Commerce Modules, scoping a cart to a sales channel, region, and a customer. +- [Cart Management](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/cart/concepts/index.html.md): Store and manage carts, including their addresses, line items, shipping methods, and more. +- [Apply Promotion Adjustments](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/cart/promotions/index.html.md): Apply promotions or discounts to line items and shipping methods by adding adjustment lines that are factored into their subtotals. +- [Apply Tax Lines](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/cart/tax-lines/index.html.md): Apply tax lines to line items and shipping methods. +- [Cart Scoping](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/cart/links-to-other-modules/index.html.md): When used in the Medusa application, Medusa creates links to other Commerce Modules, scoping a cart to a sales channel, region, and a customer. *** ## How to Use the Cart Module -In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](undefined/docs/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package. @@ -27552,7 +27574,7 @@ export const config = { } ``` -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). *** @@ -27565,7 +27587,7 @@ In this document, you’ll learn how a promotion is applied to a cart’s line i An adjustment line indicates a change to an item or a shipping method’s amount. It’s used to apply promotions or discounts on a cart. -The [LineItemAdjustment](undefined/references/cart/models/LineItemAdjustment) data model represents changes on a line item, and the [ShippingMethodAdjustment](undefined/references/cart/models/ShippingMethodAdjustment) data model represents changes on a shipping method. +The [LineItemAdjustment](https://docs.medusajs.com/references/cart/models/LineItemAdjustment/index.html.md) data model represents changes on a line item, and the [ShippingMethodAdjustment](https://docs.medusajs.com/references/cart/models/ShippingMethodAdjustment/index.html.md) data model represents changes on a shipping method. ![A diagram showcasing the relations between other data models and adjustment line models](https://res.cloudinary.com/dza7lstvk/image/upload/v1711534248/Medusa%20Resources/cart-adjustments_k4sttb.jpg) @@ -27575,7 +27597,7 @@ The `amount` property of the adjustment line indicates the amount to be discount ## Discountable Option -The [LineItem](undefined/references/cart/models/LineItem) data model has an `is_discountable` property that indicates whether promotions can be applied to the line item. It’s enabled by default. +The [LineItem](https://docs.medusajs.com/references/cart/models/LineItem/index.html.md) data model has an `is_discountable` property that indicates whether promotions can be applied to the line item. It’s enabled by default. When disabled, a promotion can’t be applied to a line item. In the context of the Promotion Module, the promotion isn’t applied to the line item even if it matches its rules. @@ -27583,9 +27605,9 @@ When disabled, a promotion can’t be applied to a line item. In the context of ## Promotion Actions -When using the Cart and Promotion modules together, such as in the Medusa application, use the [computeActions method of the Promotion Module’s main service](undefined/references/promotion/computeActions). It retrieves the actions of line items and shipping methods. +When using the Cart and Promotion modules together, such as in the Medusa application, use the [computeActions method of the Promotion Module’s main service](https://docs.medusajs.com/references/promotion/computeActions/index.html.md). It retrieves the actions of line items and shipping methods. -Learn more about actions in the [Promotion Module’s documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/promotion/actions). +Learn more about actions in the [Promotion Module’s documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/promotion/actions/index.html.md). For example: @@ -27681,7 +27703,7 @@ In this document, you’ll learn about tax lines in a cart and how to retrieve t ## What are Tax Lines? -A tax line indicates the tax rate of a line item or a shipping method. The [LineItemTaxLine data model](undefined/references/cart/models/LineItemTaxLine) represents a line item’s tax line, and the [ShippingMethodTaxLine data model](undefined/references/cart/models/ShippingMethodTaxLine) represents a shipping method’s tax line. +A tax line indicates the tax rate of a line item or a shipping method. The [LineItemTaxLine data model](https://docs.medusajs.com/references/cart/models/LineItemTaxLine/index.html.md) represents a line item’s tax line, and the [ShippingMethodTaxLine data model](https://docs.medusajs.com/references/cart/models/ShippingMethodTaxLine/index.html.md) represents a shipping method’s tax line. ![A diagram showcasing the relation between other data models and the tax line models](https://res.cloudinary.com/dza7lstvk/image/upload/v1711534431/Medusa%20Resources/cart-tax-lines_oheaq6.jpg) @@ -27770,11 +27792,11 @@ Read-only links are used to query data across modules, but the relations aren't The Store Module has a `Currency` data model that stores the supported currencies of a store. However, these currencies don't hold all the details of a currency, such as its name or symbol. -Instead, Medusa defines a read-only link between the [Store Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/store)'s `StoreCurrency` data model and the Currency Module's `Currency` data model. Because the link is read-only from the `Store`'s side, you can only retrieve the details of a store's supported currencies, and not the other way around. +Instead, Medusa defines a read-only link between the [Store Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/store/index.html.md)'s `StoreCurrency` data model and the Currency Module's `Currency` data model. Because the link is read-only from the `Store`'s side, you can only retrieve the details of a store's supported currencies, and not the other way around. ### Retrieve with Query -To retrieve the details of a store's currencies with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `supported_currencies.currency.*` in `fields`: +To retrieve the details of a store's currencies with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `supported_currencies.currency.*` in `fields`: ### query.graph @@ -27811,22 +27833,22 @@ const { data: stores } = useQueryGraphStep({ In this section of the documentation, you will find resources to learn more about the Currency Module and how to use it in your application. -Refer to the [Medusa Admin User Guide](undefined/user-guide/settings/store) to learn how to manage your store's currencies using the dashboard. +Refer to the [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/settings/store/index.html.md) to learn how to manage your store's currencies using the dashboard. -Medusa has currency related features available out-of-the-box through the Currency Module. A [module](undefined/docs/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Currency Module. +Medusa has currency related features available out-of-the-box through the Currency Module. A [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Currency Module. -Learn more about why modules are isolated in [this documentation](undefined/docs/learn/fundamentals/modules/isolation). +Learn more about why modules are isolated in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md). ## Currency Features -- [Currency Management and Retrieval](undefined/references/currency/listAndCountCurrencies): This module adds all common currencies to your application and allows you to retrieve them. -- [Support Currencies in Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/currency/links-to-other-modules): Other Commerce Modules use currency codes in their data models or operations. Use the Currency Module to retrieve a currency code and its details. +- [Currency Management and Retrieval](https://docs.medusajs.com/references/currency/listAndCountCurrencies/index.html.md): This module adds all common currencies to your application and allows you to retrieve them. +- [Support Currencies in Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/currency/links-to-other-modules/index.html.md): Other Commerce Modules use currency codes in their data models or operations. Use the Currency Module to retrieve a currency code and its details. *** ## How to Use the Currency Module -In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](undefined/docs/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package. @@ -27950,7 +27972,7 @@ export const config = { } ``` -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). *** @@ -27959,11 +27981,11 @@ Learn more about workflows in [this documentation](undefined/docs/learn/fundamen In this document, you’ll learn how registered and unregistered accounts are distinguished in the Medusa application. -Refer to this [Medusa Admin User Guide](undefined/user-guide/customers) to learn how to manage customers using the dashboard. +Refer to this [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/customers/index.html.md) to learn how to manage customers using the dashboard. ## `has_account` Property -The [Customer data model](undefined/references/customer/models/Customer) has a `has_account` property, which is a boolean that indicates whether a customer is registered. +The [Customer data model](https://docs.medusajs.com/references/customer/models/Customer/index.html.md) has a `has_account` property, which is a boolean that indicates whether a customer is registered. When a guest customer places an order, a new `Customer` record is created with `has_account` set to `false`. @@ -27983,7 +28005,7 @@ So, there can only be one guest customer (having `has_account=false`) and one re When a merchant deletes a customer, the `Customer` record is soft-deleted, meaning it is not permanently removed from the database. -When using the Medusa Application with the [Auth Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth), possible confusion may arise in the following scenarios: +When using the Medusa Application with the [Auth Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/index.html.md), possible confusion may arise in the following scenarios: 1. An admin user is using the email address `john@example.com`, and a customer tries to register with the same email address. 2. An admin user has deleted a customer with the email address `jane@example.com`, and another customer tries to register with the same email address. @@ -28004,8 +28026,8 @@ To resolve this, you can amend the registration flow to: You can learn more about how to implement this flow in the following guides: -- [Conceptual guide on how to implement this flow with Medusa's authentication routes](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route#handling-existing-identities). -- [How-to guide on how to implement this in a storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development/customers/register). +- [Conceptual guide on how to implement this flow with Medusa's authentication routes](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route#handling-existing-identities/index.html.md). +- [How-to guide on how to implement this in a storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/customers/register/index.html.md). # Links between Customer Module and Other Modules @@ -28034,7 +28056,7 @@ This link is available starting from Medusa `v2.5.0`. ### Retrieve with Query -To retrieve the account holder associated with a customer with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `customer.*` in `fields`: +To retrieve the account holder associated with a customer with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `customer.*` in `fields`: ### query.graph @@ -28068,7 +28090,7 @@ const { data: customers } = useQueryGraphStep({ ### Manage with Link -To manage the account holders of a customer, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the account holders of a customer, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -28108,11 +28130,11 @@ createRemoteLinkStep({ ## Cart Module -Medusa defines a read-only link between the [Cart Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/cart)'s `Cart` data model and the `Customer` data model. Because the link is read-only from the `Cart`'s side, you can only retrieve the customer of a cart, and not the other way around. +Medusa defines a read-only link between the [Cart Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/cart/index.html.md)'s `Cart` data model and the `Customer` data model. Because the link is read-only from the `Cart`'s side, you can only retrieve the customer of a cart, and not the other way around. ### Retrieve with Query -To retrieve the customer of a cart with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `customer.*` in `fields`: +To retrieve the customer of a cart with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `customer.*` in `fields`: ### query.graph @@ -28148,11 +28170,11 @@ const { data: carts } = useQueryGraphStep({ ## Order Module -Medusa defines a read-only link between the [Order Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order)'s `Order` data model and the `Customer` data model. Because the link is read-only from the `Order`'s side, you can only retrieve the customer of an order, and not the other way around. +Medusa defines a read-only link between the [Order Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/index.html.md)'s `Order` data model and the `Customer` data model. Because the link is read-only from the `Order`'s side, you can only retrieve the customer of an order, and not the other way around. ### Retrieve with Query -To retrieve the customer of an order with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `customer.*` in `fields`: +To retrieve the customer of an order with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `customer.*` in `fields`: ### query.graph @@ -28189,22 +28211,22 @@ const { data: orders } = useQueryGraphStep({ In this section of the documentation, you will find resources to learn more about the Customer Module and how to use it in your application. -Refer to the [Medusa Admin User Guide](undefined/user-guide/customers) to learn how to manage customers and groups using the dashboard. +Refer to the [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/customers/index.html.md) to learn how to manage customers and groups using the dashboard. -Medusa has customer related features available out-of-the-box through the Customer Module. A [module](undefined/docs/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Customer Module. +Medusa has customer related features available out-of-the-box through the Customer Module. A [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Customer Module. -Learn more about why modules are isolated in [this documentation](undefined/docs/learn/fundamentals/modules/isolation). +Learn more about why modules are isolated in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md). ## Customer Features -- [Customer Management](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/customer/customer-accounts): Store and manage guest and registered customers in your store. -- [Customer Organization](undefined/references/customer/models): 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](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/promotion). +- [Customer Management](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/customer/customer-accounts/index.html.md): Store and manage guest and registered customers in your store. +- [Customer Organization](https://docs.medusajs.com/references/customer/models/index.html.md): 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](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/promotion/index.html.md). *** ## How to Use the Customer Module -In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](undefined/docs/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package. @@ -28321,7 +28343,7 @@ export const config = { } ``` -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). *** @@ -28334,7 +28356,7 @@ In this document, you’ll learn about some basic fulfillment concepts. A fulfillment set is a general form or way of fulfillment. For example, shipping is a form of fulfillment, and pick-up is another form of fulfillment. Each of these can be created as fulfillment sets. -A fulfillment set is represented by the [FulfillmentSet data model](undefined/references/fulfillment/models/FulfillmentSet). All other configurations, options, and management features are related to a fulfillment set, in one way or another. +A fulfillment set is represented by the [FulfillmentSet data model](https://docs.medusajs.com/references/fulfillment/models/FulfillmentSet/index.html.md). All other configurations, options, and management features are related to a fulfillment set, in one way or another. ```ts const fulfillmentSets = await fulfillmentModuleService.createFulfillmentSets( @@ -28357,11 +28379,11 @@ const fulfillmentSets = await fulfillmentModuleService.createFulfillmentSets( A service zone is a collection of geographical zones or areas. It’s used to restrict available shipping options to a defined set of locations. -A service zone is represented by the [ServiceZone data model](undefined/references/fulfillment/models/ServiceZone). It’s associated with a fulfillment set, as each service zone is specific to a form of fulfillment. For example, if a customer chooses to pick up items, you can restrict the available shipping options based on their location. +A service zone is represented by the [ServiceZone data model](https://docs.medusajs.com/references/fulfillment/models/ServiceZone/index.html.md). It’s associated with a fulfillment set, as each service zone is specific to a form of fulfillment. For example, if a customer chooses to pick up items, you can restrict the available shipping options based on their location. ![A diagram showcasing the relation between fulfillment sets, service zones, and geo zones](https://res.cloudinary.com/dza7lstvk/image/upload/v1712329770/Medusa%20Resources/service-zone_awmvfs.jpg) -A service zone can have multiple geographical zones, each represented by the [GeoZone data model](undefined/references/fulfillment/models/GeoZone). It holds location-related details to narrow down supported areas, such as country, city, or province code. +A service zone can have multiple geographical zones, each represented by the [GeoZone data model](https://docs.medusajs.com/references/fulfillment/models/GeoZone/index.html.md). It holds location-related details to narrow down supported areas, such as country, city, or province code. The province code is always in lower-case and in [ISO 3166-2 format](https://en.wikipedia.org/wiki/ISO_3166-2). @@ -28371,20 +28393,20 @@ The province code is always in lower-case and in [ISO 3166-2 format](https://en. A shipping profile defines a type of items that are shipped in a similar manner. For example, a `default` shipping profile is used for all item types, but the `digital` shipping profile is used for digital items that aren’t shipped and delivered conventionally. -A shipping profile is represented by the [ShippingProfile data model](undefined/references/fulfillment/models/ShippingProfile). It only defines the profile’s details, but it’s associated with the shipping options available for the item type. +A shipping profile is represented by the [ShippingProfile data model](https://docs.medusajs.com/references/fulfillment/models/ShippingProfile/index.html.md). It only defines the profile’s details, but it’s associated with the shipping options available for the item type. # Fulfillment Module Provider In this guide, you’ll learn about the Fulfillment Module Provider and how it's used. -Refer to this [Medusa Admin User Guide](undefined/user-guide/settings/locations-and-shipping/locations#manage-fulfillment-providers) to learn how to add a fulfillment provider to a location using the dashboard. +Refer to this [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/settings/locations-and-shipping/locations#manage-fulfillment-providers/index.html.md) to learn how to add a fulfillment provider to a location using the dashboard. ## What is a Fulfillment Module Provider? A Fulfillment Module Provider handles fulfilling items, typically using a third-party integration. -Fulfillment Module Providers registered in the Fulfillment Module's [options](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/fulfillment/module-options) are stored and represented by the [FulfillmentProvider data model](undefined/references/fulfillment/models/FulfillmentProvider). +Fulfillment Module Providers registered in the Fulfillment Module's [options](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/fulfillment/module-options/index.html.md) are stored and represented by the [FulfillmentProvider data model](https://docs.medusajs.com/references/fulfillment/models/FulfillmentProvider/index.html.md). ![Diagram showcasing the communication between Medusa, the Fulfillment Module Provider, and the third-party fulfillment provider.](https://res.cloudinary.com/dza7lstvk/image/upload/v1746794800/Medusa%20Resources/fulfillment-provider-service_ljsqpq.jpg) @@ -28406,7 +28428,7 @@ A Fulfillment Module Provider is a module whose service implements the `IFulfill The module can have multiple fulfillment provider services, where each are registered as separate fulfillment providers. -Refer to the [Create Fulfillment Module Provider](undefined/references/fulfillment/provider) guide to learn how to create a Fulfillment Module Provider. +Refer to the [Create Fulfillment Module Provider](https://docs.medusajs.com/references/fulfillment/provider/index.html.md) guide to learn how to create a Fulfillment Module Provider. {/* TODO add link to user guide */} @@ -28420,7 +28442,7 @@ After you create a fulfillment provider, you can choose it as the default Fulfil The Fulfillment Module accepts a `providers` option that allows you to configure the providers registered in your application. -Learn more about this option in the [Module Options](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/fulfillment/module-options) guide. +Learn more about this option in the [Module Options](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/fulfillment/module-options/index.html.md) guide. ### Registration on Application Start @@ -28430,7 +28452,7 @@ For each Fulfillment Module Provider, the Medusa application finds all fulfillme ### FulfillmentProvider Data Model -A registered fulfillment provider is represented by the [FulfillmentProvider data model](undefined/references/fulfillment/models/FulfillmentProvider) in the Medusa application. +A registered fulfillment provider is represented by the [FulfillmentProvider data model](https://docs.medusajs.com/references/fulfillment/models/FulfillmentProvider/index.html.md) in the Medusa application. This data model is used to reference a service in the Fulfillment Module Provider and determine whether it's installed in the application. @@ -28456,17 +28478,17 @@ In this document, you’ll learn about the concepts related to item fulfillment. ## Fulfillment Data Model -A fulfillment is the shipping and delivery of one or more items to the customer. It’s represented by the [Fulfillment data model](undefined/references/fulfillment/models/Fulfillment). +A fulfillment is the shipping and delivery of one or more items to the customer. It’s represented by the [Fulfillment data model](https://docs.medusajs.com/references/fulfillment/models/Fulfillment/index.html.md). -A fulfillment can be created to fulfill orders, [returns](../../order/return/), [exchanges](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/exchange), and [claims](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/claim). +A fulfillment can be created to fulfill orders, [returns](../../order/return/), [exchanges](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/exchange/index.html.md), and [claims](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/claim/index.html.md). *** ## Fulfillment Processing by a Fulfillment Provider -A fulfillment is associated with a [fulfillment provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/fulfillment/fulfillment-provider) that handles all its processing, such as creating a shipment for the fulfillment’s items. +A fulfillment is associated with a [fulfillment provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/fulfillment/fulfillment-provider/index.html.md) that handles all its processing, such as creating a shipment for the fulfillment’s items. -The fulfillment is also associated with a [shipping option](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/fulfillment/shipping-option) of that provider, which determines how the item is shipped. +The fulfillment is also associated with a [shipping option](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/fulfillment/shipping-option/index.html.md) of that provider, which determines how the item is shipped. ![A diagram showcasing the relation between a fulfillment, fulfillment provider, and shipping option](https://res.cloudinary.com/dza7lstvk/image/upload/v1712331947/Medusa%20Resources/fulfillment-shipping-option_jk9ndp.jpg) @@ -28482,7 +28504,7 @@ For example, the `data` property can hold the ID of the fulfillment in the third ## Fulfillment Items -A fulfillment is used to fulfill one or more items. Each item is represented by the [FulfillmentItem data model](undefined/references/fulfillment/models/FulfillmentItem). +A fulfillment is used to fulfill one or more items. Each item is represented by the [FulfillmentItem data model](https://docs.medusajs.com/references/fulfillment/models/FulfillmentItem/index.html.md). The fulfillment item holds details relevant to fulfilling the item, such as barcode, SKU, and quantity to fulfill. @@ -28492,13 +28514,13 @@ The fulfillment item holds details relevant to fulfilling the item, such as barc ## Fulfillment Label -Once a shipment is created for the fulfillment, you can store its tracking number, URL, or other related details as a label, represented by the [FulfillmentLabel data model](undefined/references/fulfillment/models/FulfillmentLabel). +Once a shipment is created for the fulfillment, you can store its tracking number, URL, or other related details as a label, represented by the [FulfillmentLabel data model](https://docs.medusajs.com/references/fulfillment/models/FulfillmentLabel/index.html.md). *** ## Fulfillment Status -The [Fulfillment data model](undefined/references/fulfillment/models/Fulfillment) has three properties to determine the current status of the fulfillment: +The [Fulfillment data model](https://docs.medusajs.com/references/fulfillment/models/Fulfillment/index.html.md) has three properties to determine the current status of the fulfillment: - `packed_at`: The date the fulfillment was packed. If set, the fulfillment has been packed. - `shipped_at`: The date the fulfillment was shipped. If set, the fulfillment has been shipped. @@ -28527,7 +28549,7 @@ The Fulfillment Module has the following links to other modules: ## Cart Module -Medusa defines a read-only link between the `ShippingMethod` data model of the [Cart Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/cart) and the `ShippingOption` data model. This means you can retrieve the details of a shipping method's shipping option, but you don't manage the links in a pivot table in the database. The shipping option of a shipping method is determined by the `shipping_option_id` property of the `ShippingMethod` data model. +Medusa defines a read-only link between the `ShippingMethod` data model of the [Cart Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/cart/index.html.md) and the `ShippingOption` data model. This means you can retrieve the details of a shipping method's shipping option, but you don't manage the links in a pivot table in the database. The shipping option of a shipping method is determined by the `shipping_option_id` property of the `ShippingMethod` data model. This link allows you to retrieve the shipping option that a shipping method was created from. @@ -28535,7 +28557,7 @@ This read-only link was added in [Medusa v2.10.0](https://github.com/medusajs/me ### Retrieve with Query -To retrieve the shipping option of a shipping method with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `shipping_option.*` in `fields`: +To retrieve the shipping option of a shipping method with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `shipping_option.*` in `fields`: ### query.graph @@ -28571,7 +28593,7 @@ const { data: shippingMethods } = useQueryGraphStep({ ## Order Module -The [Order Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order) provides order-management functionalities. +The [Order Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/index.html.md) provides order-management functionalities. Medusa defines a link between the `Fulfillment` and `Order` data models. A fulfillment is created for an orders' items. @@ -28583,7 +28605,7 @@ A fulfillment is also created for a return's items. So, Medusa defines a link be ### Retrieve with Query -To retrieve the order of a fulfillment with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `order.*` in `fields`: +To retrieve the order of a fulfillment with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `order.*` in `fields`: To retrieve the return, pass `return.*` in `fields`. @@ -28619,7 +28641,7 @@ const { data: fulfillments } = useQueryGraphStep({ ### Manage with Link -To manage the order of a cart, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the order of a cart, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -28668,7 +28690,7 @@ Medusa defines a link between the `PriceSet` and `ShippingOption` data models. A ### Retrieve with Query -To retrieve the price set of a shipping option with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `price_set.*` in `fields`: +To retrieve the price set of a shipping option with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `price_set.*` in `fields`: ### query.graph @@ -28702,7 +28724,7 @@ const { data: shippingOptions } = useQueryGraphStep({ ### Manage with Link -To manage the price set of a shipping option, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the price set of a shipping option, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -28749,7 +28771,7 @@ This link is introduced in [Medusa v2.5.0](https://github.com/medusajs/medusa/re ### Retrieve with Query -To retrieve the products of a shipping profile with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `products.*` in `fields`: +To retrieve the products of a shipping profile with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `products.*` in `fields`: ### query.graph @@ -28783,7 +28805,7 @@ const { data: shippingProfiles } = useQueryGraphStep({ ### Manage with Link -To manage the shipping profile of a product, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the shipping profile of a product, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -28836,7 +28858,7 @@ Medusa also defines a link between the `FulfillmentProvider` and `StockLocation` ### Retrieve with Query -To retrieve the stock location of a fulfillment set with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `location.*` in `fields`: +To retrieve the stock location of a fulfillment set with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `location.*` in `fields`: To retrieve the stock location of a fulfillment provider, pass `locations.*` in `fields`. @@ -28872,7 +28894,7 @@ const { data: fulfillmentSets } = useQueryGraphStep({ ### Manage with Link -To manage the stock location of a fulfillment set, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the stock location of a fulfillment set, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -28916,7 +28938,7 @@ In this document, you'll learn about the options of the Fulfillment Module. You ## providers -The `providers` option is an array of [Fulfillment Module Providers](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/fulfillment/fulfillment-provider). +The `providers` option is an array of [Fulfillment Module Providers](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/fulfillment/fulfillment-provider/index.html.md). When the Medusa application starts, these providers are registered and can be used to process fulfillments. @@ -28961,26 +28983,26 @@ In this section of the documentation, you will find resources to learn more abou Refer to the Medusa Admin User Guide to learn how to use the dashboard to: -- [Manage order fulfillments](undefined/user-guide/orders/fulfillments). -- [Manage shipping options and profiles](undefined/user-guide/settings/locations-and-shipping). +- [Manage order fulfillments](https://docs.medusajs.com/user-guide/orders/fulfillments/index.html.md). +- [Manage shipping options and profiles](https://docs.medusajs.com/user-guide/settings/locations-and-shipping/index.html.md). -Medusa has fulfillment related features available out-of-the-box through the Fulfillment Module. A [module](undefined/docs/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Fulfillment Module. +Medusa has fulfillment related features available out-of-the-box through the Fulfillment Module. A [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Fulfillment Module. -Learn more about why modules are isolated in [this documentation](undefined/docs/learn/fundamentals/modules/isolation). +Learn more about why modules are isolated in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md). ## Fulfillment Features -- [Fulfillment Management](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/fulfillment/item-fulfillment): Create fulfillments and keep track of their status, items, and more. -- [Integrate Third-Party Fulfillment Providers](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/fulfillment/fulfillment-provider): Create third-party fulfillment providers to provide customers with shipping options and fulfill their orders. -- [Restrict By Location and Rules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/fulfillment/shipping-option): Shipping options can be restricted to specific geographical locations. You can also specify custom rules to restrict shipping options. -- [Support Different Fulfillment Forms](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/fulfillment/concepts): Support various fulfillment forms, such as shipping or pick up. -- [Tiered Pricing and Price Rules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/price-rules): Set prices for shipping options with tiers and rules, allowing you to create complex pricing strategies. +- [Fulfillment Management](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/fulfillment/item-fulfillment/index.html.md): Create fulfillments and keep track of their status, items, and more. +- [Integrate Third-Party Fulfillment Providers](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/fulfillment/fulfillment-provider/index.html.md): Create third-party fulfillment providers to provide customers with shipping options and fulfill their orders. +- [Restrict By Location and Rules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/fulfillment/shipping-option/index.html.md): Shipping options can be restricted to specific geographical locations. You can also specify custom rules to restrict shipping options. +- [Support Different Fulfillment Forms](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/fulfillment/concepts/index.html.md): Support various fulfillment forms, such as shipping or pick up. +- [Tiered Pricing and Price Rules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/price-rules/index.html.md): Set prices for shipping options with tiers and rules, allowing you to create complex pricing strategies. *** ## How to Use the Fulfillment Module -In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](undefined/docs/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package. @@ -29111,13 +29133,13 @@ export const config = { } ``` -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). *** ## Configure Fulfillment Module -The Fulfillment Module accepts options for further configurations. Refer to [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/fulfillment/module-options) for details on the module's options. +The Fulfillment Module accepts options for further configurations. Refer to [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/fulfillment/module-options/index.html.md) for details on the module's options. *** @@ -29132,7 +29154,7 @@ A shipping option is a way of shipping an item. Each fulfillment provider offers When the customer places an order, they choose a shipping option to fulfill their items. -A shipping option is represented by the [ShippingOption data model](undefined/references/fulfillment/models/ShippingOption). +A shipping option is represented by the [ShippingOption data model](https://docs.medusajs.com/references/fulfillment/models/ShippingOption/index.html.md). *** @@ -29156,9 +29178,9 @@ The province code is always in lowercase and in [ISO 3166-2 format](https://en.w You can restrict shipping options by custom rules, such as the item’s weight or the customer group. -You can also restrict a shipping option's price based on specific conditions. For example, you can make a shipping option's price free based on the cart total. Learn more in the Pricing Module's [Price Rules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/price-rules#how-to-set-rules-on-a-price) guide. +You can also restrict a shipping option's price based on specific conditions. For example, you can make a shipping option's price free based on the cart total. Learn more in the Pricing Module's [Price Rules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/price-rules#how-to-set-rules-on-a-price/index.html.md) guide. -These rules are represented by the [ShippingOptionRule data model](undefined/references/fulfillment/models/ShippingOptionRule). Its properties define the custom rules: +These rules are represented by the [ShippingOptionRule data model](https://docs.medusajs.com/references/fulfillment/models/ShippingOptionRule/index.html.md). Its properties define the custom rules: - `attribute`: The name of a property or table that the rule applies to. For example, `customer_group`. - `operator`: The operator used in the condition. For example: @@ -29178,9 +29200,9 @@ A shipping option can have multiple rules. For example, you can add rules to a s A shipping option belongs to a type and a profile. -A shipping option type defines a group of shipping options with shared shipping characteristics. For example, a shipping option’s type may be `express`, while another may be `standard`. The type is represented by the [ShippingOptionType data model](undefined/references/fulfillment/models/ShippingOptionType). +A shipping option type defines a group of shipping options with shared shipping characteristics. For example, a shipping option’s type may be `express`, while another may be `standard`. The type is represented by the [ShippingOptionType data model](https://docs.medusajs.com/references/fulfillment/models/ShippingOptionType/index.html.md). -A shipping profile defines a group of items (such as products) that are shipped in a similar manner. For example, the "Standard" shipping profile applies to all products, whereas the "Digital" shipping profile applies to digital products. Shipping profiles are represented by the [ShippingProfile data model](undefined/references/fulfillment/models/ShippingProfile). +A shipping profile defines a group of items (such as products) that are shipped in a similar manner. For example, the "Standard" shipping profile applies to all products, whereas the "Digital" shipping profile applies to digital products. Shipping profiles are represented by the [ShippingProfile data model](https://docs.medusajs.com/references/fulfillment/models/ShippingProfile/index.html.md). *** @@ -29197,7 +29219,7 @@ In this guide, you'll learn about the main concepts in the Inventory Module and ## InventoryItem -An inventory item, represented by the [InventoryItem data model](undefined/references/inventory-next/models/InventoryItem), is a stock-kept item whose inventory can be managed. For example, a product. +An inventory item, represented by the [InventoryItem data model](https://docs.medusajs.com/references/inventory-next/models/InventoryItem/index.html.md), is a stock-kept item whose inventory can be managed. For example, a product. The `InventoryItem` data model holds details about the stock item. It connects to other data models like `InventoryLevel` that store stock and quantity details. @@ -29209,13 +29231,13 @@ An inventory item has a `requires_shipping` field that indicates whether the ite For example, if you're selling a digital license with limited stock that doesn't need shipping, you can set this field to `false`. -When a customer buys a product variant in the Medusa application, this field determines whether the item needs shipping. Learn more in the [Configure Selling Products](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product/selling-products) guide. +When a customer buys a product variant in the Medusa application, this field determines whether the item needs shipping. Learn more in the [Configure Selling Products](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/selling-products/index.html.md) guide. *** ## InventoryLevel -An inventory level, represented by the [InventoryLevel data model](undefined/references/inventory-next/models/InventoryLevel), stores the inventory and quantity details of an inventory item in a specific location. +An inventory level, represented by the [InventoryLevel data model](https://docs.medusajs.com/references/inventory-next/models/InventoryLevel/index.html.md), stores the inventory and quantity details of an inventory item in a specific location. It has three quantity properties: @@ -29226,19 +29248,19 @@ It has three quantity properties: ### Associated Location -The inventory level's location is set in the `location_id` property. Medusa links the `InventoryLevel` data model with the `StockLocation` data model from the [Stock Location Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/stock-location). +The inventory level's location is set in the `location_id` property. Medusa links the `InventoryLevel` data model with the `StockLocation` data model from the [Stock Location Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/stock-location/index.html.md). *** ## ReservationItem -A reservation item, represented by the [ReservationItem](undefined/references/inventory-next/models/ReservationItem) data model, represents unavailable quantity of an inventory item in a location. +A reservation item, represented by the [ReservationItem](https://docs.medusajs.com/references/inventory-next/models/ReservationItem/index.html.md) data model, represents unavailable quantity of an inventory item in a location. When an order is placed, Medusa creates a reservation item for each inventory item in the order. The reservation item stores the reserved quantity of the inventory item in the location associated with the order's sales channel. You can also use reservation items for custom use cases. For example, if you're selling event tickets, you can create a reservation item when a customer selects a ticket. Then, you can remove the reservation item if the customer doesn't complete the purchase within a specific time. -The reserved quantity is linked to a location, so it has a similar relationship to the `InventoryLevel` with the [Stock Location Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/stock-location). +The reserved quantity is linked to a location, so it has a similar relationship to the `InventoryLevel` with the [Stock Location Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/stock-location/index.html.md). # Inventory Module in Medusa Flows @@ -29249,7 +29271,7 @@ In this guide, you'll learn how Medusa uses the Inventory Module in its commerce When a product variant is created and its `manage_inventory` property's value is `true` and the variant's `inventory_items` are set, the Medusa application creates an inventory item associated with that product variant. -This flow is implemented within the [createProductVariantsWorkflow](undefined/references/medusa-workflows/createProductVariantsWorkflow) +This flow is implemented within the [createProductVariantsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createProductVariantsWorkflow/index.html.md) ![A diagram showcasing how the Inventory Module is used in the product variant creation flow](https://res.cloudinary.com/dza7lstvk/image/upload/v1709661511/Medusa%20Resources/inventory-product-create_khz2hk.jpg) @@ -29259,7 +29281,7 @@ This flow is implemented within the [createProductVariantsWorkflow](undefined/re When a product variant with `manage_inventory` set to `true` is added to the cart, the Medusa application checks whether there's sufficient stocked quantity. If not, an error is thrown and the product variant won't be added to the cart. -This flow is implemented within the [addToCartWorkflow](undefined/references/medusa-workflows/addToCartWorkflow) +This flow is implemented within the [addToCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/addToCartWorkflow/index.html.md) ![A diagram showcasing how the Inventory Module is used in the add to cart flow](https://res.cloudinary.com/dza7lstvk/image/upload/v1709711645/Medusa%20Resources/inventory-cart-flow_achwq9.jpg) @@ -29269,7 +29291,7 @@ This flow is implemented within the [addToCartWorkflow](undefined/references/med When an order is placed, the Medusa application creates a reservation item for each product variant with `manage_inventory` set to `true`. -This flow is implemented within the [completeCartWorkflow](undefined/references/medusa-workflows/completeCartWorkflow) +This flow is implemented within the [completeCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/completeCartWorkflow/index.html.md) ![A diagram showcasing how the Inventory Module is used in the order placement flow](https://res.cloudinary.com/dza7lstvk/image/upload/v1709712005/Medusa%20Resources/inventory-order-placed_qdxqdn.jpg) @@ -29283,7 +29305,7 @@ When an item in an order is fulfilled and the associated variant has its `manage - Resets the `reserved_quantity` to `0`. - Deletes the associated reservation item. -This flow is implemented within the [createOrderFulfillmentWorkflow](undefined/references/medusa-workflows/createOrderFulfillmentWorkflow) +This flow is implemented within the [createOrderFulfillmentWorkflow](https://docs.medusajs.com/references/medusa-workflows/createOrderFulfillmentWorkflow/index.html.md) ![A diagram showcasing how the Inventory Module is used in the order fulfillment flow](https://res.cloudinary.com/dza7lstvk/image/upload/v1709712390/Medusa%20Resources/inventory-order-fulfillment_o9wdxh.jpg) @@ -29293,7 +29315,7 @@ This flow is implemented within the [createOrderFulfillmentWorkflow](undefined/r 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. -This flow is implemented within the [confirmReturnReceiveWorkflow](undefined/references/medusa-workflows/confirmReturnReceiveWorkflow) +This flow is implemented within the [confirmReturnReceiveWorkflow](https://docs.medusajs.com/references/medusa-workflows/confirmReturnReceiveWorkflow/index.html.md) ![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) @@ -29308,14 +29330,14 @@ In this guide, you'll learn how inventory kits can be used in the Medusa applica Refer to the following user guides to learn how to use the Medusa Admin dashboard to: -- [Create Multi-Part Products](undefined/user-guide/products/create/multi-part). -- [Create Bundled Products](undefined/user-guide/products/create/bundle). +- [Create Multi-Part Products](https://docs.medusajs.com/user-guide/products/create/multi-part/index.html.md). +- [Create Bundled Products](https://docs.medusajs.com/user-guide/products/create/bundle/index.html.md). ## What is an Inventory Kit? An inventory kit is a collection of inventory items that are linked to a single product variant. These inventory items can be used to represent different parts of a product, or to represent a bundle of products. -The Medusa application links inventory items from the [Inventory Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/inventory) to product variants in the [Product Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product). Each variant can have multiple inventory items, and these inventory items can be re-used or shared across variants. +The Medusa application links inventory items from the [Inventory Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/inventory/index.html.md) to product variants in the [Product Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/index.html.md). Each variant can have multiple inventory items, and these inventory items can be re-used or shared across variants. Using inventory kits, you can implement use cases like: @@ -29339,9 +29361,9 @@ Then, whenever a customer purchases a bicycle, the inventory of each part is upd ### Create Multi-Part Product -Using the [Medusa Admin](undefined/user-guide/products/create/multi-part), you can create a multi-part product by creating its inventory items first, then assigning these inventory items to the product's variant(s). +Using the [Medusa Admin](https://docs.medusajs.com/user-guide/products/create/multi-part/index.html.md), you can create a multi-part product by creating its inventory items first, then assigning these inventory items to the product's variant(s). -Using [workflows](undefined/docs/learn/fundamentals/workflows), you can implement this by first creating the inventory items: +Using [workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), you can implement this by first creating the inventory items: ```ts highlights={multiPartsHighlights1} import { @@ -29404,7 +29426,7 @@ export const createMultiPartProductsWorkflow = createWorkflow( ) ``` -You start by retrieving the stock location to create the inventory items in. Alternatively, you can [create a stock location](undefined/references/medusa-workflows/createStockLocationsWorkflow). +You start by retrieving the stock location to create the inventory items in. Alternatively, you can [create a stock location](https://docs.medusajs.com/references/medusa-workflows/createStockLocationsWorkflow/index.html.md). Then, you create the inventory items that the product variant consists of. @@ -29471,15 +29493,15 @@ export const createMultiPartProductsWorkflow = createWorkflow( ) ``` -You prepare the inventory item IDs to pass to the variant using [transform](undefined/docs/learn/fundamentals/workflows/variable-manipulation) from the Workflows SDK, then pass these IDs to the created product's variant. +You prepare the inventory item IDs to pass to the variant using [transform](https://docs.medusajs.com/docs/learn/fundamentals/workflows/variable-manipulation/index.html.md) from the Workflows SDK, then pass these IDs to the created product's variant. -You can now [execute the workflow](undefined/docs/learn/fundamentals/workflows#3-execute-the-workflow) in [API routes](undefined/docs/learn/fundamentals/api-routes), [scheduled jobs](undefined/docs/learn/fundamentals/scheduled-jobs), or [subscribers](undefined/docs/learn/fundamentals/events-and-subscribers). +You can now [execute the workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows#3-execute-the-workflow/index.html.md) in [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md), [scheduled jobs](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs/index.html.md), or [subscribers](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md). *** ## Bundled Products -While inventory kits support bundled products, some features like custom pricing for a bundle or separate fulfillment for a bundle's items are not supported. To support those features, follow the [Bundled Products](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/bundled-products/examples/standard) tutorial to learn how to customize the Medusa application to add bundled products. +While inventory kits support bundled products, some features like custom pricing for a bundle or separate fulfillment for a bundle's items are not supported. To support those features, follow the [Bundled Products](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/bundled-products/examples/standard/index.html.md) tutorial to learn how to customize the Medusa application to add bundled products. Consider you have three products: shirt, pants, and shoes. You sell those products separately, but you also want to offer them as a bundle. @@ -29493,9 +29515,9 @@ Then, when the bundled product's variant is purchased, the inventory quantity of ### Create Bundled Product -You can create a bundled product in the [Medusa Admin](undefined/user-guide/products/create/bundle) by creating the products part of the bundle first, each having its own inventory items. Then, you create the bundled product whose variant(s) have inventory kits composed of inventory items from each of the products part of the bundle. +You can create a bundled product in the [Medusa Admin](https://docs.medusajs.com/user-guide/products/create/bundle/index.html.md) by creating the products part of the bundle first, each having its own inventory items. Then, you create the bundled product whose variant(s) have inventory kits composed of inventory items from each of the products part of the bundle. -Using [workflows](undefined/docs/learn/fundamentals/workflows), you can implement this by first creating the products part of the bundle: +Using [workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), you can implement this by first creating the products part of the bundle: ```ts highlights={bundledHighlights1} import { @@ -29643,7 +29665,7 @@ export const createBundledProducts = createWorkflow( ) ``` -Using [Query](undefined/docs/learn/fundamentals/module-links/query), you retrieve the product again with the inventory items of each variant. Then, you prepare the inventory items to pass to the bundled product's variant. +Using [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), you retrieve the product again with the inventory items of each variant. Then, you prepare the inventory items to pass to the bundled product's variant. Finally, create the bundled product: @@ -29689,7 +29711,7 @@ export const createBundledProducts = createWorkflow( The bundled product has the same inventory items as those of the products part of the bundle. -You can now [execute the workflow](undefined/docs/learn/fundamentals/workflows#3-execute-the-workflow) in [API routes](undefined/docs/learn/fundamentals/api-routes), [scheduled jobs](undefined/docs/learn/fundamentals/scheduled-jobs), or [subscribers](undefined/docs/learn/fundamentals/events-and-subscribers). +You can now [execute the workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows#3-execute-the-workflow/index.html.md) in [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md), [scheduled jobs](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs/index.html.md), or [subscribers](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md). # Links between Inventory Module and Other Modules @@ -29717,11 +29739,11 @@ Each product variant has different inventory details. Medusa defines a link betw 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. -Learn more about product variant's inventory management in [this guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product/variant-inventory). +Learn more about product variant's inventory management in [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/variant-inventory/index.html.md). ### Retrieve with Query -To retrieve the product variants of an inventory item with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `variants.*` in `fields`: +To retrieve the product variants of an inventory item with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `variants.*` in `fields`: ### query.graph @@ -29755,7 +29777,7 @@ const { data: inventoryItems } = useQueryGraphStep({ ### Manage with Link -To manage the variants of an inventory item, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the variants of an inventory item, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -29796,11 +29818,11 @@ createRemoteLinkStep({ ## Stock Location Module -Medusa defines a read-only link between the `InventoryLevel` data model and the [Stock Location Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/stock-location)'s `StockLocation` data model. This means you can retrieve the details of an inventory level's stock locations, but you don't manage the links in a pivot table in the database. The stock location of an inventory level is determined by the `location_id` property of the `InventoryLevel` data model. +Medusa defines a read-only link between the `InventoryLevel` data model and the [Stock Location Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/stock-location/index.html.md)'s `StockLocation` data model. This means you can retrieve the details of an inventory level's stock locations, but you don't manage the links in a pivot table in the database. The stock location of an inventory level is determined by the `location_id` property of the `InventoryLevel` data model. ### Retrieve with Query -To retrieve the stock locations of an inventory level with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `stock_locations.*` in `fields`: +To retrieve the stock locations of an inventory level with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `stock_locations.*` in `fields`: ### query.graph @@ -29837,25 +29859,25 @@ const { data: inventoryLevels } = useQueryGraphStep({ In this section of the documentation, you will find resources to learn more about the Inventory Module and how to use it in your application. -Refer to the [Medusa Admin User Guide](undefined/user-guide/inventory) to learn how to manage inventory and related features using the dashboard. +Refer to the [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/inventory/index.html.md) to learn how to manage inventory and related features using the dashboard. -Medusa has inventory related features available out-of-the-box through the Inventory Module. A [module](undefined/docs/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Inventory Module. +Medusa has inventory related features available out-of-the-box through the Inventory Module. A [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Inventory Module. -Learn more about why modules are isolated in [this documentation](undefined/docs/learn/fundamentals/modules/isolation). +Learn more about why modules are isolated in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md). ## Inventory Features -- [Inventory Items Management](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/inventory/concepts): Store and manage inventory of any stock-kept item, such as product variants. -- [Inventory Across Locations](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/inventory/concepts#inventorylevel): Manage inventory levels across different locations, such as warehouses. -- [Reservation Management](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/inventory/concepts#reservationitem): Reserve quantities of inventory items at specific locations for orders or other purposes. -- [Check Inventory Availability](undefined/references/inventory-next/confirmInventory): Check whether an inventory item has the necessary quantity for purchase. -- [Inventory Kits](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/inventory/inventory-kit): Create and manage inventory kits for a single product, allowing you to implement use cases like bundled or multi-part products. +- [Inventory Items Management](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/inventory/concepts/index.html.md): Store and manage inventory of any stock-kept item, such as product variants. +- [Inventory Across Locations](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/inventory/concepts#inventorylevel/index.html.md): Manage inventory levels across different locations, such as warehouses. +- [Reservation Management](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/inventory/concepts#reservationitem/index.html.md): Reserve quantities of inventory items at specific locations for orders or other purposes. +- [Check Inventory Availability](https://docs.medusajs.com/references/inventory-next/confirmInventory/index.html.md): Check whether an inventory item has the necessary quantity for purchase. +- [Inventory Kits](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/inventory/inventory-kit/index.html.md): Create and manage inventory kits for a single product, allowing you to implement use cases like bundled or multi-part products. *** ## How to Use the Inventory Module -In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](undefined/docs/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package. @@ -29972,7 +29994,7 @@ export const config = { } ``` -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). *** @@ -29981,13 +30003,13 @@ Learn more about workflows in [this documentation](undefined/docs/learn/fundamen In this guide, you'll learn about order claims. -Refer to this [Medusa Admin User Guide](undefined/user-guide/orders/claims) to learn how to manage an order's claims using the dashboard. +Refer to this [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/orders/claims/index.html.md) to learn how to manage an order's claims using the dashboard. ## What is a Claim? When a customer receives a defective or incorrect item, the merchant can create a claim to refund or replace that item. -A claim is represented by the [OrderClaim data model](undefined/references/order/models/OrderClaim). +A claim is represented by the [OrderClaim data model](https://docs.medusajs.com/references/order/models/OrderClaim/index.html.md). *** @@ -30002,19 +30024,19 @@ The `Claim` data model has a `type` property that indicates the type of claim: ## Old and Replacement Items -When you create a claim, a return is also created to handle receiving the old items from the customer. The return is represented by the [Return data model](undefined/references/order/models/Return). +When you create a claim, a return is also created to handle receiving the old items from the customer. The return is represented by the [Return data model](https://docs.medusajs.com/references/order/models/Return/index.html.md). -Refer to the [Returns](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/return) guide to learn more about returns. +Refer to the [Returns](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/return/index.html.md) guide to learn more about returns. -If the claim's type is `replace`, the replacement items are represented by the [ClaimItem data model](undefined/references/order/models/OrderClaimItem). +If the claim's type is `replace`, the replacement items are represented by the [ClaimItem data model](https://docs.medusajs.com/references/order/models/OrderClaimItem/index.html.md). *** ## Claim Shipping Methods -A claim uses shipping methods to send replacement items to the customer. These methods are represented by the [OrderShippingMethod data model](undefined/references/order/models/OrderShippingMethod). +A claim uses shipping methods to send replacement items to the customer. These methods are represented by the [OrderShippingMethod data model](https://docs.medusajs.com/references/order/models/OrderShippingMethod/index.html.md). -The shipping methods for returned items are linked to the claim's return, as explained in the [Returns](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/return#return-shipping-methods) guide. +The shipping methods for returned items are linked to the claim's return, as explained in the [Returns](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/return#return-shipping-methods/index.html.md) guide. *** @@ -30022,7 +30044,7 @@ The shipping methods for returned items are linked to the claim's return, as exp If the claim's type is `refund`, the refund amount is stored in the `refund_amount` property. -The [Transaction data model](undefined/references/order/models/OrderTransaction) represents the refunds made for the claim. +The [Transaction data model](https://docs.medusajs.com/references/order/models/OrderTransaction/index.html.md) represents the refunds made for the claim. *** @@ -30030,7 +30052,7 @@ The [Transaction data model](undefined/references/order/models/OrderTransaction) When you confirm a claim, the order's version increases. -Learn more about order versions in the [Order Versioning](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/order-versioning) guide. +Learn more about order versions in the [Order Versioning](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/order-versioning/index.html.md) guide. # Order Concepts @@ -30039,26 +30061,26 @@ In this document, you’ll learn about orders and related concepts ## Order -An order is a purchase made by a customer, either through the storefront or through the API. It is represented by the [Order data model](undefined/references/order/models/Order). +An order is a purchase made by a customer, either through the storefront or through the API. It is represented by the [Order data model](https://docs.medusajs.com/references/order/models/Order/index.html.md). An order holds information about: - The purchased items. - The customer who made the order. - - This is stored and handled by the [Customer Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/customer). + - This is stored and handled by the [Customer Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/customer/index.html.md). - Payment and shipping information *** ## Order Items -The items purchased in an order are represented by the [OrderItem data model](undefined/references/order/models/OrderItem). An order can have multiple items. +The items purchased in an order are represented by the [OrderItem data model](https://docs.medusajs.com/references/order/models/OrderItem/index.html.md). An order can have multiple items. ![A diagram showcasing the relation between an order and its items.](https://res.cloudinary.com/dza7lstvk/image/upload/v1712304722/Medusa%20Resources/order-order-items_uvckxd.jpg) ### Item’s Product Details -The details of the purchased products are represented by the [LineItem data model](undefined/references/order/models/OrderLineItem). Not only does a line item hold the details of the product, but also details related to its price, adjustments due to promotions, and taxes. +The details of the purchased products are represented by the [LineItem data model](https://docs.medusajs.com/references/order/models/OrderLineItem/index.html.md). Not only does a line item hold the details of the product, but also details related to its price, adjustments due to promotions, and taxes. *** @@ -30066,7 +30088,7 @@ The details of the purchased products are represented by the [LineItem data mode An order has one or more shipping methods used to handle item shipment. -Each shipping method is represented by the [OrderShippingMethod data model](undefined/references/order/models/OrderShippingMethod) that holds its details. The shipping method is linked to the order through the [OrderShipping data model](undefined/references/order/models/OrderShipping). +Each shipping method is represented by the [OrderShippingMethod data model](https://docs.medusajs.com/references/order/models/OrderShippingMethod/index.html.md) that holds its details. The shipping method is linked to the order through the [OrderShipping data model](https://docs.medusajs.com/references/order/models/OrderShipping/index.html.md). ![A diagram showcasing the relation between an order and its items.](https://res.cloudinary.com/dza7lstvk/image/upload/v1719570409/Medusa%20Resources/order-shipping-method_tkggvd.jpg) @@ -30082,19 +30104,19 @@ The Medusa application passes the `data` property to the Fulfillment Module when ## Order Totals -An order’s total amounts (including tax total, total after an item is returned, etc…) are represented by the [OrderSummary data model](undefined/references/order/models/OrderSummary). +An order’s total amounts (including tax total, total after an item is returned, etc…) are represented by the [OrderSummary data model](https://docs.medusajs.com/references/order/models/OrderSummary/index.html.md). -Refer to the [Retrieve Order Totals](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/order-totals) guide to learn how to retrieve an order’s totals. +Refer to the [Retrieve Order Totals](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/order-totals/index.html.md) guide to learn how to retrieve an order’s totals. *** ## Order Payments -Payments made on an order, whether they’re capture or refund payments, are recorded as transactions represented by the [OrderTransaction data model](undefined/references/order/models/OrderTransaction). +Payments made on an order, whether they’re capture or refund payments, are recorded as transactions represented by the [OrderTransaction data model](https://docs.medusajs.com/references/order/models/OrderTransaction/index.html.md). An order can have multiple transactions. The sum of these transactions must be equal to the order summary’s total. Otherwise, there’s an outstanding amount. -Refer to the [Transactions](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/transactions) guide to learn more. +Refer to the [Transactions](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/transactions/index.html.md) guide to learn more. # Draft Orders Plugin @@ -30113,11 +30135,11 @@ The Draft Orders Plugin is especially useful for handling customer support scena ### Features -- [Create draft orders from the Medusa Admin.](undefined/user-guide/orders/draft-orders/create) -- [Manage items in a draft order, allowing admin users to add, update, or remove items](undefined/user-guide/orders/draft-orders/manage#manage-draft-orders-items). -- [Add shipping methods to draft orders.](undefined/user-guide/orders/draft-orders/manage#manage-draft-orders-shipping-methods). -- [Associate existing customers with draft orders.](undefined/user-guide/orders/draft-orders/manage#manage-draft-orders-customer-details). -- [Convert draft orders to regular orders.](undefined/user-guide/orders/draft-orders/manage#convert-draft-order-to-regular-order). +- [Create draft orders from the Medusa Admin.](https://docs.medusajs.com/user-guide/orders/draft-orders/create/index.html.md) +- [Manage items in a draft order, allowing admin users to add, update, or remove items](https://docs.medusajs.com/user-guide/orders/draft-orders/manage#manage-draft-orders-items/index.html.md). +- [Add shipping methods to draft orders.](https://docs.medusajs.com/user-guide/orders/draft-orders/manage#manage-draft-orders-shipping-methods/index.html.md). +- [Associate existing customers with draft orders.](https://docs.medusajs.com/user-guide/orders/draft-orders/manage#manage-draft-orders-customer-details/index.html.md). +- [Convert draft orders to regular orders.](https://docs.medusajs.com/user-guide/orders/draft-orders/manage#convert-draft-order-to-regular-order/index.html.md). *** @@ -30129,7 +30151,7 @@ For earlier versions, you can install the plugin manually. ### Prerequisites -- [Medusa application >= v2.4.0](undefined/docs/learn/installation) +- [Medusa application >= v2.4.0](https://docs.medusajs.com/docs/learn/installation/index.html.md) To install the Draft Orders Plugin: @@ -30167,24 +30189,24 @@ If you open the Medusa Admin at `localhost:9000/app` and log in, you'll find an ## Draft Orders User Guides -To learn how to use the draft order features in the Medusa Admin, refer to the [Draft Orders](undefined/user-guide/orders/draft-orders) user guides. +To learn how to use the draft order features in the Medusa Admin, refer to the [Draft Orders](https://docs.medusajs.com/user-guide/orders/draft-orders/index.html.md) user guides. *** ## How Draft Orders Work -A draft order is stored in the database as a regular order. It is represented by the [Order data model](undefined/references/order/models/Order) with the following properties: +A draft order is stored in the database as a regular order. It is represented by the [Order data model](https://docs.medusajs.com/references/order/models/Order/index.html.md) with the following properties: - `status`: Set to `draft` to indicate that the order is a draft. - `is_draft_order`: Set to `true` to indicate that the order is a draft order. -So, the same [order concepts](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/concepts) apply to draft orders as well. +So, the same [order concepts](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/concepts/index.html.md) apply to draft orders as well. ### Editing Draft Orders -Similar to regular orders, draft orders can be [edited](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/edit), allowing admin users to add, update, or remove items, as well as add shipping methods. +Similar to regular orders, draft orders can be [edited](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/edit/index.html.md), allowing admin users to add, update, or remove items, as well as add shipping methods. -When the order edit is confirmed on the draft order, the changes are applied directly to the draft order and its [version](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/order-versioning) is incremented. +When the order edit is confirmed on the draft order, the changes are applied directly to the draft order and its [version](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/order-versioning/index.html.md) is incremented. ### Converting Draft Orders to Regular Orders @@ -30200,13 +30222,13 @@ Admin users can then manage the order like any other regular order, including pr In this guide, you'll learn about order edits. -Refer to this [Medusa Admin User Guide](undefined/user-guide/orders/edit) to learn how to edit an order's items using the dashboard. +Refer to this [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/orders/edit/index.html.md) to learn how to edit an order's items using the dashboard. ## What is an Order Edit? A merchant can edit an order to add new items or change the quantity of existing items. -An order edit is represented by the [OrderChange data model](undefined/references/order/models/OrderChange). +An order edit is represented by the [OrderChange data model](https://docs.medusajs.com/references/order/models/OrderChange/index.html.md). The `OrderChange` data model is associated with any type of change, including returns or exchanges. However, its `change_type` property distinguishes the type of change being made. @@ -30216,9 +30238,9 @@ For order edits, the `OrderChange`'s `change_type` is `edit`. ## Add Items in an Order Edit -When the merchant adds new items to the order in the order edit, the item is added as an [OrderItem](https://docs.medusajs.com/references/order/models/OrderItem/index.html.md). +When a merchant adds new items to an order during editing, the item is added as an [OrderItem](https://docs.medusajs.com/references/order/models/OrderItem/index.html.md). -Also, an `OrderChangeAction` is created. The [OrderChangeAction data model](https://docs.medusajs.com/references/order/models/OrderChangeAction/index.html.md) represents a change made by an `OrderChange`, such as an item added. +Additionally, an `OrderChangeAction` is created. The [OrderChangeAction data model](https://docs.medusajs.com/references/order/models/OrderChangeAction/index.html.md) represents a change made by an `OrderChange`, such as adding an item. When an item is added, an `OrderChangeAction` is created with the type `ITEM_ADD`. Its `details` property stores the item's ID, price, and quantity. @@ -30236,7 +30258,7 @@ This change is recorded as an `OrderChangeAction` with the type `ITEM_UPDATE`. I Adding new items to the order requires adding shipping methods for those items. -These shipping methods are represented by the [OrderShippingMethod data model](https://docs.medusajs.com/references/order/models/OrderItem/index.html.md). Also, an `OrderChangeAction` is created with the type `SHIPPING_ADD` +These shipping methods are represented by the [OrderShippingMethod data model](https://docs.medusajs.com/references/order/models/OrderShippingMethod/index.html.md). Also, an `OrderChangeAction` is created with the type `SHIPPING_ADD`. *** @@ -30250,14 +30272,14 @@ When an order edit is confirmed, the order’s [version](https://docs.medusajs.c Once the order edit is confirmed, any additional payment or refund required can be made on the original order. -This is determined by the comparison between the `OrderSummary` and the order's transactions, as mentioned in [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/transactions#checking-outstanding-amount/index.html.md). +This is determined by the comparison between the `OrderSummary` and the order's transactions, as mentioned in the [Transactions guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/transactions#checking-outstanding-amount/index.html.md). # Order Exchange In this guide, you’ll learn about order exchanges. -Refer to this [Medusa Admin User Guide](undefined/user-guide/orders/exchanges) to learn how to manage an order's exchanges using the dashboard. +Refer to this [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/orders/exchanges/index.html.md) to learn how to manage an order's exchanges using the dashboard. ## What is an Exchange? @@ -30265,25 +30287,25 @@ An exchange is the replacement of an item that the customer ordered with another A merchant creates the exchange, specifying which items to return and which new items to send. -The [OrderExchange data model](undefined/references/order/models/OrderExchange) represents an exchange. +The [OrderExchange data model](https://docs.medusajs.com/references/order/models/OrderExchange/index.html.md) represents an exchange. *** ## Returned and New Items -When the exchange is created, a return, represented by the [Return data model](https://docs.medusajs.com/references/order/models/Return/index.html.md), is created to handle receiving the items back from the customer. +When an exchange is created, a return, represented by the [Return data model](https://docs.medusajs.com/references/order/models/Return/index.html.md), is also created to handle receiving the items back from the customer. -Learn more about returns in [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/return/index.html.md). +Refer to the [Returns guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/return/index.html.md) to learn more about returns and how they work. -The [OrderExchangeItem data model](https://docs.medusajs.com/references/order/models/OrderExchangeItem/index.html.md) represents the new items to be sent to the customer. +The [OrderExchangeItem data model](https://docs.medusajs.com/references/order/models/OrderExchangeItem/index.html.md) represents the new items to be sent to the customer. It's associated with the `OrderExchange` data model. *** ## Exchange Shipping Methods -An exchange has shipping methods used to send the new items to the customer. They’re represented by the [OrderShippingMethod data model](undefined/references/order/models/OrderShippingMethod). +An exchange has shipping methods used to send the new items to the customer. They’re represented by the [OrderShippingMethod data model](https://docs.medusajs.com/references/order/models/OrderShippingMethod/index.html.md). -The shipping methods for the returned items are associated with the exchange's return, as explained in [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/return#return-shipping-methods/index.html.md). +The shipping methods for the returned items are associated with the exchange's return, as explained in the [Returns guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/return#return-shipping-methods/index.html.md). *** @@ -30297,7 +30319,7 @@ The `OrderExchange` data model has a `difference_due` property that stores the o |\`difference\_due > 0\`|The merchant requires additional payment from the customer of the | |\`difference\_due = 0\`|No payment processing is required.| -Any payment or refund made is stored in the [Transaction data model](https://docs.medusajs.com/references/order/models/OrderTransaction/index.html.md). +Any payments or refunds made are stored in the [OrderTransaction data model](https://docs.medusajs.com/references/order/models/OrderTransaction/index.html.md). *** @@ -30334,11 +30356,11 @@ Read-only links are used to query data across modules, but the relations aren't ## Customer Module -Medusa defines a read-only link between the `Order` data model and the [Customer Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/customer)'s `Customer` data model. This means you can retrieve the details of an order's customer, but you don't manage the links in a pivot table in the database. The customer of an order is determined by the `customer_id` property of the `Order` data model. +Medusa defines a read-only link between the `Order` data model and the [Customer Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/customer/index.html.md)'s `Customer` data model. This means you can retrieve the details of an order's customer, but you don't manage the links in a pivot table in the database. The customer of an order is determined by the `customer_id` property of the `Order` data model. ### Retrieve with Query -To retrieve the customer of an order with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `customer.*` in `fields`: +To retrieve the customer of an order with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `customer.*` in `fields`: ### query.graph @@ -30374,7 +30396,7 @@ const { data: orders } = useQueryGraphStep({ ## Cart Module -The [Cart Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/cart) provides cart-management features. +The [Cart Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/cart/index.html.md) provides cart-management features. Medusa defines a link between the `Order` and `Cart` data models. The order is linked to the cart used for the purchased. @@ -30382,7 +30404,7 @@ Medusa defines a link between the `Order` and `Cart` data models. The order is l ### Retrieve with Query -To retrieve the cart of an order with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `cart.*` in `fields`: +To retrieve the cart of an order with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `cart.*` in `fields`: ### query.graph @@ -30416,7 +30438,7 @@ const { data: orders } = useQueryGraphStep({ ### Manage with Link -To manage the cart of an order, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the cart of an order, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -30467,7 +30489,7 @@ A fulfillment is also created for a return's items. So, Medusa defines a link be ### Retrieve with Query -To retrieve the fulfillments of an order with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `fulfillments.*` in `fields`: +To retrieve the fulfillments of an order with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `fulfillments.*` in `fields`: To retrieve the fulfillments of a return, pass `fulfillments.*` in `fields`. @@ -30503,7 +30525,7 @@ const { data: orders } = useQueryGraphStep({ ### Manage with Link -To manage the fulfillments of an order, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the fulfillments of an order, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -30552,7 +30574,7 @@ So, Medusa defines links between the `PaymentCollection` data model and the `Ord ### Retrieve with Query -To retrieve the payment collections of an order, order exchange, or order claim with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `payment_collections.*` in `fields`: +To retrieve the payment collections of an order, order exchange, or order claim with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `payment_collections.*` in `fields`: ### query.graph @@ -30586,7 +30608,7 @@ const { data: orders } = useQueryGraphStep({ ### Manage with Link -To manage the payment collections of an order, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the payment collections of an order, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -30629,12 +30651,12 @@ createRemoteLinkStep({ Medusa defines read-only links between: -- the `OrderLineItem` data model and the [Product Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product)'s `Product` data model. This means you can retrieve the details of a line item's product, but you don't manage the links in a pivot table in the database. The product of a line item is determined by the `product_id` property of the `OrderLineItem` data model. -- the `OrderLineItem` data model and the [Product Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product)'s `ProductVariant` data model. This means you can retrieve the details of a line item's variant, but you don't manage the links in a pivot table in the database. The variant of a line item is determined by the `variant_id` property of the `OrderLineItem` data model. +- the `OrderLineItem` data model and the [Product Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/index.html.md)'s `Product` data model. This means you can retrieve the details of a line item's product, but you don't manage the links in a pivot table in the database. The product of a line item is determined by the `product_id` property of the `OrderLineItem` data model. +- the `OrderLineItem` data model and the [Product Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/index.html.md)'s `ProductVariant` data model. This means you can retrieve the details of a line item's variant, but you don't manage the links in a pivot table in the database. The variant of a line item is determined by the `variant_id` property of the `OrderLineItem` data model. ### Retrieve with Query -To retrieve the variant of a line item with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `variant.*` in `fields`: +To retrieve the variant of a line item with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `variant.*` in `fields`: To retrieve the product, pass `product.*` in `fields`. @@ -30678,7 +30700,7 @@ An order is associated with the promotion applied on it. Medusa defines a link b ### Retrieve with Query -To retrieve the promotion applied on an order with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `promotion.*` in `fields`: +To retrieve the promotion applied on an order with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `promotion.*` in `fields`: ### query.graph @@ -30712,7 +30734,7 @@ const { data: orders } = useQueryGraphStep({ ### Manage with Link -To manage the promotion of an order, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the promotion of an order, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -30753,11 +30775,11 @@ createRemoteLinkStep({ ## Region Module -Medusa defines a read-only link between the `Order` data model and the [Region Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/region)'s `Region` data model. This means you can retrieve the details of an order's region, but you don't manage the links in a pivot table in the database. The region of an order is determined by the `region_id` property of the `Order` data model. +Medusa defines a read-only link between the `Order` data model and the [Region Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/region/index.html.md)'s `Region` data model. This means you can retrieve the details of an order's region, but you don't manage the links in a pivot table in the database. The region of an order is determined by the `region_id` property of the `Order` data model. ### Retrieve with Query -To retrieve the region of an order with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `region.*` in `fields`: +To retrieve the region of an order with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `region.*` in `fields`: ### query.graph @@ -30793,11 +30815,11 @@ const { data: orders } = useQueryGraphStep({ ## Sales Channel Module -Medusa defines a read-only link between the `Order` data model and the [Sales Channel Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/sales-channel)'s `SalesChannel` data model. This means you can retrieve the details of an order's sales channel, but you don't manage the links in a pivot table in the database. The sales channel of an order is determined by the `sales_channel_id` property of the `Order` data model. +Medusa defines a read-only link between the `Order` data model and the [Sales Channel Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/sales-channel/index.html.md)'s `SalesChannel` data model. This means you can retrieve the details of an order's sales channel, but you don't manage the links in a pivot table in the database. The sales channel of an order is determined by the `sales_channel_id` property of the `Order` data model. ### Retrieve with Query -To retrieve the sales channel of an order with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `sales_channel.*` in `fields`: +To retrieve the sales channel of an order with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `sales_channel.*` in `fields`: ### query.graph @@ -30836,14 +30858,14 @@ In this document, you'll learn what an order change is and the related concepts. ## OrderChange Data Model -The [OrderChange data model](undefined/references/order/models/OrderChange) represents any kind of change to an order, such as a [return](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/return), [exchange](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/exchange), or [edit](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/edit). Each of these is essentially an order change that is confirmed to apply changes to the original order. +The [OrderChange data model](https://docs.medusajs.com/references/order/models/OrderChange/index.html.md) represents any kind of change to an order, such as a [return](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/return/index.html.md), [exchange](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/exchange/index.html.md), or [edit](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/edit/index.html.md). Each of these is essentially an order change that is confirmed to apply changes to the original order. The `OrderChange` model's `change_type` property indicates the purpose of the order change: -1. `edit`: The order change is making edits to the order, as explained in the [Order Edit](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/edit) guide. -2. `exchange`: The order change is associated with an exchange, which you can learn about in the [Order Exchange](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/exchange) guide. -3. `claim`: The order change is associated with a claim, which you can learn about in the [Order Claim](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/claim) guide. -4. `return_request` or `return_receive`: The order change is associated with a return, which you can learn about in the [Order Return](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/return) guide. +1. `edit`: The order change is making edits to the order, as explained in the [Order Edit](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/edit/index.html.md) guide. +2. `exchange`: The order change is associated with an exchange, which you can learn about in the [Order Exchange](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/exchange/index.html.md) guide. +3. `claim`: The order change is associated with a claim, which you can learn about in the [Order Claim](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/claim/index.html.md) guide. +4. `return_request` or `return_receive`: The order change is associated with a return, which you can learn about in the [Order Return](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/return/index.html.md) guide. Once the order change is confirmed, its changes are applied to the order. @@ -30851,7 +30873,7 @@ Once the order change is confirmed, its changes are applied to the order. ## Order Change Actions -The actions performed on the original order by an order change, such as adding an item, are represented by the [OrderChangeAction data model](undefined/references/order/models/OrderChangeAction). +The actions performed on the original order by an order change, such as adding an item, are represented by the [OrderChangeAction data model](https://docs.medusajs.com/references/order/models/OrderChangeAction/index.html.md). The `OrderChangeAction` has an `action` property that indicates the type of action to perform on the order, and a `details` property that holds additional information related to the action. @@ -30880,11 +30902,11 @@ The following table lists the possible `action` values that Medusa uses and the # Retrieve Order Totals Using Query -In this guide, you'll learn how to retrieve order totals in your Medusa application using [Query](undefined/docs/learn/fundamentals/module-links/query). +In this guide, you'll learn how to retrieve order totals in your Medusa application using [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md). You may need to retrieve order totals in your Medusa customizations, such as workflows or custom API routes, to perform custom actions with them. The ideal way to retrieve totals is using Query. -Refer to the [Order Confirmation in Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development/checkout/order-confirmation#show-order-totals) guide for a storefront-specific approach. +Refer to the [Order Confirmation in Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/checkout/order-confirmation#show-order-totals/index.html.md) guide for a storefront-specific approach. ## How to Retrieve Order Totals with Query @@ -31245,25 +31267,25 @@ When the order is retrieved, only the related data with the same version is retu In this section of the documentation, you will find resources to learn more about the Order Module and how to use it in your application. -Refer to the [Medusa Admin User Guide](undefined/user-guide/orders) to learn how to manage orders using the dashboard. +Refer to the [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/orders/index.html.md) to learn how to manage orders using the dashboard. -Medusa has order related features available out-of-the-box through the Order Module. A [module](undefined/docs/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Order Module. +Medusa has order related features available out-of-the-box through the Order Module. A [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Order Module. -Learn more about why modules are isolated in [this documentation](undefined/docs/learn/fundamentals/modules/isolation). +Learn more about why modules are isolated in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md). ## Order Features -- [Order Management](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/concepts): Store and manage your orders to retrieve, create, cancel, and perform other operations. -- [Draft Orders](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/draft-orders): Allow merchants to create orders on behalf of their customers as draft orders that later are transformed to regular orders. -- [Apply Promotion Adjustments](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/promotion-adjustments): Apply promotions or discounts to the order's items and shipping methods by adding adjustment lines that are factored into their subtotals. -- [Apply Tax Lines](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/tax-lines): Apply tax lines to an order's line items and shipping methods. -- [Returns](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/return), [Edits](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/edit), [Exchanges](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/exchange), and [Claims](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/claim): Make [changes](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/order-change) to an order to edit, return, or exchange its items, with [version-based control](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/order-versioning) over the order's timeline. +- [Order Management](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/concepts/index.html.md): Store and manage your orders to retrieve, create, cancel, and perform other operations. +- [Draft Orders](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/draft-orders/index.html.md): Allow merchants to create orders on behalf of their customers as draft orders that later are transformed to regular orders. +- [Apply Promotion Adjustments](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/promotion-adjustments/index.html.md): Apply promotions or discounts to the order's items and shipping methods by adding adjustment lines that are factored into their subtotals. +- [Apply Tax Lines](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/tax-lines/index.html.md): Apply tax lines to an order's line items and shipping methods. +- [Returns](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/return/index.html.md), [Edits](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/edit/index.html.md), [Exchanges](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/exchange/index.html.md), and [Claims](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/claim/index.html.md): Make [changes](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/order-change/index.html.md) to an order to edit, return, or exchange its items, with [version-based control](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/order-versioning/index.html.md) over the order's timeline. *** ## How to Use the Order Module -In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](undefined/docs/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package. @@ -31392,7 +31414,7 @@ export const config = { } ``` -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). *** @@ -31405,7 +31427,7 @@ In this document, you’ll learn how a promotion is applied to an order’s item An adjustment line indicates a change to a line item or a shipping method’s amount. It’s used to apply promotions or discounts on an order. -The [OrderLineItemAdjustment data model](undefined/references/order/models/OrderLineItemAdjustment) represents changes on a line item, and the [OrderShippingMethodAdjustment data model](undefined/references/order/models/OrderShippingMethodAdjustment) represents changes on a shipping method. +The [OrderLineItemAdjustment data model](https://docs.medusajs.com/references/order/models/OrderLineItemAdjustment/index.html.md) represents changes on a line item, and the [OrderShippingMethodAdjustment data model](https://docs.medusajs.com/references/order/models/OrderShippingMethodAdjustment/index.html.md) represents changes on a shipping method. ![A diagram showcasing the relation between an order, its items and shipping methods, and their adjustment lines](https://res.cloudinary.com/dza7lstvk/image/upload/v1712306017/Medusa%20Resources/order-adjustments_myflir.jpg) @@ -31425,9 +31447,9 @@ When disabled, a promotion can’t be applied to a line item. In the context of ## Promotion Actions -When using the Order and Promotion modules together, use the [computeActions method of the Promotion Module’s main service](undefined/references/promotion/computeActions). It retrieves the actions of line items and shipping methods. +When using the Order and Promotion modules together, use the [computeActions method of the Promotion Module’s main service](https://docs.medusajs.com/references/promotion/computeActions/index.html.md). It retrieves the actions of line items and shipping methods. -Learn more about actions in the [Promotion Module’s documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/promotion/actions). +Learn more about actions in the [Promotion Module’s documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/promotion/actions/index.html.md). ```ts collapsibleLines="1-10" expandButtonLabel="Show Imports" import { @@ -31523,11 +31545,11 @@ await orderModuleService.setOrderShippingMethodAdjustments( In this document, you’ll learn about order returns. -Refer to this [Medusa Admin User Guide](undefined/user-guide/orders/returns) to learn how to manage an order's returns using the dashboard. +Refer to this [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/orders/returns/index.html.md) to learn how to manage an order's returns using the dashboard. ## What is a Return? -A return is the return of items delivered from the customer back to the merchant. It is represented by the [Return data model](undefined/references/order/models/Return). +A return is the return of items delivered from the customer back to the merchant. It is represented by the [Return data model](https://docs.medusajs.com/references/order/models/Return/index.html.md). A return is requested either by the customer from the storefront, or the merchant from the admin. Medusa supports an automated Return Merchandise Authorization (RMA) flow. @@ -31539,7 +31561,7 @@ Once the merchant receives the returned items, they mark the return as received. ## Returned Items -The items to be returned are represented by the [ReturnItem data model](undefined/references/order/models/ReturnItem). +The items to be returned are represented by the [ReturnItem data model](https://docs.medusajs.com/references/order/models/ReturnItem/index.html.md). The `ReturnItem` model has two properties storing the item's quantity: @@ -31550,7 +31572,7 @@ The `ReturnItem` model has two properties storing the item's quantity: ## Return Shipping Methods -A return has shipping methods used to return the items to the merchant. The shipping methods are represented by the [OrderShippingMethod data model](undefined/references/order/models/OrderShippingMethod). +A return has shipping methods used to return the items to the merchant. The shipping methods are represented by the [OrderShippingMethod data model](https://docs.medusajs.com/references/order/models/OrderShippingMethod/index.html.md). In the Medusa application, the shipping method for a return is created only from a shipping option, provided by the Fulfillment Module, that has the rule `is_return` enabled. @@ -31560,7 +31582,7 @@ In the Medusa application, the shipping method for a return is created only from The `refund_amount` property of the `Return` data model holds the amount a merchant must refund the customer. -The [OrderTransaction data model](undefined/references/order/models/OrderTransaction) represents the refunds made for the return. +The [OrderTransaction data model](https://docs.medusajs.com/references/order/models/OrderTransaction/index.html.md) represents the refunds made for the return. *** @@ -31588,7 +31610,7 @@ In this document, you’ll learn about tax lines in an order. A tax line indicates the tax rate of a line item or a shipping method. -The [OrderLineItemTaxLine data model](undefined/references/order/models/OrderLineItemTaxLine) represents a line item’s tax line, and the [OrderShippingMethodTaxLine data model](undefined/references/order/models/OrderShippingMethodTaxLine) represents a shipping method’s tax line. +The [OrderLineItemTaxLine data model](https://docs.medusajs.com/references/order/models/OrderLineItemTaxLine/index.html.md) represents a line item’s tax line, and the [OrderShippingMethodTaxLine data model](https://docs.medusajs.com/references/order/models/OrderShippingMethodTaxLine/index.html.md) represents a shipping method’s tax line. ![A diagram showcasing the relation between orders, items and shipping methods, and tax lines](https://res.cloudinary.com/dza7lstvk/image/upload/v1712307225/Medusa%20Resources/order-tax-lines_sixujd.jpg) @@ -31615,7 +31637,7 @@ In this guide, you’ll learn about order transactions, how to check an order’ ## What is a Transaction? -A transaction represents any order payment process, such as capturing or refunding an amount. It’s represented by the [OrderTransaction data model](undefined/references/order/models/OrderTransaction). +A transaction represents any order payment process, such as capturing or refunding an amount. It’s represented by the [OrderTransaction data model](https://docs.medusajs.com/references/order/models/OrderTransaction/index.html.md). The transaction’s main purpose is to ensure a correct balance between paid and outstanding amounts. @@ -31649,7 +31671,7 @@ To check the outstanding amount of an order, the transaction amounts from the `T ## Transaction Reference -The Order Module doesn’t provide payment processing functionalities, so it doesn’t store payments that can be processed. Payment functionalities are provided by the [Payment Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment). +The Order Module doesn’t provide payment processing functionalities, so it doesn’t store payments that can be processed. Payment functionalities are provided by the [Payment Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/index.html.md). The `OrderTransaction` data model has two properties that determine which data model and record holds the actual payment’s details: @@ -31698,24 +31720,24 @@ A Commerce Module also defines data models, representing tables in the database. ## Commerce Modules List -- [API Key Module](undefined/commerce-modules/api-key) -- [Auth Module](undefined/commerce-modules/auth) -- [Cart Module](undefined/commerce-modules/cart) -- [Currency Module](undefined/commerce-modules/currency) -- [Customer Module](undefined/commerce-modules/customer) -- [Fulfillment Module](undefined/commerce-modules/fulfillment) -- [Inventory Module](undefined/commerce-modules/inventory) -- [Order Module](undefined/commerce-modules/order) -- [Payment Module](undefined/commerce-modules/payment) -- [Pricing Module](undefined/commerce-modules/pricing) -- [Product Module](undefined/commerce-modules/product) -- [Promotion Module](undefined/commerce-modules/promotion) -- [Region Module](undefined/commerce-modules/region) -- [Sales Channel Module](undefined/commerce-modules/sales-channel) -- [Stock Location Module](undefined/commerce-modules/stock-location) -- [Store Module](undefined/commerce-modules/store) -- [Tax Module](undefined/commerce-modules/tax) -- [User Module](undefined/commerce-modules/user) +- [API Key Module](https://docs.medusajs.com/commerce-modules/api-key/index.html.md) +- [Auth Module](https://docs.medusajs.com/commerce-modules/auth/index.html.md) +- [Cart Module](https://docs.medusajs.com/commerce-modules/cart/index.html.md) +- [Currency Module](https://docs.medusajs.com/commerce-modules/currency/index.html.md) +- [Customer Module](https://docs.medusajs.com/commerce-modules/customer/index.html.md) +- [Fulfillment Module](https://docs.medusajs.com/commerce-modules/fulfillment/index.html.md) +- [Inventory Module](https://docs.medusajs.com/commerce-modules/inventory/index.html.md) +- [Order Module](https://docs.medusajs.com/commerce-modules/order/index.html.md) +- [Payment Module](https://docs.medusajs.com/commerce-modules/payment/index.html.md) +- [Pricing Module](https://docs.medusajs.com/commerce-modules/pricing/index.html.md) +- [Product Module](https://docs.medusajs.com/commerce-modules/product/index.html.md) +- [Promotion Module](https://docs.medusajs.com/commerce-modules/promotion/index.html.md) +- [Region Module](https://docs.medusajs.com/commerce-modules/region/index.html.md) +- [Sales Channel Module](https://docs.medusajs.com/commerce-modules/sales-channel/index.html.md) +- [Stock Location Module](https://docs.medusajs.com/commerce-modules/stock-location/index.html.md) +- [Store Module](https://docs.medusajs.com/commerce-modules/store/index.html.md) +- [Tax Module](https://docs.medusajs.com/commerce-modules/tax/index.html.md) +- [User Module](https://docs.medusajs.com/commerce-modules/user/index.html.md) *** @@ -31747,11 +31769,11 @@ A payment provider that supports saving payment methods for customers would crea ### Relation between Account Holder and Customer -The Medusa application creates a link between the [Customer](undefined/references/customer/models/Customer) data model of the [Customer Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/customer) and the `AccountHolder` data model of the Payment Module. +The Medusa application creates a link between the [Customer](https://docs.medusajs.com/references/customer/models/Customer/index.html.md) data model of the [Customer Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/customer/index.html.md) and the `AccountHolder` data model of the Payment Module. This link indicates that a customer can have more than one account holder, each representing saved payment methods in different payment providers. -Learn more about this link in the [Link to Other Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/links-to-other-modules) guide. +Learn more about this link in the [Link to Other Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/links-to-other-modules/index.html.md) guide. *** @@ -31764,7 +31786,7 @@ If a payment provider supports saving payment methods for a customer, they must - `savePaymentMethod`: Saves a payment method for an account holder in the payment provider. - `listPaymentMethods`: Lists saved payment methods in the third-party service for an account holder. This is useful when displaying the customer's saved payment methods in the storefront. -Learn more about implementing these methods in the [Create Payment Provider guide](undefined/references/payment/provider). +Learn more about implementing these methods in the [Create Payment Provider guide](https://docs.medusajs.com/references/payment/provider/index.html.md). *** @@ -31802,11 +31824,11 @@ The Cart Module provides cart-related features, but not payment processing. Medusa defines a link between the `Cart` and `PaymentCollection` data models. A cart has a payment collection which holds all the authorized payment sessions and payments made related to the cart. -Learn more about this relation in [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-collection#usage-with-the-cart-module). +Learn more about this relation in [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-collection#usage-with-the-cart-module/index.html.md). ### Retrieve with Query -To retrieve the cart associated with the payment collection with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `cart.*` in `fields`: +To retrieve the cart associated with the payment collection with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `cart.*` in `fields`: ### query.graph @@ -31840,7 +31862,7 @@ const { data: paymentCollections } = useQueryGraphStep({ ### Manage with Link -To manage the payment collection of a cart, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the payment collection of a cart, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -31886,7 +31908,7 @@ This link is available starting from Medusa `v2.5.0`. ### Retrieve with Query -To retrieve the customer associated with an account holder with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `customer.*` in `fields`: +To retrieve the customer associated with an account holder with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `customer.*` in `fields`: ### query.graph @@ -31920,7 +31942,7 @@ const { data: accountHolders } = useQueryGraphStep({ ### Manage with Link -To manage the account holders of a customer, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the account holders of a customer, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -31968,7 +31990,7 @@ So, Medusa defines links between the `PaymentCollection` data model and the `Ord ### Retrieve with Query -To retrieve the order of a payment collection with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `order.*` in `fields`: +To retrieve the order of a payment collection with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `order.*` in `fields`: ### query.graph @@ -32002,7 +32024,7 @@ const { data: paymentCollections } = useQueryGraphStep({ ### Manage with Link -To manage the payment collections of an order, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the payment collections of an order, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -32051,7 +32073,7 @@ This increases the flexibility of your store. For example, you only show during ### Retrieve with Query -To retrieve the regions of a payment provider with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `regions.*` in `fields`: +To retrieve the regions of a payment provider with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `regions.*` in `fields`: ### query.graph @@ -32085,7 +32107,7 @@ const { data: paymentProviders } = useQueryGraphStep({ ### Manage with Link -To manage the payment providers in a region, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the payment providers in a region, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -32177,32 +32199,32 @@ The `providers` option is an array of objects that accept the following properti - `id`: A string indicating the provider's unique name or ID. - `options`: An optional object of the module provider's options. -Refer to the [Payment Module Providers](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider) documentation to learn more. +Refer to the [Payment Module Providers](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/index.html.md) documentation to learn more. # Payment Module In this section of the documentation, you will find resources to learn more about the Payment Module and how to use it in your application. -Refer to the [Medusa Admin User Guide](undefined/user-guide/orders/payments) to learn how to manage order payments using the dashboard. +Refer to the [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/orders/payments/index.html.md) to learn how to manage order payments using the dashboard. -Medusa has payment related features available out-of-the-box through the Payment Module. A [module](undefined/docs/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Payment Module. +Medusa has payment related features available out-of-the-box through the Payment Module. A [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Payment Module. -Learn more about why modules are isolated in [this documentation](undefined/docs/learn/fundamentals/modules/isolation). +Learn more about why modules are isolated in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md). ## Payment Features -- [Authorize, Capture, and Refund Payments](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment): Authorize, capture, and refund payments for a single resource. -- [Payment Collection Management](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-collection): Store and manage all payments of a single resources, such as a cart, in payment collections. -- [Integrate Third-Party Payment Providers](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider): Use payment providers like [Stripe](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe) to handle and process payments, or integrate custom payment providers. -- [Saved Payment Methods](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/account-holder): Save payment methods for customers in third-party payment providers. -- [Handle Webhook Events](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/webhook-events): Handle webhook events from third-party providers and process the associated payment. +- [Authorize, Capture, and Refund Payments](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment/index.html.md): Authorize, capture, and refund payments for a single resource. +- [Payment Collection Management](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-collection/index.html.md): Store and manage all payments of a single resources, such as a cart, in payment collections. +- [Integrate Third-Party Payment Providers](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/index.html.md): Use payment providers like [Stripe](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe/index.html.md) to handle and process payments, or integrate custom payment providers. +- [Saved Payment Methods](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/account-holder/index.html.md): Save payment methods for customers in third-party payment providers. +- [Handle Webhook Events](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/webhook-events/index.html.md): Handle webhook events from third-party providers and process the associated payment. *** ## How to Use the Payment Module -In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](undefined/docs/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package. @@ -32318,13 +32340,13 @@ export const config = { } ``` -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). *** ## Configure Payment Module -The Payment Module accepts options for further configurations. Refer to [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/module-options) for details on the module's options. +The Payment Module accepts options for further configurations. Refer to [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/module-options/index.html.md) for details on the module's options. *** @@ -32349,12 +32371,12 @@ The payment flow consists of the following steps: ![A diagram showcasing the payment flow's steps](https://res.cloudinary.com/dza7lstvk/image/upload/v1711566781/Medusa%20Resources/payment-flow_jblrvw.jpg) -- [Create Payment Collection](undefined/api/store#payment-collections_postpaymentcollections): Create a payment collection associated with a cart. +- [Create Payment Collection](https://docs.medusajs.com/api/store#payment-collections_postpaymentcollections): Create a payment collection associated with a cart. - This payment collection will hold all details related to the payment operations. -- [Show Payment Providers](undefined/api/store#payment-providers_getpaymentproviders): Show the customer the available payment providers to choose from. - - You can integrate any [payment provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider), and you can enable them per region. -- [Create and Initialize Payment Session](undefined/api/store#payment-collections_postpaymentcollectionsidpaymentsessions): Create a payment session for the selected payment provider in the Medusa application, and initialize the session in the third-party payment provider. -- [Complete Cart](undefined/api/store#carts_postcartsidcomplete): Once the customer places the order, complete the cart, which involves: +- [Show Payment Providers](https://docs.medusajs.com/api/store#payment-providers_getpaymentproviders): Show the customer the available payment providers to choose from. + - You can integrate any [payment provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/index.html.md), and you can enable them per region. +- [Create and Initialize Payment Session](https://docs.medusajs.com/api/store#payment-collections_postpaymentcollectionsidpaymentsessions): Create a payment session for the selected payment provider in the Medusa application, and initialize the session in the third-party payment provider. +- [Complete Cart](https://docs.medusajs.com/api/store#carts_postcartsidcomplete): Once the customer places the order, complete the cart, which involves: - Authorizing the payment session with the third-party payment provider. - If the third-party payment provider requires performing additional actions, show them to the customer, then retry cart completion. @@ -32362,9 +32384,9 @@ The payment flow consists of the following steps: ## Implement Payment Checkout Step in Storefront -If you're using the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), the checkout flow is already implemented with the payment step. +If you're using the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), the checkout flow is already implemented with the payment step. -If you're building a custom storefront, or you want to customize the checkout flow, you can follow the [Checkout in Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development/checkout) guide to learn how to build the checkout flow in the storefront, including the payment step. +If you're building a custom storefront, or you want to customize the checkout flow, you can follow the [Checkout in Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/checkout/index.html.md) guide to learn how to build the checkout flow in the storefront, including the payment step. *** @@ -32374,7 +32396,7 @@ If you're building a custom storefront, or you want to customize the checkout fl You can also build a custom payment flow using workflows or the Payment Module's main service. -Refer to the [Accept Payment Flow](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-flow) guide to learn more. +Refer to the [Accept Payment Flow](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-flow/index.html.md) guide to learn more. # Payment Collection @@ -32383,13 +32405,13 @@ In this document, you’ll learn what a payment collection is and how the Medusa ## What's a Payment Collection? -A payment collection stores payment details related to a resource, such as a cart or an order. It’s represented by the [PaymentCollection data model](undefined/references/payment/models/PaymentCollection). +A payment collection stores payment details related to a resource, such as a cart or an order. It’s represented by the [PaymentCollection data model](https://docs.medusajs.com/references/payment/models/PaymentCollection/index.html.md). Every purchase or request for payment starts with a payment collection. The collection holds details necessary to complete the payment, including: -- The [payment sessions](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-session) that represent the payment amount to authorize. -- The [payments](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment) that are created when a payment session is authorized. They can be captured and refunded. -- The [payment providers](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider) that handle the processing of each payment session, including the authorization, capture, and refund. +- The [payment sessions](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-session/index.html.md) that represent the payment amount to authorize. +- The [payments](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment/index.html.md) that are created when a payment session is authorized. They can be captured and refunded. +- The [payment providers](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/index.html.md) that handle the processing of each payment session, including the authorization, capture, and refund. *** @@ -32407,7 +32429,7 @@ You can use this to accept payments in increments or split payments across payme The Cart Module provides cart management features. However, it doesn’t provide any features related to accepting payment. -During checkout, the Medusa application links a cart to a payment collection, which will be used for further payment processing. It also implements the [payment flow](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-flow) during checkout. +During checkout, the Medusa application links a cart to a payment collection, which will be used for further payment processing. It also implements the [payment flow](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-flow/index.html.md) during checkout. ![Diagram showcasing the relation between the Payment and Cart modules](https://res.cloudinary.com/dza7lstvk/image/upload/v1711537849/Medusa%20Resources/cart-payment_ixziqm.jpg) @@ -32418,7 +32440,7 @@ In this guide, you'll learn how to implement it using workflows or the Payment M ## Why Implement the Payment Flow? -Medusa already provides a built-in payment flow that allows you to accept payments from customers, which you can learn about in the [Accept Payment Flow in Checkout](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-checkout-flow) guide. +Medusa already provides a built-in payment flow that allows you to accept payments from customers, which you can learn about in the [Accept Payment Flow in Checkout](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-checkout-flow/index.html.md) guide. You may need to implement a custom payment flow if you have a different use case, or you're using the Payment Module separately from the Medusa application. @@ -32430,7 +32452,7 @@ You can also follow this guide to get a general understanding of how the payment ## How to Implement the Accept Payment Flow? -For a guide on how to implement this flow in the storefront, check out [this guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development/checkout/payment). +For a guide on how to implement this flow in the storefront, check out [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/checkout/payment/index.html.md). It's highly recommended to use Medusa's workflows to implement this flow. Use the Payment Module's main service for more complex cases. @@ -32471,7 +32493,7 @@ const paymentCollection = Next, you'll show the customer the available payment providers to choose from. -In the Medusa application, you need to use [Query](undefined/docs/learn/fundamentals/module-links/query) to retrieve the available payment providers in a region. +In the Medusa application, you need to use [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) to retrieve the available payment providers in a region. ### Using Query @@ -32611,9 +32633,9 @@ The payment flow is complete once the payment session is authorized and the paym You can then: -- Complete the cart using the [completeCartWorkflow](undefined/references/medusa-workflows/completeCartWorkflow) if you're using the Medusa application. -- Capture the payment either using the [capturePaymentWorkflow](undefined/references/medusa-workflows/capturePaymentWorkflow) or [capturePayment method](undefined/references/payment/capturePayment). -- Refund captured amounts using the [refundPaymentWorkflow](undefined/references/medusa-workflows/refundPaymentWorkflow) or [refundPayment method](undefined/references/payment/refundPayment). +- Complete the cart using the [completeCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/completeCartWorkflow/index.html.md) if you're using the Medusa application. +- Capture the payment either using the [capturePaymentWorkflow](https://docs.medusajs.com/references/medusa-workflows/capturePaymentWorkflow/index.html.md) or [capturePayment method](https://docs.medusajs.com/references/payment/capturePayment/index.html.md). +- Refund captured amounts using the [refundPaymentWorkflow](https://docs.medusajs.com/references/medusa-workflows/refundPaymentWorkflow/index.html.md) or [refundPayment method](https://docs.medusajs.com/references/payment/refundPayment/index.html.md). Some payment providers allow capturing the payment automatically once it’s authorized. In that case, you don’t need to do it manually. @@ -32622,13 +32644,13 @@ Some payment providers allow capturing the payment automatically once it’s aut In this guide, you’ll learn about the Payment Module Provider and how it's used. -Refer to this [Medusa Admin User Guide](undefined/user-guide/settings/regions) to learn how to manage the payment providers available in a region using the dashboard. +Refer to this [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/settings/regions/index.html.md) to learn how to manage the payment providers available in a region using the dashboard. *** ## What is a Payment Module Provider? -The Payment Module Provider handles payment processing in the Medusa application. It integrates third-party payment services, such as [Stripe](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe). +The Payment Module Provider handles payment processing in the Medusa application. It integrates third-party payment services, such as [Stripe](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe/index.html.md). To authorize a payment amount with a payment provider, a payment session is created and associated with that payment provider. The payment provider is then used to handle the authorization. @@ -32638,7 +32660,7 @@ After the payment session is authorized, the payment provider is associated with ### List of Payment Module Providers -- [Stripe](undefined/commerce-modules/payment/payment-provider/stripe) +- [Stripe](https://docs.medusajs.com/commerce-modules/payment/payment-provider/stripe/index.html.md) ### Default Payment Provider @@ -32656,9 +32678,9 @@ A payment provider is a module whose main service extends the `AbstractPaymentPr The module can have multiple payment provider services, where each is registered as a separate payment provider. -Refer to [this guide](undefined/references/payment/provider) on how to create a payment provider for the Payment Module. +Refer to [this guide](https://docs.medusajs.com/references/payment/provider/index.html.md) on how to create a payment provider for the Payment Module. -After you create a payment provider, you can enable it as a payment provider in a region using the [Medusa Admin dashboard](undefined/user-guide/settings/regions). +After you create a payment provider, you can enable it as a payment provider in a region using the [Medusa Admin dashboard](https://docs.medusajs.com/user-guide/settings/regions/index.html.md). *** @@ -32668,7 +32690,7 @@ After you create a payment provider, you can enable it as a payment provider in The Payment Module accepts a `providers` option that allows you to configure the providers registered in your application. -Learn more about this option in the [Module Options](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/module-options) guide. +Learn more about this option in the [Module Options](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/module-options/index.html.md) guide. ### Registration on Application Start @@ -32678,7 +32700,7 @@ For each Payment Module Provider, the Medusa application finds all payment provi ### PaymentProvider Data Model -A registered payment provider is represented by the [PaymentProvider data model](undefined/references/payment/models/PaymentProvider) in the Medusa application. +A registered payment provider is represented by the [PaymentProvider data model](https://docs.medusajs.com/references/payment/models/PaymentProvider/index.html.md) in the Medusa application. ![Diagram showcasing the PaymentProvider data model](https://res.cloudinary.com/dza7lstvk/image/upload/v1746791364/Medusa%20Resources/payment-provider-model_lx91oa.jpg) @@ -32702,7 +32724,7 @@ Instead, the Medusa application will set the `is_enabled` property of the `Payme In this document, you’ll learn about the Stripe Module Provider and how to configure it in the Payment Module. -Your technical team must install the Stripe Module Provider in your Medusa application first. Then, refer to [this user guide](undefined/user-guide/settings/regions#edit-region-details) to learn how to enable the Stripe payment provider in a region using the Medusa Admin dashboard. +Your technical team must install the Stripe Module Provider in your Medusa application first. Then, refer to [this user guide](https://docs.medusajs.com/user-guide/settings/regions#edit-region-details/index.html.md) to learn how to enable the Stripe payment provider in a region using the Medusa Admin dashboard. ## Register the Stripe Module Provider @@ -32760,7 +32782,7 @@ STRIPE_API_KEY= Before customers can use Stripe to complete their purchases, you must enable the Stripe payment provider(s) in the region where you want to offer this payment method. -Refer to the [user guide](undefined/user-guide/settings/regions#edit-region-details) to learn how to edit a region and enable the Stripe payment provider. +Refer to the [user guide](https://docs.medusajs.com/user-guide/settings/regions#edit-region-details/index.html.md) to learn how to edit a region and enable the Stripe payment provider. *** @@ -32823,10 +32845,10 @@ When you set up the webhook in Stripe, choose the following events to listen to: ## Useful Guides -- [Storefront guide: Add Stripe payment method during checkout](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development/checkout/payment/stripe). -- [Integrate in Next.js Starter](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter#stripe-integration). -- [Customize Stripe Integration in Next.js Starter](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter/guides/customize-stripe). -- [Add Saved Payment Methods with Stripe](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/how-to-tutorials/tutorials/saved-payment-methods). +- [Storefront guide: Add Stripe payment method during checkout](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/checkout/payment/stripe/index.html.md). +- [Integrate in Next.js Starter](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter#stripe-integration/index.html.md). +- [Customize Stripe Integration in Next.js Starter](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/guides/customize-stripe/index.html.md). +- [Add Saved Payment Methods with Stripe](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/how-to-tutorials/tutorials/saved-payment-methods/index.html.md). # Payment Session @@ -32835,7 +32857,7 @@ In this document, you’ll learn what a payment session is. ## What's a Payment Session? -A payment session, represented by the [PaymentSession data model](undefined/references/payment/models/PaymentSession), is a payment amount to be authorized. It’s associated with a payment provider that handles authorizing it. +A payment session, represented by the [PaymentSession data model](https://docs.medusajs.com/references/payment/models/PaymentSession/index.html.md), is a payment amount to be authorized. It’s associated with a payment provider that handles authorizing it. A payment collection can have multiple payment sessions. Using this feature, you can implement payment in installments or payments using multiple providers. @@ -32847,11 +32869,11 @@ A payment collection can have multiple payment sessions. Using this feature, you Payment providers may need additional data to process the payment later. For example, the ID of the session in the third-party provider. -The `PaymentSession` data model has a `data` property used to store that data. It's set by the [payment provider in Medusa](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider) when the payment is initialized. +The `PaymentSession` data model has a `data` property used to store that data. It's set by the [payment provider in Medusa](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/index.html.md) when the payment is initialized. Then, when the payment session is authorized, the `data` property is used by the payment provider in Medusa to process the payment with the third-party provider. -If you're building a custom payment provider, learn more about initializing the payment session and setting the `data` property in the [Create Payment Provider](undefined/references/payment/provider) guide. +If you're building a custom payment provider, learn more about initializing the payment session and setting the `data` property in the [Create Payment Provider](https://docs.medusajs.com/references/payment/provider/index.html.md) guide. ### data Property in the Storefront @@ -32878,7 +32900,7 @@ In this document, you’ll learn what a payment is and how it's created, capture ## What's a Payment? -When a payment session is authorized, a payment, represented by the [Payment data model](undefined/references/payment/models/Payment), is created. This payment can later be captured or refunded. +When a payment session is authorized, a payment, represented by the [Payment data model](https://docs.medusajs.com/references/payment/models/Payment/index.html.md), is created. This payment can later be captured or refunded. A payment carries many of the data and relations of a payment session: @@ -32890,7 +32912,7 @@ A payment carries many of the data and relations of a payment session: ## Capture Payments -When a payment is captured, a capture, represented by the [Capture data model](undefined/references/payment/models/Capture), is created. It holds details related to the capture, such as the amount, the capture date, and more. +When a payment is captured, a capture, represented by the [Capture data model](https://docs.medusajs.com/references/payment/models/Capture/index.html.md), is created. It holds details related to the capture, such as the amount, the capture date, and more. The payment can also be captured incrementally, each time a capture record is created for that amount. @@ -32900,7 +32922,7 @@ The payment can also be captured incrementally, each time a capture record is cr ## Refund Payments -When a payment is refunded, a refund, represented by the [Refund data model](undefined/references/payment/models/Refund), is created. It holds details related to the refund, such as the amount, refund date, and more. +When a payment is refunded, a refund, represented by the [Refund data model](https://docs.medusajs.com/references/payment/models/Refund/index.html.md), is created. It holds details related to the refund, such as the amount, refund date, and more. A payment can be refunded multiple times, and each time a refund record is created. @@ -32912,11 +32934,11 @@ A payment can be refunded multiple times, and each time a refund record is creat Payment providers may need additional data to process the payment later. For example, the ID of the associated payment in the third-party provider. -The `Payment` data model has a `data` property used to store that data. The first time it's set is when the [payment provider in Medusa](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider) authorizes the payment. +The `Payment` data model has a `data` property used to store that data. The first time it's set is when the [payment provider in Medusa](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/index.html.md) authorizes the payment. Then, the `data` property is passed to the Medusa payment provider when the payment is captured or refunded, allowing the payment provider to utilize the data to process the payment with the third-party provider. -If you're building a custom payment provider, learn more about authorizing and capturing the payments and setting the `data` property in the [Create Payment Provider](undefined/references/payment/provider) guide. +If you're building a custom payment provider, learn more about authorizing and capturing the payments and setting the `data` property in the [Create Payment Provider](https://docs.medusajs.com/references/payment/provider/index.html.md) guide. # Payment Webhook Events @@ -32946,21 +32968,21 @@ The Medusa application has a `/hooks/payment/[identifier]_[provider]` API route - `[identifier]` is the `identifier` static property defined in the payment provider. For example, `stripe`. - `[provider]` is the ID of the provider. For example, `stripe`. -For example, when integrating basic Stripe payments with the [Stripe Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe), the webhook listener route is `/hooks/payment/stripe_stripe`. +For example, when integrating basic Stripe payments with the [Stripe Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe/index.html.md), the webhook listener route is `/hooks/payment/stripe_stripe`. You can use this webhook listener when configuring webhook events in your third-party payment provider. ### getWebhookActionAndData Method -The webhook listener API route executes the [getWebhookActionAndData method](undefined/references/payment/getWebhookActionAndData) of the Payment Module's main service. This method delegates handling of incoming webhook events to the relevant payment provider. +The webhook listener API route executes the [getWebhookActionAndData method](https://docs.medusajs.com/references/payment/getWebhookActionAndData/index.html.md) of the Payment Module's main service. This method delegates handling of incoming webhook events to the relevant payment provider. -Payment providers have a similar [getWebhookActionAndData method](undefined/references/payment/provider) to process the webhook event. So, if you're implementing a custom payment provider, make sure to implement it to handle webhook events. +Payment providers have a similar [getWebhookActionAndData method](https://docs.medusajs.com/references/payment/provider/index.html.md) to process the webhook event. So, if you're implementing a custom payment provider, make sure to implement it to handle webhook events. ![A diagram showcasing the steps of how the getWebhookActionAndData method words](https://res.cloudinary.com/dza7lstvk/image/upload/v1711567415/Medusa%20Resources/payment-webhook_seaocg.jpg) If the `getWebhookActionAndData` method returns an `authorized` or `captured` action, the Medusa application will perform one of the following actions: -View the full flow of the webhook event processing in the [processPaymentWorkflow](undefined/references/medusa-workflows/processPaymentWorkflow) reference. +View the full flow of the webhook event processing in the [processPaymentWorkflow](https://docs.medusajs.com/references/medusa-workflows/processPaymentWorkflow/index.html.md) reference. - If the method returns an `authorized` action, Medusa will set the associated payment session to `authorized`. - If the method returns a `captured` action, Medusa will set the associated payment session to `captured`. @@ -32973,7 +32995,7 @@ In this guide, you’ll learn about the main concepts in the Pricing Module. ## Price Data Model -The [Price](undefined/references/pricing/models/Price) data model represents a specific price for a resource. For example, the price of a product variant in the USD currency. +The [Price](https://docs.medusajs.com/references/pricing/models/Price/index.html.md) data model represents a specific price for a resource. For example, the price of a product variant in the USD currency. The `Price` data model has an `amount` property that represents the monetary value of the price. It's stored as an integer in base or major units. For example, `$20.00` is stored as `20`, and `$20.5` is stored as `20.5`. @@ -32983,7 +33005,7 @@ The `Price` data model belongs to other data models like `PriceSet` and `PriceLi ## Price Set -A [PriceSet](undefined/references/pricing/models/PriceSet) represents a collection of prices that are linked to a resource. For example, a product variant can have a price set that includes prices in multiple currencies, such as USD and EUR. +A [PriceSet](https://docs.medusajs.com/references/pricing/models/PriceSet/index.html.md) represents a collection of prices that are linked to a resource. For example, a product variant can have a price set that includes prices in multiple currencies, such as USD and EUR. Each of these prices is represented by the [Price data model](#price-data-model). @@ -32993,9 +33015,9 @@ Each of these prices is represented by the [Price data model](#price-data-model) ## Price List -A [PriceList](undefined/references/pricing/models/PriceList) is a group of prices that are only enabled when their conditions and rules are satisfied. For example, you can apply special prices to customers in the VIP group. +A [PriceList](https://docs.medusajs.com/references/pricing/models/PriceList/index.html.md) is a group of prices that are only enabled when their conditions and rules are satisfied. For example, you can apply special prices to customers in the VIP group. -When the conditions are met, the prices in the price list can override the default prices in a price set. Learn more in the [Price Calculation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation) guide. +When the conditions are met, the prices in the price list can override the default prices in a price set. Learn more in the [Price Calculation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation/index.html.md) guide. A price list has optional `start_date` and `end_date` properties that indicate the date range in which a price list can be applied. @@ -33009,7 +33031,7 @@ The `Price` data model has a `currency_code` property that represents the curren This adds support for multi-currency pricing, allowing you to associate a resource with a price set that contains prices in multiple currencies. -For example, Medusa links a product variant from the [Product Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product) to a price set that contains prices in multiple currencies. A variant's price set would be similar to the following: +For example, Medusa links a product variant from the [Product Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/index.html.md) to a price set that contains prices in multiple currencies. A variant's price set would be similar to the following: ```json title="Example Price Set with Multiple Currencies" { @@ -33035,7 +33057,7 @@ When the customer views and purchases a product, Medusa selects the price based ## Multi-Region Support for Prices -The `Price` data model has a relation to the [PriceRule](undefined/references/pricing/models/PriceRule) data model that allows you to define prices that are applied based on specific conditions, such as the customer's region. +The `Price` data model has a relation to the [PriceRule](https://docs.medusajs.com/references/pricing/models/PriceRule/index.html.md) data model that allows you to define prices that are applied based on specific conditions, such as the customer's region. For example, Medusa allows you to specify prices for a product variant that are applied only when the customer is in a specific region. The price would be similar to the following: @@ -33083,7 +33105,7 @@ Medusa defines a link between the `PriceSet` and `ShippingOption` data models. A ### Retrieve with Query -To retrieve the shipping option of a price set with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `shipping_option.*` in `fields`: +To retrieve the shipping option of a price set with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `shipping_option.*` in `fields`: ### query.graph @@ -33117,7 +33139,7 @@ const { data: priceSets } = useQueryGraphStep({ ### Manage with Link -To manage the price set of a shipping option, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the price set of a shipping option, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -33170,7 +33192,7 @@ You can then benefit from adding rules to prices or using the `calculatePrices` ### Retrieve with Query -To retrieve the variant of a price set with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `variant.*` in `fields`: +To retrieve the variant of a price set with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `variant.*` in `fields`: ### query.graph @@ -33204,7 +33226,7 @@ const { data: priceSets } = useQueryGraphStep({ ### Manage with Link -To manage the price set of a variant, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the price set of a variant, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -33246,26 +33268,26 @@ createRemoteLinkStep({ In this section of the documentation, you will find resources to learn more about the Pricing Module and how to use it in your application. -Refer to the [Medusa Admin User Guide](undefined/user-guide/price-lists) to learn how to manage price lists using the dashboard. +Refer to the [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/price-lists/index.html.md) to learn how to manage price lists using the dashboard. -Medusa has pricing related features available out-of-the-box through the Pricing Module. A [module](undefined/docs/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Pricing Module. +Medusa has pricing related features available out-of-the-box through the Pricing Module. A [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Pricing Module. -Learn more about why modules are isolated in [this documentation](undefined/docs/learn/fundamentals/modules/isolation). +Learn more about why modules are isolated in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md). ## Pricing Features -- [Price Management](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/concepts): Store and manage prices of a resource, such as a product or a variant. -- [Multi-Currency and Region Support](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/concepts#multi-currency-support-for-prices): Define prices for a single resource in multiple currencies and regions. -- [Advanced Rule Engine](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/price-rules): Create prices with tiers and custom rules to condition prices based on different contexts. -- [Price Lists](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/concepts#price-list): Group prices and apply them only in specific conditions with price lists. -- [Price Calculation Strategy](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation): Retrieve the best price in a given context and for the specified rule values. -- [Tax-Inclusive Pricing](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/tax-inclusive-pricing): Calculate prices with taxes included in the price, and Medusa will handle calculating the taxes automatically. +- [Price Management](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/concepts/index.html.md): Store and manage prices of a resource, such as a product or a variant. +- [Multi-Currency and Region Support](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/concepts#multi-currency-support-for-prices/index.html.md): Define prices for a single resource in multiple currencies and regions. +- [Advanced Rule Engine](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/price-rules/index.html.md): Create prices with tiers and custom rules to condition prices based on different contexts. +- [Price Lists](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/concepts#price-list/index.html.md): Group prices and apply them only in specific conditions with price lists. +- [Price Calculation Strategy](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation/index.html.md): Retrieve the best price in a given context and for the specified rule values. +- [Tax-Inclusive Pricing](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/tax-inclusive-pricing/index.html.md): Calculate prices with taxes included in the price, and Medusa will handle calculating the taxes automatically. *** ## How to Use the Pricing Module -In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](undefined/docs/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package. @@ -33392,18 +33414,18 @@ export const config = { } ``` -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). *** # Prices Calculation -In this guide, you'll learn how prices are calculated when you use the [calculatePrices method](undefined/references/pricing/calculatePrices) of the Pricing Module's main service. +In this guide, you'll learn how prices are calculated when you use the [calculatePrices method](https://docs.medusajs.com/references/pricing/calculatePrices/index.html.md) of the Pricing Module's main service. ## calculatePrices Method -The [calculatePrices method](undefined/references/pricing/calculatePrices) accepts the ID of one or more price sets and a context as parameters. +The [calculatePrices method](https://docs.medusajs.com/references/pricing/calculatePrices/index.html.md) accepts the ID of one or more price sets and a context as parameters. It returns a price object with the best-matching price for each price set. @@ -33664,12 +33686,12 @@ In this Pricing Module guide, you'll learn about tired prices, price rules for p You can manage prices and tiers using the Medusa Admin: -- [Edit shipping option prices with conditions](undefined/user-guide/settings/locations-and-shipping/locations#fixed-and-conditional-shipping-option-prices). -- [Add price lists to set prices with conditions for product variants](undefined/user-guide/price-lists). +- [Edit shipping option prices with conditions](https://docs.medusajs.com/user-guide/settings/locations-and-shipping/locations#fixed-and-conditional-shipping-option-prices/index.html.md). +- [Add price lists to set prices with conditions for product variants](https://docs.medusajs.com/user-guide/price-lists/index.html.md). ## Tiered Pricing -Each price, represented by the [Price data model](undefined/references/pricing/models/Price), has two optional properties that can be used to create tiered prices: +Each price, represented by the [Price data model](https://docs.medusajs.com/references/pricing/models/Price/index.html.md), has two optional properties that can be used to create tiered prices: - `min_quantity`: The minimum quantity that must be in the cart for the price to be applied. - `max_quantity`: The maximum quantity that can be in the cart for the price to be applied. @@ -33711,7 +33733,7 @@ When you create prices, you can specify a `min_quantity` and `max_quantity` for For example: -For most use cases where you're building customizations in the Medusa application, it's highly recommended to use [Medusa's workflows](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/medusa-workflows-reference) rather than using the Pricing Module directly. Medusa's workflows already implement extensive functionalities that you can re-use in your custom flows, with reliable roll-back mechanism. +For most use cases where you're building customizations in the Medusa application, it's highly recommended to use [Medusa's workflows](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/medusa-workflows-reference/index.html.md) rather than using the Pricing Module directly. Medusa's workflows already implement extensive functionalities that you can re-use in your custom flows, with reliable roll-back mechanism. ### Using Medusa Workflows @@ -33783,13 +33805,13 @@ In this example, you create a product with a variant whose default price is `$10 ### How are Tiered Prices Applied? -The [price calculation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation) mechanism considers the cart's items as a context when choosing the best price to apply. +The [price calculation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation/index.html.md) mechanism considers the cart's items as a context when choosing the best price to apply. For example, consider the customer added the `variant_1` product variant (created in the workflow snippet of the [above section](#how-to-create-tiered-prices)) to their cart with a quantity of `15`. The price calculation mechanism will choose the second price, which is `$8`, because the quantity of `15` is between `10` and `19`. -If there are other rules applied to the price, they may affect the price calculation. Keep reading to learn about other price rules, and refer to the [Price Calculation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation) guide for more details on the calculation mechanism. +If there are other rules applied to the price, they may affect the price calculation. Keep reading to learn about other price rules, and refer to the [Price Calculation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation/index.html.md) guide for more details on the calculation mechanism. *** @@ -33797,7 +33819,7 @@ If there are other rules applied to the price, they may affect the price calcula You can also restrict prices by advanced rules, such as a customer's group, zip code, or a cart's total. -Each rule of a price is represented by the [PriceRule data model](undefined/references/pricing/models/PriceRule). +Each rule of a price is represented by the [PriceRule data model](https://docs.medusajs.com/references/pricing/models/PriceRule/index.html.md). The `Price` data model has a `rules_count` property, which indicates how many rules, represented by `PriceRule`, are applied to the price. @@ -33813,7 +33835,7 @@ For example, a price can be restricted by a region and a zip code. ### Price List Rules -Rules applied to a price list are represented by the [PriceListRule data model](undefined/references/pricing/models/PriceListRule). +Rules applied to a price list are represented by the [PriceListRule data model](https://docs.medusajs.com/references/pricing/models/PriceListRule/index.html.md). The `rules_count` property of a `PriceList` indicates how many rules are applied to it. @@ -33825,7 +33847,7 @@ When you create prices, you can specify rules for each price. This allows you to For example: -For most use cases where you're building customizations in the Medusa application, it's highly recommended to use [Medusa's workflows](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/medusa-workflows-reference) rather than using the Pricing Module directly. Medusa's workflows already implement extensive functionalities that you can re-use in your custom flows, with reliable roll-back mechanism. +For most use cases where you're building customizations in the Medusa application, it's highly recommended to use [Medusa's workflows](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/medusa-workflows-reference/index.html.md) rather than using the Pricing Module directly. Medusa's workflows already implement extensive functionalities that you can re-use in your custom flows, with reliable roll-back mechanism. ### Using Medusa Workflows @@ -33898,9 +33920,9 @@ In this example, you create a shipping option whose default price is `$10`. When ### How is the Price Rule Applied? -The [price calculation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation) mechanism considers a price applicable when the resource that this price is in matches the specified rules. +The [price calculation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation/index.html.md) mechanism considers a price applicable when the resource that this price is in matches the specified rules. -For example, a [cart object](undefined/api/store#carts_cart_schema) has an `item_total` property. So, if a shipping option has the following price: +For example, a [cart object](https://docs.medusajs.com/api/store#carts_cart_schema) has an `item_total` property. So, if a shipping option has the following price: ```json { @@ -34520,7 +34542,7 @@ For example, if a product’s price is $50, the tax rate is 2%, and tax-inclusiv ## How is Tax-Inclusive Pricing Set? -The [PricePreference data model](undefined/references/pricing/models/PricePreference) holds the tax-inclusive setting for a context. It has two properties that indicate the context: +The [PricePreference data model](https://docs.medusajs.com/references/pricing/models/PricePreference/index.html.md) holds the tax-inclusive setting for a context. It has two properties that indicate the context: - `attribute`: The name of the attribute to compare against. For example, `region_id` or `currency_code`. - `value`: The attribute’s value. For example, `reg_123` or `usd`. @@ -34547,7 +34569,7 @@ In this example, tax-inclusivity is enabled for the `USD` currency code. ### Tax Context -As mentioned in the [Price Calculation documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation#calculation-context), The `calculatePrices` method accepts as a parameter a calculation context. +As mentioned in the [Price Calculation documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation#calculation-context/index.html.md), The `calculatePrices` method accepts as a parameter a calculation context. To get accurate tax results, pass the `region_id` and / or `currency_code` in the calculation context. @@ -34555,7 +34577,7 @@ To get accurate tax results, pass the `region_id` and / or `currency_code` in th The `calculatePrices` method returns two properties related to tax-inclusivity: -Learn more about the returned properties in [this guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation#returned-price-object). +Learn more about the returned properties in [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation#returned-price-object/index.html.md). - `is_calculated_price_tax_inclusive`: Whether the selected `calculated_price` is tax-inclusive. - `is_original_price_tax_inclusive` : Whether the selected `original_price` is tax-inclusive. @@ -34579,7 +34601,7 @@ A region’s price preference’s `is_tax_inclusive`'s value takes higher preced When you enable tax-inclusive prices for regions or currencies, this can impact how promotions are applied to the cart. So, it's recommended to enable tax-inclusiveness for promotions as well. -Learn more in the [Tax-Inclusive Promotions](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/promotion/promotion-taxes) guide. +Learn more in the [Tax-Inclusive Promotions](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/promotion/promotion-taxes/index.html.md) guide. # Calculate Product Variant Price with Taxes @@ -34590,7 +34612,7 @@ In this document, you'll learn how to calculate a product variant's price with t You'll need the following resources for the taxes calculation: -1. [Query](undefined/docs/learn/fundamentals/module-links/query) to retrieve the product's variants' prices for a context. Learn more about that in [this guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product/guides/price). +1. [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) to retrieve the product's variants' prices for a context. Learn more about that in [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/guides/price/index.html.md). 2. The Tax Module's main service to get the tax lines for each product. ```ts @@ -34613,7 +34635,7 @@ const taxModuleService = container.resolve( After resolving the resources, use Query to retrieve the products with the variants' prices for a context: -Learn more about retrieving product variants' prices for a context in [this guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product/guides/price). +Learn more about retrieving product variants' prices for a context in [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/guides/price/index.html.md). ```ts import { QueryContext } from "@medusajs/framework/utils" @@ -34702,13 +34724,13 @@ const taxLines = (await taxModuleService.getTaxLines( )) as unknown as ItemTaxLineDTO[] ``` -You use the Tax Module's main service's [getTaxLines method](undefined/references/tax/getTaxLines) to retrieve the tax line. +You use the Tax Module's main service's [getTaxLines method](https://docs.medusajs.com/references/tax/getTaxLines/index.html.md) to retrieve the tax line. For the first parameter, you use the `asTaxItem` function to format the products as expected by the `getTaxLines` method. For the second parameter, you pass the current context. You can pass other details such as the customer's ID. -Learn about the other context properties to pass in [the getTaxLines method's reference](undefined/references/tax/getTaxLines). +Learn about the other context properties to pass in [the getTaxLines method's reference](https://docs.medusajs.com/references/tax/getTaxLines/index.html.md). *** @@ -34769,7 +34791,7 @@ For each product variant, you: # Get Product Variant Prices using Query -In this document, you'll learn how to retrieve product variant prices in the Medusa application using [Query](undefined/docs/learn/fundamentals/module-links/query). +In this document, you'll learn how to retrieve product variant prices in the Medusa application using [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md). The Product Module doesn't provide pricing functionalities. The Medusa application links the Product Module's `ProductVariant` data model to the Pricing Module's `PriceSet` data model. @@ -34797,15 +34819,15 @@ const { data: products } = await query.graph({ }) ``` -Each variant in the retrieved products has a `prices` array property with all the product variant prices. Each price object has the properties of the [Pricing Module's Price data model](undefined/references/pricing/models/Price). +Each variant in the retrieved products has a `prices` array property with all the product variant prices. Each price object has the properties of the [Pricing Module's Price data model](https://docs.medusajs.com/references/pricing/models/Price/index.html.md). *** ## Retrieve Calculated Price for a Context -The Pricing Module can calculate prices of a variant based on a [context](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation#calculation-context), such as the region ID or the currency code. +The Pricing Module can calculate prices of a variant based on a [context](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation#calculation-context/index.html.md), such as the region ID or the currency code. -Learn more about prices calculation in [this Pricing Module documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation). +Learn more about prices calculation in [this Pricing Module documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation/index.html.md). To retrieve calculated prices of variants based on a context, retrieve the products using Query and: @@ -34842,16 +34864,16 @@ const { data: products } = await query.graph({ For the context of the product variant's calculated price, you pass an object to `context` with the property `variants`, whose value is another object with the property `calculated_price`. -`calculated_price`'s value is created using `QueryContext` from the Modules SDK, passing it a [calculation context object](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation#calculation-context). +`calculated_price`'s value is created using `QueryContext` from the Modules SDK, passing it a [calculation context object](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation#calculation-context/index.html.md). -Each variant in the retrieved products has a `calculated_price` object. Learn more about its properties in [this Pricing Module guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation#returned-price-object). +Each variant in the retrieved products has a `calculated_price` object. Learn more about its properties in [this Pricing Module guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/price-calculation#returned-price-object/index.html.md). # Get Product Variant Inventory Quantity -In this guide, you'll learn how to retrieve the available inventory quantity of a product variant in your Medusa application customizations. That includes API routes, workflows, subscribers, scheduled jobs, and any resource that can access the [Medusa container](undefined/docs/learn/fundamentals/medusa-container). +In this guide, you'll learn how to retrieve the available inventory quantity of a product variant in your Medusa application customizations. That includes API routes, workflows, subscribers, scheduled jobs, and any resource that can access the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). -Refer to the [Retrieve Product Variant Inventory](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development/products/inventory) storefront guide. +Refer to the [Retrieve Product Variant Inventory](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/products/inventory/index.html.md) storefront guide. ## Understanding Product Variant Inventory Availability @@ -34859,7 +34881,7 @@ Product variants have a `manage_inventory` boolean field that indicates whether When `manage_inventory` is disabled, the Medusa application always considers the product variant to be in stock. So, you can't retrieve the inventory quantity for those products. -When `manage_inventory` is enabled, the Medusa application tracks the inventory of the product variant using the [Inventory Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/inventory). For example, when a customer purchases a product variant, the Medusa application decrements the stocked quantity of the product variant. +When `manage_inventory` is enabled, the Medusa application tracks the inventory of the product variant using the [Inventory Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/inventory/index.html.md). For example, when a customer purchases a product variant, the Medusa application decrements the stocked quantity of the product variant. This guide explains how to retrieve the inventory quantity of a product variant when `manage_inventory` is enabled. @@ -34885,7 +34907,7 @@ const availability = await getVariantAvailability(query, { }) ``` -A product variant's inventory quantity is set per [stock location](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/stock-location). This stock location is linked to a [sales channel](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/sales-channel). +A product variant's inventory quantity is set per [stock location](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/stock-location/index.html.md). This stock location is linked to a [sales channel](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/sales-channel/index.html.md). So, to retrieve the inventory quantity of a product variant using `getVariantAvailability`, you need to also provide the ID of the sales channel to retrieve the inventory quantity in. @@ -34933,7 +34955,7 @@ To retrieve the sales channel ID to use in the `getVariantAvailability` function ### Method 1: Use Sales Channel Scope in Store Routes -Requests sent to API routes starting with `/store` must include a [publishable API key in the request header](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/sales-channel/publishable-api-keys). This scopes the request to one or more sales channels associated with the publishable API key. +Requests sent to API routes starting with `/store` must include a [publishable API key in the request header](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/sales-channel/publishable-api-keys/index.html.md). This scopes the request to one or more sales channels associated with the publishable API key. So, if you're retrieving the variant inventory availability in an API route starting with `/store`, you can access the sales channel using the `publishable_key_context.sales_channel_ids` property of the request object: @@ -34993,7 +35015,7 @@ const availability = await getVariantAvailability(query, { }) ``` -In this example, you retrieve the sales channels of the variant's product using [Query](undefined/docs/learn/fundamentals/module-links/query). +In this example, you retrieve the sales channels of the variant's product using [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md). You pass the ID of the variant as a filter, and you specify `product.sales_channels.*` as the fields to retrieve. This retrieves the sales channels linked to the variant's product. @@ -35025,12 +35047,12 @@ Read-only links are used to query data across modules, but the relations aren't Medusa defines read-only links between: -- The [Cart Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/cart)'s `LineItem` data model and the `Product` data model. Because the link is read-only from the `LineItem`'s side, you can only retrieve the product of a line item, and not the other way around. -- The `ProductVariant` data model and the [Cart Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/cart)'s `LineItem` data model. Because the link is read-only from the `LineItem`'s side, you can only retrieve the variant of a line item, and not the other way around. +- The [Cart Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/cart/index.html.md)'s `LineItem` data model and the `Product` data model. Because the link is read-only from the `LineItem`'s side, you can only retrieve the product of a line item, and not the other way around. +- The `ProductVariant` data model and the [Cart Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/cart/index.html.md)'s `LineItem` data model. Because the link is read-only from the `LineItem`'s side, you can only retrieve the variant of a line item, and not the other way around. ### Retrieve with Query -To retrieve the variant of a line item with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `variant.*` in `fields`: +To retrieve the variant of a line item with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `variant.*` in `fields`: To retrieve the product, pass `product.*` in `fields`. @@ -35074,7 +35096,7 @@ This link is introduced in [Medusa v2.5.0](https://github.com/medusajs/medusa/re ### Retrieve with Query -To retrieve the shipping profile of a product with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `shipping_profile.*` in `fields`: +To retrieve the shipping profile of a product with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `shipping_profile.*` in `fields`: ### query.graph @@ -35108,7 +35130,7 @@ const { data: products } = useQueryGraphStep({ ### Manage with Link -To manage the shipping profile of a product, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the shipping profile of a product, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -35157,11 +35179,11 @@ Medusa defines a link between the `ProductVariant` and `InventoryItem` data mode When the `manage_inventory` property of a product variant is enabled, you can manage the variant's inventory in different locations through this relation. -Learn more about product variant's inventory management in [this guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product/variant-inventory). +Learn more about product variant's inventory management in [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/variant-inventory/index.html.md). ### Retrieve with Query -To retrieve the inventory items of a product variant with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `inventory_items.*` in `fields`: +To retrieve the inventory items of a product variant with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `inventory_items.*` in `fields`: ### query.graph @@ -35195,7 +35217,7 @@ const { data: variants } = useQueryGraphStep({ ### Manage with Link -To manage the inventory items of a variant, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the inventory items of a variant, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -35238,12 +35260,12 @@ createRemoteLinkStep({ Medusa defines read-only links between: -- the [Order Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order)'s `OrderLineItem` data model and the `Product` data model. Because the link is read-only from the `OrderLineItem`'s side, you can only retrieve the product of an order line item, and not the other way around. -- the [Order Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order)'s `OrderLineItem` data model and the `ProductVariant` data model. Because the link is read-only from the `OrderLineItem`'s side, you can only retrieve the variant of an order line item, and not the other way around. +- the [Order Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/index.html.md)'s `OrderLineItem` data model and the `Product` data model. Because the link is read-only from the `OrderLineItem`'s side, you can only retrieve the product of an order line item, and not the other way around. +- the [Order Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/index.html.md)'s `OrderLineItem` data model and the `ProductVariant` data model. Because the link is read-only from the `OrderLineItem`'s side, you can only retrieve the variant of an order line item, and not the other way around. ### Retrieve with Query -To retrieve the variant of a line item with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `variant.*` in `fields`: +To retrieve the variant of a line item with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `variant.*` in `fields`: To retrieve the product, pass `product.*` in `fields`. @@ -35291,7 +35313,7 @@ So, to add prices for a product variant, create a price set and add the prices t ### Retrieve with Query -To retrieve the price set of a variant with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `price_set.*` in `fields`: +To retrieve the price set of a variant with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `price_set.*` in `fields`: ### query.graph @@ -35325,7 +35347,7 @@ const { data: variants } = useQueryGraphStep({ ### Manage with Link -To manage the price set of a variant, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the price set of a variant, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -35374,7 +35396,7 @@ Medusa defines a link between the `Product` and `SalesChannel` data models. A pr ### Retrieve with Query -To retrieve the sales channels of a product with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `sales_channels.*` in `fields`: +To retrieve the sales channels of a product with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `sales_channels.*` in `fields`: ### query.graph @@ -35408,7 +35430,7 @@ const { data: products } = useQueryGraphStep({ ### Manage with Link -To manage the sales channels of a product, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the sales channels of a product, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -35450,24 +35472,24 @@ createRemoteLinkStep({ In this section of the documentation, you will find resources to learn more about the Product Module and how to use it in your application. -Refer to the [Medusa Admin User Guide](undefined/user-guide/products) to learn how to manage products using the dashboard. +Refer to the [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/products/index.html.md) to learn how to manage products using the dashboard. -Medusa has product related features available out-of-the-box through the Product Module. A [module](undefined/docs/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Product Module. +Medusa has product related features available out-of-the-box through the Product Module. A [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Product Module. -Learn more about why modules are isolated in [this documentation](undefined/docs/learn/fundamentals/modules/isolation). +Learn more about why modules are isolated in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md). ## Product Features -- [Products Management](undefined/references/product/models/Product): Store and manage products. Products have custom options, such as color or size, and each variant in the product sets the value for these options. -- [Product Organization](undefined/references/product/models): The Product Module provides different data models used to organize products, including categories, collections, tags, and more. -- [Bundled and Multi-Part Products](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/inventory/inventory-kit): Create and manage inventory kits for a single product, allowing you to implement use cases like bundled or multi-part products. -- [Tiered Pricing and Price Rules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/price-rules): Set prices for product variants with tiers and rules, allowing you to create complex pricing strategies. +- [Products Management](https://docs.medusajs.com/references/product/models/Product/index.html.md): Store and manage products. Products have custom options, such as color or size, and each variant in the product sets the value for these options. +- [Product Organization](https://docs.medusajs.com/references/product/models/index.html.md): The Product Module provides different data models used to organize products, including categories, collections, tags, and more. +- [Bundled and Multi-Part Products](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/inventory/inventory-kit/index.html.md): Create and manage inventory kits for a single product, allowing you to implement use cases like bundled or multi-part products. +- [Tiered Pricing and Price Rules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/price-rules/index.html.md): Set prices for product variants with tiers and rules, allowing you to create complex pricing strategies. *** ## How to Use the Product Module -In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](undefined/docs/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package. @@ -35596,7 +35618,7 @@ export const config = { } ``` -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). *** @@ -35625,7 +35647,7 @@ This guide explains how these configurations work, then provides examples of set ### Product Shipping Requirement -The Medusa application defines a link between the `Product` data model and the [ShippingProfile](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/fulfillment/concepts#shipping-profile) data model in the [Fulfillment Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/fulfillment), allowing you to associate a product with a shipping profile. +The Medusa application defines a link between the `Product` data model and the [ShippingProfile](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/fulfillment/concepts#shipping-profile/index.html.md) data model in the [Fulfillment Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/fulfillment/index.html.md), allowing you to associate a product with a shipping profile. ![Diagram showcasing the link between a product and its shipping profile](https://res.cloudinary.com/dza7lstvk/image/upload/v1752827367/Medusa%20Resources/product-shipping-requirement_cpfpkz.jpg) @@ -35635,13 +35657,13 @@ If a product doesn't have an associated shipping profile, its variants don't req ### Overriding Shipping Requirements for Variants -A product variant whose inventory is managed by Medusa (its `manage_inventory` property is enabled) has an [inventory item](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/inventory/concepts#inventoryitem). +A product variant whose inventory is managed by Medusa (its `manage_inventory` property is enabled) has an [inventory item](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/inventory/concepts#inventoryitem/index.html.md). The inventory item has a `requires_shipping` property that can be used to override the variant's shipping requirement. This is useful if the product has an associated shipping profile but you want to disable shipping for a specific variant, or vice versa. ![Diagram showcasing the link between a product variant and its inventory item, and the inventory item's shipping requirement](https://res.cloudinary.com/dza7lstvk/image/upload/v1752828341/Medusa%20Resources/product-variant-shipping-requirement_ux5y44.jpg) -Refer to the [Product Variant Inventory](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product/variant-inventory) guide to learn more. +Refer to the [Product Variant Inventory](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/variant-inventory/index.html.md) guide to learn more. When a product variant is purchased, the Medusa application decides whether the purchased item requires shipping based on the following conditions (in the following order): @@ -35658,7 +35680,7 @@ This is a common misconception, where you expect to not receive any shipping opt If you want to show the shipping options only if the cart has items that require shipping, you can either: -- Create a custom [API route](undefined/docs/learn/fundamentals/api-routes) that checks whether the cart has items that require shipping. +- Create a custom [API route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) that checks whether the cart has items that require shipping. - Perform this check in your storefront's frontend code, such as in the checkout page, and show or hide the shipping options accordingly. *** @@ -35681,21 +35703,21 @@ By combining configurations of shipment requirements and inventory management, y In this guide, you'll learn about the inventory management features related to product variants. -Refer to this [Medusa Admin User Guide](undefined/user-guide/products/variants#manage-product-variant-inventory) to learn how to manage inventory of product variants. +Refer to this [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/products/variants#manage-product-variant-inventory/index.html.md) to learn how to manage inventory of product variants. ## Configure Inventory Management of Product Variants -A product variant, represented by the [ProductVariant](undefined/references/product/models/ProductVariant) data model, has a `manage_inventory` field that's disabled by default. This field indicates whether you'll manage the inventory quantity of the product variant in the Medusa application. You can also keep `manage_inventory` disabled if you manage the product's inventory in an external system, such as an ERP. +A product variant, represented by the [ProductVariant](https://docs.medusajs.com/references/product/models/ProductVariant/index.html.md) data model, has a `manage_inventory` field that's disabled by default. This field indicates whether you'll manage the inventory quantity of the product variant in the Medusa application. You can also keep `manage_inventory` disabled if you manage the product's inventory in an external system, such as an ERP. -The Product Module doesn't provide inventory-management features. Instead, the Medusa application uses the [Inventory Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/inventory) to manage inventory for products and variants. When `manage_inventory` is disabled, the Medusa application always considers the product variant to be in stock. This is useful if your product's variants aren't items that can be stocked, such as digital products, or they don't have a limited stock quantity. +The Product Module doesn't provide inventory-management features. Instead, the Medusa application uses the [Inventory Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/inventory/index.html.md) to manage inventory for products and variants. When `manage_inventory` is disabled, the Medusa application always considers the product variant to be in stock. This is useful if your product's variants aren't items that can be stocked, such as digital products, or they don't have a limited stock quantity. -When `manage_inventory` is enabled, the Medusa application tracks the inventory of the product variant using the [Inventory Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/inventory). For example, when a customer purchases a product variant, the Medusa application decrements the stocked quantity of the product variant. +When `manage_inventory` is enabled, the Medusa application tracks the inventory of the product variant using the [Inventory Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/inventory/index.html.md). For example, when a customer purchases a product variant, the Medusa application decrements the stocked quantity of the product variant. *** ## How the Medusa Application Manages Inventory -When a product variant has `manage_inventory` enabled, the Medusa application creates an inventory item using the [Inventory Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/inventory) and links it to the product variant. +When a product variant has `manage_inventory` enabled, the Medusa application creates an inventory item using the [Inventory Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/inventory/index.html.md) and links it to the product variant. ![Diagram showcasing the link between a product variant and its inventory item](https://res.cloudinary.com/dza7lstvk/image/upload/v1709652779/Medusa%20Resources/product-inventory_kmjnud.jpg) @@ -35703,17 +35725,17 @@ The inventory item has one or more locations, called inventory levels, that repr ![Diagram showcasing the link between a variant and its inventory item, and the inventory item's level.](https://res.cloudinary.com/dza7lstvk/image/upload/v1738580390/Medusa%20Resources/variant-inventory-level_bbee2t.jpg) -Learn more about inventory concepts in the [Inventory Module's documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/inventory/concepts). +Learn more about inventory concepts in the [Inventory Module's documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/inventory/concepts/index.html.md). -The Medusa application represents and manages stock locations using the [Stock Location Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/stock-location). It creates a read-only link between the `InventoryLevel` and `StockLocation` data models so that it can retrieve the stock location of an inventory level. +The Medusa application represents and manages stock locations using the [Stock Location Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/stock-location/index.html.md). It creates a read-only link between the `InventoryLevel` and `StockLocation` data models so that it can retrieve the stock location of an inventory level. ![Diagram showcasing the read-only link between an inventory level and a stock location](https://res.cloudinary.com/dza7lstvk/image/upload/v1738582163/Medusa%20Resources/inventory-level-stock_amxfg5.jpg) -Learn more about the Stock Location Module in the [Stock Location Module's documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/stock-location/concepts). +Learn more about the Stock Location Module in the [Stock Location Module's documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/stock-location/concepts/index.html.md). ### Product Inventory in Storefronts -When a storefront sends a request to the Medusa application, it must always pass a [publishable API key](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/sales-channel/publishable-api-keys) in the request header. This API key specifies the sales channels, available through the [Sales Channel Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/sales-channel), of the storefront. +When a storefront sends a request to the Medusa application, it must always pass a [publishable API key](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/sales-channel/publishable-api-keys/index.html.md) in the request header. This API key specifies the sales channels, available through the [Sales Channel Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/sales-channel/index.html.md), of the storefront. The Medusa application links sales channels to stock locations, indicating the locations available for a specific sales channel. So, all inventory-related operations are scoped by the sales channel and its associated stock locations. @@ -35727,7 +35749,7 @@ For example, the availability of a product variant is determined by the `stocked Product variants have an `allow_backorder` field that's disabled by default. When enabled, the Medusa application allows customers to purchase the product variant even when it's out of stock. Use this when your product variant is available through on-demand or pre-order purchase. -You can also allow customers to subscribe to restock notifications of a product variant as explained in [this guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/commerce-automation/restock-notification). +You can also allow customers to subscribe to restock notifications of a product variant as explained in [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/commerce-automation/restock-notification/index.html.md). *** @@ -35735,20 +35757,20 @@ You can also allow customers to subscribe to restock notifications of a product The following guides provide more details on inventory management in the Medusa application: -- [Inventory Kits in the Inventory Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/inventory/inventory-kit): Learn how you can implement bundled or multi-part products through the Inventory Module. -- [Retrieve Product Variant Inventory Quantity](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product/guides/variant-inventory): Learn how to retrieve the available inventory quantity of a product variant. -- [Configure Selling Products](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product/selling-products): Learn how to use inventory management to support different use cases when selling products. -- [Inventory in Flows](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/inventory/inventory-in-flows): Learn how Medusa utilizes inventory management in different flows. +- [Inventory Kits in the Inventory Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/inventory/inventory-kit/index.html.md): Learn how you can implement bundled or multi-part products through the Inventory Module. +- [Retrieve Product Variant Inventory Quantity](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/guides/variant-inventory/index.html.md): Learn how to retrieve the available inventory quantity of a product variant. +- [Configure Selling Products](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/selling-products/index.html.md): Learn how to use inventory management to support different use cases when selling products. +- [Inventory in Flows](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/inventory/inventory-in-flows/index.html.md): Learn how Medusa utilizes inventory management in different flows. - [Storefront guide: how to retrieve a product variant's inventory details](https://docs.medusajs.com/resources/storefront-development/products/inventory/index.html.md). # Promotion Actions -In this document, you’ll learn about promotion actions and how they’re computed using the [computeActions method](undefined/references/promotion/computeActions). +In this document, you’ll learn about promotion actions and how they’re computed using the [computeActions method](https://docs.medusajs.com/references/promotion/computeActions/index.html.md). ## computeActions Method -The Promotion Module's main service has a [computeActions method](undefined/references/promotion/computeActions) that returns an array of actions to perform on a cart when one or more promotions are applied. +The Promotion Module's main service has a [computeActions method](https://docs.medusajs.com/references/promotion/computeActions/index.html.md) that returns an array of actions to perform on a cart when one or more promotions are applied. Actions inform you what adjustment must be made to a cart item or shipping method. Each action is an object having the `action` property indicating the type of action. @@ -35775,7 +35797,7 @@ export interface AddItemAdjustmentAction { This action means that a new record should be created of the `LineItemAdjustment` data model in the Cart Module, or `OrderLineItemAdjustment` data model in the Order Module. -Refer to [this reference](undefined/references/promotion/interfaces/promotion.AddItemAdjustmentAction) for details on the object’s properties. +Refer to [this reference](https://docs.medusajs.com/references/promotion/interfaces/promotion.AddItemAdjustmentAction/index.html.md) for details on the object’s properties. ### `removeItemAdjustment` Action @@ -35796,7 +35818,7 @@ export interface RemoveItemAdjustmentAction { This action means that a new record should be removed of the `LineItemAdjustment` (or `OrderLineItemAdjustment`) with the specified ID in the `adjustment_id` property. -Refer to [this reference](undefined/references/promotion/interfaces/promotion.RemoveItemAdjustmentAction) for details on the object’s properties. +Refer to [this reference](https://docs.medusajs.com/references/promotion/interfaces/promotion.RemoveItemAdjustmentAction/index.html.md) for details on the object’s properties. ### `addShippingMethodAdjustment` Action @@ -35816,7 +35838,7 @@ export interface AddShippingMethodAdjustment { This action means that a new record should be created of the `ShippingMethodAdjustment` data model in the Cart Module, or `OrderShippingMethodAdjustment` data model in the Order Module. -Refer to [this reference](undefined/references/promotion/interfaces/promotion.AddShippingMethodAdjustment) for details on the object’s properties. +Refer to [this reference](https://docs.medusajs.com/references/promotion/interfaces/promotion.AddShippingMethodAdjustment/index.html.md) for details on the object’s properties. ### `removeShippingMethodAdjustment` Action @@ -35836,7 +35858,7 @@ export interface RemoveShippingMethodAdjustment { When the Medusa application receives this action type, it removes the `ShippingMethodAdjustment` (or `OrderShippingMethodAdjustment`) with the specified ID in the `adjustment_id` property. -Refer to [this reference](undefined/references/promotion/interfaces/promotion.RemoveShippingMethodAdjustment) for details on the object’s properties. +Refer to [this reference](https://docs.medusajs.com/references/promotion/interfaces/promotion.RemoveShippingMethodAdjustment/index.html.md) for details on the object’s properties. ### `campaignBudgetExceeded` Action @@ -35851,7 +35873,7 @@ export interface CampaignBudgetExceededAction { } ``` -Refer to [this reference](undefined/references/promotion/interfaces/promotion.CampaignBudgetExceededAction) for details on the object’s properties. +Refer to [this reference](https://docs.medusajs.com/references/promotion/interfaces/promotion.CampaignBudgetExceededAction/index.html.md) for details on the object’s properties. # Application Method @@ -35860,7 +35882,7 @@ In this guide, you'll learn what an application method is in the Promotion Modul ## What is an Application Method? -The [ApplicationMethod data model](undefined/references/promotion/models/ApplicationMethod) defines how a promotion is applied. It has the following properties that determine its behavior: +The [ApplicationMethod data model](https://docs.medusajs.com/references/promotion/models/ApplicationMethod/index.html.md) defines how a promotion is applied. It has the following properties that determine its behavior: |Property|Purpose|Possible Values| |---|---|---| @@ -35872,7 +35894,7 @@ The [ApplicationMethod data model](undefined/references/promotion/models/Applica When the promotion is applied to a cart item or a shipping method (in other words, when `target_type` is `items` or `shipping_methods`), you can restrict which items/shipping methods the promotion is applied to. -The `ApplicationMethod` data model has a collection of [PromotionRule](undefined/references/promotion/models/PromotionRule) records to restrict which items or shipping methods the promotion applies to. The `target_rules` property in the `ApplicationMethod` represents this relation. +The `ApplicationMethod` data model has a collection of [PromotionRule](https://docs.medusajs.com/references/promotion/models/PromotionRule/index.html.md) records to restrict which items or shipping methods the promotion applies to. The `target_rules` property in the `ApplicationMethod` represents this relation. ![A diagram showcasing the target\_rules relation between the ApplicationMethod and PromotionRule data models](https://res.cloudinary.com/dza7lstvk/image/upload/v1709898273/Medusa%20Resources/application-method-target-rules_hqaymz.jpg) @@ -35935,11 +35957,13 @@ This condition is applied on the quantity of every applicable item in the cart. In this guide, you'll learn what a campaign is and its related concepts. -Refer to this [Medusa Admin User Guide](undefined/user-guide/promotions/campaigns) to learn how to manage campaigns using the dashboard. +Refer to this [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/promotions/campaigns/index.html.md) to learn how to manage campaigns using the dashboard. ## What is a Campaign? -A [Campaign](https://docs.medusajs.com/references/promotion/models/Campaign/index.html.md) combines promotions under the same conditions, such as start and end dates. +A [Campaign](https://docs.medusajs.com/references/promotion/models/Campaign/index.html.md) combines [promotions](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/promotion/concepts#what-is-a-promotion/index.html.md) under the same conditions, such as start and end dates. + +Campaigns are useful for grouping promotions that share the same time frame or target audience. They're also useful for limiting the usage of promotions. ![A diagram showcasing the relation between the Campaign and Promotion data models](https://res.cloudinary.com/dza7lstvk/image/upload/v1709899225/Medusa%20Resources/campagin-promotion_hh3qsi.jpg) @@ -35947,7 +35971,7 @@ A [Campaign](https://docs.medusajs.com/references/promotion/models/Campaign/inde ## Campaign Limits -Each campaign has a budget represented by the [CampaignBudget data model](https://docs.medusajs.com/references/promotion/models/CampaignBudget/index.html.md). The budget limits how many times the promotion can be used. +Each campaign can have a budget represented by the [CampaignBudget data model](https://docs.medusajs.com/references/promotion/models/CampaignBudget/index.html.md). The budget limits how many times the promotion can be used. There are two types of budgets: @@ -35971,11 +35995,11 @@ However, once a promotion is applied to a cart, it remains valid until the order In this guide, you’ll learn about the main promotion and rule concepts in the Promotion Module. -Refer to this [Medusa Admin User Guide](undefined/user-guide/promotions) to learn how to manage promotions using the dashboard. +Refer to this [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/promotions/index.html.md) to learn how to manage promotions using the dashboard. ## What is a Promotion? -A promotion, represented by the [Promotion data model](undefined/references/promotion/models/Promotion), is a discount that can be applied on cart items, shipping methods, or entire orders. +A promotion, represented by the [Promotion data model](https://docs.medusajs.com/references/promotion/models/Promotion/index.html.md), is a discount that can be applied on cart items, shipping methods, or entire orders. A promotion has two types: @@ -35994,7 +36018,7 @@ The Medusa Admin UI may not provide a way to create each of these promotion exam ## Promotion Rules -A promotion can be restricted by a set of rules, each rule is represented by the [PromotionRule data model](undefined/references/promotion/models/PromotionRule). +A promotion can be restricted by a set of rules, each rule is represented by the [PromotionRule data model](https://docs.medusajs.com/references/promotion/models/PromotionRule/index.html.md). For example, you can create a promotion that only customers of the `VIP` customer group can use. @@ -36027,9 +36051,9 @@ In this case, a customer’s group must be in the `VIP` and `B2B` set of values ### Using Workflows -If you're managing promotions using [Medusa's workflows](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/medusa-workflows-reference) or the API routes that use them, you can specify rules for the promotion or its [application method](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/promotion/application-method). +If you're managing promotions using [Medusa's workflows](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/medusa-workflows-reference/index.html.md) or the API routes that use them, you can specify rules for the promotion or its [application method](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/promotion/application-method/index.html.md). -For example, if you're creating a promotion using the [createPromotionsWorkflow](undefined/references/medusa-workflows/createPromotionsWorkflow): +For example, if you're creating a promotion using the [createPromotionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createPromotionsWorkflow/index.html.md): ```ts const { result } = await createPromotionsWorkflow(container) @@ -36066,9 +36090,9 @@ In this example, the promotion is restricted to customers with the `cusgrp_123` For most use cases, it's recommended to use [workflows](#using-workflows) instead of directly using the module's service. -If you're managing promotions using the Promotion Module's service, you can specify rules for the promotion or its [application method](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/promotion/application-method) in its methods. +If you're managing promotions using the Promotion Module's service, you can specify rules for the promotion or its [application method](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/promotion/application-method/index.html.md) in its methods. -For example, if you're creating a promotion with the [createPromotions](undefined/references/promotion/createPromotions) method: +For example, if you're creating a promotion with the [createPromotions](https://docs.medusajs.com/references/promotion/createPromotions/index.html.md) method: ```ts const promotions = await promotionModuleService.createPromotions([ @@ -36153,11 +36177,11 @@ A promotion can be applied on line items and shipping methods of a cart. Medusa ![A diagram showcasing an example of how data models from the Cart and Promotion modules are linked](https://res.cloudinary.com/dza7lstvk/image/upload/v1711538015/Medusa%20Resources/cart-promotion_kuh9vm.jpg) -Medusa also defines a read-only link between the [Cart Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/cart)'s `LineItemAdjustment` data model and the `Promotion` data model. Because the link is read-only from the `LineItemAdjustment`'s side, you can only retrieve the promotion applied on a line item, and not the other way around. +Medusa also defines a read-only link between the [Cart Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/cart/index.html.md)'s `LineItemAdjustment` data model and the `Promotion` data model. Because the link is read-only from the `LineItemAdjustment`'s side, you can only retrieve the promotion applied on a line item, and not the other way around. ### Retrieve with Query -To retrieve the carts that a promotion is applied on with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `carts.*` in `fields`: +To retrieve the carts that a promotion is applied on with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `carts.*` in `fields`: To retrieve the promotion of a line item adjustment, pass `promotion.*` in `fields`. @@ -36193,7 +36217,7 @@ const { data: promotions } = useQueryGraphStep({ ### Manage with Link -To manage the promotions of a cart, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the promotions of a cart, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -36240,7 +36264,7 @@ An order is associated with the promotion applied on it. Medusa defines a link b ### Retrieve with Query -To retrieve the orders a promotion is applied on with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `orders.*` in `fields`: +To retrieve the orders a promotion is applied on with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `orders.*` in `fields`: ### query.graph @@ -36274,7 +36298,7 @@ const { data: promotions } = useQueryGraphStep({ ### Manage with Link -To manage the promotion of an order, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the promotion of an order, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -36316,24 +36340,24 @@ createRemoteLinkStep({ In this section of the documentation, you will find resources to learn more about the Promotion Module and how to use it in your application. -Refer to the [Medusa Admin User Guide](undefined/user-guide/promotions) to learn how to manage promotions using the dashboard. +Refer to the [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/promotions/index.html.md) to learn how to manage promotions using the dashboard. -Medusa has promotion related features available out-of-the-box through the Promotion Module. A [module](undefined/docs/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Promotion Module. +Medusa has promotion related features available out-of-the-box through the Promotion Module. A [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Promotion Module. -Learn more about why modules are isolated in [this documentation](undefined/docs/learn/fundamentals/modules/isolation). +Learn more about why modules are isolated in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md). ## Promotion Features -- [Discount Functionalities](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/promotion/concepts): A promotion discounts an amount or percentage of a cart's items, shipping methods, or the entire order. -- [Flexible Promotion Rules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/promotion/concepts#flexible-rules): A promotion has rules that restricts when the promotion is applied. -- [Campaign Management](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/promotion/campaign): A campaign combines promotions under the same conditions, such as start and end dates, and budget configurations. -- [Apply Promotion on Carts and Orders](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/promotion/actions): Apply promotions on carts and orders to discount items, shipping methods, or the entire order. +- [Discount Functionalities](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/promotion/concepts/index.html.md): A promotion discounts an amount or percentage of a cart's items, shipping methods, or the entire order. +- [Flexible Promotion Rules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/promotion/concepts#flexible-rules/index.html.md): A promotion has rules that restricts when the promotion is applied. +- [Campaign Management](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/promotion/campaign/index.html.md): A campaign combines promotions under the same conditions, such as start and end dates, and budget configurations. +- [Apply Promotion on Carts and Orders](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/promotion/actions/index.html.md): Apply promotions on carts and orders to discount items, shipping methods, or the entire order. *** ## How to Use the Promotion Module -In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](undefined/docs/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package. @@ -36455,7 +36479,7 @@ export const config = { } ``` -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). *** @@ -36472,13 +36496,13 @@ By default, promotions are tax-exclusive, meaning that the discount amount is ap A tax-inclusive promotion is a promotion for which taxes are calculated from the discount amount entered by the merchant. -When a promotion is tax-inclusive, the discount amount is reduced by the calculated tax amount based on the [tax region's rate](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/tax/tax-region). The reduced discount amount is then applied to the cart total. +When a promotion is tax-inclusive, the discount amount is reduced by the calculated tax amount based on the [tax region's rate](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/tax/tax-region/index.html.md). The reduced discount amount is then applied to the cart total. Tax-inclusiveness doesn't apply to Buy X Get Y promotions. ### When to Use Tax-Inclusive Promotions -Tax-inclusive promotions are most useful when using [tax-inclusive prices](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/tax-inclusive-pricing) for items in the cart. +Tax-inclusive promotions are most useful when using [tax-inclusive prices](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/tax-inclusive-pricing/index.html.md) for items in the cart. In this scenario, Medusa applies taxes consistently across the cart, ensuring that the total price reflects the taxes and promotions correctly. @@ -36488,23 +36512,23 @@ You can see this in action in the [examples below](#tax-inclusiveness-examples). ## What Makes a Promotion Tax-Inclusive? -The [Promotion data model](undefined/references/promotion/models/Promotion) has an `is_tax_inclusive` property that determines whether the promotion is tax-inclusive. +The [Promotion data model](https://docs.medusajs.com/references/promotion/models/Promotion/index.html.md) has an `is_tax_inclusive` property that determines whether the promotion is tax-inclusive. If `is_tax_inclusive` is disabled (which is the default), the promotion's discount amount will be applied as-is to the cart, before taxes are calculated. See an example in the [Tax-Exclusive Promotion Example](#tax-exclusive-promotion-example) section. -If `is_tax_inclusive` is enabled, the promotion's discount amount will first be reduced by the calculated tax amount (based on the [tax region's rate](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/tax/tax-region)). The reduced discount amount is then applied to the cart total. See an example in the [Tax-Inclusive Promotion Example](#tax-inclusive-promotion-example) section. +If `is_tax_inclusive` is enabled, the promotion's discount amount will first be reduced by the calculated tax amount (based on the [tax region's rate](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/tax/tax-region/index.html.md)). The reduced discount amount is then applied to the cart total. See an example in the [Tax-Inclusive Promotion Example](#tax-inclusive-promotion-example) section. *** ## How to Set a Promotion as Tax-Inclusive -You can enable tax-inclusiveness for a promotion when [creating it in the Medusa Admin](undefined/user-guide/promotions/create). +You can enable tax-inclusiveness for a promotion when [creating it in the Medusa Admin](https://docs.medusajs.com/user-guide/promotions/create/index.html.md). -You can set the `is_tax_inclusive` property when creating a promotion by using either the [Promotion workflows](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/promotion/workflows) or the [Promotion Module's service](undefined/references/promotion). +You can set the `is_tax_inclusive` property when creating a promotion by using either the [Promotion workflows](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/promotion/workflows/index.html.md) or the [Promotion Module's service](https://docs.medusajs.com/references/promotion/index.html.md). -For most use cases, it's recommended to use [workflows](undefined/docs/learn/fundamentals/workflows) instead of directly using the module's service, as they implement the necessary rollback mechanisms in case of errors. +For most use cases, it's recommended to use [workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) instead of directly using the module's service, as they implement the necessary rollback mechanisms in case of errors. -For example, if you're creating a promotion with the [createPromotionsWorkflow](undefined/references/medusa-workflows/createPromotionsWorkflow) in an API route: +For example, if you're creating a promotion with the [createPromotionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createPromotionsWorkflow/index.html.md) in an API route: ```ts highlights={[["17"]]} import type { @@ -36553,7 +36577,7 @@ Consider the following scenario: - A tax-exclusive promotion gives a `$10` discount on the cart's total. - The cart's tax region has a `25%` tax rate. - The cart total before applying the promotion is `$100`. -- [The prices in the cart's tax region are tax-exclusive](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/tax-inclusive-pricing). +- [The prices in the cart's tax region are tax-exclusive](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/tax-inclusive-pricing/index.html.md). The result: @@ -36568,7 +36592,7 @@ Consider the following scenario: - A tax-inclusive promotion gives a `$10` discount on the cart's total. - The cart's tax region has a `25%` tax rate. - The cart total before applying the promotion is `$100`. -- [The prices in the cart's tax region are tax-exclusive](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/tax-inclusive-pricing). +- [The prices in the cart's tax region are tax-exclusive](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/tax-inclusive-pricing/index.html.md). The result: @@ -36584,7 +36608,7 @@ Consider the following scenario: - A tax-inclusive promotion gives a `$10` discount on the cart's total. - The cart's tax region has a `25%` tax rate. - The cart total before applying the promotion is `$100`. -- [The prices in the cart's tax region are tax-inclusive](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/tax-inclusive-pricing). +- [The prices in the cart's tax region are tax-inclusive](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/tax-inclusive-pricing/index.html.md). The result: @@ -36616,11 +36640,11 @@ Read-only links are used to query data across modules, but the relations aren't ## Cart Module -Medusa defines a read-only link between the [Cart Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/cart)'s `Cart` data model and the `Region` data model. Because the link is read-only from the `Cart`'s side, you can only retrieve the region of a cart, and not the other way around. +Medusa defines a read-only link between the [Cart Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/cart/index.html.md)'s `Cart` data model and the `Region` data model. Because the link is read-only from the `Cart`'s side, you can only retrieve the region of a cart, and not the other way around. ### Retrieve with Query -To retrieve the region of a cart with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `region.*` in `fields`: +To retrieve the region of a cart with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `region.*` in `fields`: ### query.graph @@ -36656,11 +36680,11 @@ const { data: carts } = useQueryGraphStep({ ## Order Module -Medusa defines a read-only link between the [Order Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order)'s `Order` data model and the `Region` data model. Because the link is read-only from the `Order`'s side, you can only retrieve the region of an order, and not the other way around. +Medusa defines a read-only link between the [Order Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/index.html.md)'s `Order` data model and the `Region` data model. Because the link is read-only from the `Order`'s side, you can only retrieve the region of an order, and not the other way around. ### Retrieve with Query -To retrieve the region of an order with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `region.*` in `fields`: +To retrieve the region of an order with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `region.*` in `fields`: ### query.graph @@ -36704,7 +36728,7 @@ Medusa defines a module link between the `PaymentProvider` and the `Region` data ### Retrieve with Query -To retrieve the payment providers of a region with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `payment_providers.*` in `fields`: +To retrieve the payment providers of a region with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `payment_providers.*` in `fields`: ### query.graph @@ -36738,7 +36762,7 @@ const { data: regions } = useQueryGraphStep({ ### Manage with Link -To manage the payment providers in a region, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the payment providers in a region, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -36780,25 +36804,25 @@ createRemoteLinkStep({ In this section of the documentation, you will find resources to learn more about the Region Module and how to use it in your application. -Refer to the [Medusa Admin User Guide](undefined/user-guide/settings/regions) to learn how to manage regions using the dashboard. +Refer to the [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/settings/regions/index.html.md) to learn how to manage regions using the dashboard. -Medusa has region related features available out-of-the-box through the Region Module. A [module](undefined/docs/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Region Module. +Medusa has region related features available out-of-the-box through the Region Module. A [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Region Module. -Learn more about why modules are isolated in [this documentation](undefined/docs/learn/fundamentals/modules/isolation). +Learn more about why modules are isolated in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md). *** ## Region Features -- [Region Management](undefined/references/region/models/Region): Manage regions in your store. You can create regions with different currencies and settings. -- [Multi-Currency Support](undefined/references/region/models/Region): Each region has a currency. You can support multiple currencies in your store by creating multiple regions. -- [Different Settings Per Region](undefined/references/region/models/Region): Each region has its own settings, such as what countries belong to a region or its tax settings. +- [Region Management](https://docs.medusajs.com/references/region/models/Region/index.html.md): Manage regions in your store. You can create regions with different currencies and settings. +- [Multi-Currency Support](https://docs.medusajs.com/references/region/models/Region/index.html.md): Each region has a currency. You can support multiple currencies in your store by creating multiple regions. +- [Different Settings Per Region](https://docs.medusajs.com/references/region/models/Region/index.html.md): Each region has its own settings, such as what countries belong to a region or its tax settings. *** ## How to Use Region Module's Service -In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](undefined/docs/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package. @@ -36914,7 +36938,7 @@ export const config = { } ``` -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). *** @@ -36949,7 +36973,7 @@ Medusa defines a link between the `ApiKey` and the `SalesChannel` data models. ### Retrieve with Query -To retrieve the API keys associated with a sales channel with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `publishable_api_keys.*` in `fields`: +To retrieve the API keys associated with a sales channel with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `publishable_api_keys.*` in `fields`: ### query.graph @@ -36983,7 +37007,7 @@ const { data: salesChannels } = useQueryGraphStep({ ### Manage with Link -To manage the sales channels of an API key, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the sales channels of an API key, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -37024,11 +37048,11 @@ createRemoteLinkStep({ ## Cart Module -Medusa defines a read-only link between the [Cart Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/cart)'s `Cart` data model and the `SalesChannel` data model. Because the link is read-only from the `Cart`'s side, you can only retrieve the sales channel of a cart, and not the other way around. +Medusa defines a read-only link between the [Cart Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/cart/index.html.md)'s `Cart` data model and the `SalesChannel` data model. Because the link is read-only from the `Cart`'s side, you can only retrieve the sales channel of a cart, and not the other way around. ### Retrieve with Query -To retrieve the sales channel of a cart with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `sales_channel.*` in `fields`: +To retrieve the sales channel of a cart with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `sales_channel.*` in `fields`: ### query.graph @@ -37064,11 +37088,11 @@ const { data: carts } = useQueryGraphStep({ ## Order Module -Medusa defines a read-only link between the [Order Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order)'s `Order` data model and the `SalesChannel` data model. Because the link is read-only from the `Order`'s side, you can only retrieve the sales channel of an order, and not the other way around. +Medusa defines a read-only link between the [Order Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/index.html.md)'s `Order` data model and the `SalesChannel` data model. Because the link is read-only from the `Order`'s side, you can only retrieve the sales channel of an order, and not the other way around. ### Retrieve with Query -To retrieve the sales channel of an order with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `sales_channel.*` in `fields`: +To retrieve the sales channel of an order with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `sales_channel.*` in `fields`: ### query.graph @@ -37112,7 +37136,7 @@ A product can be available in more than one sales channel. You can retrieve only ### Retrieve with Query -To retrieve the products of a sales channel with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `products.*` in `fields`: +To retrieve the products of a sales channel with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `products.*` in `fields`: ### query.graph @@ -37146,7 +37170,7 @@ const { data: salesChannels } = useQueryGraphStep({ ### Manage with Link -To manage the sales channels of a product, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the sales channels of a product, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -37195,7 +37219,7 @@ Medusa defines a link between the `SalesChannel` and `StockLocation` data models ### Retrieve with Query -To retrieve the stock locations of a sales channel with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `stock_locations.*` in `fields`: +To retrieve the stock locations of a sales channel with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `stock_locations.*` in `fields`: ### query.graph @@ -37229,7 +37253,7 @@ const { data: salesChannels } = useQueryGraphStep({ ### Manage with Link -To manage the stock locations of a sales channel, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the stock locations of a sales channel, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -37271,11 +37295,11 @@ createRemoteLinkStep({ In this section of the documentation, you will find resources to learn more about the Sales Channel Module and how to use it in your application. -Refer to the [Medusa Admin User Guide](undefined/user-guide/settings/sales-channels) to learn how to manage sales channels using the dashboard. +Refer to the [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/settings/sales-channels/index.html.md) to learn how to manage sales channels using the dashboard. -Medusa has sales channel related features available out-of-the-box through the Sales Channel Module. A [module](undefined/docs/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Sales Channel Module. +Medusa has sales channel related features available out-of-the-box through the Sales Channel Module. A [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Sales Channel Module. -Learn more about why modules are isolated in [this documentation](undefined/docs/learn/fundamentals/modules/isolation). +Learn more about why modules are isolated in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md). ## What's a Sales Channel? @@ -37291,16 +37315,16 @@ Some use case examples for using a sales channel: ## Sales Channel Features -- [Sales Channel Management](undefined/references/sales-channel/models/SalesChannel): Manage sales channels in your store. Each sales channel has different meta information such as name or description, allowing you to easily differentiate between sales channels. -- [Product Availability](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/sales-channel/links-to-other-modules): Medusa uses the Product and Sales Channel modules to allow merchants to specify a product's availability per sales channel. -- [Cart and Order Scoping](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/sales-channel/links-to-other-modules): Carts, available through the Cart Module, are scoped to a sales channel. Paired with the product availability feature, you benefit from more features like allowing only products available in sales channel in a cart. -- [Inventory Availability Per Sales Channel](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/sales-channel/links-to-other-modules): Medusa links sales channels to stock locations, allowing you to retrieve available inventory of products based on the specified sales channel. +- [Sales Channel Management](https://docs.medusajs.com/references/sales-channel/models/SalesChannel/index.html.md): Manage sales channels in your store. Each sales channel has different meta information such as name or description, allowing you to easily differentiate between sales channels. +- [Product Availability](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/sales-channel/links-to-other-modules/index.html.md): Medusa uses the Product and Sales Channel modules to allow merchants to specify a product's availability per sales channel. +- [Cart and Order Scoping](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/sales-channel/links-to-other-modules/index.html.md): Carts, available through the Cart Module, are scoped to a sales channel. Paired with the product availability feature, you benefit from more features like allowing only products available in sales channel in a cart. +- [Inventory Availability Per Sales Channel](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/sales-channel/links-to-other-modules/index.html.md): Medusa links sales channels to stock locations, allowing you to retrieve available inventory of products based on the specified sales channel. *** ## How to Use Sales Channel Module's Service -In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](undefined/docs/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package. @@ -37422,7 +37446,7 @@ export const config = { } ``` -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). *** @@ -37448,7 +37472,7 @@ The Medusa application infers the associated sales channels and ensures that onl ## How to Create a Publishable API Key? -To create a publishable API key, either use the [Medusa Admin](undefined/user-guide/settings/developer/publishable-api-keys) or the [Admin API Routes](undefined/api/admin#publishable-api-keys). +To create a publishable API key, either use the [Medusa Admin](https://docs.medusajs.com/user-guide/settings/developer/publishable-api-keys/index.html.md) or the [Admin API Routes](https://docs.medusajs.com/api/admin#publishable-api-keys). *** @@ -37477,7 +37501,7 @@ export async function GET( In this example, you retrieve the scope's sales channel IDs using `req.publishable_key_context.sales_channel_ids`, whose value is an array of IDs. -You can then use these IDs based on your business logic. For example, you can retrieve the sales channels' details using [Query](undefined/docs/learn/fundamentals/module-links/query). +You can then use these IDs based on your business logic. For example, you can retrieve the sales channels' details using [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md). Notice that the request object's type is `MedusaStoreRequest` instead of `MedusaRequest` to ensure the availability of the `publishable_key_context` property. @@ -37488,15 +37512,15 @@ In this guide, you’ll learn about the main concepts in the Stock Location Modu ## Stock Location -A stock location, represented by the [StockLocation data model](undefined/references/stock-location-next/models/StockLocation), represents a location where stock items are kept. For example, a warehouse. +A stock location, represented by the [StockLocation data model](https://docs.medusajs.com/references/stock-location-next/models/StockLocation/index.html.md), represents a location where stock items are kept. For example, a warehouse. -Medusa uses stock locations to provide inventory details, stored and managed by the [Inventory Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/inventory/concepts), per location. +Medusa uses stock locations to provide inventory details, stored and managed by the [Inventory Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/inventory/concepts/index.html.md), per location. *** ## StockLocationAddress -The [StockLocationAddress data model](undefined/references/stock-location-next/models/StockLocationAddress) belongs to the `StockLocation` data model. It provides more detailed information about the location, such as country code or street address. +The [StockLocationAddress data model](https://docs.medusajs.com/references/stock-location-next/models/StockLocationAddress/index.html.md) belongs to the `StockLocation` data model. It provides more detailed information about the location, such as country code or street address. # Links between Stock Location Module and Other Modules @@ -37532,7 +37556,7 @@ Medusa also defines a link between the `FulfillmentProvider` and `StockLocation` ### Retrieve with Query -To retrieve the fulfillment sets of a stock location with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `fulfillment_sets.*` in `fields`: +To retrieve the fulfillment sets of a stock location with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `fulfillment_sets.*` in `fields`: To retrieve the fulfillment providers, pass `fulfillment_providers.*` in `fields`. @@ -37568,7 +37592,7 @@ const { data: stockLocations } = useQueryGraphStep({ ### Manage with Link -To manage the stock location of a fulfillment set, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the stock location of a fulfillment set, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -37609,11 +37633,11 @@ createRemoteLinkStep({ ## Inventory Module -Medusa defines a read-only link between the [Inventory Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/inventory)'s `InventoryLevel` data model and the `StockLocation` data model. Because the link is read-only from the `InventoryLevel`'s side, you can only retrieve the stock location of an inventory level, and not the other way around. +Medusa defines a read-only link between the [Inventory Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/inventory/index.html.md)'s `InventoryLevel` data model and the `StockLocation` data model. Because the link is read-only from the `InventoryLevel`'s side, you can only retrieve the stock location of an inventory level, and not the other way around. ### Retrieve with Query -To retrieve the stock locations of an inventory level with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `stock_locations.*` in `fields`: +To retrieve the stock locations of an inventory level with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `stock_locations.*` in `fields`: ### query.graph @@ -37657,7 +37681,7 @@ Medusa defines a link between the `SalesChannel` and `StockLocation` data models ### Retrieve with Query -To retrieve the sales channels of a stock location with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `sales_channels.*` in `fields`: +To retrieve the sales channels of a stock location with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `sales_channels.*` in `fields`: ### query.graph @@ -37691,7 +37715,7 @@ const { data: stockLocations } = useQueryGraphStep({ ### Manage with Link -To manage the stock locations of a sales channel, use [Link](undefined/docs/learn/fundamentals/module-links/link): +To manage the stock locations of a sales channel, use [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): ### link.create @@ -37733,22 +37757,22 @@ createRemoteLinkStep({ In this section of the documentation, you will find resources to learn more about the Stock Location Module and how to use it in your application. -Refer to the [Medusa Admin User Guide](undefined/user-guide/settings/locations-and-shipping) to learn how to manage stock locations using the dashboard. +Refer to the [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/settings/locations-and-shipping/index.html.md) to learn how to manage stock locations using the dashboard. -Medusa has stock location related features available out-of-the-box through the Stock Location Module. A [module](undefined/docs/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Stock Location Module. +Medusa has stock location related features available out-of-the-box through the Stock Location Module. A [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Stock Location Module. -Learn more about why modules are isolated in [this documentation](undefined/docs/learn/fundamentals/modules/isolation). +Learn more about why modules are isolated in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md). ## Stock Location Features -- [Stock Location Management](undefined/references/stock-location-next/models): Store and manage stock locations. Medusa links stock locations with data models of other modules that require a location, such as the [Inventory Module's InventoryLevel](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/stock-location/links-to-other-modules). -- [Address Management](undefined/references/stock-location-next/models/StockLocationAddress): Manage the address of each stock location. +- [Stock Location Management](https://docs.medusajs.com/references/stock-location-next/models/index.html.md): Store and manage stock locations. Medusa links stock locations with data models of other modules that require a location, such as the [Inventory Module's InventoryLevel](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/stock-location/links-to-other-modules/index.html.md). +- [Address Management](https://docs.medusajs.com/references/stock-location-next/models/StockLocationAddress/index.html.md): Manage the address of each stock location. *** ## How to Use Stock Location Module's Service -In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](undefined/docs/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package. @@ -37861,7 +37885,7 @@ export const config = { } ``` -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). *** @@ -37886,11 +37910,11 @@ Read-only links are used to query data across modules, but the relations aren't The Store Module has a `Currency` data model that stores the supported currencies of a store. However, these currencies don't hold all the details of a currency, such as its name or symbol. -Instead, Medusa defines a read-only link between the [Currency Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/currency)'s `Currency` data model and the Store Module's `StoreCurrency` data model. This means you can retrieve the details of a store's supported currencies, but you don't manage the links in a pivot table in the database. The currencies of a store are determined by the `currency_code` of the [Currency](undefined/references/store/models/StoreCurrency) data model in the Store Module (not in the Currency Module). +Instead, Medusa defines a read-only link between the [Currency Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/currency/index.html.md)'s `Currency` data model and the Store Module's `StoreCurrency` data model. This means you can retrieve the details of a store's supported currencies, but you don't manage the links in a pivot table in the database. The currencies of a store are determined by the `currency_code` of the [Currency](https://docs.medusajs.com/references/store/models/StoreCurrency/index.html.md) data model in the Store Module (not in the Currency Module). ### Retrieve with Query -To retrieve the details of a store's currencies with [Query](undefined/docs/learn/fundamentals/module-links/query), pass `supported_currencies.currency.*` in `fields`: +To retrieve the details of a store's currencies with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), pass `supported_currencies.currency.*` in `fields`: ### query.graph @@ -37927,22 +37951,22 @@ const { data: stores } = useQueryGraphStep({ In this section of the documentation, you will find resources to learn more about the Store Module and how to use it in your application. -Refer to the [Medusa Admin User Guide](undefined/user-guide/settings/store) to learn how to manage your store using the dashboard. +Refer to the [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/settings/store/index.html.md) to learn how to manage your store using the dashboard. -Medusa has store related features available out-of-the-box through the Store Module. A [module](undefined/docs/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Store Module. +Medusa has store related features available out-of-the-box through the Store Module. A [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Store Module. -Learn more about why modules are isolated in [this documentation](undefined/docs/learn/fundamentals/modules/isolation). +Learn more about why modules are isolated in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md). ## Store Features -- [Store Management](undefined/references/store/models/Store): Create and manage stores in your application. -- [Multi-Tenancy Support](undefined/references/store/models/Store): Create multiple stores, each having its own configurations. +- [Store Management](https://docs.medusajs.com/references/store/models/Store/index.html.md): Create and manage stores in your application. +- [Multi-Tenancy Support](https://docs.medusajs.com/references/store/models/Store/index.html.md): Create multiple stores, each having its own configurations. *** ## How to Use Store Module's Service -In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](undefined/docs/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package. @@ -38059,7 +38083,7 @@ export const config = { } ``` -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). *** @@ -38070,7 +38094,7 @@ In this guide, you'll learn about the options of the Tax Module. ## providers -The `providers` option is an array of either [tax module providers](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/tax/tax-provider) or path to a file that defines a tax provider. +The `providers` option is an array of either [tax module providers](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/tax/tax-provider/index.html.md) or path to a file that defines a tax provider. When the Medusa application starts, these providers are registered and can be used to retrieve tax lines. @@ -38111,24 +38135,24 @@ The objects in the array accept the following properties: In this section of the documentation, you will find resources to learn more about the Tax Module and how to use it in your application. -Refer to the [Medusa Admin User Guide](undefined/user-guide/settings/tax-regions) to learn how to manage tax regions using the dashboard. +Refer to the [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/settings/tax-regions/index.html.md) to learn how to manage tax regions using the dashboard. -Medusa has tax related features available out-of-the-box through the Tax Module. A [module](undefined/docs/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Tax Module. +Medusa has tax related features available out-of-the-box through the Tax Module. A [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this Tax Module. -Learn more about why modules are isolated in [this documentation](undefined/docs/learn/fundamentals/modules/isolation). +Learn more about why modules are isolated in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md). ## Tax Features -- [Tax Settings Per Region](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/tax/tax-region): Set different tax settings for each tax region. -- [Tax Rates and Rules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/tax/tax-rates-and-rules): Manage each region's default tax rates and override them with conditioned tax rates. -- [Retrieve Tax Lines for carts and orders](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/tax/tax-calculation-with-provider): Calculate and retrieve the tax lines of a cart or order's line items and shipping methods with tax providers. -- [Custom Tax Providers](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/tax/tax-provider): Create custom tax providers to calculate tax lines differently for each tax region. +- [Tax Settings Per Region](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/tax/tax-region/index.html.md): Set different tax settings for each tax region. +- [Tax Rates and Rules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/tax/tax-rates-and-rules/index.html.md): Manage each region's default tax rates and override them with conditioned tax rates. +- [Retrieve Tax Lines for carts and orders](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/tax/tax-calculation-with-provider/index.html.md): Calculate and retrieve the tax lines of a cart or order's line items and shipping methods with tax providers. +- [Custom Tax Providers](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/tax/tax-provider/index.html.md): Create custom tax providers to calculate tax lines differently for each tax region. *** ## How to Use Tax Module's Service -In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](undefined/docs/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package. @@ -38241,13 +38265,13 @@ export const config = { } ``` -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). *** ## Configure Tax Module -The Tax Module accepts options for further configurations. Refer to [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/tax/module-options) for details on the module's options. +The Tax Module accepts options for further configurations. Refer to [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/tax/module-options/index.html.md) for details on the module's options. *** @@ -38258,7 +38282,7 @@ In this guide, you’ll learn how tax lines are calculated using the tax provide ## Tax Lines Calculation -Tax lines are calculated and retrieved using the [getTaxLines method of the Tax Module’s main service](undefined/references/tax/getTaxLines). It accepts an array of line items and shipping methods, and the context of the calculation. +Tax lines are calculated and retrieved using the [getTaxLines method of the Tax Module’s main service](https://docs.medusajs.com/references/tax/getTaxLines/index.html.md). It accepts an array of line items and shipping methods, and the context of the calculation. For example: @@ -38314,24 +38338,24 @@ The method returns tax lines for the line item and shipping methods. For example ## Using the Tax Provider in the Calculation -The tax lines retrieved by the `getTaxLines` method are actually retrieved from the tax region’s [Tax Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/tax/tax-provider). +The tax lines retrieved by the `getTaxLines` method are actually retrieved from the tax region’s [Tax Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/tax/tax-provider/index.html.md). A tax module implements the logic to shape tax lines. Each tax region uses a tax provider. -Learn more about tax providers, configuring, and creating them in the [Tax Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/tax/tax-provider) guide. +Learn more about tax providers, configuring, and creating them in the [Tax Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/tax/tax-provider/index.html.md) guide. # Tax Module Provider In this guide, you’ll learn about the Tax Module Provider and how it's used. -Refer to this [Medusa Admin User Guide](undefined/user-guide/settings/tax-regions) to learn how to manage tax provider of a tax region using the dashboard. +Refer to this [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/settings/tax-regions/index.html.md) to learn how to manage tax provider of a tax region using the dashboard. ## What is a Tax Module Provider? The Tax Module Provider handles tax line calculations in the Medusa application. It integrates third-party tax services, such as TaxJar, or implements custom tax calculation logic. -The Medusa application uses the Tax Module Provider whenever it needs to calculate tax lines for a cart or order, or when you [calculate the tax lines using the Tax Module's service](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/tax/tax-calculation-with-provider). +The Medusa application uses the Tax Module Provider whenever it needs to calculate tax lines for a cart or order, or when you [calculate the tax lines using the Tax Module's service](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/tax/tax-calculation-with-provider/index.html.md). ![Diagram showcasing the communication between Medusa the Tax Module Provider, and the third-party tax provider.](https://res.cloudinary.com/dza7lstvk/image/upload/v1746790996/Medusa%20Resources/tax-provider-service_kcgpne.jpg) @@ -38339,7 +38363,7 @@ The Medusa application uses the Tax Module Provider whenever it needs to calcula ## Default Tax Provider -The Tax Module provides a `system` tax provider that acts as a placeholder tax provider. It performs basic tax calculation, as you can see in the [Create Tax Module Provider](undefined/references/tax/provider#gettaxlines) guide. +The Tax Module provides a `system` tax provider that acts as a placeholder tax provider. It performs basic tax calculation, as you can see in the [Create Tax Module Provider](https://docs.medusajs.com/references/tax/provider#gettaxlines/index.html.md) guide. This provider is installed by default in your application and you can use it with tax regions. @@ -38353,9 +38377,9 @@ A Tax Module Provider is a module whose service implements the `ITaxProvider` im The module can have multiple tax provider services, where each are registered as separate tax providers. -Refer to the [Create Tax Module Provider](undefined/references/tax/provider) guide to learn how to create a Tax Module Provider. +Refer to the [Create Tax Module Provider](https://docs.medusajs.com/references/tax/provider/index.html.md) guide to learn how to create a Tax Module Provider. -After you create a tax provider, you can choose it as the default Tax Module Provider for a region in the [Medusa Admin dashboard](undefined/user-guide/settings/tax-regions). +After you create a tax provider, you can choose it as the default Tax Module Provider for a region in the [Medusa Admin dashboard](https://docs.medusajs.com/user-guide/settings/tax-regions/index.html.md). *** @@ -38365,7 +38389,7 @@ After you create a tax provider, you can choose it as the default Tax Module Pro The Tax Module accepts a `providers` option that allows you to configure the providers registered in your application. -Learn more about this option in the [Module Options](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/tax/module-options) guide. +Learn more about this option in the [Module Options](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/tax/module-options/index.html.md) guide. ### Registration on Application Start @@ -38375,7 +38399,7 @@ For each Tax Module Provider, the Medusa application finds all tax provider serv ### TaxProvider Data Model -A registered tax provider is represented by the [TaxProvider data model](undefined/references/tax/models/TaxProvider) in the Medusa application. +A registered tax provider is represented by the [TaxProvider data model](https://docs.medusajs.com/references/tax/models/TaxProvider/index.html.md) in the Medusa application. This data model is used to reference a service in the Tax Module Provider and determine whether it's installed in the application. @@ -38399,7 +38423,7 @@ Then, the next time the Medusa application starts, it will set the `is_enabled` In this guide, you’ll learn about tax rates and rules. -Refer to this [Medusa Admin User Guide](undefined/user-guide/settings/tax-regions#manage-tax-rate-overrides) to learn how to manage tax rates using the dashboard. +Refer to this [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/settings/tax-regions#manage-tax-rate-overrides/index.html.md) to learn how to manage tax rates using the dashboard. ## What are Tax Rates? @@ -38421,7 +38445,7 @@ You can create tax rates that override the default for specific conditions or ru For example, you can have a default 10% tax rate, but for products of type “Shirt” it is 15%. -A tax region can have multiple tax rates, and each tax rate can have multiple tax rules. The [TaxRateRule data model](undefined/references/tax/models/TaxRateRule) represents a tax rate’s rule. +A tax region can have multiple tax rates, and each tax rate can have multiple tax rules. The [TaxRateRule data model](https://docs.medusajs.com/references/tax/models/TaxRateRule/index.html.md) represents a tax rate’s rule. ![A diagram showcasing the relation between TaxRegion, TaxRate, and TaxRateRule](https://res.cloudinary.com/dza7lstvk/image/upload/v1711462167/Medusa%20Resources/tax-rate-rule_enzbp2.jpg) @@ -38437,11 +38461,11 @@ So, to override the default tax rate for product types “Shirt”, you create a In this document, you’ll learn about tax regions and how to use them with the Region Module. -Refer to this [Medusa Admin User Guide](undefined/user-guide/settings/tax-regions) to learn how to manage tax regions using the dashboard. +Refer to this [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/settings/tax-regions/index.html.md) to learn how to manage tax regions using the dashboard. ## What is a Tax Region? -A tax region, represented by the [TaxRegion data model](undefined/references/tax/models/TaxRegion), stores tax settings related to a region that your store serves. +A tax region, represented by the [TaxRegion data model](https://docs.medusajs.com/references/tax/models/TaxRegion/index.html.md), stores tax settings related to a region that your store serves. Tax regions can inherit settings and rules from a parent tax region. @@ -38455,7 +38479,7 @@ Tax rules define the tax rates and behavior within a tax region. They specify: - Which products the tax applies to. - Other custom rules to determine tax applicability. -Learn more about tax rules in the [Tax Rates and Rules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/tax/tax-rates-and-rules) guide. +Learn more about tax rules in the [Tax Rates and Rules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/tax/tax-rates-and-rules/index.html.md) guide. *** @@ -38465,14 +38489,14 @@ Each tax region can have a default tax provider. The tax provider is responsible You can use Medusa's default tax provider or create a custom one, allowing you to integrate with third-party tax services or implement your own tax calculation logic. -Learn more about tax providers in the [Tax Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/tax/tax-provider) guide. +Learn more about tax providers in the [Tax Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/tax/tax-provider/index.html.md) guide. # Send Invite User Email Notification In this guide, you'll learn how to handle the `invite.created` and `invite.resent` events to send an invite email (or other notification type) to the user. -Refer to the [Manage Invites](undefined/user-guide/settings/users/invites) user guide to learn how to manage invites using the Medusa Admin. +Refer to the [Manage Invites](https://docs.medusajs.com/user-guide/settings/users/invites/index.html.md) user guide to learn how to manage invites using the Medusa Admin. ## User Invite Flow Overview @@ -38480,11 +38504,11 @@ Refer to the [Manage Invites](undefined/user-guide/settings/users/invites) user Admin users can add new users to their store by sending them an invite. The flow for inviting users is as follows: -1. An admin user invites a user either through the [Medusa Admin](undefined/user-guide/settings/users/invites) or using the [Create Invite API route](undefined/api/admin#invites_postinvites). +1. An admin user invites a user either through the [Medusa Admin](https://docs.medusajs.com/user-guide/settings/users/invites/index.html.md) or using the [Create Invite API route](https://docs.medusajs.com/api/admin#invites_postinvites). 2. The invite is created and the `invite.created` event is emitted. - At this point, you can handle the event to send an email or notification to the user. 3. The invited user receives the invite and can accept it, which creates a new user. - - The invited user can accept the invite either through the Medusa Admin or using the [Accept Invite API route](undefined/api/admin#invites_postinvitesaccept). + - The invited user can accept the invite either through the Medusa Admin or using the [Accept Invite API route](https://docs.medusajs.com/api/admin#invites_postinvitesaccept). The admin user can also resend the invite if the invited user doesn't receive the invite or doesn't accept it before expiry, which emits the `invite.resent` event. @@ -38498,13 +38522,13 @@ After adding the subscriber, you will have a complete user invite flow that you To send an email or notification to the user, you must have a Notification Module Provider set up. -Medusa provides providers like [SendGrid](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid) and [Resend](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/integrations/guides/resend), and you can also [create your own custom provider](undefined/references/notification-provider-module). +Medusa provides providers like [SendGrid](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid/index.html.md) and [Resend](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/integrations/guides/resend/index.html.md), and you can also [create your own custom provider](https://docs.medusajs.com/references/notification-provider-module/index.html.md). -Refer to the [Notification Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification#what-is-a-notification-module-provider) documentation for a list of available providers and how to set them up. +Refer to the [Notification Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification#what-is-a-notification-module-provider/index.html.md) documentation for a list of available providers and how to set them up. ### Testing with the Local Notification Module Provider -For testing purposes, you can use the [Local Notification Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification/local) by adding this to your `medusa-config.ts`: +For testing purposes, you can use the [Local Notification Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/local/index.html.md) by adding this to your `medusa-config.ts`: ```ts title="medusa-config.ts" module.exports = defineConfig({ @@ -38535,7 +38559,7 @@ The Local provider logs email details to your terminal instead of sending actual ## Create the Invite User Subscriber -To create a [subscriber](undefined/docs/learn/fundamentals/events-and-subscribers) that handles the `invite.created` and `invite.resent` events, create the file `src/subscribers/user-invited.ts` with the following content: +To create a [subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md) that handles the `invite.created` and `invite.resent` events, create the file `src/subscribers/user-invited.ts` with the following content: ```ts title="src/subscribers/user-invited.ts" highlights={highlights} import { SubscriberArgs, type SubscriberConfig } from "@medusajs/framework" @@ -38586,7 +38610,7 @@ export const config: SubscriberConfig = { } ``` -The subscriber receives the ID of the invite in the event payload. You resolve [Query](undefined/docs/learn/fundamentals/module-links/query) to fetch the invite details, including the email and token. +The subscriber receives the ID of the invite in the event payload. You resolve [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) to fetch the invite details, including the email and token. ### Invite URL @@ -38616,7 +38640,7 @@ Start the Medusa application with the following command: npm run dev ``` -Then, open the Medusa Admin (locally at `http://localhost:9000/app`) and go to Settings → Users. Create an invite as explained in the [Manage Invites](undefined/user-guide/settings/users/invites) user guide. +Then, open the Medusa Admin (locally at `http://localhost:9000/app`) and go to Settings → Users. Create an invite as explained in the [Manage Invites](https://docs.medusajs.com/user-guide/settings/users/invites/index.html.md) user guide. Once you create the invite, you should see that the `invite.created` event is emitted in the server's logs: @@ -38636,7 +38660,7 @@ The following section provides example notification templates for some Notificat ### SendGrid -Refer to the [SendGrid Notification Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid) documentation for more details on how to set up SendGrid. +Refer to the [SendGrid Notification Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid/index.html.md) documentation for more details on how to set up SendGrid. The following HTML template can be used with SendGrid to send an invite email: @@ -38765,7 +38789,7 @@ You can also customize the template further to show other information, such as t ### Resend -If you've integrated Resend as explained in the [Resend Integration Guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/integrations/guides/resend), you can add a new template for user invites at `src/modules/resend/emails/user-invited.tsx`: +If you've integrated Resend as explained in the [Resend Integration Guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/integrations/guides/resend/index.html.md), you can add a new template for user invites at `src/modules/resend/emails/user-invited.tsx`: ```tsx title="src/modules/resend/emails/user-invited.tsx" import { @@ -38934,22 +38958,22 @@ JWT_SECRET=supersecret In this section of the documentation, you will find resources to learn more about the User Module and how to use it in your application. -Refer to the [Medusa Admin User Guide](undefined/user-guide/settings/users) to learn how to manage users using the dashboard. +Refer to the [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/settings/users/index.html.md) to learn how to manage users using the dashboard. -Medusa has user related features available out-of-the-box through the User Module. A [module](undefined/docs/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this User Module. +Medusa has user related features available out-of-the-box through the User Module. A [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in Commerce Modules, such as this User Module. -Learn more about why modules are isolated in [this documentation](undefined/docs/learn/fundamentals/modules/isolation). +Learn more about why modules are isolated in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md). ## User Features -- [User Management](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/user/user-creation-flows): Store and manage users in your store. -- [Invite Users](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/user/user-creation-flows#invite-users): Invite users to join your store and manage those invites. +- [User Management](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/user/user-creation-flows/index.html.md): Store and manage users in your store. +- [Invite Users](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/user/user-creation-flows#invite-users/index.html.md): Invite users to join your store and manage those invites. *** ## How to Use User Module's Service -In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](undefined/docs/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package. @@ -39066,13 +39090,13 @@ export const config = { } ``` -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). *** ## Configure User Module -The User Module accepts options for further configurations. Refer to [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/user/module-options) for details on the module's options. +The User Module accepts options for further configurations. Refer to [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/user/module-options/index.html.md) for details on the module's options. *** @@ -39081,11 +39105,11 @@ The User Module accepts options for further configurations. Refer to [this docum In this document, learn the different ways to create a user using the User Module. -Refer to this [Medusa Admin User Guide](undefined/user-guide/settings/users) to learn how to manage users using the dashboard. +Refer to this [Medusa Admin User Guide](https://docs.medusajs.com/user-guide/settings/users/index.html.md) to learn how to manage users using the dashboard. ## Straightforward User Creation -To create a user, use the [createUsers method of the User Module’s main service](undefined/references/user/createUsers): +To create a user, use the [createUsers method of the User Module’s main service](https://docs.medusajs.com/references/user/createUsers/index.html.md): ```ts const user = await userModuleService.createUsers({ @@ -39099,7 +39123,7 @@ You can pair this with the Auth Module to allow the user to authenticate, as exp ## Invite Users -To create a user, you can create an invite for them using the [createInvites method](undefined/references/user/createInvites) of the User Module's main service: +To create a user, you can create an invite for them using the [createInvites method](https://docs.medusajs.com/references/user/createInvites/index.html.md) of the User Module's main service: ```ts const invite = await userModuleService.createInvites({ @@ -39125,7 +39149,7 @@ const user = await userModuleService.createUsers({ ### Invite Expiry -An invite has an expiry date. You can renew the expiry date and refresh the token using the [refreshInviteTokens method](undefined/references/user/refreshInviteTokens): +An invite has an expiry date. You can renew the expiry date and refresh the token using the [refreshInviteTokens method](https://docs.medusajs.com/references/user/refreshInviteTokens/index.html.md): ```ts await userModuleService.refreshInviteTokens(["invite_123"]) @@ -39208,7 +39232,7 @@ The environment variable must be set as a system environment variable and not in To test the module out, you'll track in the console when an order is placed. -You'll first create a [workflow](undefined/docs/learn/fundamentals/workflows) that tracks the order completion event. Then, you can execute the workflow in a [subscriber](undefined/docs/learn/fundamentals/events-and-subscribers) that listens to the `order.placed` event. +You'll first create a [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) that tracks the order completion event. Then, you can execute the workflow in a [subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md) that listens to the `order.placed` event. For example, create a workflow at `src/workflows/track-order-placed.ts` with the following content: @@ -39272,7 +39296,7 @@ export const trackOrderPlacedWorkflow = createWorkflow( This workflow retrieves the order details using the `useQueryGraphStep` and then tracks the order placement event using the `trackOrderPlacedStep`. -In the step, you resolve the service of the Analytics Module from the [Medusa container](undefined/docs/learn/fundamentals/medusa-container) and use its `track` method to track the event. This method will use the underlying provider configured (which is the Local Analytics Module Provider, in this case) to track the event. +In the step, you resolve the service of the Analytics Module from the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md) and use its `track` method to track the event. This method will use the underlying provider configured (which is the Local Analytics Module Provider, in this case) to track the event. Next, create a subscriber at `src/subscribers/order-placed.ts` with the following content: @@ -39307,7 +39331,7 @@ You'll now track the order placement event whenever an order is placed in your M ## Additional Resources -- [How to Use the Analytics Module](undefined/references/analytics/service) +- [How to Use the Analytics Module](https://docs.medusajs.com/references/analytics/service/index.html.md) # Analytics Module @@ -39336,12 +39360,12 @@ An Analytics Module Provider implements the underlying logic of sending analytic Medusa provides two Analytics Module Providers: Local and PostHog module providers. -You can also [create a custom Analytics Module Provider](undefined/references/analytics/provider) that integrates with a third-party service, like Segment. +You can also [create a custom Analytics Module Provider](https://docs.medusajs.com/references/analytics/provider/index.html.md) that integrates with a third-party service, like Segment. -- [Local](undefined/infrastructure-modules/analytics/local) -- [PostHog](undefined/infrastructure-modules/analytics/posthog) +- [Local](https://docs.medusajs.com/infrastructure-modules/analytics/local/index.html.md) +- [PostHog](https://docs.medusajs.com/infrastructure-modules/analytics/posthog/index.html.md) -[Segment](undefined/integrations/guides/segment): undefined +[Segment](https://docs.medusajs.com/integrations/guides/segment/index.html.md): undefined To configure the Analytics Module and its provider, add it to the list of modules in your `medusa-config.ts` file. For example: @@ -39368,7 +39392,7 @@ Refer to the documentation of each provider for specific configuration options. ### Track Events -To track an event, you can use the Analytics Module as part of the [workflows](undefined/docs/learn/fundamentals/workflows) you build for your custom features. A workflow is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +To track an event, you can use the Analytics Module as part of the [workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) you build for your custom features. A workflow is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. In a step of your workflow, you can resolve the Analytics Module's service and use its methods to track events or identify users. @@ -39434,7 +39458,7 @@ export const trackOrderPlacedWorkflow = createWorkflow( This workflow retrieves the order details using the `useQueryGraphStep` and then tracks the order placement event using the `trackOrderPlacedStep`. -In the step, you resolve the service of the Analytics Module from the [Medusa container](undefined/docs/learn/fundamentals/medusa-container) and use its `track` method to track the event. This method will use the underlying provider configured in `medusa-config.ts` to track the event. +In the step, you resolve the service of the Analytics Module from the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md) and use its `track` method to track the event. This method will use the underlying provider configured in `medusa-config.ts` to track the event. ### Execute Analytics Workflow @@ -39538,7 +39562,7 @@ POSTHOG_HOST= To test the module out, you'll track in PostHog when an order is placed. -You'll first create a [workflow](undefined/docs/learn/fundamentals/workflows) that tracks the order completion event. Then, you can execute the workflow in a [subscriber](undefined/docs/learn/fundamentals/events-and-subscribers) that listens to the `order.placed` event. +You'll first create a [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) that tracks the order completion event. Then, you can execute the workflow in a [subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md) that listens to the `order.placed` event. For example, create a workflow at `src/workflows/track-order-placed.ts` with the following content: @@ -39602,7 +39626,7 @@ export const trackOrderPlacedWorkflow = createWorkflow( This workflow retrieves the order details using the `useQueryGraphStep` and then tracks the order placement event using the `trackOrderPlacedStep`. -In the step, you resolve the service of the Analytics Module from the [Medusa container](undefined/docs/learn/fundamentals/medusa-container) and use its `track` method to track the event. This method will use the underlying provider configured (which is the PostHog Analytics Module Provider, in this case) to track the event. +In the step, you resolve the service of the Analytics Module from the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md) and use its `track` method to track the event. This method will use the underlying provider configured (which is the PostHog Analytics Module Provider, in this case) to track the event. Next, create a subscriber at `src/subscribers/order-placed.ts` with the following content: @@ -39637,7 +39661,7 @@ You'll now track the order placement event whenever an order is placed in your M ## Additional Resources -- [How to Use the Analytics Module](undefined/references/analytics/service) +- [How to Use the Analytics Module](https://docs.medusajs.com/references/analytics/service/index.html.md) # How to Create a Cache Module @@ -39816,7 +39840,7 @@ The In-Memory Cache Module uses a plain JavaScript Map object to store the cache This module is helpful for development or when you’re testing out Medusa, but it’s not recommended to be used in production. -For production, it’s recommended to use modules like [Redis Cache Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/cache/redis). +For production, it’s recommended to use modules like [Redis Cache Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/cache/redis/index.html.md). *** @@ -39862,13 +39886,13 @@ The underlying database, third-party service, or caching logic is flexible since ### Default Cache Module -By default, Medusa uses the [In-Memory Cache Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/cache/in-memory). This module uses a plain JavaScript Map object to store the cache data. While this is suitable for development, it's recommended to use other Cache Modules, such as the [Redis Cache Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/cache/redis), for production. You can also [Create a Cache Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/cache/create). +By default, Medusa uses the [In-Memory Cache Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/cache/in-memory/index.html.md). This module uses a plain JavaScript Map object to store the cache data. While this is suitable for development, it's recommended to use other Cache Modules, such as the [Redis Cache Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/cache/redis/index.html.md), for production. You can also [Create a Cache Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/cache/create/index.html.md). *** ## How to Use the Cache Module? -You can use the registered Cache Module as part of the [workflows](undefined/docs/learn/fundamentals/workflows) you build for your custom features. A workflow is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +You can use the registered Cache Module as part of the [workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) you build for your custom features. A workflow is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. In a step of your workflow, you can resolve the Cache Module's service and use its methods to cache data, retrieve cached data, or clear the cache. @@ -39900,7 +39924,7 @@ export const workflow = createWorkflow( ) ``` -In the example above, you create a workflow that has a step. In the step, you resolve the service of the Cache Module from the [Medusa container](undefined/docs/learn/fundamentals/medusa-container). +In the example above, you create a workflow that has a step. In the step, you resolve the service of the Cache Module from the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). Then, you use the `set` method of the Cache Module to cache the value `"value"` with the key `"key"`. @@ -39908,17 +39932,17 @@ Then, you use the `set` method of the Cache Module to cache the value `"value"` ## List of Cache Modules -Medusa provides the following Cache Modules. You can use one of them, or [Create a Cache Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/cache/create). +Medusa provides the following Cache Modules. You can use one of them, or [Create a Cache Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/cache/create/index.html.md). -- [In-Memory](undefined/infrastructure-modules/cache/in-memory) -- [Redis](undefined/infrastructure-modules/cache/redis) +- [In-Memory](https://docs.medusajs.com/infrastructure-modules/cache/in-memory/index.html.md) +- [Redis](https://docs.medusajs.com/infrastructure-modules/cache/redis/index.html.md) # Redis Cache Module The Redis Cache Module uses Redis to cache data in your store. In production, it's recommended to use this module. -Our Cloud offering automatically provisions a Redis instance and configures the Redis Cache Module for you. Learn more in the [Redis](undefined/cloud/redis) Cloud documentation. +Our Cloud offering automatically provisions a Redis instance and configures the Redis Cache Module for you. Learn more in the [Redis](https://docs.medusajs.com/cloud/redis/index.html.md) Cloud documentation. *** @@ -40205,7 +40229,7 @@ The Local Event Module uses Node EventEmitter to implement Medusa's pub/sub even This module is useful for development and testing, but it’s not recommended to be used in production. -For production, it’s recommended to use modules like [Redis Event Bus Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/event/redis). +For production, it’s recommended to use modules like [Redis Event Bus Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/event/redis/index.html.md). *** @@ -40257,19 +40281,19 @@ An Event Module implements the underlying publish/subscribe system that handles This makes the event architecture customizable, as you can either choose one of Medusa’s event modules or create your own. -Learn more about Medusa's event systems in the [Events and Subscribers documentation](undefined/docs/learn/fundamentals/events-and-subscribers). +Learn more about Medusa's event systems in the [Events and Subscribers documentation](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md). ### Default Event Module -By default, Medusa uses the [Local Event Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/event/local). This module uses Node’s EventEmitter to implement the publish/subscribe system. While this is suitable for development, it's recommended to use other Event Modules, such as the [Redis Event Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/event/redis), for production. You can also [Create an Event Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/event/create). +By default, Medusa uses the [Local Event Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/event/local/index.html.md). This module uses Node’s EventEmitter to implement the publish/subscribe system. While this is suitable for development, it's recommended to use other Event Modules, such as the [Redis Event Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/event/redis/index.html.md), for production. You can also [Create an Event Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/event/create/index.html.md). *** ## How to Use the Event Module? -You can use the registered Event Module as part of the [workflows](undefined/docs/learn/fundamentals/workflows) you build for your custom features. A workflow is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +You can use the registered Event Module as part of the [workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) you build for your custom features. A workflow is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. -Medusa provides the helper step [emitEventStep](undefined/references/helper-steps/emitEventStep) that you can use in your workflow. You can also resolve the Event Module's service in a step of your workflow and use its methods to emit events. +Medusa provides the helper step [emitEventStep](https://docs.medusajs.com/references/helper-steps/emitEventStep/index.html.md) that you can use in your workflow. You can also resolve the Event Module's service in a step of your workflow and use its methods to emit events. For example: @@ -40305,7 +40329,7 @@ export const workflow = createWorkflow( ) ``` -In the example above, you create a workflow that has a step. In the step, you resolve the service of the Event Module from the [Medusa container](undefined/docs/learn/fundamentals/medusa-container). +In the example above, you create a workflow that has a step. In the step, you resolve the service of the Event Module from the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). Then, you use the `emit` method of the Event Module to emit an event with the name `"custom.event"` and the data payload `{ id: "123" }`. @@ -40313,10 +40337,10 @@ Then, you use the `emit` method of the Event Module to emit an event with the na ## List of Event Modules -Medusa provides the following Event Modules. You can use one of them, or [Create an Event Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/event/create). +Medusa provides the following Event Modules. You can use one of them, or [Create an Event Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/event/create/index.html.md). -- [Local](undefined/infrastructure-modules/event/local) -- [Redis](undefined/infrastructure-modules/event/redis) +- [Local](https://docs.medusajs.com/infrastructure-modules/event/local/index.html.md) +- [Redis](https://docs.medusajs.com/infrastructure-modules/event/redis/index.html.md) # Redis Event Module @@ -40327,7 +40351,7 @@ It's powered by BullMQ and `io-redis`. BullMQ is responsible for the message que In production, it's recommended to use this module. -Our Cloud offering automatically provisions a Redis instance and configures the Redis Event Module for you. Learn more in the [Redis](undefined/cloud/redis) Cloud documentation. +Our Cloud offering automatically provisions a Redis instance and configures the Redis Event Module for you. Learn more in the [Redis](https://docs.medusajs.com/cloud/redis/index.html.md) Cloud documentation. *** @@ -40395,7 +40419,7 @@ Connection to Redis in module 'event-redis' established The Local File Module Provider stores files uploaded to your Medusa application in the `/uploads` directory. -- The Local File Module Provider is only for development purposes. Use the [S3 File Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/file/s3) in production instead. +- The Local File Module Provider is only for development purposes. Use the [S3 File Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/file/s3/index.html.md) in production instead. - The Local File Module Provider will only read files uploaded through Medusa. It will not read files uploaded manually to the `static` (or other configured) directory. *** @@ -40454,7 +40478,7 @@ The File Module exposes the functionalities to upload assets, such as product im ## How to Use the File Module? -You can use the File Module as part of the [workflows](undefined/docs/learn/fundamentals/workflows) you build for your custom features. A workflow is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +You can use the File Module as part of the [workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) you build for your custom features. A workflow is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. In a step of your workflow, you can resolve the File Module's service and use its methods to upload files, retrieve files, or delete files. @@ -40492,7 +40516,7 @@ export const workflow = createWorkflow( ) ``` -In the example above, you create a workflow that has a step. In the step, you resolve the service of the File Module from the [Medusa container](undefined/docs/learn/fundamentals/medusa-container). +In the example above, you create a workflow that has a step. In the step, you resolve the service of the File Module from the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). Then, you use the `retrieveFile` method of the File Module to retrieve the URL of the file with the name `"image.png"`. The URL is then returned as a response from the step and the workflow. @@ -40504,19 +40528,19 @@ A File Module Provider implements the underlying logic of handling uploads and d Only one File Module Provider can be registered at a time. If you register multiple providers, the File Module will throw an error. -By default, Medusa uses the [Local File Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/file/local). This module uploads files to the `uploads` directory of your Medusa application. +By default, Medusa uses the [Local File Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/file/local/index.html.md). This module uploads files to the `uploads` directory of your Medusa application. -This is useful for development. However, for production, it’s highly recommended to use other File Module Providers, such as the S3 File Module Provider. You can also [Create a File Provider](undefined/references/file-provider-module). +This is useful for development. However, for production, it’s highly recommended to use other File Module Providers, such as the S3 File Module Provider. You can also [Create a File Provider](https://docs.medusajs.com/references/file-provider-module/index.html.md). -- [Local](undefined/infrastructure-modules/file/local) -- [AWS S3 (and Compatible APIs)](undefined/infrastructure-modules/file/s3) +- [Local](https://docs.medusajs.com/infrastructure-modules/file/local/index.html.md) +- [AWS S3 (and Compatible APIs)](https://docs.medusajs.com/infrastructure-modules/file/s3/index.html.md) # S3 File Module Provider The S3 File Module Provider integrates Amazon S3 and services following a compatible API (such as MinIO or DigitalOcean Spaces) to store files uploaded to your Medusa application. -Cloud offers a managed file storage solution with AWS S3 for your Medusa application. Refer to the [S3](undefined/cloud/s3) Cloud documentation for more details. +Cloud offers a managed file storage solution with AWS S3 for your Medusa application. Refer to the [S3](https://docs.medusajs.com/cloud/s3/index.html.md) Cloud documentation for more details. ## Prerequisites @@ -40685,7 +40709,7 @@ For example, Medusa uses the Locking Module in inventory management to ensure th ## How to Use the Locking Module? -You can use the Locking Module as part of the [workflows](undefined/docs/learn/fundamentals/workflows) you build for your custom features. A workflow is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +You can use the Locking Module as part of the [workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) you build for your custom features. A workflow is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. In a step of your workflow, you can resolve the Locking Module's service and use its methods to execute an asynchronous job, acquire a lock, or release locks. @@ -40722,7 +40746,7 @@ export const workflow = createWorkflow( ) ``` -In the example above, you create a workflow that has a step. In the step, you resolve the services of the Locking and Product modules from the [Medusa container](undefined/docs/learn/fundamentals/medusa-container). +In the example above, you create a workflow that has a step. In the step, you resolve the services of the Locking and Product modules from the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). Then, you use the `execute` method of the Locking Module to acquire a lock for the product with the ID `prod_123` and execute an asynchronous function, which deletes the product. @@ -40740,7 +40764,7 @@ In those scenarios, you can use the Locking Module to acquire a lock for a resou A Locking Module Provider implements the underlying logic of the Locking Module. It manages the locking mechanisms and ensures that only one process can access a shared resource at a time. -Medusa provides [multiple Locking Module Providers](#list-of-locking-module-providers) that are suitable for development and production. You can also create a [custom Locking Module Provider](undefined/references/locking-module-provider) to implement custom locking mechanisms or integrate with third-party services. +Medusa provides [multiple Locking Module Providers](#list-of-locking-module-providers) that are suitable for development and production. You can also create a [custom Locking Module Provider](https://docs.medusajs.com/references/locking-module-provider/index.html.md) to implement custom locking mechanisms or integrate with third-party services. ### Default Locking Module Provider @@ -40776,10 +40800,10 @@ When you register other providers in `medusa-config.ts`, Medusa will set the def ## List of Locking Module Providers -Medusa provides the following Locking Module Providers. You can use one of them, or [Create a Locking Module Provider](undefined/references/locking-module-provider). +Medusa provides the following Locking Module Providers. You can use one of them, or [Create a Locking Module Provider](https://docs.medusajs.com/references/locking-module-provider/index.html.md). -- [Redis](undefined/infrastructure-modules/locking/redis) -- [PostgreSQL](undefined/infrastructure-modules/locking/postgres) +- [Redis](https://docs.medusajs.com/infrastructure-modules/locking/redis/index.html.md) +- [PostgreSQL](https://docs.medusajs.com/infrastructure-modules/locking/postgres/index.html.md) # PostgreSQL Locking Module Provider @@ -40788,7 +40812,7 @@ The PostgreSQL Locking Module Provider uses PostgreSQL's advisory locks to contr The provider uses the existing PostgreSQL database in your application to manage locks, so you don't need to set up a separate database or service to manage locks. -While this provider is suitable for production environments, it's recommended to use the [Redis Locking Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/locking/redis) if possible. +While this provider is suitable for production environments, it's recommended to use the [Redis Locking Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/locking/redis/index.html.md) if possible. *** @@ -40856,7 +40880,7 @@ module.exports = defineConfig({ If you use the Locking Module in your customizations, the PostgreSQL Locking Module Provider will be used by default in this case. You can also explicitly use this provider by passing its identifier `lp_locking-postgres` to the Locking Module's service methods. -For example, when using the `acquire` method in a [workflow step](undefined/docs/learn/fundamentals/workflows): +For example, when using the `acquire` method in a [workflow step](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md): ```ts import { Modules } from "@medusajs/framework/utils" @@ -40883,7 +40907,7 @@ The Redis Locking Module Provider uses Redis to manage locks across multiple ins This provider is recommended for production environments where Medusa is running in a multi-instance setup. -Our Cloud offering automatically provisions a Redis instance and configures the Redis Locking Module Provider for you. Learn more in the [Redis](undefined/cloud/redis) Cloud documentation. +Our Cloud offering automatically provisions a Redis instance and configures the Redis Locking Module Provider for you. Learn more in the [Redis](https://docs.medusajs.com/cloud/redis/index.html.md) Cloud documentation. *** @@ -40994,7 +41018,7 @@ module.exports = defineConfig({ If you use the Locking Module in your customizations, the Redis Locking Module Provider will be used by default in this case. You can also explicitly use this provider by passing its identifier `lp_locking-redis` to the Locking Module's service methods. -For example, when using the `acquire` method in a [workflow step](undefined/docs/learn/fundamentals/workflows): +For example, when using the `acquire` method in a [workflow step](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md): ```ts import { Modules } from "@medusajs/framework/utils" @@ -41063,10 +41087,10 @@ it's important to specify its channels to make sure it's used when a notificatio ## Send Notifications to the Admin Notification Panel -The Local Notification Module Provider can also be used to send notifications to the [Medusa Admin's notification panel](undefined/user-guide#check-notifications). +The Local Notification Module Provider can also be used to send notifications to the [Medusa Admin's notification panel](https://docs.medusajs.com/user-guide#check-notifications/index.html.md). You can send notifications to the admin dashboard when a certain action occurs using a subscriber, a custom workflow or a workflow hook. -For example, to send an admin notification whenever an order is placed, create a [subscriber](undefined/docs/learn/fundamentals/events-and-subscribers) at `src/subscribers/order-placed.ts` with the following content: +For example, to send an admin notification whenever an order is placed, create a [subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md) at `src/subscribers/order-placed.ts` with the following content: ```ts title="src/subscribers/order-placed.ts" highlights={highlights} collapsibleLines="1-6" expandButtonLabel="Show Imports" import type { @@ -41099,7 +41123,7 @@ export const config: SubscriberConfig = { In this subscriber, you: -- Resolve the Notification Module's main service from the [Medusa container](undefined/docs/learn/fundamentals/medusa-container). +- Resolve the Notification Module's main service from the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). - Use the `createNotifications` method of the Notification Module's main service to create a notification to be sent to the admin dashboard. By specifying the `feed` channel, the Local Notification Module Provider is used to send the notification. - The `template` property of the `createNotifications` method's parameter must be set to `admin-ui`. - The `data` property allows you to customize the content of the admin notification. It must contain `title` and `description` properties. @@ -41127,7 +41151,7 @@ The Notification Module exposes the functionalities to send a notification to a ## How to Use the Notification Module? -You can use the Notification Module as part of the [workflows](undefined/docs/learn/fundamentals/workflows) you build for your custom features. A workflow is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +You can use the Notification Module as part of the [workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) you build for your custom features. A workflow is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. In a step of your workflow, you can resolve the Notification Module's service and use its methods to send notifications. @@ -41164,11 +41188,11 @@ export const workflow = createWorkflow( ) ``` -In the example above, you create a workflow that has a step. In the step, you resolve the service of the Notification Module from the [Medusa container](undefined/docs/learn/fundamentals/medusa-container). +In the example above, you create a workflow that has a step. In the step, you resolve the service of the Notification Module from the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). Then, you use the `createNotifications` method of the Notification Module to send an email notification. -Find a full example of sending a notification in the [Send Notification guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification/send-notification). +Find a full example of sending a notification in the [Send Notification guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/send-notification/index.html.md). *** @@ -41176,16 +41200,16 @@ Find a full example of sending a notification in the [Send Notification guide](u A Notification Module Provider implements the underlying logic of sending notification. It either integrates a third-party service or uses custom logic to send the notification. -By default, Medusa uses the [Local Notification Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification/local) which only simulates sending the notification by logging a message in the terminal. +By default, Medusa uses the [Local Notification Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/local/index.html.md) which only simulates sending the notification by logging a message in the terminal. -Medusa provides other Notification Modules that actually send notifications, such as the [SendGrid Notification Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification/send-notification). You can also [Create a Notification Module Provider](undefined/references/notification-provider-module). +Medusa provides other Notification Modules that actually send notifications, such as the [SendGrid Notification Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/send-notification/index.html.md). You can also [Create a Notification Module Provider](https://docs.medusajs.com/references/notification-provider-module/index.html.md). -- [Local](undefined/infrastructure-modules/notification/local) -- [SendGrid](undefined/infrastructure-modules/notification/sendgrid) -- [Mailchimp](undefined/integrations/guides/mailchimp) -- [Resend](undefined/integrations/guides/resend) -- [Slack](undefined/integrations/guides/slack) -- [Twilio SMS](undefined/how-to-tutorials/tutorials/phone-auth#step-3-integrate-twilio-sms) +- [Local](https://docs.medusajs.com/infrastructure-modules/notification/local/index.html.md) +- [SendGrid](https://docs.medusajs.com/infrastructure-modules/notification/sendgrid/index.html.md) +- [Mailchimp](https://docs.medusajs.com/integrations/guides/mailchimp/index.html.md) +- [Resend](https://docs.medusajs.com/integrations/guides/resend/index.html.md) +- [Slack](https://docs.medusajs.com/integrations/guides/slack/index.html.md) +- [Twilio SMS](https://docs.medusajs.com/how-to-tutorials/tutorials/phone-auth#step-3-integrate-twilio-sms/index.html.md) *** @@ -41234,7 +41258,7 @@ In this guide, you'll learn about the different ways to send notifications using ## Using the Create Method -In your resource, such as a [subscriber](undefined/docs/learn/fundamentals/events-and-subscribers), resolve the Notification Module's main service and use its `create` method: +In your resource, such as a [subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md), resolve the Notification Module's main service and use its `create` method: ```ts title="src/subscribers/product-created.ts" highlights={highlights} collapsibleLines="1-7" expandButtonLabel="Show Imports" import type { @@ -41271,13 +41295,13 @@ The `create` method accepts an object or an array of objects having the followin - template: (\`string\`) The ID of the template used for the notification. This is useful for providers like SendGrid, where you define templates within SendGrid and use their IDs here. - data: (\`Record\\`) The data to pass along to the template, if necessary. -For a full list of properties accepted, refer to [this guide](undefined/references/notification-provider-module#create). +For a full list of properties accepted, refer to [this guide](https://docs.medusajs.com/references/notification-provider-module#create/index.html.md). *** ## Using the sendNotificationsStep -If you want to send a notification as part of a workflow, You can use the [sendNotificationsStep](undefined/references/medusa-workflows/steps/sendNotificationsStep) in your workflow. +If you want to send a notification as part of a workflow, You can use the [sendNotificationsStep](https://docs.medusajs.com/references/medusa-workflows/steps/sendNotificationsStep/index.html.md) in your workflow. For example: @@ -41319,7 +41343,7 @@ export const sendEmailWorkflow = createWorkflow( ) ``` -For a full list of input properties accepted, refer to the [sendNotificationsStep](undefined/references/medusa-workflows/steps/sendNotificationsStep) reference. +For a full list of input properties accepted, refer to the [sendNotificationsStep](https://docs.medusajs.com/references/medusa-workflows/steps/sendNotificationsStep/index.html.md) reference. You can then execute this workflow in a subscriber, API route, or scheduled job. @@ -41422,7 +41446,7 @@ Refer to [this SendGrid documentation guide](https://docs.sendgrid.com/ui/sendin To test the module out, you'll listen to the `product.created` event and send an email when a product is created. -Create a [subscriber](undefined/docs/learn/fundamentals/events-and-subscribers) at `src/subscribers/product-created.ts` with the following content: +Create a [subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md) at `src/subscribers/product-created.ts` with the following content: ```ts title="src/subscribers/product-created.ts" highlights={highlights} collapsibleLines="1-7" expandButtonLabel="Show Imports" import type { @@ -41464,7 +41488,7 @@ export const config: SubscriberConfig = { In this subscriber, you: -- Resolve the Notification Module's main service and [Query](undefined/docs/learn/fundamentals/module-links/query) from the [Medusa container](undefined/docs/learn/fundamentals/medusa-container). +- Resolve the Notification Module's main service and [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) from the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). - Retrieve the product's details using Query to pass them to the template in SendGrid. - Use the `createNotifications` method of the Notification Module's main service to create a notification to be sent to the specified email. By specifying the `email` channel, the SendGrid Notification Module Provider is used to send the notification. - The `template` property of the `createNotifications` method's parameter specifies the ID of the template defined in SendGrid. @@ -41476,19 +41500,19 @@ Then, start the Medusa application: npm run dev ``` -And create a product either using the [API route](undefined/api/admin#products_postproducts) or the [Medusa Admin](undefined/user-guide/products/create). This runs the subscriber and sends an email using SendGrid. +And create a product either using the [API route](https://docs.medusajs.com/api/admin#products_postproducts) or the [Medusa Admin](https://docs.medusajs.com/user-guide/products/create/index.html.md). This runs the subscriber and sends an email using SendGrid. ### Other Events to Handle Medusa emits other events that you can handle to send notifications using the SendGrid Notification Module Provider, such as `order.placed` when an order is placed. -Refer to the [Events Reference](undefined/references/events) for a complete list of events emitted by Medusa. +Refer to the [Events Reference](https://docs.medusajs.com/references/events/index.html.md) for a complete list of events emitted by Medusa. ### Sending Emails with SendGrid in Workflows -You can also send an email using SendGrid in any [workflow](undefined/docs/learn/fundamentals/workflows). This allows you to send emails within your custom flows. +You can also send an email using SendGrid in any [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). This allows you to send emails within your custom flows. -You can use the [sendNotifcationStep](undefined/references/medusa-workflows/steps/sendNotificationsStep) in your workflow to send an email using SendGrid. +You can use the [sendNotifcationStep](https://docs.medusajs.com/references/medusa-workflows/steps/sendNotificationsStep/index.html.md) in your workflow to send an email using SendGrid. For example: @@ -41565,7 +41589,7 @@ This subscriber will run every time a product is created, and it will execute th Medusa's architectural functionalities, such as emitting and subscribing to events or caching data, are all implemented in Infrastructure Modules. An Infrastructure Module is a package that can be installed and used in any Medusa application. These modules allow you to choose and integrate custom services for architectural purposes. -For example, you can use our [Redis Event Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/event/redis) to handle event functionalities, or create a custom module that implements these functionalities with Memcached. Learn more in [the Architecture documentation](undefined/docs/learn/introduction/architecture). +For example, you can use our [Redis Event Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/event/redis/index.html.md) to handle event functionalities, or create a custom module that implements these functionalities with Memcached. Learn more in [the Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). This section of the documentation showcases Medusa's Infrastructure Modules, how they work, and how to use them in your Medusa application. @@ -41573,82 +41597,82 @@ This section of the documentation showcases Medusa's Infrastructure Modules, how The Analytics Module is available starting [Medusa v2.8.3](https://github.com/medusajs/medusa/releases/tag/v2.8.3). -The Analytics Module exposes functionalities to track and analyze user interactions and system events. For example, tracking cart updates or completed orders. Learn more in the [Analytics Module documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/analytics). +The Analytics Module exposes functionalities to track and analyze user interactions and system events. For example, tracking cart updates or completed orders. Learn more in the [Analytics Module documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/analytics/index.html.md). {/* The Analytics Module has module providers that implement the underlying logic of integrating third-party services for tracking analytics. The following Analytics Module Providers are provided by Medusa. You can also create a custom provider as explained in the [Create Analytics Module Provider guide](/references/analytics/provider). */} -- [Local](undefined/infrastructure-modules/analytics/local) -- [PostHog](undefined/infrastructure-modules/analytics/posthog) +- [Local](https://docs.medusajs.com/infrastructure-modules/analytics/local/index.html.md) +- [PostHog](https://docs.medusajs.com/infrastructure-modules/analytics/posthog/index.html.md) ## Cache Module -A Cache Module is used to cache the results of computations such as price selection or various tax calculations. Learn more in [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/cache). +A Cache Module is used to cache the results of computations such as price selection or various tax calculations. Learn more in [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/cache/index.html.md). -The following Cache modules are provided by Medusa. You can also create your own cache module as explained in [this guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/cache/create). +The following Cache modules are provided by Medusa. You can also create your own cache module as explained in [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/cache/create/index.html.md). -- [In-Memory](undefined/infrastructure-modules/cache/in-memory) -- [Redis](undefined/infrastructure-modules/cache/redis) +- [In-Memory](https://docs.medusajs.com/infrastructure-modules/cache/in-memory/index.html.md) +- [Redis](https://docs.medusajs.com/infrastructure-modules/cache/redis/index.html.md) *** ## Event Module -An Event Module implements the underlying publish/subscribe system that handles queueing events, emitting them, and executing their subscribers. Learn more in [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/event). +An Event Module implements the underlying publish/subscribe system that handles queueing events, emitting them, and executing their subscribers. Learn more in [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/event/index.html.md). -The following Event modules are provided by Medusa. You can also create your own event module as explained in [this guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/event/create). +The following Event modules are provided by Medusa. You can also create your own event module as explained in [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/event/create/index.html.md). -- [Local](undefined/infrastructure-modules/event/local) -- [Redis](undefined/infrastructure-modules/event/redis) +- [Local](https://docs.medusajs.com/infrastructure-modules/event/local/index.html.md) +- [Redis](https://docs.medusajs.com/infrastructure-modules/event/redis/index.html.md) *** ## File Module -The File Module handles file upload and storage of assets, such as product images. Refer to the [File Module documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/file) to learn more about it. +The File Module handles file upload and storage of assets, such as product images. Refer to the [File Module documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/file/index.html.md) to learn more about it. -The File Module has module providers that implement the underlying logic of handling uploads and downloads of assets, such as integrating third-party services. The following File Module Providers are provided by Medusa. You can also create a custom provider as explained in the [Create File Module Provider guide](undefined/references/file-provider-module). +The File Module has module providers that implement the underlying logic of handling uploads and downloads of assets, such as integrating third-party services. The following File Module Providers are provided by Medusa. You can also create a custom provider as explained in the [Create File Module Provider guide](https://docs.medusajs.com/references/file-provider-module/index.html.md). -- [Local](undefined/infrastructure-modules/file/local) -- [AWS S3 (and Compatible APIs)](undefined/infrastructure-modules/file/s3) +- [Local](https://docs.medusajs.com/infrastructure-modules/file/local/index.html.md) +- [AWS S3 (and Compatible APIs)](https://docs.medusajs.com/infrastructure-modules/file/s3/index.html.md) *** ## Locking Module -The Locking Module manages access to shared resources by multiple processes or threads. It prevents conflicts between processes and ensures data consistency. Refer to the [Locking Module documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/locking) to learn more about it. +The Locking Module manages access to shared resources by multiple processes or threads. It prevents conflicts between processes and ensures data consistency. Refer to the [Locking Module documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/locking/index.html.md) to learn more about it. -The Locking Module uses module providers that implement the underlying logic of the locking mechanism. The following Locking Module Providers are provided by Medusa. You can also create a custom provider as explained in the [Create Locking Module Provider guide](undefined/references/locking-module-provider). +The Locking Module uses module providers that implement the underlying logic of the locking mechanism. The following Locking Module Providers are provided by Medusa. You can also create a custom provider as explained in the [Create Locking Module Provider guide](https://docs.medusajs.com/references/locking-module-provider/index.html.md). -- [Redis](undefined/infrastructure-modules/locking/redis) -- [PostgreSQL](undefined/infrastructure-modules/locking/postgres) +- [Redis](https://docs.medusajs.com/infrastructure-modules/locking/redis/index.html.md) +- [PostgreSQL](https://docs.medusajs.com/infrastructure-modules/locking/postgres/index.html.md) *** ## Notification Module -The Notification Module handles sending notifications to users or customers, such as reset password instructions or newsletters. Refer to the [Notifcation Module documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification) to learn more about it. +The Notification Module handles sending notifications to users or customers, such as reset password instructions or newsletters. Refer to the [Notifcation Module documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/index.html.md) to learn more about it. -The Notification Module has module providers that implement the underlying logic of sending notifications, typically through integrating a third-party service. The following modules are provided by Medusa. You can also create a custom provider as explained in the [Create Notification Module Provider guide](undefined/references/notification-provider-module). +The Notification Module has module providers that implement the underlying logic of sending notifications, typically through integrating a third-party service. The following modules are provided by Medusa. You can also create a custom provider as explained in the [Create Notification Module Provider guide](https://docs.medusajs.com/references/notification-provider-module/index.html.md). -- [Local](undefined/infrastructure-modules/notification/local) -- [SendGrid](undefined/infrastructure-modules/notification/sendgrid) +- [Local](https://docs.medusajs.com/infrastructure-modules/notification/local/index.html.md) +- [SendGrid](https://docs.medusajs.com/infrastructure-modules/notification/sendgrid/index.html.md) ### Notification Module Provider Guides -- [Send Notification](undefined/infrastructure-modules/notification/send-notification) -- [Create Notification Provider](undefined/references/notification-provider-module) -- [Resend](undefined/integrations/guides/resend) +- [Send Notification](https://docs.medusajs.com/infrastructure-modules/notification/send-notification/index.html.md) +- [Create Notification Provider](https://docs.medusajs.com/references/notification-provider-module/index.html.md) +- [Resend](https://docs.medusajs.com/integrations/guides/resend/index.html.md) *** ## Workflow Engine Module -A Workflow Engine Module handles tracking and recording the transactions and statuses of workflows and their steps. Learn more about it in the [Worklow Engine Module documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/workflow-engine). +A Workflow Engine Module handles tracking and recording the transactions and statuses of workflows and their steps. Learn more about it in the [Worklow Engine Module documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/workflow-engine/index.html.md). The following Workflow Engine modules are provided by Medusa. -- [In-Memory](undefined/infrastructure-modules/workflow-engine/in-memory) -- [Redis](undefined/infrastructure-modules/workflow-engine/redis) +- [In-Memory](https://docs.medusajs.com/infrastructure-modules/workflow-engine/in-memory/index.html.md) +- [Redis](https://docs.medusajs.com/infrastructure-modules/workflow-engine/redis/index.html.md) # How to Use the Workflow Engine Module @@ -41677,7 +41701,7 @@ const step1 = createStep( ) ``` -This will resolve the service of the configured Workflow Engine Module, which is the [In-Memory Workflow Engine Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/workflow-engine/in-memory) by default. +This will resolve the service of the configured Workflow Engine Module, which is the [In-Memory Workflow Engine Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/workflow-engine/in-memory/index.html.md) by default. You can then use the Workflow Engine Module's service's methods in the step. The rest of this guide details these methods. @@ -41685,7 +41709,7 @@ You can then use the Workflow Engine Module's service's methods in the step. The ## retryStep -This method retries a step that has temporary failed, such as a step that has `autoRetry` set to `false` or when the machine running the Medusa application shuts down. Learn more about it in the [Retry Failed Steps](undefined/docs/learn/fundamentals/workflows/retry-failed-steps) guide. +This method retries a step that has temporary failed, such as a step that has `autoRetry` set to `false` or when the machine running the Medusa application shuts down. Learn more about it in the [Retry Failed Steps](https://docs.medusajs.com/docs/learn/fundamentals/workflows/retry-failed-steps/index.html.md) guide. This method is available since [Medusa v2.10.2](https://github.com/medusajs/medusa/releases/tag/v2.10.2). @@ -41726,7 +41750,7 @@ workflowEngine.retryStep({ ## setStepSuccess -This method sets an async step in a currently-executing [long-running workflow](undefined/docs/learn/fundamentals/workflows/long-running-workflow) as successful. The workflow will then continue to the next step. +This method sets an async step in a currently-executing [long-running workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/long-running-workflow/index.html.md) as successful. The workflow will then continue to the next step. ### Example @@ -41767,7 +41791,7 @@ await workflowEngineModuleService.setStepSuccess({ ## setStepFailure -This method sets an async step in a currently-executing [long-running workflow](undefined/docs/learn/fundamentals/workflows/long-running-workflow) as failed. The workflow will then stop executing and the compensation functions of the workflow's steps will be executed. +This method sets an async step in a currently-executing [long-running workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/long-running-workflow/index.html.md) as failed. The workflow will then stop executing and the compensation functions of the workflow's steps will be executed. ### Example @@ -41808,9 +41832,9 @@ await workflowEngineModuleService.setStepFailure({ ## subscribe -This method subscribes to a workflow's events. You can use this method to listen to a [long-running workflow](undefined/docs/learn/fundamentals/workflows/long-running-workflow)'s events and retrieve its result once it's done executing. +This method subscribes to a workflow's events. You can use this method to listen to a [long-running workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/long-running-workflow/index.html.md)'s events and retrieve its result once it's done executing. -Refer to the [Long-Running Workflows](undefined/docs/learn/fundamentals/workflows/long-running-workflow#access-long-running-workflow-status-and-result) documentation to learn more. +Refer to the [Long-Running Workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/long-running-workflow#access-long-running-workflow-status-and-result/index.html.md) documentation to learn more. ### Example @@ -41856,7 +41880,7 @@ await workflowEngineModuleService.subscribe({ ## unsubscribe -This method unsubscribes from a workflow's events. You can use this method to stop listening to a [long-running workflow](undefined/docs/learn/fundamentals/workflows/long-running-workflow)'s events after you've received the result. +This method unsubscribes from a workflow's events. You can use this method to stop listening to a [long-running workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/long-running-workflow/index.html.md)'s events after you've received the result. ### Example @@ -41881,7 +41905,7 @@ The In-Memory Workflow Engine Module uses a plain JavaScript Map object to store This module is helpful for development or when you’re testing out Medusa, but it’s not recommended to be used in production. -For production, it’s recommended to use modules like [Redis Workflow Engine Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/workflow-engine/redis). +For production, it’s recommended to use modules like [Redis Workflow Engine Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/workflow-engine/redis/index.html.md). *** @@ -41917,13 +41941,13 @@ A Workflow Engine Module handles tracking and recording the transactions and sta ### Default Workflow Engine Module -Medusa uses the [In-Memory Workflow Engine Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/workflow-engine/in-memory) by default. For production purposes, it's recommended to use the [Redis Workflow Engine Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/workflow-engine/redis) instead. +Medusa uses the [In-Memory Workflow Engine Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/workflow-engine/in-memory/index.html.md) by default. For production purposes, it's recommended to use the [Redis Workflow Engine Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/workflow-engine/redis/index.html.md) instead. *** ## How to Use the Workflow Engine Module? -You can use the registered Workflow Engine Module as part of the [workflows](undefined/docs/learn/fundamentals/workflows) you build for your custom features. A workflow is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. +You can use the registered Workflow Engine Module as part of the [workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) you build for your custom features. A workflow is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism. In a step of your workflow, you can resolve the Workflow Engine Module's service and use its methods to track and record the transactions and statuses of workflows and their steps. @@ -41963,7 +41987,7 @@ export const workflow = createWorkflow( ) ``` -In the example above, you create a workflow that has a step. In the step, you resolve the service of the Workflow Engine Module from the [Medusa container](undefined/docs/learn/fundamentals/medusa-container). +In the example above, you create a workflow that has a step. In the step, you resolve the service of the Workflow Engine Module from the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). Then, you use the `listWorkflowExecutions` method of the Workflow Engine Module to list the workflow executions with the transaction ID `transaction_id`. The workflow execution is then returned as a response from the step and the workflow. @@ -41973,15 +41997,15 @@ Then, you use the `listWorkflowExecutions` method of the Workflow Engine Module Medusa provides the following Workflow Engine Modules. -- [In-Memory](undefined/infrastructure-modules/workflow-engine/in-memory) -- [Redis](undefined/infrastructure-modules/workflow-engine/redis) +- [In-Memory](https://docs.medusajs.com/infrastructure-modules/workflow-engine/in-memory/index.html.md) +- [Redis](https://docs.medusajs.com/infrastructure-modules/workflow-engine/redis/index.html.md) # Redis Workflow Engine Module The Redis Workflow Engine Module uses Redis to track workflow executions and handle their subscribers. In production, it's recommended to use this module. -Our Cloud offering automatically provisions a Redis instance and configures the Redis Workflow Engine Module for you. Learn more in the [Redis](undefined/cloud/redis) Cloud documentation. +Our Cloud offering automatically provisions a Redis instance and configures the Redis Workflow Engine Module for you. Learn more in the [Redis](https://docs.medusajs.com/cloud/redis/index.html.md) Cloud documentation. *** @@ -42047,649 +42071,649 @@ Connection to Redis in module 'workflow-engine-redis' established ## Workflows -- [createApiKeysWorkflow](undefined/references/medusa-workflows/createApiKeysWorkflow/index.html.md) -- [deleteApiKeysWorkflow](undefined/references/medusa-workflows/deleteApiKeysWorkflow/index.html.md) -- [linkSalesChannelsToApiKeyWorkflow](undefined/references/medusa-workflows/linkSalesChannelsToApiKeyWorkflow/index.html.md) -- [revokeApiKeysWorkflow](undefined/references/medusa-workflows/revokeApiKeysWorkflow/index.html.md) -- [updateApiKeysWorkflow](undefined/references/medusa-workflows/updateApiKeysWorkflow/index.html.md) -- [generateResetPasswordTokenWorkflow](undefined/references/medusa-workflows/generateResetPasswordTokenWorkflow/index.html.md) -- [addShippingMethodToCartWorkflow](undefined/references/medusa-workflows/addShippingMethodToCartWorkflow/index.html.md) -- [addToCartWorkflow](undefined/references/medusa-workflows/addToCartWorkflow/index.html.md) -- [completeCartWorkflow](undefined/references/medusa-workflows/completeCartWorkflow/index.html.md) -- [confirmVariantInventoryWorkflow](undefined/references/medusa-workflows/confirmVariantInventoryWorkflow/index.html.md) -- [createCartCreditLinesWorkflow](undefined/references/medusa-workflows/createCartCreditLinesWorkflow/index.html.md) -- [createCartWorkflow](undefined/references/medusa-workflows/createCartWorkflow/index.html.md) -- [createPaymentCollectionForCartWorkflow](undefined/references/medusa-workflows/createPaymentCollectionForCartWorkflow/index.html.md) -- [deleteCartCreditLinesWorkflow](undefined/references/medusa-workflows/deleteCartCreditLinesWorkflow/index.html.md) -- [listShippingOptionsForCartWithPricingWorkflow](undefined/references/medusa-workflows/listShippingOptionsForCartWithPricingWorkflow/index.html.md) -- [listShippingOptionsForCartWorkflow](undefined/references/medusa-workflows/listShippingOptionsForCartWorkflow/index.html.md) -- [refreshCartItemsWorkflow](undefined/references/medusa-workflows/refreshCartItemsWorkflow/index.html.md) -- [refreshCartShippingMethodsWorkflow](undefined/references/medusa-workflows/refreshCartShippingMethodsWorkflow/index.html.md) -- [refreshPaymentCollectionForCartWorkflow](undefined/references/medusa-workflows/refreshPaymentCollectionForCartWorkflow/index.html.md) -- [refundPaymentAndRecreatePaymentSessionWorkflow](undefined/references/medusa-workflows/refundPaymentAndRecreatePaymentSessionWorkflow/index.html.md) -- [transferCartCustomerWorkflow](undefined/references/medusa-workflows/transferCartCustomerWorkflow/index.html.md) -- [updateCartPromotionsWorkflow](undefined/references/medusa-workflows/updateCartPromotionsWorkflow/index.html.md) -- [updateCartWorkflow](undefined/references/medusa-workflows/updateCartWorkflow/index.html.md) -- [updateLineItemInCartWorkflow](undefined/references/medusa-workflows/updateLineItemInCartWorkflow/index.html.md) -- [updateTaxLinesWorkflow](undefined/references/medusa-workflows/updateTaxLinesWorkflow/index.html.md) -- [validateExistingPaymentCollectionStep](undefined/references/medusa-workflows/validateExistingPaymentCollectionStep/index.html.md) -- [batchLinksWorkflow](undefined/references/medusa-workflows/batchLinksWorkflow/index.html.md) -- [createLinksWorkflow](undefined/references/medusa-workflows/createLinksWorkflow/index.html.md) -- [dismissLinksWorkflow](undefined/references/medusa-workflows/dismissLinksWorkflow/index.html.md) -- [updateLinksWorkflow](undefined/references/medusa-workflows/updateLinksWorkflow/index.html.md) -- [createCustomerAccountWorkflow](undefined/references/medusa-workflows/createCustomerAccountWorkflow/index.html.md) -- [createCustomerAddressesWorkflow](undefined/references/medusa-workflows/createCustomerAddressesWorkflow/index.html.md) -- [createCustomersWorkflow](undefined/references/medusa-workflows/createCustomersWorkflow/index.html.md) -- [deleteCustomerAddressesWorkflow](undefined/references/medusa-workflows/deleteCustomerAddressesWorkflow/index.html.md) -- [deleteCustomersWorkflow](undefined/references/medusa-workflows/deleteCustomersWorkflow/index.html.md) -- [removeCustomerAccountWorkflow](undefined/references/medusa-workflows/removeCustomerAccountWorkflow/index.html.md) -- [updateCustomerAddressesWorkflow](undefined/references/medusa-workflows/updateCustomerAddressesWorkflow/index.html.md) -- [updateCustomersWorkflow](undefined/references/medusa-workflows/updateCustomersWorkflow/index.html.md) -- [createCustomerGroupsWorkflow](undefined/references/medusa-workflows/createCustomerGroupsWorkflow/index.html.md) -- [deleteCustomerGroupsWorkflow](undefined/references/medusa-workflows/deleteCustomerGroupsWorkflow/index.html.md) -- [linkCustomerGroupsToCustomerWorkflow](undefined/references/medusa-workflows/linkCustomerGroupsToCustomerWorkflow/index.html.md) -- [linkCustomersToCustomerGroupWorkflow](undefined/references/medusa-workflows/linkCustomersToCustomerGroupWorkflow/index.html.md) -- [updateCustomerGroupsWorkflow](undefined/references/medusa-workflows/updateCustomerGroupsWorkflow/index.html.md) -- [createDefaultsWorkflow](undefined/references/medusa-workflows/createDefaultsWorkflow/index.html.md) -- [addDraftOrderItemsWorkflow](undefined/references/medusa-workflows/addDraftOrderItemsWorkflow/index.html.md) -- [addDraftOrderPromotionWorkflow](undefined/references/medusa-workflows/addDraftOrderPromotionWorkflow/index.html.md) -- [addDraftOrderShippingMethodsWorkflow](undefined/references/medusa-workflows/addDraftOrderShippingMethodsWorkflow/index.html.md) -- [beginDraftOrderEditWorkflow](undefined/references/medusa-workflows/beginDraftOrderEditWorkflow/index.html.md) -- [cancelDraftOrderEditWorkflow](undefined/references/medusa-workflows/cancelDraftOrderEditWorkflow/index.html.md) -- [confirmDraftOrderEditWorkflow](undefined/references/medusa-workflows/confirmDraftOrderEditWorkflow/index.html.md) -- [convertDraftOrderStep](undefined/references/medusa-workflows/convertDraftOrderStep/index.html.md) -- [convertDraftOrderWorkflow](undefined/references/medusa-workflows/convertDraftOrderWorkflow/index.html.md) -- [deleteDraftOrdersWorkflow](undefined/references/medusa-workflows/deleteDraftOrdersWorkflow/index.html.md) -- [removeDraftOrderActionItemWorkflow](undefined/references/medusa-workflows/removeDraftOrderActionItemWorkflow/index.html.md) -- [removeDraftOrderActionShippingMethodWorkflow](undefined/references/medusa-workflows/removeDraftOrderActionShippingMethodWorkflow/index.html.md) -- [removeDraftOrderPromotionsWorkflow](undefined/references/medusa-workflows/removeDraftOrderPromotionsWorkflow/index.html.md) -- [removeDraftOrderShippingMethodWorkflow](undefined/references/medusa-workflows/removeDraftOrderShippingMethodWorkflow/index.html.md) -- [requestDraftOrderEditWorkflow](undefined/references/medusa-workflows/requestDraftOrderEditWorkflow/index.html.md) -- [updateDraftOrderActionItemWorkflow](undefined/references/medusa-workflows/updateDraftOrderActionItemWorkflow/index.html.md) -- [updateDraftOrderActionShippingMethodWorkflow](undefined/references/medusa-workflows/updateDraftOrderActionShippingMethodWorkflow/index.html.md) -- [updateDraftOrderItemWorkflow](undefined/references/medusa-workflows/updateDraftOrderItemWorkflow/index.html.md) -- [updateDraftOrderShippingMethodWorkflow](undefined/references/medusa-workflows/updateDraftOrderShippingMethodWorkflow/index.html.md) -- [updateDraftOrderStep](undefined/references/medusa-workflows/updateDraftOrderStep/index.html.md) -- [updateDraftOrderWorkflow](undefined/references/medusa-workflows/updateDraftOrderWorkflow/index.html.md) -- [deleteFilesWorkflow](undefined/references/medusa-workflows/deleteFilesWorkflow/index.html.md) -- [uploadFilesWorkflow](undefined/references/medusa-workflows/uploadFilesWorkflow/index.html.md) -- [batchShippingOptionRulesWorkflow](undefined/references/medusa-workflows/batchShippingOptionRulesWorkflow/index.html.md) -- [calculateShippingOptionsPricesWorkflow](undefined/references/medusa-workflows/calculateShippingOptionsPricesWorkflow/index.html.md) -- [cancelFulfillmentWorkflow](undefined/references/medusa-workflows/cancelFulfillmentWorkflow/index.html.md) -- [createFulfillmentWorkflow](undefined/references/medusa-workflows/createFulfillmentWorkflow/index.html.md) -- [createReturnFulfillmentWorkflow](undefined/references/medusa-workflows/createReturnFulfillmentWorkflow/index.html.md) -- [createServiceZonesWorkflow](undefined/references/medusa-workflows/createServiceZonesWorkflow/index.html.md) -- [createShipmentWorkflow](undefined/references/medusa-workflows/createShipmentWorkflow/index.html.md) -- [createShippingOptionsWorkflow](undefined/references/medusa-workflows/createShippingOptionsWorkflow/index.html.md) -- [createShippingProfilesWorkflow](undefined/references/medusa-workflows/createShippingProfilesWorkflow/index.html.md) -- [deleteFulfillmentSetsWorkflow](undefined/references/medusa-workflows/deleteFulfillmentSetsWorkflow/index.html.md) -- [deleteServiceZonesWorkflow](undefined/references/medusa-workflows/deleteServiceZonesWorkflow/index.html.md) -- [deleteShippingOptionsWorkflow](undefined/references/medusa-workflows/deleteShippingOptionsWorkflow/index.html.md) -- [markFulfillmentAsDeliveredWorkflow](undefined/references/medusa-workflows/markFulfillmentAsDeliveredWorkflow/index.html.md) -- [updateFulfillmentWorkflow](undefined/references/medusa-workflows/updateFulfillmentWorkflow/index.html.md) -- [updateServiceZonesWorkflow](undefined/references/medusa-workflows/updateServiceZonesWorkflow/index.html.md) -- [updateShippingOptionsWorkflow](undefined/references/medusa-workflows/updateShippingOptionsWorkflow/index.html.md) -- [updateShippingProfilesWorkflow](undefined/references/medusa-workflows/updateShippingProfilesWorkflow/index.html.md) -- [validateFulfillmentDeliverabilityStep](undefined/references/medusa-workflows/validateFulfillmentDeliverabilityStep/index.html.md) -- [batchInventoryItemLevelsWorkflow](undefined/references/medusa-workflows/batchInventoryItemLevelsWorkflow/index.html.md) -- [bulkCreateDeleteLevelsWorkflow](undefined/references/medusa-workflows/bulkCreateDeleteLevelsWorkflow/index.html.md) -- [createInventoryItemsWorkflow](undefined/references/medusa-workflows/createInventoryItemsWorkflow/index.html.md) -- [createInventoryLevelsWorkflow](undefined/references/medusa-workflows/createInventoryLevelsWorkflow/index.html.md) -- [deleteInventoryItemWorkflow](undefined/references/medusa-workflows/deleteInventoryItemWorkflow/index.html.md) -- [deleteInventoryLevelsWorkflow](undefined/references/medusa-workflows/deleteInventoryLevelsWorkflow/index.html.md) -- [updateInventoryItemsWorkflow](undefined/references/medusa-workflows/updateInventoryItemsWorkflow/index.html.md) -- [updateInventoryLevelsWorkflow](undefined/references/medusa-workflows/updateInventoryLevelsWorkflow/index.html.md) -- [validateInventoryLevelsDelete](undefined/references/medusa-workflows/validateInventoryLevelsDelete/index.html.md) -- [acceptInviteWorkflow](undefined/references/medusa-workflows/acceptInviteWorkflow/index.html.md) -- [createInvitesWorkflow](undefined/references/medusa-workflows/createInvitesWorkflow/index.html.md) -- [deleteInvitesWorkflow](undefined/references/medusa-workflows/deleteInvitesWorkflow/index.html.md) -- [refreshInviteTokensWorkflow](undefined/references/medusa-workflows/refreshInviteTokensWorkflow/index.html.md) -- [deleteLineItemsWorkflow](undefined/references/medusa-workflows/deleteLineItemsWorkflow/index.html.md) -- [acceptOrderTransferValidationStep](undefined/references/medusa-workflows/acceptOrderTransferValidationStep/index.html.md) -- [acceptOrderTransferWorkflow](undefined/references/medusa-workflows/acceptOrderTransferWorkflow/index.html.md) -- [addOrderLineItemsWorkflow](undefined/references/medusa-workflows/addOrderLineItemsWorkflow/index.html.md) -- [archiveOrderWorkflow](undefined/references/medusa-workflows/archiveOrderWorkflow/index.html.md) -- [beginClaimOrderValidationStep](undefined/references/medusa-workflows/beginClaimOrderValidationStep/index.html.md) -- [beginClaimOrderWorkflow](undefined/references/medusa-workflows/beginClaimOrderWorkflow/index.html.md) -- [beginExchangeOrderWorkflow](undefined/references/medusa-workflows/beginExchangeOrderWorkflow/index.html.md) -- [beginOrderEditOrderWorkflow](undefined/references/medusa-workflows/beginOrderEditOrderWorkflow/index.html.md) -- [beginOrderEditValidationStep](undefined/references/medusa-workflows/beginOrderEditValidationStep/index.html.md) -- [beginOrderExchangeValidationStep](undefined/references/medusa-workflows/beginOrderExchangeValidationStep/index.html.md) -- [beginReceiveReturnValidationStep](undefined/references/medusa-workflows/beginReceiveReturnValidationStep/index.html.md) -- [beginReceiveReturnWorkflow](undefined/references/medusa-workflows/beginReceiveReturnWorkflow/index.html.md) -- [beginReturnOrderValidationStep](undefined/references/medusa-workflows/beginReturnOrderValidationStep/index.html.md) -- [beginReturnOrderWorkflow](undefined/references/medusa-workflows/beginReturnOrderWorkflow/index.html.md) -- [cancelBeginOrderClaimValidationStep](undefined/references/medusa-workflows/cancelBeginOrderClaimValidationStep/index.html.md) -- [cancelBeginOrderClaimWorkflow](undefined/references/medusa-workflows/cancelBeginOrderClaimWorkflow/index.html.md) -- [cancelBeginOrderEditValidationStep](undefined/references/medusa-workflows/cancelBeginOrderEditValidationStep/index.html.md) -- [cancelBeginOrderEditWorkflow](undefined/references/medusa-workflows/cancelBeginOrderEditWorkflow/index.html.md) -- [cancelBeginOrderExchangeValidationStep](undefined/references/medusa-workflows/cancelBeginOrderExchangeValidationStep/index.html.md) -- [cancelBeginOrderExchangeWorkflow](undefined/references/medusa-workflows/cancelBeginOrderExchangeWorkflow/index.html.md) -- [cancelClaimValidateOrderStep](undefined/references/medusa-workflows/cancelClaimValidateOrderStep/index.html.md) -- [cancelExchangeValidateOrder](undefined/references/medusa-workflows/cancelExchangeValidateOrder/index.html.md) -- [cancelOrderChangeWorkflow](undefined/references/medusa-workflows/cancelOrderChangeWorkflow/index.html.md) -- [cancelOrderClaimWorkflow](undefined/references/medusa-workflows/cancelOrderClaimWorkflow/index.html.md) -- [cancelOrderExchangeWorkflow](undefined/references/medusa-workflows/cancelOrderExchangeWorkflow/index.html.md) -- [cancelOrderFulfillmentValidateOrder](undefined/references/medusa-workflows/cancelOrderFulfillmentValidateOrder/index.html.md) -- [cancelOrderFulfillmentWorkflow](undefined/references/medusa-workflows/cancelOrderFulfillmentWorkflow/index.html.md) -- [cancelOrderTransferRequestWorkflow](undefined/references/medusa-workflows/cancelOrderTransferRequestWorkflow/index.html.md) -- [cancelOrderWorkflow](undefined/references/medusa-workflows/cancelOrderWorkflow/index.html.md) -- [cancelReceiveReturnValidationStep](undefined/references/medusa-workflows/cancelReceiveReturnValidationStep/index.html.md) -- [cancelRequestReturnValidationStep](undefined/references/medusa-workflows/cancelRequestReturnValidationStep/index.html.md) -- [cancelReturnReceiveWorkflow](undefined/references/medusa-workflows/cancelReturnReceiveWorkflow/index.html.md) -- [cancelReturnRequestWorkflow](undefined/references/medusa-workflows/cancelReturnRequestWorkflow/index.html.md) -- [cancelReturnValidateOrder](undefined/references/medusa-workflows/cancelReturnValidateOrder/index.html.md) -- [cancelReturnWorkflow](undefined/references/medusa-workflows/cancelReturnWorkflow/index.html.md) -- [cancelTransferOrderRequestValidationStep](undefined/references/medusa-workflows/cancelTransferOrderRequestValidationStep/index.html.md) -- [cancelValidateOrder](undefined/references/medusa-workflows/cancelValidateOrder/index.html.md) -- [completeOrderWorkflow](undefined/references/medusa-workflows/completeOrderWorkflow/index.html.md) -- [confirmClaimRequestValidationStep](undefined/references/medusa-workflows/confirmClaimRequestValidationStep/index.html.md) -- [confirmClaimRequestWorkflow](undefined/references/medusa-workflows/confirmClaimRequestWorkflow/index.html.md) -- [confirmExchangeRequestValidationStep](undefined/references/medusa-workflows/confirmExchangeRequestValidationStep/index.html.md) -- [confirmExchangeRequestWorkflow](undefined/references/medusa-workflows/confirmExchangeRequestWorkflow/index.html.md) -- [confirmOrderEditRequestValidationStep](undefined/references/medusa-workflows/confirmOrderEditRequestValidationStep/index.html.md) -- [confirmOrderEditRequestWorkflow](undefined/references/medusa-workflows/confirmOrderEditRequestWorkflow/index.html.md) -- [confirmReceiveReturnValidationStep](undefined/references/medusa-workflows/confirmReceiveReturnValidationStep/index.html.md) -- [confirmReturnReceiveWorkflow](undefined/references/medusa-workflows/confirmReturnReceiveWorkflow/index.html.md) -- [confirmReturnRequestValidationStep](undefined/references/medusa-workflows/confirmReturnRequestValidationStep/index.html.md) -- [confirmReturnRequestWorkflow](undefined/references/medusa-workflows/confirmReturnRequestWorkflow/index.html.md) -- [createAndCompleteReturnOrderWorkflow](undefined/references/medusa-workflows/createAndCompleteReturnOrderWorkflow/index.html.md) -- [createClaimShippingMethodValidationStep](undefined/references/medusa-workflows/createClaimShippingMethodValidationStep/index.html.md) -- [createClaimShippingMethodWorkflow](undefined/references/medusa-workflows/createClaimShippingMethodWorkflow/index.html.md) -- [createCompleteReturnValidationStep](undefined/references/medusa-workflows/createCompleteReturnValidationStep/index.html.md) -- [createExchangeShippingMethodValidationStep](undefined/references/medusa-workflows/createExchangeShippingMethodValidationStep/index.html.md) -- [createExchangeShippingMethodWorkflow](undefined/references/medusa-workflows/createExchangeShippingMethodWorkflow/index.html.md) -- [createFulfillmentValidateOrder](undefined/references/medusa-workflows/createFulfillmentValidateOrder/index.html.md) -- [createOrUpdateOrderPaymentCollectionWorkflow](undefined/references/medusa-workflows/createOrUpdateOrderPaymentCollectionWorkflow/index.html.md) -- [createOrderChangeActionsWorkflow](undefined/references/medusa-workflows/createOrderChangeActionsWorkflow/index.html.md) -- [createOrderChangeWorkflow](undefined/references/medusa-workflows/createOrderChangeWorkflow/index.html.md) -- [createOrderCreditLinesWorkflow](undefined/references/medusa-workflows/createOrderCreditLinesWorkflow/index.html.md) -- [createOrderEditShippingMethodValidationStep](undefined/references/medusa-workflows/createOrderEditShippingMethodValidationStep/index.html.md) -- [createOrderEditShippingMethodWorkflow](undefined/references/medusa-workflows/createOrderEditShippingMethodWorkflow/index.html.md) -- [createOrderFulfillmentWorkflow](undefined/references/medusa-workflows/createOrderFulfillmentWorkflow/index.html.md) -- [createOrderPaymentCollectionWorkflow](undefined/references/medusa-workflows/createOrderPaymentCollectionWorkflow/index.html.md) -- [createOrderShipmentWorkflow](undefined/references/medusa-workflows/createOrderShipmentWorkflow/index.html.md) -- [createOrderWorkflow](undefined/references/medusa-workflows/createOrderWorkflow/index.html.md) -- [createOrdersWorkflow](undefined/references/medusa-workflows/createOrdersWorkflow/index.html.md) -- [createReturnShippingMethodValidationStep](undefined/references/medusa-workflows/createReturnShippingMethodValidationStep/index.html.md) -- [createReturnShippingMethodWorkflow](undefined/references/medusa-workflows/createReturnShippingMethodWorkflow/index.html.md) -- [createShipmentValidateOrder](undefined/references/medusa-workflows/createShipmentValidateOrder/index.html.md) -- [declineOrderChangeWorkflow](undefined/references/medusa-workflows/declineOrderChangeWorkflow/index.html.md) -- [declineOrderTransferRequestWorkflow](undefined/references/medusa-workflows/declineOrderTransferRequestWorkflow/index.html.md) -- [declineTransferOrderRequestValidationStep](undefined/references/medusa-workflows/declineTransferOrderRequestValidationStep/index.html.md) -- [deleteOrderChangeActionsWorkflow](undefined/references/medusa-workflows/deleteOrderChangeActionsWorkflow/index.html.md) -- [deleteOrderChangeWorkflow](undefined/references/medusa-workflows/deleteOrderChangeWorkflow/index.html.md) -- [deleteOrderPaymentCollections](undefined/references/medusa-workflows/deleteOrderPaymentCollections/index.html.md) -- [dismissItemReturnRequestValidationStep](undefined/references/medusa-workflows/dismissItemReturnRequestValidationStep/index.html.md) -- [dismissItemReturnRequestWorkflow](undefined/references/medusa-workflows/dismissItemReturnRequestWorkflow/index.html.md) -- [exchangeAddNewItemValidationStep](undefined/references/medusa-workflows/exchangeAddNewItemValidationStep/index.html.md) -- [exchangeRequestItemReturnValidationStep](undefined/references/medusa-workflows/exchangeRequestItemReturnValidationStep/index.html.md) -- [fetchShippingOptionForOrderWorkflow](undefined/references/medusa-workflows/fetchShippingOptionForOrderWorkflow/index.html.md) -- [getOrderDetailWorkflow](undefined/references/medusa-workflows/getOrderDetailWorkflow/index.html.md) -- [getOrdersListWorkflow](undefined/references/medusa-workflows/getOrdersListWorkflow/index.html.md) -- [listShippingOptionsForOrderWorkflow](undefined/references/medusa-workflows/listShippingOptionsForOrderWorkflow/index.html.md) -- [markOrderFulfillmentAsDeliveredWorkflow](undefined/references/medusa-workflows/markOrderFulfillmentAsDeliveredWorkflow/index.html.md) -- [markPaymentCollectionAsPaid](undefined/references/medusa-workflows/markPaymentCollectionAsPaid/index.html.md) -- [maybeRefreshShippingMethodsWorkflow](undefined/references/medusa-workflows/maybeRefreshShippingMethodsWorkflow/index.html.md) -- [orderClaimAddNewItemValidationStep](undefined/references/medusa-workflows/orderClaimAddNewItemValidationStep/index.html.md) -- [orderClaimAddNewItemWorkflow](undefined/references/medusa-workflows/orderClaimAddNewItemWorkflow/index.html.md) -- [orderClaimItemValidationStep](undefined/references/medusa-workflows/orderClaimItemValidationStep/index.html.md) -- [orderClaimItemWorkflow](undefined/references/medusa-workflows/orderClaimItemWorkflow/index.html.md) -- [orderClaimRequestItemReturnValidationStep](undefined/references/medusa-workflows/orderClaimRequestItemReturnValidationStep/index.html.md) -- [orderClaimRequestItemReturnWorkflow](undefined/references/medusa-workflows/orderClaimRequestItemReturnWorkflow/index.html.md) -- [orderEditAddNewItemValidationStep](undefined/references/medusa-workflows/orderEditAddNewItemValidationStep/index.html.md) -- [orderEditAddNewItemWorkflow](undefined/references/medusa-workflows/orderEditAddNewItemWorkflow/index.html.md) -- [orderEditUpdateItemQuantityValidationStep](undefined/references/medusa-workflows/orderEditUpdateItemQuantityValidationStep/index.html.md) -- [orderEditUpdateItemQuantityWorkflow](undefined/references/medusa-workflows/orderEditUpdateItemQuantityWorkflow/index.html.md) -- [orderExchangeAddNewItemWorkflow](undefined/references/medusa-workflows/orderExchangeAddNewItemWorkflow/index.html.md) -- [orderExchangeRequestItemReturnWorkflow](undefined/references/medusa-workflows/orderExchangeRequestItemReturnWorkflow/index.html.md) -- [orderFulfillmentDeliverablilityValidationStep](undefined/references/medusa-workflows/orderFulfillmentDeliverablilityValidationStep/index.html.md) -- [receiveAndCompleteReturnOrderWorkflow](undefined/references/medusa-workflows/receiveAndCompleteReturnOrderWorkflow/index.html.md) -- [receiveCompleteReturnValidationStep](undefined/references/medusa-workflows/receiveCompleteReturnValidationStep/index.html.md) -- [receiveItemReturnRequestValidationStep](undefined/references/medusa-workflows/receiveItemReturnRequestValidationStep/index.html.md) -- [receiveItemReturnRequestWorkflow](undefined/references/medusa-workflows/receiveItemReturnRequestWorkflow/index.html.md) -- [removeAddItemClaimActionWorkflow](undefined/references/medusa-workflows/removeAddItemClaimActionWorkflow/index.html.md) -- [removeClaimAddItemActionValidationStep](undefined/references/medusa-workflows/removeClaimAddItemActionValidationStep/index.html.md) -- [removeClaimItemActionValidationStep](undefined/references/medusa-workflows/removeClaimItemActionValidationStep/index.html.md) -- [removeClaimShippingMethodValidationStep](undefined/references/medusa-workflows/removeClaimShippingMethodValidationStep/index.html.md) -- [removeClaimShippingMethodWorkflow](undefined/references/medusa-workflows/removeClaimShippingMethodWorkflow/index.html.md) -- [removeExchangeItemActionValidationStep](undefined/references/medusa-workflows/removeExchangeItemActionValidationStep/index.html.md) -- [removeExchangeShippingMethodValidationStep](undefined/references/medusa-workflows/removeExchangeShippingMethodValidationStep/index.html.md) -- [removeExchangeShippingMethodWorkflow](undefined/references/medusa-workflows/removeExchangeShippingMethodWorkflow/index.html.md) -- [removeItemClaimActionWorkflow](undefined/references/medusa-workflows/removeItemClaimActionWorkflow/index.html.md) -- [removeItemExchangeActionWorkflow](undefined/references/medusa-workflows/removeItemExchangeActionWorkflow/index.html.md) -- [removeItemOrderEditActionWorkflow](undefined/references/medusa-workflows/removeItemOrderEditActionWorkflow/index.html.md) -- [removeItemReceiveReturnActionValidationStep](undefined/references/medusa-workflows/removeItemReceiveReturnActionValidationStep/index.html.md) -- [removeItemReceiveReturnActionWorkflow](undefined/references/medusa-workflows/removeItemReceiveReturnActionWorkflow/index.html.md) -- [removeItemReturnActionWorkflow](undefined/references/medusa-workflows/removeItemReturnActionWorkflow/index.html.md) -- [removeOrderEditItemActionValidationStep](undefined/references/medusa-workflows/removeOrderEditItemActionValidationStep/index.html.md) -- [removeOrderEditShippingMethodValidationStep](undefined/references/medusa-workflows/removeOrderEditShippingMethodValidationStep/index.html.md) -- [removeOrderEditShippingMethodWorkflow](undefined/references/medusa-workflows/removeOrderEditShippingMethodWorkflow/index.html.md) -- [removeReturnItemActionValidationStep](undefined/references/medusa-workflows/removeReturnItemActionValidationStep/index.html.md) -- [removeReturnShippingMethodValidationStep](undefined/references/medusa-workflows/removeReturnShippingMethodValidationStep/index.html.md) -- [removeReturnShippingMethodWorkflow](undefined/references/medusa-workflows/removeReturnShippingMethodWorkflow/index.html.md) -- [requestItemReturnValidationStep](undefined/references/medusa-workflows/requestItemReturnValidationStep/index.html.md) -- [requestItemReturnWorkflow](undefined/references/medusa-workflows/requestItemReturnWorkflow/index.html.md) -- [requestOrderEditRequestValidationStep](undefined/references/medusa-workflows/requestOrderEditRequestValidationStep/index.html.md) -- [requestOrderEditRequestWorkflow](undefined/references/medusa-workflows/requestOrderEditRequestWorkflow/index.html.md) -- [requestOrderTransferValidationStep](undefined/references/medusa-workflows/requestOrderTransferValidationStep/index.html.md) -- [requestOrderTransferWorkflow](undefined/references/medusa-workflows/requestOrderTransferWorkflow/index.html.md) -- [throwUnlessPaymentCollectionNotPaid](undefined/references/medusa-workflows/throwUnlessPaymentCollectionNotPaid/index.html.md) -- [throwUnlessStatusIsNotPaid](undefined/references/medusa-workflows/throwUnlessStatusIsNotPaid/index.html.md) -- [updateClaimAddItemValidationStep](undefined/references/medusa-workflows/updateClaimAddItemValidationStep/index.html.md) -- [updateClaimAddItemWorkflow](undefined/references/medusa-workflows/updateClaimAddItemWorkflow/index.html.md) -- [updateClaimItemValidationStep](undefined/references/medusa-workflows/updateClaimItemValidationStep/index.html.md) -- [updateClaimItemWorkflow](undefined/references/medusa-workflows/updateClaimItemWorkflow/index.html.md) -- [updateClaimShippingMethodValidationStep](undefined/references/medusa-workflows/updateClaimShippingMethodValidationStep/index.html.md) -- [updateClaimShippingMethodWorkflow](undefined/references/medusa-workflows/updateClaimShippingMethodWorkflow/index.html.md) -- [updateExchangeAddItemValidationStep](undefined/references/medusa-workflows/updateExchangeAddItemValidationStep/index.html.md) -- [updateExchangeAddItemWorkflow](undefined/references/medusa-workflows/updateExchangeAddItemWorkflow/index.html.md) -- [updateExchangeShippingMethodValidationStep](undefined/references/medusa-workflows/updateExchangeShippingMethodValidationStep/index.html.md) -- [updateExchangeShippingMethodWorkflow](undefined/references/medusa-workflows/updateExchangeShippingMethodWorkflow/index.html.md) -- [updateOrderChangeActionsWorkflow](undefined/references/medusa-workflows/updateOrderChangeActionsWorkflow/index.html.md) -- [updateOrderChangesWorkflow](undefined/references/medusa-workflows/updateOrderChangesWorkflow/index.html.md) -- [updateOrderEditAddItemValidationStep](undefined/references/medusa-workflows/updateOrderEditAddItemValidationStep/index.html.md) -- [updateOrderEditAddItemWorkflow](undefined/references/medusa-workflows/updateOrderEditAddItemWorkflow/index.html.md) -- [updateOrderEditItemQuantityValidationStep](undefined/references/medusa-workflows/updateOrderEditItemQuantityValidationStep/index.html.md) -- [updateOrderEditItemQuantityWorkflow](undefined/references/medusa-workflows/updateOrderEditItemQuantityWorkflow/index.html.md) -- [updateOrderEditShippingMethodValidationStep](undefined/references/medusa-workflows/updateOrderEditShippingMethodValidationStep/index.html.md) -- [updateOrderEditShippingMethodWorkflow](undefined/references/medusa-workflows/updateOrderEditShippingMethodWorkflow/index.html.md) -- [updateOrderTaxLinesWorkflow](undefined/references/medusa-workflows/updateOrderTaxLinesWorkflow/index.html.md) -- [updateOrderValidationStep](undefined/references/medusa-workflows/updateOrderValidationStep/index.html.md) -- [updateOrderWorkflow](undefined/references/medusa-workflows/updateOrderWorkflow/index.html.md) -- [updateReceiveItemReturnRequestValidationStep](undefined/references/medusa-workflows/updateReceiveItemReturnRequestValidationStep/index.html.md) -- [updateReceiveItemReturnRequestWorkflow](undefined/references/medusa-workflows/updateReceiveItemReturnRequestWorkflow/index.html.md) -- [updateRequestItemReturnValidationStep](undefined/references/medusa-workflows/updateRequestItemReturnValidationStep/index.html.md) -- [updateRequestItemReturnWorkflow](undefined/references/medusa-workflows/updateRequestItemReturnWorkflow/index.html.md) -- [updateReturnShippingMethodValidationStep](undefined/references/medusa-workflows/updateReturnShippingMethodValidationStep/index.html.md) -- [updateReturnShippingMethodWorkflow](undefined/references/medusa-workflows/updateReturnShippingMethodWorkflow/index.html.md) -- [updateReturnValidationStep](undefined/references/medusa-workflows/updateReturnValidationStep/index.html.md) -- [updateReturnWorkflow](undefined/references/medusa-workflows/updateReturnWorkflow/index.html.md) -- [validateOrderCreditLinesStep](undefined/references/medusa-workflows/validateOrderCreditLinesStep/index.html.md) -- [capturePaymentWorkflow](undefined/references/medusa-workflows/capturePaymentWorkflow/index.html.md) -- [processPaymentWorkflow](undefined/references/medusa-workflows/processPaymentWorkflow/index.html.md) -- [refundPaymentWorkflow](undefined/references/medusa-workflows/refundPaymentWorkflow/index.html.md) -- [refundPaymentsWorkflow](undefined/references/medusa-workflows/refundPaymentsWorkflow/index.html.md) -- [validatePaymentsRefundStep](undefined/references/medusa-workflows/validatePaymentsRefundStep/index.html.md) -- [validateRefundStep](undefined/references/medusa-workflows/validateRefundStep/index.html.md) -- [createPaymentSessionsWorkflow](undefined/references/medusa-workflows/createPaymentSessionsWorkflow/index.html.md) -- [createRefundReasonsWorkflow](undefined/references/medusa-workflows/createRefundReasonsWorkflow/index.html.md) -- [deletePaymentSessionsWorkflow](undefined/references/medusa-workflows/deletePaymentSessionsWorkflow/index.html.md) -- [deleteRefundReasonsWorkflow](undefined/references/medusa-workflows/deleteRefundReasonsWorkflow/index.html.md) -- [updateRefundReasonsWorkflow](undefined/references/medusa-workflows/updateRefundReasonsWorkflow/index.html.md) -- [batchPriceListPricesWorkflow](undefined/references/medusa-workflows/batchPriceListPricesWorkflow/index.html.md) -- [createPriceListPricesWorkflow](undefined/references/medusa-workflows/createPriceListPricesWorkflow/index.html.md) -- [createPriceListsWorkflow](undefined/references/medusa-workflows/createPriceListsWorkflow/index.html.md) -- [deletePriceListsWorkflow](undefined/references/medusa-workflows/deletePriceListsWorkflow/index.html.md) -- [removePriceListPricesWorkflow](undefined/references/medusa-workflows/removePriceListPricesWorkflow/index.html.md) -- [updatePriceListPricesWorkflow](undefined/references/medusa-workflows/updatePriceListPricesWorkflow/index.html.md) -- [updatePriceListsWorkflow](undefined/references/medusa-workflows/updatePriceListsWorkflow/index.html.md) -- [createPricePreferencesWorkflow](undefined/references/medusa-workflows/createPricePreferencesWorkflow/index.html.md) -- [deletePricePreferencesWorkflow](undefined/references/medusa-workflows/deletePricePreferencesWorkflow/index.html.md) -- [updatePricePreferencesWorkflow](undefined/references/medusa-workflows/updatePricePreferencesWorkflow/index.html.md) -- [batchLinkProductsToCategoryWorkflow](undefined/references/medusa-workflows/batchLinkProductsToCategoryWorkflow/index.html.md) -- [batchLinkProductsToCollectionWorkflow](undefined/references/medusa-workflows/batchLinkProductsToCollectionWorkflow/index.html.md) -- [batchProductVariantsWorkflow](undefined/references/medusa-workflows/batchProductVariantsWorkflow/index.html.md) -- [batchProductsWorkflow](undefined/references/medusa-workflows/batchProductsWorkflow/index.html.md) -- [createCollectionsWorkflow](undefined/references/medusa-workflows/createCollectionsWorkflow/index.html.md) -- [createProductOptionsWorkflow](undefined/references/medusa-workflows/createProductOptionsWorkflow/index.html.md) -- [createProductTagsWorkflow](undefined/references/medusa-workflows/createProductTagsWorkflow/index.html.md) -- [createProductTypesWorkflow](undefined/references/medusa-workflows/createProductTypesWorkflow/index.html.md) -- [createProductVariantsWorkflow](undefined/references/medusa-workflows/createProductVariantsWorkflow/index.html.md) -- [createProductsWorkflow](undefined/references/medusa-workflows/createProductsWorkflow/index.html.md) -- [deleteCollectionsWorkflow](undefined/references/medusa-workflows/deleteCollectionsWorkflow/index.html.md) -- [deleteProductOptionsWorkflow](undefined/references/medusa-workflows/deleteProductOptionsWorkflow/index.html.md) -- [deleteProductTagsWorkflow](undefined/references/medusa-workflows/deleteProductTagsWorkflow/index.html.md) -- [deleteProductTypesWorkflow](undefined/references/medusa-workflows/deleteProductTypesWorkflow/index.html.md) -- [deleteProductVariantsWorkflow](undefined/references/medusa-workflows/deleteProductVariantsWorkflow/index.html.md) -- [deleteProductsWorkflow](undefined/references/medusa-workflows/deleteProductsWorkflow/index.html.md) -- [exportProductsWorkflow](undefined/references/medusa-workflows/exportProductsWorkflow/index.html.md) -- [importProductsAsChunksWorkflow](undefined/references/medusa-workflows/importProductsAsChunksWorkflow/index.html.md) -- [importProductsWorkflow](undefined/references/medusa-workflows/importProductsWorkflow/index.html.md) -- [updateCollectionsWorkflow](undefined/references/medusa-workflows/updateCollectionsWorkflow/index.html.md) -- [updateProductOptionsWorkflow](undefined/references/medusa-workflows/updateProductOptionsWorkflow/index.html.md) -- [updateProductTagsWorkflow](undefined/references/medusa-workflows/updateProductTagsWorkflow/index.html.md) -- [updateProductTypesWorkflow](undefined/references/medusa-workflows/updateProductTypesWorkflow/index.html.md) -- [updateProductVariantsWorkflow](undefined/references/medusa-workflows/updateProductVariantsWorkflow/index.html.md) -- [updateProductsWorkflow](undefined/references/medusa-workflows/updateProductsWorkflow/index.html.md) -- [upsertVariantPricesWorkflow](undefined/references/medusa-workflows/upsertVariantPricesWorkflow/index.html.md) -- [validateProductInputStep](undefined/references/medusa-workflows/validateProductInputStep/index.html.md) -- [createProductCategoriesWorkflow](undefined/references/medusa-workflows/createProductCategoriesWorkflow/index.html.md) -- [deleteProductCategoriesWorkflow](undefined/references/medusa-workflows/deleteProductCategoriesWorkflow/index.html.md) -- [updateProductCategoriesWorkflow](undefined/references/medusa-workflows/updateProductCategoriesWorkflow/index.html.md) -- [addOrRemoveCampaignPromotionsWorkflow](undefined/references/medusa-workflows/addOrRemoveCampaignPromotionsWorkflow/index.html.md) -- [batchPromotionRulesWorkflow](undefined/references/medusa-workflows/batchPromotionRulesWorkflow/index.html.md) -- [createCampaignsWorkflow](undefined/references/medusa-workflows/createCampaignsWorkflow/index.html.md) -- [createPromotionRulesWorkflow](undefined/references/medusa-workflows/createPromotionRulesWorkflow/index.html.md) -- [createPromotionsWorkflow](undefined/references/medusa-workflows/createPromotionsWorkflow/index.html.md) -- [deleteCampaignsWorkflow](undefined/references/medusa-workflows/deleteCampaignsWorkflow/index.html.md) -- [deletePromotionRulesWorkflow](undefined/references/medusa-workflows/deletePromotionRulesWorkflow/index.html.md) -- [deletePromotionsWorkflow](undefined/references/medusa-workflows/deletePromotionsWorkflow/index.html.md) -- [updateCampaignsWorkflow](undefined/references/medusa-workflows/updateCampaignsWorkflow/index.html.md) -- [updatePromotionRulesWorkflow](undefined/references/medusa-workflows/updatePromotionRulesWorkflow/index.html.md) -- [updatePromotionsStatusWorkflow](undefined/references/medusa-workflows/updatePromotionsStatusWorkflow/index.html.md) -- [updatePromotionsValidationStep](undefined/references/medusa-workflows/updatePromotionsValidationStep/index.html.md) -- [updatePromotionsWorkflow](undefined/references/medusa-workflows/updatePromotionsWorkflow/index.html.md) -- [createRegionsWorkflow](undefined/references/medusa-workflows/createRegionsWorkflow/index.html.md) -- [deleteRegionsWorkflow](undefined/references/medusa-workflows/deleteRegionsWorkflow/index.html.md) -- [updateRegionsWorkflow](undefined/references/medusa-workflows/updateRegionsWorkflow/index.html.md) -- [createReservationsWorkflow](undefined/references/medusa-workflows/createReservationsWorkflow/index.html.md) -- [deleteReservationsByLineItemsWorkflow](undefined/references/medusa-workflows/deleteReservationsByLineItemsWorkflow/index.html.md) -- [deleteReservationsWorkflow](undefined/references/medusa-workflows/deleteReservationsWorkflow/index.html.md) -- [updateReservationsWorkflow](undefined/references/medusa-workflows/updateReservationsWorkflow/index.html.md) -- [createReturnReasonsWorkflow](undefined/references/medusa-workflows/createReturnReasonsWorkflow/index.html.md) -- [deleteReturnReasonsWorkflow](undefined/references/medusa-workflows/deleteReturnReasonsWorkflow/index.html.md) -- [updateReturnReasonsWorkflow](undefined/references/medusa-workflows/updateReturnReasonsWorkflow/index.html.md) -- [createSalesChannelsWorkflow](undefined/references/medusa-workflows/createSalesChannelsWorkflow/index.html.md) -- [deleteSalesChannelsWorkflow](undefined/references/medusa-workflows/deleteSalesChannelsWorkflow/index.html.md) -- [linkProductsToSalesChannelWorkflow](undefined/references/medusa-workflows/linkProductsToSalesChannelWorkflow/index.html.md) -- [updateSalesChannelsWorkflow](undefined/references/medusa-workflows/updateSalesChannelsWorkflow/index.html.md) -- [createViewConfigurationWorkflow](undefined/references/medusa-workflows/createViewConfigurationWorkflow/index.html.md) -- [updateViewConfigurationWorkflow](undefined/references/medusa-workflows/updateViewConfigurationWorkflow/index.html.md) -- [createShippingOptionTypesWorkflow](undefined/references/medusa-workflows/createShippingOptionTypesWorkflow/index.html.md) -- [deleteShippingOptionTypesWorkflow](undefined/references/medusa-workflows/deleteShippingOptionTypesWorkflow/index.html.md) -- [updateShippingOptionTypesWorkflow](undefined/references/medusa-workflows/updateShippingOptionTypesWorkflow/index.html.md) -- [deleteShippingProfileWorkflow](undefined/references/medusa-workflows/deleteShippingProfileWorkflow/index.html.md) -- [validateStepShippingProfileDelete](undefined/references/medusa-workflows/validateStepShippingProfileDelete/index.html.md) -- [createLocationFulfillmentSetWorkflow](undefined/references/medusa-workflows/createLocationFulfillmentSetWorkflow/index.html.md) -- [createStockLocationsWorkflow](undefined/references/medusa-workflows/createStockLocationsWorkflow/index.html.md) -- [deleteStockLocationsWorkflow](undefined/references/medusa-workflows/deleteStockLocationsWorkflow/index.html.md) -- [linkSalesChannelsToStockLocationWorkflow](undefined/references/medusa-workflows/linkSalesChannelsToStockLocationWorkflow/index.html.md) -- [updateStockLocationsWorkflow](undefined/references/medusa-workflows/updateStockLocationsWorkflow/index.html.md) -- [createStoresWorkflow](undefined/references/medusa-workflows/createStoresWorkflow/index.html.md) -- [deleteStoresWorkflow](undefined/references/medusa-workflows/deleteStoresWorkflow/index.html.md) -- [updateStoresWorkflow](undefined/references/medusa-workflows/updateStoresWorkflow/index.html.md) -- [createTaxRateRulesWorkflow](undefined/references/medusa-workflows/createTaxRateRulesWorkflow/index.html.md) -- [createTaxRatesWorkflow](undefined/references/medusa-workflows/createTaxRatesWorkflow/index.html.md) -- [createTaxRegionsWorkflow](undefined/references/medusa-workflows/createTaxRegionsWorkflow/index.html.md) -- [deleteTaxRateRulesWorkflow](undefined/references/medusa-workflows/deleteTaxRateRulesWorkflow/index.html.md) -- [deleteTaxRatesWorkflow](undefined/references/medusa-workflows/deleteTaxRatesWorkflow/index.html.md) -- [deleteTaxRegionsWorkflow](undefined/references/medusa-workflows/deleteTaxRegionsWorkflow/index.html.md) -- [maybeListTaxRateRuleIdsStep](undefined/references/medusa-workflows/maybeListTaxRateRuleIdsStep/index.html.md) -- [setTaxRateRulesWorkflow](undefined/references/medusa-workflows/setTaxRateRulesWorkflow/index.html.md) -- [updateTaxRatesWorkflow](undefined/references/medusa-workflows/updateTaxRatesWorkflow/index.html.md) -- [updateTaxRegionsWorkflow](undefined/references/medusa-workflows/updateTaxRegionsWorkflow/index.html.md) -- [createUserAccountWorkflow](undefined/references/medusa-workflows/createUserAccountWorkflow/index.html.md) -- [createUsersWorkflow](undefined/references/medusa-workflows/createUsersWorkflow/index.html.md) -- [deleteUsersWorkflow](undefined/references/medusa-workflows/deleteUsersWorkflow/index.html.md) -- [removeUserAccountWorkflow](undefined/references/medusa-workflows/removeUserAccountWorkflow/index.html.md) -- [updateUsersWorkflow](undefined/references/medusa-workflows/updateUsersWorkflow/index.html.md) +- [createApiKeysWorkflow](https://docs.medusajs.com/references/medusa-workflows/createApiKeysWorkflow/index.html.md) +- [deleteApiKeysWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteApiKeysWorkflow/index.html.md) +- [linkSalesChannelsToApiKeyWorkflow](https://docs.medusajs.com/references/medusa-workflows/linkSalesChannelsToApiKeyWorkflow/index.html.md) +- [revokeApiKeysWorkflow](https://docs.medusajs.com/references/medusa-workflows/revokeApiKeysWorkflow/index.html.md) +- [updateApiKeysWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateApiKeysWorkflow/index.html.md) +- [generateResetPasswordTokenWorkflow](https://docs.medusajs.com/references/medusa-workflows/generateResetPasswordTokenWorkflow/index.html.md) +- [addShippingMethodToCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/addShippingMethodToCartWorkflow/index.html.md) +- [addToCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/addToCartWorkflow/index.html.md) +- [completeCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/completeCartWorkflow/index.html.md) +- [confirmVariantInventoryWorkflow](https://docs.medusajs.com/references/medusa-workflows/confirmVariantInventoryWorkflow/index.html.md) +- [createCartCreditLinesWorkflow](https://docs.medusajs.com/references/medusa-workflows/createCartCreditLinesWorkflow/index.html.md) +- [createCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/createCartWorkflow/index.html.md) +- [createPaymentCollectionForCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/createPaymentCollectionForCartWorkflow/index.html.md) +- [deleteCartCreditLinesWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteCartCreditLinesWorkflow/index.html.md) +- [listShippingOptionsForCartWithPricingWorkflow](https://docs.medusajs.com/references/medusa-workflows/listShippingOptionsForCartWithPricingWorkflow/index.html.md) +- [listShippingOptionsForCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/listShippingOptionsForCartWorkflow/index.html.md) +- [refreshCartItemsWorkflow](https://docs.medusajs.com/references/medusa-workflows/refreshCartItemsWorkflow/index.html.md) +- [refreshCartShippingMethodsWorkflow](https://docs.medusajs.com/references/medusa-workflows/refreshCartShippingMethodsWorkflow/index.html.md) +- [refreshPaymentCollectionForCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/refreshPaymentCollectionForCartWorkflow/index.html.md) +- [refundPaymentAndRecreatePaymentSessionWorkflow](https://docs.medusajs.com/references/medusa-workflows/refundPaymentAndRecreatePaymentSessionWorkflow/index.html.md) +- [transferCartCustomerWorkflow](https://docs.medusajs.com/references/medusa-workflows/transferCartCustomerWorkflow/index.html.md) +- [updateCartPromotionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateCartPromotionsWorkflow/index.html.md) +- [updateCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateCartWorkflow/index.html.md) +- [updateLineItemInCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateLineItemInCartWorkflow/index.html.md) +- [updateTaxLinesWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateTaxLinesWorkflow/index.html.md) +- [validateExistingPaymentCollectionStep](https://docs.medusajs.com/references/medusa-workflows/validateExistingPaymentCollectionStep/index.html.md) +- [batchLinksWorkflow](https://docs.medusajs.com/references/medusa-workflows/batchLinksWorkflow/index.html.md) +- [createLinksWorkflow](https://docs.medusajs.com/references/medusa-workflows/createLinksWorkflow/index.html.md) +- [dismissLinksWorkflow](https://docs.medusajs.com/references/medusa-workflows/dismissLinksWorkflow/index.html.md) +- [updateLinksWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateLinksWorkflow/index.html.md) +- [createCustomerAccountWorkflow](https://docs.medusajs.com/references/medusa-workflows/createCustomerAccountWorkflow/index.html.md) +- [createCustomerAddressesWorkflow](https://docs.medusajs.com/references/medusa-workflows/createCustomerAddressesWorkflow/index.html.md) +- [createCustomersWorkflow](https://docs.medusajs.com/references/medusa-workflows/createCustomersWorkflow/index.html.md) +- [deleteCustomerAddressesWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteCustomerAddressesWorkflow/index.html.md) +- [deleteCustomersWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteCustomersWorkflow/index.html.md) +- [removeCustomerAccountWorkflow](https://docs.medusajs.com/references/medusa-workflows/removeCustomerAccountWorkflow/index.html.md) +- [updateCustomerAddressesWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateCustomerAddressesWorkflow/index.html.md) +- [updateCustomersWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateCustomersWorkflow/index.html.md) +- [createCustomerGroupsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createCustomerGroupsWorkflow/index.html.md) +- [deleteCustomerGroupsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteCustomerGroupsWorkflow/index.html.md) +- [linkCustomerGroupsToCustomerWorkflow](https://docs.medusajs.com/references/medusa-workflows/linkCustomerGroupsToCustomerWorkflow/index.html.md) +- [linkCustomersToCustomerGroupWorkflow](https://docs.medusajs.com/references/medusa-workflows/linkCustomersToCustomerGroupWorkflow/index.html.md) +- [updateCustomerGroupsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateCustomerGroupsWorkflow/index.html.md) +- [createDefaultsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createDefaultsWorkflow/index.html.md) +- [addDraftOrderItemsWorkflow](https://docs.medusajs.com/references/medusa-workflows/addDraftOrderItemsWorkflow/index.html.md) +- [addDraftOrderPromotionWorkflow](https://docs.medusajs.com/references/medusa-workflows/addDraftOrderPromotionWorkflow/index.html.md) +- [addDraftOrderShippingMethodsWorkflow](https://docs.medusajs.com/references/medusa-workflows/addDraftOrderShippingMethodsWorkflow/index.html.md) +- [beginDraftOrderEditWorkflow](https://docs.medusajs.com/references/medusa-workflows/beginDraftOrderEditWorkflow/index.html.md) +- [cancelDraftOrderEditWorkflow](https://docs.medusajs.com/references/medusa-workflows/cancelDraftOrderEditWorkflow/index.html.md) +- [confirmDraftOrderEditWorkflow](https://docs.medusajs.com/references/medusa-workflows/confirmDraftOrderEditWorkflow/index.html.md) +- [convertDraftOrderStep](https://docs.medusajs.com/references/medusa-workflows/convertDraftOrderStep/index.html.md) +- [convertDraftOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/convertDraftOrderWorkflow/index.html.md) +- [deleteDraftOrdersWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteDraftOrdersWorkflow/index.html.md) +- [removeDraftOrderActionItemWorkflow](https://docs.medusajs.com/references/medusa-workflows/removeDraftOrderActionItemWorkflow/index.html.md) +- [removeDraftOrderActionShippingMethodWorkflow](https://docs.medusajs.com/references/medusa-workflows/removeDraftOrderActionShippingMethodWorkflow/index.html.md) +- [removeDraftOrderPromotionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/removeDraftOrderPromotionsWorkflow/index.html.md) +- [removeDraftOrderShippingMethodWorkflow](https://docs.medusajs.com/references/medusa-workflows/removeDraftOrderShippingMethodWorkflow/index.html.md) +- [requestDraftOrderEditWorkflow](https://docs.medusajs.com/references/medusa-workflows/requestDraftOrderEditWorkflow/index.html.md) +- [updateDraftOrderActionItemWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateDraftOrderActionItemWorkflow/index.html.md) +- [updateDraftOrderActionShippingMethodWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateDraftOrderActionShippingMethodWorkflow/index.html.md) +- [updateDraftOrderItemWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateDraftOrderItemWorkflow/index.html.md) +- [updateDraftOrderShippingMethodWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateDraftOrderShippingMethodWorkflow/index.html.md) +- [updateDraftOrderStep](https://docs.medusajs.com/references/medusa-workflows/updateDraftOrderStep/index.html.md) +- [updateDraftOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateDraftOrderWorkflow/index.html.md) +- [deleteFilesWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteFilesWorkflow/index.html.md) +- [uploadFilesWorkflow](https://docs.medusajs.com/references/medusa-workflows/uploadFilesWorkflow/index.html.md) +- [batchShippingOptionRulesWorkflow](https://docs.medusajs.com/references/medusa-workflows/batchShippingOptionRulesWorkflow/index.html.md) +- [calculateShippingOptionsPricesWorkflow](https://docs.medusajs.com/references/medusa-workflows/calculateShippingOptionsPricesWorkflow/index.html.md) +- [cancelFulfillmentWorkflow](https://docs.medusajs.com/references/medusa-workflows/cancelFulfillmentWorkflow/index.html.md) +- [createFulfillmentWorkflow](https://docs.medusajs.com/references/medusa-workflows/createFulfillmentWorkflow/index.html.md) +- [createReturnFulfillmentWorkflow](https://docs.medusajs.com/references/medusa-workflows/createReturnFulfillmentWorkflow/index.html.md) +- [createServiceZonesWorkflow](https://docs.medusajs.com/references/medusa-workflows/createServiceZonesWorkflow/index.html.md) +- [createShipmentWorkflow](https://docs.medusajs.com/references/medusa-workflows/createShipmentWorkflow/index.html.md) +- [createShippingOptionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createShippingOptionsWorkflow/index.html.md) +- [createShippingProfilesWorkflow](https://docs.medusajs.com/references/medusa-workflows/createShippingProfilesWorkflow/index.html.md) +- [deleteFulfillmentSetsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteFulfillmentSetsWorkflow/index.html.md) +- [deleteServiceZonesWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteServiceZonesWorkflow/index.html.md) +- [deleteShippingOptionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteShippingOptionsWorkflow/index.html.md) +- [markFulfillmentAsDeliveredWorkflow](https://docs.medusajs.com/references/medusa-workflows/markFulfillmentAsDeliveredWorkflow/index.html.md) +- [updateFulfillmentWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateFulfillmentWorkflow/index.html.md) +- [updateServiceZonesWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateServiceZonesWorkflow/index.html.md) +- [updateShippingOptionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateShippingOptionsWorkflow/index.html.md) +- [updateShippingProfilesWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateShippingProfilesWorkflow/index.html.md) +- [validateFulfillmentDeliverabilityStep](https://docs.medusajs.com/references/medusa-workflows/validateFulfillmentDeliverabilityStep/index.html.md) +- [batchInventoryItemLevelsWorkflow](https://docs.medusajs.com/references/medusa-workflows/batchInventoryItemLevelsWorkflow/index.html.md) +- [bulkCreateDeleteLevelsWorkflow](https://docs.medusajs.com/references/medusa-workflows/bulkCreateDeleteLevelsWorkflow/index.html.md) +- [createInventoryItemsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createInventoryItemsWorkflow/index.html.md) +- [createInventoryLevelsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createInventoryLevelsWorkflow/index.html.md) +- [deleteInventoryItemWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteInventoryItemWorkflow/index.html.md) +- [deleteInventoryLevelsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteInventoryLevelsWorkflow/index.html.md) +- [updateInventoryItemsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateInventoryItemsWorkflow/index.html.md) +- [updateInventoryLevelsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateInventoryLevelsWorkflow/index.html.md) +- [validateInventoryLevelsDelete](https://docs.medusajs.com/references/medusa-workflows/validateInventoryLevelsDelete/index.html.md) +- [acceptInviteWorkflow](https://docs.medusajs.com/references/medusa-workflows/acceptInviteWorkflow/index.html.md) +- [createInvitesWorkflow](https://docs.medusajs.com/references/medusa-workflows/createInvitesWorkflow/index.html.md) +- [deleteInvitesWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteInvitesWorkflow/index.html.md) +- [refreshInviteTokensWorkflow](https://docs.medusajs.com/references/medusa-workflows/refreshInviteTokensWorkflow/index.html.md) +- [deleteLineItemsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteLineItemsWorkflow/index.html.md) +- [acceptOrderTransferValidationStep](https://docs.medusajs.com/references/medusa-workflows/acceptOrderTransferValidationStep/index.html.md) +- [acceptOrderTransferWorkflow](https://docs.medusajs.com/references/medusa-workflows/acceptOrderTransferWorkflow/index.html.md) +- [addOrderLineItemsWorkflow](https://docs.medusajs.com/references/medusa-workflows/addOrderLineItemsWorkflow/index.html.md) +- [archiveOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/archiveOrderWorkflow/index.html.md) +- [beginClaimOrderValidationStep](https://docs.medusajs.com/references/medusa-workflows/beginClaimOrderValidationStep/index.html.md) +- [beginClaimOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/beginClaimOrderWorkflow/index.html.md) +- [beginExchangeOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/beginExchangeOrderWorkflow/index.html.md) +- [beginOrderEditOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/beginOrderEditOrderWorkflow/index.html.md) +- [beginOrderEditValidationStep](https://docs.medusajs.com/references/medusa-workflows/beginOrderEditValidationStep/index.html.md) +- [beginOrderExchangeValidationStep](https://docs.medusajs.com/references/medusa-workflows/beginOrderExchangeValidationStep/index.html.md) +- [beginReceiveReturnValidationStep](https://docs.medusajs.com/references/medusa-workflows/beginReceiveReturnValidationStep/index.html.md) +- [beginReceiveReturnWorkflow](https://docs.medusajs.com/references/medusa-workflows/beginReceiveReturnWorkflow/index.html.md) +- [beginReturnOrderValidationStep](https://docs.medusajs.com/references/medusa-workflows/beginReturnOrderValidationStep/index.html.md) +- [beginReturnOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/beginReturnOrderWorkflow/index.html.md) +- [cancelBeginOrderClaimValidationStep](https://docs.medusajs.com/references/medusa-workflows/cancelBeginOrderClaimValidationStep/index.html.md) +- [cancelBeginOrderClaimWorkflow](https://docs.medusajs.com/references/medusa-workflows/cancelBeginOrderClaimWorkflow/index.html.md) +- [cancelBeginOrderEditValidationStep](https://docs.medusajs.com/references/medusa-workflows/cancelBeginOrderEditValidationStep/index.html.md) +- [cancelBeginOrderEditWorkflow](https://docs.medusajs.com/references/medusa-workflows/cancelBeginOrderEditWorkflow/index.html.md) +- [cancelBeginOrderExchangeValidationStep](https://docs.medusajs.com/references/medusa-workflows/cancelBeginOrderExchangeValidationStep/index.html.md) +- [cancelBeginOrderExchangeWorkflow](https://docs.medusajs.com/references/medusa-workflows/cancelBeginOrderExchangeWorkflow/index.html.md) +- [cancelClaimValidateOrderStep](https://docs.medusajs.com/references/medusa-workflows/cancelClaimValidateOrderStep/index.html.md) +- [cancelExchangeValidateOrder](https://docs.medusajs.com/references/medusa-workflows/cancelExchangeValidateOrder/index.html.md) +- [cancelOrderChangeWorkflow](https://docs.medusajs.com/references/medusa-workflows/cancelOrderChangeWorkflow/index.html.md) +- [cancelOrderClaimWorkflow](https://docs.medusajs.com/references/medusa-workflows/cancelOrderClaimWorkflow/index.html.md) +- [cancelOrderExchangeWorkflow](https://docs.medusajs.com/references/medusa-workflows/cancelOrderExchangeWorkflow/index.html.md) +- [cancelOrderFulfillmentValidateOrder](https://docs.medusajs.com/references/medusa-workflows/cancelOrderFulfillmentValidateOrder/index.html.md) +- [cancelOrderFulfillmentWorkflow](https://docs.medusajs.com/references/medusa-workflows/cancelOrderFulfillmentWorkflow/index.html.md) +- [cancelOrderTransferRequestWorkflow](https://docs.medusajs.com/references/medusa-workflows/cancelOrderTransferRequestWorkflow/index.html.md) +- [cancelOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/cancelOrderWorkflow/index.html.md) +- [cancelReceiveReturnValidationStep](https://docs.medusajs.com/references/medusa-workflows/cancelReceiveReturnValidationStep/index.html.md) +- [cancelRequestReturnValidationStep](https://docs.medusajs.com/references/medusa-workflows/cancelRequestReturnValidationStep/index.html.md) +- [cancelReturnReceiveWorkflow](https://docs.medusajs.com/references/medusa-workflows/cancelReturnReceiveWorkflow/index.html.md) +- [cancelReturnRequestWorkflow](https://docs.medusajs.com/references/medusa-workflows/cancelReturnRequestWorkflow/index.html.md) +- [cancelReturnValidateOrder](https://docs.medusajs.com/references/medusa-workflows/cancelReturnValidateOrder/index.html.md) +- [cancelReturnWorkflow](https://docs.medusajs.com/references/medusa-workflows/cancelReturnWorkflow/index.html.md) +- [cancelTransferOrderRequestValidationStep](https://docs.medusajs.com/references/medusa-workflows/cancelTransferOrderRequestValidationStep/index.html.md) +- [cancelValidateOrder](https://docs.medusajs.com/references/medusa-workflows/cancelValidateOrder/index.html.md) +- [completeOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/completeOrderWorkflow/index.html.md) +- [confirmClaimRequestValidationStep](https://docs.medusajs.com/references/medusa-workflows/confirmClaimRequestValidationStep/index.html.md) +- [confirmClaimRequestWorkflow](https://docs.medusajs.com/references/medusa-workflows/confirmClaimRequestWorkflow/index.html.md) +- [confirmExchangeRequestValidationStep](https://docs.medusajs.com/references/medusa-workflows/confirmExchangeRequestValidationStep/index.html.md) +- [confirmExchangeRequestWorkflow](https://docs.medusajs.com/references/medusa-workflows/confirmExchangeRequestWorkflow/index.html.md) +- [confirmOrderEditRequestValidationStep](https://docs.medusajs.com/references/medusa-workflows/confirmOrderEditRequestValidationStep/index.html.md) +- [confirmOrderEditRequestWorkflow](https://docs.medusajs.com/references/medusa-workflows/confirmOrderEditRequestWorkflow/index.html.md) +- [confirmReceiveReturnValidationStep](https://docs.medusajs.com/references/medusa-workflows/confirmReceiveReturnValidationStep/index.html.md) +- [confirmReturnReceiveWorkflow](https://docs.medusajs.com/references/medusa-workflows/confirmReturnReceiveWorkflow/index.html.md) +- [confirmReturnRequestValidationStep](https://docs.medusajs.com/references/medusa-workflows/confirmReturnRequestValidationStep/index.html.md) +- [confirmReturnRequestWorkflow](https://docs.medusajs.com/references/medusa-workflows/confirmReturnRequestWorkflow/index.html.md) +- [createAndCompleteReturnOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/createAndCompleteReturnOrderWorkflow/index.html.md) +- [createClaimShippingMethodValidationStep](https://docs.medusajs.com/references/medusa-workflows/createClaimShippingMethodValidationStep/index.html.md) +- [createClaimShippingMethodWorkflow](https://docs.medusajs.com/references/medusa-workflows/createClaimShippingMethodWorkflow/index.html.md) +- [createCompleteReturnValidationStep](https://docs.medusajs.com/references/medusa-workflows/createCompleteReturnValidationStep/index.html.md) +- [createExchangeShippingMethodValidationStep](https://docs.medusajs.com/references/medusa-workflows/createExchangeShippingMethodValidationStep/index.html.md) +- [createExchangeShippingMethodWorkflow](https://docs.medusajs.com/references/medusa-workflows/createExchangeShippingMethodWorkflow/index.html.md) +- [createFulfillmentValidateOrder](https://docs.medusajs.com/references/medusa-workflows/createFulfillmentValidateOrder/index.html.md) +- [createOrUpdateOrderPaymentCollectionWorkflow](https://docs.medusajs.com/references/medusa-workflows/createOrUpdateOrderPaymentCollectionWorkflow/index.html.md) +- [createOrderChangeActionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createOrderChangeActionsWorkflow/index.html.md) +- [createOrderChangeWorkflow](https://docs.medusajs.com/references/medusa-workflows/createOrderChangeWorkflow/index.html.md) +- [createOrderCreditLinesWorkflow](https://docs.medusajs.com/references/medusa-workflows/createOrderCreditLinesWorkflow/index.html.md) +- [createOrderEditShippingMethodValidationStep](https://docs.medusajs.com/references/medusa-workflows/createOrderEditShippingMethodValidationStep/index.html.md) +- [createOrderEditShippingMethodWorkflow](https://docs.medusajs.com/references/medusa-workflows/createOrderEditShippingMethodWorkflow/index.html.md) +- [createOrderFulfillmentWorkflow](https://docs.medusajs.com/references/medusa-workflows/createOrderFulfillmentWorkflow/index.html.md) +- [createOrderPaymentCollectionWorkflow](https://docs.medusajs.com/references/medusa-workflows/createOrderPaymentCollectionWorkflow/index.html.md) +- [createOrderShipmentWorkflow](https://docs.medusajs.com/references/medusa-workflows/createOrderShipmentWorkflow/index.html.md) +- [createOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/createOrderWorkflow/index.html.md) +- [createOrdersWorkflow](https://docs.medusajs.com/references/medusa-workflows/createOrdersWorkflow/index.html.md) +- [createReturnShippingMethodValidationStep](https://docs.medusajs.com/references/medusa-workflows/createReturnShippingMethodValidationStep/index.html.md) +- [createReturnShippingMethodWorkflow](https://docs.medusajs.com/references/medusa-workflows/createReturnShippingMethodWorkflow/index.html.md) +- [createShipmentValidateOrder](https://docs.medusajs.com/references/medusa-workflows/createShipmentValidateOrder/index.html.md) +- [declineOrderChangeWorkflow](https://docs.medusajs.com/references/medusa-workflows/declineOrderChangeWorkflow/index.html.md) +- [declineOrderTransferRequestWorkflow](https://docs.medusajs.com/references/medusa-workflows/declineOrderTransferRequestWorkflow/index.html.md) +- [declineTransferOrderRequestValidationStep](https://docs.medusajs.com/references/medusa-workflows/declineTransferOrderRequestValidationStep/index.html.md) +- [deleteOrderChangeActionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteOrderChangeActionsWorkflow/index.html.md) +- [deleteOrderChangeWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteOrderChangeWorkflow/index.html.md) +- [deleteOrderPaymentCollections](https://docs.medusajs.com/references/medusa-workflows/deleteOrderPaymentCollections/index.html.md) +- [dismissItemReturnRequestValidationStep](https://docs.medusajs.com/references/medusa-workflows/dismissItemReturnRequestValidationStep/index.html.md) +- [dismissItemReturnRequestWorkflow](https://docs.medusajs.com/references/medusa-workflows/dismissItemReturnRequestWorkflow/index.html.md) +- [exchangeAddNewItemValidationStep](https://docs.medusajs.com/references/medusa-workflows/exchangeAddNewItemValidationStep/index.html.md) +- [exchangeRequestItemReturnValidationStep](https://docs.medusajs.com/references/medusa-workflows/exchangeRequestItemReturnValidationStep/index.html.md) +- [fetchShippingOptionForOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/fetchShippingOptionForOrderWorkflow/index.html.md) +- [getOrderDetailWorkflow](https://docs.medusajs.com/references/medusa-workflows/getOrderDetailWorkflow/index.html.md) +- [getOrdersListWorkflow](https://docs.medusajs.com/references/medusa-workflows/getOrdersListWorkflow/index.html.md) +- [listShippingOptionsForOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/listShippingOptionsForOrderWorkflow/index.html.md) +- [markOrderFulfillmentAsDeliveredWorkflow](https://docs.medusajs.com/references/medusa-workflows/markOrderFulfillmentAsDeliveredWorkflow/index.html.md) +- [markPaymentCollectionAsPaid](https://docs.medusajs.com/references/medusa-workflows/markPaymentCollectionAsPaid/index.html.md) +- [maybeRefreshShippingMethodsWorkflow](https://docs.medusajs.com/references/medusa-workflows/maybeRefreshShippingMethodsWorkflow/index.html.md) +- [orderClaimAddNewItemValidationStep](https://docs.medusajs.com/references/medusa-workflows/orderClaimAddNewItemValidationStep/index.html.md) +- [orderClaimAddNewItemWorkflow](https://docs.medusajs.com/references/medusa-workflows/orderClaimAddNewItemWorkflow/index.html.md) +- [orderClaimItemValidationStep](https://docs.medusajs.com/references/medusa-workflows/orderClaimItemValidationStep/index.html.md) +- [orderClaimItemWorkflow](https://docs.medusajs.com/references/medusa-workflows/orderClaimItemWorkflow/index.html.md) +- [orderClaimRequestItemReturnValidationStep](https://docs.medusajs.com/references/medusa-workflows/orderClaimRequestItemReturnValidationStep/index.html.md) +- [orderClaimRequestItemReturnWorkflow](https://docs.medusajs.com/references/medusa-workflows/orderClaimRequestItemReturnWorkflow/index.html.md) +- [orderEditAddNewItemValidationStep](https://docs.medusajs.com/references/medusa-workflows/orderEditAddNewItemValidationStep/index.html.md) +- [orderEditAddNewItemWorkflow](https://docs.medusajs.com/references/medusa-workflows/orderEditAddNewItemWorkflow/index.html.md) +- [orderEditUpdateItemQuantityValidationStep](https://docs.medusajs.com/references/medusa-workflows/orderEditUpdateItemQuantityValidationStep/index.html.md) +- [orderEditUpdateItemQuantityWorkflow](https://docs.medusajs.com/references/medusa-workflows/orderEditUpdateItemQuantityWorkflow/index.html.md) +- [orderExchangeAddNewItemWorkflow](https://docs.medusajs.com/references/medusa-workflows/orderExchangeAddNewItemWorkflow/index.html.md) +- [orderExchangeRequestItemReturnWorkflow](https://docs.medusajs.com/references/medusa-workflows/orderExchangeRequestItemReturnWorkflow/index.html.md) +- [orderFulfillmentDeliverablilityValidationStep](https://docs.medusajs.com/references/medusa-workflows/orderFulfillmentDeliverablilityValidationStep/index.html.md) +- [receiveAndCompleteReturnOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/receiveAndCompleteReturnOrderWorkflow/index.html.md) +- [receiveCompleteReturnValidationStep](https://docs.medusajs.com/references/medusa-workflows/receiveCompleteReturnValidationStep/index.html.md) +- [receiveItemReturnRequestValidationStep](https://docs.medusajs.com/references/medusa-workflows/receiveItemReturnRequestValidationStep/index.html.md) +- [receiveItemReturnRequestWorkflow](https://docs.medusajs.com/references/medusa-workflows/receiveItemReturnRequestWorkflow/index.html.md) +- [removeAddItemClaimActionWorkflow](https://docs.medusajs.com/references/medusa-workflows/removeAddItemClaimActionWorkflow/index.html.md) +- [removeClaimAddItemActionValidationStep](https://docs.medusajs.com/references/medusa-workflows/removeClaimAddItemActionValidationStep/index.html.md) +- [removeClaimItemActionValidationStep](https://docs.medusajs.com/references/medusa-workflows/removeClaimItemActionValidationStep/index.html.md) +- [removeClaimShippingMethodValidationStep](https://docs.medusajs.com/references/medusa-workflows/removeClaimShippingMethodValidationStep/index.html.md) +- [removeClaimShippingMethodWorkflow](https://docs.medusajs.com/references/medusa-workflows/removeClaimShippingMethodWorkflow/index.html.md) +- [removeExchangeItemActionValidationStep](https://docs.medusajs.com/references/medusa-workflows/removeExchangeItemActionValidationStep/index.html.md) +- [removeExchangeShippingMethodValidationStep](https://docs.medusajs.com/references/medusa-workflows/removeExchangeShippingMethodValidationStep/index.html.md) +- [removeExchangeShippingMethodWorkflow](https://docs.medusajs.com/references/medusa-workflows/removeExchangeShippingMethodWorkflow/index.html.md) +- [removeItemClaimActionWorkflow](https://docs.medusajs.com/references/medusa-workflows/removeItemClaimActionWorkflow/index.html.md) +- [removeItemExchangeActionWorkflow](https://docs.medusajs.com/references/medusa-workflows/removeItemExchangeActionWorkflow/index.html.md) +- [removeItemOrderEditActionWorkflow](https://docs.medusajs.com/references/medusa-workflows/removeItemOrderEditActionWorkflow/index.html.md) +- [removeItemReceiveReturnActionValidationStep](https://docs.medusajs.com/references/medusa-workflows/removeItemReceiveReturnActionValidationStep/index.html.md) +- [removeItemReceiveReturnActionWorkflow](https://docs.medusajs.com/references/medusa-workflows/removeItemReceiveReturnActionWorkflow/index.html.md) +- [removeItemReturnActionWorkflow](https://docs.medusajs.com/references/medusa-workflows/removeItemReturnActionWorkflow/index.html.md) +- [removeOrderEditItemActionValidationStep](https://docs.medusajs.com/references/medusa-workflows/removeOrderEditItemActionValidationStep/index.html.md) +- [removeOrderEditShippingMethodValidationStep](https://docs.medusajs.com/references/medusa-workflows/removeOrderEditShippingMethodValidationStep/index.html.md) +- [removeOrderEditShippingMethodWorkflow](https://docs.medusajs.com/references/medusa-workflows/removeOrderEditShippingMethodWorkflow/index.html.md) +- [removeReturnItemActionValidationStep](https://docs.medusajs.com/references/medusa-workflows/removeReturnItemActionValidationStep/index.html.md) +- [removeReturnShippingMethodValidationStep](https://docs.medusajs.com/references/medusa-workflows/removeReturnShippingMethodValidationStep/index.html.md) +- [removeReturnShippingMethodWorkflow](https://docs.medusajs.com/references/medusa-workflows/removeReturnShippingMethodWorkflow/index.html.md) +- [requestItemReturnValidationStep](https://docs.medusajs.com/references/medusa-workflows/requestItemReturnValidationStep/index.html.md) +- [requestItemReturnWorkflow](https://docs.medusajs.com/references/medusa-workflows/requestItemReturnWorkflow/index.html.md) +- [requestOrderEditRequestValidationStep](https://docs.medusajs.com/references/medusa-workflows/requestOrderEditRequestValidationStep/index.html.md) +- [requestOrderEditRequestWorkflow](https://docs.medusajs.com/references/medusa-workflows/requestOrderEditRequestWorkflow/index.html.md) +- [requestOrderTransferValidationStep](https://docs.medusajs.com/references/medusa-workflows/requestOrderTransferValidationStep/index.html.md) +- [requestOrderTransferWorkflow](https://docs.medusajs.com/references/medusa-workflows/requestOrderTransferWorkflow/index.html.md) +- [throwUnlessPaymentCollectionNotPaid](https://docs.medusajs.com/references/medusa-workflows/throwUnlessPaymentCollectionNotPaid/index.html.md) +- [throwUnlessStatusIsNotPaid](https://docs.medusajs.com/references/medusa-workflows/throwUnlessStatusIsNotPaid/index.html.md) +- [updateClaimAddItemValidationStep](https://docs.medusajs.com/references/medusa-workflows/updateClaimAddItemValidationStep/index.html.md) +- [updateClaimAddItemWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateClaimAddItemWorkflow/index.html.md) +- [updateClaimItemValidationStep](https://docs.medusajs.com/references/medusa-workflows/updateClaimItemValidationStep/index.html.md) +- [updateClaimItemWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateClaimItemWorkflow/index.html.md) +- [updateClaimShippingMethodValidationStep](https://docs.medusajs.com/references/medusa-workflows/updateClaimShippingMethodValidationStep/index.html.md) +- [updateClaimShippingMethodWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateClaimShippingMethodWorkflow/index.html.md) +- [updateExchangeAddItemValidationStep](https://docs.medusajs.com/references/medusa-workflows/updateExchangeAddItemValidationStep/index.html.md) +- [updateExchangeAddItemWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateExchangeAddItemWorkflow/index.html.md) +- [updateExchangeShippingMethodValidationStep](https://docs.medusajs.com/references/medusa-workflows/updateExchangeShippingMethodValidationStep/index.html.md) +- [updateExchangeShippingMethodWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateExchangeShippingMethodWorkflow/index.html.md) +- [updateOrderChangeActionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateOrderChangeActionsWorkflow/index.html.md) +- [updateOrderChangesWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateOrderChangesWorkflow/index.html.md) +- [updateOrderEditAddItemValidationStep](https://docs.medusajs.com/references/medusa-workflows/updateOrderEditAddItemValidationStep/index.html.md) +- [updateOrderEditAddItemWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateOrderEditAddItemWorkflow/index.html.md) +- [updateOrderEditItemQuantityValidationStep](https://docs.medusajs.com/references/medusa-workflows/updateOrderEditItemQuantityValidationStep/index.html.md) +- [updateOrderEditItemQuantityWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateOrderEditItemQuantityWorkflow/index.html.md) +- [updateOrderEditShippingMethodValidationStep](https://docs.medusajs.com/references/medusa-workflows/updateOrderEditShippingMethodValidationStep/index.html.md) +- [updateOrderEditShippingMethodWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateOrderEditShippingMethodWorkflow/index.html.md) +- [updateOrderTaxLinesWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateOrderTaxLinesWorkflow/index.html.md) +- [updateOrderValidationStep](https://docs.medusajs.com/references/medusa-workflows/updateOrderValidationStep/index.html.md) +- [updateOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateOrderWorkflow/index.html.md) +- [updateReceiveItemReturnRequestValidationStep](https://docs.medusajs.com/references/medusa-workflows/updateReceiveItemReturnRequestValidationStep/index.html.md) +- [updateReceiveItemReturnRequestWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateReceiveItemReturnRequestWorkflow/index.html.md) +- [updateRequestItemReturnValidationStep](https://docs.medusajs.com/references/medusa-workflows/updateRequestItemReturnValidationStep/index.html.md) +- [updateRequestItemReturnWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateRequestItemReturnWorkflow/index.html.md) +- [updateReturnShippingMethodValidationStep](https://docs.medusajs.com/references/medusa-workflows/updateReturnShippingMethodValidationStep/index.html.md) +- [updateReturnShippingMethodWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateReturnShippingMethodWorkflow/index.html.md) +- [updateReturnValidationStep](https://docs.medusajs.com/references/medusa-workflows/updateReturnValidationStep/index.html.md) +- [updateReturnWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateReturnWorkflow/index.html.md) +- [validateOrderCreditLinesStep](https://docs.medusajs.com/references/medusa-workflows/validateOrderCreditLinesStep/index.html.md) +- [capturePaymentWorkflow](https://docs.medusajs.com/references/medusa-workflows/capturePaymentWorkflow/index.html.md) +- [processPaymentWorkflow](https://docs.medusajs.com/references/medusa-workflows/processPaymentWorkflow/index.html.md) +- [refundPaymentWorkflow](https://docs.medusajs.com/references/medusa-workflows/refundPaymentWorkflow/index.html.md) +- [refundPaymentsWorkflow](https://docs.medusajs.com/references/medusa-workflows/refundPaymentsWorkflow/index.html.md) +- [validatePaymentsRefundStep](https://docs.medusajs.com/references/medusa-workflows/validatePaymentsRefundStep/index.html.md) +- [validateRefundStep](https://docs.medusajs.com/references/medusa-workflows/validateRefundStep/index.html.md) +- [createPaymentSessionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createPaymentSessionsWorkflow/index.html.md) +- [createRefundReasonsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createRefundReasonsWorkflow/index.html.md) +- [deletePaymentSessionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deletePaymentSessionsWorkflow/index.html.md) +- [deleteRefundReasonsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteRefundReasonsWorkflow/index.html.md) +- [updateRefundReasonsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateRefundReasonsWorkflow/index.html.md) +- [batchPriceListPricesWorkflow](https://docs.medusajs.com/references/medusa-workflows/batchPriceListPricesWorkflow/index.html.md) +- [createPriceListPricesWorkflow](https://docs.medusajs.com/references/medusa-workflows/createPriceListPricesWorkflow/index.html.md) +- [createPriceListsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createPriceListsWorkflow/index.html.md) +- [deletePriceListsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deletePriceListsWorkflow/index.html.md) +- [removePriceListPricesWorkflow](https://docs.medusajs.com/references/medusa-workflows/removePriceListPricesWorkflow/index.html.md) +- [updatePriceListPricesWorkflow](https://docs.medusajs.com/references/medusa-workflows/updatePriceListPricesWorkflow/index.html.md) +- [updatePriceListsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updatePriceListsWorkflow/index.html.md) +- [createPricePreferencesWorkflow](https://docs.medusajs.com/references/medusa-workflows/createPricePreferencesWorkflow/index.html.md) +- [deletePricePreferencesWorkflow](https://docs.medusajs.com/references/medusa-workflows/deletePricePreferencesWorkflow/index.html.md) +- [updatePricePreferencesWorkflow](https://docs.medusajs.com/references/medusa-workflows/updatePricePreferencesWorkflow/index.html.md) +- [batchLinkProductsToCategoryWorkflow](https://docs.medusajs.com/references/medusa-workflows/batchLinkProductsToCategoryWorkflow/index.html.md) +- [batchLinkProductsToCollectionWorkflow](https://docs.medusajs.com/references/medusa-workflows/batchLinkProductsToCollectionWorkflow/index.html.md) +- [batchProductVariantsWorkflow](https://docs.medusajs.com/references/medusa-workflows/batchProductVariantsWorkflow/index.html.md) +- [batchProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/batchProductsWorkflow/index.html.md) +- [createCollectionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createCollectionsWorkflow/index.html.md) +- [createProductOptionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createProductOptionsWorkflow/index.html.md) +- [createProductTagsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createProductTagsWorkflow/index.html.md) +- [createProductTypesWorkflow](https://docs.medusajs.com/references/medusa-workflows/createProductTypesWorkflow/index.html.md) +- [createProductVariantsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createProductVariantsWorkflow/index.html.md) +- [createProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createProductsWorkflow/index.html.md) +- [deleteCollectionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteCollectionsWorkflow/index.html.md) +- [deleteProductOptionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteProductOptionsWorkflow/index.html.md) +- [deleteProductTagsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteProductTagsWorkflow/index.html.md) +- [deleteProductTypesWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteProductTypesWorkflow/index.html.md) +- [deleteProductVariantsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteProductVariantsWorkflow/index.html.md) +- [deleteProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteProductsWorkflow/index.html.md) +- [exportProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/exportProductsWorkflow/index.html.md) +- [importProductsAsChunksWorkflow](https://docs.medusajs.com/references/medusa-workflows/importProductsAsChunksWorkflow/index.html.md) +- [importProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/importProductsWorkflow/index.html.md) +- [updateCollectionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateCollectionsWorkflow/index.html.md) +- [updateProductOptionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateProductOptionsWorkflow/index.html.md) +- [updateProductTagsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateProductTagsWorkflow/index.html.md) +- [updateProductTypesWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateProductTypesWorkflow/index.html.md) +- [updateProductVariantsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateProductVariantsWorkflow/index.html.md) +- [updateProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateProductsWorkflow/index.html.md) +- [upsertVariantPricesWorkflow](https://docs.medusajs.com/references/medusa-workflows/upsertVariantPricesWorkflow/index.html.md) +- [validateProductInputStep](https://docs.medusajs.com/references/medusa-workflows/validateProductInputStep/index.html.md) +- [createProductCategoriesWorkflow](https://docs.medusajs.com/references/medusa-workflows/createProductCategoriesWorkflow/index.html.md) +- [deleteProductCategoriesWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteProductCategoriesWorkflow/index.html.md) +- [updateProductCategoriesWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateProductCategoriesWorkflow/index.html.md) +- [addOrRemoveCampaignPromotionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/addOrRemoveCampaignPromotionsWorkflow/index.html.md) +- [batchPromotionRulesWorkflow](https://docs.medusajs.com/references/medusa-workflows/batchPromotionRulesWorkflow/index.html.md) +- [createCampaignsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createCampaignsWorkflow/index.html.md) +- [createPromotionRulesWorkflow](https://docs.medusajs.com/references/medusa-workflows/createPromotionRulesWorkflow/index.html.md) +- [createPromotionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createPromotionsWorkflow/index.html.md) +- [deleteCampaignsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteCampaignsWorkflow/index.html.md) +- [deletePromotionRulesWorkflow](https://docs.medusajs.com/references/medusa-workflows/deletePromotionRulesWorkflow/index.html.md) +- [deletePromotionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deletePromotionsWorkflow/index.html.md) +- [updateCampaignsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateCampaignsWorkflow/index.html.md) +- [updatePromotionRulesWorkflow](https://docs.medusajs.com/references/medusa-workflows/updatePromotionRulesWorkflow/index.html.md) +- [updatePromotionsStatusWorkflow](https://docs.medusajs.com/references/medusa-workflows/updatePromotionsStatusWorkflow/index.html.md) +- [updatePromotionsValidationStep](https://docs.medusajs.com/references/medusa-workflows/updatePromotionsValidationStep/index.html.md) +- [updatePromotionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updatePromotionsWorkflow/index.html.md) +- [createRegionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createRegionsWorkflow/index.html.md) +- [deleteRegionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteRegionsWorkflow/index.html.md) +- [updateRegionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateRegionsWorkflow/index.html.md) +- [createReservationsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createReservationsWorkflow/index.html.md) +- [deleteReservationsByLineItemsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteReservationsByLineItemsWorkflow/index.html.md) +- [deleteReservationsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteReservationsWorkflow/index.html.md) +- [updateReservationsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateReservationsWorkflow/index.html.md) +- [createReturnReasonsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createReturnReasonsWorkflow/index.html.md) +- [deleteReturnReasonsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteReturnReasonsWorkflow/index.html.md) +- [updateReturnReasonsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateReturnReasonsWorkflow/index.html.md) +- [createSalesChannelsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createSalesChannelsWorkflow/index.html.md) +- [deleteSalesChannelsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteSalesChannelsWorkflow/index.html.md) +- [linkProductsToSalesChannelWorkflow](https://docs.medusajs.com/references/medusa-workflows/linkProductsToSalesChannelWorkflow/index.html.md) +- [updateSalesChannelsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateSalesChannelsWorkflow/index.html.md) +- [createViewConfigurationWorkflow](https://docs.medusajs.com/references/medusa-workflows/createViewConfigurationWorkflow/index.html.md) +- [updateViewConfigurationWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateViewConfigurationWorkflow/index.html.md) +- [createShippingOptionTypesWorkflow](https://docs.medusajs.com/references/medusa-workflows/createShippingOptionTypesWorkflow/index.html.md) +- [deleteShippingOptionTypesWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteShippingOptionTypesWorkflow/index.html.md) +- [updateShippingOptionTypesWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateShippingOptionTypesWorkflow/index.html.md) +- [deleteShippingProfileWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteShippingProfileWorkflow/index.html.md) +- [validateStepShippingProfileDelete](https://docs.medusajs.com/references/medusa-workflows/validateStepShippingProfileDelete/index.html.md) +- [createLocationFulfillmentSetWorkflow](https://docs.medusajs.com/references/medusa-workflows/createLocationFulfillmentSetWorkflow/index.html.md) +- [createStockLocationsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createStockLocationsWorkflow/index.html.md) +- [deleteStockLocationsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteStockLocationsWorkflow/index.html.md) +- [linkSalesChannelsToStockLocationWorkflow](https://docs.medusajs.com/references/medusa-workflows/linkSalesChannelsToStockLocationWorkflow/index.html.md) +- [updateStockLocationsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateStockLocationsWorkflow/index.html.md) +- [createStoresWorkflow](https://docs.medusajs.com/references/medusa-workflows/createStoresWorkflow/index.html.md) +- [deleteStoresWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteStoresWorkflow/index.html.md) +- [updateStoresWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateStoresWorkflow/index.html.md) +- [createTaxRateRulesWorkflow](https://docs.medusajs.com/references/medusa-workflows/createTaxRateRulesWorkflow/index.html.md) +- [createTaxRatesWorkflow](https://docs.medusajs.com/references/medusa-workflows/createTaxRatesWorkflow/index.html.md) +- [createTaxRegionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createTaxRegionsWorkflow/index.html.md) +- [deleteTaxRateRulesWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteTaxRateRulesWorkflow/index.html.md) +- [deleteTaxRatesWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteTaxRatesWorkflow/index.html.md) +- [deleteTaxRegionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteTaxRegionsWorkflow/index.html.md) +- [maybeListTaxRateRuleIdsStep](https://docs.medusajs.com/references/medusa-workflows/maybeListTaxRateRuleIdsStep/index.html.md) +- [setTaxRateRulesWorkflow](https://docs.medusajs.com/references/medusa-workflows/setTaxRateRulesWorkflow/index.html.md) +- [updateTaxRatesWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateTaxRatesWorkflow/index.html.md) +- [updateTaxRegionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateTaxRegionsWorkflow/index.html.md) +- [createUserAccountWorkflow](https://docs.medusajs.com/references/medusa-workflows/createUserAccountWorkflow/index.html.md) +- [createUsersWorkflow](https://docs.medusajs.com/references/medusa-workflows/createUsersWorkflow/index.html.md) +- [deleteUsersWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteUsersWorkflow/index.html.md) +- [removeUserAccountWorkflow](https://docs.medusajs.com/references/medusa-workflows/removeUserAccountWorkflow/index.html.md) +- [updateUsersWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateUsersWorkflow/index.html.md) ## Steps -- [createApiKeysStep](undefined/references/medusa-workflows/steps/createApiKeysStep/index.html.md) -- [deleteApiKeysStep](undefined/references/medusa-workflows/steps/deleteApiKeysStep/index.html.md) -- [linkSalesChannelsToApiKeyStep](undefined/references/medusa-workflows/steps/linkSalesChannelsToApiKeyStep/index.html.md) -- [revokeApiKeysStep](undefined/references/medusa-workflows/steps/revokeApiKeysStep/index.html.md) -- [updateApiKeysStep](undefined/references/medusa-workflows/steps/updateApiKeysStep/index.html.md) -- [validateSalesChannelsExistStep](undefined/references/medusa-workflows/steps/validateSalesChannelsExistStep/index.html.md) -- [setAuthAppMetadataStep](undefined/references/medusa-workflows/steps/setAuthAppMetadataStep/index.html.md) -- [addShippingMethodToCartStep](undefined/references/medusa-workflows/steps/addShippingMethodToCartStep/index.html.md) -- [confirmInventoryStep](undefined/references/medusa-workflows/steps/confirmInventoryStep/index.html.md) -- [createCartsStep](undefined/references/medusa-workflows/steps/createCartsStep/index.html.md) -- [createLineItemAdjustmentsStep](undefined/references/medusa-workflows/steps/createLineItemAdjustmentsStep/index.html.md) -- [createLineItemsStep](undefined/references/medusa-workflows/steps/createLineItemsStep/index.html.md) -- [createPaymentCollectionsStep](undefined/references/medusa-workflows/steps/createPaymentCollectionsStep/index.html.md) -- [createShippingMethodAdjustmentsStep](undefined/references/medusa-workflows/steps/createShippingMethodAdjustmentsStep/index.html.md) -- [findOneOrAnyRegionStep](undefined/references/medusa-workflows/steps/findOneOrAnyRegionStep/index.html.md) -- [findOrCreateCustomerStep](undefined/references/medusa-workflows/steps/findOrCreateCustomerStep/index.html.md) -- [findSalesChannelStep](undefined/references/medusa-workflows/steps/findSalesChannelStep/index.html.md) -- [getActionsToComputeFromPromotionsStep](undefined/references/medusa-workflows/steps/getActionsToComputeFromPromotionsStep/index.html.md) -- [getLineItemActionsStep](undefined/references/medusa-workflows/steps/getLineItemActionsStep/index.html.md) -- [getPromotionCodesToApply](undefined/references/medusa-workflows/steps/getPromotionCodesToApply/index.html.md) -- [getVariantPriceSetsStep](undefined/references/medusa-workflows/steps/getVariantPriceSetsStep/index.html.md) -- [getVariantsStep](undefined/references/medusa-workflows/steps/getVariantsStep/index.html.md) -- [prepareAdjustmentsFromPromotionActionsStep](undefined/references/medusa-workflows/steps/prepareAdjustmentsFromPromotionActionsStep/index.html.md) -- [removeLineItemAdjustmentsStep](undefined/references/medusa-workflows/steps/removeLineItemAdjustmentsStep/index.html.md) -- [removeShippingMethodAdjustmentsStep](undefined/references/medusa-workflows/steps/removeShippingMethodAdjustmentsStep/index.html.md) -- [removeShippingMethodFromCartStep](undefined/references/medusa-workflows/steps/removeShippingMethodFromCartStep/index.html.md) -- [reserveInventoryStep](undefined/references/medusa-workflows/steps/reserveInventoryStep/index.html.md) -- [retrieveCartStep](undefined/references/medusa-workflows/steps/retrieveCartStep/index.html.md) -- [setTaxLinesForItemsStep](undefined/references/medusa-workflows/steps/setTaxLinesForItemsStep/index.html.md) -- [updateCartPromotionsStep](undefined/references/medusa-workflows/steps/updateCartPromotionsStep/index.html.md) -- [updateCartsStep](undefined/references/medusa-workflows/steps/updateCartsStep/index.html.md) -- [updateLineItemsStep](undefined/references/medusa-workflows/steps/updateLineItemsStep/index.html.md) -- [updateShippingMethodsStep](undefined/references/medusa-workflows/steps/updateShippingMethodsStep/index.html.md) -- [validateAndReturnShippingMethodsDataStep](undefined/references/medusa-workflows/steps/validateAndReturnShippingMethodsDataStep/index.html.md) -- [validateCartPaymentsStep](undefined/references/medusa-workflows/steps/validateCartPaymentsStep/index.html.md) -- [validateCartShippingOptionsPriceStep](undefined/references/medusa-workflows/steps/validateCartShippingOptionsPriceStep/index.html.md) -- [validateCartShippingOptionsStep](undefined/references/medusa-workflows/steps/validateCartShippingOptionsStep/index.html.md) -- [validateCartStep](undefined/references/medusa-workflows/steps/validateCartStep/index.html.md) -- [validateLineItemPricesStep](undefined/references/medusa-workflows/steps/validateLineItemPricesStep/index.html.md) -- [validateShippingStep](undefined/references/medusa-workflows/steps/validateShippingStep/index.html.md) -- [validateVariantPricesStep](undefined/references/medusa-workflows/steps/validateVariantPricesStep/index.html.md) -- [createEntitiesStep](undefined/references/medusa-workflows/steps/createEntitiesStep/index.html.md) -- [createRemoteLinkStep](undefined/references/medusa-workflows/steps/createRemoteLinkStep/index.html.md) -- [deleteEntitiesStep](undefined/references/medusa-workflows/steps/deleteEntitiesStep/index.html.md) -- [dismissRemoteLinkStep](undefined/references/medusa-workflows/steps/dismissRemoteLinkStep/index.html.md) -- [emitEventStep](undefined/references/medusa-workflows/steps/emitEventStep/index.html.md) -- [removeRemoteLinkStep](undefined/references/medusa-workflows/steps/removeRemoteLinkStep/index.html.md) -- [updateRemoteLinksStep](undefined/references/medusa-workflows/steps/updateRemoteLinksStep/index.html.md) -- [useQueryGraphStep](undefined/references/medusa-workflows/steps/useQueryGraphStep/index.html.md) -- [useRemoteQueryStep](undefined/references/medusa-workflows/steps/useRemoteQueryStep/index.html.md) -- [validatePresenceOfStep](undefined/references/medusa-workflows/steps/validatePresenceOfStep/index.html.md) -- [createCustomerAddressesStep](undefined/references/medusa-workflows/steps/createCustomerAddressesStep/index.html.md) -- [createCustomersStep](undefined/references/medusa-workflows/steps/createCustomersStep/index.html.md) -- [deleteCustomerAddressesStep](undefined/references/medusa-workflows/steps/deleteCustomerAddressesStep/index.html.md) -- [deleteCustomersStep](undefined/references/medusa-workflows/steps/deleteCustomersStep/index.html.md) -- [maybeUnsetDefaultBillingAddressesStep](undefined/references/medusa-workflows/steps/maybeUnsetDefaultBillingAddressesStep/index.html.md) -- [maybeUnsetDefaultShippingAddressesStep](undefined/references/medusa-workflows/steps/maybeUnsetDefaultShippingAddressesStep/index.html.md) -- [updateCustomerAddressesStep](undefined/references/medusa-workflows/steps/updateCustomerAddressesStep/index.html.md) -- [updateCustomersStep](undefined/references/medusa-workflows/steps/updateCustomersStep/index.html.md) -- [validateCustomerAccountCreation](undefined/references/medusa-workflows/steps/validateCustomerAccountCreation/index.html.md) -- [createCustomerGroupsStep](undefined/references/medusa-workflows/steps/createCustomerGroupsStep/index.html.md) -- [deleteCustomerGroupStep](undefined/references/medusa-workflows/steps/deleteCustomerGroupStep/index.html.md) -- [linkCustomerGroupsToCustomerStep](undefined/references/medusa-workflows/steps/linkCustomerGroupsToCustomerStep/index.html.md) -- [linkCustomersToCustomerGroupStep](undefined/references/medusa-workflows/steps/linkCustomersToCustomerGroupStep/index.html.md) -- [updateCustomerGroupsStep](undefined/references/medusa-workflows/steps/updateCustomerGroupsStep/index.html.md) -- [createDefaultStoreStep](undefined/references/medusa-workflows/steps/createDefaultStoreStep/index.html.md) -- [deleteDraftOrdersStep](undefined/references/medusa-workflows/steps/deleteDraftOrdersStep/index.html.md) -- [validateDraftOrderStep](undefined/references/medusa-workflows/steps/validateDraftOrderStep/index.html.md) -- [deleteFilesStep](undefined/references/medusa-workflows/steps/deleteFilesStep/index.html.md) -- [uploadFilesStep](undefined/references/medusa-workflows/steps/uploadFilesStep/index.html.md) -- [buildPriceSet](undefined/references/medusa-workflows/steps/buildPriceSet/index.html.md) -- [calculateShippingOptionsPricesStep](undefined/references/medusa-workflows/steps/calculateShippingOptionsPricesStep/index.html.md) -- [cancelFulfillmentStep](undefined/references/medusa-workflows/steps/cancelFulfillmentStep/index.html.md) -- [createFulfillmentSets](undefined/references/medusa-workflows/steps/createFulfillmentSets/index.html.md) -- [createFulfillmentStep](undefined/references/medusa-workflows/steps/createFulfillmentStep/index.html.md) -- [createReturnFulfillmentStep](undefined/references/medusa-workflows/steps/createReturnFulfillmentStep/index.html.md) -- [createServiceZonesStep](undefined/references/medusa-workflows/steps/createServiceZonesStep/index.html.md) -- [createShippingOptionRulesStep](undefined/references/medusa-workflows/steps/createShippingOptionRulesStep/index.html.md) -- [createShippingOptionsPriceSetsStep](undefined/references/medusa-workflows/steps/createShippingOptionsPriceSetsStep/index.html.md) -- [createShippingProfilesStep](undefined/references/medusa-workflows/steps/createShippingProfilesStep/index.html.md) -- [deleteFulfillmentSetsStep](undefined/references/medusa-workflows/steps/deleteFulfillmentSetsStep/index.html.md) -- [deleteServiceZonesStep](undefined/references/medusa-workflows/steps/deleteServiceZonesStep/index.html.md) -- [deleteShippingOptionRulesStep](undefined/references/medusa-workflows/steps/deleteShippingOptionRulesStep/index.html.md) -- [deleteShippingOptionsStep](undefined/references/medusa-workflows/steps/deleteShippingOptionsStep/index.html.md) -- [setShippingOptionsPricesStep](undefined/references/medusa-workflows/steps/setShippingOptionsPricesStep/index.html.md) -- [updateFulfillmentStep](undefined/references/medusa-workflows/steps/updateFulfillmentStep/index.html.md) -- [updateServiceZonesStep](undefined/references/medusa-workflows/steps/updateServiceZonesStep/index.html.md) -- [updateShippingOptionRulesStep](undefined/references/medusa-workflows/steps/updateShippingOptionRulesStep/index.html.md) -- [updateShippingProfilesStep](undefined/references/medusa-workflows/steps/updateShippingProfilesStep/index.html.md) -- [upsertShippingOptionsStep](undefined/references/medusa-workflows/steps/upsertShippingOptionsStep/index.html.md) -- [validateShipmentStep](undefined/references/medusa-workflows/steps/validateShipmentStep/index.html.md) -- [validateShippingOptionPricesStep](undefined/references/medusa-workflows/steps/validateShippingOptionPricesStep/index.html.md) -- [adjustInventoryLevelsStep](undefined/references/medusa-workflows/steps/adjustInventoryLevelsStep/index.html.md) -- [attachInventoryItemToVariants](undefined/references/medusa-workflows/steps/attachInventoryItemToVariants/index.html.md) -- [createInventoryItemsStep](undefined/references/medusa-workflows/steps/createInventoryItemsStep/index.html.md) -- [createInventoryLevelsStep](undefined/references/medusa-workflows/steps/createInventoryLevelsStep/index.html.md) -- [deleteInventoryItemStep](undefined/references/medusa-workflows/steps/deleteInventoryItemStep/index.html.md) -- [deleteInventoryLevelsStep](undefined/references/medusa-workflows/steps/deleteInventoryLevelsStep/index.html.md) -- [updateInventoryItemsStep](undefined/references/medusa-workflows/steps/updateInventoryItemsStep/index.html.md) -- [updateInventoryLevelsStep](undefined/references/medusa-workflows/steps/updateInventoryLevelsStep/index.html.md) -- [validateInventoryDeleteStep](undefined/references/medusa-workflows/steps/validateInventoryDeleteStep/index.html.md) -- [validateInventoryItemsForCreate](undefined/references/medusa-workflows/steps/validateInventoryItemsForCreate/index.html.md) -- [validateInventoryLocationsStep](undefined/references/medusa-workflows/steps/validateInventoryLocationsStep/index.html.md) -- [createInviteStep](undefined/references/medusa-workflows/steps/createInviteStep/index.html.md) -- [deleteInvitesStep](undefined/references/medusa-workflows/steps/deleteInvitesStep/index.html.md) -- [refreshInviteTokensStep](undefined/references/medusa-workflows/steps/refreshInviteTokensStep/index.html.md) -- [validateTokenStep](undefined/references/medusa-workflows/steps/validateTokenStep/index.html.md) -- [deleteLineItemsStep](undefined/references/medusa-workflows/steps/deleteLineItemsStep/index.html.md) -- [listLineItemsStep](undefined/references/medusa-workflows/steps/listLineItemsStep/index.html.md) -- [updateLineItemsStepWithSelector](undefined/references/medusa-workflows/steps/updateLineItemsStepWithSelector/index.html.md) -- [acquireLockStep](undefined/references/medusa-workflows/steps/acquireLockStep/index.html.md) -- [releaseLockStep](undefined/references/medusa-workflows/steps/releaseLockStep/index.html.md) -- [notifyOnFailureStep](undefined/references/medusa-workflows/steps/notifyOnFailureStep/index.html.md) -- [sendNotificationsStep](undefined/references/medusa-workflows/steps/sendNotificationsStep/index.html.md) -- [addOrderTransactionStep](undefined/references/medusa-workflows/steps/addOrderTransactionStep/index.html.md) -- [archiveOrdersStep](undefined/references/medusa-workflows/steps/archiveOrdersStep/index.html.md) -- [cancelOrderChangeStep](undefined/references/medusa-workflows/steps/cancelOrderChangeStep/index.html.md) -- [cancelOrderClaimStep](undefined/references/medusa-workflows/steps/cancelOrderClaimStep/index.html.md) -- [cancelOrderExchangeStep](undefined/references/medusa-workflows/steps/cancelOrderExchangeStep/index.html.md) -- [cancelOrderFulfillmentStep](undefined/references/medusa-workflows/steps/cancelOrderFulfillmentStep/index.html.md) -- [cancelOrderReturnStep](undefined/references/medusa-workflows/steps/cancelOrderReturnStep/index.html.md) -- [cancelOrdersStep](undefined/references/medusa-workflows/steps/cancelOrdersStep/index.html.md) -- [completeOrdersStep](undefined/references/medusa-workflows/steps/completeOrdersStep/index.html.md) -- [createCompleteReturnStep](undefined/references/medusa-workflows/steps/createCompleteReturnStep/index.html.md) -- [createOrderChangeStep](undefined/references/medusa-workflows/steps/createOrderChangeStep/index.html.md) -- [createOrderClaimItemsFromActionsStep](undefined/references/medusa-workflows/steps/createOrderClaimItemsFromActionsStep/index.html.md) -- [createOrderClaimsStep](undefined/references/medusa-workflows/steps/createOrderClaimsStep/index.html.md) -- [createOrderExchangeItemsFromActionsStep](undefined/references/medusa-workflows/steps/createOrderExchangeItemsFromActionsStep/index.html.md) -- [createOrderExchangesStep](undefined/references/medusa-workflows/steps/createOrderExchangesStep/index.html.md) -- [createOrderLineItemsStep](undefined/references/medusa-workflows/steps/createOrderLineItemsStep/index.html.md) -- [createOrdersStep](undefined/references/medusa-workflows/steps/createOrdersStep/index.html.md) -- [createReturnsStep](undefined/references/medusa-workflows/steps/createReturnsStep/index.html.md) -- [declineOrderChangeStep](undefined/references/medusa-workflows/steps/declineOrderChangeStep/index.html.md) -- [deleteClaimsStep](undefined/references/medusa-workflows/steps/deleteClaimsStep/index.html.md) -- [deleteExchangesStep](undefined/references/medusa-workflows/steps/deleteExchangesStep/index.html.md) -- [deleteOrderChangeActionsStep](undefined/references/medusa-workflows/steps/deleteOrderChangeActionsStep/index.html.md) -- [deleteOrderChangesStep](undefined/references/medusa-workflows/steps/deleteOrderChangesStep/index.html.md) -- [deleteOrderLineItems](undefined/references/medusa-workflows/steps/deleteOrderLineItems/index.html.md) -- [deleteOrderShippingMethods](undefined/references/medusa-workflows/steps/deleteOrderShippingMethods/index.html.md) -- [deleteReturnsStep](undefined/references/medusa-workflows/steps/deleteReturnsStep/index.html.md) -- [previewOrderChangeStep](undefined/references/medusa-workflows/steps/previewOrderChangeStep/index.html.md) -- [registerOrderChangesStep](undefined/references/medusa-workflows/steps/registerOrderChangesStep/index.html.md) -- [registerOrderDeliveryStep](undefined/references/medusa-workflows/steps/registerOrderDeliveryStep/index.html.md) -- [registerOrderFulfillmentStep](undefined/references/medusa-workflows/steps/registerOrderFulfillmentStep/index.html.md) -- [registerOrderShipmentStep](undefined/references/medusa-workflows/steps/registerOrderShipmentStep/index.html.md) -- [setOrderTaxLinesForItemsStep](undefined/references/medusa-workflows/steps/setOrderTaxLinesForItemsStep/index.html.md) -- [updateOrderChangeActionsStep](undefined/references/medusa-workflows/steps/updateOrderChangeActionsStep/index.html.md) -- [updateOrderChangesStep](undefined/references/medusa-workflows/steps/updateOrderChangesStep/index.html.md) -- [updateOrderShippingMethodsStep](undefined/references/medusa-workflows/steps/updateOrderShippingMethodsStep/index.html.md) -- [updateOrdersStep](undefined/references/medusa-workflows/steps/updateOrdersStep/index.html.md) -- [updateReturnItemsStep](undefined/references/medusa-workflows/steps/updateReturnItemsStep/index.html.md) -- [updateReturnsStep](undefined/references/medusa-workflows/steps/updateReturnsStep/index.html.md) -- [authorizePaymentSessionStep](undefined/references/medusa-workflows/steps/authorizePaymentSessionStep/index.html.md) -- [cancelPaymentStep](undefined/references/medusa-workflows/steps/cancelPaymentStep/index.html.md) -- [capturePaymentStep](undefined/references/medusa-workflows/steps/capturePaymentStep/index.html.md) -- [refundPaymentStep](undefined/references/medusa-workflows/steps/refundPaymentStep/index.html.md) -- [refundPaymentsStep](undefined/references/medusa-workflows/steps/refundPaymentsStep/index.html.md) -- [createPaymentAccountHolderStep](undefined/references/medusa-workflows/steps/createPaymentAccountHolderStep/index.html.md) -- [createPaymentSessionStep](undefined/references/medusa-workflows/steps/createPaymentSessionStep/index.html.md) -- [createRefundReasonStep](undefined/references/medusa-workflows/steps/createRefundReasonStep/index.html.md) -- [deletePaymentSessionsStep](undefined/references/medusa-workflows/steps/deletePaymentSessionsStep/index.html.md) -- [deleteRefundReasonsStep](undefined/references/medusa-workflows/steps/deleteRefundReasonsStep/index.html.md) -- [updatePaymentCollectionStep](undefined/references/medusa-workflows/steps/updatePaymentCollectionStep/index.html.md) -- [updateRefundReasonsStep](undefined/references/medusa-workflows/steps/updateRefundReasonsStep/index.html.md) -- [validateDeletedPaymentSessionsStep](undefined/references/medusa-workflows/steps/validateDeletedPaymentSessionsStep/index.html.md) -- [createPriceListPricesStep](undefined/references/medusa-workflows/steps/createPriceListPricesStep/index.html.md) -- [createPriceListsStep](undefined/references/medusa-workflows/steps/createPriceListsStep/index.html.md) -- [deletePriceListsStep](undefined/references/medusa-workflows/steps/deletePriceListsStep/index.html.md) -- [getExistingPriceListsPriceIdsStep](undefined/references/medusa-workflows/steps/getExistingPriceListsPriceIdsStep/index.html.md) -- [removePriceListPricesStep](undefined/references/medusa-workflows/steps/removePriceListPricesStep/index.html.md) -- [updatePriceListPricesStep](undefined/references/medusa-workflows/steps/updatePriceListPricesStep/index.html.md) -- [updatePriceListsStep](undefined/references/medusa-workflows/steps/updatePriceListsStep/index.html.md) -- [validatePriceListsStep](undefined/references/medusa-workflows/steps/validatePriceListsStep/index.html.md) -- [validateVariantPriceLinksStep](undefined/references/medusa-workflows/steps/validateVariantPriceLinksStep/index.html.md) -- [createPricePreferencesStep](undefined/references/medusa-workflows/steps/createPricePreferencesStep/index.html.md) -- [createPriceSetsStep](undefined/references/medusa-workflows/steps/createPriceSetsStep/index.html.md) -- [deletePricePreferencesStep](undefined/references/medusa-workflows/steps/deletePricePreferencesStep/index.html.md) -- [updatePricePreferencesAsArrayStep](undefined/references/medusa-workflows/steps/updatePricePreferencesAsArrayStep/index.html.md) -- [updatePricePreferencesStep](undefined/references/medusa-workflows/steps/updatePricePreferencesStep/index.html.md) -- [updatePriceSetsStep](undefined/references/medusa-workflows/steps/updatePriceSetsStep/index.html.md) -- [batchLinkProductsToCategoryStep](undefined/references/medusa-workflows/steps/batchLinkProductsToCategoryStep/index.html.md) -- [batchLinkProductsToCollectionStep](undefined/references/medusa-workflows/steps/batchLinkProductsToCollectionStep/index.html.md) -- [createCollectionsStep](undefined/references/medusa-workflows/steps/createCollectionsStep/index.html.md) -- [createProductOptionsStep](undefined/references/medusa-workflows/steps/createProductOptionsStep/index.html.md) -- [createProductTagsStep](undefined/references/medusa-workflows/steps/createProductTagsStep/index.html.md) -- [createProductTypesStep](undefined/references/medusa-workflows/steps/createProductTypesStep/index.html.md) -- [createProductVariantsStep](undefined/references/medusa-workflows/steps/createProductVariantsStep/index.html.md) -- [createProductsStep](undefined/references/medusa-workflows/steps/createProductsStep/index.html.md) -- [createVariantPricingLinkStep](undefined/references/medusa-workflows/steps/createVariantPricingLinkStep/index.html.md) -- [deleteCollectionsStep](undefined/references/medusa-workflows/steps/deleteCollectionsStep/index.html.md) -- [deleteProductOptionsStep](undefined/references/medusa-workflows/steps/deleteProductOptionsStep/index.html.md) -- [deleteProductTagsStep](undefined/references/medusa-workflows/steps/deleteProductTagsStep/index.html.md) -- [deleteProductTypesStep](undefined/references/medusa-workflows/steps/deleteProductTypesStep/index.html.md) -- [deleteProductVariantsStep](undefined/references/medusa-workflows/steps/deleteProductVariantsStep/index.html.md) -- [deleteProductsStep](undefined/references/medusa-workflows/steps/deleteProductsStep/index.html.md) -- [generateProductCsvStep](undefined/references/medusa-workflows/steps/generateProductCsvStep/index.html.md) -- [getAllProductsStep](undefined/references/medusa-workflows/steps/getAllProductsStep/index.html.md) -- [getProductsStep](undefined/references/medusa-workflows/steps/getProductsStep/index.html.md) -- [getVariantAvailabilityStep](undefined/references/medusa-workflows/steps/getVariantAvailabilityStep/index.html.md) -- [normalizeCsvStep](undefined/references/medusa-workflows/steps/normalizeCsvStep/index.html.md) -- [normalizeCsvToChunksStep](undefined/references/medusa-workflows/steps/normalizeCsvToChunksStep/index.html.md) -- [parseProductCsvStep](undefined/references/medusa-workflows/steps/parseProductCsvStep/index.html.md) -- [processImportChunksStep](undefined/references/medusa-workflows/steps/processImportChunksStep/index.html.md) -- [updateCollectionsStep](undefined/references/medusa-workflows/steps/updateCollectionsStep/index.html.md) -- [updateProductOptionsStep](undefined/references/medusa-workflows/steps/updateProductOptionsStep/index.html.md) -- [updateProductTagsStep](undefined/references/medusa-workflows/steps/updateProductTagsStep/index.html.md) -- [updateProductTypesStep](undefined/references/medusa-workflows/steps/updateProductTypesStep/index.html.md) -- [updateProductVariantsStep](undefined/references/medusa-workflows/steps/updateProductVariantsStep/index.html.md) -- [updateProductsStep](undefined/references/medusa-workflows/steps/updateProductsStep/index.html.md) -- [waitConfirmationProductImportStep](undefined/references/medusa-workflows/steps/waitConfirmationProductImportStep/index.html.md) -- [createProductCategoriesStep](undefined/references/medusa-workflows/steps/createProductCategoriesStep/index.html.md) -- [deleteProductCategoriesStep](undefined/references/medusa-workflows/steps/deleteProductCategoriesStep/index.html.md) -- [updateProductCategoriesStep](undefined/references/medusa-workflows/steps/updateProductCategoriesStep/index.html.md) -- [addCampaignPromotionsStep](undefined/references/medusa-workflows/steps/addCampaignPromotionsStep/index.html.md) -- [addRulesToPromotionsStep](undefined/references/medusa-workflows/steps/addRulesToPromotionsStep/index.html.md) -- [createCampaignsStep](undefined/references/medusa-workflows/steps/createCampaignsStep/index.html.md) -- [createPromotionsStep](undefined/references/medusa-workflows/steps/createPromotionsStep/index.html.md) -- [deleteCampaignsStep](undefined/references/medusa-workflows/steps/deleteCampaignsStep/index.html.md) -- [deletePromotionsStep](undefined/references/medusa-workflows/steps/deletePromotionsStep/index.html.md) -- [removeCampaignPromotionsStep](undefined/references/medusa-workflows/steps/removeCampaignPromotionsStep/index.html.md) -- [removeRulesFromPromotionsStep](undefined/references/medusa-workflows/steps/removeRulesFromPromotionsStep/index.html.md) -- [updateCampaignsStep](undefined/references/medusa-workflows/steps/updateCampaignsStep/index.html.md) -- [updatePromotionRulesStep](undefined/references/medusa-workflows/steps/updatePromotionRulesStep/index.html.md) -- [updatePromotionsStep](undefined/references/medusa-workflows/steps/updatePromotionsStep/index.html.md) -- [createRegionsStep](undefined/references/medusa-workflows/steps/createRegionsStep/index.html.md) -- [deleteRegionsStep](undefined/references/medusa-workflows/steps/deleteRegionsStep/index.html.md) -- [setRegionsPaymentProvidersStep](undefined/references/medusa-workflows/steps/setRegionsPaymentProvidersStep/index.html.md) -- [updateRegionsStep](undefined/references/medusa-workflows/steps/updateRegionsStep/index.html.md) -- [createReservationsStep](undefined/references/medusa-workflows/steps/createReservationsStep/index.html.md) -- [deleteReservationsByLineItemsStep](undefined/references/medusa-workflows/steps/deleteReservationsByLineItemsStep/index.html.md) -- [deleteReservationsStep](undefined/references/medusa-workflows/steps/deleteReservationsStep/index.html.md) -- [updateReservationsStep](undefined/references/medusa-workflows/steps/updateReservationsStep/index.html.md) -- [createReturnReasonsStep](undefined/references/medusa-workflows/steps/createReturnReasonsStep/index.html.md) -- [deleteReturnReasonStep](undefined/references/medusa-workflows/steps/deleteReturnReasonStep/index.html.md) -- [updateReturnReasonsStep](undefined/references/medusa-workflows/steps/updateReturnReasonsStep/index.html.md) -- [associateLocationsWithSalesChannelsStep](undefined/references/medusa-workflows/steps/associateLocationsWithSalesChannelsStep/index.html.md) -- [associateProductsWithSalesChannelsStep](undefined/references/medusa-workflows/steps/associateProductsWithSalesChannelsStep/index.html.md) -- [canDeleteSalesChannelsOrThrowStep](undefined/references/medusa-workflows/steps/canDeleteSalesChannelsOrThrowStep/index.html.md) -- [createDefaultSalesChannelStep](undefined/references/medusa-workflows/steps/createDefaultSalesChannelStep/index.html.md) -- [createSalesChannelsStep](undefined/references/medusa-workflows/steps/createSalesChannelsStep/index.html.md) -- [deleteSalesChannelsStep](undefined/references/medusa-workflows/steps/deleteSalesChannelsStep/index.html.md) -- [detachLocationsFromSalesChannelsStep](undefined/references/medusa-workflows/steps/detachLocationsFromSalesChannelsStep/index.html.md) -- [detachProductsFromSalesChannelsStep](undefined/references/medusa-workflows/steps/detachProductsFromSalesChannelsStep/index.html.md) -- [updateSalesChannelsStep](undefined/references/medusa-workflows/steps/updateSalesChannelsStep/index.html.md) -- [createViewConfigurationStep](undefined/references/medusa-workflows/steps/createViewConfigurationStep/index.html.md) -- [setActiveViewConfigurationStep](undefined/references/medusa-workflows/steps/setActiveViewConfigurationStep/index.html.md) -- [updateViewConfigurationStep](undefined/references/medusa-workflows/steps/updateViewConfigurationStep/index.html.md) -- [createShippingOptionTypesStep](undefined/references/medusa-workflows/steps/createShippingOptionTypesStep/index.html.md) -- [deleteShippingOptionTypesStep](undefined/references/medusa-workflows/steps/deleteShippingOptionTypesStep/index.html.md) -- [listShippingOptionsForContextStep](undefined/references/medusa-workflows/steps/listShippingOptionsForContextStep/index.html.md) -- [updateShippingOptionTypesStep](undefined/references/medusa-workflows/steps/updateShippingOptionTypesStep/index.html.md) -- [deleteShippingProfilesStep](undefined/references/medusa-workflows/steps/deleteShippingProfilesStep/index.html.md) -- [createStockLocations](undefined/references/medusa-workflows/steps/createStockLocations/index.html.md) -- [deleteStockLocationsStep](undefined/references/medusa-workflows/steps/deleteStockLocationsStep/index.html.md) -- [updateStockLocationsStep](undefined/references/medusa-workflows/steps/updateStockLocationsStep/index.html.md) -- [createStoresStep](undefined/references/medusa-workflows/steps/createStoresStep/index.html.md) -- [deleteStoresStep](undefined/references/medusa-workflows/steps/deleteStoresStep/index.html.md) -- [updateStoresStep](undefined/references/medusa-workflows/steps/updateStoresStep/index.html.md) -- [createTaxRateRulesStep](undefined/references/medusa-workflows/steps/createTaxRateRulesStep/index.html.md) -- [createTaxRatesStep](undefined/references/medusa-workflows/steps/createTaxRatesStep/index.html.md) -- [createTaxRegionsStep](undefined/references/medusa-workflows/steps/createTaxRegionsStep/index.html.md) -- [deleteTaxRateRulesStep](undefined/references/medusa-workflows/steps/deleteTaxRateRulesStep/index.html.md) -- [deleteTaxRatesStep](undefined/references/medusa-workflows/steps/deleteTaxRatesStep/index.html.md) -- [deleteTaxRegionsStep](undefined/references/medusa-workflows/steps/deleteTaxRegionsStep/index.html.md) -- [getItemTaxLinesStep](undefined/references/medusa-workflows/steps/getItemTaxLinesStep/index.html.md) -- [listTaxRateIdsStep](undefined/references/medusa-workflows/steps/listTaxRateIdsStep/index.html.md) -- [listTaxRateRuleIdsStep](undefined/references/medusa-workflows/steps/listTaxRateRuleIdsStep/index.html.md) -- [updateTaxRatesStep](undefined/references/medusa-workflows/steps/updateTaxRatesStep/index.html.md) -- [updateTaxRegionsStep](undefined/references/medusa-workflows/steps/updateTaxRegionsStep/index.html.md) -- [createUsersStep](undefined/references/medusa-workflows/steps/createUsersStep/index.html.md) -- [deleteUsersStep](undefined/references/medusa-workflows/steps/deleteUsersStep/index.html.md) -- [updateUsersStep](undefined/references/medusa-workflows/steps/updateUsersStep/index.html.md) +- [createApiKeysStep](https://docs.medusajs.com/references/medusa-workflows/steps/createApiKeysStep/index.html.md) +- [deleteApiKeysStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteApiKeysStep/index.html.md) +- [linkSalesChannelsToApiKeyStep](https://docs.medusajs.com/references/medusa-workflows/steps/linkSalesChannelsToApiKeyStep/index.html.md) +- [revokeApiKeysStep](https://docs.medusajs.com/references/medusa-workflows/steps/revokeApiKeysStep/index.html.md) +- [updateApiKeysStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateApiKeysStep/index.html.md) +- [validateSalesChannelsExistStep](https://docs.medusajs.com/references/medusa-workflows/steps/validateSalesChannelsExistStep/index.html.md) +- [setAuthAppMetadataStep](https://docs.medusajs.com/references/medusa-workflows/steps/setAuthAppMetadataStep/index.html.md) +- [addShippingMethodToCartStep](https://docs.medusajs.com/references/medusa-workflows/steps/addShippingMethodToCartStep/index.html.md) +- [confirmInventoryStep](https://docs.medusajs.com/references/medusa-workflows/steps/confirmInventoryStep/index.html.md) +- [createCartsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createCartsStep/index.html.md) +- [createLineItemAdjustmentsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createLineItemAdjustmentsStep/index.html.md) +- [createLineItemsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createLineItemsStep/index.html.md) +- [createPaymentCollectionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createPaymentCollectionsStep/index.html.md) +- [createShippingMethodAdjustmentsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createShippingMethodAdjustmentsStep/index.html.md) +- [findOneOrAnyRegionStep](https://docs.medusajs.com/references/medusa-workflows/steps/findOneOrAnyRegionStep/index.html.md) +- [findOrCreateCustomerStep](https://docs.medusajs.com/references/medusa-workflows/steps/findOrCreateCustomerStep/index.html.md) +- [findSalesChannelStep](https://docs.medusajs.com/references/medusa-workflows/steps/findSalesChannelStep/index.html.md) +- [getActionsToComputeFromPromotionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/getActionsToComputeFromPromotionsStep/index.html.md) +- [getLineItemActionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/getLineItemActionsStep/index.html.md) +- [getPromotionCodesToApply](https://docs.medusajs.com/references/medusa-workflows/steps/getPromotionCodesToApply/index.html.md) +- [getVariantPriceSetsStep](https://docs.medusajs.com/references/medusa-workflows/steps/getVariantPriceSetsStep/index.html.md) +- [getVariantsStep](https://docs.medusajs.com/references/medusa-workflows/steps/getVariantsStep/index.html.md) +- [prepareAdjustmentsFromPromotionActionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/prepareAdjustmentsFromPromotionActionsStep/index.html.md) +- [removeLineItemAdjustmentsStep](https://docs.medusajs.com/references/medusa-workflows/steps/removeLineItemAdjustmentsStep/index.html.md) +- [removeShippingMethodAdjustmentsStep](https://docs.medusajs.com/references/medusa-workflows/steps/removeShippingMethodAdjustmentsStep/index.html.md) +- [removeShippingMethodFromCartStep](https://docs.medusajs.com/references/medusa-workflows/steps/removeShippingMethodFromCartStep/index.html.md) +- [reserveInventoryStep](https://docs.medusajs.com/references/medusa-workflows/steps/reserveInventoryStep/index.html.md) +- [retrieveCartStep](https://docs.medusajs.com/references/medusa-workflows/steps/retrieveCartStep/index.html.md) +- [setTaxLinesForItemsStep](https://docs.medusajs.com/references/medusa-workflows/steps/setTaxLinesForItemsStep/index.html.md) +- [updateCartPromotionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateCartPromotionsStep/index.html.md) +- [updateCartsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateCartsStep/index.html.md) +- [updateLineItemsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateLineItemsStep/index.html.md) +- [updateShippingMethodsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateShippingMethodsStep/index.html.md) +- [validateAndReturnShippingMethodsDataStep](https://docs.medusajs.com/references/medusa-workflows/steps/validateAndReturnShippingMethodsDataStep/index.html.md) +- [validateCartPaymentsStep](https://docs.medusajs.com/references/medusa-workflows/steps/validateCartPaymentsStep/index.html.md) +- [validateCartShippingOptionsPriceStep](https://docs.medusajs.com/references/medusa-workflows/steps/validateCartShippingOptionsPriceStep/index.html.md) +- [validateCartShippingOptionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/validateCartShippingOptionsStep/index.html.md) +- [validateCartStep](https://docs.medusajs.com/references/medusa-workflows/steps/validateCartStep/index.html.md) +- [validateLineItemPricesStep](https://docs.medusajs.com/references/medusa-workflows/steps/validateLineItemPricesStep/index.html.md) +- [validateShippingStep](https://docs.medusajs.com/references/medusa-workflows/steps/validateShippingStep/index.html.md) +- [validateVariantPricesStep](https://docs.medusajs.com/references/medusa-workflows/steps/validateVariantPricesStep/index.html.md) +- [createEntitiesStep](https://docs.medusajs.com/references/medusa-workflows/steps/createEntitiesStep/index.html.md) +- [createRemoteLinkStep](https://docs.medusajs.com/references/medusa-workflows/steps/createRemoteLinkStep/index.html.md) +- [deleteEntitiesStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteEntitiesStep/index.html.md) +- [dismissRemoteLinkStep](https://docs.medusajs.com/references/medusa-workflows/steps/dismissRemoteLinkStep/index.html.md) +- [emitEventStep](https://docs.medusajs.com/references/medusa-workflows/steps/emitEventStep/index.html.md) +- [removeRemoteLinkStep](https://docs.medusajs.com/references/medusa-workflows/steps/removeRemoteLinkStep/index.html.md) +- [updateRemoteLinksStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateRemoteLinksStep/index.html.md) +- [useQueryGraphStep](https://docs.medusajs.com/references/medusa-workflows/steps/useQueryGraphStep/index.html.md) +- [useRemoteQueryStep](https://docs.medusajs.com/references/medusa-workflows/steps/useRemoteQueryStep/index.html.md) +- [validatePresenceOfStep](https://docs.medusajs.com/references/medusa-workflows/steps/validatePresenceOfStep/index.html.md) +- [createCustomerAddressesStep](https://docs.medusajs.com/references/medusa-workflows/steps/createCustomerAddressesStep/index.html.md) +- [createCustomersStep](https://docs.medusajs.com/references/medusa-workflows/steps/createCustomersStep/index.html.md) +- [deleteCustomerAddressesStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteCustomerAddressesStep/index.html.md) +- [deleteCustomersStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteCustomersStep/index.html.md) +- [maybeUnsetDefaultBillingAddressesStep](https://docs.medusajs.com/references/medusa-workflows/steps/maybeUnsetDefaultBillingAddressesStep/index.html.md) +- [maybeUnsetDefaultShippingAddressesStep](https://docs.medusajs.com/references/medusa-workflows/steps/maybeUnsetDefaultShippingAddressesStep/index.html.md) +- [updateCustomerAddressesStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateCustomerAddressesStep/index.html.md) +- [updateCustomersStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateCustomersStep/index.html.md) +- [validateCustomerAccountCreation](https://docs.medusajs.com/references/medusa-workflows/steps/validateCustomerAccountCreation/index.html.md) +- [createCustomerGroupsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createCustomerGroupsStep/index.html.md) +- [deleteCustomerGroupStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteCustomerGroupStep/index.html.md) +- [linkCustomerGroupsToCustomerStep](https://docs.medusajs.com/references/medusa-workflows/steps/linkCustomerGroupsToCustomerStep/index.html.md) +- [linkCustomersToCustomerGroupStep](https://docs.medusajs.com/references/medusa-workflows/steps/linkCustomersToCustomerGroupStep/index.html.md) +- [updateCustomerGroupsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateCustomerGroupsStep/index.html.md) +- [createDefaultStoreStep](https://docs.medusajs.com/references/medusa-workflows/steps/createDefaultStoreStep/index.html.md) +- [deleteDraftOrdersStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteDraftOrdersStep/index.html.md) +- [validateDraftOrderStep](https://docs.medusajs.com/references/medusa-workflows/steps/validateDraftOrderStep/index.html.md) +- [deleteFilesStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteFilesStep/index.html.md) +- [uploadFilesStep](https://docs.medusajs.com/references/medusa-workflows/steps/uploadFilesStep/index.html.md) +- [buildPriceSet](https://docs.medusajs.com/references/medusa-workflows/steps/buildPriceSet/index.html.md) +- [calculateShippingOptionsPricesStep](https://docs.medusajs.com/references/medusa-workflows/steps/calculateShippingOptionsPricesStep/index.html.md) +- [cancelFulfillmentStep](https://docs.medusajs.com/references/medusa-workflows/steps/cancelFulfillmentStep/index.html.md) +- [createFulfillmentSets](https://docs.medusajs.com/references/medusa-workflows/steps/createFulfillmentSets/index.html.md) +- [createFulfillmentStep](https://docs.medusajs.com/references/medusa-workflows/steps/createFulfillmentStep/index.html.md) +- [createReturnFulfillmentStep](https://docs.medusajs.com/references/medusa-workflows/steps/createReturnFulfillmentStep/index.html.md) +- [createServiceZonesStep](https://docs.medusajs.com/references/medusa-workflows/steps/createServiceZonesStep/index.html.md) +- [createShippingOptionRulesStep](https://docs.medusajs.com/references/medusa-workflows/steps/createShippingOptionRulesStep/index.html.md) +- [createShippingOptionsPriceSetsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createShippingOptionsPriceSetsStep/index.html.md) +- [createShippingProfilesStep](https://docs.medusajs.com/references/medusa-workflows/steps/createShippingProfilesStep/index.html.md) +- [deleteFulfillmentSetsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteFulfillmentSetsStep/index.html.md) +- [deleteServiceZonesStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteServiceZonesStep/index.html.md) +- [deleteShippingOptionRulesStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteShippingOptionRulesStep/index.html.md) +- [deleteShippingOptionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteShippingOptionsStep/index.html.md) +- [setShippingOptionsPricesStep](https://docs.medusajs.com/references/medusa-workflows/steps/setShippingOptionsPricesStep/index.html.md) +- [updateFulfillmentStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateFulfillmentStep/index.html.md) +- [updateServiceZonesStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateServiceZonesStep/index.html.md) +- [updateShippingOptionRulesStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateShippingOptionRulesStep/index.html.md) +- [updateShippingProfilesStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateShippingProfilesStep/index.html.md) +- [upsertShippingOptionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/upsertShippingOptionsStep/index.html.md) +- [validateShipmentStep](https://docs.medusajs.com/references/medusa-workflows/steps/validateShipmentStep/index.html.md) +- [validateShippingOptionPricesStep](https://docs.medusajs.com/references/medusa-workflows/steps/validateShippingOptionPricesStep/index.html.md) +- [adjustInventoryLevelsStep](https://docs.medusajs.com/references/medusa-workflows/steps/adjustInventoryLevelsStep/index.html.md) +- [attachInventoryItemToVariants](https://docs.medusajs.com/references/medusa-workflows/steps/attachInventoryItemToVariants/index.html.md) +- [createInventoryItemsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createInventoryItemsStep/index.html.md) +- [createInventoryLevelsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createInventoryLevelsStep/index.html.md) +- [deleteInventoryItemStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteInventoryItemStep/index.html.md) +- [deleteInventoryLevelsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteInventoryLevelsStep/index.html.md) +- [updateInventoryItemsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateInventoryItemsStep/index.html.md) +- [updateInventoryLevelsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateInventoryLevelsStep/index.html.md) +- [validateInventoryDeleteStep](https://docs.medusajs.com/references/medusa-workflows/steps/validateInventoryDeleteStep/index.html.md) +- [validateInventoryItemsForCreate](https://docs.medusajs.com/references/medusa-workflows/steps/validateInventoryItemsForCreate/index.html.md) +- [validateInventoryLocationsStep](https://docs.medusajs.com/references/medusa-workflows/steps/validateInventoryLocationsStep/index.html.md) +- [createInviteStep](https://docs.medusajs.com/references/medusa-workflows/steps/createInviteStep/index.html.md) +- [deleteInvitesStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteInvitesStep/index.html.md) +- [refreshInviteTokensStep](https://docs.medusajs.com/references/medusa-workflows/steps/refreshInviteTokensStep/index.html.md) +- [validateTokenStep](https://docs.medusajs.com/references/medusa-workflows/steps/validateTokenStep/index.html.md) +- [deleteLineItemsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteLineItemsStep/index.html.md) +- [listLineItemsStep](https://docs.medusajs.com/references/medusa-workflows/steps/listLineItemsStep/index.html.md) +- [updateLineItemsStepWithSelector](https://docs.medusajs.com/references/medusa-workflows/steps/updateLineItemsStepWithSelector/index.html.md) +- [acquireLockStep](https://docs.medusajs.com/references/medusa-workflows/steps/acquireLockStep/index.html.md) +- [releaseLockStep](https://docs.medusajs.com/references/medusa-workflows/steps/releaseLockStep/index.html.md) +- [notifyOnFailureStep](https://docs.medusajs.com/references/medusa-workflows/steps/notifyOnFailureStep/index.html.md) +- [sendNotificationsStep](https://docs.medusajs.com/references/medusa-workflows/steps/sendNotificationsStep/index.html.md) +- [addOrderTransactionStep](https://docs.medusajs.com/references/medusa-workflows/steps/addOrderTransactionStep/index.html.md) +- [archiveOrdersStep](https://docs.medusajs.com/references/medusa-workflows/steps/archiveOrdersStep/index.html.md) +- [cancelOrderChangeStep](https://docs.medusajs.com/references/medusa-workflows/steps/cancelOrderChangeStep/index.html.md) +- [cancelOrderClaimStep](https://docs.medusajs.com/references/medusa-workflows/steps/cancelOrderClaimStep/index.html.md) +- [cancelOrderExchangeStep](https://docs.medusajs.com/references/medusa-workflows/steps/cancelOrderExchangeStep/index.html.md) +- [cancelOrderFulfillmentStep](https://docs.medusajs.com/references/medusa-workflows/steps/cancelOrderFulfillmentStep/index.html.md) +- [cancelOrderReturnStep](https://docs.medusajs.com/references/medusa-workflows/steps/cancelOrderReturnStep/index.html.md) +- [cancelOrdersStep](https://docs.medusajs.com/references/medusa-workflows/steps/cancelOrdersStep/index.html.md) +- [completeOrdersStep](https://docs.medusajs.com/references/medusa-workflows/steps/completeOrdersStep/index.html.md) +- [createCompleteReturnStep](https://docs.medusajs.com/references/medusa-workflows/steps/createCompleteReturnStep/index.html.md) +- [createOrderChangeStep](https://docs.medusajs.com/references/medusa-workflows/steps/createOrderChangeStep/index.html.md) +- [createOrderClaimItemsFromActionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createOrderClaimItemsFromActionsStep/index.html.md) +- [createOrderClaimsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createOrderClaimsStep/index.html.md) +- [createOrderExchangeItemsFromActionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createOrderExchangeItemsFromActionsStep/index.html.md) +- [createOrderExchangesStep](https://docs.medusajs.com/references/medusa-workflows/steps/createOrderExchangesStep/index.html.md) +- [createOrderLineItemsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createOrderLineItemsStep/index.html.md) +- [createOrdersStep](https://docs.medusajs.com/references/medusa-workflows/steps/createOrdersStep/index.html.md) +- [createReturnsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createReturnsStep/index.html.md) +- [declineOrderChangeStep](https://docs.medusajs.com/references/medusa-workflows/steps/declineOrderChangeStep/index.html.md) +- [deleteClaimsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteClaimsStep/index.html.md) +- [deleteExchangesStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteExchangesStep/index.html.md) +- [deleteOrderChangeActionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteOrderChangeActionsStep/index.html.md) +- [deleteOrderChangesStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteOrderChangesStep/index.html.md) +- [deleteOrderLineItems](https://docs.medusajs.com/references/medusa-workflows/steps/deleteOrderLineItems/index.html.md) +- [deleteOrderShippingMethods](https://docs.medusajs.com/references/medusa-workflows/steps/deleteOrderShippingMethods/index.html.md) +- [deleteReturnsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteReturnsStep/index.html.md) +- [previewOrderChangeStep](https://docs.medusajs.com/references/medusa-workflows/steps/previewOrderChangeStep/index.html.md) +- [registerOrderChangesStep](https://docs.medusajs.com/references/medusa-workflows/steps/registerOrderChangesStep/index.html.md) +- [registerOrderDeliveryStep](https://docs.medusajs.com/references/medusa-workflows/steps/registerOrderDeliveryStep/index.html.md) +- [registerOrderFulfillmentStep](https://docs.medusajs.com/references/medusa-workflows/steps/registerOrderFulfillmentStep/index.html.md) +- [registerOrderShipmentStep](https://docs.medusajs.com/references/medusa-workflows/steps/registerOrderShipmentStep/index.html.md) +- [setOrderTaxLinesForItemsStep](https://docs.medusajs.com/references/medusa-workflows/steps/setOrderTaxLinesForItemsStep/index.html.md) +- [updateOrderChangeActionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateOrderChangeActionsStep/index.html.md) +- [updateOrderChangesStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateOrderChangesStep/index.html.md) +- [updateOrderShippingMethodsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateOrderShippingMethodsStep/index.html.md) +- [updateOrdersStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateOrdersStep/index.html.md) +- [updateReturnItemsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateReturnItemsStep/index.html.md) +- [updateReturnsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateReturnsStep/index.html.md) +- [authorizePaymentSessionStep](https://docs.medusajs.com/references/medusa-workflows/steps/authorizePaymentSessionStep/index.html.md) +- [cancelPaymentStep](https://docs.medusajs.com/references/medusa-workflows/steps/cancelPaymentStep/index.html.md) +- [capturePaymentStep](https://docs.medusajs.com/references/medusa-workflows/steps/capturePaymentStep/index.html.md) +- [refundPaymentStep](https://docs.medusajs.com/references/medusa-workflows/steps/refundPaymentStep/index.html.md) +- [refundPaymentsStep](https://docs.medusajs.com/references/medusa-workflows/steps/refundPaymentsStep/index.html.md) +- [createPaymentAccountHolderStep](https://docs.medusajs.com/references/medusa-workflows/steps/createPaymentAccountHolderStep/index.html.md) +- [createPaymentSessionStep](https://docs.medusajs.com/references/medusa-workflows/steps/createPaymentSessionStep/index.html.md) +- [createRefundReasonStep](https://docs.medusajs.com/references/medusa-workflows/steps/createRefundReasonStep/index.html.md) +- [deletePaymentSessionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deletePaymentSessionsStep/index.html.md) +- [deleteRefundReasonsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteRefundReasonsStep/index.html.md) +- [updatePaymentCollectionStep](https://docs.medusajs.com/references/medusa-workflows/steps/updatePaymentCollectionStep/index.html.md) +- [updateRefundReasonsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateRefundReasonsStep/index.html.md) +- [validateDeletedPaymentSessionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/validateDeletedPaymentSessionsStep/index.html.md) +- [createPriceListPricesStep](https://docs.medusajs.com/references/medusa-workflows/steps/createPriceListPricesStep/index.html.md) +- [createPriceListsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createPriceListsStep/index.html.md) +- [deletePriceListsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deletePriceListsStep/index.html.md) +- [getExistingPriceListsPriceIdsStep](https://docs.medusajs.com/references/medusa-workflows/steps/getExistingPriceListsPriceIdsStep/index.html.md) +- [removePriceListPricesStep](https://docs.medusajs.com/references/medusa-workflows/steps/removePriceListPricesStep/index.html.md) +- [updatePriceListPricesStep](https://docs.medusajs.com/references/medusa-workflows/steps/updatePriceListPricesStep/index.html.md) +- [updatePriceListsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updatePriceListsStep/index.html.md) +- [validatePriceListsStep](https://docs.medusajs.com/references/medusa-workflows/steps/validatePriceListsStep/index.html.md) +- [validateVariantPriceLinksStep](https://docs.medusajs.com/references/medusa-workflows/steps/validateVariantPriceLinksStep/index.html.md) +- [createPricePreferencesStep](https://docs.medusajs.com/references/medusa-workflows/steps/createPricePreferencesStep/index.html.md) +- [createPriceSetsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createPriceSetsStep/index.html.md) +- [deletePricePreferencesStep](https://docs.medusajs.com/references/medusa-workflows/steps/deletePricePreferencesStep/index.html.md) +- [updatePricePreferencesAsArrayStep](https://docs.medusajs.com/references/medusa-workflows/steps/updatePricePreferencesAsArrayStep/index.html.md) +- [updatePricePreferencesStep](https://docs.medusajs.com/references/medusa-workflows/steps/updatePricePreferencesStep/index.html.md) +- [updatePriceSetsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updatePriceSetsStep/index.html.md) +- [batchLinkProductsToCategoryStep](https://docs.medusajs.com/references/medusa-workflows/steps/batchLinkProductsToCategoryStep/index.html.md) +- [batchLinkProductsToCollectionStep](https://docs.medusajs.com/references/medusa-workflows/steps/batchLinkProductsToCollectionStep/index.html.md) +- [createCollectionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createCollectionsStep/index.html.md) +- [createProductOptionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createProductOptionsStep/index.html.md) +- [createProductTagsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createProductTagsStep/index.html.md) +- [createProductTypesStep](https://docs.medusajs.com/references/medusa-workflows/steps/createProductTypesStep/index.html.md) +- [createProductVariantsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createProductVariantsStep/index.html.md) +- [createProductsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createProductsStep/index.html.md) +- [createVariantPricingLinkStep](https://docs.medusajs.com/references/medusa-workflows/steps/createVariantPricingLinkStep/index.html.md) +- [deleteCollectionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteCollectionsStep/index.html.md) +- [deleteProductOptionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteProductOptionsStep/index.html.md) +- [deleteProductTagsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteProductTagsStep/index.html.md) +- [deleteProductTypesStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteProductTypesStep/index.html.md) +- [deleteProductVariantsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteProductVariantsStep/index.html.md) +- [deleteProductsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteProductsStep/index.html.md) +- [generateProductCsvStep](https://docs.medusajs.com/references/medusa-workflows/steps/generateProductCsvStep/index.html.md) +- [getAllProductsStep](https://docs.medusajs.com/references/medusa-workflows/steps/getAllProductsStep/index.html.md) +- [getProductsStep](https://docs.medusajs.com/references/medusa-workflows/steps/getProductsStep/index.html.md) +- [getVariantAvailabilityStep](https://docs.medusajs.com/references/medusa-workflows/steps/getVariantAvailabilityStep/index.html.md) +- [normalizeCsvStep](https://docs.medusajs.com/references/medusa-workflows/steps/normalizeCsvStep/index.html.md) +- [normalizeCsvToChunksStep](https://docs.medusajs.com/references/medusa-workflows/steps/normalizeCsvToChunksStep/index.html.md) +- [parseProductCsvStep](https://docs.medusajs.com/references/medusa-workflows/steps/parseProductCsvStep/index.html.md) +- [processImportChunksStep](https://docs.medusajs.com/references/medusa-workflows/steps/processImportChunksStep/index.html.md) +- [updateCollectionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateCollectionsStep/index.html.md) +- [updateProductOptionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateProductOptionsStep/index.html.md) +- [updateProductTagsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateProductTagsStep/index.html.md) +- [updateProductTypesStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateProductTypesStep/index.html.md) +- [updateProductVariantsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateProductVariantsStep/index.html.md) +- [updateProductsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateProductsStep/index.html.md) +- [waitConfirmationProductImportStep](https://docs.medusajs.com/references/medusa-workflows/steps/waitConfirmationProductImportStep/index.html.md) +- [createProductCategoriesStep](https://docs.medusajs.com/references/medusa-workflows/steps/createProductCategoriesStep/index.html.md) +- [deleteProductCategoriesStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteProductCategoriesStep/index.html.md) +- [updateProductCategoriesStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateProductCategoriesStep/index.html.md) +- [addCampaignPromotionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/addCampaignPromotionsStep/index.html.md) +- [addRulesToPromotionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/addRulesToPromotionsStep/index.html.md) +- [createCampaignsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createCampaignsStep/index.html.md) +- [createPromotionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createPromotionsStep/index.html.md) +- [deleteCampaignsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteCampaignsStep/index.html.md) +- [deletePromotionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deletePromotionsStep/index.html.md) +- [removeCampaignPromotionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/removeCampaignPromotionsStep/index.html.md) +- [removeRulesFromPromotionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/removeRulesFromPromotionsStep/index.html.md) +- [updateCampaignsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateCampaignsStep/index.html.md) +- [updatePromotionRulesStep](https://docs.medusajs.com/references/medusa-workflows/steps/updatePromotionRulesStep/index.html.md) +- [updatePromotionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updatePromotionsStep/index.html.md) +- [createRegionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createRegionsStep/index.html.md) +- [deleteRegionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteRegionsStep/index.html.md) +- [setRegionsPaymentProvidersStep](https://docs.medusajs.com/references/medusa-workflows/steps/setRegionsPaymentProvidersStep/index.html.md) +- [updateRegionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateRegionsStep/index.html.md) +- [createReservationsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createReservationsStep/index.html.md) +- [deleteReservationsByLineItemsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteReservationsByLineItemsStep/index.html.md) +- [deleteReservationsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteReservationsStep/index.html.md) +- [updateReservationsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateReservationsStep/index.html.md) +- [createReturnReasonsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createReturnReasonsStep/index.html.md) +- [deleteReturnReasonStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteReturnReasonStep/index.html.md) +- [updateReturnReasonsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateReturnReasonsStep/index.html.md) +- [associateLocationsWithSalesChannelsStep](https://docs.medusajs.com/references/medusa-workflows/steps/associateLocationsWithSalesChannelsStep/index.html.md) +- [associateProductsWithSalesChannelsStep](https://docs.medusajs.com/references/medusa-workflows/steps/associateProductsWithSalesChannelsStep/index.html.md) +- [canDeleteSalesChannelsOrThrowStep](https://docs.medusajs.com/references/medusa-workflows/steps/canDeleteSalesChannelsOrThrowStep/index.html.md) +- [createDefaultSalesChannelStep](https://docs.medusajs.com/references/medusa-workflows/steps/createDefaultSalesChannelStep/index.html.md) +- [createSalesChannelsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createSalesChannelsStep/index.html.md) +- [deleteSalesChannelsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteSalesChannelsStep/index.html.md) +- [detachLocationsFromSalesChannelsStep](https://docs.medusajs.com/references/medusa-workflows/steps/detachLocationsFromSalesChannelsStep/index.html.md) +- [detachProductsFromSalesChannelsStep](https://docs.medusajs.com/references/medusa-workflows/steps/detachProductsFromSalesChannelsStep/index.html.md) +- [updateSalesChannelsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateSalesChannelsStep/index.html.md) +- [createViewConfigurationStep](https://docs.medusajs.com/references/medusa-workflows/steps/createViewConfigurationStep/index.html.md) +- [setActiveViewConfigurationStep](https://docs.medusajs.com/references/medusa-workflows/steps/setActiveViewConfigurationStep/index.html.md) +- [updateViewConfigurationStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateViewConfigurationStep/index.html.md) +- [createShippingOptionTypesStep](https://docs.medusajs.com/references/medusa-workflows/steps/createShippingOptionTypesStep/index.html.md) +- [deleteShippingOptionTypesStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteShippingOptionTypesStep/index.html.md) +- [listShippingOptionsForContextStep](https://docs.medusajs.com/references/medusa-workflows/steps/listShippingOptionsForContextStep/index.html.md) +- [updateShippingOptionTypesStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateShippingOptionTypesStep/index.html.md) +- [deleteShippingProfilesStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteShippingProfilesStep/index.html.md) +- [createStockLocations](https://docs.medusajs.com/references/medusa-workflows/steps/createStockLocations/index.html.md) +- [deleteStockLocationsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteStockLocationsStep/index.html.md) +- [updateStockLocationsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateStockLocationsStep/index.html.md) +- [createStoresStep](https://docs.medusajs.com/references/medusa-workflows/steps/createStoresStep/index.html.md) +- [deleteStoresStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteStoresStep/index.html.md) +- [updateStoresStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateStoresStep/index.html.md) +- [createTaxRateRulesStep](https://docs.medusajs.com/references/medusa-workflows/steps/createTaxRateRulesStep/index.html.md) +- [createTaxRatesStep](https://docs.medusajs.com/references/medusa-workflows/steps/createTaxRatesStep/index.html.md) +- [createTaxRegionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createTaxRegionsStep/index.html.md) +- [deleteTaxRateRulesStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteTaxRateRulesStep/index.html.md) +- [deleteTaxRatesStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteTaxRatesStep/index.html.md) +- [deleteTaxRegionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteTaxRegionsStep/index.html.md) +- [getItemTaxLinesStep](https://docs.medusajs.com/references/medusa-workflows/steps/getItemTaxLinesStep/index.html.md) +- [listTaxRateIdsStep](https://docs.medusajs.com/references/medusa-workflows/steps/listTaxRateIdsStep/index.html.md) +- [listTaxRateRuleIdsStep](https://docs.medusajs.com/references/medusa-workflows/steps/listTaxRateRuleIdsStep/index.html.md) +- [updateTaxRatesStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateTaxRatesStep/index.html.md) +- [updateTaxRegionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateTaxRegionsStep/index.html.md) +- [createUsersStep](https://docs.medusajs.com/references/medusa-workflows/steps/createUsersStep/index.html.md) +- [deleteUsersStep](https://docs.medusajs.com/references/medusa-workflows/steps/deleteUsersStep/index.html.md) +- [updateUsersStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateUsersStep/index.html.md) # Events Reference @@ -42724,7 +42748,7 @@ to send a reset password email to the user or customer, for example. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [generateResetPasswordTokenWorkflow](undefined/references/medusa-workflows/generateResetPasswordTokenWorkflow) +- [generateResetPasswordTokenWorkflow](https://docs.medusajs.com/references/medusa-workflows/generateResetPasswordTokenWorkflow/index.html.md) *** @@ -42756,7 +42780,7 @@ Emitted when a cart is created. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [createCartWorkflow](undefined/references/medusa-workflows/createCartWorkflow) +- [createCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/createCartWorkflow/index.html.md) *** @@ -42776,10 +42800,10 @@ Emitted when a cart's details are updated. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [updateLineItemInCartWorkflow](undefined/references/medusa-workflows/updateLineItemInCartWorkflow) -- [updateCartWorkflow](undefined/references/medusa-workflows/updateCartWorkflow) -- [addToCartWorkflow](undefined/references/medusa-workflows/addToCartWorkflow) -- [addShippingMethodToCartWorkflow](undefined/references/medusa-workflows/addShippingMethodToCartWorkflow) +- [updateLineItemInCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateLineItemInCartWorkflow/index.html.md) +- [updateCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateCartWorkflow/index.html.md) +- [addToCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/addToCartWorkflow/index.html.md) +- [addShippingMethodToCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/addShippingMethodToCartWorkflow/index.html.md) *** @@ -42800,7 +42824,7 @@ event is emitted alongside the `cart.updated` event. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [updateCartWorkflow](undefined/references/medusa-workflows/updateCartWorkflow) +- [updateCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateCartWorkflow/index.html.md) *** @@ -42821,7 +42845,7 @@ Emitted when the customer in the cart is transferred. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [transferCartCustomerWorkflow](undefined/references/medusa-workflows/transferCartCustomerWorkflow) +- [transferCartCustomerWorkflow](https://docs.medusajs.com/references/medusa-workflows/transferCartCustomerWorkflow/index.html.md) *** @@ -42851,8 +42875,8 @@ Emitted when a customer is created. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [createCustomersWorkflow](undefined/references/medusa-workflows/createCustomersWorkflow) -- [createCustomerAccountWorkflow](undefined/references/medusa-workflows/createCustomerAccountWorkflow) +- [createCustomersWorkflow](https://docs.medusajs.com/references/medusa-workflows/createCustomersWorkflow/index.html.md) +- [createCustomerAccountWorkflow](https://docs.medusajs.com/references/medusa-workflows/createCustomerAccountWorkflow/index.html.md) *** @@ -42872,7 +42896,7 @@ Emitted when a customer is updated. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [updateCustomersWorkflow](undefined/references/medusa-workflows/updateCustomersWorkflow) +- [updateCustomersWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateCustomersWorkflow/index.html.md) *** @@ -42892,8 +42916,8 @@ Emitted when a customer is deleted. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [deleteCustomersWorkflow](undefined/references/medusa-workflows/deleteCustomersWorkflow) -- [removeCustomerAccountWorkflow](undefined/references/medusa-workflows/removeCustomerAccountWorkflow) +- [deleteCustomersWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteCustomersWorkflow/index.html.md) +- [removeCustomerAccountWorkflow](https://docs.medusajs.com/references/medusa-workflows/removeCustomerAccountWorkflow/index.html.md) *** @@ -42923,7 +42947,7 @@ Emitted when a shipment is created for an order. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [createOrderShipmentWorkflow](undefined/references/medusa-workflows/createOrderShipmentWorkflow) +- [createOrderShipmentWorkflow](https://docs.medusajs.com/references/medusa-workflows/createOrderShipmentWorkflow/index.html.md) *** @@ -42943,7 +42967,7 @@ Emitted when a fulfillment is marked as delivered. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [markOrderFulfillmentAsDeliveredWorkflow](undefined/references/medusa-workflows/markOrderFulfillmentAsDeliveredWorkflow) +- [markOrderFulfillmentAsDeliveredWorkflow](https://docs.medusajs.com/references/medusa-workflows/markOrderFulfillmentAsDeliveredWorkflow/index.html.md) *** @@ -42977,7 +43001,7 @@ Emitted when an invite is accepted. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [acceptInviteWorkflow](undefined/references/medusa-workflows/acceptInviteWorkflow) +- [acceptInviteWorkflow](https://docs.medusajs.com/references/medusa-workflows/acceptInviteWorkflow/index.html.md) *** @@ -42998,7 +43022,7 @@ to send an email to the invited users, for example. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [createInvitesWorkflow](undefined/references/medusa-workflows/createInvitesWorkflow) +- [createInvitesWorkflow](https://docs.medusajs.com/references/medusa-workflows/createInvitesWorkflow/index.html.md) *** @@ -43018,7 +43042,7 @@ Emitted when invites are deleted. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [deleteInvitesWorkflow](undefined/references/medusa-workflows/deleteInvitesWorkflow) +- [deleteInvitesWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteInvitesWorkflow/index.html.md) *** @@ -43040,7 +43064,7 @@ for example. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [refreshInviteTokensWorkflow](undefined/references/medusa-workflows/refreshInviteTokensWorkflow) +- [refreshInviteTokensWorkflow](https://docs.medusajs.com/references/medusa-workflows/refreshInviteTokensWorkflow/index.html.md) *** @@ -43071,7 +43095,7 @@ Emitted when an order edit is requested. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [requestOrderEditRequestWorkflow](undefined/references/medusa-workflows/requestOrderEditRequestWorkflow) +- [requestOrderEditRequestWorkflow](https://docs.medusajs.com/references/medusa-workflows/requestOrderEditRequestWorkflow/index.html.md) *** @@ -43092,7 +43116,7 @@ Emitted when an order edit request is confirmed. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [confirmOrderEditRequestWorkflow](undefined/references/medusa-workflows/confirmOrderEditRequestWorkflow) +- [confirmOrderEditRequestWorkflow](https://docs.medusajs.com/references/medusa-workflows/confirmOrderEditRequestWorkflow/index.html.md) *** @@ -43113,7 +43137,7 @@ Emitted when an order edit request is canceled. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [cancelBeginOrderEditWorkflow](undefined/references/medusa-workflows/cancelBeginOrderEditWorkflow) +- [cancelBeginOrderEditWorkflow](https://docs.medusajs.com/references/medusa-workflows/cancelBeginOrderEditWorkflow/index.html.md) *** @@ -43156,8 +43180,8 @@ doesn't include updates made by an edit. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [updateOrderWorkflow](undefined/references/medusa-workflows/updateOrderWorkflow) -- [updateDraftOrderWorkflow](undefined/references/medusa-workflows/updateDraftOrderWorkflow) +- [updateOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateOrderWorkflow/index.html.md) +- [updateDraftOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateDraftOrderWorkflow/index.html.md) *** @@ -43178,8 +43202,8 @@ order. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [convertDraftOrderWorkflow](undefined/references/medusa-workflows/convertDraftOrderWorkflow) -- [completeCartWorkflow](undefined/references/medusa-workflows/completeCartWorkflow) +- [convertDraftOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/convertDraftOrderWorkflow/index.html.md) +- [completeCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/completeCartWorkflow/index.html.md) *** @@ -43199,7 +43223,7 @@ Emitted when an order is canceld. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [cancelOrderWorkflow](undefined/references/medusa-workflows/cancelOrderWorkflow) +- [cancelOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/cancelOrderWorkflow/index.html.md) *** @@ -43219,7 +43243,7 @@ Emitted when orders are completed. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [completeOrderWorkflow](undefined/references/medusa-workflows/completeOrderWorkflow) +- [completeOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/completeOrderWorkflow/index.html.md) *** @@ -43239,7 +43263,7 @@ Emitted when an order is archived. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [archiveOrderWorkflow](undefined/references/medusa-workflows/archiveOrderWorkflow) +- [archiveOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/archiveOrderWorkflow/index.html.md) *** @@ -43261,7 +43285,7 @@ Emitted when a fulfillment is created for an order. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [createOrderFulfillmentWorkflow](undefined/references/medusa-workflows/createOrderFulfillmentWorkflow) +- [createOrderFulfillmentWorkflow](https://docs.medusajs.com/references/medusa-workflows/createOrderFulfillmentWorkflow/index.html.md) *** @@ -43283,7 +43307,7 @@ Emitted when an order's fulfillment is canceled. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [cancelOrderFulfillmentWorkflow](undefined/references/medusa-workflows/cancelOrderFulfillmentWorkflow) +- [cancelOrderFulfillmentWorkflow](https://docs.medusajs.com/references/medusa-workflows/cancelOrderFulfillmentWorkflow/index.html.md) *** @@ -43304,8 +43328,8 @@ Emitted when a return request is confirmed. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [createAndCompleteReturnOrderWorkflow](undefined/references/medusa-workflows/createAndCompleteReturnOrderWorkflow) -- [confirmReturnRequestWorkflow](undefined/references/medusa-workflows/confirmReturnRequestWorkflow) +- [createAndCompleteReturnOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/createAndCompleteReturnOrderWorkflow/index.html.md) +- [confirmReturnRequestWorkflow](https://docs.medusajs.com/references/medusa-workflows/confirmReturnRequestWorkflow/index.html.md) *** @@ -43326,8 +43350,8 @@ Emitted when a return is marked as received. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [createAndCompleteReturnOrderWorkflow](undefined/references/medusa-workflows/createAndCompleteReturnOrderWorkflow) -- [confirmReturnReceiveWorkflow](undefined/references/medusa-workflows/confirmReturnReceiveWorkflow) +- [createAndCompleteReturnOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/createAndCompleteReturnOrderWorkflow/index.html.md) +- [confirmReturnReceiveWorkflow](https://docs.medusajs.com/references/medusa-workflows/confirmReturnReceiveWorkflow/index.html.md) *** @@ -43348,7 +43372,7 @@ Emitted when a claim is created for an order. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [confirmClaimRequestWorkflow](undefined/references/medusa-workflows/confirmClaimRequestWorkflow) +- [confirmClaimRequestWorkflow](https://docs.medusajs.com/references/medusa-workflows/confirmClaimRequestWorkflow/index.html.md) *** @@ -43369,7 +43393,7 @@ Emitted when an exchange is created for an order. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [confirmExchangeRequestWorkflow](undefined/references/medusa-workflows/confirmExchangeRequestWorkflow) +- [confirmExchangeRequestWorkflow](https://docs.medusajs.com/references/medusa-workflows/confirmExchangeRequestWorkflow/index.html.md) *** @@ -43391,7 +43415,7 @@ another customer. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [requestOrderTransferWorkflow](undefined/references/medusa-workflows/requestOrderTransferWorkflow) +- [requestOrderTransferWorkflow](https://docs.medusajs.com/references/medusa-workflows/requestOrderTransferWorkflow/index.html.md) *** @@ -43420,9 +43444,9 @@ Emitted when a payment is captured. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [capturePaymentWorkflow](undefined/references/medusa-workflows/capturePaymentWorkflow) -- [processPaymentWorkflow](undefined/references/medusa-workflows/processPaymentWorkflow) -- [markPaymentCollectionAsPaid](undefined/references/medusa-workflows/markPaymentCollectionAsPaid) +- [capturePaymentWorkflow](https://docs.medusajs.com/references/medusa-workflows/capturePaymentWorkflow/index.html.md) +- [processPaymentWorkflow](https://docs.medusajs.com/references/medusa-workflows/processPaymentWorkflow/index.html.md) +- [markPaymentCollectionAsPaid](https://docs.medusajs.com/references/medusa-workflows/markPaymentCollectionAsPaid/index.html.md) *** @@ -43442,7 +43466,7 @@ Emitted when a payment is refunded. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [refundPaymentWorkflow](undefined/references/medusa-workflows/refundPaymentWorkflow) +- [refundPaymentWorkflow](https://docs.medusajs.com/references/medusa-workflows/refundPaymentWorkflow/index.html.md) *** @@ -43472,7 +43496,7 @@ Emitted when product categories are created. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [createProductCategoriesWorkflow](undefined/references/medusa-workflows/createProductCategoriesWorkflow) +- [createProductCategoriesWorkflow](https://docs.medusajs.com/references/medusa-workflows/createProductCategoriesWorkflow/index.html.md) *** @@ -43492,7 +43516,7 @@ Emitted when product categories are updated. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [updateProductCategoriesWorkflow](undefined/references/medusa-workflows/updateProductCategoriesWorkflow) +- [updateProductCategoriesWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateProductCategoriesWorkflow/index.html.md) *** @@ -43512,7 +43536,7 @@ Emitted when product categories are deleted. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [deleteProductCategoriesWorkflow](undefined/references/medusa-workflows/deleteProductCategoriesWorkflow) +- [deleteProductCategoriesWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteProductCategoriesWorkflow/index.html.md) *** @@ -43542,7 +43566,7 @@ Emitted when product collections are created. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [createCollectionsWorkflow](undefined/references/medusa-workflows/createCollectionsWorkflow) +- [createCollectionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createCollectionsWorkflow/index.html.md) *** @@ -43562,7 +43586,7 @@ Emitted when product collections are updated. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [updateCollectionsWorkflow](undefined/references/medusa-workflows/updateCollectionsWorkflow) +- [updateCollectionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateCollectionsWorkflow/index.html.md) *** @@ -43582,7 +43606,7 @@ Emitted when product collections are deleted. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [deleteCollectionsWorkflow](undefined/references/medusa-workflows/deleteCollectionsWorkflow) +- [deleteCollectionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteCollectionsWorkflow/index.html.md) *** @@ -43612,7 +43636,7 @@ Emitted when product options are updated. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [updateProductOptionsWorkflow](undefined/references/medusa-workflows/updateProductOptionsWorkflow) +- [updateProductOptionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateProductOptionsWorkflow/index.html.md) *** @@ -43632,7 +43656,7 @@ Emitted when product options are created. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [createProductOptionsWorkflow](undefined/references/medusa-workflows/createProductOptionsWorkflow) +- [createProductOptionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createProductOptionsWorkflow/index.html.md) *** @@ -43652,7 +43676,7 @@ Emitted when product options are deleted. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [deleteProductOptionsWorkflow](undefined/references/medusa-workflows/deleteProductOptionsWorkflow) +- [deleteProductOptionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteProductOptionsWorkflow/index.html.md) *** @@ -43682,7 +43706,7 @@ Emitted when product tags are updated. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [updateProductTagsWorkflow](undefined/references/medusa-workflows/updateProductTagsWorkflow) +- [updateProductTagsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateProductTagsWorkflow/index.html.md) *** @@ -43702,7 +43726,7 @@ Emitted when product tags are created. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [createProductTagsWorkflow](undefined/references/medusa-workflows/createProductTagsWorkflow) +- [createProductTagsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createProductTagsWorkflow/index.html.md) *** @@ -43722,7 +43746,7 @@ Emitted when product tags are deleted. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [deleteProductTagsWorkflow](undefined/references/medusa-workflows/deleteProductTagsWorkflow) +- [deleteProductTagsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteProductTagsWorkflow/index.html.md) *** @@ -43752,7 +43776,7 @@ Emitted when product types are updated. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [updateProductTypesWorkflow](undefined/references/medusa-workflows/updateProductTypesWorkflow) +- [updateProductTypesWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateProductTypesWorkflow/index.html.md) *** @@ -43772,7 +43796,7 @@ Emitted when product types are created. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [createProductTypesWorkflow](undefined/references/medusa-workflows/createProductTypesWorkflow) +- [createProductTypesWorkflow](https://docs.medusajs.com/references/medusa-workflows/createProductTypesWorkflow/index.html.md) *** @@ -43792,7 +43816,7 @@ Emitted when product types are deleted. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [deleteProductTypesWorkflow](undefined/references/medusa-workflows/deleteProductTypesWorkflow) +- [deleteProductTypesWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteProductTypesWorkflow/index.html.md) *** @@ -43822,8 +43846,8 @@ Emitted when product variants are updated. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [updateProductVariantsWorkflow](undefined/references/medusa-workflows/updateProductVariantsWorkflow) -- [batchProductVariantsWorkflow](undefined/references/medusa-workflows/batchProductVariantsWorkflow) +- [updateProductVariantsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateProductVariantsWorkflow/index.html.md) +- [batchProductVariantsWorkflow](https://docs.medusajs.com/references/medusa-workflows/batchProductVariantsWorkflow/index.html.md) *** @@ -43843,11 +43867,11 @@ Emitted when product variants are created. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [createProductVariantsWorkflow](undefined/references/medusa-workflows/createProductVariantsWorkflow) -- [createProductsWorkflow](undefined/references/medusa-workflows/createProductsWorkflow) -- [batchProductVariantsWorkflow](undefined/references/medusa-workflows/batchProductVariantsWorkflow) -- [batchProductsWorkflow](undefined/references/medusa-workflows/batchProductsWorkflow) -- [importProductsWorkflow](undefined/references/medusa-workflows/importProductsWorkflow) +- [createProductVariantsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createProductVariantsWorkflow/index.html.md) +- [createProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createProductsWorkflow/index.html.md) +- [batchProductVariantsWorkflow](https://docs.medusajs.com/references/medusa-workflows/batchProductVariantsWorkflow/index.html.md) +- [batchProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/batchProductsWorkflow/index.html.md) +- [importProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/importProductsWorkflow/index.html.md) *** @@ -43867,8 +43891,8 @@ Emitted when product variants are deleted. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [deleteProductVariantsWorkflow](undefined/references/medusa-workflows/deleteProductVariantsWorkflow) -- [batchProductVariantsWorkflow](undefined/references/medusa-workflows/batchProductVariantsWorkflow) +- [deleteProductVariantsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteProductVariantsWorkflow/index.html.md) +- [batchProductVariantsWorkflow](https://docs.medusajs.com/references/medusa-workflows/batchProductVariantsWorkflow/index.html.md) *** @@ -43898,9 +43922,9 @@ Emitted when products are updated. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [updateProductsWorkflow](undefined/references/medusa-workflows/updateProductsWorkflow) -- [batchProductsWorkflow](undefined/references/medusa-workflows/batchProductsWorkflow) -- [importProductsWorkflow](undefined/references/medusa-workflows/importProductsWorkflow) +- [updateProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateProductsWorkflow/index.html.md) +- [batchProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/batchProductsWorkflow/index.html.md) +- [importProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/importProductsWorkflow/index.html.md) *** @@ -43920,9 +43944,9 @@ Emitted when products are created. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [createProductsWorkflow](undefined/references/medusa-workflows/createProductsWorkflow) -- [batchProductsWorkflow](undefined/references/medusa-workflows/batchProductsWorkflow) -- [importProductsWorkflow](undefined/references/medusa-workflows/importProductsWorkflow) +- [createProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createProductsWorkflow/index.html.md) +- [batchProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/batchProductsWorkflow/index.html.md) +- [importProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/importProductsWorkflow/index.html.md) *** @@ -43942,9 +43966,9 @@ Emitted when products are deleted. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [deleteProductsWorkflow](undefined/references/medusa-workflows/deleteProductsWorkflow) -- [batchProductsWorkflow](undefined/references/medusa-workflows/batchProductsWorkflow) -- [importProductsWorkflow](undefined/references/medusa-workflows/importProductsWorkflow) +- [deleteProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteProductsWorkflow/index.html.md) +- [batchProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/batchProductsWorkflow/index.html.md) +- [importProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/importProductsWorkflow/index.html.md) *** @@ -43974,7 +43998,7 @@ Emitted when regions are updated. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [updateRegionsWorkflow](undefined/references/medusa-workflows/updateRegionsWorkflow) +- [updateRegionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateRegionsWorkflow/index.html.md) *** @@ -43994,7 +44018,7 @@ Emitted when regions are created. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [createRegionsWorkflow](undefined/references/medusa-workflows/createRegionsWorkflow) +- [createRegionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createRegionsWorkflow/index.html.md) *** @@ -44014,7 +44038,7 @@ Emitted when regions are deleted. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [deleteRegionsWorkflow](undefined/references/medusa-workflows/deleteRegionsWorkflow) +- [deleteRegionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteRegionsWorkflow/index.html.md) *** @@ -44044,7 +44068,7 @@ Emitted when sales channels are created. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [createSalesChannelsWorkflow](undefined/references/medusa-workflows/createSalesChannelsWorkflow) +- [createSalesChannelsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createSalesChannelsWorkflow/index.html.md) *** @@ -44064,7 +44088,7 @@ Emitted when sales channels are updated. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [updateSalesChannelsWorkflow](undefined/references/medusa-workflows/updateSalesChannelsWorkflow) +- [updateSalesChannelsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateSalesChannelsWorkflow/index.html.md) *** @@ -44084,7 +44108,7 @@ Emitted when sales channels are deleted. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [deleteSalesChannelsWorkflow](undefined/references/medusa-workflows/deleteSalesChannelsWorkflow) +- [deleteSalesChannelsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteSalesChannelsWorkflow/index.html.md) *** @@ -44114,7 +44138,7 @@ Emitted when shipping option types are updated. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [updateShippingOptionTypesWorkflow](undefined/references/medusa-workflows/updateShippingOptionTypesWorkflow) +- [updateShippingOptionTypesWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateShippingOptionTypesWorkflow/index.html.md) *** @@ -44134,7 +44158,7 @@ Emitted when shipping option types are created. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [createShippingOptionTypesWorkflow](undefined/references/medusa-workflows/createShippingOptionTypesWorkflow) +- [createShippingOptionTypesWorkflow](https://docs.medusajs.com/references/medusa-workflows/createShippingOptionTypesWorkflow/index.html.md) *** @@ -44154,7 +44178,7 @@ Emitted when shipping option types are deleted. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [deleteShippingOptionTypesWorkflow](undefined/references/medusa-workflows/deleteShippingOptionTypesWorkflow) +- [deleteShippingOptionTypesWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteShippingOptionTypesWorkflow/index.html.md) *** @@ -44184,9 +44208,9 @@ Emitted when users are created. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [createUsersWorkflow](undefined/references/medusa-workflows/createUsersWorkflow) -- [createUserAccountWorkflow](undefined/references/medusa-workflows/createUserAccountWorkflow) -- [acceptInviteWorkflow](undefined/references/medusa-workflows/acceptInviteWorkflow) +- [createUsersWorkflow](https://docs.medusajs.com/references/medusa-workflows/createUsersWorkflow/index.html.md) +- [createUserAccountWorkflow](https://docs.medusajs.com/references/medusa-workflows/createUserAccountWorkflow/index.html.md) +- [acceptInviteWorkflow](https://docs.medusajs.com/references/medusa-workflows/acceptInviteWorkflow/index.html.md) *** @@ -44206,7 +44230,7 @@ Emitted when users are updated. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [updateUsersWorkflow](undefined/references/medusa-workflows/updateUsersWorkflow) +- [updateUsersWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateUsersWorkflow/index.html.md) *** @@ -44226,8 +44250,8 @@ Emitted when users are deleted. The following workflows emit this event when they're executed. These workflows are executed by Medusa's API routes. You can also view the events emitted by API routes in the [Store](https://docs.medusajs.com/api/store) and [Admin](https://docs.medusajs.com/api/admin) API references. -- [deleteUsersWorkflow](undefined/references/medusa-workflows/deleteUsersWorkflow) -- [removeUserAccountWorkflow](undefined/references/medusa-workflows/removeUserAccountWorkflow) +- [deleteUsersWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteUsersWorkflow/index.html.md) +- [removeUserAccountWorkflow](https://docs.medusajs.com/references/medusa-workflows/removeUserAccountWorkflow/index.html.md) # build Command - Medusa CLI Reference @@ -44245,7 +44269,7 @@ The build is output to a new `.medusa/server` directory. npx medusa build ``` -Refer to the [Build Medusa Application](undefined/docs/learn/build) guide for next steps. +Refer to the [Build Medusa Application](https://docs.medusajs.com/docs/learn/build/index.html.md) guide for next steps. ## Options @@ -44402,7 +44426,7 @@ npx medusa develop # exec Command - Medusa CLI Reference -Run a custom CLI script using Medusa's CLI tool. Learn more about it in [Custom CLI Scripts guide](undefined/docs/learn/fundamentals/custom-cli-scripts). +Run a custom CLI script using Medusa's CLI tool. Learn more about it in [Custom CLI Scripts guide](https://docs.medusajs.com/docs/learn/fundamentals/custom-cli-scripts/index.html.md). ```bash npx medusa exec [file] [args...] @@ -44447,7 +44471,7 @@ medusa new [ []] # plugin Commands - Medusa CLI Reference -Commands in the Medusa CLI starting with `plugin:` perform actions related to [plugin development](undefined/docs/learn/fundamentals/plugins). +Commands in the Medusa CLI starting with `plugin:` perform actions related to [plugin development](https://docs.medusajs.com/docs/learn/fundamentals/plugins/index.html.md). These commands are available starting from [Medusa v2.3.0](https://github.com/medusajs/medusa/releases/tag/v2.3.0). @@ -44571,7 +44595,7 @@ npx medusa user --email user@example.com --invite The command will create a user invite and output the invite token. You can then either: - Accept the invite in the Medusa Admin at the path `/app/invite?token=` -- Accept the invite using the [Accept Invite API route](undefined/api/admin#invites_postinvitesaccept). +- Accept the invite using the [Accept Invite API route](https://docs.medusajs.com/api/admin#invites_postinvitesaccept). # Medusa CLI Reference @@ -44612,7 +44636,7 @@ The build is output to a new `.medusa/server` directory. npx medusa build ``` -Refer to the [Build Medusa Application](undefined/docs/learn/build) guide for next steps. +Refer to the [Build Medusa Application](https://docs.medusajs.com/docs/learn/build/index.html.md) guide for next steps. ## Options @@ -44769,7 +44793,7 @@ npx medusa develop # exec Command - Medusa CLI Reference -Run a custom CLI script using Medusa's CLI tool. Learn more about it in [Custom CLI Scripts guide](undefined/docs/learn/fundamentals/custom-cli-scripts). +Run a custom CLI script using Medusa's CLI tool. Learn more about it in [Custom CLI Scripts guide](https://docs.medusajs.com/docs/learn/fundamentals/custom-cli-scripts/index.html.md). ```bash npx medusa exec [file] [args...] @@ -44814,7 +44838,7 @@ medusa new [ []] # plugin Commands - Medusa CLI Reference -Commands in the Medusa CLI starting with `plugin:` perform actions related to [plugin development](undefined/docs/learn/fundamentals/plugins). +Commands in the Medusa CLI starting with `plugin:` perform actions related to [plugin development](https://docs.medusajs.com/docs/learn/fundamentals/plugins/index.html.md). These commands are available starting from [Medusa v2.3.0](https://github.com/medusajs/medusa/releases/tag/v2.3.0). @@ -44938,7 +44962,7 @@ npx medusa user --email user@example.com --invite The command will create a user invite and output the invite token. You can then either: - Accept the invite in the Medusa Admin at the path `/app/invite?token=` -- Accept the invite using the [Accept Invite API route](undefined/api/admin#invites_postinvitesaccept). +- Accept the invite using the [Accept Invite API route](https://docs.medusajs.com/api/admin#invites_postinvitesaccept). # Medusa CLI Reference @@ -44986,7 +45010,7 @@ There are three types of authentication: The JS SDK provides a set of configurations to customize the authentication method and storage. You can set these configurations when initializing the SDK. -For a full list of JS SDK configurations and their possible values, check out the [JS SDK Overview](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk#js-sdk-configurations) documentation. +For a full list of JS SDK configurations and their possible values, check out the [JS SDK Overview](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk#js-sdk-configurations/index.html.md) documentation. ### Authentication Type @@ -45106,7 +45130,7 @@ In this example, you set the `fetchCredentials` configuration to `same-origin`, If you're using an API key for authentication, you don't need to log in the user. -The JS SDK has an `auth.login` method that allows you to login admin users, customers, or any [actor type](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types) with any [auth provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/auth-providers). +The JS SDK has an `auth.login` method that allows you to login admin users, customers, or any [actor type](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types/index.html.md) with any [auth provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/auth-providers/index.html.md). Not only does this method log in the user, but it also stores the JWT token or session cookie for you and automatically includes it in the headers of all requests to the Medusa API. This means you don't have to manually set the authorization header for each request. @@ -45170,13 +45194,13 @@ In this example, you call the `sdk.auth.login` method passing it the actor type If the authentication is successful, there are two types of returned data: -- An object with a `location` property: This means the authentication requires more actions, which happens when using third-party authentication providers, such as [Google](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/auth-providers/google). In that case, you need to redirect the customer to the location to complete their authentication. - - Refer to the [Third-Party Login in Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development/customers/third-party-login) guide for an example implementation. +- An object with a `location` property: This means the authentication requires more actions, which happens when using third-party authentication providers, such as [Google](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/auth-providers/google/index.html.md). In that case, you need to redirect the customer to the location to complete their authentication. + - Refer to the [Third-Party Login in Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/customers/third-party-login/index.html.md) guide for an example implementation. - A string: This means the authentication was successful, and the user is logged in. The JS SDK automatically stores the JWT token or session cookie for you and includes it in the headers of all requests to the Medusa API. All requests you send afterwards will be authenticated with the stored token or session cookie. If the authentication fails, the `catch` block will be executed, and you can handle the error accordingly. -You can learn more about this method in the [auth.login reference](undefined/references/js-sdk/auth/login). +You can learn more about this method in the [auth.login reference](https://docs.medusajs.com/references/js-sdk/auth/login/index.html.md). ### Manually Set JWT Token @@ -45213,7 +45237,7 @@ sdk.auth.logout() }) ``` -You can learn more about this method in the [auth.logout reference](undefined/references/js-sdk/auth/logout). +You can learn more about this method in the [auth.logout reference](https://docs.medusajs.com/references/js-sdk/auth/logout/index.html.md). ### Manually Clearing JWT Token @@ -45307,7 +45331,7 @@ export const sdk = new Medusa({ }) ``` -In Medusa Admin customizations that are created in a Medusa project, you use `import.meta.env` to access environment variables, whereas in customizations built in a Medusa plugin, you use the global variable `__BACKEND_URL__` to access the backend URL. You can learn more in the [Admin Environment Variables](undefined/docs/learn/fundamentals/admin/environment-variables) chapter. +In Medusa Admin customizations that are created in a Medusa project, you use `import.meta.env` to access environment variables, whereas in customizations built in a Medusa plugin, you use the global variable `__BACKEND_URL__` to access the backend URL. You can learn more in the [Admin Environment Variables](https://docs.medusajs.com/docs/learn/fundamentals/admin/environment-variables/index.html.md) chapter. ### JS SDK Configurations @@ -45333,7 +45357,7 @@ The `Medusa` initializer accepts as a parameter an object with the following pro The JS SDK supports different types of authentication methods and allow you to flexibly configure them. -To learn more about configuring authentication in the JS SDK and sending authenticated requests, refer to the [Authentication](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk/auth/overview) guide. +To learn more about configuring authentication in the JS SDK and sending authenticated requests, refer to the [Authentication](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/auth/overview/index.html.md) guide. *** @@ -45754,7 +45778,7 @@ Learn more in the [Next.js documentation](https://nextjs.org/docs/app/building-y In this guide, you'll learn how to add line items with custom prices to a cart in Medusa. -When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules) which are available out-of-the-box. These features include managing carts and adding line items to them. +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md) which are available out-of-the-box. These features include managing carts and adding line items to them. By default, you can add product variants to the cart, where the price of its associated line item is based on the product variant's price. However, you can build customizations to add line items with custom prices to the cart. This is useful when integrating an Enterprise Resource Planning (ERP), Product Information Management (PIM), or other third-party services that provide real-time prices for your products. @@ -45791,15 +45815,15 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll first be asked for the project's name. You can also optionally choose to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter). +You'll first be asked for the project's name. You can also optionally choose to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md). Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name. If you chose to install the Next.js starter, it'll be installed in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more about Medusa's architecture in [this documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more about Medusa's architecture in [this documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterwards, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** @@ -45813,7 +45837,7 @@ To integrate third-party services into Medusa, you create a custom module. A mod In this step, you'll create a Metal Price Module that uses the GoldAPI.io service to retrieve real-time prices for metals like Gold and Silver. You'll use this module later to retrieve the real-time price of a product variant based on the metals in it, and add it to the cart with that custom price. -Learn more about modules in [this documentation](undefined/docs/learn/fundamentals/modules). +Learn more about modules in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). ### Create Module Directory @@ -45853,7 +45877,7 @@ A module can accept options that are passed to its service. You define an `Optio The service's constructor receives the module's options as a second parameter. You store the options in the service's `options_` property. -A module has a container of Medusa Framework tools and local resources in the module that you can access in the service constructor's first parameter. Learn more in [this documentation](undefined/docs/learn/fundamentals/modules/container). +A module has a container of Medusa Framework tools and local resources in the module that you can access in the service constructor's first parameter. Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/container/index.html.md). #### Add Method to Retrieve Metal Prices @@ -46019,15 +46043,15 @@ In this section, you'll implement the logic to retrieve the real-time price of a A workflow is a series of queries and actions, called steps, that complete a task. You construct a workflow like you construct a function, but it's a special function that allows you to track its executions' progress, define roll-back logic, and configure other advanced features. Then, you execute the workflow from other customizations, such as in an endpoint. -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows) +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) The workflow you'll implement in this section has the following steps: -- [useQueryGraphStep (Retrieve Cart)](undefined/references/helper-steps/useQueryGraphStep): Retrieve the cart's ID and currency using Query. -- [useQueryGraphStep (Retrieve Variant)](undefined/references/helper-steps/useQueryGraphStep): Retrieve the variant's details using Query +- [useQueryGraphStep (Retrieve Cart)](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the cart's ID and currency using Query. +- [useQueryGraphStep (Retrieve Variant)](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the variant's details using Query - [getVariantMetalPricesStep](#getvariantmetalpricesstep): Retrieve the variant's price using the third-party service. -- [addToCartWorkflow](undefined/references/medusa-workflows/addToCartWorkflow): Add the item with the custom price to the cart. -- [useQueryGraphStep (Retrieve Cart)](undefined/references/helper-steps/useQueryGraphStep): Retrieve the updated cart's details using Query. +- [addToCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/addToCartWorkflow/index.html.md): Add the item with the custom price to the cart. +- [useQueryGraphStep (Retrieve Cart)](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the updated cart's details using Query. `useQueryGraphStep` and `addToCartWorkflow` are available through Medusa's core workflows package. You'll only implement the `getVariantMetalPricesStep`. @@ -46075,7 +46099,7 @@ You create a step with `createStep` from the Workflows SDK. It accepts two param 1. The step's unique name, which is `get-variant-metal-prices`. 2. An async function that receives two parameters: - An input object with the variant, currency code, and quantity. The variant has a `calculated_price` property that holds the variant's fixed price in the Medusa application. This is useful when you want to add a fixed price to the real-time custom price, such as handling fees. - - The [Medusa container](undefined/docs/learn/fundamentals/medusa-container), which is a registry of Framework and commerce tools that you can access in the step. + - The [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which is a registry of Framework and commerce tools that you can access in the step. In the step function, so far you only resolve the Metal Prices Module's service from the Medusa container. @@ -46196,7 +46220,7 @@ You create a workflow with `createWorkflow` from the Workflows SDK. It accepts t 1. The workflow's unique name, which is `add-custom-to-cart`. 2. A function that receives an input object with the cart's ID and the item to add to the cart. The item has the variant's ID, quantity, and optional metadata. -In the function, you first retrieve the cart's details using the `useQueryGraphStep` helper step. This step uses [Query](undefined/docs/learn/fundamentals/module-links/query) which is a Modules SDK tool that retrieves data across modules. You use it to retrieve the cart's ID and currency code. +In the function, you first retrieve the cart's details using the `useQueryGraphStep` helper step. This step uses [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) which is a Modules SDK tool that retrieves data across modules. You use it to retrieve the cart's ID and currency code. You also retrieve the variant's details using the `useQueryGraphStep` helper step. You pass the variant's ID to the step's filters and specify the fields to retrieve. To retrieve the variant's price based on the cart's context, you pass the cart's currency code to the `calculated_price` context. @@ -46255,7 +46279,7 @@ addToCartWorkflow.runAsStep({ You prepare the item to add to the cart using `transform` from the Workflows SDK. It allows you to manipulate and create variables in a workflow. After that, you use Medusa's `addToCartWorkflow` to add the item with the custom price to the cart. -A workflow's constructor function has some constraints in implementation, which is why you need to use `transform` for variable manipulation. Learn more about these constraints in [this documentation](undefined/docs/learn/fundamentals/workflows/constructor-constraints). +A workflow's constructor function has some constraints in implementation, which is why you need to use `transform` for variable manipulation. Learn more about these constraints in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/constructor-constraints/index.html.md). Lastly, you'll retrieve the cart's details again and return them. Add the following import at the beginning of the file: @@ -46289,7 +46313,7 @@ Now that you've implemented the logic to add an item with a custom price to the An API Route is an endpoint that exposes commerce features to external applications and clients, such as storefronts. You'll create an API route at the path `/store/carts/:id/line-items-metals` that executes the workflow from the previous step to add a product variant with custom price to the cart. -Learn more about API routes in [this documentation](undefined/docs/learn/fundamentals/api-routes). +Learn more about API routes in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). ### Create API Route @@ -46328,7 +46352,7 @@ Since you export a `POST` function in this file, you're exposing a `POST` API ro 1. A request object with details and context on the request, such as path and body parameters. 2. A response object to manipulate and send the response. -In the function, you retrieve the cart's ID from the path parameter, and the item's details from the request body. This API route will accept the same request body parameters as Medusa's [Add Item to Cart API Route](undefined/api/store#carts_postcartsidlineitems). +In the function, you retrieve the cart's ID from the path parameter, and the item's details from the request body. This API route will accept the same request body parameters as Medusa's [Add Item to Cart API Route](https://docs.medusajs.com/api/store#carts_postcartsidlineitems). Then, you execute the `addCustomToCartWorkflow` by invoking it, passing it the Medusa container, which is available in the request's `scope` property, then executing its `run` method. You pass the workflow's input object with the cart's ID and the item to add to the cart. @@ -46340,7 +46364,7 @@ To ensure that the request body contains the required parameters, you'll add a m A middleware is a function executed before the API route when a request is sent to it. You define middlewares in Medusa in the `src/api/middlewares.ts` directory. -Learn more about middlewares in [this documentation](undefined/docs/learn/fundamentals/api-routes/middlewares). +Learn more about middlewares in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md). To add a validation middleware to the custom API route, create the file `src/api/middlewares.ts` with the following content: @@ -46376,11 +46400,11 @@ You pass in the `routes` array an object having the following properties: - `matcher`: The route to apply the middleware on. - `method`: The HTTP method to apply the middleware on for the specified API route. -- `middlewares`: An array of the middlewares to apply. You apply the `validateAndTransformBody` middleware, which validates the request body based on the `StoreAddCartLineItem` schema. This validation schema is the same schema used for Medusa's [Add Item to Cart API Route](undefined/api/store#carts_postcartsidlineitems). +- `middlewares`: An array of the middlewares to apply. You apply the `validateAndTransformBody` middleware, which validates the request body based on the `StoreAddCartLineItem` schema. This validation schema is the same schema used for Medusa's [Add Item to Cart API Route](https://docs.medusajs.com/api/store#carts_postcartsidlineitems). Any request sent to the `/store/carts/:id/line-items-metals` API route will now fail if it doesn't have the required parameters. -Learn more about API route validation in [this documentation](undefined/docs/learn/fundamentals/api-routes/validation). +Learn more about API route validation in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/validation/index.html.md). ### Prepare to Test API Route @@ -46530,18 +46554,18 @@ This price will be reflected in the cart's total price, and you can proceed to c ## Next Steps -You've now implemented custom item pricing in Medusa. You can also customize the [storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter) to use the new API route to add custom-priced items to the cart. +You've now implemented custom item pricing in Medusa. You can also customize the [storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) to use the new API route to add custom-priced items to the cart. -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). # Implement Quote Management in Medusa In this guide, you'll learn how to implement quote management in Medusa. -When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules) which are available out-of-the-box. +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md) which are available out-of-the-box. By default, the Medusa application provides standard commerce features for orders and carts. However, Medusa's customization capabilities facilitate extending existing features to implement quote-management features. @@ -46583,27 +46607,27 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll first be asked for the project's name. You can also optionally choose to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter). +You'll first be asked for the project's name. You can also optionally choose to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md). Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name. If you chose to install the Next.js starter, it'll be installed in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more about Medusa's architecture in [this documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more about Medusa's architecture in [this documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterwards, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** ## Step 2: Add Quote Module -In Medusa, you can build custom features in a [module](undefined/docs/learn/fundamentals/modules). A module is a reusable package with functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. +In Medusa, you can build custom features in a [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). A module is a reusable package with functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. In the module, you define the data models necessary for a feature and the logic to manage these data models. Later, you can build commerce flows around your module and link its data models to other modules' data models, such as orders and carts. In this step, you'll build a Quote Module that defines the necessary data model to store quotes. -Learn more about modules in [this documentation](undefined/docs/learn/fundamentals/modules). +Learn more about modules in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). ### Create Module Directory @@ -46615,7 +46639,7 @@ A module is created under the `src/modules` directory of your Medusa application A data model represents a table in the database. You create data models using Medusa's Data Model Language (DML). It simplifies defining a table's columns, relations, and indexes with straightforward methods and configurations. -Learn more about data models in [this documentation](undefined/docs/learn/fundamentals/modules#1-create-data-model). +Learn more about data models in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#1-create-data-model/index.html.md). For the Quote Module, you need to define a `Quote` data model that represents a quote requested by a customer. @@ -46659,10 +46683,10 @@ You define the `Quote` data model using the `model.define` method of the DML. It - `merchant_rejected`: The merchant has rejected the quote. - `customer_id`: The ID of the customer who requested the quote. You'll later learn how to link this to a customer record. - `draft_order_id`: The ID of the draft order created for the quote. You'll later learn how to link this to an order record. -- `order_change_id`: The ID of the order change created for the quote. An [order change](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/order-change) is a record of changes made to an order, such as price or quantity updates of the order's items. These changes are later applied to the order. You'll later learn how to link this to an order change record. +- `order_change_id`: The ID of the order change created for the quote. An [order change](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/order-change/index.html.md) is a record of changes made to an order, such as price or quantity updates of the order's items. These changes are later applied to the order. You'll later learn how to link this to an order change record. - `cart_id`: The ID of the cart that the quote was created from. The cart will hold the items that the customer wants a quote for. You'll later learn how to link this to a cart record. -Learn more about defining data model properties in the [Property Types documentation](undefined/docs/learn/fundamentals/data-models/properties). +Learn more about defining data model properties in the [Property Types documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/properties/index.html.md). ### Create Module's Service @@ -46670,7 +46694,7 @@ You now have the necessary data model in the Quote Module, but you need to defin A service is a TypeScript or JavaScript class that the module exports. In the service's methods, you can connect to the database, allowing you to manage your data models, or connect to a third-party service, which is useful if you're integrating with external services. -Learn more about services in [this documentation](undefined/docs/learn/fundamentals/modules#2-create-service). +Learn more about services in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#2-create-service/index.html.md). To create the Quote Module's service, create the file `src/modules/quote/service.ts` with the following content: @@ -46691,7 +46715,7 @@ The `QuoteModuleService` extends `MedusaService` from the Modules SDK which gene So, the `QuoteModuleService` class now has methods like `createQuotes` and `retrieveQuote`. -Find all methods generated by the `MedusaService` in [this reference](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference). +Find all methods generated by the `MedusaService` in [this reference](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/index.html.md). You'll use this service later when you implement custom flows for quote management. @@ -46744,7 +46768,7 @@ Each object in the `modules` array has a `resolve` property, whose value is eith Since data models represent tables in the database, you define how they're created in the database with migrations. A migration is a TypeScript or JavaScript file that defines database changes made by a module. -Learn more about migrations in [this documentation](undefined/docs/learn/fundamentals/modules#5-generate-migrations). +Learn more about migrations in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#5-generate-migrations/index.html.md). Medusa's CLI tool generates the migrations for you. To generate a migration for the Quote Module, run the following command in your Medusa application's directory: @@ -46768,20 +46792,20 @@ The table for the `Quote` data model is now created in the database. ## Step 3: Define Links to Other Modules -When you defined the `Quote` data model, you added properties that store the ID of records managed by other modules. For example, the `customer_id` property stores the ID of the customer that requested the quote, but customers are managed by the [Customer Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/customer). +When you defined the `Quote` data model, you added properties that store the ID of records managed by other modules. For example, the `customer_id` property stores the ID of the customer that requested the quote, but customers are managed by the [Customer Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/customer/index.html.md). Medusa integrates modules into your application without implications or side effects by isolating modules from one another. This means you can't directly create relationships between data models in your module and data models in other modules. Instead, Medusa provides the mechanism to define links between data models, and retrieve and manage linked records while maintaining module isolation. Links are useful to define associations between data models in different modules, or extend a model in another module to associate custom properties with it. -To learn more about module isolation, refer to the [Module Isolation documentation](undefined/docs/learn/fundamentals/modules/isolation). +To learn more about module isolation, refer to the [Module Isolation documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md). In this step, you'll define the following links between the Quote Module's data model and data models in other modules: -1. `Quote` \<> `Cart` data model of the [Cart Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/cart): link quotes to the carts they were created from. -2. `Quote` \<> `Customer` data model of the [Customer Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/customer): link quotes to the customers who requested them. -3. `Quote` \<> `OrderChange` data model of the [Order Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order): link quotes to the order changes that record adjustments made to the quote's draft order. -4. `Quote` \<> `Order` data model of the [Order Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order): link quotes to their draft orders that are later converted to orders. +1. `Quote` \<> `Cart` data model of the [Cart Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/cart/index.html.md): link quotes to the carts they were created from. +2. `Quote` \<> `Customer` data model of the [Customer Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/customer/index.html.md): link quotes to the customers who requested them. +3. `Quote` \<> `OrderChange` data model of the [Order Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/index.html.md): link quotes to the order changes that record adjustments made to the quote's draft order. +4. `Quote` \<> `Order` data model of the [Order Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/index.html.md): link quotes to their draft orders that are later converted to orders. ### Define Quote \<> Cart Link @@ -46902,18 +46926,18 @@ You've finished creating the links that allow you to retrieve data related to qu You're now ready to start implementing quote-management features. The first one you'll implement is the ability for customers to request a quote for a set of items in their cart. -To build custom commerce features in Medusa, you create a [workflow](undefined/docs/learn/fundamentals/workflows). A workflow is a series of queries and actions, called steps, that complete a task. You construct a workflow like you construct a function, but it's a special function that allows you to track its executions' progress, define roll-back logic, and configure other advanced features. Then, you execute the workflow from other customizations, such as in an endpoint. +To build custom commerce features in Medusa, you create a [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). A workflow is a series of queries and actions, called steps, that complete a task. You construct a workflow like you construct a function, but it's a special function that allows you to track its executions' progress, define roll-back logic, and configure other advanced features. Then, you execute the workflow from other customizations, such as in an endpoint. So, in this section, you'll learn how to create a workflow that creates a quote for a customer. -Learn more about workflows in the [Workflows documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in the [Workflows documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). The workflow will have the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the cart that the customer wants a quote for. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the customer requesting the quote. -- [createOrderWorkflow](undefined/references/medusa-workflows/createOrderWorkflow): Create the draft order for the quote. -- [beginOrderEditOrderWorkflow](undefined/references/medusa-workflows/beginOrderEditOrderWorkflow): Create the order change for the draft order. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the cart that the customer wants a quote for. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the customer requesting the quote. +- [createOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/createOrderWorkflow/index.html.md): Create the draft order for the quote. +- [beginOrderEditOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/beginOrderEditOrderWorkflow/index.html.md): Create the order change for the draft order. - [createQuotesStep](#createQuotesStep): Create the quote for the customer. The first four steps are provided by Medusa in its `@medusajs/medusa/core-flows` package. So, you only need to implement the `createQuotesStep` step. @@ -46960,7 +46984,7 @@ You create a step with `createStep` from the Workflows SDK. It accepts two param 1. The step's unique name, which is `create-quotes`. 2. An async function that receives two parameters: - The step's input, which is in this case an array of quotes to create. - - An object that has properties including the [Medusa container](undefined/docs/learn/fundamentals/medusa-container), which is a registry of Framework and commerce tools that you can access in the step. + - An object that has properties including the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which is a registry of Framework and commerce tools that you can access in the step. In the step function, you resolve the Quote Module's service from the Medusa container using the `resolve` method of the container, passing it the module's name as a parameter. @@ -46997,7 +47021,7 @@ export const createQuotesStep = createStep( The compensation function accepts two parameters: 1. The data passed from the step in the second parameter of `StepResponse`, which in this case is an array of quote IDs. -2. An object that has properties including the [Medusa container](undefined/docs/learn/fundamentals/medusa-container). +2. An object that has properties including the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). In the compensation function, you resolve the Quote Module's service from the Medusa container and call the `deleteQuotes` method to delete the quotes created in the step. @@ -47072,7 +47096,7 @@ It accepts as a second parameter a constructor function, which is the workflow's In the workflow's constructor function, you use `useQueryGraphStep` to retrieve the cart and customer details using the IDs passed as an input to the workflow. -`useQueryGraphStep` uses [Query](undefined/docs/learn/fundamentals/module-links/query), whic allows you to retrieve data across modules. For example, in the above snippet you're retrieving the cart's promotions, which are managed in the [Promotion Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/promotion), by passing `promotions.code` to the `fields` array. +`useQueryGraphStep` uses [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), whic allows you to retrieve data across modules. For example, in the above snippet you're retrieving the cart's promotions, which are managed in the [Promotion Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/promotion/index.html.md), by passing `promotions.code` to the `fields` array. Next, you want to create the draft order for the quote. Replace the `TODO` in the workflow with the following: @@ -47101,7 +47125,7 @@ const draftOrder = createOrderWorkflow.runAsStep({ // TODO create order change ``` -You first prepare the order's details using `transform` from the Workflows SDK. Since Medusa creates an internal representation of the workflow's constructor before any data actually has a value, you can't manipulate data directly in the function. So, Medusa provides utilities like `transform` to manipulate data instead. You can learn more in the [transform variables](undefined/docs/learn/fundamentals/workflows/variable-manipulation) documentation. +You first prepare the order's details using `transform` from the Workflows SDK. Since Medusa creates an internal representation of the workflow's constructor before any data actually has a value, you can't manipulate data directly in the function. So, Medusa provides utilities like `transform` to manipulate data instead. You can learn more in the [transform variables](https://docs.medusajs.com/docs/learn/fundamentals/workflows/variable-manipulation/index.html.md) documentation. Then, you create the draft order using the `createOrderWorkflow` workflow which you imported from `@medusajs/medusa/core-flows`. The workflow creates and returns the created order. @@ -47162,11 +47186,11 @@ In the next step, you'll learn how to execute the workflow when a customer reque ## Step 5: Create Quote API Route -Now that you have the logic to create a quote for a customer, you need to expose it so that frontend clients, such as a storefront, can use it. You do this by creating an [API route](undefined/docs/learn/fundamentals/api-routes). +Now that you have the logic to create a quote for a customer, you need to expose it so that frontend clients, such as a storefront, can use it. You do this by creating an [API route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). An API Route is an endpoint that exposes commerce features to external applications and clients, such as storefronts. You'll create an API route at the path `/store/customers/me/quotes` that executes the workflow from the previous step. -Learn more about API routes in [this documentation](undefined/docs/learn/fundamentals/api-routes). +Learn more about API routes in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). ### Implement API Route @@ -47278,7 +47302,7 @@ export const POST = async ( Now that you have the validation schema, you need to add the middleware that ensures the request body is validated before the route handler is executed. A middleware is a function executed when a request is sent to an API Route. It's executed before the route handler. -Learn more about middleware in the [Middlewares documentation](undefined/docs/learn/fundamentals/api-routes/middlewares). +Learn more about middleware in the [Middlewares documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md). Middlewares are created in the `src/api/middlewares.ts` file. So create the file `src/api/middlewares.ts` with the following content: @@ -47316,7 +47340,7 @@ In the route handler you just created, you specified what fields to retrieve in To add the Query configurations, you'll first create a file that exports the default fields to retrieve for a quote, then apply them in a `validateAndTransformQuery` middleware. -Learn more about configuring Query for requests in the [Request Query Configurations documentation](undefined/docs/learn/fundamentals/module-links/query#request-query-configurations). +Learn more about configuring Query for requests in the [Request Query Configurations documentation](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query#request-query-configurations/index.html.md). Create the file `src/api/store/customers/me/quotes/query-config.ts` with the following content: @@ -47454,15 +47478,15 @@ Then, open the Medusa Admin dashboard at `http://localhost:9000/app` and login u All requests sent to routes starting with `/store` must have a publishable API key in their header. This ensures that the request is scoped to a specific sales channel of your storefront. -To learn more about publishable API keys, refer to the [Publishable API Key documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/sales-channel/publishable-api-keys). +To learn more about publishable API keys, refer to the [Publishable API Key documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/sales-channel/publishable-api-keys/index.html.md). -To retrieve the publishable API key from the Medusa Admin, refer to [this user guide](undefined/user-guide/settings/developer/publishable-api-keys). +To retrieve the publishable API key from the Medusa Admin, refer to [this user guide](https://docs.medusajs.com/user-guide/settings/developer/publishable-api-keys/index.html.md). #### Retrieve Customer Authentication Token As mentioned before, the API route you added requires the customer to be authenticated. So, you'll first create a customer, then retrieve their authentication token to use in the request. -Before creating the customer, retrieve a registration token using the [Retrieve Registration JWT Token API route](undefined/api/store#auth_postactor_typeauth_provider_register): +Before creating the customer, retrieve a registration token using the [Retrieve Registration JWT Token API route](https://docs.medusajs.com/api/store#auth_postactor_typeauth_provider_register): ```bash curl -X POST 'http://localhost:9000/auth/customer/emailpass/register' \ @@ -47475,7 +47499,7 @@ curl -X POST 'http://localhost:9000/auth/customer/emailpass/register' \ Make sure to replace the email and password with the credentials you want. -Then, register the customer using the [Create Customer API route](undefined/api/store#customers_postcustomers): +Then, register the customer using the [Create Customer API route](https://docs.medusajs.com/api/store#customers_postcustomers): ```bash curl -X POST 'http://localhost:9000/store/customers' \ @@ -47494,7 +47518,7 @@ Make sure to replace: Also, if you changed the email in the first request, make sure to change it here as well. -The customer is now registered. Lastly, you need to retrieve its authenticated token by sending a request to the [Authenticate Customer API route](undefined/api/store#auth_postactor_typeauth_provider): +The customer is now registered. Lastly, you need to retrieve its authenticated token by sending a request to the [Authenticate Customer API route](https://docs.medusajs.com/api/store#auth_postactor_typeauth_provider): ```bash curl -X POST 'http://localhost:9000/auth/customer/emailpass' \ @@ -47511,7 +47535,7 @@ Copy the returned token to use it in the next requests. The customer needs a cart with an item before creating the quote. -A cart requires a region ID. You can retrieve a region ID using the [List Regions API route](undefined/api/store#regions_getregions): +A cart requires a region ID. You can retrieve a region ID using the [List Regions API route](https://docs.medusajs.com/api/store#regions_getregions): ```bash curl 'http://localhost:9000/store/regions' \ @@ -47520,7 +47544,7 @@ curl 'http://localhost:9000/store/regions' \ Make sure to replace the `{your_publishable_api_key}` with the publishable API key you retrieved from the Medusa Admin. -Then, create a cart for the customer using the [Create Cart API route](undefined/api/store#carts_postcarts): +Then, create a cart for the customer using the [Create Cart API route](https://docs.medusajs.com/api/store#carts_postcarts): ```bash curl -X POST 'http://localhost:9000/store/carts' \ @@ -47540,7 +47564,7 @@ Make sure to replace: This will create and return a cart. Copy its ID for the next request. -You now need to add a product variant to the cart. You can retrieve a product variant ID using the [List Products API route](undefined/api/store#products_getproducts): +You now need to add a product variant to the cart. You can retrieve a product variant ID using the [List Products API route](https://docs.medusajs.com/api/store#products_getproducts): ```bash curl 'http://localhost:9000/store/products' \ @@ -47551,7 +47575,7 @@ Make sure to replace the `{your_publishable_api_key}` with the publishable API k Copy the ID of a variant in a product from the response. -Finally, to add the product variant to the cart, use the [Add Item to Cart API route](undefined/api/store#carts_postcartsidlineitems): +Finally, to add the product variant to the cart, use the [Add Item to Cart API route](https://docs.medusajs.com/api/store#carts_postcartsidlineitems): ```bash curl -X POST 'http://localhost:9000/store/carts/{id}/line-items' \ @@ -47575,12 +47599,12 @@ This adds the product variant to the cart. You can now use the cart to create a For more accurate totals and processing of the quote's draft order, you should: -- Add shipping and billing addresses by [updating the cart](undefined/api/store#carts_postcartsid). -- [Choose a shipping method](undefined/api/store#carts_postcartsidshippingmethods) for the cart. -- [Create a payment collection](undefined/api/store#payment-collections_postpaymentcollections) for the cart. -- [Initialize payment session](undefined/api/store#payment-collections_postpaymentcollectionsidpaymentsessions) in the payment collection. +- Add shipping and billing addresses by [updating the cart](https://docs.medusajs.com/api/store#carts_postcartsid). +- [Choose a shipping method](https://docs.medusajs.com/api/store#carts_postcartsidshippingmethods) for the cart. +- [Create a payment collection](https://docs.medusajs.com/api/store#payment-collections_postpaymentcollections) for the cart. +- [Initialize payment session](https://docs.medusajs.com/api/store#payment-collections_postpaymentcollectionsidpaymentsessions) in the payment collection. -You can also learn how to build a checkout experience in a storefront by following [this storefront development guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development/checkout). It's not specific to quote management, so you'll need to change the last step to create a quote instead of an order. +You can also learn how to build a checkout experience in a storefront by following [this storefront development guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/checkout/index.html.md). It's not specific to quote management, so you'll need to change the last step to create a quote instead of an order. #### Create Quote @@ -47648,7 +47672,7 @@ In the route handler function, you resolve Query from the Medusa container and u `req.queryConfig` also includes pagination parameters, such as `limit`, `offset`, and `count`, and they're returned in the `metadata` property of Query's result. You return the pagination details and the list of quotes in the response. -Learn more about paginating Query results in the [Query documentation](undefined/docs/learn/fundamentals/module-links/query#apply-pagination). +Learn more about paginating Query results in the [Query documentation](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query#apply-pagination/index.html.md). ### Add Query Configurations @@ -47777,11 +47801,11 @@ Now that you have the API route to retrieve the list of quotes, you want to show A UI route is a React component that specifies the content to be shown in a new page in the Medusa Admin dashboard. You'll create a UI route to display the list of quotes in the Medusa Admin. -Learn more about UI routes in the [UI Routes documentation](undefined/docs/learn/fundamentals/admin/ui-routes). +Learn more about UI routes in the [UI Routes documentation](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md). ### Configure JS SDK -Medusa provides a [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk) that you can use to send requests to the Medusa server from any client application, including your Medusa Admin customizations. +Medusa provides a [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md) that you can use to send requests to the Medusa server from any client application, including your Medusa Admin customizations. The JS SDK is installed by default in your Medusa application. To configure it, create the file `src/admin/lib/sdk.ts` with the following content: @@ -47943,7 +47967,7 @@ export default Quotes The route file must export a React component that implements the content of the page. To show a link to the route in the sidebar, you can also export a configuation object created with `defineRouteConfig` that specifies the label and icon of the route in the Medusa Admin sidebar. -In the `Quotes` component, you'll show a table of quotes using the [DataTable component](undefined/ui/components/data-table) from Medusa UI. This componet requires you first define the columns of the table. +In the `Quotes` component, you'll show a table of quotes using the [DataTable component](https://docs.medusajs.com/ui/components/data-table/index.html.md) from Medusa UI. This componet requires you first define the columns of the table. To define the table's columns, add in the same file and before the `Quotes` component the following: @@ -48190,7 +48214,7 @@ You define a `useQuote` hook that accepts the quote's ID and optional query para The hook returns the fetched data from the Medusa server. You'll use this hook later in the UI route. -In addition, you'll need a hook to retrieve a preview of the quote's draft order. An order preview includes changes or edits to be applied on an order's items, such as changes in prices and quantities. Medusa already provides a [Get Order Preview API route](undefined/api/admin#orders_getordersidpreview) that you can use to retrieve the preview. +In addition, you'll need a hook to retrieve a preview of the quote's draft order. An order preview includes changes or edits to be applied on an order's items, such as changes in prices and quantities. Medusa already provides a [Get Order Preview API route](https://docs.medusajs.com/api/admin#orders_getordersidpreview) that you can use to retrieve the preview. To create the hook, create the file `src/admin/hooks/order-preview.tsx` with the following content: @@ -48760,7 +48784,7 @@ In this step, you'll implement the functionality to reject a quote from the quot To reject a quote, you'll need to create a workflow that will handle the rejection process. The workflow has the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the quote's details. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the quote's details. - [validateQuoteNotAccepted](#validateQuoteNotAccepted): Validate that the quote isn't already accepted by the customer. - [updateQuoteStatusStep](#updateQuoteStatusStep): Update the quote's status to \`merchant\_rejected\`. @@ -49122,7 +49146,7 @@ In this step, you'll implement the functionality to send a quote back to the cus You'll implement the logic of sending the quote in a workflow. The workflow has the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the quote's details. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the quote's details. - [validateQuoteNotAccepted](#validateQuoteNotAccepted): Validate that the quote isn't already accepted by the customer. - [updateQuoteStatusStep](#updateQuoteStatusStep): Update the quote's status to \`pending\_customer\`. @@ -49483,7 +49507,7 @@ In this step, you'll implement the functionality to reject a quote from the cust To reject a quote from the customer's perspective, you'll need to create a workflow that will handle the rejection process. The workflow has the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the quote's details. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the quote's details. - [validateQuoteNotAccepted](#validateQuoteNotAccepted): Validate that the quote isn't already accepted by the customer. - [updateQuoteStatusStep](#updateQuoteStatusStep): Update the quote's status to \`customer\_rejected\`. @@ -49632,11 +49656,11 @@ In this step, you'll implement the functionality to allow a customer to accept a You'll implement the quote acceptance logic in a workflow. The workflow has the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the quote's details. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the quote's details. - [validateQuoteCanAcceptStep](#validateQuoteCanAcceptStep): Validate that the quote can be accepted. - [updateQuotesStep](#updateQuotesStep): Update the quote's status to \`accepted\`. -- [confirmOrderEditRequestWorkflow](undefined/references/medusa-workflows/confirmOrderEditRequestWorkflow): Confirm the changes made on the draft order, such as changes to item quantities and prices. -- [updateOrderWorkflow](undefined/references/medusa-workflows/updateOrderWorkflow): Update the draft order to change its status and convert it into an order. +- [confirmOrderEditRequestWorkflow](https://docs.medusajs.com/references/medusa-workflows/confirmOrderEditRequestWorkflow/index.html.md): Confirm the changes made on the draft order, such as changes to item quantities and prices. +- [updateOrderWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateOrderWorkflow/index.html.md): Update the draft order to change its status and convert it into an order. You only need to implement the `validateQuoteCanAcceptStep` step before implementing the workflow, as the other steps are already available for use. @@ -49832,15 +49856,15 @@ You can also view the quote from the Medusa Admin dashboard, where you'll find i The last feature you'll add is allowing merchants or admin users to make changes to the quote's items. This includes updating the item's quantity and price. -Since you're using an [order change](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/order-change) to manage edits to the quote's draft orders, you don't need to implement customizations on the server side, such as adding workflows or API routes. Instead, you'll only add a new UI route in the Medusa Admin that uses the [Order Edit API routes](undefined/api/admin#order-edits) to provide the functionality to edit the quote's items. +Since you're using an [order change](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/order-change/index.html.md) to manage edits to the quote's draft orders, you don't need to implement customizations on the server side, such as adding workflows or API routes. Instead, you'll only add a new UI route in the Medusa Admin that uses the [Order Edit API routes](https://docs.medusajs.com/api/admin#order-edits) to provide the functionality to edit the quote's items. -Order changes also allow you to add or remove items from the quote. However, for simplicity, this guide only covers how to update the item's quantity and price. Refer to the [Order Change](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/order-change) documentation to learn more. +Order changes also allow you to add or remove items from the quote. However, for simplicity, this guide only covers how to update the item's quantity and price. Refer to the [Order Change](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/order-change/index.html.md) documentation to learn more. ![Edit quote items page in Medusa Admin](https://res.cloudinary.com/dza7lstvk/image/upload/v1741169659/Medusa%20Resources/Screenshot_2025-03-05_at_12.14.05_PM_ufvkqb.png) In this step, you'll add a new UI route to manage the quote's items. This will include: -1. Adding hooks to send requests to [Medusa's Order Edits API routes](undefined/api/admin#order-edits). +1. Adding hooks to send requests to [Medusa's Order Edits API routes](https://docs.medusajs.com/api/admin#order-edits). 2. Implement the components you'll use within the UI route. 3. Add the new UI route to the Medusa Admin. @@ -50406,11 +50430,11 @@ The changes can now be previewed from the quote's details page. The customer can You've now implemented quote management features in Medusa. There's still more that you can implement to enhance the quote management experience: - Refer to the [B2B starter](https://github.com/medusajs/b2b-starter-medusa) for more quote-management related features, including how to add or remove items from a quote, and how to allow messages between the customer and the merchant. -- To build a storefront, refer to the [Storefront development guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development). You can also add to the storefront features related to quote-management using the APIs you implemented in this guide. +- To build a storefront, refer to the [Storefront development guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/index.html.md). You can also add to the storefront features related to quote-management using the APIs you implemented in this guide. -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). # Medusa Examples @@ -50445,7 +50469,7 @@ export const GET = ( This creates a `GET` API route at `/hello-world`. -Learn more in [this documentation](undefined/docs/learn/fundamentals/api-routes). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). ### Resolve Resources in API Route @@ -50474,7 +50498,7 @@ export const GET = async ( This resolves the Product Module's main service. -Learn more in [this documentation](undefined/docs/learn/fundamentals/medusa-container). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). ### Use Path Parameters @@ -50498,7 +50522,7 @@ export const GET = async ( } ``` -Learn more about path parameters in [this documentation](undefined/docs/learn/fundamentals/api-routes/parameters#path-parameters). +Learn more about path parameters in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/parameters#path-parameters/index.html.md). ### Use Query Parameters @@ -50520,7 +50544,7 @@ export const GET = async ( } ``` -Learn more about query parameters in [this documentation](undefined/docs/learn/fundamentals/api-routes/parameters#query-parameters). +Learn more about query parameters in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/parameters#query-parameters/index.html.md). ### Use Body Parameters @@ -50546,7 +50570,7 @@ export const POST = async ( } ``` -Learn more about request body parameters in [this documentation](undefined/docs/learn/fundamentals/api-routes/parameters#request-body-parameters). +Learn more about request body parameters in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/parameters#request-body-parameters/index.html.md). ### Set Response Code @@ -50565,7 +50589,7 @@ export const GET = async ( } ``` -Learn more about setting the response code in [this documentation](undefined/docs/learn/fundamentals/api-routes/responses#set-response-status-code). +Learn more about setting the response code in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/responses#set-response-status-code/index.html.md). ### Execute a Workflow in an API Route @@ -50593,7 +50617,7 @@ export async function GET( } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/workflows#3-execute-the-workflow). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows#3-execute-the-workflow/index.html.md). ### Change Response Content Type @@ -50627,7 +50651,7 @@ export const GET = async ( This changes the response type to return an event stream. -Learn more in [this documentation](undefined/docs/learn/fundamentals/api-routes/responses#change-response-content-type). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/responses#change-response-content-type/index.html.md). ### Create Middleware @@ -50677,7 +50701,7 @@ export default defineMiddlewares({ }) ``` -Learn more about middlewares in [this documentation](undefined/docs/learn/fundamentals/api-routes/middlewares). +Learn more about middlewares in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md). ### Restrict HTTP Methods in Middleware @@ -50760,13 +50784,13 @@ export const POST = async ( } ``` -Learn more about request body validation in [this documentation](undefined/docs/learn/fundamentals/api-routes/validation). +Learn more about request body validation in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/validation/index.html.md). ### Pass Additional Data to API Route In this example, you'll pass additional data to the Create Product API route, then consume its hook: -Find this example in details in [this documentation](undefined/docs/learn/customization/extend-features/extend-create-product). +Find this example in details in [this documentation](https://docs.medusajs.com/docs/learn/customization/extend-features/extend-create-product/index.html.md). 1. Create the file `src/api/middlewares.ts` with the following content: @@ -50787,7 +50811,7 @@ export default defineMiddlewares({ }) ``` -Learn more about additional data in [this documentation](undefined/docs/learn/fundamentals/api-routes/additional-data). +Learn more about additional data in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/additional-data/index.html.md). 2. Create the file `src/workflows/hooks/created-product.ts` with the following content: @@ -50810,7 +50834,7 @@ createProductsWorkflow.hooks.productsCreated( ) ``` -Learn more about workflow hooks in [this documentation](undefined/docs/learn/fundamentals/workflows/workflow-hooks). +Learn more about workflow hooks in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/workflow-hooks/index.html.md). ### Restrict an API Route to Admin Users @@ -50839,7 +50863,7 @@ export default defineMiddlewares({ }) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/api-routes/protected-routes). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/protected-routes/index.html.md). ### Restrict an API Route to Logged-In Customers @@ -50865,7 +50889,7 @@ export default defineMiddlewares({ }) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/api-routes/protected-routes). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/protected-routes/index.html.md). ### Retrieve Logged-In Admin User @@ -50896,7 +50920,7 @@ export const GET = async ( } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/api-routes/protected-routes#retrieve-logged-in-admin-users-details). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/protected-routes#retrieve-logged-in-admin-users-details/index.html.md). ### Retrieve Logged-In Customer @@ -50930,7 +50954,7 @@ export const GET = async ( } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/api-routes/protected-routes#retrieve-logged-in-customers-details). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/protected-routes#retrieve-logged-in-customers-details/index.html.md). ### Throw Errors in API Route @@ -50955,7 +50979,7 @@ export const GET = async ( } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/api-routes/errors). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/errors/index.html.md). ### Override Error Handler of API Routes @@ -50984,7 +51008,7 @@ export default defineMiddlewares({ }) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/api-routes/errors#override-error-handler), +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/errors#override-error-handler/index.html.md), ### Setting up CORS for Custom API Routes @@ -51075,7 +51099,7 @@ A module is a package of reusable commerce or architectural functionalities. The ### Create Module -Find this example explained in details in [this documentation](undefined/docs/learn/fundamentals/modules). +Find this example explained in details in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). 1. Create the directory `src/modules/blog`. 2. Create the file `src/modules/blog/models/post.ts` with the following data model: @@ -51209,7 +51233,7 @@ class BlogModuleService extends MedusaService({ export default BlogModuleService ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/modules/multiple-services). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/multiple-services/index.html.md). ### Accept Module Options @@ -51261,7 +51285,7 @@ export default class BlogModuleService extends MedusaService({ } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/modules/options). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/options/index.html.md). ### Integrate Third-Party System in Module @@ -51302,7 +51326,7 @@ export class BlogClient { } ``` -Find a longer example of integrating a third-party service in [this documentation](undefined/docs/learn/customization/integrate-systems/service). +Find a longer example of integrating a third-party service in [this documentation](https://docs.medusajs.com/docs/learn/customization/integrate-systems/service/index.html.md). *** @@ -51336,7 +51360,7 @@ npx medusa db:generate blog npx medusa db:migrate ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/modules#1-create-data-model). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#1-create-data-model/index.html.md). ### Data Model Property Types @@ -51423,7 +51447,7 @@ const Post = model.define("post", { }) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/data-models/properties). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/properties/index.html.md). ### Set Primary Key @@ -51466,7 +51490,7 @@ const Post = model.define("post", { export default Post ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/data-models/properties#set-primary-key-property). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/properties#set-primary-key-property/index.html.md). ### Default Property Value @@ -51488,7 +51512,7 @@ const Post = model.define("post", { export default Post ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/data-models/properties#property-default-value). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/properties#property-default-value/index.html.md). ### Nullable Property @@ -51505,7 +51529,7 @@ const Post = model.define("post", { export default Post ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/data-models/properties#make-property-optional). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/properties#make-property-optional/index.html.md). ### Unique Property @@ -51522,7 +51546,7 @@ const Post = model.define("post", { export default Post ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/data-models/properties#unique-property). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/properties#unique-property/index.html.md). ### Define Database Index on Property @@ -51541,7 +51565,7 @@ const MyCustom = model.define("my_custom", { export default MyCustom ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/data-models/properties#define-database-index-on-property). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/properties#define-database-index-on-property/index.html.md). ### Define Composite Index on Data Model @@ -51568,7 +51592,7 @@ const MyCustom = model.define("my_custom", { export default MyCustom ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/data-models/index). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/index/index.html.md). ### Make a Property Searchable @@ -51595,7 +51619,7 @@ const posts = await blogModuleService.listPosts({ }) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/data-models/properties#searchable-property). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/properties#searchable-property/index.html.md). ### Create One-to-One Relationship @@ -51619,7 +51643,7 @@ const Email = model.define("email", { }) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/data-models/relationships#one-to-one-relationship). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/relationships#one-to-one-relationship/index.html.md). ### Create One-to-Many Relationship @@ -51643,7 +51667,7 @@ const Product = model.define("product", { }) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/data-models/relationships#one-to-many-relationship). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/relationships#one-to-many-relationship/index.html.md). ### Create Many-to-Many Relationship @@ -51667,7 +51691,7 @@ const Product = model.define("product", { }) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/data-models/relationships#many-to-many-relationship). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/relationships#many-to-many-relationship/index.html.md). ### Configure Cascades of Data Model @@ -51690,7 +51714,7 @@ const Store = model.define("store", { This configures the delete cascade on the `Store` data model so that, when a store is delete, its products are also deleted. -Learn more in [this documentation](undefined/docs/learn/fundamentals/data-models/relationships#cascades). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/relationships#cascades/index.html.md). ### Manage One-to-One Relationship @@ -51732,7 +51756,7 @@ const user = await blogModuleService.updateUsers({ }) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/data-models/manage-relationships#manage-one-to-one-relationship). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/manage-relationships#manage-one-to-one-relationship/index.html.md). ### Manage One-to-Many Relationship @@ -51757,7 +51781,7 @@ const product = await blogModuleService.updateProducts({ }) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/data-models/manage-relationships#manage-one-to-many-relationship) +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/manage-relationships#manage-one-to-many-relationship/index.html.md) ### Manage Many-to-Many Relationship @@ -51794,7 +51818,7 @@ const updatedProduct = await blogModuleService.updateProducts({ }) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/data-models/manage-relationships#manage-many-to-many-relationship). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/manage-relationships#manage-many-to-many-relationship/index.html.md). ### Retrieve Related Records @@ -51811,7 +51835,7 @@ const product = await blogModuleService.retrieveProducts( ) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/data-models/manage-relationships#retrieve-records-of-relation). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/manage-relationships#retrieve-records-of-relation/index.html.md). *** @@ -51840,9 +51864,9 @@ export default BlogModuleService The `BlogModuleService` will now have data-management methods for `Post`. -Refer to [this reference](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference) for details on the generated methods. +Refer to [this reference](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/index.html.md) for details on the generated methods. -Learn more about the service factory in [this documentation](undefined/docs/learn/fundamentals/modules/service-factory). +Learn more about the service factory in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/service-factory/index.html.md). ### Resolve Resources in the Service @@ -51899,7 +51923,7 @@ export default class BlogModuleService { } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/modules/container). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/container/index.html.md). ### Access Module Options in Service @@ -51931,7 +51955,7 @@ export default class BlogModuleService extends MedusaService({ } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/modules/options). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/options/index.html.md). ### Run Database Query in Service @@ -51967,7 +51991,7 @@ class BlogModuleService { } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/modules/db-operations#run-queries) +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/db-operations#run-queries/index.html.md) ### Execute Database Operations in Transactions @@ -52024,7 +52048,7 @@ class BlogModuleService { } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/modules/db-operations#execute-operations-in-transactions). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/db-operations#execute-operations-in-transactions/index.html.md). *** @@ -52055,7 +52079,7 @@ export default defineLink( npx medusa db:migrate ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/module-links). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md). ### Define a List Link @@ -52075,7 +52099,7 @@ export default defineLink( ) ``` -Learn more about list links in [this documentation](undefined/docs/learn/fundamentals/module-links#define-a-list-link). +Learn more about list links in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/module-links#define-a-list-link/index.html.md). ### Set Delete Cascade on Link Definition @@ -52095,7 +52119,7 @@ export default defineLink( ) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/module-links#define-a-list-link). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/module-links#define-a-list-link/index.html.md). ### Add Custom Columns to Module Link @@ -52155,7 +52179,7 @@ const { data } = await query.graph({ }) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/module-links/custom-columns). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/module-links/custom-columns/index.html.md). ### Create Link Between Records @@ -52177,7 +52201,7 @@ await link.create({ }) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/module-links/link#create-link). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link#create-link/index.html.md). ### Dismiss Link Between Records @@ -52199,7 +52223,7 @@ await link.dismiss({ }) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/module-links/link#dismiss-link). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link#dismiss-link/index.html.md). ### Cascade Delete Linked Records @@ -52219,7 +52243,7 @@ await link.delete({ }) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/module-links/link#cascade-delete-linked-records). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link#cascade-delete-linked-records/index.html.md). ### Restore Linked Records @@ -52239,7 +52263,7 @@ await link.restore({ }) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/module-links/link#restore-linked-records). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link#restore-linked-records/index.html.md). *** @@ -52275,7 +52299,7 @@ export const GET = async ( } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/module-links/query). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md). ### Retrieve Linked Records of Data Model @@ -52309,7 +52333,7 @@ export const GET = async ( } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/module-links/query#retrieve-linked-records). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query#retrieve-linked-records/index.html.md). ### Apply Filters to Retrieved Records @@ -52345,7 +52369,7 @@ export const GET = async ( } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/module-links/query#apply-filters). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query#apply-filters/index.html.md). ### Apply Pagination and Sort Records @@ -52390,7 +52414,7 @@ export const GET = async ( } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/module-links/query#sort-records). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query#sort-records/index.html.md). *** @@ -52457,7 +52481,7 @@ const myWorkflow = createWorkflow( export default myWorkflow ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/workflows). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). ### Execute a Workflow @@ -52547,7 +52571,7 @@ export const config = { }; ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/workflows#3-execute-the-workflow). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows#3-execute-the-workflow/index.html.md). ### Step with a Compensation Function @@ -52574,7 +52598,7 @@ const step1 = createStep( ) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/workflows/compensation-function). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/compensation-function/index.html.md). ### Manipulate Variables in Workflow @@ -52604,7 +52628,7 @@ const myWorkflow = createWorkflow( ) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/workflows/variable-manipulation) +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/variable-manipulation/index.html.md) ### Using Conditions in Workflow @@ -52671,7 +52695,7 @@ const workflow = createWorkflow( ) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/workflows/execute-another-workflow). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/execute-another-workflow/index.html.md). ### Consume a Workflow Hook @@ -52692,7 +52716,7 @@ createProductsWorkflow.hooks.productsCreated( This executes a custom step at the hook's designated point in the workflow. -Learn more in [this documentation](undefined/docs/learn/fundamentals/workflows/workflow-hooks). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/workflow-hooks/index.html.md). ### Expose a Hook @@ -52723,7 +52747,7 @@ export const myWorkflow = createWorkflow( ) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/workflows/add-workflow-hook). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/add-workflow-hook/index.html.md). ### Retry Steps @@ -52747,7 +52771,7 @@ export const step1 = createStep( ) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/workflows/retry-failed-steps). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/retry-failed-steps/index.html.md). ### Run Steps in Parallel @@ -52788,7 +52812,7 @@ const myWorkflow = createWorkflow( ) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/workflows/parallel-steps). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/parallel-steps/index.html.md). ### Configure Workflow Timeout @@ -52816,7 +52840,7 @@ const myWorkflow = createWorkflow({ export default myWorkflow ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/workflows/workflow-timeout). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/workflow-timeout/index.html.md). ### Configure Step Timeout @@ -52834,7 +52858,7 @@ const step1 = createStep( ) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/workflows/workflow-timeout#configure-step-timeout). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/workflow-timeout#configure-step-timeout/index.html.md). ### Long-Running Workflow @@ -52854,7 +52878,7 @@ const step2 = createStep( ) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/workflows/long-running-workflow). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/long-running-workflow/index.html.md). ### Change Step Status in Long-Running Workflow @@ -52867,7 +52891,7 @@ const { transaction } = await myLongRunningWorkflow(req.scope) .run() ``` -2. In an API route, workflow, or other resource, change a step's status to successful using the [Worfklow Engine Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/workflow-engine): +2. In an API route, workflow, or other resource, change a step's status to successful using the [Worfklow Engine Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/workflow-engine/index.html.md): ```ts highlights={stepSuccessHighlights} const workflowEngineService = container.resolve( @@ -52888,7 +52912,7 @@ await workflowEngineService.setStepSuccess({ }) ``` -3. In an API route, workflow, or other resource, change a step's status to failure using the [Worfklow Engine Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/workflow-engine): +3. In an API route, workflow, or other resource, change a step's status to failure using the [Worfklow Engine Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/workflow-engine/index.html.md): ```ts highlights={stepFailureHighlights} const workflowEngineService = container.resolve( @@ -52909,7 +52933,7 @@ await workflowEngineService.setStepFailure({ }) ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/workflows/long-running-workflow). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/long-running-workflow/index.html.md). ### Access Long-Running Workflow's Result @@ -52955,7 +52979,7 @@ export async function GET(req: MedusaRequest, res: MedusaResponse) { } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/workflows/long-running-workflow#access-long-running-workflow-status-and-result). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/long-running-workflow#access-long-running-workflow-status-and-result/index.html.md). *** @@ -52985,7 +53009,7 @@ export const config: SubscriberConfig = { } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/events-and-subscribers). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md). ### Resolve Resources in Subscriber @@ -53015,7 +53039,7 @@ export const config: SubscriberConfig = { } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/events-and-subscribers#resolve-resources). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers#resolve-resources/index.html.md). ### Send a Notification to Reset Password @@ -53060,7 +53084,7 @@ export const config: SubscriberConfig = { } ``` -Learn more in [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/reset-password). +Learn more in [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/reset-password/index.html.md). ### Execute a Workflow in a Subscriber @@ -53100,7 +53124,7 @@ export const config: SubscriberConfig = { } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/workflows#3-execute-the-workflow) +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows#3-execute-the-workflow/index.html.md) *** @@ -53126,7 +53150,7 @@ export const config = { } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/scheduled-jobs). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs/index.html.md). ### Resolve Resources in Scheduled Job @@ -53155,7 +53179,7 @@ export const config = { } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/scheduled-jobs#resolve-resources) +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs#resolve-resources/index.html.md) ### Specify a Job's Execution Number @@ -53174,7 +53198,7 @@ export const config = { } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/scheduled-jobs/execution-number). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs/execution-number/index.html.md). ### Execute a Workflow in a Scheduled Job @@ -53203,7 +53227,7 @@ export const config = { } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/workflows#3-execute-the-workflow) +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows#3-execute-the-workflow/index.html.md) *** @@ -53225,7 +53249,7 @@ export default async function helloWorldLoader() { } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/modules/loaders). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/loaders/index.html.md). ### Resolve Resources in Loader @@ -53248,7 +53272,7 @@ export default async function helloWorldLoader({ } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/modules/container). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/container/index.html.md). ### Access Module Options @@ -53275,7 +53299,7 @@ export default async function helloWorldLoader({ } ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/modules/options). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/options/index.html.md). ### Register Resources in the Module's Container @@ -53307,7 +53331,7 @@ Where the first parameter of `registerAdd` is the name to register the resource You can customize the Medusa Admin to inject widgets in existing pages, or create new pages using UI routes. -For a list of components to use in the admin dashboard, refere to [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components). +For a list of components to use in the admin dashboard, refere to [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/index.html.md). ### Create Widget @@ -53336,7 +53360,7 @@ export const config = defineWidgetConfig({ export default ProductWidget ``` -Learn more about widgets in [this documentation](undefined/docs/learn/fundamentals/admin/widgets). +Learn more about widgets in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/admin/widgets/index.html.md). ### Receive Details Props in Widgets @@ -53373,7 +53397,7 @@ export const config = defineWidgetConfig({ export default ProductWidget ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/admin/widgets#detail-widget-props). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/admin/widgets#detail-widget-props/index.html.md). ### Create a UI Route @@ -53406,7 +53430,7 @@ export default CustomPage This adds a new page at `localhost:9000/app/custom`. -Learn more in [this documentation](undefined/docs/learn/fundamentals/admin/ui-routes). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md). ### Create Settings Page @@ -53437,7 +53461,7 @@ export default CustomSettingPage This adds a setting page at `localhost:9000/app/settings/custom`. -Learn more in [this documentation](undefined/docs/learn/fundamentals/admin/ui-routes#create-settings-page) +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes#create-settings-page/index.html.md) ### Accept Path Parameters in UI Routes @@ -53466,7 +53490,7 @@ export default CustomPage This creates a UI route at `localhost:9000/app/custom/:id`, where `:id` is a path parameter. -Learn more in [this documentation](undefined/docs/learn/fundamentals/admin/ui-routes#path-parameters) +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes#path-parameters/index.html.md) ### Send Request to API Route @@ -53513,7 +53537,7 @@ export const config = defineWidgetConfig({ export default ProductWidget ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/admin/tips#send-requests-to-api-routes) +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/admin/tips#send-requests-to-api-routes/index.html.md) ### Add Link to Another Page @@ -53541,7 +53565,7 @@ export const config = defineWidgetConfig({ export default ProductWidget ``` -Learn more in [this documentation](undefined/docs/learn/fundamentals/admin/tips#routing-functionalities). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/admin/tips#routing-functionalities/index.html.md). *** @@ -53549,7 +53573,7 @@ Learn more in [this documentation](undefined/docs/learn/fundamentals/admin/tips# Medusa provides a `@medusajs/test-utils` package with utility tools to create integration tests for your custom API routes, modules, or other Medusa customizations. -For details on setting up your project for integration tests, refer to [this documentation](undefined/docs/learn/debugging-and-testing/testing-tools). +For details on setting up your project for integration tests, refer to [this documentation](https://docs.medusajs.com/docs/learn/debugging-and-testing/testing-tools/index.html.md). ### Test Custom API Route @@ -53583,7 +53607,7 @@ Then, run the test with the following command: npm run test:integration ``` -Learn more in [this documentation](undefined/docs/learn/debugging-and-testing/testing-tools/integration-tests/api-routes). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/debugging-and-testing/testing-tools/integration-tests/api-routes/index.html.md). ### Test Workflow @@ -53613,7 +53637,7 @@ Then, run the test with the following command: npm run test:integration ``` -Learn more in [this documentation](undefined/docs/learn/debugging-and-testing/testing-tools/integration-tests/workflows). +Learn more in [this documentation](https://docs.medusajs.com/docs/learn/debugging-and-testing/testing-tools/integration-tests/workflows/index.html.md). ### Test Module's Service @@ -53655,7 +53679,7 @@ npm run test:modules Medusa provides all its commerce features as separate Commerce Modules, such as the Product or Order modules. -Refer to the [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules) documentation for concepts and reference of every module's main service. +Refer to the [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md) documentation for concepts and reference of every module's main service. ### Create an Actor Type to Authenticate @@ -53778,11 +53802,11 @@ export default defineMiddlewares({ Now, manager users can use the `/manager` API route to register, and all routes starting with `/manager/me` are only accessible by authenticated managers. -Find an elaborate example and learn more in [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/create-actor-type). +Find an elaborate example and learn more in [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/create-actor-type/index.html.md). ### Apply Promotion on Cart Items and Shipping -To apply a promotion on a cart's items and shipping methods using the [Cart](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/cart) and [Promotion](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/promotion) modules: +To apply a promotion on a cart's items and shipping methods using the [Cart](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/cart/index.html.md) and [Promotion](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/promotion/index.html.md) modules: ```ts import { @@ -53859,11 +53883,11 @@ await cartModuleService.setShippingMethodAdjustments( ) ``` -Learn more in [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/cart/tax-lines). +Learn more in [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/cart/tax-lines/index.html.md). ### Retrieve Tax Lines of a Cart's Items and Shipping -To retrieve the tax lines of a cart's items and shipping methods using the [Cart](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/cart) and [Tax](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/tax) modules: +To retrieve the tax lines of a cart's items and shipping methods using the [Cart](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/cart/index.html.md) and [Tax](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/tax/index.html.md) modules: ```ts // retrieve the cart @@ -53903,11 +53927,11 @@ await cartModuleService.setLineItemTaxLines( ) ``` -Learn more in [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/cart/tax-lines) +Learn more in [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/cart/tax-lines/index.html.md) ### Apply Promotion on an Order's Items and Shipping -To apply a promotion on an order's items and shipping methods using the [Order](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order) and [Promotion](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/promotion) modules: +To apply a promotion on an order's items and shipping methods using the [Order](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/index.html.md) and [Promotion](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/promotion/index.html.md) modules: ```ts import { @@ -53988,7 +54012,7 @@ await orderModuleService.setOrderShippingMethodAdjustments( ) ``` -Learn more in [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/order/promotion-adjustments) +Learn more in [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/order/promotion-adjustments/index.html.md) ### Accept Payment using Module @@ -54055,11 +54079,11 @@ const payment = ) ``` -Learn more in [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-flow). +Learn more in [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-flow/index.html.md). ### Get Variant's Prices for Region and Currency -To get prices of a product variant for a region and currency using [Query](undefined/docs/learn/fundamentals/module-links/query): +To get prices of a product variant for a region and currency using [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md): ```ts import { QueryContext } from "@medusajs/framework/utils" @@ -54087,11 +54111,11 @@ const { data: products } = await query.graph({ }) ``` -Learn more in [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product/guides/price#retrieve-calculated-price-for-a-context). +Learn more in [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/guides/price#retrieve-calculated-price-for-a-context/index.html.md). ### Get All Variant's Prices -To get all prices of a product variant using [Query](undefined/docs/learn/fundamentals/module-links/query): +To get all prices of a product variant using [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md): ```ts const { data: products } = await query.graph({ @@ -54109,11 +54133,11 @@ const { data: products } = await query.graph({ }) ``` -Learn more in [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product/guides/price). +Learn more in [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/guides/price/index.html.md). ### Get Variant Prices with Taxes -To get a variant's prices with taxes using [Query](undefined/docs/learn/fundamentals/module-links/query) and the [Tax Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/tax) +To get a variant's prices with taxes using [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) and the [Tax Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/tax/index.html.md) ```ts import { @@ -54211,11 +54235,11 @@ products.forEach((product) => { }) ``` -Learn more in [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product/guides/price-with-taxes). +Learn more in [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/guides/price-with-taxes/index.html.md). ### Invite Users -To invite a user using the [User Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/user): +To invite a user using the [User Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/user/index.html.md): ```ts const invite = await userModuleService.createInvites({ @@ -54225,7 +54249,7 @@ const invite = await userModuleService.createInvites({ ### Accept User Invite -To accept an invite and create a user using the [User Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/user): +To accept an invite and create a user using the [User Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/user/index.html.md): ```ts const invite = @@ -54244,13 +54268,13 @@ const user = await userModuleService.createUsers({ # How-to & Tutorials -In this section of the documentation, you'll find how-to guides and tutorials that will help you customize the Medusa server and admin. These guides are useful after you've learned Medusa's main concepts in the [Get Started](undefined/docs/learn) section of the documentation. +In this section of the documentation, you'll find how-to guides and tutorials that will help you customize the Medusa server and admin. These guides are useful after you've learned Medusa's main concepts in the [Get Started](https://docs.medusajs.com/docs/learn/index.html.md) section of the documentation. You can follow these guides to learn how to customize the Medusa server and admin to fit your business requirements. This section of the documentation also includes deployment guides to help you deploy your Medusa server and admin to different platforms. ## Example Snippets -For a quick access to code snippets of the different concepts you learned about, such as API routes and workflows, refer to the [Examples Snippets](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/examples) documentation. +For a quick access to code snippets of the different concepts you learned about, such as API routes and workflows, refer to the [Examples Snippets](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/examples/index.html.md) documentation. *** @@ -54258,16 +54282,16 @@ For a quick access to code snippets of the different concepts you learned about, ## Deployment Guides -Deployment guides are a collection of guides that help you deploy your Medusa server and admin to different platforms. Learn more in the [Deployment Overview](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/deployment) documentation. +Deployment guides are a collection of guides that help you deploy your Medusa server and admin to different platforms. Learn more in the [Deployment Overview](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/deployment/index.html.md) documentation. # Send Abandoned Cart Notifications in Medusa In this tutorial, you will learn how to send notifications to customers who have abandoned their carts. -When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules), which are available out-of-the-box. These features include cart-management capabilities. +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md), which are available out-of-the-box. These features include cart-management capabilities. -Medusa's [Notification Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification) allows you to send notifications to users or customers, such as password reset emails, order confirmation SMS, or other types of notifications. +Medusa's [Notification Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/index.html.md) allows you to send notifications to users or customers, such as password reset emails, order confirmation SMS, or other types of notifications. In this tutorial, you will use the Notification Module to send an email to customers who have abandoned their carts. The email will contain a link to recover the customer's cart, encouraging them to complete their purchase. You will use SendGrid to send the emails, but you can also use other email providers. @@ -54300,15 +54324,15 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You will first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose "Yes." +You will first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose "Yes." Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name and the Next.js Starter Storefront in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterwards, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** @@ -54322,9 +54346,9 @@ Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/for Medusa's Notification Module provides the general functionality to send notifications, but the sending logic is implemented in a module provider. This allows you to integrate the email provider of your choice. -To send the cart-abandonment emails, you will use SendGrid. Medusa provides a [SendGrid Notification Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid) that you can use to send emails. +To send the cart-abandonment emails, you will use SendGrid. Medusa provides a [SendGrid Notification Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid/index.html.md) that you can use to send emails. -Alternatively, you can use [other Notification Module Providers](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification#what-is-a-notification-module-provider) or [create a custom provider](undefined/references/notification-provider-module). +Alternatively, you can use [other Notification Module Providers](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification#what-is-a-notification-module-provider/index.html.md) or [create a custom provider](https://docs.medusajs.com/references/notification-provider-module/index.html.md). To set up SendGrid, add the SendGrid Notification Module Provider to `medusa-config.ts`: @@ -54373,14 +54397,14 @@ You can now use SendGrid to send emails in Medusa. You will now implement the sending logic for the abandoned cart notifications. -To build custom commerce features in Medusa, you create a [workflow](undefined/docs/learn/fundamentals/workflows). A workflow is a series of queries and actions, called steps, that complete a task. You construct a workflow like you construct a function, but it is a special function that allows you to track its executions' progress, define roll-back logic, and configure other advanced features. Then, you execute the workflow from other customizations, such as in a scheduled job. +To build custom commerce features in Medusa, you create a [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). A workflow is a series of queries and actions, called steps, that complete a task. You construct a workflow like you construct a function, but it is a special function that allows you to track its executions' progress, define roll-back logic, and configure other advanced features. Then, you execute the workflow from other customizations, such as in a scheduled job. In this step, you will create the workflow that sends the abandoned cart notifications. Later, you will learn how to execute it once a day. The workflow will receive the list of abandoned carts as an input. The workflow has the following steps: - [sendAbandonedNotificationsStep](#sendAbandonedNotificationsStep): Send the abandoned cart notifications. -- [updateCartsStep](undefined/references/medusa-workflows/steps/updateCartsStep): Update the cart to store the last notification date. +- [updateCartsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateCartsStep/index.html.md): Update the cart to store the last notification date. Medusa provides the second step in its `@medusajs/medusa/core-flows` package. So, you only need to implement the first one. @@ -54446,7 +54470,7 @@ You create a step with `createStep` from the Workflows SDK. It accepts two param 1. The step's unique name, which is `create-review`. 2. An async function that receives two parameters: - The step's input, which is in this case an object with the review's properties. - - An object that has properties including the [Medusa container](undefined/docs/learn/fundamentals/medusa-container), which is a registry of Framework and commerce tools that you can access in the step. + - An object that has properties including the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which is a registry of Framework and commerce tools that you can access in the step. In the step function, you first resolve the Notification Module's service, which has methods to manage notifications. Then, you prepare the data of each notification, and create the notifications with the `createNotifications` method. @@ -54520,7 +54544,7 @@ In the workflow's constructor function, you: - Use the `sendAbandonedNotificationsStep` to send the notifications to the carts' customers. - Use the `updateCartsStep` from Medusa's core flows to update the carts' metadata with the last notification date. -Notice that you use the `transform` function to prepare the `updateCartsStep`'s input. Medusa does not support direct data manipulation in a workflow's constructor function. You can learn more about it in the [Data Manipulation in Workflows documentation](undefined/docs/learn/fundamentals/workflows/variable-manipulation). +Notice that you use the `transform` function to prepare the `updateCartsStep`'s input. Medusa does not support direct data manipulation in a workflow's constructor function. You can learn more about it in the [Data Manipulation in Workflows documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/variable-manipulation/index.html.md). Your workflow is now ready for use. You will learn how to execute it in the next section. @@ -54665,7 +54689,7 @@ ABANDONED_CART_TEMPLATE_ID=your-sendgrid-template-id The next step is to automate sending the abandoned cart notifications. You need a task that runs once a day to find the carts that have been abandoned for a certain period and send the notifications to the customers. -To run a task at a scheduled interval, you can use a [scheduled job](undefined/docs/learn/fundamentals/scheduled-jobs). A scheduled job is an asynchronous function that the Medusa application runs at the interval you specify during the Medusa application's runtime. +To run a task at a scheduled interval, you can use a [scheduled job](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs/index.html.md). A scheduled job is an asynchronous function that the Medusa application runs at the interval you specify during the Medusa application's runtime. You can create a scheduled job in a TypeScript or JavaScript file under the `src/jobs` directory. So, to create the scheduled job that sends the abandoned cart notifications, create the file `src/jobs/send-abandoned-cart-notification.ts` with the following content: @@ -54704,10 +54728,10 @@ export const config = { In a scheduled job's file, you must export: -1. An asynchronous function that holds the job's logic. The function receives the [Medusa container](undefined/docs/learn/fundamentals/medusa-container) as a parameter. +1. An asynchronous function that holds the job's logic. The function receives the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md) as a parameter. 2. A `config` object that specifies the job's name and schedule. The schedule is a [cron expression](https://crontab.guru/) that defines the interval at which the job runs. -In the scheduled job function, so far you resolve the [Logger](undefined/docs/learn/debugging-and-testing/logging) to log messages, and [Query](undefined/docs/learn/fundamentals/module-links/query) to retrieve data across modules. +In the scheduled job function, so far you resolve the [Logger](https://docs.medusajs.com/docs/learn/debugging-and-testing/logging/index.html.md) to log messages, and [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) to retrieve data across modules. You also define a `oneDayAgo` date, which is the date that you will use as the condition of an abandoned cart. In addition, you define variables to paginate the carts. @@ -54796,7 +54820,7 @@ Finally, start the Medusa application with the following command: npm run dev ``` -And in the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter)'s directory (that you installed in the first step), start the storefront with the following command: +And in the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md)'s directory (that you installed in the first step), start the storefront with the following command: ```bash npm2yarn npm run dev @@ -54881,13 +54905,13 @@ Then, either open the link in an abandoned cart email or navigate to `localhost: You have now implemented the logic to send abandoned cart notifications in Medusa. You can implement other customizations with Medusa, such as: -- [Implement Product Reviews](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/how-to-tutorials/tutorials/product-reviews). -- [Implement Wishlist](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/plugins/guides/wishlist). -- [Allow Custom-Item Pricing](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/examples/guides/custom-item-price). +- [Implement Product Reviews](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/how-to-tutorials/tutorials/product-reviews/index.html.md). +- [Implement Wishlist](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/plugins/guides/wishlist/index.html.md). +- [Allow Custom-Item Pricing](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/examples/guides/custom-item-price/index.html.md). -If you are new to Medusa, check out the [main documentation](undefined/docs/learn), where you will get a more in-depth learning of all the concepts you have used in this guide and more. +If you are new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you will get a more in-depth learning of all the concepts you have used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). # Implement Agentic Commerce (ChatGPT Instant Checkout) Specifications @@ -57983,7 +58007,7 @@ If you encounter issues not covered in troubleshooting guides: In this tutorial, you'll learn how to implement first-purchase discounts in Medusa. -When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules), which are available out-of-the-box. These features include promotion and cart management features. +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md), which are available out-of-the-box. These features include promotion and cart management features. The first-purchase discount feature encourages customers to sign up and make their first purchase by offering them a discount. In this tutorial, you'll learn how to implement this feature in Medusa. @@ -58018,15 +58042,15 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -First, you'll be asked for the project's name. Then, when prompted about installing the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose "Yes." +First, you'll be asked for the project's name. Then, when prompted about installing the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose "Yes." Afterward, the installation process will start, which will install the Medusa application in a directory with your project's name and the Next.js Starter Storefront in a separate directory named `{project-name}-storefront`. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterward, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** @@ -58048,7 +58072,7 @@ You can customize the promotion based on your use case. For example, it can be a Make sure to set the promotion's code to `FIRST_PURCHASE`, as you'll be using this code in your Medusa customization. If you want to use a different code, make sure to update the code in the next steps accordingly. -Refer to the [Create Promotions User Guide](undefined/user-guide/promotions/create) to learn how to create promotions in Medusa. +Refer to the [Create Promotions User Guide](https://docs.medusajs.com/user-guide/promotions/create/index.html.md) to learn how to create promotions in Medusa. Once you create and publish the promotion, you can proceed to the next steps. @@ -58062,8 +58086,8 @@ In this step, you'll customize the Medusa application to automatically apply the To build this feature, you need to: -- Create a [workflow](undefined/docs/learn/fundamentals/workflows) that implements the logic to apply the first-purchase promotion to a cart. -- Execute the workflow in a [subscriber](undefined/docs/learn/fundamentals/events-and-subscribers) that is triggered when a cart is created, or when it's transferred to a customer. +- Create a [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) that implements the logic to apply the first-purchase promotion to a cart. +- Execute the workflow in a [subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md) that is triggered when a cart is created, or when it's transferred to a customer. ### a. Store the First-Purchase Promotion Code @@ -58081,13 +58105,13 @@ You'll reference this constant in the next steps. Next, you'll create the workflow that implements the logic to apply the first-purchase promotion to a cart. -A [workflow](undefined/docs/learn/fundamentals/workflows) is a series of actions, called steps, that complete a task with rollback and retry mechanisms. In Medusa, you build commerce features in workflows, then execute them in other customizations, such as subscribers, scheduled jobs, and API routes. +A [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) is a series of actions, called steps, that complete a task with rollback and retry mechanisms. In Medusa, you build commerce features in workflows, then execute them in other customizations, such as subscribers, scheduled jobs, and API routes. The workflow you'll build will have the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the cart's details, including its promotions and customer. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the details of the first-purchase promotion. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the updated cart's details, including its promotions. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the cart's details, including its promotions and customer. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the details of the first-purchase promotion. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the updated cart's details, including its promotions. Medusa provides all these steps in its `@medusajs/medusa/core-flows` package, so you can implement the workflow right away. @@ -58159,17 +58183,17 @@ You create a workflow using `createWorkflow` from the Workflows SDK. It accepts In the workflow's constructor function, you: -- Retrieve the cart's details, including its promotions and customer, using the [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep). +- Retrieve the cart's details, including its promotions and customer, using the [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md). - Retrieve the details of the first-purchase promotion using the `useQueryGraphStep`. - You pass the `FIRST_PURCHASE_PROMOTION_CODE` constant to the `filters` option to retrieve the promotion. -- Use the [when-then](undefined/docs/learn/fundamentals/workflows/conditions) utility to only apply the promotion if the first-purchase promotion exists, the cart doesn't have the promotion, and the customer doesn't have any orders. `when` receives two parameters: +- Use the [when-then](https://docs.medusajs.com/docs/learn/fundamentals/workflows/conditions/index.html.md) utility to only apply the promotion if the first-purchase promotion exists, the cart doesn't have the promotion, and the customer doesn't have any orders. `when` receives two parameters: - An object to use in the condition function. - A condition function that receives the first parameter object and returns a boolean indicating whether to execute the steps in the `then` block. - Retrieve the updated cart's details, including its promotions, using the `useQueryGraphStep` again. Finally, you return a `WorkflowResponse` with the updated cart's details. -You can't perform data manipulation in a workflow's constructor function. Instead, the Workflows SDK includes utility functions like `when` to perform typical operations that require accessing data values. Learn more about workflow constraints in the [Workflow Constraints](undefined/docs/learn/fundamentals/workflows/constructor-constraints) documentation. +You can't perform data manipulation in a workflow's constructor function. Instead, the Workflows SDK includes utility functions like `when` to perform typical operations that require accessing data values. Learn more about workflow constraints in the [Workflow Constraints](https://docs.medusajs.com/docs/learn/fundamentals/workflows/constructor-constraints/index.html.md) documentation. ### c. Create the Subscriber @@ -58177,7 +58201,7 @@ Next, you'll create a subscriber that executes the workflow when a cart is creat A cart can be transferred to a customer when they sign up or log in, or in B2B use cases. -A [subscriber](undefined/docs/learn/fundamentals/events-and-subscribers) is an asynchronous function that listens to events to perform a task. In this case, you'll create a subscriber that listens to the `cart.created` and `cart.customer_transferred` events to execute the workflow. +A [subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md) is an asynchronous function that listens to events to perform a task. In this case, you'll create a subscriber that listens to the `cart.created` and `cart.customer_transferred` events to execute the workflow. To create the subscriber, create the file `src/subscribers/apply-first-purchase.ts` with the following content: @@ -58209,13 +58233,13 @@ A subscriber file must export: 1. An asynchronous function, which is the subscriber that is executed when the event is emitted. 2. A configuration object that holds the names of the events the subscriber listens to, which are `cart.created` and `cart.customer_transferred` in this case. -The subscriber function receives an object as a parameter that has a `container` property, which is the [Medusa container](undefined/docs/learn/fundamentals/medusa-container). The Medusa container holds Framework and commerce tools that you can resolve and use in your customizations. +The subscriber function receives an object as a parameter that has a `container` property, which is the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). The Medusa container holds Framework and commerce tools that you can resolve and use in your customizations. In the subscriber function, you execute the `applyFirstPurchasePromoWorkflow` by invoking it, passing it the Medusa container, then calling its `run` method. You pass the `cart_id` from the event payload as an input to the workflow. ### Test it Out -You can now test the automatic application of the first-purchase promotion to a cart. To do that, you'll use the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter) you installed in the first step. +You can now test the automatic application of the first-purchase promotion to a cart. To do that, you'll use the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) you installed in the first step. The Next.js Starter Storefront was installed in a separate directory from Medusa. The directory's name is `{your-project}-storefront`. @@ -58251,12 +58275,12 @@ You now automatically apply the first-purchase promotion to a cart, but any cust So, you need to add custom validation to ensure that the first-purchase promotion is only used by first-time customers. -In this step, you'll customize Medusa's existing workflows to validate the first-purchase promotion usage. You can do that by consuming the [workflows' hooks](undefined/docs/learn/fundamentals/workflows/workflow-hooks). A workflow hook is a point in a workflow where you can inject custom functionality as a step function. +In this step, you'll customize Medusa's existing workflows to validate the first-purchase promotion usage. You can do that by consuming the [workflows' hooks](https://docs.medusajs.com/docs/learn/fundamentals/workflows/workflow-hooks/index.html.md). A workflow hook is a point in a workflow where you can inject custom functionality as a step function. You'll consume the hooks of the following workflows: -- [updateCartPromotionsWorkflow](undefined/references/medusa-workflows/updateCartPromotionsWorkflow): This workflow is used to add or remove promotions from a cart. You'll check that the customer is a first-time customer before allowing the promotion to be added. -- [completeCartWorkflow](undefined/references/medusa-workflows/completeCartWorkflow): This workflow is used to complete a cart and place an order. You'll validate that the first-purchase promotion is only used by first-time customers before allowing the order to be placed. +- [updateCartPromotionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateCartPromotionsWorkflow/index.html.md): This workflow is used to add or remove promotions from a cart. You'll check that the customer is a first-time customer before allowing the promotion to be added. +- [completeCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/completeCartWorkflow/index.html.md): This workflow is used to complete a cart and place an order. You'll validate that the first-purchase promotion is only used by first-time customers before allowing the order to be placed. ### a. Consume `updateCartPromotionsWorkflow.validate` Hook @@ -58324,7 +58348,7 @@ In the step function, you check if the `FIRST_PURCHASE_PROMOTION_CODE` is being If any of these validations fail, you throw a `MedusaError` with the appropriate error message. This will prevent the promotion from being applied to the cart. -To retrieve the customer's details, you use [Query](undefined/docs/learn/fundamentals/module-links/query). Query allows you to retrieve data across modules in your Medusa application. +To retrieve the customer's details, you use [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md). Query allows you to retrieve data across modules in your Medusa application. ### b. Consume `completeCartWorkflow.validate` Hook @@ -58555,15 +58579,15 @@ If you don't see the pop-up, make sure that you're logged out. ## Next Steps -You've now implemented the first-purchase discount feature in Medusa. You can add more features to build customer loyalty, such as a [loyalty points system](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/how-to-tutorials/tutorials/loyalty-points) or [product reviews](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/how-to-tutorials/tutorials/product-reviews). +You've now implemented the first-purchase discount feature in Medusa. You can add more features to build customer loyalty, such as a [loyalty points system](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/how-to-tutorials/tutorials/loyalty-points/index.html.md) or [product reviews](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/how-to-tutorials/tutorials/product-reviews/index.html.md). -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). ### Troubleshooting -If you encounter issues during your development, check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting). +If you encounter issues during your development, check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/index.html.md). ### Getting Help @@ -58577,7 +58601,7 @@ If you encounter issues not covered in the troubleshooting guides: In this tutorial, you will learn how to add a gift message to items in carts and orders in Medusa. -When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules), which are available out-of-the-box. These features include cart and order management capabilities. +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md), which are available out-of-the-box. These features include cart and order management capabilities. You can customize the Medusa application and storefront to add a gift message to items in the cart. This feature allows customers to add a personalized message to their gifts, enhancing the shopping experience. @@ -58609,15 +58633,15 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -First, you'll be asked for the project's name. Then, when prompted about installing the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose "Yes." +First, you'll be asked for the project's name. Then, when prompted about installing the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose "Yes." Afterward, the installation process will start, which will install the Medusa application in a directory with your project's name and the Next.js Starter Storefront in a separate directory named `{project-name}-storefront`. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterward, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** @@ -58674,7 +58698,7 @@ In `src/modules/cart/components/item/index.tsx`, add the following imports at th import { Checkbox, Textarea, Button, Label } from "@medusajs/ui" ``` -You import components from the [Medusa UI library](undefined/ui) that will be useful for the gift inputs. +You import components from the [Medusa UI library](https://docs.medusajs.com/ui/index.html.md) that will be useful for the gift inputs. Next, in the `Item` component, add the following variables before the `changeQuantity` function: @@ -59077,7 +59101,7 @@ In this step, you'll customize the Medusa Admin dashboard to show the gift items ### What is a Widget? -The Medusa Admin dashboard's pages are customizable to insert [widgets](undefined/docs/learn/fundamentals/admin/widgets) of custom content in predefined injection zones. You create these widgets as React components that allow admin users to perform custom actions. +The Medusa Admin dashboard's pages are customizable to insert [widgets](https://docs.medusajs.com/docs/learn/fundamentals/admin/widgets/index.html.md) of custom content in predefined injection zones. You create these widgets as React components that allow admin users to perform custom actions. So, to show the gift items with their messages in an order, you'll create a custom widget that shows the gift items in the order details page. @@ -59126,7 +59150,7 @@ export default OrderGiftItemsWidget A widget file must export: - A React component that renders the widget content. -- A configuration object created with `defineWidgetConfig` that defines the widget's [injection zone](undefined/admin-widget-injection-zones). +- A configuration object created with `defineWidgetConfig` that defines the widget's [injection zone](https://docs.medusajs.com/admin-widget-injection-zones/index.html.md). You define the `OrderGiftItemsWidget` component that is injected in the `order.details.side.after` zone. Because it's injected in the order details page, it receives the order details as a `data` prop. @@ -59150,7 +59174,7 @@ Go to the Orders page and click on an order that has gift items. You'll find a n ## Optional: Handle Gift Items in Fulfillment Provider -If you have a custom fulfillment provider and you want to handle gift items in it, you can do so in the `createFulfillment` method of the [Fulfillment Module Provider's service](undefined/references/fulfillment/provider). +If you have a custom fulfillment provider and you want to handle gift items in it, you can do so in the `createFulfillment` method of the [Fulfillment Module Provider's service](https://docs.medusajs.com/references/fulfillment/provider/index.html.md). For example: @@ -59186,13 +59210,13 @@ You filter the order items to find the items that are part of the fulfillment an You've now added gift messages to items in carts and orders in Medusa. -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). ### Troubleshooting -If you encounter issues during your development, check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting). +If you encounter issues during your development, check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/index.html.md). ### Getting Help @@ -59206,7 +59230,7 @@ If you encounter issues not covered in the troubleshooting guides: In this tutorial, you will learn how to generate invoices for orders in your Medusa application. -When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules), which are available out-of-the-box. These features include order management capabilities. +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md), which are available out-of-the-box. These features include order management capabilities. You can extend the Medusa application to automatically generate invoices (or sales orders), manage invoice configurations through the admin dashboard, and provide customers with easy access to their invoices through the storefront. @@ -59243,25 +59267,25 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose Yes. +You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose Yes. Afterward, the installation process will start, which will install the Medusa application in a directory with your project's name, and the Next.js Starter Storefront in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterward, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** ## Step 2: Create Invoice Generator Module -In Medusa, you can build custom features in a [module](undefined/docs/learn/fundamentals/modules). A module is a reusable package with the data models and functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. +In Medusa, you can build custom features in a [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). A module is a reusable package with the data models and functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. In this step, you'll build an Invoice Generator Module that defines the data models and logic to manage invoices. Later, you'll build commerce flows related to invoices around the module. -Refer to the [Modules documentation](undefined/docs/learn/fundamentals/modules) to learn more. +Refer to the [Modules documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) to learn more. ### a. Create Module Directory @@ -59271,7 +59295,7 @@ Create the directory `src/modules/invoice-generator` that will hold the Invoice A data model represents a table in the database. You create data models using Medusa's Data Model Language (DML). It simplifies defining a table's columns, relations, and indexes with straightforward methods and configurations. -Refer to the [Data Models documentation](undefined/docs/learn/fundamentals/modules#1-create-data-model) to learn more. +Refer to the [Data Models documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#1-create-data-model/index.html.md) to learn more. For the Invoice Generator Module, you'll create a data model to store default invoice configurations and another to store generated invoices. @@ -59305,7 +59329,7 @@ The `InvoiceConfig` data model has the following properties: You can also add other fields as needed, such as tax information or payment terms. -Learn more about defining data model properties in the [Property Types documentation](undefined/docs/learn/fundamentals/data-models/properties). +Learn more about defining data model properties in the [Property Types documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/properties/index.html.md). #### Invoice Data Model @@ -59346,7 +59370,7 @@ You can manage your module's data models in a service. A service is a TypeScript class that the module exports. In the service's methods, you can connect to the database, allowing you to manage your data models, or connect to a third-party service, which is useful if you're integrating with external services. -Refer to the [Module Service documentation](undefined/docs/learn/fundamentals/modules#2-create-service) to learn more. +Refer to the [Module Service documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#2-create-service/index.html.md) to learn more. To create the Invoice Generator Module's service, create the file `src/modules/invoice-generator/service.ts` with the following content: @@ -59367,7 +59391,7 @@ The `InvoiceGeneratorService` extends `MedusaService`, which generates a class w So, the `InvoiceGeneratorService` class now has methods like `createInvoices` and `retrieveInvoice`. -Find all methods generated by the `MedusaService` in [the Service Factory reference](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference). +Find all methods generated by the `MedusaService` in [the Service Factory reference](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/index.html.md). ### d. Export Module Definition @@ -59414,7 +59438,7 @@ Each object in the `modules` array has a `resolve` property, whose value is eith Since data models represent tables in the database, you define how they're created in the database with migrations. A migration is a TypeScript class that defines database changes made by a module. -Refer to the [Migrations documentation](undefined/docs/learn/fundamentals/modules#5-generate-migrations) to learn more. +Refer to the [Migrations documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#5-generate-migrations/index.html.md) to learn more. Medusa's CLI tool can generate the migrations for you. To generate a migration for the Invoice Generator Module, run the following command in your Medusa application's directory: @@ -59438,7 +59462,7 @@ The tables for the `InvoiceConfig` and `Invoice` data models are now created in In this step, you'll create default invoice configurations that admins can later manage through the Medusa Admin dashboard. -Since you need to create the default configurations when the Medusa application starts, you'll use a [loader](undefined/docs/learn/fundamentals/modules/loaders). A loader is a script in your module that Medusa runs on application startup. +Since you need to create the default configurations when the Medusa application starts, you'll use a [loader](https://docs.medusajs.com/docs/learn/fundamentals/modules/loaders/index.html.md). A loader is a script in your module that Medusa runs on application startup. ### a. Create Loader @@ -59473,7 +59497,7 @@ export default async function createDefaultConfigLoader({ } ``` -The loader function accepts an object having the [module's container](undefined/docs/learn/fundamentals/modules/container) as a parameter. You can use this container to resolve Framework tools and the module's resources. +The loader function accepts an object having the [module's container](https://docs.medusajs.com/docs/learn/fundamentals/modules/container/index.html.md) as a parameter. You can use this container to resolve Framework tools and the module's resources. In the loader, you resolve a service that Medusa generates for the `InvoiceConfig` data model. You use that service to create default configurations if none exist. @@ -59495,7 +59519,7 @@ export default Module(INVOICE_MODULE, { You pass a `loaders` property to the `Module` function, whose value is an array of loader functions. -Refer to the [Loaders](undefined/docs/learn/fundamentals/modules/loaders) documentation to learn more about loaders. +Refer to the [Loaders](https://docs.medusajs.com/docs/learn/fundamentals/modules/loaders/index.html.md) documentation to learn more about loaders. ### c. Run the Loader @@ -59515,15 +59539,15 @@ In this step, you'll customize the Medusa application to allow admin users to ma To build this feature, you need to create: -1. A [workflow](undefined/docs/learn/fundamentals/workflows) with the business logic to manage invoice configurations. -2. An [API route](undefined/docs/learn/fundamentals/api-routes) that exposes the invoice configuration management functionality to clients. -3. A [settings page](undefined/docs/learn/fundamentals/admin/ui-routes#create-settings-page) in the Medusa Admin dashboard that allows admin users to manage the invoice configurations. +1. A [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) with the business logic to manage invoice configurations. +2. An [API route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) that exposes the invoice configuration management functionality to clients. +3. A [settings page](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes#create-settings-page/index.html.md) in the Medusa Admin dashboard that allows admin users to manage the invoice configurations. ### a. Invoice Configuration Management Workflow A workflow is a series of queries and actions, called steps, that complete a task. A workflow is similar to a function, but it allows you to track its executions' progress, define roll-back logic, and configure other advanced features. -Refer to the [Workflows documentation](undefined/docs/learn/fundamentals/workflows) to learn more. +Refer to the [Workflows documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) to learn more. The workflow that manages invoice configurations will have a single step that updates the invoice configuration. @@ -59585,7 +59609,7 @@ You create a step with the `createStep` function. It accepts three parameters: 1. The step's unique name. 2. An async function that receives two parameters: - The step's input, which is an object having the data to update in the invoice configuration. - - An object that has properties including the [Medusa container](undefined/docs/learn/fundamentals/medusa-container), which is a registry of Framework and commerce tools that you can access in the step. + - An object that has properties including the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which is a registry of Framework and commerce tools that you can access in the step. 3. An async compensation function that undoes the actions performed by the step function. This function is only executed if an error occurs during the workflow's execution. In the step function, you resolve the Invoice Generator Module's service from the Medusa container. Then, you either retrieve the invoice configuration by its ID, or list all invoice configurations and use the first one. @@ -59650,7 +59674,7 @@ Next, you'll create two API routes: An API route is created in a `route.ts` file under a sub-directory of the `src/api` directory. The path of the API route is the file's path relative to `src/api`. -Refer to the [API routes](undefined/docs/learn/fundamentals/api-routes) to learn more about them. +Refer to the [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) to learn more about them. Create the file `src/api/admin/invoice-config/route.ts` with the following content: @@ -59676,7 +59700,7 @@ export async function GET( Since you export a `GET` route handler function, you expose a `GET` API route at `/admin/invoice-config`. -In the route handler, you resolve [Query](undefined/docs/learn/fundamentals/module-links/query) from the Medusa container. It allows you to retrieve data across modules. +In the route handler, you resolve [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) from the Medusa container. It allows you to retrieve data across modules. You retrieve the default invoice configuration and return it in the response. @@ -59733,7 +59757,7 @@ You return the updated invoice configuration in the response. #### Add Validation Middleware -To validate the body parameters of requests sent to the API route, you need to apply a [middleware](undefined/docs/learn/fundamentals/api-routes/middlewares). +To validate the body parameters of requests sent to the API route, you need to apply a [middleware](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md). To apply a middleware to a route, create the file `src/api/middlewares.ts` with the following content: @@ -59758,7 +59782,7 @@ You apply Medusa's `validateAndTransformBody` middleware to `POST` requests sent The middleware function accepts a Zod schema, which you created in the API route's file. -Refer to the [Middlewares](undefined/docs/learn/fundamentals/api-routes/middlewares) documentation to learn more. +Refer to the [Middlewares](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md) documentation to learn more. ### c. Create Settings Page @@ -59766,7 +59790,7 @@ Next, you'll create a settings page in the Medusa Admin dashboard that allows ad #### Initialize JS SDK -To send requests to the Medusa server, you'll use the [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk). It's already installed in your Medusa project, but you need to initialize it before using it in your customizations. +To send requests to the Medusa server, you'll use the [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md). It's already installed in your Medusa project, but you need to initialize it before using it in your customizations. Create the file `src/admin/lib/sdk.ts` with the following content: @@ -59782,13 +59806,13 @@ export const sdk = new Medusa({ }) ``` -Learn more about the initialization options in the [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk) reference. +Learn more about the initialization options in the [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md) reference. #### Create Settings Page Component -Settings pages are [UI routes](undefined/docs/learn/fundamentals/admin/ui-routes#create-settings-page) created under the `/src/admin/routes/settings` directory. Medusa will then add the settings page under the Settings section of the Medusa Admin dashboard. +Settings pages are [UI routes](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes#create-settings-page/index.html.md) created under the `/src/admin/routes/settings` directory. Medusa will then add the settings page under the Settings section of the Medusa Admin dashboard. -Refer to the [UI Routes](undefined/docs/learn/fundamentals/admin/ui-routes) documentation to learn more. +Refer to the [UI Routes](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md) documentation to learn more. Create the file `src/admin/routes/settings/invoice-config/page.tsx` with the following content: @@ -59910,7 +59934,7 @@ In the component, you: 3. Define a function that returns the current invoice configuration data, which is useful to create the form. 4. Define a `form` instance with `useForm` from `react-hook-form`. You pass it the Zod validation schema as a type argument, and the default values using the `getFormDefaultValues` function. 5. Define a `handleSubmit` function that updates the invoice configuration using the mutation. -6. Define an `uploadLogo` function that uploads a logo using Medusa's [Upload API route](undefined/api/admin#uploads_postuploads). +6. Define an `uploadLogo` function that uploads a logo using Medusa's [Upload API route](https://docs.medusajs.com/api/admin#uploads_postuploads). 7. Reset the form's default values when the `data` changes, ensuring the form reflects the latest invoice configuration. Finally, replace the `TODO` comment with the following `return` statement: @@ -60040,7 +60064,7 @@ return ( You render the form and its fields. When the form is submitted, you execute the `handleSubmit` function to update the invoice configuration. -Refer to the [Admin Components](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components/components/forms) documentation to learn more about creating forms in the Medusa Admin dashboard. +Refer to the [Admin Components](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/components/forms/index.html.md) documentation to learn more about creating forms in the Medusa Admin dashboard. ### Test Update Invoice Configurations @@ -60655,8 +60679,8 @@ In this step, you'll create a workflow that generates an invoice PDF using the ` The workflow that generates the invoice PDF will have the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve order details -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve countries for billing and shipping addresses +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve order details +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve countries for billing and shipping addresses - [getOrderInvoiceStep](#getOrderInvoiceStep): Retrieve the invoice to generate its PDF. - [generateInvoicePdfStep](#generateInvoicePdfStep): Generate invoice PDF @@ -60877,7 +60901,7 @@ In the workflow, you: 1. Retrieve the order details using `useQueryGraphStep`. 2. Prepare the country codes filter from the billing and shipping addresses. You'll use this filter to retrieve the display names of the countries. - - To manipulate data in a workflow, you need to use the `transform` function. Learn more in the [Data Manipulation](undefined/docs/learn/fundamentals/workflows/variable-manipulation) documentation. + - To manipulate data in a workflow, you need to use the `transform` function. Learn more in the [Data Manipulation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/variable-manipulation/index.html.md) documentation. 3. Retrieve the country details, including the display names, using `useQueryGraphStep`. 4. Transform the order to replace country codes with display names. 5. Retrieve or create the invoice using the `getOrderInvoiceStep`. @@ -60925,7 +60949,7 @@ You export a `GET` route handler function, exposing a `GET` API route at `/admin In the route handler, you execute the `generateInvoicePdfWorkflow` which will return the PDF buffer. -Workflows and steps serialize their output. So, you must recreate the buffer from the serialized output using `Buffer.from`. Learn more in the [Constructor Constraints](undefined/docs/learn/fundamentals/workflows/constructor-constraints#returned-values) documentation. +Workflows and steps serialize their output. So, you must recreate the buffer from the serialized output using `Buffer.from`. Learn more in the [Constructor Constraints](https://docs.medusajs.com/docs/learn/fundamentals/workflows/constructor-constraints#returned-values/index.html.md) documentation. Finally, you set the response headers to indicate that the response is a PDF file and send the buffer as the response body. @@ -60976,7 +61000,7 @@ You'll test out both API routes in the next steps. In this step, you'll create an admin widget that allows admin users to download invoices directly from order detail pages. -A [widget](undefined/docs/learn/fundamentals/admin/widgets) is a React component that is injected into an existing admin page. +A [widget](https://docs.medusajs.com/docs/learn/fundamentals/admin/widgets/index.html.md) is a React component that is injected into an existing admin page. To create the widget, create the file `src/admin/widgets/order-invoice.tsx` with the following content: @@ -61222,7 +61246,7 @@ Then, place an order in the storefront. You'll see the "Download Invoice" button In this step, you'll send an order confirmation email with the invoice PDF attached when an order is placed. -You can listen to events that occur in your Medusa application, such as when an order is placed, using [subscribers](undefined/docs/learn/fundamentals/events-and-subscribers). A subscriber is an asynchronous function that is executed whenever its associated event is emitted. +You can listen to events that occur in your Medusa application, such as when an order is placed, using [subscribers](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md). A subscriber is an asynchronous function that is executed whenever its associated event is emitted. To create a subscriber, create the file `src/subscribers/order-placed.ts` with the following content: @@ -61311,11 +61335,11 @@ In the subscriber, you: - Use Query to retrieve the order details. These details are useful to pass to the notification template. - Generate the invoice PDF using the `generateInvoicePdfWorkflow`. - Convert the PDF buffer to a binary string, which is required for the email attachment. -- Send an email using the [Notification Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification) with the order details and the invoice PDF attached. +- Send an email using the [Notification Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/index.html.md) with the order details and the invoice PDF attached. #### Notification Module Provider to Use -Since the notification's channel is `email`, you need a Notification Module Provider that supports sending emails, such as [SendGrid](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid) or [Resend](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/integrations/guides/resend). +Since the notification's channel is `email`, you need a Notification Module Provider that supports sending emails, such as [SendGrid](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid/index.html.md) or [Resend](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/integrations/guides/resend/index.html.md). After setting up the Notification Module provider, make sure to replace the `template` of the notification with the template ID from the provider: @@ -61502,7 +61526,7 @@ The subscriber will run whenever any of the following events are emitted: In the subscriber, you execute the `markInvoicesStaleWorkflow` to mark the order's invoices as stale whenever an order is updated. -Refer to the [Events Reference](undefined/references/events) for a complete list of events that Medusa emits. +Refer to the [Events Reference](https://docs.medusajs.com/references/events/index.html.md) for a complete list of events that Medusa emits. ### Test Order Updates @@ -61528,13 +61552,13 @@ You've successfully implemented the invoice generator feature in Medusa. You can ### Learn More about Medusa -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). ### Troubleshooting -If you encounter issues during your development, check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting). +If you encounter issues during your development, check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/index.html.md). ### Getting Help @@ -61548,9 +61572,9 @@ If you encounter issues not covered in the troubleshooting guides: In this tutorial, you'll learn how to implement a loyalty points system in Medusa. -Cloud provides a beta Loyalty Plugin feature that facilitates building a loyalty point system. Refer to the [Cloud Loyalty Plugin](undefined/cloud/loyalty-plugin) documentation to learn more. +Cloud provides a beta Loyalty Plugin feature that facilitates building a loyalty point system. Refer to the [Cloud Loyalty Plugin](https://docs.medusajs.com/cloud/loyalty-plugin/index.html.md) documentation to learn more. -When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules), which are available out-of-the-box. These features include management capabilities related to carts, orders, promotions, and more. +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md), which are available out-of-the-box. These features include management capabilities related to carts, orders, promotions, and more. A loyalty point system allows customers to earn points for purchases, which can be redeemed for discounts or rewards. In this tutorial, you'll learn how to customize the Medusa application to implement a loyalty points system. @@ -61587,27 +61611,27 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose Yes. +You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose Yes. Afterward, the installation process will start, which will install the Medusa application in a directory with your project's name, and the Next.js Starter Storefront in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterward, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** ## Step 2: Create Loyalty Module -In Medusa, you can build custom features in a [module](undefined/docs/learn/fundamentals/modules). A module is a reusable package with functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. +In Medusa, you can build custom features in a [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). A module is a reusable package with functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. In the module, you define the data models necessary for a feature and the logic to manage these data models. Later, you can build commerce flows around your module. In this step, you'll build a Loyalty Module that defines the necessary data models to store and manage loyalty points for customers. -Refer to the [Modules documentation](undefined/docs/learn/fundamentals/modules) to learn more. +Refer to the [Modules documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) to learn more. ### Create Module Directory @@ -61617,7 +61641,7 @@ Modules are created under the `src/modules` directory of your Medusa application A data model represents a table in the database. You create data models using Medusa's Data Model Language (DML). It simplifies defining a table's columns, relations, and indexes with straightforward methods and configurations. -Refer to the [Data Models documentation](undefined/docs/learn/fundamentals/modules#1-create-data-model) to learn more. +Refer to the [Data Models documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#1-create-data-model/index.html.md) to learn more. For the Loyalty Module, you need to define a `LoyaltyPoint` data model that represents a customer's loyalty points. So, create the file `src/modules/loyalty/models/loyalty-point.ts` with the following content: @@ -61641,7 +61665,7 @@ The `LoyaltyPoint` data model has the following properties: - `points`: The number of loyalty points a customer has. - `customer_id`: The ID of the customer who owns the loyalty points. This property has a unique index to ensure that each customer has only one record in the `loyalty_point` table. -Learn more about defining data model properties in the [Property Types documentation](undefined/docs/learn/fundamentals/data-models/properties). +Learn more about defining data model properties in the [Property Types documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/properties/index.html.md). ### Create Module's Service @@ -61649,7 +61673,7 @@ You now have the necessary data model in the Loyalty Module, but you'll need to A service is a TypeScript or JavaScript class that the module exports. In the service's methods, you can connect to the database, allowing you to manage your data models, or connect to a third-party service, which is useful if you're integrating with external services. -Refer to the [Module Service documentation](undefined/docs/learn/fundamentals/modules#2-create-service) to learn more. +Refer to the [Module Service documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#2-create-service/index.html.md) to learn more. To create the Loyalty Module's service, create the file `src/modules/loyalty/service.ts` with the following content: @@ -61673,7 +61697,7 @@ The `LoyaltyModuleService` extends `MedusaService` from the Modules SDK which ge So, the `LoyaltyModuleService` class now has methods like `createLoyaltyPoints` and `retrieveLoyaltyPoint`. -Find all methods generated by the `MedusaService` in [the Service Factory reference](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference). +Find all methods generated by the `MedusaService` in [the Service Factory reference](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/index.html.md). #### Add Methods to the Service @@ -61847,7 +61871,7 @@ Each object in the `modules` array has a `resolve` property, whose value is eith Since data models represent tables in the database, you define how they're created in the database with migrations. A migration is a TypeScript or JavaScript file that defines database changes made by a module. -Refer to the [Migrations documentation](undefined/docs/learn/fundamentals/modules#5-generate-migrations) to learn more. +Refer to the [Migrations documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#5-generate-migrations/index.html.md) to learn more. Medusa's CLI tool can generate the migrations for you. To generate a migration for the Loyalty Module, run the following command in your Medusa application's directory: @@ -61873,15 +61897,15 @@ Now that you have a module that stores and manages loyalty points in the databas The first flow you'll build will either add points to a customer's loyalty points or deduct them based on a purchased order. If the customer hasn't redeemed points, the points are added to their loyalty points. Otherwise, the points are deducted from their loyalty points. -To build custom commerce features in Medusa, you create a [workflow](undefined/docs/learn/fundamentals/workflows). A workflow is a series of queries and actions, called steps, that complete a task. You construct a workflow like you construct a function, but it's a special function that allows you to track its executions' progress, define roll-back logic, and configure other advanced features. Then, you execute the workflow from other customizations, such as in an endpoint. +To build custom commerce features in Medusa, you create a [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). A workflow is a series of queries and actions, called steps, that complete a task. You construct a workflow like you construct a function, but it's a special function that allows you to track its executions' progress, define roll-back logic, and configure other advanced features. Then, you execute the workflow from other customizations, such as in an endpoint. In this section, you'll build the workflow that adds or deducts loyalty points for an order's customer. Later, you'll execute this workflow when an order is placed. -Learn more about workflows in the [Workflows documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in the [Workflows documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). The workflow will have the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the order's details. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the order's details. - [validateCustomerExistsStep](#validateCustomerExistsStep): Validate that the customer is registered. - [getCartLoyaltyPromoStep](#getCartLoyaltyPromoStep): Retrieve the cart's loyalty promotion. @@ -61927,7 +61951,7 @@ You create a step with `createStep` from the Workflows SDK. It accepts two param 1. The step's unique name, which is `validate-customer-exists`. 2. An async function that receives two parameters: - The step's input, which is in this case an object with the customer's details. - - An object that has properties including the [Medusa container](undefined/docs/learn/fundamentals/medusa-container), which is a registry of Framework and commerce tools that you can access in the step. + - An object that has properties including the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which is a registry of Framework and commerce tools that you can access in the step. In the step function, you validate that the customer is defined and that it's registered based on its `has_account` property. Otherwise, you throw an error. @@ -62090,7 +62114,7 @@ The compensation function undoes the actions performed in a step. Then, if an er The compensation function accepts two parameters: 1. Data passed from the step function to the compensation function. The data is passed as a second parameter of the returned `StepResponse` instance. -2. An object that has properties including the [Medusa container](undefined/docs/learn/fundamentals/medusa-container). +2. An object that has properties including the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). In the compensation function, you resolve the Loyalty Module's service from the Medusa container. Then, you call the `addPoints` method to restore the points deducted from the customer's loyalty points if an error occurs. @@ -62297,7 +62321,7 @@ It accepts as a second parameter a constructor function, which is the workflow's In the workflow's constructor function, you: - Use `useQueryGraphStep` to retrieve the order's details. You pass the order's ID as a filter to retrieve the order. - - This step uses [Query](undefined/docs/learn/fundamentals/module-links/query), which is a tool that retrieves data across modules. + - This step uses [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), which is a tool that retrieves data across modules. - Validate that the customer is registered using the `validateCustomerExistsStep`. - Retrieve the cart's loyalty promotion using the `getCartLoyaltyPromoStep`. - Use `when` to check whether the order's cart has a loyalty promotion. @@ -62310,7 +62334,7 @@ In the workflow's constructor function, you: You'll use this workflow next when an order is placed. -To learn more about the constraints on a workflow's constructor function, refer to the [Workflow Constraints](undefined/docs/learn/fundamentals/workflows/constructor-constraints) documentation. Refer to the [When-Then](undefined/docs/learn/fundamentals/workflows/conditions) documentation to learn more about the `when` method and how to use it in a workflow. +To learn more about the constraints on a workflow's constructor function, refer to the [Workflow Constraints](https://docs.medusajs.com/docs/learn/fundamentals/workflows/constructor-constraints/index.html.md) documentation. Refer to the [When-Then](https://docs.medusajs.com/docs/learn/fundamentals/workflows/conditions/index.html.md) documentation to learn more about the `when` method and how to use it in a workflow. *** @@ -62318,11 +62342,11 @@ To learn more about the constraints on a workflow's constructor function, refer Now that you have the workflow that handles adding or deducting loyalty points for an order, you need to execute it when an order is placed. -Medusa has an event system that allows you to listen to events emitted by the Medusa server using a [subscriber](undefined/docs//learn/fundamentals/events-and-subscribers). A subscriber is an asynchronous function that's executed when its associated event is emitted. In a subscriber, you can execute a workflow that performs actions in result of the event. +Medusa has an event system that allows you to listen to events emitted by the Medusa server using a [subscriber](https://docs.medusajs.com/docs//learn/fundamentals/events-and-subscribers/index.html.md). A subscriber is an asynchronous function that's executed when its associated event is emitted. In a subscriber, you can execute a workflow that performs actions in result of the event. In this step, you'll create a subscriber that listens to the `order.placed` event and executes the `handleOrderPointsWorkflow` workflow. -Refer to the [Events and Subscribers](undefined/docs/learn/fundamentals/events-and-subscribers) documentation to learn more. +Refer to the [Events and Subscribers](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md) documentation to learn more. Subscribers are created in a TypeScript or JavaScript file under the `src/subscribers` directory. So, to create a subscriber, create the fle `src/subscribers/order-placed.ts` with the following content: @@ -62365,7 +62389,7 @@ Whenever an order is placed now, the subscriber will be executed, which in turn ### Test it Out -To test out the loyalty points flow, you'll use the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter) that you installed in the first step. As mentioned in that step, the storefront will be installed in a separate directory from the Medusa application, and its name is `{project-name}-storefront`, where `{project-name}` is the name of your Medusa application's directory. +To test out the loyalty points flow, you'll use the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) that you installed in the first step. As mentioned in that step, the storefront will be installed in a separate directory from the Medusa application, and its name is `{project-name}-storefront`, where `{project-name}` is the name of your Medusa application's directory. So, run the following command in the Medusa application's directory to start the Medusa server: @@ -62401,11 +62425,11 @@ Since you didn't redeem any points during checkout, loyalty points will be added Next, you want to allow customers to view their loyalty points. You can show them on their profile page, or during checkout. -To expose a feature to clients, you create an [API route](undefined/docs/learn/fundamentals/api-routes). An API Route is an endpoint that exposes commerce features to external applications and clients, such as storefronts. +To expose a feature to clients, you create an [API route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). An API Route is an endpoint that exposes commerce features to external applications and clients, such as storefronts. You'll create an API route at the path `/store/customers/me/loyalty-points` that returns the loyalty points of the authenticated customer. -Learn more about API routes in [this documentation](undefined/docs/learn/fundamentals/api-routes). +Learn more about API routes in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). An API route is created in a `route.ts` file under a sub-directory of the `src/api` directory. The path of the API route is the file's path relative to `src/api`. @@ -62603,14 +62627,14 @@ The next feature you'll implement allows the customer to apply their loyalty poi The workflow will have the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the cart's details. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the cart's details. - [validateCustomerExistsStep](#validateCustomerExistsStep): Validate that the customer is registered. - [getCartLoyaltyPromoStep](#getCartLoyaltyPromoStep): Retrieve the cart's loyalty promotion. - [getCartLoyaltyPromoAmountStep](#getCartLoyaltyPromoAmountStep): Get the amount to be discounted based on the loyalty points. -- [createPromotionsStep](undefined/references/medusa-workflows/steps/createPromotionsStep): Create a new loyalty promotion for the cart. -- [updateCartPromotionsWorkflow](undefined/references/medusa-workflows/updateCartPromotionsWorkflow): Update the cart's promotions with the new loyalty promotion. -- [updateCartsStep](undefined/references/medusa-workflows/steps/updateCartsStep): Update the cart to store the ID of the loyalty promotion in the metadata. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the cart's details again. +- [createPromotionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/createPromotionsStep/index.html.md): Create a new loyalty promotion for the cart. +- [updateCartPromotionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateCartPromotionsWorkflow/index.html.md): Update the cart's promotions with the new loyalty promotion. +- [updateCartsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateCartsStep/index.html.md): Update the cart to store the ID of the loyalty promotion in the metadata. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the cart's details again. Most of the workflow's steps are either provided by Medusa in the `@medusajs/medusa/core-flows` package or steps you've already implemented. You only need to implement the `getCartLoyaltyPromoAmountStep` step. @@ -62807,7 +62831,7 @@ const promoToCreate = transform({ // TODO create promotion and apply it on cart ``` -Since data manipulation isn't allowed in a workflow constructor, you use the [transform](undefined/docs/learn/fundamentals/workflows/variable-manipulation) function from the Workflows SDK. It accepts two parameters: +Since data manipulation isn't allowed in a workflow constructor, you use the [transform](https://docs.medusajs.com/docs/learn/fundamentals/workflows/variable-manipulation/index.html.md) function from the Workflows SDK. It accepts two parameters: - The data to perform manipulation on. In this case, you pass the cart's details and the amount to be discounted. - A function that receives the data from the first parameter, and returns the transformed data. @@ -62818,7 +62842,7 @@ In the transformation function, you prepare th data of the loyalty promotion to - You add a rule to the promotion that ensures it can be used only in carts having their `customer_id` equal to this customer's ID. This prevents other customers from using this promotion. - You create a campaign for the promotion, and you set the campaign budget to a single usage. This prevents the customer from using the promotion again. -Learn more about promotion concepts in the [Promotion Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/promotion)'s documentation. +Learn more about promotion concepts in the [Promotion Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/promotion/index.html.md)'s documentation. You can now use the returned data to create a promotion and apply it to the cart. Replace the new `TODO` with the following: @@ -63001,12 +63025,12 @@ To implement this functionality, you'll need to: The workflow will have the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the cart's details. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the cart's details. - [getCartLoyaltyPromoStep](#getCartLoyaltyPromoStep): Retrieve the cart's loyalty promotion. -- [updateCartPromotionsWorkflow](undefined/references/medusa-workflows/updateCartPromotionsWorkflow): Update the cart's promotions to remove the loyalty promotion. -- [updateCartsStep](undefined/references/medusa-workflows/steps/updateCartsStep): Update the cart to remove the loyalty promotion ID from the metadata. -- [updatePromotionsStep](undefined/references/medusa-workflows/steps/updatePromotionsStep): Deactive the loyalty promotion. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the cart's details again. +- [updateCartPromotionsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateCartPromotionsWorkflow/index.html.md): Update the cart's promotions to remove the loyalty promotion. +- [updateCartsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updateCartsStep/index.html.md): Update the cart to remove the loyalty promotion ID from the metadata. +- [updatePromotionsStep](https://docs.medusajs.com/references/medusa-workflows/steps/updatePromotionsStep/index.html.md): Deactive the loyalty promotion. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the cart's details again. Since you already have all the steps, you can create the workflow. @@ -63223,9 +63247,9 @@ After the customer applies the loyalty points to the cart and places the order, So, in this step, you'll hook into Medusa's cart completion flow to perform the validation. -Since Medusa uses workflows in its API routes, it allows you to hook into them and perform custom functionalities using [Workflow Hooks](undefined/docs/learn/fundamentals/workflows/workflow-hooks). A workflow hook is a point in a workflow where you can inject custom functionality as a step function, called a hook handler. +Since Medusa uses workflows in its API routes, it allows you to hook into them and perform custom functionalities using [Workflow Hooks](https://docs.medusajs.com/docs/learn/fundamentals/workflows/workflow-hooks/index.html.md). A workflow hook is a point in a workflow where you can inject custom functionality as a step function, called a hook handler. -Medusa uses the [completeCartWorkflow](undefined/references/medusa-workflows/completeCartWorkflow) hook to complete the cart and place an order. This workflow has a `validate` hook that allows you to perform custom validation before the cart is completed. +Medusa uses the [completeCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/completeCartWorkflow/index.html.md) hook to complete the cart and place an order. This workflow has a `validate` hook that allows you to perform custom validation before the cart is completed. To consume the `validate` hook, create the file `src/workflows/hooks/complete-cart.ts` with the following content: @@ -63321,20 +63345,20 @@ You can confirm that the loyalty points were deducted either by sending a reques You've now implement a loyalty points system in Medusa. There's still more that you can implement based on your use case: -- Add loyalty points on registration or other events. Refer to the [Events Reference](undefined/references/events) for a full list of available events you can listen to. +- Add loyalty points on registration or other events. Refer to the [Events Reference](https://docs.medusajs.com/references/events/index.html.md) for a full list of available events you can listen to. - Show the customer their loyalty point usage history. This will require adding another data model in the Loyalty Module that records the usage history. You can create records of that data model when an order that has a loyalty promotion is placed, then customize the storefront to show a new page for loyalty points history. -- Customize the Medusa Admin to show a new page or [UI Route](undefined/docs/learn/fundamentals/admin/ui-routes) for loyalty points information and analytics. +- Customize the Medusa Admin to show a new page or [UI Route](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md) for loyalty points information and analytics. -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). # Implement Phone Authentication and Integrate Twilio SMS In this tutorial, you will learn how to implement phone number authentication in your Medusa application. -When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules), which are available out-of-the-box. These features include authentication with custom providers and for custom user or actor types. +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md), which are available out-of-the-box. These features include authentication with custom providers and for custom user or actor types. In this tutorial, you'll learn how to implement a custom authentication provider that allows customers to log in with their phone number. You'll also integrate [Twilio](https://www.twilio.com/en-us/messaging/channels/sms) to send SMS messages to those customers with the one-time password (OTP) for authentication. @@ -63374,25 +63398,25 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose Yes. +You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose Yes. Afterward, the installation process will start, which will install the Medusa application in a directory with your project's name, and the Next.js Starter Storefront in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterward, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** ## Step 2: Implement Phone Authentication Module Provider -In Medusa, you integrate custom authentication providers by creating an [Authentication Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/auth-providers). Then, you can use that provider to authenticate users using custom logic. +In Medusa, you integrate custom authentication providers by creating an [Authentication Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/auth-providers/index.html.md). Then, you can use that provider to authenticate users using custom logic. In this step, you'll create a Phone Authentication Module Provider that allows users to log in with their phone numbers and an OTP. Later, you'll integrate Twilio to send the OTPs to the users, and customize the storefront to allow customers to log in with their phone numbers. -An Authentication Module Provider doesn't need to handle storing and managing specific user details, such as creating customers or admin users. Instead, it only focuses on the logic of authenticating a type of user using custom logic or integration. You can learn more in the [Auth Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth) documentation. +An Authentication Module Provider doesn't need to handle storing and managing specific user details, such as creating customers or admin users. Instead, it only focuses on the logic of authenticating a type of user using custom logic or integration. You can learn more in the [Auth Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/index.html.md) documentation. ### Prerequisite: Install jsonwebtoken @@ -63462,9 +63486,9 @@ An Authentication Module Provider must also have the following static properties A module provider's constructor receives two parameters: -- `container`: The [module's container](undefined/docs/learn/fundamentals/modules/container) that contains Framework resources available to the module. You access the following resources: - - `logger`: A [Logger](undefined/docs/learn/debugging-and-testing/logging) class to log debug messages. - - `event_bus`: The [Event Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/event)'s service to emit events. +- `container`: The [module's container](https://docs.medusajs.com/docs/learn/fundamentals/modules/container/index.html.md) that contains Framework resources available to the module. You access the following resources: + - `logger`: A [Logger](https://docs.medusajs.com/docs/learn/debugging-and-testing/logging/index.html.md) class to log debug messages. + - `event_bus`: The [Event Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/event/index.html.md)'s service to emit events. - `options`: Options that are passed to the module provider when it's registered in Medusa's configurations. You define the following option: - `jwtSecret`: A secret used to sign and verify the OTPs. @@ -63474,7 +63498,7 @@ In the constructor, you set the class's properties to the injected dependencies In the next sections, you'll implement the methods of the `AbstractAuthModuleProvider` class. -Refer to the [Create Auth Module Provider](undefined/references/auth/provider) guide for detailed information about the methods. +Refer to the [Create Auth Module Provider](https://docs.medusajs.com/references/auth/provider/index.html.md) guide for detailed information about the methods. ### c. Implement validateOptions Method @@ -63507,11 +63531,11 @@ In the method, you throw an error if the `jwtSecret` option is not set. ### d. Implement register Method -When a customer (or another actor type) registers in your application, they must also have an [auth identity](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types) that allows them to login. +When a customer (or another actor type) registers in your application, they must also have an [auth identity](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types/index.html.md) that allows them to login. The `register` method of an auth provider uses custom logic to create the auth identity for the actor type (such as customer). In the method, you can perform custom validation and specify the custom authentication details to store for the user's auth identity. -Medusa uses the `register` method to create an auth identity that will be associated with the customer when they register. You can learn more in the [Authentication Flows](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/auth-flows) documentation. +Medusa uses the `register` method to create an auth identity that will be associated with the customer when they register. You can learn more in the [Authentication Flows](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/auth-flows/index.html.md) documentation. ![Diagram showcasing the relation between a customer and auth identity](https://res.cloudinary.com/dza7lstvk/image/upload/v1747747179/Medusa%20Resources/customer-auth-identity_je1bvh.jpg) @@ -63568,9 +63592,9 @@ class PhoneAuthService extends AbstractAuthModuleProvider { The `register` method receives an object parameter with the following properties: - `data`: An object containing properties like `body` that holds request-body parameters. Clients will pass relevant authentication data, such as the user's phone number, in the request body. -- `authIdentityProviderService`: A service injected by the [Auth Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth) that allows you to manage auth identities. +- `authIdentityProviderService`: A service injected by the [Auth Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/index.html.md) that allows you to manage auth identities. -The method receives other parameters, which you can find in the [Create Auth Module Provider](undefined/references/auth/provider#register) guide. +The method receives other parameters, which you can find in the [Create Auth Module Provider](https://docs.medusajs.com/references/auth/provider#register/index.html.md) guide. #### Method Logic @@ -63679,9 +63703,9 @@ You add two methods: the `authenticate` method, and a helper `generateOTP` metho The `authenticate` method receives an object parameter with the following properties: - `data`: An object containing properties like `body` that holds request-body parameters. Clients will pass relevant authentication data, such as the user's phone number, in the request body. -- `authIdentityProviderService`: A service injected by the [Auth Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth) that allows you to manage auth identities. +- `authIdentityProviderService`: A service injected by the [Auth Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/index.html.md) that allows you to manage auth identities. -The method receives other parameters, which you can find in the [Create Auth Module Provider](undefined/references/auth/provider#authenticate) guide. +The method receives other parameters, which you can find in the [Create Auth Module Provider](https://docs.medusajs.com/references/auth/provider#authenticate/index.html.md) guide. #### authenticate Logic @@ -63782,9 +63806,9 @@ class PhoneAuthService extends AbstractAuthModuleProvider { The `validateCallback` method receives an object parameter with the following properties: - `data`: An object containing properties like `query` that holds query parameters. Clients will pass relevant authentication data, such as the user's phone number and OTP, in the request query. -- `authIdentityProviderService`: A service injected by the [Auth Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth) that allows you to manage auth identities. +- `authIdentityProviderService`: A service injected by the [Auth Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/index.html.md) that allows you to manage auth identities. -The method receives other parameters, which you can find in the [Create Auth Module Provider](undefined/references/auth/provider#validatecallback) guide. +The method receives other parameters, which you can find in the [Create Auth Module Provider](https://docs.medusajs.com/references/auth/provider#validatecallback/index.html.md) guide. #### Method Logic @@ -63872,7 +63896,7 @@ module.exports = defineConfig({ To pass an Auth Module Provider to the Auth Module, you add the `modules` property to the Medusa configuration and pass the Auth Module in its value. -The Auth Module accepts a `dependencies` option, allowing you to inject dependencies into the containers of the module and its providers. The Auth Module requires passing the [Cache Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/cache) and Logger, but you also inject the `event_bus` dependency to use the Event Module's service in the Phone Authentication Module Provider. +The Auth Module accepts a `dependencies` option, allowing you to inject dependencies into the containers of the module and its providers. The Auth Module requires passing the [Cache Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/cache/index.html.md) and Logger, but you also inject the `event_bus` dependency to use the Event Module's service in the Phone Authentication Module Provider. The Auth Module also accepts a `providers` option, which is an array of Auth Module Providers to register. You register the `emailpass` provider, which is registered by default when you don't provide any other providers. @@ -63957,7 +63981,7 @@ This will return a `token` in the response: #### b. Register Customer -Next, you'll register the customer using the [Register Customer](undefined/api/store#customers_postcustomers) API route. You'll pass the registration token you received in the previous step in the header of this request. +Next, you'll register the customer using the [Register Customer](https://docs.medusajs.com/api/store#customers_postcustomers) API route. You'll pass the registration token you received in the previous step in the header of this request. So, send a `POST` request to `/store/customers`: @@ -63979,7 +64003,7 @@ Make sure to replace: - `{publishable_api_key}` with the publishable API key you retrieved from the Medusa Admin dashboard. - `{reg_token}` with the registration token you received in the previous step. - The customer details in the request body with the ones you want to use. Use the same phone number you used in the previous step. - - You pass the email because it's required by the [Register Customer](undefined/api/store#customers_postcustomers) API route. You set it to the phone number with a `gmail.com` domain. + - You pass the email because it's required by the [Register Customer](https://docs.medusajs.com/api/store#customers_postcustomers) API route. You set it to the phone number with a `gmail.com` domain. The request will return the created customer's details: @@ -64006,7 +64030,7 @@ The customer can now authenticate using the phone number and OTP. #### c. Authenticate Customer -Next, you'll authenticate the customer using the [Authenticate Customer](undefined/api/store#auth_postactor_typeauth_provider) API route. This would send the customer an OTP to their phone number (which you'll implement in the next step). +Next, you'll authenticate the customer using the [Authenticate Customer](https://docs.medusajs.com/api/store#auth_postactor_typeauth_provider) API route. This would send the customer an OTP to their phone number (which you'll implement in the next step). So, send a `POST` request to `/auth/customer/phone-auth`: @@ -64042,7 +64066,7 @@ info: Generated OTP: 576794 As mentioned before, this is only for debugging purposes. In the next step, you'll implement the logic to send the OTP to the user using Twilio. -So, to verify the OTP, you'll send a request to the [Verify Callback API route](undefined/api/store#auth_postactor_typeauth_providercallback): +So, to verify the OTP, you'll send a request to the [Verify Callback API route](https://docs.medusajs.com/api/store#auth_postactor_typeauth_providercallback): ```bash curl -X POST 'http://localhost:9000/auth/customer/phone-auth/callback?phone=%2B19077890116&otp=476588' @@ -64061,7 +64085,7 @@ If the OTP is valid, you'll receive a JWT token in the response: } ``` -You can use this token to authenticate the customer in the application. For example, you can use the token to [retrieve the customer's details](undefined/api/store#customers_getcustomersme). +You can use this token to authenticate the customer in the application. For example, you can use the token to [retrieve the customer's details](https://docs.medusajs.com/api/store#customers_getcustomersme). If the OTP has expired, send a request to the [Authenticate Customer](#c-authenticate-customer) API route to generate a new OTP @@ -64069,7 +64093,7 @@ If the OTP has expired, send a request to the [Authenticate Customer](#c-authent ## Step 3: Integrate Twilio SMS -Similar to the Auth Module, the [Notification Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification) allows registering custom providers to send notifications, such as SMS or email. +Similar to the Auth Module, the [Notification Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/index.html.md) allows registering custom providers to send notifications, such as SMS or email. In this step, you'll create a Twilio Notification Module Provider, then use it to send the OTP to the customer. @@ -64136,7 +64160,7 @@ A Notification Module Provider must have an `identifier` static property, which A module provider's constructor receives two parameters: -- `container`: The [module's container](undefined/docs/learn/fundamentals/modules/container) that contains Framework resources available to the module. You don't need to access any resources for this provider. +- `container`: The [module's container](https://docs.medusajs.com/docs/learn/fundamentals/modules/container/index.html.md) that contains Framework resources available to the module. You don't need to access any resources for this provider. - `options`: Options that are passed to the module provider when it's registered in Medusa's configurations. You define the following option: - `accountSid`: The Twilio account SID. - `authToken`: The Twilio auth token. @@ -64148,7 +64172,7 @@ In the constructor, you set the class's properties to the injected dependencies In the next sections, you'll implement the methods of the `AbstractNotificationProviderService` class. -Refer to the [Create Notification Module Provider](undefined/references/notification-provider-module) guide for detailed information about the methods. +Refer to the [Create Notification Module Provider](https://docs.medusajs.com/references/notification-provider-module/index.html.md) guide for detailed information about the methods. ### d. Implement validateOptions Method @@ -64240,7 +64264,7 @@ The `send` method receives an object parameter with the following properties: - `template`: The template to use for the SMS. This is used to retrieve the fallback content of the SMS if `content.text` is not provided. - `data`: An object containing the data to use in the template. This is used to replace placeholders in the template with actual values. -The method receives other parameters, which you can find in the [Create Notification Module Provider](undefined/references/notification-provider-module#send) guide. +The method receives other parameters, which you can find in the [Create Notification Module Provider](https://docs.medusajs.com/references/notification-provider-module#send/index.html.md) guide. #### send Method Logic @@ -64358,11 +64382,11 @@ You can retrieve these information from the Twilio Console homepage. Now that you have integrated Twilio into Medusa, you can use it to send the OTP to the customer. To do that, you need to handle the `phone-auth.otp.generated` event that you emitted in the `authenticate` method of the Phone Authentication Module Provider. -You can listen to events in a [subscriber](undefined/docs/learn/fundamentals/events-and-subscribers). A subscriber is an asynchronous function that listens to events to perform actions when the event is emitted. +You can listen to events in a [subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md). A subscriber is an asynchronous function that listens to events to perform actions when the event is emitted. In this step, you'll create a subscriber that listens to the `phone-auth.otp.generated` event and sends an SMS to the customer with the OTP. -Refer to the [Events and Subscribers](undefined/docs/learn/fundamentals/events-and-subscribers) documentation to learn more. +Refer to the [Events and Subscribers](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md) documentation to learn more. Subscribers are created in a TypeScript or JavaScript file under the `src/subscribers` directory. So, to create a subscriber, create the file `src/subscribers/send-otp.ts` with the following content: @@ -64409,7 +64433,7 @@ The subscriber function accepts an object with the following properties: - `event`: An object with the event's data payload. In the `authenticate` method, you emitted the event with the following data: - `phone`: The phone number of the user. - `otp`: The OTP that was generated. -- `container`: The [Medusa container](undefined/docs/learn/fundamentals/medusa-container), which you can use to resolve Framework and commerce resources. +- `container`: The [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which you can use to resolve Framework and commerce resources. In the subscriber function, you resolve the Notification Module's service from the Medusa container. Then, you use its `createNotifications` method to send the OTP to the user. @@ -64436,7 +64460,7 @@ Make sure to remove the OTP logging line in the `generateOTP` method of the Phon ## Step 4: Use Phone Authentication in the Next.js Starter Storefront -In this step, you'll customize the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter) to allow customers to authenticate using their phone number and OTP. +In this step, you'll customize the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) to allow customers to authenticate using their phone number and OTP. By default, the Next.js Starter Storefront supports email and password authentication. You'll replace it with phone authentication, but you can also keep both authentication methods if you want to. @@ -64490,7 +64514,7 @@ export const authenticateWithPhone = async (phone: string) => { The function accepts the phone number as a parameter. -In the function, you use the [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk), which is configured within the Next.js Starter Storefront, to send a request to the `/auth/customer/phone-auth` API route. You pass the phone number in the request body. +In the function, you use the [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md), which is configured within the Next.js Starter Storefront, to send a request to the `/auth/customer/phone-auth` API route. You pass the phone number in the request body. If the request doesn't return a `location` property set to `otp`, you throw an error. Otherwise, you return `true` to indicate that the request was successful. @@ -64601,7 +64625,7 @@ The function accepts an object with the following properties: In the function, you retrieve a registration token for the customer using the `/auth/customer/phone-auth/register` API route. You pass the phone number in the request body. -Then, after setting the registration token in the cookies, you create a customer using the [Create Customer](undefined/api/store#customers_postcustomers) API route. You pass the following properties in the request body: +Then, after setting the registration token in the cookies, you create a customer using the [Create Customer](https://docs.medusajs.com/api/store#customers_postcustomers) API route. You pass the following properties in the request body: - `email`: The email of the customer. You set it to the phone number with a `@gmail.com` domain. - `first_name`: The first name of the customer. @@ -65278,11 +65302,11 @@ If you go to your profile page and click on "Profile" in the sidebar, the email While removing the email and phone fields from the profile page prevents customers using the storefront from updating their phone number, it doesn't prevent them from updating it using Medusa's API. -In this section, you'll add a [middleware](undefined/docs/learn/fundamentals/api-routes/middlewares) to the `/store/customers/me` API route that prevents customers from updating their phone number. +In this section, you'll add a [middleware](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md) to the `/store/customers/me` API route that prevents customers from updating their phone number. A middleware is a function that's executed whenever a request is sent to an API route. It's executed before the route handler, allowing you to validate requests, apply authentication guards, and more. -Learn more in the [Middlewares](undefined/docs/learn/fundamentals/api-routes/middlewares) documentation. +Learn more in the [Middlewares](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md) documentation. To add a middleware in your Medusa application, create the file `src/api/middlewares.ts` with the following content: @@ -65362,13 +65386,13 @@ The login form of Medusa Admin can't be customized, so you'll have to build a cu ### Learn More about Medusa -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). ### Troubleshooting -If you encounter issues during your development, check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting). +If you encounter issues during your development, check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/index.html.md). ### Getting Help @@ -65383,7 +65407,7 @@ If you encounter issues not covered in the troubleshooting guides: In this tutorial, you'll learn how to implement pre-orders in Medusa. -When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules) that are available out-of-the-box. +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md) that are available out-of-the-box. The pre-orders feature allows customers to purchase a product before it's available for delivery. Once the product is available, it's automatically shipped to the customer. This is useful when a business is launching and marketing a new product, such as merchandise or books. @@ -65422,25 +65446,25 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose Yes. +You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose Yes. Afterward, the installation process will start, which will install the Medusa application in a directory with your project's name, and the Next.js Starter Storefront in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterward, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** ## Step 2: Create Preorder Module -In Medusa, you can build custom features in a [module](undefined/docs/learn/fundamentals/modules). A module is a reusable package with the data models and functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. +In Medusa, you can build custom features in a [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). A module is a reusable package with the data models and functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. In this step, you'll build a Preorder Module that defines the data models and logic to manage pre-orders. Later, you'll build commerce flows related to pre-orders around the module. -Refer to the [Modules documentation](undefined/docs/learn/fundamentals/modules) to learn more. +Refer to the [Modules documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) to learn more. ### a. Create Module Directory @@ -65450,7 +65474,7 @@ Create the directory `src/modules/preorder` that will hold the Preorder Module's A data model represents a table in the database. You create data models using Medusa's Data Model Language (DML). It simplifies defining a table's columns, relations, and indexes with straightforward methods and configurations. -Refer to the [Data Models documentation](undefined/docs/learn/fundamentals/modules#1-create-data-model) to learn more. +Refer to the [Data Models documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#1-create-data-model/index.html.md) to learn more. For the Preorder Module, you'll define a data model to represent pre-order configurations for a product variant, and another to represent a pre-order placed by a customer. @@ -65493,7 +65517,7 @@ The `PreorderVariant` data model has the following properties: Data relevant for pre-orders like price, inventory, etc... are all either included in the `ProductVariant` data model or its linked records. So, you don't need to duplicate this information in the `PreorderVariant` data model. -Learn more about defining data model properties in the [Property Types documentation](undefined/docs/learn/fundamentals/data-models/properties). +Learn more about defining data model properties in the [Property Types documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/properties/index.html.md). #### Preorder Data Model @@ -65545,7 +65569,7 @@ You can manage your module's data models in a service. A service is a TypeScript class that the module exports. In the service's methods, you can connect to the database, allowing you to manage your data models, or connect to a third-party service, which is useful if you're integrating with external services. -Refer to the [Module Service documentation](undefined/docs/learn/fundamentals/modules#2-create-service) to learn more. +Refer to the [Module Service documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#2-create-service/index.html.md) to learn more. To create the Preorder Module's service, create the file `src/modules/preorder/services/preorder.ts` with the following content: @@ -65564,7 +65588,7 @@ The `PreorderModuleService` extends `MedusaService`, which generates a class wit So, the `PreorderModuleService` class now has methods like `createPreorders` and `retrievePreorder`. -Find all methods generated by the `MedusaService` in [the Service Factory reference](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference). +Find all methods generated by the `MedusaService` in [the Service Factory reference](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/index.html.md). ### d. Export Module Definition @@ -65613,7 +65637,7 @@ Each object in the `modules` array has a `resolve` property, whose value is eith Since data models represent tables in the database, you define how they're created in the database with migrations. A migration is a TypeScript class that defines database changes made by a module. -Refer to the [Migrations documentation](undefined/docs/learn/fundamentals/modules#5-generate-migrations) to learn more. +Refer to the [Migrations documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#5-generate-migrations/index.html.md) to learn more. Medusa's CLI tool can generate the migrations for you. To generate a migration for the Preorder Module, run the following command in your Medusa application's directory: @@ -65639,7 +65663,7 @@ Since Medusa isolates modules to integrate them into your application without si Instead, Medusa provides a mechanism to define links between data models, and retrieve and manage linked records while maintaining module isolation. -Refer to the [Module Isolation documentation](undefined/docs/learn/fundamentals/modules/isolation) to learn more. +Refer to the [Module Isolation documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md) to learn more. In this step, you'll define a link between the data models in the Preorder Module and the data models in Medusa's Commerce Modules. @@ -65665,7 +65689,7 @@ You define a link using the `defineLink` function. It accepts two parameters: In later steps, you'll learn how this link allows you to retrieve and manage product variants and their pre-order configurations. -Refer to the [Module Links](undefined/docs/learn/fundamentals/module-links) documentation to learn more about defining links. +Refer to the [Module Links](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md) documentation to learn more about defining links. ### b. Preorder \<> Order Link @@ -65720,8 +65744,8 @@ In this step, you'll implement the logic to manage pre-order configurations of p When you build commerce features in Medusa that can be consumed by client applications, such as the Medusa Admin dashboard or a storefront, you need to implement: -1. A [workflow](undefined/docs/learn/fundamentals/workflows) with steps that define the business logic of the feature. -2. An [API route](undefined/docs/learn/fundamentals/api-routes) that exposes the workflow's functionality to client applications. +1. A [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) with steps that define the business logic of the feature. +2. An [API route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) that exposes the workflow's functionality to client applications. In this step, you'll implement the workflows and API routes to manage pre-order configurations of product variants. @@ -65731,12 +65755,12 @@ The first workflow you'll implement allows merchants to create or update pre-ord A workflow is a series of queries and actions, called steps, that complete a task. A workflow is similar to a function, but it allows you to track its executions' progress, define roll-back logic, and configure other advanced features. -Refer to the [Workflows documentation](undefined/docs/learn/fundamentals/workflows) to learn more. +Refer to the [Workflows documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) to learn more. The workflow you'll build will have the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Confirm that the product variant exists. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Try to retrieve existing pre-order configurations. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Confirm that the product variant exists. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Try to retrieve existing pre-order configurations. The `useQueryGraphStep` and `createRemoteLinkStep` are available through Medusa's `@medusajs/medusa/core-flows` package. You'll implement other steps in the workflow. @@ -65799,7 +65823,7 @@ You create a step with the `createStep` function. It accepts three parameters: 1. The step's unique name. 2. An async function that receives two parameters: - The step's input, which is an object with the pre-order variant's properties. - - An object that has properties including the [Medusa container](undefined/docs/learn/fundamentals/medusa-container), which is a registry of Framework and commerce tools that you can access in the step. + - An object that has properties including the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which is a registry of Framework and commerce tools that you can access in the step. 3. An async compensation function that undoes the actions performed by the step function. This function is only executed if an error occurs during the workflow's execution. In the step function, you resolve the Preorder Module's service from the Medusa container using its `resolve` method, passing it the module's name as a parameter. @@ -65955,10 +65979,10 @@ It accepts as a second parameter a constructor function that holds the workflow' In the workflow, you: -1. Try to retrieve the variant's details to confirm it exists. The [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep) uses [Query](undefined/docs/learn/fundamentals/module-links/query) which allows you to retrieve data across modules. +1. Try to retrieve the variant's details to confirm it exists. The [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md) uses [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) which allows you to retrieve data across modules. - If it doesn't exist, an error is thrown and the workflow will stop executing. 2. Try to retrieve the variant's existing preorder configurations, if any. -3. Use [when-then](undefined/docs/learn/fundamentals/workflows/conditions) to check if there are existing pre-order configurations. +3. Use [when-then](https://docs.medusajs.com/docs/learn/fundamentals/workflows/conditions/index.html.md) to check if there are existing pre-order configurations. - If so, you update the pre-order variant record. 4. Use `when-then` to check if there are no existing pre-order configurations. - If so, you create a pre-order variant record and link it to the product variant. @@ -65966,7 +65990,7 @@ In the workflow, you: A workflow must return an instance of `WorkflowResponse` that accepts the data to return to the workflow's executor. -`when-then` and `transform` allow you to access the values of data during execution. Learn more in the [Data Manipulation](undefined/docs/learn/fundamentals/workflows/variable-manipulation) and [When-Then](undefined/docs/learn/fundamentals/workflows/conditions) documentation. +`when-then` and `transform` allow you to access the values of data during execution. Learn more in the [Data Manipulation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/variable-manipulation/index.html.md) and [When-Then](https://docs.medusajs.com/docs/learn/fundamentals/workflows/conditions/index.html.md) documentation. ### b. Upsert Pre-Order Variant API Route @@ -65974,7 +65998,7 @@ Next, you'll create the API route that exposes the workflow's functionality to c An API route is created in a `route.ts` file under a sub-directory of the `src/api` directory. The path of the API route is the file's path relative to `src/api`. -Refer to the [API routes](undefined/docs/learn/fundamentals/api-routes) documentation to learn more about them. +Refer to the [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) documentation to learn more about them. Create the file `src/api/admin/variants/[id]/preorders/route.ts` with the following content: @@ -66026,7 +66050,7 @@ Finally, you return the created or updated pre-order variant record in the respo #### Add Validation Middleware -To validate the body parameters of requests sent to the API route, you need to apply a [middleware](undefined/docs/learn/fundamentals/api-routes/middlewares). +To validate the body parameters of requests sent to the API route, you need to apply a [middleware](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md). To apply a middleware to a route, create the file `src/api/middlewares.ts` with the following content: @@ -66056,7 +66080,7 @@ You apply Medusa's `validateAndTransformBody` middleware to `POST` requests sent The middleware function accepts a Zod schema, which you created in the API route's file. -Refer to the [Middlewares](undefined/docs/learn/fundamentals/api-routes/middlewares) documentation to learn more. +Refer to the [Middlewares](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md) documentation to learn more. You'll test this API route later when you customize the Medusa Admin. @@ -66066,7 +66090,7 @@ Next, you'll create a workflow that will disable the pre-order variant configura This workflow has the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the pre-order configurations of a variant. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the pre-order configurations of a variant. - [disablePreorderVariantStep](#disablePreorderVariantStep): Disable the pre-order variant configurations. You only need to implement the `disablePreorderVariantStep`. @@ -66207,13 +66231,13 @@ In this step, you'll customize the Medusa Admin to allow admin users to manage p The Medusa Admin dashboard is customizable, allowing you to insert widgets into existing pages, or create new pages. -Refer to the [Admin Development](undefined/docs/learn/fundamentals/admin) documentation to learn more. +Refer to the [Admin Development](https://docs.medusajs.com/docs/learn/fundamentals/admin/index.html.md) documentation to learn more. In this step, you'll insert a widget into the product variant page that allows admin users to manage pre-order configurations. ### a. Initialize JS SDK -To send requests to the Medusa server, you'll use the [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk). It's already installed in your Medusa project, but you need to initialize it before using it in your customizations. +To send requests to the Medusa server, you'll use the [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md). It's already installed in your Medusa project, but you need to initialize it before using it in your customizations. Create the file `src/admin/lib/sdk.ts` with the following content: @@ -66229,7 +66253,7 @@ export const sdk = new Medusa({ }) ``` -Learn more about the initialization options in the [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk) reference. +Learn more about the initialization options in the [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md) reference. ### b. Define Types @@ -66284,7 +66308,7 @@ To send requests to the Medusa server with support for caching and refetching ca So, you'll create a hook that exposes queries and mutations to manage pre-order configurations. -Refer to the [Admin Development Tips](undefined/docs/learn/fundamentals/admin/tips#send-requests-to-api-routes) documentation to learn more. +Refer to the [Admin Development Tips](https://docs.medusajs.com/docs/learn/fundamentals/admin/tips#send-requests-to-api-routes/index.html.md) documentation to learn more. Create the file `src/admin/hooks/use-preorder-variant.ts` with the following content: @@ -66353,7 +66377,7 @@ export const usePreorderVariant = (variant: HttpTypes.AdminProductVariant) => { The `usePreorderVariant` hook returns an object with the following properties: -- `preorderVariant`: The pre-order variant. It's retrieved from Medusa's [Retrieve Variant](undefined/api/admin#products_getproductsidvariantsvariant_id) API route, which allows expanding linked records using the `fields` query parameter. +- `preorderVariant`: The pre-order variant. It's retrieved from Medusa's [Retrieve Variant](https://docs.medusajs.com/api/admin#products_getproductsidvariantsvariant_id) API route, which allows expanding linked records using the `fields` query parameter. - `isLoading`: Whether the pre-order variant is being retrieved. - `error`: Errors that occur while retrieving the pre-order variant. - `upsertPreorder`: A mutation to create or update a pre-order variant. @@ -66610,7 +66634,7 @@ const PreorderWidget = ({ You render the variant's pre-order configurations if available. You also give the admin user the option to add or edit pre-order configurations and remove (disable) them. -To show the pre-order configuration form, you use the [Drawer](undefined/ui/components/drawer) component from Medusa UI. +To show the pre-order configuration form, you use the [Drawer](https://docs.medusajs.com/ui/components/drawer/index.html.md) component from Medusa UI. ### Test the Customizations @@ -66653,10 +66677,10 @@ In this step, you'll wrap custom logic around Medusa's cart completion logic in The workflow that completes a cart with pre-order items has the following steps: -- [completeCartWorkflow](undefined/references/medusa-workflows/completeCartWorkflow): Complete the cart with pre-order items. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve all line items in the cart. +- [completeCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/completeCartWorkflow/index.html.md): Complete the cart with pre-order items. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve all line items in the cart. - [retrievePreorderItemIdsStep](#retrievePreorderItemIdsStep): Retrieve the IDs of pre-order variants in the cart. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the created order. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the created order. You only need to implement the `retrievePreorderItemIdsStep` and `createPreordersStep` steps. @@ -66826,12 +66850,12 @@ The workflow receives the cart ID as input. In the workflow, you: -1. Complete the cart using the [completeCartWorkflow](undefined/references/medusa-workflows/completeCartWorkflow) as a step. This is Medusa's cart completion logic. -2. Retrieve all line items in the cart using the [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep). +1. Complete the cart using the [completeCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/completeCartWorkflow/index.html.md) as a step. This is Medusa's cart completion logic. +2. Retrieve all line items in the cart using the [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md). 3. Retrieve the IDs of the pre-order variants in the cart using the `retrievePreorderItemIdsStep`. -4. Use [when-then](undefined/docs/learn/fundamentals/workflows/conditions) to check if there are pre-order items in the cart. +4. Use [when-then](https://docs.medusajs.com/docs/learn/fundamentals/workflows/conditions/index.html.md) to check if there are pre-order items in the cart. - If so, you create `Preorder` records for the pre-order items using the `createPreordersStep`. -5. Retrieve the created order using the [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep). +5. Retrieve the created order using the [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md). 6. Return the created Medusa order. ### b. Create Complete Pre-order Cart API Route @@ -66877,7 +66901,7 @@ In some use cases, you may want to allow customers to either pre-order products, In those cases, you can perform custom logic within Medusa's add-to-cart logic to validate an item before it's added to the cart. -You do this using [workflow hooks](undefined/docs/learn/fundamentals/workflows/workflow-hooks). A workflow hook is a point in a workflow where you can inject custom functionality as a step function. +You do this using [workflow hooks](https://docs.medusajs.com/docs/learn/fundamentals/workflows/workflow-hooks/index.html.md). A workflow hook is a point in a workflow where you can inject custom functionality as a step function. To consume the `validate` hook of the `addToCartWorkflow` that holds the add-to-cart logic, create the file `src/workflows/hooks/validate-cart.ts` with the following content: @@ -66951,7 +66975,7 @@ In the step function, you check whether the cart's existing items have pre-order If the checks don't match, you throw an error, preventing the new item from being added to the cart. -Refer to the [Workflow Hooks](undefined/docs/learn/fundamentals/workflows/workflow-hooks) documentation to learn more. +Refer to the [Workflow Hooks](https://docs.medusajs.com/docs/learn/fundamentals/workflows/workflow-hooks/index.html.md) documentation to learn more. You can test this out after customizing the storefront in the next section. @@ -67578,17 +67602,17 @@ You can see the pre-order variant's title, status, available date, and a link to When a pre-order variant reaches its available date, you want to automatically fulfill the pre-order items in the order. -In this step, you'll create a workflow that automatically fulfills a pre-order. Then, you'll execute the workflow in a [scheduled job](undefined/docs/learn/fundamentals/scheduled-jobs) that runs every day. +In this step, you'll create a workflow that automatically fulfills a pre-order. Then, you'll execute the workflow in a [scheduled job](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs/index.html.md) that runs every day. ### a. Create Auto Fulfill Pre-order Workflow The workflow that automatically fulfills a pre-order has the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the Medusa order details. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the Medusa order details. - [retrieveItemsToFulfillStep](#retrieveItemsToFulfillStep): Retrieve the items to fulfill in the order. -- [createOrderFulfillmentWorkflow](undefined/references/medusa-workflows/createOrderFulfillmentWorkflow): Create a fulfillment for the Medusa order. +- [createOrderFulfillmentWorkflow](https://docs.medusajs.com/references/medusa-workflows/createOrderFulfillmentWorkflow/index.html.md): Create a fulfillment for the Medusa order. - [updatePreordersStep](#updatePreordersStep): Update the status of the pre-order. -- [emitEventStep](undefined/references/helper-steps/emitEventStep): Emit an event indicating that a pre-order was fulfilled. +- [emitEventStep](https://docs.medusajs.com/references/helper-steps/emitEventStep/index.html.md): Emit an event indicating that a pre-order was fulfilled. You only need to implement the `retrieveItemsToFulfillStep` and `updatePreordersStep` steps. @@ -67762,11 +67786,11 @@ The workflow receives as an input: In the workflow, you: -- Retrieve the Medusa order using the [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep). +- Retrieve the Medusa order using the [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md). - Retrieve the items to fulfill in the order using the `retrieveItemsToFulfillStep`. -- Create a fulfillment for the Medusa order using the [createOrderFulfillmentWorkflow](undefined/references/medusa-workflows/createOrderFulfillmentWorkflow) as a step. +- Create a fulfillment for the Medusa order using the [createOrderFulfillmentWorkflow](https://docs.medusajs.com/references/medusa-workflows/createOrderFulfillmentWorkflow/index.html.md) as a step. - Update the pre-order status to `FULFILLED` using the `updatePreordersStep`. -- Emit an event indicating that a pre-order was fulfilled using the [emitEventStep](undefined/references/helper-steps/emitEventStep). +- Emit an event indicating that a pre-order was fulfilled using the [emitEventStep](https://docs.medusajs.com/references/helper-steps/emitEventStep/index.html.md). - Return the fulfillment in the response. #### Optional: Capture Payment @@ -67777,7 +67801,7 @@ Some payment providers may automatically capture the payment when the order is p In some use cases, you may want to capture the payment for the pre-order when fulfilling it. -To do that, you can use Medusa's [capturePaymentWorkflow](undefined/references/medusa-workflows/capturePaymentWorkflow) to capture the payment for the order in the workflow. +To do that, you can use Medusa's [capturePaymentWorkflow](https://docs.medusajs.com/references/medusa-workflows/capturePaymentWorkflow/index.html.md) to capture the payment for the order in the workflow. First, change the `retrieveItemsToFulfillStep` to return the total of the pre-ordered items: @@ -67928,7 +67952,7 @@ Next, you'll create a scheduled job that runs the `fulfillPreorderWorkflow` ever A scheduled job is an asynchronous function that executes tasks in the background at specified intervals. -Refer to the [Scheduled Jobs](undefined/docs/learn/fundamentals/scheduled-jobs) documentation to learn more. +Refer to the [Scheduled Jobs](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs/index.html.md) documentation to learn more. To create a scheduled job, create the file `src/jobs/fulfill-preorders.ts` with the following content: @@ -68118,7 +68142,7 @@ Make sure to revert the changes once you're done testing. In the `fulfillPreorderWorkflow`, you emitted the `preorder.fulfilled` event. This is useful for performing actions when a pre-order is fulfilled separately from the main flow. -For example, you may want to send a notification to the customer when their pre-order is fulfilled. You can do this by creating a [subscriber](undefined/docs/learn/fundamentals/events-and-subscribers). +For example, you may want to send a notification to the customer when their pre-order is fulfilled. You can do this by creating a [subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md). A subscriber is an asynchronous function that is executed when its associated event is emitted. @@ -68181,11 +68205,11 @@ A subscriber file must export: The subscriber receives among its parameters the data payload of the emitted event, which includes the IDs of the Medusa order and the pre-order variant. -In the subscriber, you retrieve the details of the order and pre-order variants. Then, you use the [Notification Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification) to send a notification. +In the subscriber, you retrieve the details of the order and pre-order variants. Then, you use the [Notification Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/index.html.md) to send a notification. -Notice that the `createNotifications` method receives a `channel` property for a notification. This indicates which [Notification Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification#what-is-a-notification-module-provider) to send the notification with. +Notice that the `createNotifications` method receives a `channel` property for a notification. This indicates which [Notification Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification#what-is-a-notification-module-provider/index.html.md) to send the notification with. -The `feed` channel is useful for debugging, as it logs the notification in the terminal. To send an email, you can instead [set up a provider like SendGrid](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/integrations#notification) and change the channel to `email`. +The `feed` channel is useful for debugging, as it logs the notification in the terminal. To send an email, you can instead [set up a provider like SendGrid](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/integrations#notification/index.html.md) and change the channel to `email`. To test the subscriber, [perform the steps to test fulfilling pre-orders](#test-scheduled-job). Once a pre-order is fulfilled, you'll see the following message logged in your terminal: @@ -68193,7 +68217,7 @@ To test the subscriber, [perform the steps to test fulfilling pre-orders](#test- info: Processing preorder.fulfilled which has 1 subscribers ``` -Learn more about sending notifications in the [Notification Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification) documentation. +Learn more about sending notifications in the [Notification Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/index.html.md) documentation. *** @@ -68359,8 +68383,8 @@ In this step, you'll create a workflow that cancels or creates pre-orders based The workflow that will handle order edits has the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the order's items with their pre-order variants. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the pre-orders of the order. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the order's items with their pre-order variants. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the pre-orders of the order. - [retrievePreorderUpdatesStep](#retrievePreorderUpdatesStep): Retrieve the pre-orders that need to be created and canceled. - [updatePreordersStep](#updatePreordersStep): Update the status of orders to be canceled. - [createPreordersStep](#createPreordersStep): Create pre-orders for new pre-order items. @@ -68531,12 +68555,12 @@ The workflow receives the order ID as an input. In the workflow, you: -1. Retrieve the order details using the [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep). -2. Retrieve the pre-orders of the order using the [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep). +1. Retrieve the order details using the [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md). +2. Retrieve the pre-orders of the order using the [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md). 3. Retrieve the pre-orders to cancel and create using the `retrievePreorderUpdatesStep`. 4. Update the pre-orders to cancel using the `updatePreordersStep`. 5. Create the pre-orders to create using the `createPreordersStep`. -6. Emit the `preorder.cancelled` event for the pre-orders that were canceled using the [emitEventStep](undefined/references/helper-steps/emitEventStep). +6. Emit the `preorder.cancelled` event for the pre-orders that were canceled using the [emitEventStep](https://docs.medusajs.com/references/helper-steps/emitEventStep/index.html.md). - You can handle the event similar to the [preorder.fulfilled](#optional-send-notification-to-customer) event to notify the customer. 7. Return the created and canceled pre-orders in the response. @@ -68585,7 +68609,7 @@ To edit the order: 1. Click the icon at the top right of the order details section. 2. Choose Edit from the dropdown. 3. In the order edit form, you can add or remove items from the order. - - Learn more about the order edit form in the [user guide](undefined/user-guide/orders/edit). + - Learn more about the order edit form in the [user guide](https://docs.medusajs.com/user-guide/orders/edit/index.html.md). 4. Click the "Confirm Edit" button at the bottom of the form, then click "Continue" in the confirmation modal. 5. The order edit request will be shown at the top of the page. Click the "Force confirm" button to confirm the order edit. @@ -68605,13 +68629,13 @@ You've now implemented the pre-order feature in Medusa. You can expand on this f ### Learn More about Medusa -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). ### Troubleshooting -If you encounter issues during your development, check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting). +If you encounter issues during your development, check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/index.html.md). ### Getting Help @@ -68625,7 +68649,7 @@ If you encounter issues not covered in the troubleshooting guides: In this tutorial, you'll learn how to implement a product builder in Medusa. -When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules) that are available out-of-the-box. +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md) that are available out-of-the-box. A product builder allows customers to customize the product before adding it to the cart. This may include entering custom options like engraving text, adding complementary products to the cart, or purchasing add-ons with the product, such as insurance. @@ -68663,23 +68687,23 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose Yes. +You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose Yes. Afterward, the installation process will start, which will install the Medusa application in a directory with your project's name, and the Next.js Starter Storefront in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterward, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** ## Step 2: Create Product Builder Module -In Medusa, you can build custom features in a [module](undefined/docs/learn/fundamentals/modules). A module is a reusable package with the data models and functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. +In Medusa, you can build custom features in a [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). A module is a reusable package with the data models and functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. -Refer to the [Modules](undefined/docs/learn/fundamentals/modules) documentation to learn more. +Refer to the [Modules](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) documentation to learn more. In this step, you'll build a Product Builder Module that defines the data models and logic to manage product builder configurations. The module will support three types of configurations: @@ -68695,7 +68719,7 @@ Create the directory `src/modules/product-builder` that will hold the Product Bu A data model represents a table in the database. You create data models using Medusa's Data Model Language (DML). It simplifies defining a table's columns, relations, and indexes with straightforward methods and configurations. -Refer to the [Data Models](undefined/docs/learn/fundamentals/modules#1-create-data-model) documentation to learn more. +Refer to the [Data Models](https://docs.medusajs.com/docs/learn/fundamentals/modules#1-create-data-model/index.html.md) documentation to learn more. For the Product Builder Module, you'll define four data models to represent the different aspects of product customization. @@ -68739,7 +68763,7 @@ The `ProductBuilder` data model has the following properties: Ignore the type errors for the related data models. You'll create them next. -Learn more about defining data model properties in the [Property Types documentation](undefined/docs/learn/fundamentals/data-models/properties). +Learn more about defining data model properties in the [Property Types documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/properties/index.html.md). #### ProductBuilderCustomField Data Model @@ -68836,7 +68860,7 @@ You can manage your module's data models in a service. A service is a TypeScript class that the module exports. In the service's methods, you can connect to the database, allowing you to manage your data models, or connect to a third-party service, which is useful if you're integrating with external services. -Refer to the [Module Service documentation](undefined/docs/learn/fundamentals/modules#2-create-service) to learn more. +Refer to the [Module Service documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#2-create-service/index.html.md) to learn more. To create the Product Builder Module's service, create the file `src/modules/product-builder/service.ts` with the following content: @@ -68861,7 +68885,7 @@ The `ProductBuilderModuleService` extends `MedusaService`, which generates a cla So, the `ProductBuilderModuleService` class now has methods like `createProductBuilders` and `retrieveProductBuilder`. -Find all methods generated by the `MedusaService` in [the Service Factory](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference) reference. +Find all methods generated by the `MedusaService` in [the Service Factory](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/index.html.md) reference. ### d. Create the Module Definition @@ -68910,7 +68934,7 @@ Each object in the `modules` array has a `resolve` property, whose value is eith Since data models represent tables in the database, you define how they're created in the database with migrations. A migration is a TypeScript class that defines database changes made by a module. -Refer to the [Migrations documentation](undefined/docs/learn/fundamentals/modules#5-generate-migrations) to learn more. +Refer to the [Migrations documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#5-generate-migrations/index.html.md) to learn more. Medusa's CLI tool can generate the migrations for you. To generate a migration for the Product Builder Module, run the following command in your Medusa application's directory: @@ -68936,7 +68960,7 @@ Since Medusa isolates modules to integrate them into your application without si Instead, Medusa provides a mechanism to define links between data models, and retrieve and manage linked records while maintaining module isolation. -Refer to the [Module Links](undefined/docs/learn/fundamentals/module-links) documentation to learn more about defining links. +Refer to the [Module Links](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md) documentation to learn more about defining links. In this step, you'll define links between the data models in the Product Builder Module and the data models in Medusa's Product Module: @@ -69027,8 +69051,8 @@ In this step, you'll implement the logic to manage product builder configuration To implement the product builder management functionality, you'll create: -- A [workflow](undefined/docs/learn/fundamentals/workflows) to create or update (upsert) product builder configurations. -- An [API route](undefined/docs/learn/fundamentals/api-routes) to expose the workflow's functionality to client applications. +- A [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) to create or update (upsert) product builder configurations. +- An [API route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) to expose the workflow's functionality to client applications. ### a. Upsert Product Builder Workflow @@ -69036,11 +69060,11 @@ The first workflow you'll implement creates or updates builder configurations fo A workflow is a series of queries and actions, called steps, that complete a task. A workflow is similar to a function, but it allows you to track its executions' progress, define roll-back logic, and configure other advanced features. -Refer to the [Workflows](undefined/docs/learn/fundamentals/workflows) documentation to learn more. +Refer to the [Workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) documentation to learn more. The workflow you'll build will have the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the product builder configuration, if it exists. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the product builder configuration, if it exists. - [prepareProductBuilderCustomFieldsStep](#prepareProductBuilderCustomFieldsStep): Prepare custom fields to create, update, or delete. - [createProductBuilderCustomFieldsStep](#createProductBuilderCustomFieldsStep): Create custom fields for the product builder. - [updateProductBuilderCustomFieldsStep](#updateProductBuilderCustomFieldsStep): Update custom fields for the product builder. @@ -69051,7 +69075,7 @@ The workflow you'll build will have the following steps: - [prepareProductBuilderAddonsStep](#prepareProductBuilderAddonsStep): Prepare addon products to create, or delete. - [createProductBuilderAddonsStep](#createProductBuilderAddonsStep): Create addon products for the product builder. - [deleteProductBuilderAddonsStep](#deleteProductBuilderAddonsStep): Delete addon products for the product builder. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the updated product builder configuration. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the updated product builder configuration. The `useQueryGraphStep`, `createRemoteLinkStep`, and `dismissRemoteLinkStep` are available through Medusa's `@medusajs/medusa/core-flows` package. You'll implement other steps in the workflow. @@ -69095,7 +69119,7 @@ You create a step with the `createStep` function. It accepts three parameters: 1. The step's unique name. 2. An async function that receives two parameters: - The step's input, which is an object with the product builder's properties. - - An object that has properties including the [Medusa container](undefined/docs/learn/fundamentals/medusa-container), which is a registry of Framework and commerce tools that you can access in the step. + - An object that has properties including the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which is a registry of Framework and commerce tools that you can access in the step. 3. An async compensation function that undoes the actions performed by the step function. This function is only executed if an error occurs during the workflow's execution. In the step function, you resolve the Product Builder Module's service from the Medusa container and create a product builder record. @@ -69817,12 +69841,12 @@ const productBuilderId = transform({ In this snippet, you: 1. Try to retrieve the existing product builder using the `useQueryGraphStep`. - - This step uses [Query](undefined/docs/learn/fundamentals/module-links/query) to retrieve data across modules. -2. Use [when-then](undefined/docs/learn/fundamentals/workflows/conditions) to check whether the existing product builder was found. + - This step uses [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) to retrieve data across modules. +2. Use [when-then](https://docs.medusajs.com/docs/learn/fundamentals/workflows/conditions/index.html.md) to check whether the existing product builder was found. - If there's no existing product builder, you create a new one using the `createProductBuilderStep`, then link it to the product using the `createRemoteLinkStep`. -3. Use [transform](undefined/docs/learn/fundamentals/workflows/variable-manipulation) to extract the product builder ID from either the existing or newly created product builder. +3. Use [transform](https://docs.medusajs.com/docs/learn/fundamentals/workflows/variable-manipulation/index.html.md) to extract the product builder ID from either the existing or newly created product builder. -In a workflow, you can't manipulate data or check conditions because Medusa stores an internal representation of the workflow on application startup. Learn more in the [Data Manipulation](undefined/docs/learn/fundamentals/workflows/variable-manipulation) and [Conditions](undefined/docs/learn/fundamentals/workflows/conditions) documentation. +In a workflow, you can't manipulate data or check conditions because Medusa stores an internal representation of the workflow on application startup. Learn more in the [Data Manipulation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/variable-manipulation/index.html.md) and [Conditions](https://docs.medusajs.com/docs/learn/fundamentals/workflows/conditions/index.html.md) documentation. Next, you need to manage the custom fields passed in the input. Replace the new `TODO` in the workflow with the following: @@ -70043,7 +70067,7 @@ Next, you'll create the API route that exposes the workflow's functionality to c An API route is created in a `route.ts` file under a sub-directory of the `src/api` directory. The path of the API route is the file's path relative to `src/api`. -Refer to the [API routes](undefined/docs/learn/fundamentals/api-routes) documentation to learn more about them. +Refer to the [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) documentation to learn more about them. Create the file `src/api/admin/products/[id]/builder/route.ts` with the following content: @@ -70103,7 +70127,7 @@ You'll test this API route later when you customize the Medusa Admin dashboard. #### Add Validation Middleware -To validate the body parameters of requests sent to the API route, you need to apply a [middleware](undefined/docs/learn/fundamentals/api-routes/middlewares). +To validate the body parameters of requests sent to the API route, you need to apply a [middleware](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md). To apply a middleware to a route, create the file `src/api/middlewares.ts` with the following content: @@ -70131,7 +70155,7 @@ You apply the `validateAndTransformBody` middleware to the `POST` route of the ` Any request that doesn't conform to the schema will receive a 400 Bad Request response. -Refer to the [Middlewares](undefined/docs/learn/fundamentals/api-routes/middlewares) documentation to learn more. +Refer to the [Middlewares](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md) documentation to learn more. *** @@ -70188,7 +70212,7 @@ export const GET = async ( Since you export a `GET` route handler function, you expose a `GET` API route at `/admin/products/:id/builder`. -In the route handler function, you resolve [Query](undefined/docs/learn/fundamentals/module-links/query) to retrieve the product builder configuration for the specified product ID. You also retrieve its custom fields, complementary products, and addon products. +In the route handler function, you resolve [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) to retrieve the product builder configuration for the specified product ID. You also retrieve its custom fields, complementary products, and addon products. You return the product builder configuration in the response. @@ -70305,7 +70329,7 @@ export default defineMiddlewares({ You apply the `validateAndTransformQuery` middleware to the `GET` API route at `/admin/products/complementary`. The middleware accepts two parameters: 1. The Zod schema to validate the query parameters. -2. An object of [Request Query Configurations](undefined/docs/learn/fundamentals/module-links/query#request-query-configurations). You enable the `isList` option to indicate that the pagination query parameters should be added as query configurations in the `req.queryConfig.pagination` object. +2. An object of [Request Query Configurations](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query#request-query-configurations/index.html.md). You enable the `isList` option to indicate that the pagination query parameters should be added as query configurations in the `req.queryConfig.pagination` object. ### c. Retrieve Addon Products API Route @@ -70392,13 +70416,13 @@ In this step, you'll customize the Medusa Admin to allow admin users to manage a The Medusa Admin dashboard is customizable, allowing you to insert widgets into existing pages, or create new pages. -Refer to the [Admin Development](undefined/docs/learn/fundamentals/admin) documentation to learn more. +Refer to the [Admin Development](https://docs.medusajs.com/docs/learn/fundamentals/admin/index.html.md) documentation to learn more. In this step, you'll create the components to manage a product's builder configurations, then inject a widget into the product details page to show the configurations and allow managing them. ### a. Initialize JS SDK -To send requests to the Medusa server, you'll use the [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk). It's already installed in your Medusa project, but you need to initialize it before using it in your customizations. +To send requests to the Medusa server, you'll use the [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md). It's already installed in your Medusa project, but you need to initialize it before using it in your customizations. Create the file `src/admin/lib/sdk.ts` with the following content: @@ -70414,7 +70438,7 @@ export const sdk = new Medusa({ }) ``` -Learn more about the initialization options in the [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk) reference. +Learn more about the initialization options in the [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md) reference. ### b. Define Types @@ -71155,7 +71179,7 @@ return ( ) ``` -You display a [Focus Modal](undefined/ui/components/focus-modal) that shows the tabs with each of their content. +You display a [Focus Modal](https://docs.medusajs.com/ui/components/focus-modal/index.html.md) that shows the tabs with each of their content. The modal has a button to move between tabs, then save the changes when the admin user reaches the last tab. @@ -71452,7 +71476,7 @@ You define the following types: Next, you need to retrieve the builder configuration for a product when the customer views its details page. -Since you've defined a link between the product and its builder configuration, you can retrieve the builder configuration of a product by specifying it in the `fields` query parameter of the [List Products API Route](undefined/api/store#products_getproducts). +Since you've defined a link between the product and its builder configuration, you can retrieve the builder configuration of a product by specifying it in the `fields` query parameter of the [List Products API Route](https://docs.medusajs.com/api/store#products_getproducts). In `src/lib/data/products.ts`, add the following import at the top of the file: @@ -72427,8 +72451,8 @@ The workflow will have the following steps: - [validateProductBuilderConfigurationStep](#validateProductBuilderConfigurationStep): Validates the product builder configuration - [addToCartWorkflow](#addToCartWorkflow): Adds the product to the cart. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Get cart with items details. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Get updated cart details. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Get cart with items details. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Get updated cart details. You only need to implement the `validateProductBuilderConfigurationStep`, as Medusa provides the rest. @@ -72654,7 +72678,7 @@ addToCartWorkflow.runAsStep({ You prepare the data to add the main product variant to the cart. You include in the item's metadata the product builder ID, any custom fields, and a flag to identify it as the main product in the builder configuration. -After that, you use the [addToCartWorkflow](undefined/references/medusa-workflows/addToCartWorkflow) to add the main product to the cart. +After that, you use the [addToCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/addToCartWorkflow/index.html.md) to add the main product to the cart. Next, you need to add the complementary and addon product variants to the cart. Replace the `TODO` with the following: @@ -73692,9 +73716,9 @@ You'll create a workflow, use that workflow in an API route, then customize the The workflow to remove a product with builder configurations from the cart has the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve cart details. -- [deleteLineItemsWorkflow](undefined/references/medusa-workflows/deleteLineItemsWorkflow): Delete line items from the cart. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the updated cart details. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve cart details. +- [deleteLineItemsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteLineItemsWorkflow/index.html.md): Delete line items from the cart. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the updated cart details. Medusa provides all of these steps, so you can create the workflow without needing to implement any custom steps. @@ -74346,13 +74370,13 @@ You've now implemented the product builder feature in Medusa. You can expand on ### Learn More about Medusa -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). ### Troubleshooting -If you encounter issues during your development, check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting). +If you encounter issues during your development, check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/index.html.md). ### Getting Help @@ -74366,7 +74390,7 @@ If you encounter issues not covered in the troubleshooting guides: In this tutorial, you'll learn how to create a product feed in Medusa that can be used for Meta and Google. -When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules) that are available out-of-the-box. +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md) that are available out-of-the-box. Businesses that are selling on social media platforms like Meta (Instagram and Facebook) and Google need to upload their product catalog to those platforms and keep them in sync with their Medusa store. Creating a product feed allows you to automate this process. @@ -74402,15 +74426,15 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose Yes. +You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose Yes. Afterward, the installation process will start, which will install the Medusa application in a directory with your project's name, and the Next.js Starter Storefront in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterward, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** @@ -74418,11 +74442,11 @@ Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/for In this step, you'll create the logic to build an XML string for a product feed. -In Medusa, you implement commerce logic within a [workflow](undefined/docs/learn/fundamentals/workflows). A workflow is a series of queries and actions, called steps, that complete a task. A workflow is similar to a function, but it allows you to track its executions' progress, define roll-back logic, and configure other advanced features. +In Medusa, you implement commerce logic within a [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). A workflow is a series of queries and actions, called steps, that complete a task. A workflow is similar to a function, but it allows you to track its executions' progress, define roll-back logic, and configure other advanced features. You'll create a workflow that builds a product feed. Later, you'll execute the workflow from an API route, allowing third-party services to retrieve the product feed. -Refer to the [Workflows](undefined/docs/learn/fundamentals/workflows) documentation to learn more about workflows. +Refer to the [Workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) documentation to learn more about workflows. The workflow you'll create will have the following steps: @@ -74485,7 +74509,7 @@ After that, you create a step with the `createStep` function. It accepts two par 1. The step's unique name. 2. An async function that receives two parameters: - The step's input, which is an object holding the requested currency and country codes. - - An object that has properties including the [Medusa container](undefined/docs/learn/fundamentals/medusa-container), which is a registry of Framework and commerce tools that you can access in the step. + - An object that has properties including the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which is a registry of Framework and commerce tools that you can access in the step. Next, you'll implement the step's logic. Add the following in the step function: @@ -74551,14 +74575,14 @@ You first initialize an empty array of `FeedItem` objects that you'll populate l Then, you resolve the following resources from the Medusa container: -- [Query](undefined/docs/learn/fundamentals/module-links/query) that allows you to retrieve data across modules. -- [Medusa Configurations](undefined/docs/learn/configurations/medusa-config) that are defined in `medusa-config.ts`. +- [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) that allows you to retrieve data across modules. +- [Medusa Configurations](https://docs.medusajs.com/docs/learn/configurations/medusa-config/index.html.md) that are defined in `medusa-config.ts`. You use the Medusa configurations to retrieve the storefront URL, which you'll use to build the product links in the feed. If the storefront URL is not set in the configurations, you fall back to the `STOREFRONT_URL` environment variable. After that, you use Query to retrieve product data with pagination. For each product, you retrieve fields and relations useful for the feed. You still need to add the logic for populating the feed items. -To retrieve the product variant prices for a currency code, you must pass the currency code as a [query context](undefined/docs/learn/fundamentals/module-links/query-context). Learn more in the [Get Variant Prices](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product/guides/price) chapter. +To retrieve the product variant prices for a currency code, you must pass the currency code as a [query context](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query-context/index.html.md). Learn more in the [Get Variant Prices](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/guides/price/index.html.md) chapter. Finally, a step function must return a `StepResponse` instance with the step's output, which is the list of feed items. @@ -74617,7 +74641,7 @@ For each product, you: - Skip the product if it doesn't have variants. - In Medusa, customers purchase variants of a product. - Try to retrieve the sales channel of a product that has stock locations in the requested country code. - - In Medusa, a product variant's inventory is tracked by stock locations that are associated with sales channels. So, you must retrieve the product's sales channel that matches the requested country code to check the availability of each variant. Learn more in the [Product Variant Inventory](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product/variant-inventory) guide. + - In Medusa, a product variant's inventory is tracked by stock locations that are associated with sales channels. So, you must retrieve the product's sales channel that matches the requested country code to check the availability of each variant. Learn more in the [Product Variant Inventory](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/variant-inventory/index.html.md) guide. - For each variant, you: - Retrieve the variant's price and sale price. - If the `calculated_price.original_amount` is different than `calculated_price.calculated_amount`, the variant is on sale and the `calculated_price.calculated_amount` is the sale price. @@ -74747,9 +74771,9 @@ In the next step, you'll create an API route that executes this workflow. In this step, you'll expose the product feed XML by creating an API route. -An [API route](undefined/docs/learn/fundamentals/api-routes) is an endpoint that exposes commerce features to external applications and clients, such as third-party services. +An [API route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) is an endpoint that exposes commerce features to external applications and clients, such as third-party services. -Refer to the [API routes](undefined/docs/learn/fundamentals/api-routes) documentation to learn more. +Refer to the [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) documentation to learn more. An API route is created in a `route.ts` file under a sub-directory of the `src/api` directory. The path of the API route is the file's path relative to `src/api`. @@ -74792,7 +74816,7 @@ Finally, you set the response headers to indicate that the content is XML and se To ensure that the country and currency codes are passed as query parameters, you need to apply a middleware. -A [middleware](undefined/docs/learn/fundamentals/api-routes/middlewares) is a function that runs when a request is sent before running the route handler. It's useful to validate request query and body parameters. +A [middleware](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md) is a function that runs when a request is sent before running the route handler. It's useful to validate request query and body parameters. To apply a middleware on the API route, create the file `src/api/middlewares.ts` with the following content: @@ -74856,9 +74880,9 @@ You'll receive an XML in the response similar to the following: ## Step 4: Use the Product Feed -If your Medusa application is [deployed](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/deployment), you can now use the product feed API route on social platforms like [Meta](https://www.facebook.com/business/help/125074381480892?id=725943027795860) and [Google](https://support.google.com/merchants/answer/11586438?hl=en\&sjid=6331702527227918188-EU). +If your Medusa application is [deployed](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/deployment/index.html.md), you can now use the product feed API route on social platforms like [Meta](https://www.facebook.com/business/help/125074381480892?id=725943027795860) and [Google](https://support.google.com/merchants/answer/11586438?hl=en\&sjid=6331702527227918188-EU). -Make sure to set the [admin.storefrontUrl](undefined/docs/learn/configurations/medusa-config#storefronturl) or `STOREFRONT_URL` environment variable before using the product feed API route. +Make sure to set the [admin.storefrontUrl](https://docs.medusajs.com/docs/learn/configurations/medusa-config#storefronturl/index.html.md) or `STOREFRONT_URL` environment variable before using the product feed API route. For example, to add your product feed as a data source in Meta: @@ -74893,13 +74917,13 @@ You can add more fields to the product feed based on your use case. Refer to [Me ### Learn More about Medusa -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). ### Troubleshooting -If you encounter issues during your development, check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting). +If you encounter issues during your development, check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/index.html.md). ### Getting Help @@ -74913,7 +74937,7 @@ If you encounter issues not covered in the troubleshooting guides: In this tutorial, you'll learn how to implement product reviews in Medusa. -When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules) which are available out-of-the-box. The features include product-management features. +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md) which are available out-of-the-box. The features include product-management features. Medusa doesn't provide product reviews out-of-the-box, but the Medusa Framework facilitates implementing customizations like product reviews. In this tutorial, you'll learn how to customize the Medusa server, Admin dashboard, and Next.js Starter Storefront to implement product reviews. @@ -74949,27 +74973,27 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose Yes. +You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose Yes. Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name, and the Next.js Starter Storefront in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterwards, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** ## Step 2: Add Product Review Module -In Medusa, you can build custom features in a [module](undefined/docs/learn/fundamentals/modules). A module is a reusable package with functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. +In Medusa, you can build custom features in a [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). A module is a reusable package with functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. In the module, you define the data models necessary for a feature and the logic to manage these data models. Later, you can build commerce flows around your module. In this step, you'll build a Product Review Module that defines the necessary data models to store and manage product reviews. -Refer to the [Modules documentation](undefined/docs/learn/fundamentals/modules) to learn more. +Refer to the [Modules documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) to learn more. ### Create Module Directory @@ -74979,7 +75003,7 @@ A module is created under the `src/modules` directory of your Medusa application A data model represents a table in the database. You create data models using Medusa's Data Model Language (DML). It simplifies defining a table's columns, relations, and indexes with straightforward methods and configurations. -Refer to the [Data Models documentation](undefined/docs/learn/fundamentals/modules#1-create-data-model) to learn more. +Refer to the [Data Models documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#1-create-data-model/index.html.md) to learn more. For the Product Review Module, you need to define a `Review` data model that represents a product review. So, create the file `src/modules/product-review/models/review.ts` with the following content: @@ -75014,14 +75038,14 @@ The `Review` data model has the following properties: - `id`: A unique ID for the review. - `title`: The review's title. - `content`: The review's content. -- `rating`: The review's rating. You also add a [check constraint](undefined/docs/learn/fundamentals/data-models/check-constraints) to ensure the rating is between 1 and 5. +- `rating`: The review's rating. You also add a [check constraint](https://docs.medusajs.com/docs/learn/fundamentals/data-models/check-constraints/index.html.md) to ensure the rating is between 1 and 5. - `first_name`: The first name of the reviewer. - `last_name`: The last name of the reviewer. - `status`: The review's status, which can be `pending`, `approved`, or `rejected`. - `product_id`: The ID of the product the review is for. - `customer_id`: The ID of the customer who submitted the review. -Learn more about defining data model properties in the [Property Types documentation](undefined/docs/learn/fundamentals/data-models/properties). +Learn more about defining data model properties in the [Property Types documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/properties/index.html.md). ### Create Module's Service @@ -75029,7 +75053,7 @@ You now have the necessary data model in the Review Module, but you'll need to m A service is a TypeScript or JavaScript class that the module exports. In the service's methods, you can connect to the database, allowing you to manage your data models, or connect to a third-party service, which is useful if you're integrating with external services. -Refer to the [Module Service documentation](undefined/docs/learn/fundamentals/modules#2-create-service) to learn more. +Refer to the [Module Service documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#2-create-service/index.html.md) to learn more. To create the Review Module's service, create the file `src/modules/product-review/service.ts` with the following content: @@ -75049,7 +75073,7 @@ The `ProductReviewModuleService` extends `MedusaService` from the Modules SDK wh So, the `ProductReviewModuleService` class now has methods like `createReviews` and `retrieveReview`. -Find all methods generated by the `MedusaService` in [the Service Factory reference](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference). +Find all methods generated by the `MedusaService` in [the Service Factory reference](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/index.html.md). You'll use this service later when you implement custom flows for product reviews. @@ -75100,7 +75124,7 @@ Each object in the `modules` array has a `resolve` property, whose value is eith Since data models represent tables in the database, you define how they're created in the database with migrations. A migration is a TypeScript or JavaScript file that defines database changes made by a module. -Refer to the [Migrations documentation](undefined/docs/learn/fundamentals/modules#5-generate-migrations) to learn more. +Refer to the [Migrations documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#5-generate-migrations/index.html.md) to learn more. Medusa's CLI tool can generate the migrations for you. To generate a migration for the Review Module, run the following command in your Medusa application's directory: @@ -75122,13 +75146,13 @@ The table for the `Review` data model is now created in the database. ## Step 3: Define Review \<> Product Link -When you defined the `Review` data model, you added properties that store the ID of records managed by other modules. For example, the `product_id` property stores the ID of the product this review is for, but products are managed by the [Product Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product). +When you defined the `Review` data model, you added properties that store the ID of records managed by other modules. For example, the `product_id` property stores the ID of the product this review is for, but products are managed by the [Product Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/index.html.md). Medusa integrates modules into your application without implications or side effects by isolating modules from one another. This means you can't directly create relationships between data models in your module and data models in other modules. Instead, Medusa provides the mechanism to define links between data models, and retrieve and manage linked records while maintaining module isolation. Links are useful to define associations between data models in different modules, or extend a model in another module to associate custom properties with it. -Refer to the [Module Isolation documentation](undefined/docs/learn/fundamentals/modules/isolation) to learn more. +Refer to the [Module Isolation documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md) to learn more. In this step, you'll define a link between the Product Review Module's `Review` data model, and the Product Module's `Product` data model. You'll then use this link to retrieve the product associated with a review. @@ -75168,15 +75192,15 @@ You can now retrieve the product of a review, as you'll see in later steps. You're now ready to start implementing product-review features. The first one you'll implement is the ability for customers to create a product review. -To build custom commerce features in Medusa, you create a [workflow](undefined/docs/learn/fundamentals/workflows). A workflow is a series of queries and actions, called steps, that complete a task. You construct a workflow like you construct a function, but it's a special function that allows you to track its executions' progress, define roll-back logic, and configure other advanced features. Then, you execute the workflow from other customizations, such as in an endpoint. +To build custom commerce features in Medusa, you create a [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). A workflow is a series of queries and actions, called steps, that complete a task. You construct a workflow like you construct a function, but it's a special function that allows you to track its executions' progress, define roll-back logic, and configure other advanced features. Then, you execute the workflow from other customizations, such as in an endpoint. So, in this section, you'll learn how to create a workflow that creates a review. Later, you'll execute this workflow in an API route. -Learn more about workflows in the [Workflows documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in the [Workflows documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). The workflow will have the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the product to confirm it exists. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the product to confirm it exists. - [createReviewStep](#createReviewStep): Create the review. The `useQueryGraphStep` step is provided by Medusa in its `@medusajs/medusa/core-flows` package. So, you only need to implement the `createReviewStep` step. @@ -75234,7 +75258,7 @@ You create a step with `createStep` from the Workflows SDK. It accepts two param 1. The step's unique name, which is `create-review`. 2. An async function that receives two parameters: - The step's input, which is in this case an object with the review's properties. - - An object that has properties including the [Medusa container](undefined/docs/learn/fundamentals/medusa-container), which is a registry of Framework and commerce tools that you can access in the step. + - An object that has properties including the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which is a registry of Framework and commerce tools that you can access in the step. In the step function, you resolve the Review Module's service from the Medusa container using its `resolve` method, passing it the module's name as a parameter. @@ -75252,7 +75276,7 @@ The compensation function undoes the actions performed in a step. Then, if an er The compensation function accepts two parameters: 1. The data passed from the step in the second parameter of `StepResponse`, which in this case is the ID of the created review. -2. An object that has properties including the [Medusa container](undefined/docs/learn/fundamentals/medusa-container). +2. An object that has properties including the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). In the compensation function, you resolve the Review Module's service from the Medusa container and call the `deleteReviews` method to delete the review created in the step. @@ -75315,7 +75339,7 @@ In the workflow's constructor function, you: - use `useQueryGraphStep` to retrieve the product. By setting the `options.throwIfKeyNotFound` to `true`, the step throws an error if the product doesn't exist. - Call the `createReviewStep` step to create the review. -`useQueryGraphStep` uses [Query](undefined/docs/learn/fundamentals/module-links/query), which allows you to retrieve data across modules. For example, in the above snippet you're retrieving the product, which is managed in the [Product Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product), by passing `id` to the `fields` array. +`useQueryGraphStep` uses [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), which allows you to retrieve data across modules. For example, in the above snippet you're retrieving the product, which is managed in the [Product Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/index.html.md), by passing `id` to the `fields` array. A workflow must return an instance of `WorkflowResponse`. The `WorkflowResponse` constructor accepts the workflow's output as a parameter, which is an object holding the created review in this case. @@ -75325,11 +75349,11 @@ In the next step, you'll learn how to execute this workflow in an API route. ## Step 5: Create Review API Route -Now that you have the logic to create a product review, you need to expose it so that frontend clients, such as a storefront, can use it. You do this by creating an [API route](undefined/docs/learn/fundamentals/api-routes). +Now that you have the logic to create a product review, you need to expose it so that frontend clients, such as a storefront, can use it. You do this by creating an [API route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). An API Route is an endpoint that exposes commerce features to external applications and clients, such as storefronts. You'll create an API route at the path `/store/reviews` that executes the workflow from the previous step. -Learn more about API routes in [this documentation](undefined/docs/learn/fundamentals/api-routes). +Learn more about API routes in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). ### Implement API Route @@ -75398,7 +75422,7 @@ In the route handler, you execute the `createReviewWorkflow` workflow by invokin Now that you have the API route, you need to enforce validation of the request body, and require authentication to access the route. You can do this with a middleware. A middleware is a function executed when a request is sent to an API Route. It's executed before the route handler. -Learn more about middleware in the [Middlewares documentation](undefined/docs/learn/fundamentals/api-routes/middlewares). +Learn more about middleware in the [Middlewares documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md). Middlewares are created in the `src/api/middlewares.ts` file. So create the file `src/api/middlewares.ts` with the following content: @@ -75449,15 +75473,15 @@ Then, open the Medusa Admin dashboard at `http://localhost:9000/app` and login u All requests sent to routes starting with `/store` must have a publishable API key in their header. This ensures that the request is scoped to a specific sales channel of your storefront. -To learn more about publishable API keys, refer to the [Publishable API Key documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/sales-channel/publishable-api-keys). +To learn more about publishable API keys, refer to the [Publishable API Key documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/sales-channel/publishable-api-keys/index.html.md). -To retrieve the publishable API key from the Medusa Admin, refer to [this user guide](undefined/user-guide/settings/developer/publishable-api-keys). +To retrieve the publishable API key from the Medusa Admin, refer to [this user guide](https://docs.medusajs.com/user-guide/settings/developer/publishable-api-keys/index.html.md). #### Retrieve Customer Authentication Token As mentioned before, the API route you added requires the customer to be authenticated. So, you'll first create a customer, then retrieve their authentication token to use in the request. -Before creating the customer, retrieve a registration token using the [Retrieve Registration JWT Token API route](undefined/api/store#auth_postactor_typeauth_provider_register): +Before creating the customer, retrieve a registration token using the [Retrieve Registration JWT Token API route](https://docs.medusajs.com/api/store#auth_postactor_typeauth_provider_register): ```bash curl -X POST 'http://localhost:9000/auth/customer/emailpass/register' \ @@ -75470,7 +75494,7 @@ curl -X POST 'http://localhost:9000/auth/customer/emailpass/register' \ Make sure to replace the email and password with the credentials you want. -Then, register the customer using the [Create Customer API route](undefined/api/store#customers_postcustomers): +Then, register the customer using the [Create Customer API route](https://docs.medusajs.com/api/store#customers_postcustomers): ```bash curl -X POST 'http://localhost:9000/store/customers' \ @@ -75489,7 +75513,7 @@ Make sure to replace: Also, if you changed the email in the first request, make sure to change it here as well. -The customer is now registered. Lastly, you need to retrieve its authenticated token by sending a request to the [Authenticate Customer API route](undefined/api/store#auth_postactor_typeauth_provider): +The customer is now registered. Lastly, you need to retrieve its authenticated token by sending a request to the [Authenticate Customer API route](https://docs.medusajs.com/api/store#auth_postactor_typeauth_provider): ```bash curl -X POST 'http://localhost:9000/auth/customer/emailpass' \ @@ -75592,7 +75616,7 @@ You first define a `GetAdminReviewsSchema` schema that will allow clients to pas - `offset`: The number of items to skip before retrieving the reviews. - `order`: The fields to sort the reviews by in ascending or descending order. -Then, you export a `GET` function, which exposes a `GET` API Route at the path `/admin/reviews`. In the route handler you resolve [Query](undefined/docs/learn/fundamentals/module-links/query) from the Medusa container, which allows you to retrieve data across modules. +Then, you export a `GET` function, which exposes a `GET` API Route at the path `/admin/reviews`. In the route handler you resolve [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) from the Medusa container, which allows you to retrieve data across modules. Next, you retrieve all reviews using Query. Notice that you pass in `query.graph` the `req.queryConfig` object. This object holds the fields to retrieve and the pagination configurations. @@ -75655,15 +75679,15 @@ You pass `product.*` in the fields to retrieve, allowing you to retrieve the pro ## Step 7: Add Reviews UI Route -Now that you have an API route that retrieves reviews, you'll customize the Medusa Admin to add a new "Reviews" page by creating a [UI Route](undefined/docs/learn/fundamentals/admin/ui-routes). +Now that you have an API route that retrieves reviews, you'll customize the Medusa Admin to add a new "Reviews" page by creating a [UI Route](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md). A UI route is a React component that specifies the content to be shown in a new page in the Medusa Admin dashboard. You'll create a UI route to display the list of reviews in the Medusa Admin. -Learn more about UI routes in the [UI Routes documentation](undefined/docs/learn/fundamentals/admin/ui-routes). +Learn more about UI routes in the [UI Routes documentation](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md). ### Configure JS SDK -Medusa provides a [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk) that you can use to send requests to the Medusa server from any client application, including your Medusa Admin customizations. +Medusa provides a [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md) that you can use to send requests to the Medusa server from any client application, including your Medusa Admin customizations. The JS SDK is installed by default in your Medusa application. To configure it, create the file `src/admin/lib/sdk.ts` with the following content: @@ -75770,7 +75794,7 @@ const columns = [ Before defining the component, you define a `Review` type, then define the columns of the table you'll show on the page. -To display the table, you'll use the [DataTable](undefined/ui/components/data-table) component from Medusa UI. To define the columns of the table, you use the `createDataTableColumnHelper` function from Medusa UI, which returns a `columnHelper` object. You then use the `columnHelper` object to define the table's columns. +To display the table, you'll use the [DataTable](https://docs.medusajs.com/ui/components/data-table/index.html.md) component from Medusa UI. To define the columns of the table, you use the `createDataTableColumnHelper` function from Medusa UI, which returns a `columnHelper` object. You then use the `columnHelper` object to define the table's columns. Next, you'll add the component that renders the content of the page. Replace the `TODO` with the following: @@ -76266,7 +76290,7 @@ You first define a `GetStoreReviewsSchema` schema that will allow clients to pas - `offset`: The number of items to skip before retrieving the reviews. - `order`: The fields to sort the reviews by in ascending or descending order. -Then, you export a `GET` function, and that exposes a `GET` API Route at the path `/store/products/[id]/reviews`. In the route handler you resolve [Query](undefined/docs/learn/fundamentals/module-links/query) from the Medusa container, which allows you to retrieve data across modules. +Then, you export a `GET` function, and that exposes a `GET` API Route at the path `/store/products/[id]/reviews`. In the route handler you resolve [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) from the Medusa container, which allows you to retrieve data across modules. Next, you retrieve the approved reviews of a product using Query. Notice that you pass in `query.graph` the `req.queryConfig` object. This object holds the fields to retrieve and the pagination configurations. You'll configure this object in a bit. @@ -76351,7 +76375,7 @@ You define the type of a product review object and the properties it has. ### Add Functions to Fetch and Submit Reviews -Next, you'll add two functions that fetch and submit reviews using the API routes you created earlier. To send requests to the API routes, you can use Medusa's [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk). +Next, you'll add two functions that fetch and submit reviews using the API routes you created earlier. To send requests to the API routes, you can use Medusa's [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md). In `src/lib/data/products.ts`, add the following functions: @@ -76771,16 +76795,16 @@ You've now implemented product-review features in Medusa. There's still more tha - Add a feature to allow customers to upvote or downvote reviews. - Allow customers to add images to their reviews. -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). # Implement Quick Re-Order Functionality in Medusa In this tutorial, you'll learn how to implement a re-order functionality in Medusa. -When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules) which are available out-of-the-box. The features include order-management features. +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md) which are available out-of-the-box. The features include order-management features. The Medusa Framework facilitates building custom features that are necessary for your business use case. In this tutorial, you'll learn how to implement a re-order functionality in Medusa. This feature is useful for businesses whose customers are likely to repeat their orders, such as B2B or food delivery businesses. @@ -76815,34 +76839,34 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose Yes. +You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose Yes. Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name, and the Next.js Starter Storefront in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterwards, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** ## Step 2: Implement Re-Order Workflow -To build custom commerce features in Medusa, you create a [workflow](undefined/docs/learn/fundamentals/workflows). A workflow is a series of queries and actions, called steps, that complete a task. +To build custom commerce features in Medusa, you create a [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). A workflow is a series of queries and actions, called steps, that complete a task. By using workflows, you can track their executions' progress, define roll-back logic, and configure other advanced features. Then, you execute the workflow from other customizations, such as in an API Route. In this section, you'll implement the re-order functionality in a workflow. Later, you'll execute the workflow in a custom API route. -Refer to the [Workflows documentation](undefined/docs/learn/fundamentals/workflows) to learn more. +Refer to the [Workflows documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) to learn more. The workflow will have the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the order's details. -- [createCartWorkflow](undefined/references/medusa-workflows/createCartWorkflow): Create a cart for the re-order. -- [addShippingMethodToCartWorkflow](undefined/references/medusa-workflows/addShippingMethodToCartWorkflow): Add the order's shipping method(s) to the cart. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the cart's details. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the order's details. +- [createCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/createCartWorkflow/index.html.md): Create a cart for the re-order. +- [addShippingMethodToCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/addShippingMethodToCartWorkflow/index.html.md): Add the order's shipping method(s) to the cart. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the cart's details. This workflow uses steps from Medusa's `@medusajs/medusa/core-flows` package. So, you can implement the workflow without implementing custom steps. @@ -76895,9 +76919,9 @@ You create a workflow using `createWorkflow` from the Workflows SDK. It accepts It accepts as a second parameter a constructor function, which is the workflow's implementation. The function can accept input, which in this case is an object holding the ID of the order to re-order. -In the workflow's constructor function, so far you use the `useQueryGraphStep` step to retrieve the order's details. This step uses [Query](undefined/docs/learn/fundamentals/module-links/query) under the hood, which allows you to query data across [modules](undefined/docs/learn/fundamentals/modules). +In the workflow's constructor function, so far you use the `useQueryGraphStep` step to retrieve the order's details. This step uses [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) under the hood, which allows you to query data across [modules](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). -Refer to the [Query documentation](undefined/docs/learn/fundamentals/module-links/query) to learn more about how to use it. +Refer to the [Query documentation](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) to learn more about how to use it. ### b. Create a Cart @@ -76951,7 +76975,7 @@ const { id: cart_id } = createCartWorkflow.runAsStep({ Data manipulation is not allowed in a workflow, as Medusa stores its definition before executing it. Instead, you can use `transform` from the Workflows SDK to manipulate the data. -Learn more about why you can't manipulate data in a workflow and the `transform` function in the [Data Manipulation in Workflows documentation](undefined/docs/learn/fundamentals/workflows/variable-manipulation). +Learn more about why you can't manipulate data in a workflow and the `transform` function in the [Data Manipulation in Workflows documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/variable-manipulation/index.html.md). `transform` accepts the following parameters: @@ -76960,7 +76984,7 @@ Learn more about why you can't manipulate data in a workflow and the `transform` In the above code snippet, you use `transform` to create the input for the `createCartWorkflow` step. The input is an object that holds the cart's details, including its items, shipping and billing addresses, and more. -Learn about other input parameters you can pass in the [createCartWorkflow reference](undefined/references/medusa-workflows/createCartWorkflow). +Learn about other input parameters you can pass in the [createCartWorkflow reference](https://docs.medusajs.com/references/medusa-workflows/createCartWorkflow/index.html.md). After that, you execute the `createCartWorkflow` passing it the transformed input. The workflow returns the cart's details, including its ID. @@ -77045,11 +77069,11 @@ In the next step, you'll create an API route that exposes the re-order functiona ## Step 3: Create Re-Order API Route -Now that you have the logic to re-order, you need to expose it so that frontend clients, such as a storefront, can use it. You do this by creating an [API route](undefined/docs/learn/fundamentals/api-routes). +Now that you have the logic to re-order, you need to expose it so that frontend clients, such as a storefront, can use it. You do this by creating an [API route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). An API Route is an endpoint that exposes commerce features to external applications and clients, such as storefronts. You'll create an API route at the path `/store/customers/me/orders/:id` that executes the workflow from the previous step. -Refer to the [API Routes documentation](undefined/docs/learn/fundamentals/api-routes) to learn more. +Refer to the [API Routes documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) to learn more. An API route is created in a `route.ts` file under a sub-directory of the `src/api` directory. The path of the API route is the file's path relative to `src/api`. @@ -77082,7 +77106,7 @@ export async function POST( Since you export a `POST` route handler function, you expose a `POST` API route at `/store/customers/me/orders/:id`. -API routes that start with `/store/customers/me` are protected by default, meaning that only authenticated customers can access them. Learn more in the [Protected API Routes documentation](undefined/docs/learn/fundamentals/api-routes/protected-routes). +API routes that start with `/store/customers/me` are protected by default, meaning that only authenticated customers can access them. Learn more in the [Protected API Routes documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/protected-routes/index.html.md). The route handler function accepts two parameters: @@ -77091,7 +77115,7 @@ The route handler function accepts two parameters: In the route handler function, you execute the `reorderWorkflow`. To execute a workflow, you: -- Invoke it, passing it the [Medusa container](undefined/docs/learn/fundamentals/medusa-container) available in the `req.scope` property. +- Invoke it, passing it the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md) available in the `req.scope` property. - The Medusa container is a registry of Framework and commerce resources that you can resolve and use in your customizations. - Call the `run` method, passing it an object with the workflow's input. @@ -77103,7 +77127,7 @@ You'll test out this API route after you customize the Next.js Starter Storefron ## Step 4: Customize the Next.js Starter Storefront -In this step, you'll customize the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter) to add a re-order button. You installed the Next.js Starter Storefront in the first step with the Medusa application, but you can also install it separately as explained in the [Next.js Starter Storefront documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter). +In this step, you'll customize the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) to add a re-order button. You installed the Next.js Starter Storefront in the first step with the Medusa application, but you can also install it separately as explained in the [Next.js Starter Storefront documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md). The Next.js Starter Storefront provides rich commerce features and a sleek design. You can use it as-is or build on top of it to tailor it for your business's unique use case, design, and customer experience. @@ -77152,9 +77176,9 @@ export const reorder = async (id: string) => { You add a function that accepts the order ID as a parameter. -The function uses the `client.fetch` method of the [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk) to send a request to the API route you created in the previous step. +The function uses the `client.fetch` method of the [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md) to send a request to the API route you created in the previous step. -The JS SDK is already configured in the Next.js Starter Storefront. Refer to the [JS SDK documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk) to learn more about it. +The JS SDK is already configured in the Next.js Starter Storefront. Refer to the [JS SDK documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md) to learn more about it. Once the request succeeds, you use the `setCartId` function that's defined in the storefront to set the cart ID in a cookie. This ensures the cart is used across the storefront. @@ -77273,20 +77297,20 @@ You now have a re-order functionality in your Medusa application and Next.js Sta For example, you can add quick orders on the storefront's homepage, allowing customers to quickly re-order their last orders. -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). # Use Saved Payment Methods During Checkout In this tutorial, you'll learn how to allow customers to save their payment methods and use them for future purchases. -When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules) which are available out-of-the-box. +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md) which are available out-of-the-box. Medusa's architecture facilitates integrating third-party services, such as payment providers. These payment providers can process payments and securely store customers' payment methods for future use. -In this tutorial, you'll expand on Medusa's [Stripe Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe) to allow customers to re-use their saved payment methods during checkout. +In this tutorial, you'll expand on Medusa's [Stripe Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe/index.html.md) to allow customers to re-use their saved payment methods during checkout. You can follow this guide whether you're new to Medusa or an advanced Medusa developer. @@ -77321,23 +77345,23 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose Yes. +You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose Yes. Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name, and the Next.js Starter Storefront in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterwards, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** ## Step 2: Set Up the Stripe Module Provider -Medusa's [Payment Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment) provides payment-related models and the interface to manage and process payments. However, it delegates the actual payment processing to module providers that integrate third-party payment services. +Medusa's [Payment Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/index.html.md) provides payment-related models and the interface to manage and process payments. However, it delegates the actual payment processing to module providers that integrate third-party payment services. -The [Stripe Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe) is a Payment Module Provider that integrates Stripe into your Medusa application to process payments. It can also save payment methods securely. +The [Stripe Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe/index.html.md) is a Payment Module Provider that integrates Stripe into your Medusa application to process payments. It can also save payment methods securely. In this section, you'll set up the Stripe Module Provider in your Medusa application. @@ -77380,7 +77404,7 @@ You register provides in the `providers` option of the Payment Module. Each prov - `id`: The ID of the provider. This is used to identify the provider in the Medusa application. - `options`: The options to be passed to the provider. In this case, the `apiKey` option is required for the Stripe Module Provider. -Learn about other options in the [Stripe Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe#module-options) documentation. +Learn about other options in the [Stripe Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe#module-options/index.html.md) documentation. ### Add Environment Variables @@ -77396,7 +77420,7 @@ Where `STRIPE_API_KEY` is your Stripe Secret API Key. You can find it in the Str ### Enable Stripe in a Region -In Medusa, each [region](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/region) (which is a geographical area where your store operates) can have different payment methods enabled. So, after registering the Stripe Module Provider, you need to enable it in a region. +In Medusa, each [region](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/region/index.html.md) (which is a geographical area where your store operates) can have different payment methods enabled. So, after registering the Stripe Module Provider, you need to enable it in a region. To enable it in a region, start the Medusa application with the following command: @@ -77423,7 +77447,7 @@ The Stripe Module Provider supports different payment methods in Stripe, such as ### Add Evnironement Variable to Storefront -The [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter) supports payment with Stripe during checkout if it's enabled in the region. +The [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) supports payment with Stripe during checkout if it's enabled in the region. The Next.js Starter Storefront was installed in a separate directory from Medusa. The directory's name is `{your-project}-storefront`. @@ -77445,15 +77469,15 @@ Where `NEXT_PUBLIC_STRIPE_KEY` is your Stripe public API key. You can find it in ## Step 3: List Payment Methods API Route -The Payment Module uses [account holders](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/account-holder) to represent a customer's details that are stored in a third-party payment provider. Medusa creates an account holder for each customer, allowing you later to retrieve the customer's saved payment methods in the third-party provider. +The Payment Module uses [account holders](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/account-holder/index.html.md) to represent a customer's details that are stored in a third-party payment provider. Medusa creates an account holder for each customer, allowing you later to retrieve the customer's saved payment methods in the third-party provider. ![Diagram illustrating the relation between customers and account holders in Medusa, and customers in Stripe](https://res.cloudinary.com/dza7lstvk/image/upload/v1745314344/Medusa%20Resources/customer-account-stripe_in5ei6.jpg) -While this feature is available out-of-the-box, you need to expose it to clients, like storefronts, by creating an [API route](undefined/docs/learn/fundamentals/api-routes). An API Route is an endpoint that exposes commerce features to external applications and clients. +While this feature is available out-of-the-box, you need to expose it to clients, like storefronts, by creating an [API route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). An API Route is an endpoint that exposes commerce features to external applications and clients. In this step, you'll create an API route that lists the saved payment methods for an authenticated customer. -Refer to the [API routes](undefined/docs/learn/fundamentals/api-routes) documentation to learn more. +Refer to the [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) documentation to learn more. ### Create API Route @@ -77515,16 +77539,16 @@ Since you export a route handler function named `GET`, you expose a `GET` API ro 1. A request object with details and context on the request, such as body parameters or authenticated customer details. 2. A response object to manipulate and send the response. -The request object has a `scope` property, which is an instance of the [Medusa container](undefined/docs/learn/fundamentals/medusa-container). The Medusa container is a registry of Framework and commerce tools that you can access in the API route. +The request object has a `scope` property, which is an instance of the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). The Medusa container is a registry of Framework and commerce tools that you can access in the API route. You use the Medusa container to resolve: -- [Query](undefined/docs/learn/fundamentals/module-links/query), which is a tool that retrieves data across modules in the Medusa application. -- The [Payment Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment)'s service, which provides an interface to manage and process payments with third-party providers. +- [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), which is a tool that retrieves data across modules in the Medusa application. +- The [Payment Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/index.html.md)'s service, which provides an interface to manage and process payments with third-party providers. You use Query to retrieve the account holder with the ID passed as a path parameter. If the account holder is not found, you throw an error. -Then, you use the [listPaymentMethods](undefined/references/payment/listPaymentMethods) method of the Payment Module's service to retrieve the payment providers saved in the third-party provider. The method accepts an object with the following properties: +Then, you use the [listPaymentMethods](https://docs.medusajs.com/references/payment/listPaymentMethods/index.html.md) method of the Payment Module's service to retrieve the payment providers saved in the third-party provider. The method accepts an object with the following properties: - `provider_id`: The ID of the provider, such as Stripe's ID. The account holder stores the ID its associated provider. - `context`: The context of the request. In this case, you pass the account holder's ID to retrieve the payment methods associated with it in the third-party provider. @@ -77535,9 +77559,9 @@ Finally, you return the payment methods in the response. Only authenticated customers can access and use saved payment methods. So, you need to protect the API route to ensure that only authenticated customers can access it. -To protect an API route, you can add a [middleware](undefined/docs/learn/fundamentals/api-routes/middlewares). A middleware is a function executed when a request is sent to an API Route. You can add an authentication middleware that ensures that the request is authenticated before executing the route handler function. +To protect an API route, you can add a [middleware](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md). A middleware is a function executed when a request is sent to an API Route. You can add an authentication middleware that ensures that the request is authenticated before executing the route handler function. -Refer to the [Middlewares](undefined/docs/learn/fundamentals/api-routes/middlewares) documentation to learn more. +Refer to the [Middlewares](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md) documentation to learn more. Middlewares are added in the `src/api/middlewares.ts` file. So, create the file with the following content: @@ -77565,7 +77589,7 @@ The `src/api/middlewares.ts` file must use the `defineMiddlewares` function and You apply the `authenticate` middleware to the API route you created earlier. The `authenticate` middleware ensures that only authenticated customers can access the API route. -Refer to the [Protected Routes](undefined/docs/learn/fundamentals/api-routes/protected-routes) documentation to learn more about the `authenticate` middleware. +Refer to the [Protected Routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/protected-routes/index.html.md) documentation to learn more about the `authenticate` middleware. Your API route can now only be accessed by authenticated customers. You'll test it out as you customize the Next.js Starter Storefront in the next steps. @@ -77573,7 +77597,7 @@ Your API route can now only be accessed by authenticated customers. You'll test ## Step 4: Save Payment Methods During Checkout -In this step, you'll customize the checkout flow in the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter) to save payment methods during checkout. +In this step, you'll customize the checkout flow in the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) to save payment methods during checkout. The Next.js Starter Storefront was installed in a separate directory from Medusa. The directory's name is `{your-project}-storefront`. @@ -77583,9 +77607,9 @@ So, if your Medusa application's directory is `medusa-payment`, you can find the cd ../medusa-payment-storefront # change based on your project name ``` -During checkout, when the customer chooses a payment method, such as Stripe, the Next.js Starter Storefront creates a [payment session](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-session) in Medusa using the [Initialize Payment Session](undefined/api/store#payment-collections_postpaymentcollectionsidpaymentsessions) API route. +During checkout, when the customer chooses a payment method, such as Stripe, the Next.js Starter Storefront creates a [payment session](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-session/index.html.md) in Medusa using the [Initialize Payment Session](https://docs.medusajs.com/api/store#payment-collections_postpaymentcollectionsidpaymentsessions) API route. -Under the hood, Medusa uses the associated payment provider (Stripe) to initiate the payment process with the associated third-party payment provider. The [Initialize Payment Session](undefined/api/store#payment-collections_postpaymentcollectionsidpaymentsessions) API route accepts a `data` object parameter in the request body that allows you to pass data relevant to the third-party payment provider. +Under the hood, Medusa uses the associated payment provider (Stripe) to initiate the payment process with the associated third-party payment provider. The [Initialize Payment Session](https://docs.medusajs.com/api/store#payment-collections_postpaymentcollectionsidpaymentsessions) API route accepts a `data` object parameter in the request body that allows you to pass data relevant to the third-party payment provider. So, to save the payment method that the customer uses during checkout with Stripe, you must pass the `setup_future_usage` property in the `data` object. The `setup_future_usage` property is a Stripe-specific property that allows you to save the payment method for future use. @@ -78115,11 +78139,11 @@ Once the order is placed successfully, you can check it in the Medusa Admin dash You've added support for saved payment methods in your Medusa application and Next.js Starter Storefront, allowing customers to save their payment methods during checkout and use them in future orders. -You can add more features to the saved payment methods, such as allowing customers to delete saved payment methods. You can use [Stripe's APIs](https://docs.stripe.com/api/payment_methods/detach) in the storefront or add an [API route](undefined/docs/learn/fundamentals/api-routes) in Medusa to delete the saved payment method. +You can add more features to the saved payment methods, such as allowing customers to delete saved payment methods. You can use [Stripe's APIs](https://docs.stripe.com/api/payment_methods/detach) in the storefront or add an [API route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) in Medusa to delete the saved payment method. -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). # Integrate Algolia (Search) with Medusa @@ -78162,15 +78186,15 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose "Yes." +You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose "Yes." Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name and the Next.js Starter Storefront in a separate directory named `{project-name}-storefront`. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterwards, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** @@ -78180,7 +78204,7 @@ To integrate third-party services into Medusa, you create a custom module. A mod In this step, you'll create a custom module that provides the necessary functionalities to integrate Algolia with Medusa. -Refer to the [Modules documentation](undefined/docs/learn/fundamentals/modules) to learn more. +Refer to the [Modules documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) to learn more. Before building the module, you need to install Algolia's JavaScript client. Run the following command in your Medusa application's root directory: @@ -78236,7 +78260,7 @@ If you want to index other types of data, such as product categories, you can ad A module's service receives the module's options as a second parameter in its constructor. In the constructor, you initialize the Algolia client using the module's options. -A module has a container that holds all resources registered in that module, and you can access those resources in the first parameter of the constructor. Learn more about it in the [Module Container documentation](undefined/docs/learn/fundamentals/modules/container). +A module has a container that holds all resources registered in that module, and you can access those resources in the first parameter of the constructor. Learn more about it in the [Module Container documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/container/index.html.md). #### Index Data Method @@ -78426,15 +78450,15 @@ Your module is now ready for use. You'll see how to use it in the next steps. To keep the Algolia index in sync with Medusa, you need to trigger indexing when products are created, updated, or deleted in Medusa. You can also allow the admin to manually trigger a reindex. -To implement the indexing functionality, you need to create a [workflow](undefined/docs/learn/fundamentals/workflows). A workflow is a series of actions, called steps, that complete a task. You construct a workflow like you construct a function, but it's a special function that allows you to track its executions' progress, define roll-back logic, and configure other advanced features. +To implement the indexing functionality, you need to create a [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). A workflow is a series of actions, called steps, that complete a task. You construct a workflow like you construct a function, but it's a special function that allows you to track its executions' progress, define roll-back logic, and configure other advanced features. -Learn more about workflows in the [Workflows documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in the [Workflows documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). In this step, you'll create a workflow that indexes products in Algolia. In the next steps, you'll learn how to use the workflow when products are created, updated, or deleted, or when the admin manually triggers a reindex. The workflow has the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve products matching specified filters and pagination parameters. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve products matching specified filters and pagination parameters. - [syncProductsStep](#syncProductsStep): Index products in Algolia. Medusa provides the `useQueryGraphStep` in its `@medusajs/medusa/core-flows` package. So, you only need to implement the second step. @@ -78486,7 +78510,7 @@ You create a step with `createStep` from the Workflows SDK. It accepts two param 1. The step's unique name, which is `sync-products`. 2. An async function that receives two parameters: - The step's input, which is in this case an object holding an array of products to sync into Algolia. - - An object that has properties including the [Medusa container](undefined/docs/learn/fundamentals/medusa-container), which is a registry of Framework and commerce tools that you can access in the step. + - An object that has properties including the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which is a registry of Framework and commerce tools that you can access in the step. In the step function, you resolve the Algolia Module's service from the Medusa container using the name you exported in the module definition's file. @@ -78561,7 +78585,18 @@ export const syncProductsWorkflow = createWorkflow( ({ filters, limit, offset }: SyncProductsWorkflowInput) => { const { data, metadata } = useQueryGraphStep({ entity: "product", - fields: ["id", "title", "description", "handle", "thumbnail", "categories.*", "tags.*"], + fields: [ + "id", + "title", + "description", + "handle", + "thumbnail", + "categories.id", + "categories.name", + "categories.handle", + "tags.id", + "tags.value", + ], pagination: { take: limit, skip: offset, @@ -78590,7 +78625,7 @@ It accepts as a second parameter a constructor function, which is the workflow's In the workflow's constructor function, you: -1. Execute `useQueryGraphStep` to retrieve products from Medusa's database. This step uses Medusa's [Query](undefined/docs/learn/fundamentals/module-links/query) tool to retrieve data across modules. You pass it the pagination and filter parameters you received in the input. +1. Execute `useQueryGraphStep` to retrieve products from Medusa's database. This step uses Medusa's [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) tool to retrieve data across modules. You pass it the pagination and filter parameters you received in the input. 2. Execute `syncProductsStep` to index the products in Algolia. You pass it the products you retrieved in the previous step. A workflow must return an instance of `WorkflowResponse`. The `WorkflowResponse` constructor accepts the workflow's output as a parameter, which is an object holding the retrieved products and their pagination details. @@ -78613,7 +78648,7 @@ In this step, you'll add the functionality to trigger the `syncProductsWorkflow` A subscriber is an asynchronous function that listens to one or more events and performs actions when these events are emitted. A subscriber is useful when syncing data across systems, as the operation can be time-consuming and should be performed in the background. -Learn more about subscribers in the [Events and Subscribers documentation](undefined/docs/learn/fundamentals/events-and-subscribers). +Learn more about subscribers in the [Events and Subscribers documentation](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md). You create a subscriber in a TypeScript or JavaScript file under the `src/subscribers` directory. So, to create the subscriber that listens to the `algolia.sync` event, create the file `src/subscribers/algolia-sync.ts` with the following content: @@ -78679,7 +78714,7 @@ To allow the Medusa Admin dashboard to trigger the `algolia.sync` event, you nee An API Route is an endpoint that exposes commerce features to external applications and clients, such as storefronts. -Learn more about API routes in [this documentation](undefined/docs/learn/fundamentals/api-routes). +Learn more about API routes in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). An API route is created in a `route.ts` file under a sub-directory of the `src/api` directory. The path of the API route is the file's path relative to `src/api`. @@ -78709,7 +78744,7 @@ Since you export a `POST` route handler function, you expose a `POST` API route 1. A request object with details and context on the request, such as body parameters or authenticated user details. 2. A response object to manipulate and send the response. -In the route handler, you use the Medusa container that is available in the request object to resolve the [Event Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/event). This module manages events and their subscribers. +In the route handler, you use the Medusa container that is available in the request object to resolve the [Event Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/event/index.html.md). This module manages events and their subscribers. Then, you emit the `algolia.sync` event using the Event Module's `emit` method, passing it the event name. @@ -78717,15 +78752,15 @@ Finally, you send a response with a message indicating that data is being synced ### Add Algolia Sync Page to Admin Dashboard -The last step is to add a new page to the admin dashboard that allows the admin to trigger the reindex. You add a new page using a [UI Route](undefined/docs/learn/fundamentals/admin/ui-routes). +The last step is to add a new page to the admin dashboard that allows the admin to trigger the reindex. You add a new page using a [UI Route](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md). A UI route is a React component that specifies the content to be shown in a new page in the Medusa Admin dashboard. You'll create a UI route to display a button that triggers the reindex when clicked. -Learn more about UI routes in the [UI Routes documentation](undefined/docs/learn/fundamentals/admin/ui-routes). +Learn more about UI routes in the [UI Routes documentation](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md). #### Configure JS SDK -Before creating the UI route, you'll configure Medusa's [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk) that you can use to send requests to the Medusa server from any client application, including your Medusa Admin customizations. +Before creating the UI route, you'll configure Medusa's [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md) that you can use to send requests to the Medusa server from any client application, including your Medusa Admin customizations. The JS SDK is installed by default in your Medusa application. To configure it, create the file `src/admin/lib/sdk.ts` with the following content: @@ -78824,7 +78859,7 @@ npm run dev Then, open the Medusa Admin at `http://localhost:9000/app` and log in with the credentials you set up in the first step. -Can't remember the credentials? Learn how to create a user in the [Medusa CLI reference](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/medusa-cli/commands/user). +Can't remember the credentials? Learn how to create a user in the [Medusa CLI reference](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/medusa-cli/commands/user/index.html.md). After you log in, go to Settings from the sidebar. You'll find in the Settings' sidebar a new "Algolia" item. If you click on it, you'll find the page you created with the button to sync products to Algolia. @@ -79068,9 +79103,9 @@ Finally, you return the search results as it is in the response. ### Add Validation Middleware -To ensure that requests sent to the API route have the required request body parameters, you can use a [middleware](undefined/docs/learn/fundamentals/api-routes/middlewares). A middleware is a function executed when a request is sent to an API Route. It's executed before the route handler. +To ensure that requests sent to the API route have the required request body parameters, you can use a [middleware](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md). A middleware is a function executed when a request is sent to an API Route. It's executed before the route handler. -Learn more about middleware in the [Middlewares documentation](undefined/docs/learn/fundamentals/api-routes/middlewares). +Learn more about middleware in the [Middlewares documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md). Middlewares are created in the `src/api/middlewares.ts` file. So create the file `src/api/middlewares.ts` with the following content: @@ -79106,7 +79141,7 @@ You can use the search API route now. You'll see it in action as you customize t ## Step 7: Search Products in Next.js Starter Storefront -The last step is to provide the search functionalities to customers on your storefront. In the first step, you installed the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter) along with the Medusa application. +The last step is to provide the search functionalities to customers on your storefront. In the first step, you installed the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) along with the Medusa application. In this step, you'll customize the Next.js Starter Storefront to add the search functionality. @@ -79331,16 +79366,16 @@ You've now integrated Algolia with Medusa and added search functionality to your - Add filters to the search results. You can do that using Algolia's [widgets](https://www.algolia.com/doc/guides/building-search-ui/widgets/showcase/react/) and customizing the search API route in Medusa to accept filter parameters. - Support indexing other data types, such as product categories. You can create the subscribers and workflows for categories similar to products. -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). # Implement Localization in Medusa by Integrating Contentful In this tutorial, you'll learn how to localize your Medusa store's data with Contentful. -When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. While Medusa provides features essential for internationalization, such as support for multiple [regions](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/region) and [currencies](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/currency), it doesn't provide content localization. +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. While Medusa provides features essential for internationalization, such as support for multiple [regions](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/region/index.html.md) and [currencies](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/currency/index.html.md), it doesn't provide content localization. However, Medusa's architecture supports the integration of third-party services to provide additional features, such as data localization. One service you can integrate is [Contentful](https://www.contentful.com/), a headless content management system (CMS) that allows you to manage and deliver content across multiple channels. @@ -79354,7 +79389,7 @@ By following this tutorial, you'll learn how to: - Trigger syncing products and related data to Contentful when: - A product is created. - The admin user triggers syncing the products. -- Customize the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter) to fetch localized data from Contentful through Medusa. +- Customize the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) to fetch localized data from Contentful through Medusa. - Listen to webhook events in Contentful to update Medusa's data accordingly. You can follow this tutorial whether you're new to Medusa or an advanced Medusa developer. @@ -79380,25 +79415,25 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -First, you'll be asked for the project's name. Then, when prompted about installing the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose "Yes." +First, you'll be asked for the project's name. Then, when prompted about installing the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose "Yes." Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name and the Next.js Starter Storefront in a separate directory named `{project-name}-storefront`. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterwards, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** ## Step 2: Create Contentful Module -To integrate third-party services into Medusa, you create a module. A [module](undefined/docs/learn/fundamentals/modules) is a reusable package that provides functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. +To integrate third-party services into Medusa, you create a module. A [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) is a reusable package that provides functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. In this step, you'll create a module that provides the necessary functionalities to integrate Contentful with Medusa. -Refer to the [Modules](undefined/docs/learn/fundamentals/modules) documentation to learn more about modules and their structure. +Refer to the [Modules](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) documentation to learn more about modules and their structure. ### Install Contentful SDKs @@ -79418,9 +79453,9 @@ A module is created under the `src/modules` directory of your Medusa application When the Medusa application starts, you want to establish a connection to Contentful, then create the necessary content types if they don't exist in Contentful. -A module can specify a task to run on the Medusa application's startup using [loaders](undefined/docs/learn/fundamentals/modules/loaders). A loader is an asynchronous function that a module exports. Then, when the Medusa application starts, it runs the loader. The loader can be used to perform one-time tasks such as connecting to a database, creating content types, or initializing data. +A module can specify a task to run on the Medusa application's startup using [loaders](https://docs.medusajs.com/docs/learn/fundamentals/modules/loaders/index.html.md). A loader is an asynchronous function that a module exports. Then, when the Medusa application starts, it runs the loader. The loader can be used to perform one-time tasks such as connecting to a database, creating content types, or initializing data. -Refer to the [Loaders](undefined/docs/learn/fundamentals/modules/loaders) documentation to learn more about how loaders work and when to use them. +Refer to the [Loaders](https://docs.medusajs.com/docs/learn/fundamentals/modules/loaders/index.html.md) documentation to learn more about how loaders work and when to use them. Loaders are created in a TypeScript or JavaScript file under the `loaders` directory of a module. So, create the file `src/modules/contentful/loader/create-content-models.ts` with the following content: @@ -79487,11 +79522,11 @@ export default async function syncContentModelsLoader({ The loader file exports an asynchronous function that accepts an object having the following properties: -- `container`: The [Module container](undefined/docs/learn/fundamentals/modules/container), which is a registry of resources available to the module. You can use it to resolve or register resources in the module's container. +- `container`: The [Module container](https://docs.medusajs.com/docs/learn/fundamentals/modules/container/index.html.md), which is a registry of resources available to the module. You can use it to resolve or register resources in the module's container. - `options`: An object of options passed to the module. These options are useful to pass secrets or options that may change per environment. You'll learn how to pass these options later. - The Contentful Module expects the options to include the Contentful tokens for the management and delivery APIs, the space ID, environment, and optionally the default locale to use. -In the loader function, you validate the options passed to the module, and throw an error if they're invalid. Then, you resolve from the Module's container the [Logger](undefined/docs/learn/debugging-and-testing/logging) used to log messages in the terminal. +In the loader function, you validate the options passed to the module, and throw an error if they're invalid. Then, you resolve from the Module's container the [Logger](https://docs.medusajs.com/docs/learn/debugging-and-testing/logging/index.html.md) used to log messages in the terminal. Finally, you create clients for Contentful's management and delivery APIs, passing them the necessary module's options. If the connection fails, an error is thrown, which is handled in the `catch` block. @@ -79501,7 +79536,7 @@ In the loader, you need to create content types in Contentful if they don't alre In this tutorial, you'll only create content types for a product and its variants and options. However, you can create content types for other data models, such as categories or collections, by following the same approach. -You can learn more about the product-related data models, which the content types are based on, in the [Product Module's Data Models](undefined/references/product/models) reference. +You can learn more about the product-related data models, which the content types are based on, in the [Product Module's Data Models](https://docs.medusajs.com/references/product/models/index.html.md) reference. To create the content type for products, replace the `TODO` in the loader with the following: @@ -80455,15 +80490,15 @@ You now have all the methods necessary to build the creation flow. To implement the logic that's triggered when a product is created in Medusa, or when the admin user triggers a sync manually, you need to create a workflow. -A [workflow](undefined/docs/learn/fundamentals/workflows) is a series of actions, called steps, that complete a task. You construct a workflow like you construct a function, but it's a special function that allows you to track its executions' progress, define roll-back logic, and configure other advanced features. +A [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) is a series of actions, called steps, that complete a task. You construct a workflow like you construct a function, but it's a special function that allows you to track its executions' progress, define roll-back logic, and configure other advanced features. -Learn more about workflows in the [Workflows documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in the [Workflows documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). In this section, you'll create a workflow that creates Medusa products in Contentful using the Contentful Module. The workflow has the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve products to create in Contentful. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve products to create in Contentful. - [createProductsContentfulStep](#createProductsContentfulStep): Create the products in Contentful. Medusa provides the `useQueryGraphStep` in its `@medusajs/medusa/core-flows` package. So, you only need to implement the second step. @@ -80529,10 +80564,10 @@ You create a step with `createStep` from the Workflows SDK. It accepts three par 1. The step's unique name, which is `create-products-contentful-step`. 2. An async function that receives two parameters: - The step's input, which is in this case an object holding an array of products to create in Contentful. - - An object that has properties including the [Medusa container](undefined/docs/learn/fundamentals/medusa-container), which is a registry of Framework and commerce tools that you can access in the step. + - An object that has properties including the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which is a registry of Framework and commerce tools that you can access in the step. 3. An optional compensation function that undoes the actions performed in the step if an error occurs in the workflow's execution. This mechanism ensures data consistency in your application, especially as you integrate external systems. -The Medusa container is different from the module's container. Since modules are isolated, they each have a container with their resources. Refer to the [Module Container](undefined/docs/learn/fundamentals/modules/container) documentation for more information. +The Medusa container is different from the module's container. Since modules are isolated, they each have a container with their resources. Refer to the [Module Container](https://docs.medusajs.com/docs/learn/fundamentals/modules/container/index.html.md) documentation for more information. In the step function, you resolve the Contentful Module's service from the Medusa container using the name you exported in the module definition's file. @@ -80600,7 +80635,7 @@ It accepts as a second parameter a constructor function, which is the workflow's In the workflow's constructor function, you: -1. Retrieve the Medusa products using the `useQueryGraphStep` helper step. This step uses Medusa's [Query](undefined/docs/learn/fundamentals/module-links/query) tool to retrieve data across modules. You pass it the product IDs to retrieve. +1. Retrieve the Medusa products using the `useQueryGraphStep` helper step. This step uses Medusa's [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) tool to retrieve data across modules. You pass it the product IDs to retrieve. 2. Create the product entries in Contentful using the `createProductsContentfulStep` step. A workflow must return an instance of `WorkflowResponse`. The `WorkflowResponse` constructor accepts the workflow's output as a parameter, which is an object of the product entries created in Contentful. @@ -80613,11 +80648,11 @@ You now have the workflow that you can execute when a product is created in Medu Medusa has an event system that allows you to listen for events, such as `product.created`, and perform an asynchronous action when the event is emitted. -You listen to events in a subscriber. A [subscriber](undefined/docs/learn/fundamentals/events-and-subscribers) is an asynchronous function that listens to one or more events and performs actions when these events are emitted. A subscriber is useful when syncing data across systems, as the operation can be time-consuming and should be performed in the background. +You listen to events in a subscriber. A [subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md) is an asynchronous function that listens to one or more events and performs actions when these events are emitted. A subscriber is useful when syncing data across systems, as the operation can be time-consuming and should be performed in the background. In this step, you'll create a subscriber that listens to the `product.created` event and executes the `createProductsContentfulWorkflow` workflow. -Learn more about subscribers in the [Events and Subscribers documentation](undefined/docs/learn/fundamentals/events-and-subscribers). +Learn more about subscribers in the [Events and Subscribers documentation](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md). To create a subscriber, create the file `src/subscribers/create-product.ts` with the following content: @@ -80673,7 +80708,7 @@ npm run dev Then, open the Medusa Admin dashboard and login. -Can't remember the credentials? Learn how to create a user in the [Medusa CLI reference](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/medusa-cli/commands/user). +Can't remember the credentials? Learn how to create a user in the [Medusa CLI reference](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/medusa-cli/commands/user/index.html.md). Next, open the Products page and create a new product. @@ -80761,7 +80796,7 @@ export const config: SubscriberConfig = { You create a subscriber that listens to the `products.sync` event. -In the subscriber function, you use [Query](undefined/docs/learn/fundamentals/module-links/query) to retrieve all the products in Medusa with pagination. Then, for each batch of products, you execute the `createProductsContentfulWorkflow` workflow, passing the product IDs to the workflow. +In the subscriber function, you use [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) to retrieve all the products in Medusa with pagination. Then, for each batch of products, you execute the `createProductsContentfulWorkflow` workflow, passing the product IDs to the workflow. Finally, you log a message to the console to indicate that the products were synced to Contentful. @@ -80771,7 +80806,7 @@ Next, to allow the admin user to trigger the sync manually, you need to create a An API Route is an endpoint that exposes commerce features to external applications and clients, such as storefronts. -Learn more about API routes in [this documentation](undefined/docs/learn/fundamentals/api-routes). +Learn more about API routes in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). An API route is created in a `route.ts` file under a sub-directory of the `src/api` directory. The path of the API route is the file's path relative to `src/api`. @@ -80805,19 +80840,19 @@ Since you export a `POST` route handler function, you expose an `API` route at ` 1. A request object with details and context on the request, such as body parameters or authenticated user details. 2. A response object to manipulate and send the response. -In the route handler, you resolve the [Event Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/event)'s service from the Medusa container and emit the `products.sync` event. +In the route handler, you resolve the [Event Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/event/index.html.md)'s service from the Medusa container and emit the `products.sync` event. ### Create UI Route to Trigger Sync Finally, you'll add a new page to the Medusa Admin dashboard that displays a button to trigger the sync. To add a page, you need to create a UI route. -A [UI route](undefined/docs/learn/fundamentals/admin/ui-routes) is a React component that specifies the content to be shown in a new page of the Medusa Admin dashboard. You'll create a UI route to display a button that triggers product syncing to Contentful when clicked. +A [UI route](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md) is a React component that specifies the content to be shown in a new page of the Medusa Admin dashboard. You'll create a UI route to display a button that triggers product syncing to Contentful when clicked. -Refer to the [UI Routes](undefined/docs/learn/fundamentals/admin/ui-routes) documentation for more information. +Refer to the [UI Routes](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md) documentation for more information. #### Configure JS SDK -Before creating the UI route, you'll configure Medusa's [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk) so that you can use it to send requests to the Medusa server. +Before creating the UI route, you'll configure Medusa's [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md) so that you can use it to send requests to the Medusa server. The JS SDK is installed by default in your Medusa application. To configure it, create the file `src/admin/lib/sdk.ts` with the following content: @@ -81014,7 +81049,7 @@ Finally, you return the formatted locales in the JSON response. ### Customize Storefront to Show Locales -In the first step of this tutorial, you installed the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter) along with the Medusa application. This storefront provides ecommerce features like a product catalog, a cart, and a checkout. +In the first step of this tutorial, you installed the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) along with the Medusa application. This storefront provides ecommerce features like a product catalog, a cart, and a checkout. In this section, you'll customize the storefront to show the locales to customers and allow them to select from them. The selected locale will be stored in the browser's cookies, allowing you to use it later when retrieving a product's localized data. @@ -81280,13 +81315,13 @@ You'll implement this feature by: ### Link Medusa's Product to Contentful's Product -Medusa facilitates retrieving data across systems using [module links](undefined/docs/learn/fundamentals/module-links). A module link forms an association between data models of two modules while maintaining module isolation. +Medusa facilitates retrieving data across systems using [module links](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md). A module link forms an association between data models of two modules while maintaining module isolation. -Not only do module links support Medusa data models, but they also support virtual data models that are not persisted in Medusa's database. In that case, you create a [read-only module link](undefined/docs/learn/fundamentals/module-links/read-only) that allows you to retrieve data across systems. +Not only do module links support Medusa data models, but they also support virtual data models that are not persisted in Medusa's database. In that case, you create a [read-only module link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/read-only/index.html.md) that allows you to retrieve data across systems. In this section, you'll define a read-only module link between Medusa's product and Contentful's product, allowing you to later retrieve a product's entry in Contentful within a single query. -Learn more about read-only module links in the [Read-Only Module Links](undefined/docs/learn/fundamentals/module-links/read-only) documentation. +Learn more about read-only module links in the [Read-Only Module Links](https://docs.medusajs.com/docs/learn/fundamentals/module-links/read-only/index.html.md) documentation. Module links are defined in a TypeScript or JavaScript file under the `src/links` directory. So, create the file `src/links/product-contentful.ts` with the following content: @@ -81411,7 +81446,7 @@ Then, you format the retrieved products to: - Pass the product's ID in the `product_id` property. This is essential to map a product in Medusa to its entry in Contentful. - Remove the circular references in the product's variants, options, and values to avoid infinite loops. -To paginate the retrieved products, implemet a `listAndCount` method as explained in the [Query Context](undefined/docs/learn/fundamentals/module-links/query-context#using-pagination-with-query) documentation. +To paginate the retrieved products, implemet a `listAndCount` method as explained in the [Query Context](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query-context#using-pagination-with-query/index.html.md) documentation. ### Retrieve Product Details for Locale API Route @@ -81460,14 +81495,14 @@ export const GET = async ( Since you export a `GET` route handler function, you expose a `GET` route at `/store/products/[id]/[locale]`. The route accepts two path parameters: the product's ID and the locale code. -In the route handler, you retrieve the `locale` and `id` path parameters from the request. Then, you resolve [Query](undefined/docs/learn/fundamentals/module-links/query) from the Medusa container. +In the route handler, you retrieve the `locale` and `id` path parameters from the request. Then, you resolve [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) from the Medusa container. Next, you use Query to retrieve the localized details of the specified product. To do that, you pass an object with the following properties: - `entity`: The entity to retrieve, which is `product`. - `fields`: The fields to retrieve. Notice that you include the `contentful_product.*` field, which is available through the module link you created earlier. - `filters`: The filter to apply on the retrieved products. You apply the product's ID as a filter. -- `context`: An additional context to be passed to the methods retrieving the data. To pass a context, you use [Query Context](undefined/docs/learn/fundamentals/module-links/query-context). +- `context`: An additional context to be passed to the methods retrieving the data. To pass a context, you use [Query Context](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query-context/index.html.md). By specifying `contentful_product.*` in the `fields` property, Medusa will retrieve the product's entry from Contentful using the `list` method you added to the Contentful Module's service. @@ -81741,7 +81776,7 @@ In this step, you'll set up a webhook listener that updates Medusa's product dat ### Prerequisites: Public Server -Webhooks can only trigger deployed listeners. So, you must either [deploy your Medusa application](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/deployment), or use tools like [ngrok](https://ngrok.com/) to publicly expose your local application. +Webhooks can only trigger deployed listeners. So, you must either [deploy your Medusa application](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/deployment/index.html.md), or use tools like [ngrok](https://ngrok.com/) to publicly expose your local application. ### Set Up Webhooks in Contentful @@ -82001,11 +82036,11 @@ You define a `handleContentfulHookWorkflow` function that receives the webhook d In the workflow, you: - Prepare the data for the update using the `prepareUpdateDataStep` step. -- Use a [when](undefined/docs/learn/fundamentals/workflows/conditions) condition to check if the entry type is a `product`, and if so, update the product using the `updateProductsWorkflow`. +- Use a [when](https://docs.medusajs.com/docs/learn/fundamentals/workflows/conditions/index.html.md) condition to check if the entry type is a `product`, and if so, update the product using the `updateProductsWorkflow`. - Use a `when` condition to check if the entry type is a `productVariant`, and if so, update the product variant using the `updateProductVariantsWorkflow`. - Use a `when` condition to check if the entry type is a `productOption`, and if so, update the product option using the `updateProductOptionsWorkflow`. -You can't perform data manipulation in a workflow's constructor function. Instead, the Workflows SDK includes utility functions like `when` to perform typical operations that requires accessing data values. Learn more about workflow constraints in the [Workflow Constraints](undefined/docs/learn/fundamentals/workflows/constructor-constraints) documetation. +You can't perform data manipulation in a workflow's constructor function. Instead, the Workflows SDK includes utility functions like `when` to perform typical operations that requires accessing data values. Learn more about workflow constraints in the [Workflow Constraints](https://docs.medusajs.com/docs/learn/fundamentals/workflows/constructor-constraints/index.html.md) documetation. ### Add the Webhook Listener API Route @@ -82080,20 +82115,20 @@ Then, try updating a product's title (in the default locale) in Contentful. You You've now integrated Contentful with Medusa and supported localized product details. You can expand on the features in this tutorial to: 1. Add support for other data types, such as product categories or collections. - - Refer to the data model references for each [Commerce Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules) to figure out the content types you need to create in Contentful. + - Refer to the data model references for each [Commerce Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md) to figure out the content types you need to create in Contentful. 2. Listen to other product events and update the Contentful entries accordingly. - - Refer to the [Events Reference](undefined/references/events) for details on all events emitted in Medusa. + - Refer to the [Events Reference](https://docs.medusajs.com/references/events/index.html.md) for details on all events emitted in Medusa. 3. Add localization for the entire Next.js Starter Storefront. You can either: - Create content types in Contentful for different sections in the storefront, then use them to retrieve the localized content; - Or use the approaches recommended in the [Next.js documentation](https://nextjs.org/docs/app/building-your-application/routing/internationalization). -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). ### Troubleshooting -If you encounter issues during your development, check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting). +If you encounter issues during your development, check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/index.html.md). ### Getting Help @@ -82106,7 +82141,7 @@ If you encounter issues not covered in the troubleshooting guides: # How to Build Magento Data Migration Plugin -In this tutorial, you'll learn how to build a [plugin](undefined/docs/learn/fundamentals/plugins) that migrates data, such as products, from Magento to Medusa. +In this tutorial, you'll learn how to build a [plugin](https://docs.medusajs.com/docs/learn/fundamentals/plugins/index.html.md) that migrates data, such as products, from Magento to Medusa. Magento is known for its customization capabilities. However, its monolithic architecture imposes limitations on business requirements, often forcing development teams to implement hacky workarounds. Over time, these customizations become challenging to maintain, especially as the business scales, leading to increased technical debt and slower feature delivery. @@ -82152,23 +82187,23 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll be asked for the project's name. You can also optionally choose to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter). +You'll be asked for the project's name. You can also optionally choose to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md). Afterward, the installation process will start, which will install the Medusa application in a directory with your project's name. If you chose to install the Next.js starter, it'll be installed in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Refer to the [Medusa Architecture](undefined/docs/learn/introduction/architecture) documentation to learn more. +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Refer to the [Medusa Architecture](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md) documentation to learn more. Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterward, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** ## Step 2: Install a Medusa Plugin Project -A plugin is a package of reusable Medusa customizations that you can install in any Medusa application. You can add in the plugin [API Routes](undefined/docs/learn/fundamentals/api-routes), [Workflows](undefined/docs/learn/fundamentals/workflows), and other customizations, as you'll see in this guide. Afterward, you can test it out locally in a Medusa application, then publish it to npm to install and use it in any Medusa application. +A plugin is a package of reusable Medusa customizations that you can install in any Medusa application. You can add in the plugin [API Routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md), [Workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), and other customizations, as you'll see in this guide. Afterward, you can test it out locally in a Medusa application, then publish it to npm to install and use it in any Medusa application. -Refer to the [Plugins](undefined/docs/learn/fundamentals/plugins) documentation to learn more about plugins. +Refer to the [Plugins](https://docs.medusajs.com/docs/learn/fundamentals/plugins/index.html.md) documentation to learn more about plugins. A Medusa plugin is set up in a different project, giving you the flexibility in building and publishing it, while providing you with the tools to test it out locally in a Medusa application. @@ -82242,7 +82277,7 @@ To connect to external applications in Medusa, you create a custom module. A mod In this step, you'll create a Magento Module in the Magento plugin that connects to a Magento server's REST APIs and retrieves data, such as products. -Refer to the [Modules](undefined/docs/learn/fundamentals/modules) documentation to learn more about modules. +Refer to the [Modules](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) documentation to learn more about modules. ### Create Module Directory @@ -82291,7 +82326,7 @@ You create a `MagentoModuleService` that has an `options` property to store the - `password`: The password of the Magento admin user. - `migrationOptions`: Additional options useful for migrating data, such as the base URL to use for product images. -The service's constructor accepts as a first parameter the [Module Container](undefined/docs/learn/fundamentals/modules/container), which allows you to access resources available for the module. As a second parameter, it accepts the module's options. +The service's constructor accepts as a first parameter the [Module Container](https://docs.medusajs.com/docs/learn/fundamentals/modules/container/index.html.md), which allows you to access resources available for the module. As a second parameter, it accepts the module's options. ### Add Authentication Logic @@ -82705,7 +82740,7 @@ Where: - `MAGENTO_PASSWORD`: The password of the Magento admin user. - `MAGENTO_IMAGE_BASE_URL`: The base URL to use for product images. Magento stores product images in the `pub/media/catalog/product` directory, so you can reference them directly or use a CDN URL. If the URLs of product images in the Medusa server already have a different base URL, you can omit this option. -Medusa supports integrating third-party services, such as [S3](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/file/s3), in a File Module Provider. Refer to the [File Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/file) documentation to find other module providers and how to create a custom provider. +Medusa supports integrating third-party services, such as [S3](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/file/s3/index.html.md), in a File Module Provider. Refer to the [File Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/file/index.html.md) documentation to find other module providers and how to create a custom provider. You can now use the Magento Module to migrate data, which you'll do in the next steps. @@ -82719,18 +82754,18 @@ A workflow is a series of queries and actions, called steps, that complete a tas By implementing the migration feature in a workflow, you ensure that the data remains consistent and that the migration process can be rolled back if an error occurs. -Refer to the [Workflows](undefined/docs/learn/fundamentals/workflows) documentation to learn more about workflows. +Refer to the [Workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) documentation to learn more about workflows. ### Workflow Steps The workflow you'll create will have the following steps: - [getMagentoProductsStep](#getMagentoProductsStep): Retrieve products from Magento using the Magento Module. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve Medusa store details, which you'll need when creating the products. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve a shipping profile, which you'll associate the created products with. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve Magento products that are already in Medusa to update them, instead of creating them. -- [createProductsWorkflow](undefined/references/medusa-workflows/createProductsWorkflow): Create products in the Medusa application. -- [updateProductsWorkflow](undefined/references/medusa-workflows/updateProductsWorkflow): Update existing products in the Medusa application. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve Medusa store details, which you'll need when creating the products. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve a shipping profile, which you'll associate the created products with. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve Magento products that are already in Medusa to update them, instead of creating them. +- [createProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createProductsWorkflow/index.html.md): Create products in the Medusa application. +- [updateProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateProductsWorkflow/index.html.md): Update existing products in the Medusa application. You only need to implement the `getMagentoProductsStep` step, which retrieves the products from Magento. The other steps and workflows are provided by Medusa's `@medusajs/medusa/core-flows` package. @@ -82773,7 +82808,7 @@ You create a step using `createStep` from the Workflows SDK. It accepts two para 1. The step's name, which is `get-magento-products`. 2. An async function that executes the step's logic. The function receives two parameters: - The input data for the step, which in this case is the pagination parameters. - - An object holding the workflow's context, including the [Medusa Container](undefined/docs/learn/fundamentals/medusa-container) that allows you to resolve Framework and commerce tools. + - An object holding the workflow's context, including the [Medusa Container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md) that allows you to resolve Framework and commerce tools. In the step function, you resolve the Magento Module's service from the container, then use its `getProducts` method to retrieve the products from Magento. @@ -82857,7 +82892,7 @@ const { data: shippingProfiles } = useQueryGraphStep({ // TODO retrieve existing products ``` -You use the `useQueryGraphStep` step to retrieve the store details and shipping profiles. `useQueryGraphStep` is a Medusa step that wraps [Query](undefined/docs/learn/fundamentals/module-links/query), allowing you to use it in a workflow. Query is a tool that retrieves data across modules. +You use the `useQueryGraphStep` step to retrieve the store details and shipping profiles. `useQueryGraphStep` is a Medusa step that wraps [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), allowing you to use it in a workflow. Query is a tool that retrieves data across modules. Whe retrieving the store details, you specifically retrieve its supported currencies and default sales channel ID. You'll associate the products with the store's default sales channel, and set their variant prices in the supported currencies. You'll also associate the products with a shipping profile. @@ -82883,7 +82918,7 @@ const { data: existingProducts } = useQueryGraphStep({ Since the Medusa application creates an internal representation of the workflow's constructor function, you can't manipulate data directly, as variables have no value while creating the internal representation. -Refer to the [Workflows](undefined/docs/learn/fundamentals/workflows/constructor-constraints) documentation to learn more about the workflow constructor function's constraints. +Refer to the [Workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/constructor-constraints/index.html.md) documentation to learn more about the workflow constructor function's constraints. Instead, you can manipulate data in a workflow's constructor function using `transform` from the Workflows SDK. `transform` is a function that accepts two parameters: @@ -83040,11 +83075,11 @@ You can now use this workflow to migrate products from Magento to Medusa. You'll ## Step 6: Schedule Product Migration -There are many ways to execute tasks asynchronously in Medusa, such as [scheduling a job](undefined/docs/learn/fundamentals/scheduled-jobs) or [handling emitted events](undefined/docs/learn/fundamentals/events-and-subscribers). +There are many ways to execute tasks asynchronously in Medusa, such as [scheduling a job](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs/index.html.md) or [handling emitted events](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md). In this guide, you'll learn how to schedule the product migration at a specified interval using a scheduled job. A scheduled job is an asynchronous function that the Medusa application runs at the interval you specify during the Medusa application's runtime. -Refer to the [Scheduled Jobs](undefined/docs/learn/fundamentals/scheduled-jobs) documentation to learn more about scheduled jobs. +Refer to the [Scheduled Jobs](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs/index.html.md) documentation to learn more about scheduled jobs. To create a scheduled job, in your plugin, create the file `src/jobs/migrate-magento.ts` with the following content: @@ -83090,10 +83125,10 @@ export const config = { A scheduled job file must export: -- An asynchronous function that executes the job's logic. The function receives the [Medusa container](undefined/docs/learn/fundamentals/medusa-container) as a parameter. +- An asynchronous function that executes the job's logic. The function receives the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md) as a parameter. - An object with the job's configuration, including the name and the schedule. The schedule is a cron job pattern as a string. -In the job function, you resolve the [logger](undefined/docs/learn/debugging-and-testing/logging) from the container to log messages. Then, you paginate the product migration process by running the `migrateProductsFromMagentoWorkflow` workflow at each page until you've migrated all products. You use the pagination result returned by the workflow to determine whether there are more products to migrate. +In the job function, you resolve the [logger](https://docs.medusajs.com/docs/learn/debugging-and-testing/logging/index.html.md) from the container to log messages. Then, you paginate the product migration process by running the `migrateProductsFromMagentoWorkflow` workflow at each page until you've migrated all products. You use the pagination result returned by the workflow to determine whether there are more products to migrate. Based on the job's configurations, the Medusa application will run the job at midnight every day. @@ -83145,11 +83180,11 @@ To confirm that the products were migrated, open the Medusa Admin dashboard at ` You've now implemented the logic to migrate products from Magento to Medusa. You can re-use the plugin across Medusa applications. You can also expand on the plugin to: - Migrate other entities, such as orders, customers, and categories. Migrating other entities follows the same pattern as migrating products, using workflows and scheduled jobs. You only need to format the data to be migrated as needed. -- Allow triggering migrations from the Medusa Admin dashboard using [Admin Customizations](undefined/docs/learn/fundamentals/admin). This feature is available in the [Example Repository](https://github.com/medusajs/example-repository/tree/main/src/admin). +- Allow triggering migrations from the Medusa Admin dashboard using [Admin Customizations](https://docs.medusajs.com/docs/learn/fundamentals/admin/index.html.md). This feature is available in the [Example Repository](https://github.com/medusajs/example-repository/tree/main/src/admin). -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). # Add Newsletter Subscriptions with Mailchimp in Medusa @@ -83158,7 +83193,7 @@ In this tutorial, you'll learn how to integrate Mailchimp with Medusa to manage When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. Medusa's architecture facilitates integrating third-party services to customize Medusa's infrastructure for your business needs. -Medusa's [Notification Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification) allows you to customize Medusa's infrastructure to send notifications using the third-party provider that fits your business needs, such as [Mailchimp](https://mailchimp.com/). +Medusa's [Notification Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/index.html.md) allows you to customize Medusa's infrastructure to send notifications using the third-party provider that fits your business needs, such as [Mailchimp](https://mailchimp.com/). In this tutorial, you'll integrate Mailchimp with Medusa to allow customers to subscribe to your newsletter and automate sending newsletters. @@ -83193,27 +83228,27 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -First, you'll be asked for the project's name. Then, when prompted about installing the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose "Yes." +First, you'll be asked for the project's name. Then, when prompted about installing the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose "Yes." Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name and the Next.js Starter Storefront in a separate directory named `{project-name}-storefront`. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterwards, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** ## Step 2: Create Mailchimp Module Provider -To integrate third-party services into Medusa, you create a custom [module](undefined/docs/learn/fundamentals/modules). A module is a reusable package with functionalities related to a single feature or domain. +To integrate third-party services into Medusa, you create a custom [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). A module is a reusable package with functionalities related to a single feature or domain. -Medusa's [Notification Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification) provides an interface to send notifications in your Medusa application. It delegates the actual sending of notifications to the underlying provider, such as Mailchimp. +Medusa's [Notification Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/index.html.md) provides an interface to send notifications in your Medusa application. It delegates the actual sending of notifications to the underlying provider, such as Mailchimp. In this step, you'll integrate Mailchimp as a Notification Module Provider. Later, you'll use it to handle newsletter subscriptions and send newsletters. -Refer to the [Modules](undefined/docs/learn/fundamentals/modules) documentation to learn more about modules in Medusa. +Refer to the [Modules](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) documentation to learn more about modules in Medusa. ### a. Install Mailchimp Marketing API SDK @@ -83282,7 +83317,7 @@ The service must also have an `identifier` static property, which is a unique id The service's constructor receives two parameters: -- `container`: The [module's container](undefined/docs/learn/fundamentals/modules/container) that contains Framework resources available to the module. You don't need to use it for this tutorial. +- `container`: The [module's container](https://docs.medusajs.com/docs/learn/fundamentals/modules/container/index.html.md) that contains Framework resources available to the module. You don't need to use it for this tutorial. - `options`: Options that are passed to the module provider when it's registered in Medusa's configurations. You define the following options: - `apiKey`: The Mailchimp API key. - `server`: The Mailchimp server prefix. For example, `us10`. @@ -83392,7 +83427,7 @@ This method receives the same parameter as the `send` method, which is an object - `to`: The email address to add to the Mailchimp audience list. - `data`: An object containing additional data, such as the user's first and last name. -Learn about other properties in the object in the [Create Notification Module Provider](undefined/references/notification-provider-module#send) guide. +Learn about other properties in the object in the [Create Notification Module Provider](https://docs.medusajs.com/references/notification-provider-module#send/index.html.md) guide. In the method, you use the `mailchimp.lists.addListMember` method to subscribe an email address to the Mailchimp audience list. You pass the `listId` from the module's options and the email address along with optional first and last names. @@ -83560,7 +83595,7 @@ class MailchimpNotificationProviderService extends AbstractNotificationProviderS This method receives the same parameter as the `send` method, which is an object containing the notification details. -Learn about the object's properties in the [Create Notification Module Provider](undefined/references/notification-provider-module#send) guide. +Learn about the object's properties in the [Create Notification Module Provider](https://docs.medusajs.com/references/notification-provider-module#send/index.html.md) guide. In the method, you: @@ -83603,7 +83638,7 @@ class MailchimpNotificationProviderService extends AbstractNotificationProviderS This method receives an object of notification details, including the `template` property that specifies which template to use for sending the notification. -Learn about other properties in the object in the [Create Notification Module Provider](undefined/references/notification-provider-module#send) guide. +Learn about other properties in the object in the [Create Notification Module Provider](https://docs.medusajs.com/references/notification-provider-module#send/index.html.md) guide. In the method, you perform an action based on the `template` value: @@ -83895,9 +83930,9 @@ Now that you've integrated Mailchimp with Medusa, you need to allow customers to In this step, you will: -- Create an [API route](undefined/docs/learn/fundamentals/api-routes) to subscribe customers. An API Route is an endpoint that exposes commerce features to external applications and clients, such as storefronts. +- Create an [API route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) to subscribe customers. An API Route is an endpoint that exposes commerce features to external applications and clients, such as storefronts. - In the API route, you'll emit an event indicating that the customer is signing up for the newsletter. -- Create a [subscriber](undefined/docs/learn/fundamentals/events-and-subscribers) that listens to the event emitted by the API route. The subscriber will use Mailchimp to subscribe the customer to the newsletter audience list. +- Create a [subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md) that listens to the event emitted by the API route. The subscriber will use Mailchimp to subscribe the customer to the newsletter audience list. ### a. Create the API Route @@ -83943,7 +83978,7 @@ Then, you export a `POST` route handler function. This will expose a `POST` API 1. A request object with details and context on the request, such as body parameters. 2. A response object to manipulate and send the response. -In the route handler, you use the [Medusa container](undefined/docs/learn/fundamentals/medusa-container) to resolve the [Event Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/event)'s service. +In the route handler, you use the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md) to resolve the [Event Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/event/index.html.md)'s service. Then, you emit the `newsletter.signup` event, passing as the event payload the email, first name, and last name from the request body. @@ -83951,7 +83986,7 @@ Finally, you send a JSON response indicating that the request was successful. ### b. Add Validation Middleware -To validate that requests sent to the `/store/newsletter` API route have the required body parameters, you'll add a validation [middleware](undefined/docs/learn/fundamentals/api-routes/middlewares). A middleware is a function that is executed before an API route's handler when a request is made to the route. +To validate that requests sent to the `/store/newsletter` API route have the required body parameters, you'll add a validation [middleware](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md). A middleware is a function that is executed before an API route's handler when a request is made to the route. To apply the validation middleware on the `/store/newsletter` API route, create the file `src/api/middlewares.ts` with the following content: @@ -84019,7 +84054,7 @@ A subscriber file must export: The subscriber function receives an object as a parameter that has a `container` property, which is the Medusa container. The Medusa container holds Framework and commerce tools that you can resolve and use in your customizations. -In the subscriber function, you resolve the [Notification Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification)'s service from the Medusa container. Then, you call the `createNotifications` method to create a notification with the following properties: +In the subscriber function, you resolve the [Notification Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/index.html.md)'s service from the Medusa container. Then, you call the `createNotifications` method to create a notification with the following properties: - `channel`: The channel to send the notification through, which is `email` in this case. Since the [Mailchimp Notification Module Provider is registered with the email channel](#g-add-module-provider-to-medusas-configurations), it will process the notification. - `to`: The email address to subscribe to the newsletter. @@ -84032,7 +84067,7 @@ Now you have an API route that allows customers to subscribe to the newsletter. ## Step 4: Add Newsletter Subscription Form in the Storefront -In this step, you'll customize the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter) that you installed as part of the first step. You'll add a newsletter subscription form in the storefront's footer that allows customers to subscribe to the newsletter. +In this step, you'll customize the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) that you installed as part of the first step. You'll add a newsletter subscription form in the storefront's footer that allows customers to subscribe to the newsletter. The Next.js Starter Storefront was installed in a separate directory from Medusa. The directory's name is `{your-project}-storefront`. @@ -84065,7 +84100,7 @@ export const subscribeToNewsletter = async (email: string) => { } ``` -You use the [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk), which is already configured in the Next.js Starter Storefront, to send a `POST` request to the `/store/newsletter` API route. You pass the email address in the request body. +You use the [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md), which is already configured in the Next.js Starter Storefront, to send a `POST` request to the `/store/newsletter` API route. You pass the email address in the request body. ### b. Create Newsletter Subscription Form @@ -84143,7 +84178,7 @@ Once the customer enters their email and submits the form, you use the `subscrib You also show a toast notification to the customer indicating that they successfully subscribed to the newsletter. -The `toast` function is imported from [Medusa UI](undefined/ui), which requires adding `Toaster` component in the application's tree. So, import the `Toaster` component in the file `src/app/[countryCode]/(main)/layout.tsx`: +The `toast` function is imported from [Medusa UI](https://docs.medusajs.com/ui/index.html.md), which requires adding `Toaster` component in the application's tree. So, import the `Toaster` component in the file `src/app/[countryCode]/(main)/layout.tsx`: ```tsx title="src/app/[countryCode]/(main)/layout.tsx" badgeLabel="Storefront" badgeColor="blue" import { Toaster } from "@medusajs/ui" @@ -84224,7 +84259,7 @@ To automate the newsletter, you will: ### a. Create the Workflow -A [workflow](undefined/docs/learn/fundamentals/workflows) is a series of actions, called steps, that complete a task with rollback and retry mechanisms. In Medusa, you build commerce features in workflows, then execute them in other customizations, such as subscribers, scheduled jobs, and API routes. +A [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) is a series of actions, called steps, that complete a task with rollback and retry mechanisms. In Medusa, you build commerce features in workflows, then execute them in other customizations, such as subscribers, scheduled jobs, and API routes. You'll create a workflow that retrieves the latest products added to your Medusa store, then creates a notification with the product data useful to send the newsletter. @@ -84286,11 +84321,11 @@ You create a workflow using `createWorkflow` from the Workflows SDK. It accepts In the workflow's constructor function, you: -1. Use the [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep) to retrieve products created in the last 7 days. You retrieve the product's title, handle, thumbnail, and description fields. -2. Use the [when-then](undefined/docs/learn/fundamentals/workflows/conditions) utility to send the notification only if there are new products. `when` receives two parameters: +1. Use the [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md) to retrieve products created in the last 7 days. You retrieve the product's title, handle, thumbnail, and description fields. +2. Use the [when-then](https://docs.medusajs.com/docs/learn/fundamentals/workflows/conditions/index.html.md) utility to send the notification only if there are new products. `when` receives two parameters: - An object to use in the condition function. - A condition function that receives the first parameter object and returns a boolean indicating whether to execute the steps in the `then` block. -3. If the `when` condition is met, you use the [sendNotificationsStep](undefined/references/medusa-workflows/steps/sendNotificationsStep) to create a notification with the following properties: +3. If the `when` condition is met, you use the [sendNotificationsStep](https://docs.medusajs.com/references/medusa-workflows/steps/sendNotificationsStep/index.html.md) to create a notification with the following properties: - `to`: The audience to send the notification to. This will be filled in by the Mailchimp Notification Module Provider, so you use a placeholder value. - `channel`: The channel to send the notification through, which is `email` in this case. - `template`: The template to use for the notification, which is `new-products`. @@ -84298,11 +84333,11 @@ In the workflow's constructor function, you: Finally, you return an instance of `WorkflowResponse` indicating that the workflow was completed successfully. -You can't perform data manipulation in a workflow's constructor function. Instead, the Workflows SDK includes utility functions like `when` to perform typical operations that require accessing data values. Learn more about workflow constraints in the [Workflow Constraints](undefined/docs/learn/fundamentals/workflows/constructor-constraints) documentation. +You can't perform data manipulation in a workflow's constructor function. Instead, the Workflows SDK includes utility functions like `when` to perform typical operations that require accessing data values. Learn more about workflow constraints in the [Workflow Constraints](https://docs.medusajs.com/docs/learn/fundamentals/workflows/constructor-constraints/index.html.md) documentation. ### b. Create a Scheduled Job -To automate executing a task at a specified interval, you can create a [scheduled job](undefined/docs/learn/fundamentals/scheduled-jobs). A scheduled job is a background task that runs at a specified interval, such as every hour or every day. +To automate executing a task at a specified interval, you can create a [scheduled job](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs/index.html.md). A scheduled job is a background task that runs at a specified interval, such as every hour or every day. To create a scheduled job, create the file `src/jobs/send-weekly-newsletter.ts` with the following content: @@ -84333,13 +84368,13 @@ export const config = { A scheduled job file must export: -- An asynchronous function that executes the job's logic. The function receives the [Medusa container](undefined/docs/learn/fundamentals/medusa-container) as a parameter. +- An asynchronous function that executes the job's logic. The function receives the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md) as a parameter. - An object with the job's configuration, including the name and the schedule. The schedule is a cron job pattern as a string. - You set the schedule to run the job every Sunday at midnight, which is represented by the cron pattern `0 0 * * 0`. In the job function, you: -1. Resolve the [Logger](undefined/docs/learn/debugging-and-testing/logging) utility from the Medusa container to log messages. +1. Resolve the [Logger](https://docs.medusajs.com/docs/learn/debugging-and-testing/logging/index.html.md) utility from the Medusa container to log messages. 2. Log a message indicating that the newsletter is being sent. 3. Execute the `sendNewProductsNewsletter` workflow by invoking it, passing the Medusa container as a parameter, then calling its `run` method. 4. Log a message indicating that the newsletter was sent successfully. @@ -84355,7 +84390,7 @@ export const config = { } ``` -Also, if you didn't create any products in the past week, make sure to [create a few products in the Medusa Admin](undefined/user-guide/products/create). +Also, if you didn't create any products in the past week, make sure to [create a few products in the Medusa Admin](https://docs.medusajs.com/user-guide/products/create/index.html.md). Then, run the following command in the Medusa application's directory to start the Medusa server: @@ -84397,17 +84432,17 @@ You've now integrated Mailchimp with Medusa to allow customers to subscribe to a You can expand this feature and integration to: -- Send newsletters about other events, such as new collections or special offers. Refer to the [Events Reference](undefined/references/events) for the list of events you can listen to. +- Send newsletters about other events, such as new collections or special offers. Refer to the [Events Reference](https://docs.medusajs.com/references/events/index.html.md) for the list of events you can listen to. - Customize the registration form in the storefront to add an "opt-in for newsletter" checkbox. - Customize the notifications to match your business's brand, or use templates defined in Mailchimp instead. -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). ### Troubleshooting -If you encounter issues during your development, check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting). +If you encounter issues during your development, check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/index.html.md). ### Getting Help @@ -84418,6 +84453,1153 @@ If you encounter issues not covered in the troubleshooting guides: 3. Contact the [sales team](https://medusajs.com/contact/) to get help from the Medusa team. +# Integrate Meilisearch with Medusa + +In this tutorial, you'll learn how to integrate Meilisearch with Medusa to enable advanced search capabilities in your storefront. + +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. Medusa's architecture supports integrating third-party services, such as search engines, allowing you to build custom features around core commerce flows. + +[Meilisearch](https://www.meilisearch.com/) is an open-source, fast, and relevant search engine that you can integrate with Medusa to enhance your storefront's search functionality. + +## Summary + +By following this tutorial, you'll learn how to: + +- Install and set up Medusa. +- Integrate Meilisearch into Medusa. +- Trigger Meilisearch reindexing when a product is created, updated, or deleted, or when an admin manually triggers a reindex. +- Customize the Next.js Starter Storefront to search for products through Meilisearch. + +You can follow this tutorial whether you're new to Medusa or an advanced Medusa developer. + +![Diagram illustrating the integration of Meilisearch with Medusa](https://res.cloudinary.com/dza7lstvk/image/upload/v1758091098/Medusa%20Resources/meilisearch-summary_bdig6e.jpg) + +[Example Repository](https://github.com/medusajs/examples/tree/main/meilisearch-integration): Find the full code of the guide in this repository. + +*** + +## Step 1: Install a Medusa Application + +### Prerequisites + +- [Node.js v20+](https://nodejs.org/en/download) +- [Git CLI tool](https://git-scm.com/downloads) +- [PostgreSQL](https://www.postgresql.org/download/) + +Start by installing the Medusa application on your machine with the following command: + +```bash +npx create-medusa-app@latest +``` + +You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose "Yes." + +Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name and the Next.js Starter Storefront in a separate directory named `{project-name}-storefront`. + +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). + +Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterwards, you can log in with the new user and explore the dashboard. + +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. + +*** + +## Step 2: Create Meilisearch Module + +### Prerequisites + +- [Meilisearch instance (Cloud or local)](https://www.meilisearch.com/docs/learn/getting_started/cloud_quick_start) + +To integrate third-party services into Medusa, you create a custom module. A module is a reusable package with functionalities related to a single feature or domain. Medusa integrates the module into your application without side effects on your setup. + +In this step, you'll create a custom module that provides the necessary functionalities to integrate Meilisearch with Medusa. + +Refer to the [Modules documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) to learn more. + +Before building the module, you need to install Meilisearch's JavaScript client. Run the following command in your Medusa application's root directory: + +```bash npm2yarn +npm install meilisearch +``` + +### Create Module Directory + +A module is created under the `src/modules` directory of your Medusa application. So, create the directory `src/modules/meilisearch`. + +### Create Service + +You define a module's functionalities in a service. A service is a TypeScript or JavaScript class that the module exports. In the service's methods, you can connect to the database, which is useful if your module defines tables in the database, or connect to third-party services. + +In this section, you'll create the Meilisearch Module's service and the methods necessary to manage indexed products in Meilisearch and search through them. + +To create the Meilisearch Module's service, create the file `src/modules/meilisearch/service.ts` with the following content: + +```ts title="src/modules/meilisearch/service.ts" +const { Meilisearch } = require("meilisearch") +import { MedusaError } from "@medusajs/framework/utils" + +type MeilisearchOptions = { + host: string; + apiKey: string; + productIndexName: string; +} + +export type MeilisearchIndexType = "product" + +export default class MeilisearchModuleService { + private client: typeof Meilisearch + private options: MeilisearchOptions + + constructor({}, options: MeilisearchOptions) { + if (!options.host || !options.apiKey || !options.productIndexName) { + throw new MedusaError( + MedusaError.Types.INVALID_ARGUMENT, + "Meilisearch options are required" + ) + } + this.client = new Meilisearch({ + host: options.host, + apiKey: options.apiKey, + }) + this.options = options + } + + // TODO: Add methods +} +``` + +You export a class that serves as the Meilisearch Module's service. In the service, you define two properties: + +- `client`: An instance of the Meilisearch Client, which you'll use to perform actions with Meilisearch's API. +- `options`: An object of options that the module receives when it's registered, which you'll learn about later. The options contain: + - `apiKey`: The Meilisearch API key. + - `host`: The Meilisearch host. + - `productIndexName`: The name of the index where products are stored. + +If you want to index other types of data, such as product categories, you can add new properties for their index names in the `MeilisearchOptions` type. + +A module's service receives the module's options as a second parameter in its constructor. In the constructor, you initialize the Meilisearch client using the module's options. + +A module has a container that holds all resources registered in that module, and you can access those resources in the first parameter of the constructor. Learn more about it in the [Module Container documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/container/index.html.md). + +#### Index Data Method + +The first method you need to add to the service is a method that receives an array of data to add or update in Meilisearch's index. + +Add the following methods to the `MeilisearchModuleService` class: + +```ts title="src/modules/meilisearch/service.ts" +export default class MeilisearchModuleService { + // ... + async getIndexName(type: MeilisearchIndexType) { + switch (type) { + case "product": + return this.options.productIndexName + default: + throw new Error(`Invalid index type: ${type}`) + } + } + + async indexData(data: Record[], type: MeilisearchIndexType = "product") { + const indexName = await this.getIndexName(type) + const index = this.client.index(indexName) + + // Transform data to include id as primary key for Meilisearch + const documents = data.map((item) => ({ + ...item, + id: item.id, + })) + + await index.addDocuments(documents) + } +} +``` + +You define two methods: + +1. `getIndexName`: A method that receives an `MeilisearchIndexType` (defined in the previous snippet) and returns the index name for that type. In this case, you only have one type, `product`, so you return the product index name. + - If you want to index other types of data, you can add more cases to the switch statement. +2. `indexData`: A method that receives an array of data and an `MeilisearchIndexType`. The method indexes the data in the Meilisearch index for the given type. + +### Retrieve and Delete Methods + +The next methods you'll add to the service are methods to retrieve and delete data from the Meilisearch index. You'll use these later to keep the Meilisearch index in sync with Medusa. + +Add the following methods to the `MeilisearchModuleService` class: + +```ts title="src/modules/meilisearch/service.ts" +export default class MeilisearchModuleService { + // ... + + async retrieveFromIndex(documentIds: string[], type: MeilisearchIndexType = "product") { + const indexName = await this.getIndexName(type) + const index = this.client.index(indexName) + + const results = await Promise.all( + documentIds.map(async (id) => { + try { + return await index.getDocument(id) + } catch (error) { + // Document not found, return null + return null + } + }) + ) + + return results.filter(Boolean) + } + + async deleteFromIndex(documentIds: string[], type: MeilisearchIndexType = "product") { + const indexName = await this.getIndexName(type) + const index = this.client.index(indexName) + + await index.deleteDocuments(documentIds) + } +} +``` + +You define two methods: + +1. `retrieveFromIndex`: A method that receives an array of document IDs and a `MeilisearchIndexType`. The method retrieves the documents with the given IDs from the Meilisearch index. +2. `deleteFromIndex`: A method that receives an array of document IDs and a `MeilisearchIndexType`. The method deletes the documents with the given IDs from the Meilisearch index. + +#### Search Method + +The last method you'll implement is a method to search through the Meilisearch index. This method lets you expose search functionality to clients through Medusa's API routes. + +Add the following method to the `MeilisearchModuleService` class: + +```ts title="src/modules/meilisearch/service.ts" +export default class MeilisearchModuleService { + // ... + + async search(query: string, type: MeilisearchIndexType = "product") { + const indexName = await this.getIndexName(type) + const index = this.client.index(indexName) + + return await index.search(query) + } +} +``` + +The `search` method receives a query string and a `MeilisearchIndexType`. The method searches through the Meilisearch index for the given type, such as products, and returns the results. + +### Export Module Definition + +The final piece of a module is its definition, which you export in an `index.ts` file at its root directory. This definition tells Medusa the name of the module and its service. + +So, create the file `src/modules/meilisearch/index.ts` with the following content: + +```ts title="src/modules/meilisearch/index.ts" +import { Module } from "@medusajs/framework/utils" +import MeilisearchModuleService from "./service" + +export const MEILISEARCH_MODULE = "meilisearch" + +export default Module(MEILISEARCH_MODULE, { + service: MeilisearchModuleService, +}) +``` + +You use the `Module` function from the Modules SDK to create the module's definition. It accepts two parameters: + +1. The module's name, which is `meilisearch`. +2. An object with a required property `service` indicating the module's service. + +You also export the module's name as `MEILISEARCH_MODULE` so you can reference it later. + +### Add Module to Medusa's Configurations + +Once you finish building the module, add it to Medusa's configurations to start using it. + +In `medusa-config.ts`, add a `modules` property and pass an array with your custom module: + +```ts title="medusa-config.ts" +module.exports = defineConfig({ + // ... + modules: [ + { + resolve: "./src/modules/meilisearch", + options: { + host: process.env.MEILISEARCH_HOST!, + apiKey: process.env.MEILISEARCH_API_KEY!, + productIndexName: process.env.MEILISEARCH_PRODUCT_INDEX_NAME!, + }, + }, + ], +}) +``` + +Each object in the `modules` array has a `resolve` property, whose value is either a path to the module's directory, or an `npm` package’s name. + +You also pass an `options` property with the module's options, including the Meilisearch host, API Key, and the product index name. + +### Add Environment Variables + +Before you can start using the Meilisearch Module, you need to set the environment variables for the Meilisearch host, API Key, and the product index name. + +Add the following environment variables to your `.env` file: + +```env +MEILISEARCH_HOST=your-meilisearch-host +MEILISEARCH_API_KEY=your-meilisearch-api-key +MEILISEARCH_PRODUCT_INDEX_NAME=your-product-index-name +``` + +- `your-meilisearch-host` is the host of your Meilisearch instance. If you're running Meilisearch locally, it should be `http://127.0.0.1:7700`. +- `your-meilisearch-api-key` is the master key of your Meilisearch instance. If you're running Meilisearch locally, you should have set it when starting Meilisearch. If you're using Meilisearch Cloud, you can find it in the dashboard under "API Keys." Learn more in the [Meilisearch documentation](https://www.meilisearch.com/docs/learn/security/basic_security). +- `your-product-index-name` is the name of the index where you'll store products. You can choose any name you want. Even if the index doesn't exist, Meilisearch will create it when you add documents to it. + +Your module is now ready for use. You'll see how to use it in the next steps. + +*** + +## Step 3: Sync Products to Meilisearch Workflow + +To keep the Meilisearch index in sync with Medusa, you need to trigger indexing when products are created, updated, or deleted in Medusa. You can also allow admins to manually trigger a reindex. + +To implement the indexing functionality, you need to create a [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). A workflow is a series of actions, called steps, that complete a task. You construct a workflow like you construct a function, but it's a special function that allows you to track its executions' progress, define roll-back logic, and configure other advanced features. + +Learn more about workflows in the [Workflows documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). + +In this step, you'll create a workflow that indexes products in Meilisearch. In the next steps, you'll learn how to use the workflow when products are created, updated, or deleted, or when admins manually trigger a reindex. + +The workflow has the following steps: + +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve products matching specified filters and pagination parameters. +- [syncProductsStep](#syncProductsStep): Index products in Meilisearch. + +Medusa provides the `useQueryGraphStep` in its `@medusajs/medusa/core-flows` package. You only need to implement the second step. + +### syncProductsStep + +In the second step of the workflow, you create or update indexes in Meilisearch for the products retrieved in the first step. + +To create the step, create the file `src/workflows/steps/sync-products.ts` with the following content: + +```ts title="src/workflows/steps/sync-products.ts" +import { ProductDTO } from "@medusajs/framework/types" +import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk" +import { MEILISEARCH_MODULE } from "../../modules/meilisearch" + +export type SyncProductsStepInput = { + products: ProductDTO[] +} + +export const syncProductsStep = createStep( + "sync-products", + async ({ products }: SyncProductsStepInput, { container }) => { + const meilisearchModuleService = container.resolve( + MEILISEARCH_MODULE + ) + const existingProducts = await meilisearchModuleService.retrieveFromIndex( + products.map((product) => product.id), + "product" + ) + const newProducts = products.filter((product) => !existingProducts.some( + (p) => p.id === product.id) + ) + await meilisearchModuleService.indexData( + products as unknown as Record[], + "product" + ) + + return new StepResponse(undefined, { + newProducts: newProducts.map((product) => product.id), + existingProducts, + }) + } + // TODO add compensation +) +``` + +You create a step with `createStep` from the Workflows SDK. It accepts two parameters: + +1. The step's unique name, which is `sync-products`. +2. An async function that receives two parameters: + - The step's input, which is an object holding an array of products to sync into Meilisearch. + - An object that has properties including the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which is a registry of Framework and commerce tools that you can access in the step. + +In the step function, you resolve the Meilisearch Module's service from the Medusa container using the name you exported in the module definition's file. + +Then, you retrieve the products that are already indexed in Meilisearch and determine which products are new. You'll learn why this is useful in a bit. + +Finally, you pass the products you received in the input to Meilisearch to create or update its indices. + +A step function must return a `StepResponse` instance. The `StepResponse` constructor accepts two parameters: + +1. The step's output, which in this case is `undefined`. +2. Data to pass to the step's compensation function. + +#### Compensation Function + +The compensation function undoes the actions performed in a step. Then, if an error occurs during the workflow's execution, the compensation functions of executed steps are called to roll back the changes. This mechanism ensures data consistency in your application, especially as you integrate external systems. + +To add a compensation function to a step, pass it as a third parameter to `createStep`: + +```ts title="src/workflows/steps/sync-products.ts" +export const syncProductsStep = createStep( + // ... + async (input, { container }) => { + if (!input) { + return + } + + const meilisearchModuleService = container.resolve( + MEILISEARCH_MODULE + ) + + if (input.newProducts) { + await meilisearchModuleService.deleteFromIndex( + input.newProducts, + "product" + ) + } + + if (input.existingProducts) { + await meilisearchModuleService.indexData( + input.existingProducts, + "product" + ) + } + } +) +``` + +The compensation function receives two parameters: + +1. The data you passed as a second parameter of `StepResponse` in the step function. +2. A context object similar to the step function that holds the Medusa container. + +In the compensation function, you resolve the Meilisearch Module's service from the container. Then, you delete from Meilisearch the products that were newly indexed and revert the existing products to their original data. + +### Add Sync Products Workflow + +You can now create the workflow that syncs products to Meilisearch. + +To create the workflow, create the file `src/workflows/sync-products.ts` with the following content: + +```ts title="src/workflows/sync-products.ts" +import { createWorkflow, WorkflowResponse } from "@medusajs/framework/workflows-sdk" +import { useQueryGraphStep } from "@medusajs/medusa/core-flows" +import { syncProductsStep, SyncProductsStepInput } from "./steps/sync-products" + +type SyncProductsWorkflowInput = { + filters?: Record + limit?: number + offset?: number +} + +export const syncProductsWorkflow = createWorkflow( + "sync-products", + ({ filters, limit, offset }: SyncProductsWorkflowInput) => { + const { data, metadata } = useQueryGraphStep({ + entity: "product", + fields: [ + "id", + "title", + "description", + "handle", + "thumbnail", + "categories.id", + "categories.name", + "categories.handle", + "tags.id", + "tags.value", + ], + pagination: { + take: limit, + skip: offset, + }, + filters: { + status: "published", + ...filters, + }, + }) + + syncProductsStep({ + products: data, + } as SyncProductsStepInput) + + return new WorkflowResponse({ + products: data, + metadata, + }) + } +) +``` + +You create a workflow using `createWorkflow` from the Workflows SDK. It accepts the workflow's unique name as a first parameter. + +It accepts as a second parameter a constructor function, which is the workflow's implementation. The function can accept input, which in this case is pagination and filter parameters for the products to retrieve. + +In the workflow's constructor function, you: + +1. Retrieve products from Medusa's database using `useQueryGraphStep`. This step uses Medusa's [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) tool to retrieve data across modules. You pass it the pagination and filter parameters you received in the input. +2. Index the products in Meilisearch using `syncProductsStep`. You pass it the products you retrieved in the previous step. + +A workflow must return an instance of `WorkflowResponse`. The `WorkflowResponse` constructor accepts the workflow's output as a parameter, which is an object holding the retrieved products and their pagination details. + +In the next step, you'll learn how to execute this workflow. + +*** + +## Step 4: Trigger Meilisearch Sync Manually + +As mentioned earlier, you'll trigger the Meilisearch sync automatically when product events occur. You also want to allow admins to manually trigger a reindex. + +In this step, you'll add the functionality to trigger the `syncProductsWorkflow` manually from the Medusa Admin dashboard. This requires: + +1. Creating a subscriber that listens to a custom `meilisearch.sync` event to trigger syncing products to Meilisearch. +2. Creating an API route that the Medusa Admin dashboard can call to emit the `meilisearch.sync` event, which triggers the subscriber. +3. Adding a new page or UI route to the Medusa Admin dashboard to allow admins to trigger the reindex. + +### Create Products Sync Subscriber + +A subscriber is an asynchronous function that listens to one or more events and performs actions when these events are emitted. A subscriber is useful when syncing data across systems, as the operation can be time-consuming and should be performed in the background. + +Learn more about subscribers in the [Events and Subscribers documentation](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md). + +You create a subscriber in a TypeScript or JavaScript file under the `src/subscribers` directory. So, to create the subscriber that listens to the `meilisearch.sync` event, create the file `src/subscribers/meilisearch-sync.ts` with the following content: + +```ts title="src/subscribers/meilisearch-sync.ts" +import { + SubscriberArgs, + type SubscriberConfig, +} from "@medusajs/framework" +import { syncProductsWorkflow } from "../workflows/sync-products" + +export default async function meilisearchSyncHandler({ + container, +}: SubscriberArgs) { + const logger = container.resolve("logger") + + let hasMore = true + let offset = 0 + const limit = 50 + let totalIndexed = 0 + + logger.info("Starting product indexing...") + + while (hasMore) { + const { result: { products, metadata } } = await syncProductsWorkflow(container) + .run({ + input: { + limit, + offset, + }, + }) + + hasMore = offset + limit < (metadata?.count ?? 0) + offset += limit + totalIndexed += products.length + } + + logger.info(`Successfully indexed ${totalIndexed} products`) +} + +export const config: SubscriberConfig = { + event: "meilisearch.sync", +} +``` + +A subscriber file must export: + +1. An asynchronous function, which is the subscriber that is executed when the event is emitted. +2. A configuration object that holds the name of the event the subscriber listens to, which is `meilisearch.sync` in this case. + +The subscriber function receives an object as a parameter that has a `container` property, which is the Medusa container. + +In the subscriber function, you initialize variables to keep track of pagination and the total number of products indexed. + +Then, you start a loop that retrieves products in batches of 50. It indexes them in Meilisearch using the `syncProductsWorkflow`. Finally, you log the total number of products indexed. + +You'll learn how to emit the `meilisearch.sync` event next. + +If you want to sync other data types, you can do it in this subscriber as well. + +### Create API Route to Trigger Sync + +To allow the Medusa Admin dashboard to trigger the `meilisearch.sync` event, you need to create an API route that emits the event. + +An API Route is an endpoint that exposes commerce features to external applications and clients, such as storefronts. + +Learn more about API routes in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). + +An API route is created in a `route.ts` file under a subdirectory of the `src/api` directory. The path of the API route is the file's path relative to `src/api`. + +So, to create an API route at the path `/admin/meilisearch/sync`, create the file `src/api/admin/meilisearch/sync/route.ts` with the following content: + +```ts title="src/api/admin/meilisearch/sync/route.ts" +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" + +export async function POST( + req: MedusaRequest, + res: MedusaResponse +) { + const eventModuleService = req.scope.resolve(Modules.EVENT_BUS) + await eventModuleService.emit({ + name: "meilisearch.sync", + data: {}, + }) + res.send({ + message: "Syncing data to Meilisearch", + }) +} + +``` + +Since you export a `POST` route handler function, you expose a `POST` API route at `/admin/meilisearch/sync`. The route handler function accepts two parameters: + +1. A request object with details and context on the request, such as body parameters or authenticated user details. +2. A response object to manipulate and send the response. + +In the route handler, you use the Medusa container that is available in the request object. You resolve the [Event Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/event/index.html.md). This module manages events and their subscribers. + +Then, you emit the `meilisearch.sync` event using the Event Module's `emit` method. You pass it the event name. + +Finally, you send a response with a message indicating that data is being synced to Meilisearch. + +### Add Meilisearch Sync Page to Admin Dashboard + +The last step is to add a new page to the admin dashboard. This page allows admins to trigger the reindex. You add a new page using a [UI Route](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md). + +A UI route is a React component that specifies the content to be shown in a new page in the Medusa Admin dashboard. You'll create a UI route to display a button that triggers the reindex when clicked. + +Learn more about UI routes in the [UI Routes documentation](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md). + +#### Configure JS SDK + +Before creating the UI route, you'll configure Medusa's [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md). You can use it to send requests to the Medusa server from any client application, including your Medusa Admin customizations. + +The JS SDK is installed by default in your Medusa application. To configure it, create the file `src/admin/lib/sdk.ts` with the following content: + +```ts title="src/admin/lib/sdk.ts" +import Medusa from "@medusajs/js-sdk" + +export const sdk = new Medusa({ + baseUrl: import.meta.env.VITE_BACKEND_URL || "/", + debug: import.meta.env.DEV, + auth: { + type: "session", + }, +}) +``` + +You create an instance of the JS SDK using the `Medusa` class from the JS SDK. You pass it an object having the following properties: + +- `baseUrl`: The base URL of the Medusa server. +- `debug`: A boolean indicating whether to log debug information into the console. +- `auth`: An object specifying the authentication type. When using the JS SDK for admin customizations, you use the `session` authentication type. + +#### Create UI Route + +You'll now create the UI route that displays a button to trigger the reindex. You create a UI route in a `page.tsx` file under a subdirectory of `src/admin/routes` directory. The file's path relative to `src/admin/routes` determines its path in the dashboard. + +So, to create a new page under the Settings section of the Medusa Admin, create the file `src/admin/routes/settings/meilisearch/page.tsx` with the following content: + +```tsx title="src/admin/routes/settings/meilisearch/page.tsx" +import { Container, Heading, Button, toast } from "@medusajs/ui" +import { useMutation } from "@tanstack/react-query" +import { sdk } from "../../../lib/sdk" +import { defineRouteConfig } from "@medusajs/admin-sdk" + +const MeilisearchPage = () => { + const { mutate, isPending } = useMutation({ + mutationFn: () => + sdk.client.fetch("/admin/meilisearch/sync", { + method: "POST", + }), + onSuccess: () => { + toast.success("Successfully triggered data sync to Meilisearch") + }, + onError: (err) => { + console.error(err) + toast.error("Failed to sync data to Meilisearch") + }, + }) + + const handleSync = () => { + mutate() + } + + return ( + +
+ Meilisearch Sync +
+
+ +
+
+ ) +} + +export const config = defineRouteConfig({ + label: "Meilisearch", +}) + +export default MeilisearchPage +``` + +A UI route's file must export: + +1. A React component that defines the content of the page. +2. A configuration object that specifies the route's label in the dashboard. This label is used to show a sidebar item for the new route. + +In the React component, you use `useMutation` hook from `@tanstack/react-query` to create a mutation that sends a `POST` request to the API route you created earlier. In the mutation function, you use the JS SDK to send the request. + +Then, in the return statement, you display a button that triggers the mutation when clicked, which sends a request to the API route you created earlier. + +### Test it Out + +You'll now test out the entire flow. Start by triggering the reindex manually from the Medusa Admin dashboard, then check the Meilisearch dashboard for the indexed products. + +Run the following command to start the Medusa application: + +```bash npm2yarn +npm run dev +``` + +Then, open the Medusa Admin at `http://localhost:9000/app` and log in with the credentials you set up in the first step. + +Can't remember the credentials? Learn how to create a user in the [Medusa CLI reference](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/medusa-cli/commands/user/index.html.md). + +After you log in, go to Settings from the sidebar. You'll find a new "Meilisearch" item in the Settings' sidebar. If you click on it, you'll find the page you created with the button to sync products to Meilisearch. + +If you click on the button, the products will be synced to Meilisearch. + +![The Meilisearch Sync page in the Medusa Admin dashboard with a button to sync products to Meilisearch](https://res.cloudinary.com/dza7lstvk/image/upload/v1758094934/Medusa%20Resources/CleanShot_2025-09-17_at_10.41.51_2x_wph4pp.png) + +You can check that the sync ran and was completed by checking the Medusa logs in the terminal where you started the Medusa application. You should find the following messages: + +```bash +info: Processing meilisearch.sync which has 1 subscribers +info: Starting product indexing... +info: Successfully indexed 4 products +``` + +These messages indicate that the `meilisearch.sync` event was emitted, which triggered the subscriber you created to sync the products using the `syncProductsWorkflow`. + +Finally, you can check the Meilisearch dashboard to see the indexed products. Open the Meilisearch dashboard, either Cloud or local, and choose the index you specified for products in the environment variable `MEILISEARCH_PRODUCT_INDEX_NAME`. You'll find your Medusa products indexed there. + +![The Meilisearch dashboard showing the indexed products](https://res.cloudinary.com/dza7lstvk/image/upload/v1758095145/Medusa%20Resources/CleanShot_2025-09-17_at_10.45.29_2x_y8ytzf.png) + +*** + +## Step 5: Update Index on Product Changes + +You'll now automate the indexing of products whenever a change occurs. This includes when a product is created, updated, or deleted. + +Similar to before, you'll create subscribers to listen to these events. + +### Handle Create and Update Products + +The action to perform when a product is created or updated is the same. You'll use the `syncProductsWorkflow` to sync the product to Meilisearch. + +So, you only need one subscriber to handle these two events. To create the subscriber, create the file `src/subscribers/product-sync.ts` with the following content: + +```ts title="src/subscribers/product-sync.ts" +import { + SubscriberArgs, + type SubscriberConfig, +} from "@medusajs/framework" +import { syncProductsWorkflow } from "../workflows/sync-products" + +export default async function handleProductEvents({ + event: { data }, + container, +}: SubscriberArgs<{ id: string }>) { + await syncProductsWorkflow(container) + .run({ + input: { + filters: { + id: data.id, + }, + }, + }) +} + +export const config: SubscriberConfig = { + event: ["product.created", "product.updated"], +} +``` + +The subscriber listens to the `product.created` and `product.updated` events. When either of these events is emitted, the subscriber triggers the `syncProductsWorkflow` to sync the product to Meilisearch. + +When the `product.created` and `product.updated` events are emitted, the product's ID is passed in the event data payload. You can access this in the `event.data` property of the subscriber function's parameter. + +So, you pass the product's ID to the `syncProductsWorkflow` as a filter to retrieve only the product that was created or updated. + +#### Test it Out + +To test it out, start the Medusa application: + +```bash npm2yarn +npm run dev +``` + +Then, either create a product or update an existing one using the Medusa Admin dashboard. If you check the Meilisearch dashboard, you'll find that the product's index was created or updated. + +### Handle Product Deletion + +When a product is deleted, you need to remove it from the Meilisearch index. This requires a different action than creating or updating a product. You'll create a new workflow that deletes the product from Meilisearch, then create a subscriber that listens to the `product.deleted` event to trigger the workflow. + +#### Create Delete Product Step + +The workflow to delete a product from Meilisearch will have only one step that deletes products by their IDs from Meilisearch. + +So, create the step at `src/workflows/steps/delete-products-from-meilisearch.ts` with the following content: + +```ts title="src/workflows/steps/delete-products-from-meilisearch.ts" +import { + createStep, + StepResponse, +} from "@medusajs/framework/workflows-sdk" +import { MEILISEARCH_MODULE } from "../../modules/meilisearch" + +export type DeleteProductsFromMeilisearchStep = { + ids: string[] +} + +export const deleteProductsFromMeilisearchStep = createStep( + "delete-products-from-meilisearch-step", + async ( + { ids }: DeleteProductsFromMeilisearchStep, + { container } + ) => { + const meilisearchModuleService = container.resolve(MEILISEARCH_MODULE) + + const existingRecords = await meilisearchModuleService.retrieveFromIndex( + ids, + "product" + ) + await meilisearchModuleService.deleteFromIndex( + ids, + "product" + ) + + return new StepResponse(undefined, existingRecords) + }, + async (existingRecords, { container }) => { + if (!existingRecords) { + return + } + const meilisearchModuleService = container.resolve(MEILISEARCH_MODULE) + + await meilisearchModuleService.indexData( + existingRecords, + "product" + ) + } +) +``` + +The step receives the IDs of the products to delete as an input. + +In the step, you resolve the Meilisearch Module's service and retrieve the existing records from Meilisearch. This is useful to revert the deletion if an error occurs. + +Then, you delete the products from Meilisearch and pass the existing records to the compensation function. + +In the compensation function, you reindex the existing records if an error occurs. + +#### Create Delete Product Workflow + +You can now create the workflow that deletes products from Meilisearch. Create the file `src/workflows/delete-products-from-meilisearch.ts` with the following content: + +```ts title="src/workflows/delete-products-from-meilisearch.ts" +import { createWorkflow } from "@medusajs/framework/workflows-sdk" +import { deleteProductsFromMeilisearchStep } from "./steps/delete-products-from-meilisearch" + +type DeleteProductsFromMeilisearchWorkflowInput = { + ids: string[] +} + +export const deleteProductsFromMeilisearchWorkflow = createWorkflow( + "delete-products-from-meilisearch", + (input: DeleteProductsFromMeilisearchWorkflowInput) => { + deleteProductsFromMeilisearchStep(input) + } +) +``` + +The workflow receives an object with the IDs of the products to delete. It then executes the `deleteProductsFromMeilisearchStep` to delete the products from Meilisearch. + +#### Create Delete Product Subscriber + +Finally, you'll create the subscriber that listens to the `product.deleted` event to trigger the above workflow. + +Create the file `src/subscribers/product-delete.ts` with the following content: + +```ts title="src/subscribers/product-delete.ts" +import { + SubscriberArgs, + type SubscriberConfig, +} from "@medusajs/framework" +import { deleteProductsFromMeilisearchWorkflow } from "../workflows/delete-products-from-meilisearch" + +export default async function productDeleteHandler({ + event: { data }, + container, +}: SubscriberArgs<{ id: string }>) { + const logger = container.resolve("logger") + + logger.info(`Deleting product ${data.id} from Meilisearch`) + + await deleteProductsFromMeilisearchWorkflow(container) + .run({ + input: { + ids: [data.id], + }, + }) +} + +export const config: SubscriberConfig = { + event: "product.deleted", +} +``` + +The subscriber listens to the `product.deleted` event. When the event is emitted, the subscriber triggers the `deleteProductsFromMeilisearchWorkflow`, passing it the ID of the product to delete. + +#### Test it Out + +To test product deletion, start the Medusa application: + +```bash npm2yarn +npm run dev +``` + +Then, delete a product from the Medusa Admin dashboard. If you check the Meilisearch dashboard, you'll find that the product index was deleted there as well. + +*** + +## Step 6: Search Products in Next.js Starter Storefront + +The last step is to provide search functionalities to customers on your storefront. In the first step, you installed the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) along with the Medusa application. + +In this step, you'll customize the Next.js Starter Storefront to add search functionality. + +The Next.js Starter Storefront was installed in a separate directory from Medusa. The directory's name is `{your-project}-storefront`. + +So, if your Medusa application's directory is `medusa-search`, you can find the storefront by going back to the parent directory and changing to the `medusa-search-storefront` directory: + +```bash +cd ../medusa-search-storefront # change based on your project name +``` + +### Install Meilisearch Packages + +Before adding the implementation of search functionality, you need to install the Meilisearch packages necessary to add search functionality in your storefront. + +Run the following command in the directory of your Next.js Starter Storefront: + +```bash npm2yarn +npm install @meilisearch/instant-meilisearch react-instantsearch +``` + +This installs the Meilisearch InstantSearch JavaScript library and the React InstantSearch library. You'll use these to build the search functionality. + +### Add Search Client Configuration + +Next, you need to configure the Meilisearch search client. + +In `src/lib/config.ts`, add the following imports at the top of the file: + +```ts title="src/lib/config.ts" badgeLabel="Storefront" badgeColor="blue" +import { + instantMeiliSearch, +} from "@meilisearch/instant-meilisearch" +``` + +Then, add the following at the end of the file: + +```ts title="src/lib/config.ts" badgeLabel="Storefront" badgeColor="blue" +export const { searchClient } = instantMeiliSearch( + process.env.NEXT_PUBLIC_MEILISEARCH_HOST || "", + process.env.NEXT_PUBLIC_MEILISEARCH_API_KEY || "" +) +``` + +In the code above, you create a `searchClient` object that initializes the Meilisearch client with your Meilisearch host and API Key. + +### Set Environment Variables + +In the storefront's `.env.local` file, add the following Meilisearch-related environment variables: + +```plain badgeLabel="Storefront" badgeColor="blue" +NEXT_PUBLIC_MEILISEARCH_HOST=your_meilisearch_host +NEXT_PUBLIC_MEILISEARCH_API_KEY=your_meilisearch_api_key +NEXT_PUBLIC_MEILISEARCH_INDEX_NAME=your-products-index-name +``` + +Where: + +- `your_meilisearch_host` is your Meilisearch host, as explained in the [Add Environment Variables section](#add-environment-variables) earlier. +- `your_meilisearch_api_key` is your Meilisearch API key with search permissions. You can retrieve it as explained in the [Meilisearch Documentation](https://www.meilisearch.com/docs/learn/security/basic_security#obtaining-api-keys). +- `your-products-index-name` is the name of the index you created in Meilisearch to store the products. You can retrieve this as explained in the [Add Environment Variables section](#add-environment-variables) earlier. You'll use this variable later. + +Do not use the `masterKey` as the API key in the storefront, as it has all permissions, including write permissions. Only use an API key with search permissions. + +### Add Search Modal Component + +You'll now add a search modal component that customers can use to search for products. The search modal will display search results in real-time as the customer types in the search query. + +Later, you'll add the search modal to the navigation bar. This allows customers to open the search modal from any page. + +Create the file `src/modules/search/components/modal/index.tsx` with the following content: + +```tsx title="src/modules/search/components/modal/index.tsx" badgeLabel="Storefront" badgeColor="blue" +"use client" + +import React, { useEffect, useState } from "react" +import { Hits, InstantSearch, SearchBox } from "react-instantsearch" +import { searchClient } from "../../../../lib/config" +import Modal from "../../../common/components/modal" +import { Button } from "@medusajs/ui" +import Image from "next/image" +import Link from "next/link" +import { usePathname } from "next/navigation" + +type Hit = { + id: string; + title: string; + description: string; + handle: string; + thumbnail: string; + categories: { + id: string + name: string + handle: string + }[] + tags: { + id: string + value: string + }[] +} + +export default function SearchModal() { + const [isOpen, setIsOpen] = useState(false) + const pathname = usePathname() + + useEffect(() => { + setIsOpen(false) + }, [pathname]) + + return ( + <> +
+ +
+ setIsOpen(false)}> + + + + + + + ) +} + +const Hit = ({ hit }: { hit: Hit }) => { + return ( +
+ {hit.title} +
+

{hit.title}

+

{hit.description}

+
+ +
+ ) +} +``` + +You create a `SearchModal` component that displays a search box and search results using widgets from the `react-instantsearch` library. + +To display each result item (or hit), you create a `Hit` component. This component displays the product's title, description, and thumbnail. You also add a link to the product's page. + +Finally, you show the search modal when the customer clicks a "Search" button. You'll add this button to the navigation bar next. + +### Add Search Button to Navigation Bar + +The last step is to show the search button in the navigation bar. + +In `src/modules/layout/templates/nav/index.tsx`, add the following imports at the top of the file: + +```tsx title="src/modules/layout/templates/nav/index.tsx" badgeLabel="Storefront" badgeColor="blue" +import SearchModal from "@modules/search/components/modal" +``` + +Then, in the return statement of the `Nav` component, add the `SearchModal` component before the `div` surrounding the "Account" link: + +```tsx title="src/modules/layout/templates/nav/index.tsx" badgeLabel="Storefront" badgeColor="blue" + +``` + +The search button will now appear in the navigation bar before the Account link. + +### Test it Out + +To test out the storefront changes and the search API route, start the Medusa application: + +```bash npm2yarn +npm run dev +``` + +Then, start the Next.js Starter Storefront from its directory: + +```bash npm2yarn +npm run dev +``` + +Next, go to `localhost:8000`. You'll find a Search button at the top right of the navigation bar. If you click on it, you can search through your products. You can also click on a product to view its page. + +![The Next.js Starter Storefront showing the search modal with search results](https://res.cloudinary.com/dza7lstvk/image/upload/v1758096281/Medusa%20Resources/CleanShot_2025-09-17_at_11.04.26_2x_bhb9k7.png) + +*** + +## Next Steps + +You've now integrated Meilisearch with Medusa and added search functionality to your storefront. You can expand on these features to: + +- Add filters to the search results. You can do that using [react-instantsearch widgets](https://www.algolia.com/doc/guides/building-search-ui/widgets/showcase/react/). +- Support indexing other data types, such as product categories. You can create subscribers and workflows for categories similar to products. + +### Learn More about Medusa + +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. + +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). + +### Troubleshooting + +If you encounter issues during your development, check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/index.html.md). + +### Getting Help + +If you encounter issues not covered in the troubleshooting guides: + +1. Visit the [Medusa GitHub repository](https://github.com/medusajs/medusa) to report issues or ask questions. +2. Join the [Medusa Discord community](https://discord.gg/medusajs) for real-time support from community members. + + # Integrate Payload CMS with Medusa In this tutorial, you'll learn how to integrate [Payload](https://payloadcms.com/) with Medusa. @@ -84460,15 +85642,15 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -First, you'll be asked for the project's name. Then, when prompted about installing the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose "Yes." +First, you'll be asked for the project's name. Then, when prompted about installing the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose "Yes." Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name and the Next.js Starter Storefront in a separate directory named `{project-name}-storefront`. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterwards, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** @@ -85178,11 +86360,11 @@ Once you're logged in, you can see the `Products`, `Users`, and `Media` collecti ## Step 3: Integrate Payload with Medusa -Now that Payload is set up in the Next.js Starter Storefront, you'll create a Payload [Module](undefined/docs/learn/fundamentals/modules) to integrate it with Medusa. +Now that Payload is set up in the Next.js Starter Storefront, you'll create a Payload [Module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) to integrate it with Medusa. A module is a reusable package that provides functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. -Refer to the [Modules](undefined/docs/learn/fundamentals/modules) documentation to learn more about modules and their structure. +Refer to the [Modules](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) documentation to learn more about modules and their structure. ### a. Create Module Directory @@ -85266,7 +86448,7 @@ export default class PayloadModuleService { The constructor of a module's service receives the following parameters: -1. The [Module container](undefined/docs/learn/fundamentals/modules/container) that allows you to resolve module and Framework resources. You don't need to resolve any resources in this module, so you can leave it empty. +1. The [Module container](https://docs.medusajs.com/docs/learn/fundamentals/modules/container/index.html.md) that allows you to resolve module and Framework resources. You don't need to resolve any resources in this module, so you can leave it empty. 2. The module options, which you'll [pass to the module when you register it later](#e-add-module-to-medusas-configurations) in the Medusa application. In the constructor, you validate the module options and set up the Payload base URL and headers that are necessary to send requests to Payload. @@ -85674,7 +86856,7 @@ The Payload Module is now ready for use. You'll add customizations next to sync ## Step 4: Create Virtual Read-Only Link to Products -Medusa's [Module Links](undefined/docs/learn/fundamentals/module-links) feature allows you to virtually link data models from external services to modules in your Medusa application. Then, when you retrieve data from Medusa, you can also retrieve the linked data from the third-party service automatically. +Medusa's [Module Links](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md) feature allows you to virtually link data models from external services to modules in your Medusa application. Then, when you retrieve data from Medusa, you can also retrieve the linked data from the third-party service automatically. In this step, you'll define a virtual read-only link between the `Products` collection in Payload and the `Product` model in Medusa. Later, you'll be able to retrieve products from Payload while retrieving products in Medusa. @@ -85766,15 +86948,15 @@ The `list` method is implemented to be re-usable with different collections and In this step, you'll create the functionality to create a Medusa product in Payload. You'll later execute that functionality either when triggered by an admin user, or automatically when a product is created in Medusa. -You create custom commerce features in [workflows](undefined/docs/learn/fundamentals/workflows). A workflow is a series of queries and actions, called steps, that complete a task. A workflow is similar to a function, but it allows you to track its executions' progress, define roll-back logic, and configure other advanced features. +You create custom commerce features in [workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). A workflow is a series of queries and actions, called steps, that complete a task. A workflow is similar to a function, but it allows you to track its executions' progress, define roll-back logic, and configure other advanced features. -Refer to the [Workflows documentation](undefined/docs/learn/fundamentals/workflows) to learn more. +Refer to the [Workflows documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) to learn more. The workflow to create a Payload product will have the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the product data from Medusa +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the product data from Medusa - [createPayloadItemsStep](#createPayloadItemsStep): Create the product in Payload -- [updateProductsWorkflow](undefined/references/medusa-workflows/updateProductsWorkflow): Store the Payload product ID in Medusa +- [updateProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateProductsWorkflow/index.html.md): Store the Payload product ID in Medusa You only need to create the `createPayloadItemsStep`, as the other two steps are already available in Medusa. @@ -85840,7 +87022,7 @@ You create a step with the `createStep` function. It accepts three parameters: 1. The step's unique name. 2. An async function that receives two parameters: - The step's input, which is an object holding the collection slug and an array of items to create in Payload. - - An object that has properties including the [Medusa container](undefined/docs/learn/fundamentals/medusa-container), which is a registry of Framework and commerce tools that you can access in the step. + - An object that has properties including the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which is a registry of Framework and commerce tools that you can access in the step. 3. An async compensation function that undoes the actions performed by the step function. This function is only executed if an error occurs during the workflow's execution. In the step function, you resolve the Payload Module's service from the container. Then, you use its `create` method to create the items in Payload. @@ -85959,9 +87141,9 @@ It accepts a second parameter: a constructor function that holds the workflow's In the workflow, you: 1. Retrieve the products from Medusa using the `useQueryGraphStep`. - - This step uses [Query](undefined/docs/learn/fundamentals/module-links/query) to retrieve data across modules. + - This step uses [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) to retrieve data across modules. 2. Prepare the data to create the products in Payload. - - To manipulate data in a workflow, you need to use the `transform` function. Learn more in the [Data Manipulation](undefined/docs/learn/fundamentals/workflows/variable-manipulation) documentation. + - To manipulate data in a workflow, you need to use the `transform` function. Learn more in the [Data Manipulation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/variable-manipulation/index.html.md) documentation. 3. Create the products in Payload using the `createPayloadItemsStep` you created earlier. 4. Prepare the data to update the products in Medusa with the Payload product IDs. - You store the payload ID in the `metadata` field of the Medusa product. @@ -85977,9 +87159,9 @@ You'll use this workflow in the next steps to create Medusa products in Payload. In this step, you'll allow Medusa Admin users to trigger the creation of Medusa products in Payload. To implement this, you'll create: -- An [API route](undefined/docs/learn/fundamentals/api-routes) that emits a `products.sync-payload` event. -- A [subscriber](undefined/docs/learn/fundamentals/events-and-subscribers) that listens to the `products.sync-payload` event and executes the `createPayloadProductsWorkflow`. -- A [setting page](undefined/docs/learn/fundamentals/admin/ui-routes) in the Medusa Admin that allows admin users to trigger the product creation in Payload. +- An [API route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) that emits a `products.sync-payload` event. +- A [subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md) that listens to the `products.sync-payload` event and executes the `createPayloadProductsWorkflow`. +- A [setting page](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md) in the Medusa Admin that allows admin users to trigger the product creation in Payload. ### a. Trigger Product Sync API Route @@ -85987,7 +87169,7 @@ An API route is a REST endpoint that exposes functionalities to clients, such as An API route is created in a `route.ts` file under a sub-directory of the `src/api` directory. The path of the API route is the file's path relative to `src/api`. -Refer to the [API routes](undefined/docs/learn/fundamentals/api-routes) to learn more about them. +Refer to the [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) to learn more about them. Create the file `src/api/admin/payload/sync/[collection]/route.ts` with the following content: @@ -86014,7 +87196,7 @@ export const POST = async ( Since you export a `POST` route handler function, you're exposing a `POST` API route at `/admin/payload/sync/[collection]`, where `[collection]` is a path parameter that represents the collection slug in Payload. -In the function, you resolve the [Event Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/event)'s service and emit a `{collection}.sync-payload` event, where `{collection}` is the collection slug passed in the request. +In the function, you resolve the [Event Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/event/index.html.md)'s service and emit a `{collection}.sync-payload` event, where `{collection}` is the collection slug passed in the request. Finally, you return a success response with a message indicating that the collection is being synced with Payload. @@ -86024,7 +87206,7 @@ Next, you'll create a subscriber that listens to the `products.sync-payload` eve A subscriber is an asynchronous function that is executed whenever its associated event is emitted. -Refer to the [Subscribers documentation](undefined/docs/learn/fundamentals/events-and-subscribers) to learn more about subscribers. +Refer to the [Subscribers documentation](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md) to learn more about subscribers. To create a subscriber, create the file `src/subscribers/products-sync-payload.ts` with the following content: @@ -86085,7 +87267,7 @@ A subscriber file must export: - An asynchronous function, which is the subscriber function that is executed when the event is emitted. - A configuration object that defines the event the subscriber listens to. -In the subscriber, you use [Query](undefined/docs/learn/fundamentals/module-links/query) to retrieve all products from Medusa. +In the subscriber, you use [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) to retrieve all products from Medusa. Then, you filter the products to only include those that don't have a payload product ID set in `product.metadata.payload_id`, and you execute the `createPayloadProductsWorkflow` with the filtered products' IDs. @@ -86097,7 +87279,7 @@ Next, you'll create a setting page in the Medusa Admin that allows admin users t #### Initialize JS SDK -To send requests from your Medusa Admin customizations to the Medusa server, you need to initialize the [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk). +To send requests from your Medusa Admin customizations to the Medusa server, you need to initialize the [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md). Create the file `src/admin/lib/sdk.ts` with the following content: @@ -86113,13 +87295,13 @@ export const sdk = new Medusa({ }) ``` -Refer to the [JS SDK documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk) to learn more about initializing the SDK. +Refer to the [JS SDK documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md) to learn more about initializing the SDK. #### Create the Setting Page -A setting page is a [UI route](undefined/docs/learn/fundamentals/admin/ui-routes) that adds a custom page to the Medusa Admin under the Settings section. The UI route is a React component that renders the page's content. +A setting page is a [UI route](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md) that adds a custom page to the Medusa Admin under the Settings section. The UI route is a React component that renders the page's content. -Refer to the [UI Routes](undefined/docs/learn/fundamentals/admin/ui-routes) documentation to learn more. +Refer to the [UI Routes](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md) documentation to learn more. To create the setting page, create the file `src/admin/routes/settings/payload/page.tsx` with the following content: @@ -86867,7 +88049,7 @@ To handle the `product-variant.created` event, you'll create a workflow that add The workflow will have the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the product variant from Medusa +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the product variant from Medusa You only need to create the `updatePayloadItemsStep` step. @@ -87098,7 +88280,7 @@ To handle the `product-variant.updated` event, you'll create a workflow that upd The workflow will have the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the product variant from Medusa +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the product variant from Medusa #### Update Payload Product Variants Workflow @@ -87414,7 +88596,7 @@ To handle the `product-option.created` event, you'll create a workflow that adds The workflow will have the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the product option from Medusa +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the product option from Medusa #### Create Payload Product Options Workflow @@ -87692,13 +88874,13 @@ You've successfully integrated Medusa with Payload to manage content related to ### Learn More about Medusa -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). ### Troubleshooting -If you encounter issues during your development, check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting). +If you encounter issues during your development, check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/index.html.md). ### Getting Help @@ -87746,13 +88928,13 @@ You'll first be asked for the project's name. Then, when you're asked whether yo Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name, and the Next.js Starter Storefront in a directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more about Medusa's architecture in [this documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more about Medusa's architecture in [this documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credential and submit the form. Afterwards, you can login with the new user and explore the dashboard. The Next.js Starter Storefront is also running at `http://localhost:8000`. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** @@ -87807,7 +88989,7 @@ To integrate third-party services into Medusa, you create a custom module. A mod Medusa's Notification Module delegates sending notifications to other modules, called module providers. In this step, you'll create a Resend Module Provider that implements sending notifications through the email channel. In later steps, you'll send email notifications with Resend when an order is placed through this provider. -Learn more about modules in [this documentation](undefined/docs/learn/fundamentals/modules). +Learn more about modules in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). ### Create Module Directory @@ -87862,7 +89044,7 @@ The `ResendNotificationProviderService` class also has the following properties: - `api_key`: The Resend API key. - `from`: The email address to send the emails from. - `html_templates`: An optional object to replace the default subject and template that the Resend Module uses. This is also useful to support custom emails in different Medusa application setups. -- `logger` property, which is an instance of Medusa's [Logger](undefined/docs/learn/debugging-and-testing/logging), to log messages. +- `logger` property, which is an instance of Medusa's [Logger](https://docs.medusajs.com/docs/learn/debugging-and-testing/logging/index.html.md), to log messages. To send requests using the `resendClient`, you need to initialize it in the class's constructor. So, add the following constructor to `ResendNotificationProviderService`: @@ -87889,7 +89071,7 @@ class ResendNotificationProviderService extends AbstractNotificationProviderServ A module's service accepts two parameters: -1. Dependencies resolved from the [Module's container](undefined/docs/learn/fundamentals/modules/container), which is the module's local registry that the Medusa application adds Framework tools to. In this service, you resolve the [Logger utility](undefined/docs/learn/debugging-and-testing/logging) from the module's container. +1. Dependencies resolved from the [Module's container](https://docs.medusajs.com/docs/learn/fundamentals/modules/container/index.html.md), which is the module's local registry that the Medusa application adds Framework tools to. In this service, you resolve the [Logger utility](https://docs.medusajs.com/docs/learn/debugging-and-testing/logging/index.html.md) from the module's container. 2. The module's options that are passed to the module in Medusa's configuration as you'll see in a later section. Using the API key passed in the module's options, you initialize the Resend client. You also set the `options` and `logger` properties. @@ -88750,7 +89932,7 @@ So, to send a confirmation email when a customer places an order, which is a com Instead, you'll create a subscriber that listens to the `order.placed` event and sends an email when the event is emitted. -Learn more about Medusa's event system in [this documentation](undefined/docs/learn/fundamentals/events-and-subscribers). +Learn more about Medusa's event system in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md). ### Send Order Confirmation Email Workflow @@ -88758,7 +89940,7 @@ To send the order confirmation email, you need to retrieve the order's details f A workflow is a series of queries and actions, called steps, that complete a task. You construct a workflow like you construct a function, but it's a special function that allows you to track its executions' progress, define roll-back logic, and configure other advanced features. Then, you execute the workflow from other customizations, such as in a subscriber. -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows) +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) #### Send Notification Step @@ -88786,7 +89968,7 @@ You define the `sendNotificationStep` using the `createStep` function that accep - A string indicating the step's unique name. - The step's function definition as a second parameter. It accepts the step's input as a first parameter, and an object of options as a second. -The `container` property in the second parameter is an instance of the [Medusa container](undefined/docs/learn/fundamentals/medusa-container), which is a registry of Framework and commerce tools, such as a module's service, that you can resolve to utilize their functionalities. +The `container` property in the second parameter is an instance of the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which is a registry of Framework and commerce tools, such as a module's service, that you can resolve to utilize their functionalities. The Medusa container is accessible by all customizations, such as workflows and subscribers, except for modules. Each module has its own container with Framework tools like the Logger utility. @@ -88860,14 +90042,14 @@ You create a workflow using `createWorkflow` from the Workflows SDK. It accepts It accepts as a second parameter a constructor function, which is the workflow's implementation. The workflow has the following steps: -1. `useQueryGraphStep`, which is a step implemented by Medusa that uses [Query](undefined/docs/learn/fundamentals/module-links/query), a tool that allows you to retrieve data across modules. You use it to retrieve the order's details. +1. `useQueryGraphStep`, which is a step implemented by Medusa that uses [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), a tool that allows you to retrieve data across modules. You use it to retrieve the order's details. 2. `sendNotificationStep` which is the step you implemented. You pass it an array with one object, which is the notification's details having following properties: - `to`: The address to send the email to. You pass the customer's email that is stored in the order. - `channel`: The channel to send the notification through, which is `email`. Since you specified `email` in the Resend Module Provider's `channel` option, the Notification Module will delegate the sending to the Resend Module Provider's service. - `template`: The email's template type. You retrieve the template content in the `ResendNotificationProviderService`'s `send` method based on the template specified here. - `data`: The data to pass to the email template, which is the order's details. -A workflow's constructor function has some constraints in implementation. Learn more about them in [this documentation](undefined/docs/learn/fundamentals/workflows/constructor-constraints). +A workflow's constructor function has some constraints in implementation. Learn more about them in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/constructor-constraints/index.html.md). You'll execute the workflow when you create the subscriber next. @@ -88906,7 +90088,7 @@ A subscriber file exports: - An asynchronous function that's executed whenever the associated event is emitted, which is the `order.placed` event. - A configuration object with an `event` property indicating the event the subscriber is listening to. -The subscriber function accepts the event's details as a first paramter which has a `data` property that holds the data payload of the event. For example, Medusa emits the `order.placed` event with the order's ID in the data payload. The function also accepts as a second parameter the [Medusa container](undefined/docs/learn/fundamentals/medusa-container). +The subscriber function accepts the event's details as a first paramter which has a `data` property that holds the data payload of the event. For example, Medusa emits the `order.placed` event with the order's ID in the data payload. The function also accepts as a second parameter the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). In the function, you execute the `sendOrderConfirmationWorkflow` by invoking it, passing it the `container`, then using its `run` method. The `run` method accepts an object having an `input` property, which is the input to pass to the workflow. You pass the ID of the placed order as received in the event's data payload. @@ -88916,7 +90098,7 @@ This subscriber now runs whenever an order is placed. You'll see this in action ## Test it Out: Place an Order -To test out the Resend integration, you'll place an order using the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter) that you installed as part of installing Medusa. +To test out the Resend integration, you'll place an order using the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) that you installed as part of installing Medusa. Start your Medusa application first: @@ -88970,20 +90152,20 @@ If you check the inbox of the email address you specified in the shipping addres ## Next Steps -You've now integrated Medusa with Resend. You can add more templates for other emails, such as customer registration confirmation, user invites, and more. Check out the [Events Reference](undefined/references/events) for a list of all events that the Medusa application emits. +You've now integrated Medusa with Resend. You can add more templates for other emails, such as customer registration confirmation, user invites, and more. Check out the [Events Reference](https://docs.medusajs.com/references/events/index.html.md) for a list of all events that the Medusa application emits. ### More Resend Email Templates Find more email templates to use with the Resend Module Provider in the following guides: -- [Send Invite User Email](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/user/invite-user-subscriber). -- [Send Reset Password Email](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/reset-password). +- [Send Invite User Email](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/user/invite-user-subscriber/index.html.md). +- [Send Reset Password Email](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/reset-password/index.html.md). ### Learn More About Medusa -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). # Integrate Medusa with Sanity (CMS) @@ -89025,13 +90207,13 @@ You'll first be asked for the project's name. Then, when you're asked whether yo Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name, and the Next.js Starter Storefront in a directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more about Medusa's architecture in [this documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more about Medusa's architecture in [this documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credential and submit the form. Afterwards, you can login with the new user and explore the dashboard. The Next.js Starter Storefront is also running at `http://localhost:8000`. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** @@ -89073,7 +90255,7 @@ To integrate third-party services into Medusa, you create a custom module. A mod In this step, you'll create a Sanity Module that provides the interface to connect to and interact with Sanity. In later steps, you'll use the functionalities provided by this module to sync products to Sanity or retrieve documents from it. -Learn more about modules in [this documentation](undefined/docs/learn/fundamentals/modules). +Learn more about modules in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). ### Create Module Directory @@ -89083,9 +90265,9 @@ A module is created under the `src/modules` directory of your Medusa application You define a module's functionalities in a service. A service is a TypeScript or JavaScript class that the module exports. In the service's methods, you can connect to the database, which is useful if your module defines tables in the database, or connect to a third-party service. -Medusa registers the module's service in the [Medusa container](undefined/docs/learn/fundamentals/medusa-container), allowing you to easily resolve the service from other customizations and use its methods. +Medusa registers the module's service in the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), allowing you to easily resolve the service from other customizations and use its methods. -The Medusa application registers resources, such as a module's service or the [logging tool](undefined/docs/learn/debugging-and-testing/logging), in the Medusa container so that you can resolve them from other customizations, as you'll see in later sections. Learn more about it in [this documentation](undefined/docs/learn/fundamentals/medusa-container). +The Medusa application registers resources, such as a module's service or the [logging tool](https://docs.medusajs.com/docs/learn/debugging-and-testing/logging/index.html.md), in the Medusa container so that you can resolve them from other customizations, as you'll see in later sections. Learn more about it in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). In this section, you'll create the Sanity Module's service and the methods necessary to connect to Sanity. @@ -89114,7 +90296,7 @@ You create the `SanityModuleService` class that for now only has three propertie - `client` property of type `SanityClient` (from the Sanity SDK you installed in the previous step) to send requests to Sanity. - `studioUrl` property which will hold the URL to access the Sanity studio. -- `logger` property, which is an instance of Medusa's [Logger](undefined/docs/learn/debugging-and-testing/logging), to log messages. +- `logger` property, which is an instance of Medusa's [Logger](https://docs.medusajs.com/docs/learn/debugging-and-testing/logging/index.html.md), to log messages. In the service, you want to initialize the client early-on so that you can use it in the service's methods. This requires options to be passed to the client, like the Sanity API key or project ID. @@ -89187,7 +90369,7 @@ class SanityModuleService { The service's constructor accepts two parameters: -1. Resources to resolve from the Module's container. A module has a different container than the Medusa application, which you can learn more about it in [this documentation](undefined/docs/learn/fundamentals/modules/container). +1. Resources to resolve from the Module's container. A module has a different container than the Medusa application, which you can learn more about it in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/container/index.html.md). 2. The options passed to the module. In the constructor, you create a Sanity client using the `createClient` function imported from `@sanity/client`. You pass it the options that the module receives. @@ -89509,9 +90691,9 @@ In the next steps, you'll create a link between the Product and Sanity modules t ## Step 5: Link Product and Sanity Modules -Since a product has a document in Sanity, you want to build an association between the [Product](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product) and Sanity modules so that when you retrieve a product, you also retrieve its associated Sanity document. +Since a product has a document in Sanity, you want to build an association between the [Product](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/index.html.md) and Sanity modules so that when you retrieve a product, you also retrieve its associated Sanity document. -However, modules are [isolated](undefined/docs/learn/fundamentals/modules/isolation) to ensure they're re-usable and don't have side effects when integrated into the Medusa application. So, to build associations between modules, you define [module links](undefined/docs/learn/fundamentals/module-links). +However, modules are [isolated](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md) to ensure they're re-usable and don't have side effects when integrated into the Medusa application. So, to build associations between modules, you define [module links](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md). A Module Link associates two modules' data models while maintaining module isolation. A data model can be a table in the database or a virtual model from an external systems. @@ -89563,7 +90745,7 @@ A workflow is a series of queries and actions, called steps, that complete a tas Within a workflow's steps, you resolve modules to use their service's functionalities as part of a bigger flow. Then, you can execute the workflow from other customizations, such as in response to an event or in an API route. -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows) +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) In this section, you'll create a workflow that syncs products from Medusa to Sanity. Later, you'll execute this workflow when a product is created or updated, or when an admin user triggers the syncing manually. @@ -89640,7 +90822,7 @@ You define the `syncStep` using the `createStep` function, which accepts two par The step function accepts the step's input as a first parameter, and an object of options as a second. The object of options has a `container` property, which is an instance of the Medusa container that you can use to resolve resources. -In the step, you resolve from the Medusa container Sanity Module's service and [Query](undefined/docs/learn/fundamentals/module-links/query), which is a tool that allows you to retrieve data across modules and links. +In the step, you resolve from the Medusa container Sanity Module's service and [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), which is a tool that allows you to retrieve data across modules and links. You use Query's `graph` method to retrieve products, filtering them by their IDs and applying pagination configurations. The `graph` method accepts a `fields` property in its object parameter, which indicates the product data model's fields and relations to retrieve. @@ -89711,7 +90893,7 @@ If no errors occur, the step returns an instance of `StepResponse`, which must b `StepResponse` accepts a second parameter, which is passed to the compensation function. A compensation function defines the rollback logic of a step, and it's only executed if an error occurs in the workflow. This eliminates data inconsistency if an error occurs and the workflow can't finish execution successfully. -Learn more about compensation functions in [this documentation](undefined/docs/learn/fundamentals/workflows/compensation-function). +Learn more about compensation functions in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/compensation-function/index.html.md). The `syncStep` creates or updates products in Sanity. So, the compensation function must delete created documents or revert the update of a document to its previous data. The compensation function is only executed if an error occurs. @@ -89786,7 +90968,7 @@ The `retentionTime` property indicates how long should the workflow's progress b `createWorkflow` accepts as a second parameter a constructor function, which is the workflow's implementation. In the function, you execute the `syncStep` to sync the specified products in the input, then return its result. Workflows must return an instance of `WorkflowResponse`. -A workflow's constructor function has some constraints in implementation. Learn more about them in [this documentation](undefined/docs/learn/fundamentals/workflows/constructor-constraints). +A workflow's constructor function has some constraints in implementation. Learn more about them in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/constructor-constraints/index.html.md). You'll execute and test this workflow in the next steps. @@ -89802,7 +90984,7 @@ A subscriber is an asynchronous function that listens to one or more events. The Subscribers are useful when you want to perform an action that isn't an integral part of a flow, but as a reaction to a performed action. In this case, syncing the products to Sanity isn't integral to creating a product, so you do it in a subscriber after the product is created. -Learn more about events and subscribers in [this documentation](undefined/docs/learn/fundamentals/events-and-subscribers). You can also find the list of emitted events in [this reference](undefined/references/events). +Learn more about events and subscribers in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md). You can also find the list of emitted events in [this reference](https://docs.medusajs.com/references/events/index.html.md). So, to run the workflow you defined in the previous event when a product is created or updated, you'll create a subscriber that listens to the `product.created` and `product.updated` events. @@ -90195,7 +91377,7 @@ You can now manage the product's content in Sanity, add more fields, and customi There are cases where you need to trigger the syncing of products manually, such as when an error occurs or you have products from before creating this integration. -The Medusa Admin dashboard is customizable, allowing you to either inject components, called [widgets](undefined/docs/learn/fundamentals/admin/widgets), into existing pages, or adding new pages, called [UI routes](undefined/docs/learn/fundamentals/admin/ui-routes). In these customizations, you can send requests to the Medusa application to perform custom operations. +The Medusa Admin dashboard is customizable, allowing you to either inject components, called [widgets](https://docs.medusajs.com/docs/learn/fundamentals/admin/widgets/index.html.md), into existing pages, or adding new pages, called [UI routes](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md). In these customizations, you can send requests to the Medusa application to perform custom operations. In this step, you'll add a widget to the product's details page. In that page, you'll show whether a product is synced with Sanity, and allow the admin user to trigger syncing it manually. @@ -90203,7 +91385,7 @@ In this step, you'll add a widget to the product's details page. In that page, y Before you do that, however, you need two new API routes in your Medusa application: one to retrieve a document from Sanity, and one to trigger syncing the product data. -An API route is a REST API endpoint that exposes commerce features to the admin dashboard or other frontend clients. Learn more about API routes in [this documentation](undefined/docs/learn/fundamentals/api-routes). +An API route is a REST API endpoint that exposes commerce features to the admin dashboard or other frontend clients. Learn more about API routes in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). ### Get Sanity Document API Route @@ -90268,7 +91450,7 @@ You return in the JSON response an object having the `sanity_document` and `stud You'll test out this route in a later section. -Since the API route is added under the `/admin` prefix, only authenticated admin users can access it. Learn more about protected routes in [this documentation](undefined/docs/learn/fundamentals/api-routes/protected-routes). +Since the API route is added under the `/admin` prefix, only authenticated admin users can access it. Learn more about protected routes in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/protected-routes/index.html.md). ### Trigger Sanity Sync API Route @@ -90307,7 +91489,7 @@ In the next section, you'll customize the admin dashboard and send requests to t In this section, you'll add a widget in the product details page. The widget will show the Sanity document of the product and triggers syncing it to Sanity using the API routes you created. -To send requests from admin customizations to the Medusa server, you need to use Medusa's [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk). You'll also use [Tanstack Query](https://tanstack.com/query/latest) to benefit from features like data caching and invalidation. +To send requests from admin customizations to the Medusa server, you need to use Medusa's [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md). You'll also use [Tanstack Query](https://tanstack.com/query/latest) to benefit from features like data caching and invalidation. Do not install Tanstack Query as that will cause unexpected errors in your development. If you prefer installing it for better auto-completion in your code editor, make sure to install `v5.64.2` as a development dependency. @@ -90325,7 +91507,7 @@ export const sdk = new Medusa({ }) ``` -You initialize the JS SDK and export it. You can learn more about configuring the JS SDK in [this guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk). +You initialize the JS SDK and export it. You can learn more about configuring the JS SDK in [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md). Next, you'll create hooks using Tanstack Query to send requests to the API routes you created earlier. @@ -90513,15 +91695,15 @@ export default ProductWidget The file exports a `ProductWidget` component and a `config` object created with `defineWidgetConfig` from the Admin Extension SDK. In the `config` object, you specify the zone to inject the widget into in the `zone` property. -Find all widget injection zones in [this reference](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-widget-injection-zones). +Find all widget injection zones in [this reference](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-widget-injection-zones/index.html.md). In the widget, you use the `useSanityDocument` to retrieve the product's document from Sanity by sending a request to the API route you created earlier. You show that document's details and a button to trigger syncing the data. When the "Sync" button is clicked, you use the `useTriggerSanityProductSync` hook which sends a request to the API route you created earlier and executes the workflow that syncs the product to Sanity. The workflow will execute in the background, since you configured its step to be async. -To render a widget that matches the rest of the admin dashboard's design, you use components from the [Medusa UI package](undefined/ui), such as the `CodeBlock` or `Container` components. +To render a widget that matches the rest of the admin dashboard's design, you use components from the [Medusa UI package](https://docs.medusajs.com/ui/index.html.md), such as the `CodeBlock` or `Container` components. -Refer to the [Admin Widgets](undefined/docs/learn/fundamentals/admin/widgets) documentation to learn more. +Refer to the [Admin Widgets](https://docs.medusajs.com/docs/learn/fundamentals/admin/widgets/index.html.md) documentation to learn more. ### Test it Out @@ -90539,9 +91721,9 @@ Earlier in this guide when introducing workflows, you learned that you can track ### Retrieve Sync Executions API Route -Medusa has a [workflow engine](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/workflow-engine) that manages workflow executions, roll-backs, and other functionalities under the hood. +Medusa has a [workflow engine](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/workflow-engine/index.html.md) that manages workflow executions, roll-backs, and other functionalities under the hood. -The workflow engine is an [Infrastructure Module](undefined/docs/learn/fundamentals/modules/infrastructure-modules), which can be replaced with a [Redis Workflow Engine](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/workflow-engine/redis), or a custom one of your choice, allowing you to take ownership of your application's tooling. +The workflow engine is an [Infrastructure Module](https://docs.medusajs.com/docs/learn/fundamentals/modules/infrastructure-modules/index.html.md), which can be replaced with a [Redis Workflow Engine](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/workflow-engine/redis/index.html.md), or a custom one of your choice, allowing you to take ownership of your application's tooling. In your customizations, you can resolve the workflow engine from the container and manage executions of a workflow, such as retrieve them and check their progress. @@ -90597,7 +91779,7 @@ export const POST = async (req: MedusaRequest, res: MedusaResponse) => { This adds a `POST` API route at `/admin/sanity/syncs`. In the route handler, you execute the `sanitySyncProductsWorkflow` without passing it a `product_ids` input. The step in the workflow will retrieve all products, instead of filtering them by ID, and sync them to Sanity. -You return the transaction ID of the workflow, which you can use to track the execution's progress since the workflow will run in the background. This is not implemented in this guide, but Medusa has a [Get Execution API route](undefined/api/admin#workflows-executions_getworkflowsexecutionsworkflow_idtransaction_id) that you can use to get the details of a workflow's execution. +You return the transaction ID of the workflow, which you can use to track the execution's progress since the workflow will run in the background. This is not implemented in this guide, but Medusa has a [Get Execution API route](https://docs.medusajs.com/api/admin#workflows-executions_getworkflowsexecutionsworkflow_idtransaction_id) that you can use to get the details of a workflow's execution. ### Add Sanity UI Route @@ -90778,9 +91960,9 @@ The file must export the UI route's component. Also, to add an item in the sideb In the UI route, you use the `useSanitySyncs` hook to retrieve the list of sync executions and display them with their status. You also show a "Trigger Sync" button that, when clicked, uses the mutation from the `useTriggerSanitySync` hook to send a request to the Medusa application and trigger the sync. -To display components that match the design of the Medusa Admin, you use components from the [Medusa UI package](undefined/ui). +To display components that match the design of the Medusa Admin, you use components from the [Medusa UI package](https://docs.medusajs.com/ui/index.html.md). -Learn more about UI routes in [this documentation](undefined/docs/learn/fundamentals/admin/ui-routes). +Learn more about UI routes in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md). ### Test it Out @@ -90794,9 +91976,9 @@ If you click on it, you'll see a table of the latest syncs. You also trigger syn You've now integrated Medusa with Sanity and can benefit from powerful commerce and CMS features. -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). # Integrate Segment (Analytics) with Medusa @@ -90838,15 +92020,15 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -First, you'll be asked for the project's name. Then, when prompted about installing the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose "Yes." +First, you'll be asked for the project's name. Then, when prompted about installing the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose "Yes." Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name and the Next.js Starter Storefront in a separate directory named `{project-name}-storefront`. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterwards, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** @@ -90854,11 +92036,11 @@ Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/for To integrate third-party services into Medusa, you create a custom module. A module is a reusable package with functionalities related to a single feature or domain. -Medusa's [Analytics Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/analytics) provides an interface to track events in your Medusa application. It delegates the actual tracking to the configured Analytics Module Provider. +Medusa's [Analytics Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/analytics/index.html.md) provides an interface to track events in your Medusa application. It delegates the actual tracking to the configured Analytics Module Provider. In this step, you'll integrate Segment as an Analytics Module Provider. Later, you'll use it to track events in your Medusa application. -Refer to the [Modules](undefined/docs/learn/fundamentals/modules) documentation to learn more about modules in Medusa. +Refer to the [Modules](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) documentation to learn more about modules in Medusa. ### a. Install Segment Node SDK @@ -90918,7 +92100,7 @@ An Analytics Module Provider's service must extend the `AbstractAnalyticsProvide A module provider's constructor receives two parameters: -- `container`: The [module's container](undefined/docs/learn/fundamentals/modules/container) that contains Framework resources available to the module. In this tutorial, you don't need to resolve any resources. +- `container`: The [module's container](https://docs.medusajs.com/docs/learn/fundamentals/modules/container/index.html.md) that contains Framework resources available to the module. In this tutorial, you don't need to resolve any resources. - `options`: Options that are passed to the module provider when it's registered in Medusa's configurations. You define the following option: - `writeKey`: The Segment write key. You'll learn how to retrieve and set this option in the [Add Module Provider to Medusa's Configurations](#h-add-module-provider-to-medusas-configurations) section. @@ -90926,7 +92108,7 @@ In the constructor, you create a Segment client using the Segment Node SDK. You You'll use this client to implement the service's methods in the next sections. -Refer to the [Create Analytics Module Provider](undefined/references/analytics/provider) guide for detailed information about the methods. +Refer to the [Create Analytics Module Provider](https://docs.medusajs.com/references/analytics/provider/index.html.md) guide for detailed information about the methods. ### d. Implement identify Method @@ -90974,7 +92156,7 @@ The `identify` method receives an object with the following properties: - `group`: Alternatively, the group being identified. If this property is present, the `actor_id` is ignored. - `properties`: Additional properties to associate with the user or group. This can include traits like name, email, and so on. -The method receives other parameters, which you can find in the [Create Analytics Module Provider](undefined/references/analytics/provider#identify) guide. +The method receives other parameters, which you can find in the [Create Analytics Module Provider](https://docs.medusajs.com/references/analytics/provider#identify/index.html.md) guide. #### Method Logic @@ -91028,7 +92210,7 @@ The `track` method receives an object with the following properties: - `event`: The name of the event being tracked. - `properties`: Additional properties associated with the event. This can include details like product ID, order ID, and so on. -The method receives other parameters, which you can find in the [Create Analytics Module Provider](undefined/references/analytics/provider#track) guide. +The method receives other parameters, which you can find in the [Create Analytics Module Provider](https://docs.medusajs.com/references/analytics/provider#track/index.html.md) guide. #### Method Logic @@ -91159,9 +92341,9 @@ You'll test out the integration as you set up event tracking in the next steps. You'll first track the order-placement event, which is triggered natively in the Medusa application. -Medusa's events system allows you to listen to events triggered by the Medusa application and execute custom logic asynchronously in a [subscriber](undefined/docs/learn/fundamentals/events-and-subscribers). +Medusa's events system allows you to listen to events triggered by the Medusa application and execute custom logic asynchronously in a [subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md). -In the subscriber, you execute functionalities created in [workflows](undefined/docs/learn/fundamentals/workflows). A workflow is a series of actions, called steps, that complete a task. +In the subscriber, you execute functionalities created in [workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). A workflow is a series of actions, called steps, that complete a task. In this step, you'll create a workflow that tracks the `order.placed` event in Segment. Then, you'll create a subscriber that listens to this event and executes the workflow. @@ -91215,9 +92397,9 @@ You create a step with `createStep` from the Workflows SDK. It accepts two param - `userId`: The ID of the user performing the event. - `properties`: Additional properties associated with the event. - `timestamp`: The timestamp of the event (optional). - - An object that has properties including the [Medusa container](undefined/docs/learn/fundamentals/medusa-container), which is a registry of Framework and commerce tools that you can access in the step. + - An object that has properties including the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which is a registry of Framework and commerce tools that you can access in the step. -The Medusa container is different from the module's container. Since modules are isolated, they each have a container with their resources. Refer to the [Module Container](undefined/docs/learn/fundamentals/modules/container) documentation for more information. +The Medusa container is different from the module's container. Since modules are isolated, they each have a container with their resources. Refer to the [Module Container](https://docs.medusajs.com/docs/learn/fundamentals/modules/container/index.html.md) documentation for more information. In the step function, you resolve the Analytics Module's service from the Medusa container. This service is the interface to track events with the configured Analytics Module Provider, which is Segment in this case. @@ -91303,13 +92485,13 @@ It accepts as a second parameter a constructor function, which is the workflow's In the workflow's constructor function, you: -1. Retrieve the Medusa order using the `useQueryGraphStep` helper step. This step uses Medusa's [Query](undefined/docs/learn/fundamentals/module-links/query) tool to retrieve data across modules. You pass it the order ID to retrieve. -2. Use [transform](undefined/docs/learn/fundamentals/workflows/variable-manipulation) to prepare the tracking data, as direct data and variable manipulation isn't allowed in workflows. Learn more in the [Data Manipulation](undefined/docs/learn/fundamentals/workflows/variable-manipulation) documentation. +1. Retrieve the Medusa order using the `useQueryGraphStep` helper step. This step uses Medusa's [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) tool to retrieve data across modules. You pass it the order ID to retrieve. +2. Use [transform](https://docs.medusajs.com/docs/learn/fundamentals/workflows/variable-manipulation/index.html.md) to prepare the tracking data, as direct data and variable manipulation isn't allowed in workflows. Learn more in the [Data Manipulation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/variable-manipulation/index.html.md) documentation. 3. Send the tracking event to Segment using the `trackEventStep` you created in the previous step. You now have the workflow that tracks the order placement event. -Refer to the [Workflows](undefined/docs/learn/fundamentals/workflows) documentation to learn more about workflows and steps. +Refer to the [Workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) documentation to learn more about workflows and steps. ### c. Handle order.placed Event @@ -91350,11 +92532,11 @@ The subscriber function receives an object as a parameter that has the following In the subscriber function, you execute the `trackOrderPlacedWorkflow` by invoking it, passing the Medusa container as a parameter. Then, you chain a `run` method, passing it the order ID from the event's data payload as input. -Refer to the [Events and Subscribers](undefined/docs/learn/fundamentals/events-and-subscribers) documentation to learn more about creating subscribers. +Refer to the [Events and Subscribers](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md) documentation to learn more about creating subscribers. ### Test it Out -You'll now test out the segment integration by placing an order using the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter). +You'll now test out the segment integration by placing an order using the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md). The Next.js Starter Storefront was installed in a separate directory from Medusa. The directory's name is `{your-project}-storefront`. @@ -91395,7 +92577,7 @@ In your Medusa application, you often need to track custom events that are relev In Medusa, you can emit custom events in your workflows when an action occurs. Then, you can create a subscriber that listens to the custom event and executes a workflow to track it in Segment. -For example, if you have a `createQuoteWorkflow`, you can use Medusa's [emitEventStep](undefined/docs/learn/fundamentals/events-and-subscribers/emit-event#emit-event-in-a-workflow) to emit a custom event after the quote is created: +For example, if you have a `createQuoteWorkflow`, you can use Medusa's [emitEventStep](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/emit-event#emit-event-in-a-workflow/index.html.md) to emit a custom event after the quote is created: ```ts title="src/workflows/create-quote.ts" import { @@ -91452,17 +92634,17 @@ The above example assumes you have a `trackQuoteWorkflow` that tracks the quote You've now integrated Segment with your Medusa application and tracked common events like order placement. You can expand on the features in this tutorial to: -- Track more events in your Medusa application, such as user sign-ups, cart additions, and more. You can refer to the [Events Reference](undefined/references/events) for a full list of events emitted by Medusa. +- Track more events in your Medusa application, such as user sign-ups, cart additions, and more. You can refer to the [Events Reference](https://docs.medusajs.com/references/events/index.html.md) for a full list of events emitted by Medusa. - Emit custom events that are relevant for your business use case, and track them in Segment. - Add destinations to Segment to benefit from the data collected. Segment supports various destinations, such as Google Analytics, Metabase, and more. -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). ### Troubleshooting -If you encounter issues during your development, check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting). +If you encounter issues during your development, check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/index.html.md). ### Getting Help @@ -91514,15 +92696,15 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -First, you'll be asked for the project's name. Then, when prompted about installing the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose "Yes." +First, you'll be asked for the project's name. Then, when prompted about installing the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose "Yes." Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name and the Next.js Starter Storefront in a separate directory named `{project-name}-storefront`. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterwards, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** @@ -91532,7 +92714,7 @@ Medusa supports instrumentation and reporting through OpenTelemetry, which allow In this step, you'll set up instrumentation in your Medusa application using Sentry. -Refer to the [Instrumentation](undefined/docs/learn/debugging-and-testing/instrumentation) documentation for more details on how to set up instrumentation in Medusa. +Refer to the [Instrumentation](https://docs.medusajs.com/docs/learn/debugging-and-testing/instrumentation/index.html.md) documentation for more details on how to set up instrumentation in Medusa. ### a. Install Instrumentation Dependencies @@ -91668,7 +92850,7 @@ Tracing also works for your custom API routes, workflow executions, Query usages In this section, you'll test it by creating a custom API route that throws an error. For now, you'll only view its tracing in Sentry. Later, you'll configure capturing HTTP request errors in Sentry. -An [API Route](undefined/docs/learn/fundamentals/api-routes) is an endpoint that exposes commerce features to external applications and clients, such as storefronts. +An [API Route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) is an endpoint that exposes commerce features to external applications and clients, such as storefronts. An API route is created in a `route.ts` file under a sub-directory of the `src/api` directory. The path of the API route is the file's path relative to `src/api`. @@ -91729,7 +92911,7 @@ In the previous step, you tested tracing in Sentry by creating a custom API rout In this step, you'll capture HTTP request errors in Sentry. You'll do that by customizing Medusa's default error handler that is used to handle errors in API routes. -Refer to the [Throwing and Handling Errors](undefined/docs/learn/fundamentals/api-routes/errors) guide to learn more about Medusa's default error handling behavior. +Refer to the [Throwing and Handling Errors](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/errors/index.html.md) guide to learn more about Medusa's default error handling behavior. To customize the error handler, create the file `src/api/middlewares.ts` with the following content: @@ -91814,13 +92996,13 @@ You can also expand on your Sentry integration by enabling more features, such a - [Profiling](https://docs.sentry.io/platforms/javascript/guides/nextjs/profiling/node/) to analyze your application's performance and identify bottlenecks. - [User feedback](https://docs.sentry.io/product/user-feedback/) to collect feedback in your frontend from users about their experience with your application. -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). ### Troubleshooting -If you encounter issues during your development, check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting). +If you encounter issues during your development, check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/index.html.md). ### Getting Help @@ -91835,9 +93017,9 @@ If you encounter issues not covered in the troubleshooting guides: In this guide, you'll learn how to integrate Medusa with ShipStation. -Refer your technical team to this guide to integrate ShipStation with your Medusa application. You can then enable it using the Medusa Admin as explained in [this user guide](undefined/user-guide/settings/locations-and-shipping/locations#manage-fulfillment-providers). +Refer your technical team to this guide to integrate ShipStation with your Medusa application. You can then enable it using the Medusa Admin as explained in [this user guide](https://docs.medusajs.com/user-guide/settings/locations-and-shipping/locations#manage-fulfillment-providers/index.html.md). -When you install a Medusa application, you get a fully-fledged commerce platform with support for customizations. Medusa's [Fulfillment Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/fulfillment) provides fulfillment-related resources and functionalities in your store, but it delegates the processing and shipment of order fulfillments to providers that you can integrate. +When you install a Medusa application, you get a fully-fledged commerce platform with support for customizations. Medusa's [Fulfillment Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/fulfillment/index.html.md) provides fulfillment-related resources and functionalities in your store, but it delegates the processing and shipment of order fulfillments to providers that you can integrate. [ShipStation](https://shipstation.com/) is a shipping toolbox that connects all your shipping providers within one platform. By integrating it with Medusa, you can allow customers to choose from different providers like DHL and FedEx and view price rates retrieved from ShipStation. Admin users will also process the order fulfillment using the ShipStation integration. @@ -91871,13 +93053,13 @@ You'll first be asked for the project's name. Then, when you're asked whether yo Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name, and the Next.js Starter Storefront in a directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more about Medusa's architecture in [this documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more about Medusa's architecture in [this documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credential and submit the form. Afterwards, you can login with the new user and explore the dashboard. The Next.js Starter Storefront is also running at `http://localhost:8000`. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** @@ -91939,7 +93121,7 @@ To integrate third-party services into Medusa, you create a custom module. A mod Medusa's Fulfillment Module delegates processing fulfillments and shipments to other modules, called module providers. In this step, you'll create a ShipStation Module Provider that implements all functionalities required for fulfillment. In later steps, you'll add into Medusa shipping options for ShipStation, and allow customers to choose it during checkout. -Learn more about modules in [this documentation](undefined/docs/learn/fundamentals/modules). +Learn more about modules in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). ### Create Module Directory @@ -92072,13 +93254,13 @@ You'll use the `client` property when implementing the service's methods. In this section, you'll go back to the `ShipStationProviderService` method to implement the abstract methods of `AbstractFulfillmentProviderService`. -Refer to [this guide](undefined/references/fulfillment/provider) for a full reference of all methods, their parameters and return types. +Refer to [this guide](https://docs.medusajs.com/references/fulfillment/provider/index.html.md) for a full reference of all methods, their parameters and return types. #### getFulfillmentOptions The `getFulfillmentOptions` method returns the options that this fulfillment provider supports. When admin users add shipping options later in the Medusa Admin, they'll select one of these options. -Learn more about shipping options in [this guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/fulfillment/shipping-option). +Learn more about shipping options in [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/fulfillment/shipping-option/index.html.md). ShipStation requires that a shipment must be associated with a carrier and one of its services. So, in this method, you'll retrieve the list of carriers from ShipStation and return them as fulfillment options. Shipping options created from these fulfillment options will always have access to the option's carrier and service. @@ -92168,7 +93350,7 @@ You return an array of fulfillment-option objects, where each object represents - a `name` property, which you set to the service's `name`. The admin user will see this name when they create a shipping option for the ShipStation provider. - You can pass other data, such as `carrier_id` and `carrier_service_code`, and Medusa will store the fulfillment option in the `data` property of shipping options created later. -Learn more about the shipping option's `data` property in [this guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/fulfillment/shipping-option). +Learn more about the shipping option's `data` property in [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/fulfillment/shipping-option/index.html.md). You'll see this method in action later when you create a shipping option. @@ -92618,7 +93800,7 @@ class ShipStationProviderService extends AbstractFulfillmentProviderService { The `validateFulfillmentData` method accepts the following parameters: 1. The `data` property of the chosen shipping option during checkout. It will hold the carrier ID and its service code. -2. The `data` property of the shipping method to be created. This can hold custom data sent in the [Add Shipping Method API route](undefined/api/store#carts_postcartsidshippingmethods). +2. The `data` property of the shipping method to be created. This can hold custom data sent in the [Add Shipping Method API route](https://docs.medusajs.com/api/store#carts_postcartsidshippingmethods). 3. An object of the checkout's context, including the cart's items, the location associated with the shipping option, and more. In the method, you try to retrieve the shipment ID from the shipping method's `data` parameter if it was already created. If not, you create the shipment in ShipStation using the `createShipment` method. @@ -92852,7 +94034,7 @@ This method accepts the fulfillment's `data` property as a parameter. You get th Then, you use the client's `voidLabel` method to void the label, and `cancelShipment` to cancel the shipment. -Refer to [this guide](undefined/references/fulfillment/provider) for a full reference of all methods, their parameters and return types. +Refer to [this guide](https://docs.medusajs.com/references/fulfillment/provider/index.html.md) for a full reference of all methods, their parameters and return types. ### Export Module Definition @@ -93065,9 +94247,9 @@ You can also cancel the fulfillment by clicking on the three-dots icon, then cho You've now integrated Medusa with ShipStation. You can fulfill orders with many carriers and providers, all from a single integration and platform. -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). # Integrate Slack (Notification) with Medusa @@ -93076,7 +94258,7 @@ In this tutorial, you'll learn how to integrate Slack with Medusa to receive not When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. Medusa's architecture facilitates integrating third-party services to customize Medusa's infrastructure for your business needs. -Medusa's [Notification Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification) allows you to customize Medusa's infrastructure to send notifications using the third-party provider that fits your business needs, such as [Slack](https://slack.com/). +Medusa's [Notification Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/index.html.md) allows you to customize Medusa's infrastructure to send notifications using the third-party provider that fits your business needs, such as [Slack](https://slack.com/). In this tutorial, you'll integrate Slack with Medusa to receive notifications about created orders. @@ -93110,27 +94292,27 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -First, you'll be asked for the project's name. Then, when prompted about installing the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose "Yes." +First, you'll be asked for the project's name. Then, when prompted about installing the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose "Yes." Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name and the Next.js Starter Storefront in a separate directory named `{project-name}-storefront`. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterwards, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** ## Step 2: Create Slack Module Provider -To integrate third-party services into Medusa, you create a custom [module](undefined/docs/learn/fundamentals/modules). A module is a reusable package with functionalities related to a single feature or domain. +To integrate third-party services into Medusa, you create a custom [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). A module is a reusable package with functionalities related to a single feature or domain. -Medusa's [Notification Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification) provides an interface to send notifications in your Medusa application. It delegates the actual sending of notifications to the underlying provider, such as Slack. +Medusa's [Notification Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/index.html.md) provides an interface to send notifications in your Medusa application. It delegates the actual sending of notifications to the underlying provider, such as Slack. In this step, you'll integrate Slack as a Notification Module Provider. Later, you'll use it to send a notification when an order is created. -Refer to the [Modules](undefined/docs/learn/fundamentals/modules) documentation to learn more about modules in Medusa. +Refer to the [Modules](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) documentation to learn more about modules in Medusa. ### a. Install Axios @@ -93177,11 +94359,11 @@ class SlackNotificationProviderService extends AbstractNotificationProviderServi A Notification Module Provider's service must extend the `AbstractNotificationProviderService` class. You'll implement its methods in a bit. -The service must also have an `identifier` static property, which is a unique identifier for the module. This identifier is used when registering the module in the [Medusa container](undefined/docs/learn/fundamentals/medusa-container). +The service must also have an `identifier` static property, which is a unique identifier for the module. This identifier is used when registering the module in the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). The service's constructor receives two parameters: -- `container`: The [module's container](undefined/docs/learn/fundamentals/modules/container) that contains Framework resources available to the module. You don't need to access any resources for this provider. +- `container`: The [module's container](https://docs.medusajs.com/docs/learn/fundamentals/modules/container/index.html.md) that contains Framework resources available to the module. You don't need to access any resources for this provider. - `options`: Options that are passed to the module provider when it's registered in Medusa's configurations. You define the following options: - `webhook_url`: The Slack webhook URL to send notifications to. - `admin_url`: The URL of the Medusa Admin dashboard, which you'll use to add links in the notifications. @@ -93192,7 +94374,7 @@ In the constructor, you set the `options` property to the passed options. In the next sections, you'll implement the methods of the `AbstractNotificationProviderService` class. -Refer to the [Create Notification Module Provider](undefined/references/notification-provider-module) guide for detailed information about the methods. +Refer to the [Create Notification Module Provider](https://docs.medusajs.com/references/notification-provider-module/index.html.md) guide for detailed information about the methods. ### d. Implement validateOptions Method @@ -93398,7 +94580,7 @@ class SlackNotificationProviderService extends AbstractNotificationProviderServi The `send` method receives a `ProviderSendNotificationDTO` object, which contains the notification data and the template to use for sending the notification. -The method receives other parameters, which you can find in the [Create Notification Module Provider](undefined/references/notification-provider-module#send) guide. +The method receives other parameters, which you can find in the [Create Notification Module Provider](https://docs.medusajs.com/references/notification-provider-module#send/index.html.md) guide. In the method, you check the `template` property of the notification object. If it's `order-created`, you call the `sendOrderNotification` method to send the notification. Otherwise, you throw an error indicating that the template is not supported. @@ -93520,15 +94702,15 @@ Now that you've integrated Slack with Medusa, you can send notifications to Slac To send a notification to Slack when an order is created, you will: -- Implement the order details retrieval and notification sending with Slack in a [workflow](undefined/docs/learn/fundamentals/workflows). A workflow is a series of actions, called steps, that complete a task with rollback and retry mechanisms. -- Listen to the `order.placed` event in a [subscriber](undefined/docs/learn/fundamentals/events-and-subscribers). A subscriber is an asynchronous function that listens to events to perform actions, such as execute a workflow, when the event is emitted. +- Implement the order details retrieval and notification sending with Slack in a [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). A workflow is a series of actions, called steps, that complete a task with rollback and retry mechanisms. +- Listen to the `order.placed` event in a [subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md). A subscriber is an asynchronous function that listens to events to perform actions, such as execute a workflow, when the event is emitted. ### a. Create the Workflow The workflow to send notifications to Slack will have the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the order details. -- [sendNotificationsStep](undefined/references/medusa-workflows/steps/sendNotificationsStep): Send a notification with a configured provider. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the order details. +- [sendNotificationsStep](https://docs.medusajs.com/references/medusa-workflows/steps/sendNotificationsStep/index.html.md): Send a notification with a configured provider. Medusa provides both steps in its `@medusajs/medusa/core-flows` package. @@ -93586,7 +94768,7 @@ It accepts as a second parameter a constructor function, which is the workflow's In the workflow's constructor function, you: -- Retrieve the order's details using the `useQueryGraphStep`. This step uses Medusa's [Query](undefined/docs/learn/fundamentals/module-links/query) tool to retrieve data across modules. You pass it the order ID to retrieve. +- Retrieve the order's details using the `useQueryGraphStep`. This step uses Medusa's [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) tool to retrieve data across modules. You pass it the order ID to retrieve. - Send a notification using the `sendNotificationsStep`. You pass the step an array of notifications to send, and each notification is an object with the following properties: - `to`: The channel to send the notification to. Since you configure this in the Slack app, you just set it to `slack-channel`. - `channel`: The channel to use for sending the notification. By setting it to `slack`, the Notification Module will use the Slack Notification Module Provider to send the notification. @@ -93595,7 +94777,7 @@ In the workflow's constructor function, you: You now have a workflow that retrieves the order details and sends a notification to Slack when an order is placed. -Refer to the [Workflows](undefined/docs/learn/fundamentals/workflows) documentation to learn more about workflows and steps. +Refer to the [Workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) documentation to learn more about workflows and steps. ### b. Create the Subscriber @@ -93632,15 +94814,15 @@ A subscriber file must export: The subscriber function receives an object as a parameter that has the following properties: - `event`: An object that holds the event's data payload. The payload of the `order.placed` event is the ID of the order placed. -- `container`: The [Medusa container](undefined/docs/learn/fundamentals/medusa-container) to access the Framework and commerce tools. +- `container`: The [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md) to access the Framework and commerce tools. In the subscriber function, you execute the `orderPlacedNotificationWorkflow` by invoking it, passing the Medusa container as a parameter. Then, you chain a `run` method, passing it the order ID from the event's data payload as input. -Refer to the [Events and Subscribers](undefined/docs/learn/fundamentals/events-and-subscribers) documentation to learn more about creating subscribers. +Refer to the [Events and Subscribers](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md) documentation to learn more about creating subscribers. ### Test it Out -You'll now test out the integration by placing an order using the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter). +You'll now test out the integration by placing an order using the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md). The Next.js Starter Storefront was installed in a separate directory from Medusa. The directory's name is `{your-project}-storefront`. @@ -93674,17 +94856,17 @@ You can also click on the order's ID in the notification to open the order's det ## Next Steps -You've now integrated Slack with Medusa to receive notifications about created orders. You can expand on this integration to send other types of notifications, such as order updates. Refer to the [Events Reference](undefined/references/events) for a list of events you can listen to in your subscribers. +You've now integrated Slack with Medusa to receive notifications about created orders. You can expand on this integration to send other types of notifications, such as order updates. Refer to the [Events Reference](https://docs.medusajs.com/references/events/index.html.md) for a list of events you can listen to in your subscribers. You can also customize the notifications to include more information or change the format of the messages. Refer to [Slack's documentation](https://api.slack.com/reference/surfaces/formatting) for more information on how to format messages in Slack. -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). ### Troubleshooting -If you encounter issues during your development, check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting). +If you encounter issues during your development, check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/index.html.md). ### Getting Help @@ -93699,7 +94881,7 @@ If you encounter issues not covered in the troubleshooting guides: You can integrate any third-party service to Medusa, including storage services, notification systems, Content-Management Systems (CMS), etc… By integrating third-party services, you build flows and synchronize data around these integrations, making Medusa not only your commerce application, but a middleware layer between your data sources and operations. -Medusa provides integrations out-of-the-box that are listed here, but you can also create your own integrations, such as integrating ERP systems, as explained in [this guide](undefined/docs/learn/customization/integrate-systems). +Medusa provides integrations out-of-the-box that are listed here, but you can also create your own integrations, such as integrating ERP systems, as explained in [this guide](https://docs.medusajs.com/docs/learn/customization/integrate-systems/index.html.md). This section holds guides to help technical teams add integrations to a Medusa application. If you're not a technical user, refer your technical team to this documentation instead. @@ -93707,10 +94889,10 @@ This section holds guides to help technical teams add integrations to a Medusa a An Analytics Module Provider tracks events and user behavior in your Medusa application using a third-party service. -- [PostHog](undefined/infrastructure-modules/analytics/posthog) -- [Segment](undefined/integrations/guides/segment) +- [PostHog](https://docs.medusajs.com/infrastructure-modules/analytics/posthog/index.html.md) +- [Segment](https://docs.medusajs.com/integrations/guides/segment/index.html.md) -Learn how to integrate a custom third-party analytics provider in the [Create Analytics Module Provider](undefined/references/analytics/provider) documentation. +Learn how to integrate a custom third-party analytics provider in the [Create Analytics Module Provider](https://docs.medusajs.com/references/analytics/provider/index.html.md) documentation. *** @@ -93718,10 +94900,10 @@ Learn how to integrate a custom third-party analytics provider in the [Create An An Auth Module Provider authenticates users with their account on a third-party service. -- [Google](undefined/commerce-modules/auth/auth-providers/google) -- [GitHub](undefined/commerce-modules/auth/auth-providers/github) +- [Google](https://docs.medusajs.com/commerce-modules/auth/auth-providers/google/index.html.md) +- [GitHub](https://docs.medusajs.com/commerce-modules/auth/auth-providers/github/index.html.md) -Learn how to integrate a custom third-party authentication provider in the [Create Auth Module Provider](undefined/references/auth/provider) documentation. +Learn how to integrate a custom third-party authentication provider in the [Create Auth Module Provider](https://docs.medusajs.com/references/auth/provider/index.html.md) documentation. *** @@ -93729,9 +94911,9 @@ Learn how to integrate a custom third-party authentication provider in the [Crea Integrate a third-party Content-Management System (CMS) to utilize rich content-related features. -- [Contentful (Localization)](undefined/integrations/guides/contentful) -- [Payload CMS](undefined/integrations/guides/payload) -- [Sanity](undefined/integrations/guides/sanity) +- [Contentful (Localization)](https://docs.medusajs.com/integrations/guides/contentful/index.html.md) +- [Payload CMS](https://docs.medusajs.com/integrations/guides/payload/index.html.md) +- [Sanity](https://docs.medusajs.com/integrations/guides/sanity/index.html.md) *** @@ -93739,9 +94921,9 @@ Integrate a third-party Content-Management System (CMS) to utilize rich content- Integrate your business's Enterprise Resource Planning (ERP) system with Medusa to sync products and orders, restrict purchase with custom rules, and more. -To learn about the general approach of integrating an ERP with Medusa and the different use cases you can implement, refer to the [ERP Recipe](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/erp). +To learn about the general approach of integrating an ERP with Medusa and the different use cases you can implement, refer to the [ERP Recipe](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/erp/index.html.md). -- [Odoo](undefined/recipes/erp/odoo) +- [Odoo](https://docs.medusajs.com/recipes/erp/odoo/index.html.md) *** @@ -93749,9 +94931,9 @@ To learn about the general approach of integrating an ERP with Medusa and the di A File Module Provider uploads and manages assets, such as product images, on a third-party service. -- [AWS S3 (and Compatible APIs)](undefined/infrastructure-modules/file/s3) +- [AWS S3 (and Compatible APIs)](https://docs.medusajs.com/infrastructure-modules/file/s3/index.html.md) -Learn how to integrate a custom third-party file or storage provider in the [Create File Module Provider](undefined/references/file-provider-module) documentation. +Learn how to integrate a custom third-party file or storage provider in the [Create File Module Provider](https://docs.medusajs.com/references/file-provider-module/index.html.md) documentation. *** @@ -93759,9 +94941,9 @@ Learn how to integrate a custom third-party file or storage provider in the [Cre A Fulfillment Module Provider provides fulfillment options during checkout, calculates shipping rates, and processes an order's fulfillments. -- [ShipStation](undefined/integrations/guides/shipstation) +- [ShipStation](https://docs.medusajs.com/integrations/guides/shipstation/index.html.md) -Learn how to integrate a third-party fulfillment provider in the [Create Fulfillment Module Provider](undefined/references/fulfillment/provider) documentation. +Learn how to integrate a third-party fulfillment provider in the [Create Fulfillment Module Provider](https://docs.medusajs.com/references/fulfillment/provider/index.html.md) documentation. *** @@ -93769,7 +94951,7 @@ Learn how to integrate a third-party fulfillment provider in the [Create Fulfill Integrate a third-party service to monitor performance, errors, and other metrics in your Medusa application. -- [Sentry](undefined/integrations/guides/sentry) +- [Sentry](https://docs.medusajs.com/integrations/guides/sentry/index.html.md) *** @@ -93777,7 +94959,7 @@ Integrate a third-party service to monitor performance, errors, and other metric Migrate data from another ecommerce platform to Medusa. -- [Magento](undefined/integrations/guides/magento) +- [Magento](https://docs.medusajs.com/integrations/guides/magento/index.html.md) *** @@ -93785,13 +94967,13 @@ Migrate data from another ecommerce platform to Medusa. A Notification Module Provider sends messages to users and customers in your Medusa application using a third-party service. -- [SendGrid](undefined/infrastructure-modules/notification/sendgrid) -- [Mailchimp](undefined/integrations/guides/mailchimp) -- [Resend](undefined/integrations/guides/resend) -- [Slack](undefined/integrations/guides/slack) -- [Twilio SMS](undefined/how-to-tutorials/tutorials/phone-auth#step-3-integrate-twilio-sms) +- [SendGrid](https://docs.medusajs.com/infrastructure-modules/notification/sendgrid/index.html.md) +- [Mailchimp](https://docs.medusajs.com/integrations/guides/mailchimp/index.html.md) +- [Resend](https://docs.medusajs.com/integrations/guides/resend/index.html.md) +- [Slack](https://docs.medusajs.com/integrations/guides/slack/index.html.md) +- [Twilio SMS](https://docs.medusajs.com/how-to-tutorials/tutorials/phone-auth#step-3-integrate-twilio-sms/index.html.md) -Learn how to integrate a third-party notification provider in the [Create Notification Module Provider](undefined/references/notification-provider-module) documentation. +Learn how to integrate a third-party notification provider in the [Create Notification Module Provider](https://docs.medusajs.com/references/notification-provider-module/index.html.md) documentation. *** @@ -93799,9 +94981,9 @@ Learn how to integrate a third-party notification provider in the [Create Notifi A Payment Module Provider processes payments made in your Medusa store using a third-party service. -- [Stripe](undefined/commerce-modules/payment/payment-provider/stripe) +- [Stripe](https://docs.medusajs.com/commerce-modules/payment/payment-provider/stripe/index.html.md) -Learn how to integrate a third-party payment provider in the [Create Payment Module Provider](undefined/references/payment/provider) documentation. +Learn how to integrate a third-party payment provider in the [Create Payment Module Provider](https://docs.medusajs.com/references/payment/provider/index.html.md) documentation. *** @@ -93809,14 +94991,15 @@ Learn how to integrate a third-party payment provider in the [Create Payment Mod Integrate a search engine to index and search products or other types of data in your Medusa application. -- [Algolia](undefined/integrations/guides/algolia) +- [Algolia](https://docs.medusajs.com/integrations/guides/algolia/index.html.md) +- [Meilisearch](https://docs.medusajs.com/integrations/guides/meilisearch/index.html.md) # How to Build a Wishlist Plugin -In this guide, you'll learn how to build a wishlist [plugin](undefined/docs/learn/fundamentals/plugins) in Medusa. +In this guide, you'll learn how to build a wishlist [plugin](https://docs.medusajs.com/docs/learn/fundamentals/plugins/index.html.md) in Medusa. -When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules) which are available out-of-the-box. +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md) which are available out-of-the-box. Customers browsing your store may be interested in a product but not ready to buy it yet. They may want to save the product for later or share it with friends and family. A wishlist feature allows customers to save products they like and access them later. @@ -93851,23 +95034,23 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll be asked for the project's name. You can also optionally choose to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter). +You'll be asked for the project's name. You can also optionally choose to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md). Afterward, the installation process will start, which will install the Medusa application in a directory with your project's name. If you chose to install the Next.js starter, it'll be installed in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more about Medusa's architecture in [this documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more about Medusa's architecture in [this documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterward, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** ## Step 2: Install a Medusa Plugin Project -A plugin is a package of reusable Medusa customizations that you can install in any Medusa application. You can add in the plugin [API Routes](undefined/docs/learn/fundamentals/api-routes), [Workflows](undefined/docs/learn/fundamentals/workflows), and other customizations, as you'll see in this guide. Afterward, you can test it out locally in a Medusa application, then publish it to npm to install and use it in any Medusa application. +A plugin is a package of reusable Medusa customizations that you can install in any Medusa application. You can add in the plugin [API Routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md), [Workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md), and other customizations, as you'll see in this guide. Afterward, you can test it out locally in a Medusa application, then publish it to npm to install and use it in any Medusa application. -Learn more about plugins in [this documentation](undefined/docs/learn/fundamentals/plugins). +Learn more about plugins in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/plugins/index.html.md). A Medusa plugin is set up in a different project, giving you the flexibility in building and publishing it, while providing you with the tools to test it out locally in a Medusa application. @@ -93939,7 +95122,7 @@ While you can create modules outside of a plugin and install them in the Medusa In this step, you'll create a Wishlist Module within the wishlist plugin. This module adds custom data models for wishlists and their items, which you'll use in later steps to store a customer's wishlist. -Learn more about modules in [this documentation](undefined/docs/learn/fundamentals/modules). +Learn more about modules in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). ### Create Module Directory @@ -93951,7 +95134,7 @@ A module is created under the `src/modules` directory of your plugin. So, create A data model represents a table in the database. You create data models using Medusa's Data Model Language (DML). It simplifies defining a table's columns, relations, and indexes with straightforward methods and configurations. -Learn more about data models in [this documentation](undefined/docs/learn/fundamentals/modules#1-create-data-model). +Learn more about data models in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#1-create-data-model/index.html.md). In the Wishlist Module, you'll create two data models: `Wishlist` and `WishlistItem`. The `Wishlist` model represents a customer's wishlist, while the `WishlistItem` model represents a product in the wishlist. @@ -93986,11 +95169,11 @@ The `Wishlist` model has the following properties: - `sales_channel_id`: The ID of the sales channel where the wishlist is created. In Medusa, product availability can differ between sales channels. This ensures only products available in the customer's sales channel are added to the wishlist. - `items`: A relation to the `WishlistItem` model, representing the products in the wishlist. You'll add this data model next. -Learn more about data model [properties](undefined/docs/learn/fundamentals/data-models/properties) and [relations](undefined/docs/learn/fundamentals/data-models/relationships). +Learn more about data model [properties](https://docs.medusajs.com/docs/learn/fundamentals/data-models/properties/index.html.md) and [relations](https://docs.medusajs.com/docs/learn/fundamentals/data-models/relationships/index.html.md). You also define a unique index on the `customer_id` and `sales_channel_id` columns to ensure a customer can only have one wishlist per sales channel. -Learn more about data model indexes in [this documentation](undefined/docs/learn/fundamentals/data-models/index). +Learn more about data model indexes in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/index/index.html.md). Next, create the `WishlistItem` model in the file `src/modules/wishlist/models/wishlist-item.ts`: @@ -94027,7 +95210,7 @@ You also define a unique index on the `product_variant_id` and `wishlist_id` col You define data-management methods of your data models in a service. A service is a TypeScript or JavaScript class that the module exports. In the service's methods, you can perform database operations. -Learn more about services in [this documentation](undefined/docs/learn/fundamentals/modules#2-create-service). +Learn more about services in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#2-create-service/index.html.md). In this section, you'll create the Wishlist Module's service that's used to manage wishlists and wishlist items. Create the file `src/modules/wishlist/service.ts` with the following content: @@ -94048,7 +95231,7 @@ The `WishlistModuleService` extends `MedusaService` from the Modules SDK which g So, the `WishlistModuleService` class now has methods like `createWishlists` and `retrieveWishlist`. -Find all methods generated by the `MedusaService` in [this reference](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference). +Find all methods generated by the `MedusaService` in [this reference](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/index.html.md). You'll use this service in a later method to store and manage wishlists and wishlist items in other customizations. @@ -94082,7 +95265,7 @@ You'll later use the module's service to manage wishlists and wishlist items in Since data models represent tables in the database, you define how they're created in the database with migrations. A migration is a TypeScript or JavaScript file that defines database changes made by a module. -Learn more about migrations in [this documentation](undefined/docs/learn/fundamentals/modules#5-generate-migrations). +Learn more about migrations in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#5-generate-migrations/index.html.md). Medusa's CLI tool generates the migrations for you. To generate a migration for the Wishlist Module, run the following command in the plugin project: @@ -94108,11 +95291,11 @@ The tables of the Wishlist Module's data models are now created in the database. The Wishlist Module's data models store IDs of records in data models implemented in Medusa's core Commerce Modules, such as the ID of a customer or a product variant. -However, modules are [isolated](undefined/docs/learn/fundamentals/modules/isolation) to ensure they're re-usable and don't have side effects when integrated into the Medusa application. So, to build associations between modules, you define [module links](undefined/docs/learn/fundamentals/module-links). A Module link associates two modules' data models while maintaining module isolation. +However, modules are [isolated](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md) to ensure they're re-usable and don't have side effects when integrated into the Medusa application. So, to build associations between modules, you define [module links](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md). A Module link associates two modules' data models while maintaining module isolation. -In this section, you'll link the `Wishlist` data model to the [Customer Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/customer)'s `Customer` data model, and to the [Sales Channel](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/sales-channel) Module's `SalesChannel` data model. You'll also link the `WishlistItem` data model to the [Product Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product)'s `ProductVariant` data model. +In this section, you'll link the `Wishlist` data model to the [Customer Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/customer/index.html.md)'s `Customer` data model, and to the [Sales Channel](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/sales-channel/index.html.md) Module's `SalesChannel` data model. You'll also link the `WishlistItem` data model to the [Product Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/index.html.md)'s `ProductVariant` data model. -Learn more about module links in [this documentation](undefined/docs/learn/fundamentals/module-links). +Learn more about module links in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md). To create the link between the `Wishlist` data model and the `Customer` data model, create the file `src/modules/wishlist/links/wishlist-customer.ts` with the following content: @@ -94199,7 +95382,7 @@ A workflow is a series of queries and actions, called steps, that complete a tas In this section, you'll create a workflow that creates a wishlist for a customer. Later, you'll execute this workflow from an API route. -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows) +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) The workflow has the following steps: @@ -94268,9 +95451,9 @@ You create a step using `createStep` from the Workflows SDK. It accepts two para 1. The step's name, which is `validate-customer-create-wishlist`. 2. An async function that executes the step's logic. The function receives two parameters: - The input data for the step, which in this case is an object having a `customer_id` property. - - An object holding the workflow's context, including the [Medusa Container](undefined/docs/learn/fundamentals/medusa-container) that allows you to resolve Framework and commerce tools. + - An object holding the workflow's context, including the [Medusa Container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md) that allows you to resolve Framework and commerce tools. -In the step function, you use [Query](undefined/docs/learn/fundamentals/module-links/query) to retrieve the wishlist based on the specified customer ID. If a wishlist exists, you throw an error, stopping the workflow's execution. +In the step function, you use [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) to retrieve the wishlist based on the specified customer ID. If a wishlist exists, you throw an error, stopping the workflow's execution. You also try to retrieve the customer, and if they don't exist, you throw an error. @@ -94323,7 +95506,7 @@ The compensation function is an optional third parameter of `createStep`. It def The compensation function accepts as a first parameter the data passed as a second parameter to the `StepResponse` returned by the step function, which in this case is the wishlist's ID. In the compensation function, you resolve the Wishlist Module's service from the container and use its generated `deleteWishlists` method to delete the wishlist. -Learn more about the generated [create](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference/methods/create) and [delete](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference/methods/delete) methods. +Learn more about the generated [create](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/methods/create/index.html.md) and [delete](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/methods/delete/index.html.md) methods. ### Add createWishlistWorkflow @@ -94364,7 +95547,7 @@ It accepts as a second parameter a constructor function, which is the workflow's - Execute the `validateCustomerCreateWishlistStep` step to validate that the customer doesn't have an existing wishlist. - Execute the `createWishlistStep` step to create the wishlist. -A workflow's constructor function has some constraints in implementation, which is why you need to use `transform` for variable manipulation. Learn more about these constraints in [this documentation](undefined/docs/learn/fundamentals/workflows/constructor-constraints). +A workflow's constructor function has some constraints in implementation, which is why you need to use `transform` for variable manipulation. Learn more about these constraints in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/constructor-constraints/index.html.md). Workflows must return an instance of `WorkflowResponse`, passing as a parameter the data to return to the workflow's executor. The workflow returns an object having a `wishlist` property, which is the created wishlist. @@ -94378,7 +95561,7 @@ Now that you implemented the flow to create a wishlist for a customer, you'll cr An API Route is an endpoint that exposes commerce features to external applications and clients, such as storefronts. You'll create a `POST` API route at the path `/store/customers/me/wishlists` that executes the workflow from the previous step. -Learn more about API routes in [this documentation](undefined/docs/learn/fundamentals/api-routes). +Learn more about API routes in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). An API route is created in a `route.ts` file under a sub-directory of the `src/api` directory. The path of the API route is the file's path relative to `src/api`. @@ -94538,7 +95721,7 @@ export async function GET( } ``` -In this route handler function, you use [Query](undefined/docs/learn/fundamentals/module-links/query) to retrieve the wishlist of the authenticated customer. For each wishlist, you retrieve its items, and the product variants of those items. +In this route handler function, you use [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) to retrieve the wishlist of the authenticated customer. For each wishlist, you retrieve its items, and the product variants of those items. If the wishlist doesn't exist, you throw an error. Otherwise, you return the wishlist in the response. @@ -94573,12 +95756,12 @@ Next, you'll add the functionality to add an item to a wishlist. You'll first de The workflow to add an item to a wishlist has the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the wishlist of a customer. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the wishlist of a customer. - [validateWishlistExistsStep](#validateWishlistExistsStep): Validate that the customer's wishlist exists. - [validateWishlistSalesChannelStep](#validateWishlistSalesChannelStep): Validate that the wishlist belongs to the specified sales channel. - [validateVariantWishlistStep](#validateVariantWishlistStep): Validate that the specified variant is not already in the wishlist. - [createWishlistItemStep](#createWishlistItemStep): Create the wishlist item. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the wishlist again with the new item added. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the wishlist again with the new item added. The `useQueryGraphStep` is from Medusa's workflows package. So, you'll only implement the other steps. @@ -94647,7 +95830,7 @@ export const validateWishlistSalesChannelStep = createStep( This step receives the wishlist object and the sales channel ID as input. In the step function, if the wishlist's sales channel ID doesn't match the sales channel ID in the input, you throw an error. -To represent a data model in a type, use the [InferTypeOf](undefined/docs/learn/fundamentals/data-models/infer-type) utility. +To represent a data model in a type, use the [InferTypeOf](https://docs.medusajs.com/docs/learn/fundamentals/data-models/infer-type/index.html.md) utility. #### validateVariantWishlistStep @@ -94831,7 +96014,7 @@ export const createWishlistItemWorkflow = createWorkflow( You create a `createWishlistItemWorkflow`. In the workflow, you: -- Use the [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep) to retrieve the wishlist of a customer. Notice that you pass the link definition between a wishlist and a customer as an entry point to Query. This allows you to filter the wishlist by the customer ID. +- Use the [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md) to retrieve the wishlist of a customer. Notice that you pass the link definition between a wishlist and a customer as an entry point to Query. This allows you to filter the wishlist by the customer ID. - Use the `validateWishlistSalesChannelStep` step to validate that the wishlist belongs to the sales channel specified in the input. - Use the `validateVariantWishlistStep` step to validate that the variant specified in the input is not already in the wishlist. - Use the `createWishlistItemStep` step to create the wishlist item. @@ -94921,7 +96104,7 @@ Finally, to use the schema for validation, you need to apply the `validateAndTra The `validateAndTransformBody` middleware is available out-of-the-box in Medusa, allowing you to validate and transform the request body using a Zod schema. -Learn more about middlewares in [this documentation](undefined/docs/learn/fundamentals/api-routes/middlewares). +Learn more about middlewares in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md). To apply the middleware, create the file `src/api/middlewares.ts` with the following content: @@ -95011,11 +96194,11 @@ In this step, you'll add the functionality to remove an item from a wishlist. Yo The workflow to remove an item from a wishlist has the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the wishlist of a customer. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the wishlist of a customer. - [validateWishlistExistsStep](#validateWishlistExistsStep): Validate that the customer's wishlist exists. - [validateItemInWishlistStep](#validateItemInWishlistStep): Validate that the item is in the customer's wishlist. - [deleteWishlistItemStep](#deleteWishlistItemStep): Delete the wishlist item. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the wishlist again with the item removed. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the wishlist again with the item removed. The `useQueryGraphStep` is from Medusa's workflows package, and you implemented the `validateWishlistExistsStep` [previously](#validatewishlistexistsstep) . So, you'll only implement the other steps. @@ -95098,7 +96281,7 @@ This step receives the wishlist item ID as input. In the step function, you reso You pass the deleted wishlist item ID to the compensation function. In the compensation function, you resolve the Wishlist Module's service from the container and use its generated `restoreWishlistItems` method to restore the wishlist item if an error occurs in the workflow. -Learn more about the [softDelete](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference/methods/soft-delete) and [restore](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference/methods/restore) generated methods. +Learn more about the [softDelete](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/methods/soft-delete/index.html.md) and [restore](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/methods/restore/index.html.md) generated methods. #### Remove Item from Wishlist Workflow @@ -95158,7 +96341,7 @@ export const deleteWishlistItemWorkflow = createWorkflow( You create a `deleteWishlistItemWorkflow`. In the workflow, you: -- Use the [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep) to retrieve the wishlist of a customer. Notice that you pass the link definition between a wishlist and a customer as an entry point to Query. This allows you to filter the wishlist by the customer ID. +- Use the [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md) to retrieve the wishlist of a customer. Notice that you pass the link definition between a wishlist and a customer as an entry point to Query. This allows you to filter the wishlist by the customer ID. - Use the `validateItemInWishlistStep` step to validate that the item to remove is in the customer's wishlist. - Use the `deleteWishlistItemStep` step to delete the item from the wishlist. - Use the `useQueryGraphStep` again to retrieve the wishlist with the item removed. @@ -95318,7 +96501,7 @@ return res.json({ }) ``` -You first retrieve the [http Medusa configuration](undefined/docs/learn/configurations/medusa-config#http) which holds configurations related to JWT secrets and expiration times. You then use the `jsonwebtoken` package to sign a token containing the wishlist ID. You return the token in the response. +You first retrieve the [http Medusa configuration](https://docs.medusajs.com/docs/learn/configurations/medusa-config#http/index.html.md) which holds configurations related to JWT secrets and expiration times. You then use the `jsonwebtoken` package to sign a token containing the wishlist ID. You return the token in the response. ### Test API Route @@ -95442,7 +96625,7 @@ In this step, you'll customize the Medusa Admin dashboard to show for each produ The Medusa Admin dashboard's pages are customizable to insert widgets of custom content in pre-defined injection zones. You create these widgets as React components that allow admin users to perform custom actions. -Learn more about widgets in [this documentation](undefined/docs/learn/fundamentals/admin/widgets). +Learn more about widgets in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/admin/widgets/index.html.md). ### Add Method to Retrieve Wishlist Count @@ -95543,7 +96726,7 @@ You'll use this API route in the widget next. You'll now create the widget that will be shown on a product's page in the Medusa Admin. -In the widget, you'll send a request to the API route you created to retrieve the wishlist count for the product. To send the request, you'll use the [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk), which is a JavaScript library that simplifies sending requests to Medusa's API routes. +In the widget, you'll send a request to the API route you created to retrieve the wishlist count for the product. To send the request, you'll use the [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md), which is a JavaScript library that simplifies sending requests to Medusa's API routes. To initialize the JS SDK, create the file `src/admin/lib/sdk.ts` with the following content: @@ -95563,7 +96746,7 @@ export const sdk = new Medusa({ You initialize an instance of the JS SDK, which you'll use in the widget to send requests. -Learn more about the JS SDK and configuring it in [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk). +Learn more about the JS SDK and configuring it in [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md). Then, to create the widget, create the file `src/admin/widgets/product-widget.tsx` with the following content: @@ -95614,11 +96797,11 @@ export default ProductWidget A widget file must export a React component and a `config` object created with `defineWidgetConfig` from the Admin Extension SDK. In the `config` object, you specify the zone to inject the widget into in the `zone` property. This widget is injected into a product's page before any other sections. -Find all widget injection zones in [this reference](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-widget-injection-zones). +Find all widget injection zones in [this reference](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-widget-injection-zones/index.html.md). Since the widget is injected into a product's details page, it receives the product's details as a `data` prop. In the widget, you use [Tanstack Query](https://tanstack.com/query/latest) to benefit from features like data caching and invalidation. You use the `useQuery` hook to send a request to the API route you created to retrieve the wishlist count for the product. -Finally, you display the widget's content using components from [Medusa UI](undefined/ui), allowing you to align the design of your widget with the Medusa Admin's design system. +Finally, you display the widget's content using components from [Medusa UI](https://docs.medusajs.com/ui/index.html.md), allowing you to align the design of your widget with the Medusa Admin's design system. ### Test it Out @@ -95642,381 +96825,381 @@ Then: ## Next Steps -You've now implemented the wishlist functionality in a Medusa plugin. You can publish that plugin as explained in [this documentation](undefined/docs/learn/fundamentals/plugins/create#5-publish-plugin-to-npm) to NPM and install it in any Medusa application. This will allow you to re-use your plugin or share it with the community. +You've now implemented the wishlist functionality in a Medusa plugin. You can publish that plugin as explained in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/plugins/create#5-publish-plugin-to-npm/index.html.md) to NPM and install it in any Medusa application. This will allow you to re-use your plugin or share it with the community. -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). ## JS SDK Admin -- [batchSalesChannels](undefined/references/js_sdk/admin/ApiKey/methods/js_sdk.admin.ApiKey.batchSalesChannels/index.html.md) -- [create](undefined/references/js_sdk/admin/ApiKey/methods/js_sdk.admin.ApiKey.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/ApiKey/methods/js_sdk.admin.ApiKey.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/ApiKey/methods/js_sdk.admin.ApiKey.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/ApiKey/methods/js_sdk.admin.ApiKey.retrieve/index.html.md) -- [revoke](undefined/references/js_sdk/admin/ApiKey/methods/js_sdk.admin.ApiKey.revoke/index.html.md) -- [update](undefined/references/js_sdk/admin/ApiKey/methods/js_sdk.admin.ApiKey.update/index.html.md) -- [batchPromotions](undefined/references/js_sdk/admin/Campaign/methods/js_sdk.admin.Campaign.batchPromotions/index.html.md) -- [create](undefined/references/js_sdk/admin/Campaign/methods/js_sdk.admin.Campaign.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/Campaign/methods/js_sdk.admin.Campaign.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/Campaign/methods/js_sdk.admin.Campaign.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/Campaign/methods/js_sdk.admin.Campaign.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/Campaign/methods/js_sdk.admin.Campaign.update/index.html.md) -- [addInboundItems](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.addInboundItems/index.html.md) -- [addInboundShipping](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.addInboundShipping/index.html.md) -- [addItems](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.addItems/index.html.md) -- [addOutboundItems](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.addOutboundItems/index.html.md) -- [addOutboundShipping](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.addOutboundShipping/index.html.md) -- [cancel](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.cancel/index.html.md) -- [cancelRequest](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.cancelRequest/index.html.md) -- [create](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.create/index.html.md) -- [deleteInboundShipping](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.deleteInboundShipping/index.html.md) -- [deleteOutboundShipping](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.deleteOutboundShipping/index.html.md) -- [list](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.list/index.html.md) -- [removeInboundItem](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.removeInboundItem/index.html.md) -- [removeItem](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.removeItem/index.html.md) -- [removeOutboundItem](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.removeOutboundItem/index.html.md) -- [request](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.request/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.retrieve/index.html.md) -- [updateInboundItem](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.updateInboundItem/index.html.md) -- [updateInboundShipping](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.updateInboundShipping/index.html.md) -- [updateItem](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.updateItem/index.html.md) -- [updateOutboundItem](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.updateOutboundItem/index.html.md) -- [updateOutboundShipping](undefined/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.updateOutboundShipping/index.html.md) -- [clearToken](undefined/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.clearToken/index.html.md) -- [clearToken\_](undefined/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.clearToken_/index.html.md) -- [fetch](undefined/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.fetch/index.html.md) -- [fetchStream](undefined/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.fetchStream/index.html.md) -- [getApiKeyHeader\_](undefined/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.getApiKeyHeader_/index.html.md) -- [getJwtHeader\_](undefined/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.getJwtHeader_/index.html.md) -- [getPublishableKeyHeader\_](undefined/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.getPublishableKeyHeader_/index.html.md) -- [getToken](undefined/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.getToken/index.html.md) -- [getTokenStorageInfo\_](undefined/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.getTokenStorageInfo_/index.html.md) -- [getToken\_](undefined/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.getToken_/index.html.md) -- [initClient](undefined/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.initClient/index.html.md) -- [setToken](undefined/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.setToken/index.html.md) -- [setToken\_](undefined/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.setToken_/index.html.md) -- [throwError\_](undefined/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.throwError_/index.html.md) -- [list](undefined/references/js_sdk/admin/Currency/methods/js_sdk.admin.Currency.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/Currency/methods/js_sdk.admin.Currency.retrieve/index.html.md) -- [getItem](undefined/references/js_sdk/admin/CustomStorage/methods/js_sdk.admin.CustomStorage.getItem/index.html.md) -- [removeItem](undefined/references/js_sdk/admin/CustomStorage/methods/js_sdk.admin.CustomStorage.removeItem/index.html.md) -- [setItem](undefined/references/js_sdk/admin/CustomStorage/methods/js_sdk.admin.CustomStorage.setItem/index.html.md) -- [batchCustomerGroups](undefined/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.batchCustomerGroups/index.html.md) -- [create](undefined/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.create/index.html.md) -- [createAddress](undefined/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.createAddress/index.html.md) -- [delete](undefined/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.delete/index.html.md) -- [deleteAddress](undefined/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.deleteAddress/index.html.md) -- [list](undefined/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.list/index.html.md) -- [listAddresses](undefined/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.listAddresses/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.retrieve/index.html.md) -- [retrieveAddress](undefined/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.retrieveAddress/index.html.md) -- [update](undefined/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.update/index.html.md) -- [updateAddress](undefined/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.updateAddress/index.html.md) -- [batchCustomers](undefined/references/js_sdk/admin/CustomerGroup/methods/js_sdk.admin.CustomerGroup.batchCustomers/index.html.md) -- [create](undefined/references/js_sdk/admin/CustomerGroup/methods/js_sdk.admin.CustomerGroup.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/CustomerGroup/methods/js_sdk.admin.CustomerGroup.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/CustomerGroup/methods/js_sdk.admin.CustomerGroup.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/CustomerGroup/methods/js_sdk.admin.CustomerGroup.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/CustomerGroup/methods/js_sdk.admin.CustomerGroup.update/index.html.md) -- [addItems](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.addItems/index.html.md) -- [addPromotions](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.addPromotions/index.html.md) -- [addShippingMethod](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.addShippingMethod/index.html.md) -- [beginEdit](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.beginEdit/index.html.md) -- [cancelEdit](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.cancelEdit/index.html.md) -- [confirmEdit](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.confirmEdit/index.html.md) -- [convertToOrder](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.convertToOrder/index.html.md) -- [create](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.list/index.html.md) -- [removeActionItem](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.removeActionItem/index.html.md) -- [removeActionShippingMethod](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.removeActionShippingMethod/index.html.md) -- [removePromotions](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.removePromotions/index.html.md) -- [removeShippingMethod](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.removeShippingMethod/index.html.md) -- [requestEdit](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.requestEdit/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.update/index.html.md) -- [updateActionItem](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.updateActionItem/index.html.md) -- [updateActionShippingMethod](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.updateActionShippingMethod/index.html.md) -- [updateItem](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.updateItem/index.html.md) -- [updateShippingMethod](undefined/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.updateShippingMethod/index.html.md) -- [addInboundItems](undefined/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.addInboundItems/index.html.md) -- [addInboundShipping](undefined/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.addInboundShipping/index.html.md) -- [addOutboundItems](undefined/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.addOutboundItems/index.html.md) -- [addOutboundShipping](undefined/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.addOutboundShipping/index.html.md) -- [cancel](undefined/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.cancel/index.html.md) -- [cancelRequest](undefined/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.cancelRequest/index.html.md) -- [create](undefined/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.create/index.html.md) -- [deleteInboundShipping](undefined/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.deleteInboundShipping/index.html.md) -- [deleteOutboundShipping](undefined/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.deleteOutboundShipping/index.html.md) -- [list](undefined/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.list/index.html.md) -- [removeInboundItem](undefined/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.removeInboundItem/index.html.md) -- [removeOutboundItem](undefined/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.removeOutboundItem/index.html.md) -- [request](undefined/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.request/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.retrieve/index.html.md) -- [updateInboundItem](undefined/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.updateInboundItem/index.html.md) -- [updateInboundShipping](undefined/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.updateInboundShipping/index.html.md) -- [updateOutboundItem](undefined/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.updateOutboundItem/index.html.md) -- [updateOutboundShipping](undefined/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.updateOutboundShipping/index.html.md) -- [cancel](undefined/references/js_sdk/admin/Fulfillment/methods/js_sdk.admin.Fulfillment.cancel/index.html.md) -- [create](undefined/references/js_sdk/admin/Fulfillment/methods/js_sdk.admin.Fulfillment.create/index.html.md) -- [createShipment](undefined/references/js_sdk/admin/Fulfillment/methods/js_sdk.admin.Fulfillment.createShipment/index.html.md) -- [list](undefined/references/js_sdk/admin/FulfillmentProvider/methods/js_sdk.admin.FulfillmentProvider.list/index.html.md) -- [listFulfillmentOptions](undefined/references/js_sdk/admin/FulfillmentProvider/methods/js_sdk.admin.FulfillmentProvider.listFulfillmentOptions/index.html.md) -- [createServiceZone](undefined/references/js_sdk/admin/FulfillmentSet/methods/js_sdk.admin.FulfillmentSet.createServiceZone/index.html.md) -- [delete](undefined/references/js_sdk/admin/FulfillmentSet/methods/js_sdk.admin.FulfillmentSet.delete/index.html.md) -- [deleteServiceZone](undefined/references/js_sdk/admin/FulfillmentSet/methods/js_sdk.admin.FulfillmentSet.deleteServiceZone/index.html.md) -- [retrieveServiceZone](undefined/references/js_sdk/admin/FulfillmentSet/methods/js_sdk.admin.FulfillmentSet.retrieveServiceZone/index.html.md) -- [updateServiceZone](undefined/references/js_sdk/admin/FulfillmentSet/methods/js_sdk.admin.FulfillmentSet.updateServiceZone/index.html.md) -- [batchInventoryItemLocationLevels](undefined/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.batchInventoryItemLocationLevels/index.html.md) -- [batchInventoryItemsLocationLevels](undefined/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.batchInventoryItemsLocationLevels/index.html.md) -- [batchUpdateLevels](undefined/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.batchUpdateLevels/index.html.md) -- [create](undefined/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.delete/index.html.md) -- [deleteLevel](undefined/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.deleteLevel/index.html.md) -- [list](undefined/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.list/index.html.md) -- [listLevels](undefined/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.listLevels/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.update/index.html.md) -- [updateLevel](undefined/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.updateLevel/index.html.md) -- [accept](undefined/references/js_sdk/admin/Invite/methods/js_sdk.admin.Invite.accept/index.html.md) -- [create](undefined/references/js_sdk/admin/Invite/methods/js_sdk.admin.Invite.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/Invite/methods/js_sdk.admin.Invite.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/Invite/methods/js_sdk.admin.Invite.list/index.html.md) -- [resend](undefined/references/js_sdk/admin/Invite/methods/js_sdk.admin.Invite.resend/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/Invite/methods/js_sdk.admin.Invite.retrieve/index.html.md) -- [list](undefined/references/js_sdk/admin/Notification/methods/js_sdk.admin.Notification.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/Notification/methods/js_sdk.admin.Notification.retrieve/index.html.md) -- [archive](undefined/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.archive/index.html.md) -- [cancel](undefined/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.cancel/index.html.md) -- [cancelFulfillment](undefined/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.cancelFulfillment/index.html.md) -- [cancelTransfer](undefined/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.cancelTransfer/index.html.md) -- [complete](undefined/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.complete/index.html.md) -- [createCreditLine](undefined/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.createCreditLine/index.html.md) -- [createFulfillment](undefined/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.createFulfillment/index.html.md) -- [createShipment](undefined/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.createShipment/index.html.md) -- [list](undefined/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.list/index.html.md) -- [listChanges](undefined/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.listChanges/index.html.md) -- [listLineItems](undefined/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.listLineItems/index.html.md) -- [listShippingOptions](undefined/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.listShippingOptions/index.html.md) -- [markAsDelivered](undefined/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.markAsDelivered/index.html.md) -- [requestTransfer](undefined/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.requestTransfer/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.retrieve/index.html.md) -- [retrievePreview](undefined/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.retrievePreview/index.html.md) -- [update](undefined/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.update/index.html.md) -- [addItems](undefined/references/js_sdk/admin/OrderEdit/methods/js_sdk.admin.OrderEdit.addItems/index.html.md) -- [cancelRequest](undefined/references/js_sdk/admin/OrderEdit/methods/js_sdk.admin.OrderEdit.cancelRequest/index.html.md) -- [confirm](undefined/references/js_sdk/admin/OrderEdit/methods/js_sdk.admin.OrderEdit.confirm/index.html.md) -- [initiateRequest](undefined/references/js_sdk/admin/OrderEdit/methods/js_sdk.admin.OrderEdit.initiateRequest/index.html.md) -- [removeAddedItem](undefined/references/js_sdk/admin/OrderEdit/methods/js_sdk.admin.OrderEdit.removeAddedItem/index.html.md) -- [request](undefined/references/js_sdk/admin/OrderEdit/methods/js_sdk.admin.OrderEdit.request/index.html.md) -- [updateAddedItem](undefined/references/js_sdk/admin/OrderEdit/methods/js_sdk.admin.OrderEdit.updateAddedItem/index.html.md) -- [updateOriginalItem](undefined/references/js_sdk/admin/OrderEdit/methods/js_sdk.admin.OrderEdit.updateOriginalItem/index.html.md) -- [capture](undefined/references/js_sdk/admin/Payment/methods/js_sdk.admin.Payment.capture/index.html.md) -- [list](undefined/references/js_sdk/admin/Payment/methods/js_sdk.admin.Payment.list/index.html.md) -- [listPaymentProviders](undefined/references/js_sdk/admin/Payment/methods/js_sdk.admin.Payment.listPaymentProviders/index.html.md) -- [refund](undefined/references/js_sdk/admin/Payment/methods/js_sdk.admin.Payment.refund/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/Payment/methods/js_sdk.admin.Payment.retrieve/index.html.md) -- [create](undefined/references/js_sdk/admin/PaymentCollection/methods/js_sdk.admin.PaymentCollection.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/PaymentCollection/methods/js_sdk.admin.PaymentCollection.delete/index.html.md) -- [markAsPaid](undefined/references/js_sdk/admin/PaymentCollection/methods/js_sdk.admin.PaymentCollection.markAsPaid/index.html.md) -- [list](undefined/references/js_sdk/admin/Plugin/methods/js_sdk.admin.Plugin.list/index.html.md) -- [batchPrices](undefined/references/js_sdk/admin/PriceList/methods/js_sdk.admin.PriceList.batchPrices/index.html.md) -- [create](undefined/references/js_sdk/admin/PriceList/methods/js_sdk.admin.PriceList.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/PriceList/methods/js_sdk.admin.PriceList.delete/index.html.md) -- [linkProducts](undefined/references/js_sdk/admin/PriceList/methods/js_sdk.admin.PriceList.linkProducts/index.html.md) -- [list](undefined/references/js_sdk/admin/PriceList/methods/js_sdk.admin.PriceList.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/PriceList/methods/js_sdk.admin.PriceList.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/PriceList/methods/js_sdk.admin.PriceList.update/index.html.md) -- [create](undefined/references/js_sdk/admin/PricePreference/methods/js_sdk.admin.PricePreference.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/PricePreference/methods/js_sdk.admin.PricePreference.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/PricePreference/methods/js_sdk.admin.PricePreference.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/PricePreference/methods/js_sdk.admin.PricePreference.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/PricePreference/methods/js_sdk.admin.PricePreference.update/index.html.md) -- [batch](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.batch/index.html.md) -- [batchVariantInventoryItems](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.batchVariantInventoryItems/index.html.md) -- [batchVariants](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.batchVariants/index.html.md) -- [confirmImport](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.confirmImport/index.html.md) -- [create](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.create/index.html.md) -- [createImport](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.createImport/index.html.md) -- [createOption](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.createOption/index.html.md) -- [createVariant](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.createVariant/index.html.md) -- [delete](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.delete/index.html.md) -- [deleteOption](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.deleteOption/index.html.md) -- [deleteVariant](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.deleteVariant/index.html.md) -- [export](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.export/index.html.md) -- [import](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.import/index.html.md) -- [list](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.list/index.html.md) -- [listOptions](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.listOptions/index.html.md) -- [listVariants](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.listVariants/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.retrieve/index.html.md) -- [retrieveOption](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.retrieveOption/index.html.md) -- [retrieveVariant](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.retrieveVariant/index.html.md) -- [update](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.update/index.html.md) -- [updateOption](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.updateOption/index.html.md) -- [updateVariant](undefined/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.updateVariant/index.html.md) -- [create](undefined/references/js_sdk/admin/ProductCategory/methods/js_sdk.admin.ProductCategory.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/ProductCategory/methods/js_sdk.admin.ProductCategory.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/ProductCategory/methods/js_sdk.admin.ProductCategory.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/ProductCategory/methods/js_sdk.admin.ProductCategory.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/ProductCategory/methods/js_sdk.admin.ProductCategory.update/index.html.md) -- [updateProducts](undefined/references/js_sdk/admin/ProductCategory/methods/js_sdk.admin.ProductCategory.updateProducts/index.html.md) -- [create](undefined/references/js_sdk/admin/ProductCollection/methods/js_sdk.admin.ProductCollection.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/ProductCollection/methods/js_sdk.admin.ProductCollection.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/ProductCollection/methods/js_sdk.admin.ProductCollection.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/ProductCollection/methods/js_sdk.admin.ProductCollection.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/ProductCollection/methods/js_sdk.admin.ProductCollection.update/index.html.md) -- [updateProducts](undefined/references/js_sdk/admin/ProductCollection/methods/js_sdk.admin.ProductCollection.updateProducts/index.html.md) -- [create](undefined/references/js_sdk/admin/ProductTag/methods/js_sdk.admin.ProductTag.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/ProductTag/methods/js_sdk.admin.ProductTag.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/ProductTag/methods/js_sdk.admin.ProductTag.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/ProductTag/methods/js_sdk.admin.ProductTag.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/ProductTag/methods/js_sdk.admin.ProductTag.update/index.html.md) -- [create](undefined/references/js_sdk/admin/ProductType/methods/js_sdk.admin.ProductType.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/ProductType/methods/js_sdk.admin.ProductType.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/ProductType/methods/js_sdk.admin.ProductType.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/ProductType/methods/js_sdk.admin.ProductType.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/ProductType/methods/js_sdk.admin.ProductType.update/index.html.md) -- [list](undefined/references/js_sdk/admin/ProductVariant/methods/js_sdk.admin.ProductVariant.list/index.html.md) -- [addRules](undefined/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.addRules/index.html.md) -- [create](undefined/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.list/index.html.md) -- [listRuleAttributes](undefined/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.listRuleAttributes/index.html.md) -- [listRuleValues](undefined/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.listRuleValues/index.html.md) -- [listRules](undefined/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.listRules/index.html.md) -- [removeRules](undefined/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.removeRules/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.update/index.html.md) -- [updateRules](undefined/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.updateRules/index.html.md) -- [list](undefined/references/js_sdk/admin/RefundReason/methods/js_sdk.admin.RefundReason.list/index.html.md) -- [create](undefined/references/js_sdk/admin/Region/methods/js_sdk.admin.Region.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/Region/methods/js_sdk.admin.Region.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/Region/methods/js_sdk.admin.Region.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/Region/methods/js_sdk.admin.Region.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/Region/methods/js_sdk.admin.Region.update/index.html.md) -- [create](undefined/references/js_sdk/admin/Reservation/methods/js_sdk.admin.Reservation.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/Reservation/methods/js_sdk.admin.Reservation.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/Reservation/methods/js_sdk.admin.Reservation.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/Reservation/methods/js_sdk.admin.Reservation.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/Reservation/methods/js_sdk.admin.Reservation.update/index.html.md) -- [addReturnItem](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.addReturnItem/index.html.md) -- [addReturnShipping](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.addReturnShipping/index.html.md) -- [cancel](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.cancel/index.html.md) -- [cancelReceive](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.cancelReceive/index.html.md) -- [cancelRequest](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.cancelRequest/index.html.md) -- [confirmReceive](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.confirmReceive/index.html.md) -- [confirmRequest](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.confirmRequest/index.html.md) -- [deleteReturnShipping](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.deleteReturnShipping/index.html.md) -- [dismissItems](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.dismissItems/index.html.md) -- [initiateReceive](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.initiateReceive/index.html.md) -- [initiateRequest](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.initiateRequest/index.html.md) -- [list](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.list/index.html.md) -- [receiveItems](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.receiveItems/index.html.md) -- [removeDismissItem](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.removeDismissItem/index.html.md) -- [removeReceiveItem](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.removeReceiveItem/index.html.md) -- [removeReturnItem](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.removeReturnItem/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.retrieve/index.html.md) -- [updateDismissItem](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.updateDismissItem/index.html.md) -- [updateReceiveItem](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.updateReceiveItem/index.html.md) -- [updateRequest](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.updateRequest/index.html.md) -- [updateReturnItem](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.updateReturnItem/index.html.md) -- [updateReturnShipping](undefined/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.updateReturnShipping/index.html.md) -- [create](undefined/references/js_sdk/admin/ReturnReason/methods/js_sdk.admin.ReturnReason.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/ReturnReason/methods/js_sdk.admin.ReturnReason.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/ReturnReason/methods/js_sdk.admin.ReturnReason.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/ReturnReason/methods/js_sdk.admin.ReturnReason.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/ReturnReason/methods/js_sdk.admin.ReturnReason.update/index.html.md) -- [batchProducts](undefined/references/js_sdk/admin/SalesChannel/methods/js_sdk.admin.SalesChannel.batchProducts/index.html.md) -- [create](undefined/references/js_sdk/admin/SalesChannel/methods/js_sdk.admin.SalesChannel.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/SalesChannel/methods/js_sdk.admin.SalesChannel.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/SalesChannel/methods/js_sdk.admin.SalesChannel.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/SalesChannel/methods/js_sdk.admin.SalesChannel.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/SalesChannel/methods/js_sdk.admin.SalesChannel.update/index.html.md) -- [updateProducts](undefined/references/js_sdk/admin/SalesChannel/methods/js_sdk.admin.SalesChannel.updateProducts/index.html.md) -- [create](undefined/references/js_sdk/admin/ShippingOption/methods/js_sdk.admin.ShippingOption.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/ShippingOption/methods/js_sdk.admin.ShippingOption.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/ShippingOption/methods/js_sdk.admin.ShippingOption.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/ShippingOption/methods/js_sdk.admin.ShippingOption.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/ShippingOption/methods/js_sdk.admin.ShippingOption.update/index.html.md) -- [updateRules](undefined/references/js_sdk/admin/ShippingOption/methods/js_sdk.admin.ShippingOption.updateRules/index.html.md) -- [create](undefined/references/js_sdk/admin/ShippingOptionType/methods/js_sdk.admin.ShippingOptionType.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/ShippingOptionType/methods/js_sdk.admin.ShippingOptionType.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/ShippingOptionType/methods/js_sdk.admin.ShippingOptionType.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/ShippingOptionType/methods/js_sdk.admin.ShippingOptionType.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/ShippingOptionType/methods/js_sdk.admin.ShippingOptionType.update/index.html.md) -- [create](undefined/references/js_sdk/admin/ShippingProfile/methods/js_sdk.admin.ShippingProfile.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/ShippingProfile/methods/js_sdk.admin.ShippingProfile.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/ShippingProfile/methods/js_sdk.admin.ShippingProfile.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/ShippingProfile/methods/js_sdk.admin.ShippingProfile.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/ShippingProfile/methods/js_sdk.admin.ShippingProfile.update/index.html.md) -- [create](undefined/references/js_sdk/admin/StockLocation/methods/js_sdk.admin.StockLocation.create/index.html.md) -- [createFulfillmentSet](undefined/references/js_sdk/admin/StockLocation/methods/js_sdk.admin.StockLocation.createFulfillmentSet/index.html.md) -- [delete](undefined/references/js_sdk/admin/StockLocation/methods/js_sdk.admin.StockLocation.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/StockLocation/methods/js_sdk.admin.StockLocation.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/StockLocation/methods/js_sdk.admin.StockLocation.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/StockLocation/methods/js_sdk.admin.StockLocation.update/index.html.md) -- [updateFulfillmentProviders](undefined/references/js_sdk/admin/StockLocation/methods/js_sdk.admin.StockLocation.updateFulfillmentProviders/index.html.md) -- [updateSalesChannels](undefined/references/js_sdk/admin/StockLocation/methods/js_sdk.admin.StockLocation.updateSalesChannels/index.html.md) -- [list](undefined/references/js_sdk/admin/Store/methods/js_sdk.admin.Store.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/Store/methods/js_sdk.admin.Store.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/Store/methods/js_sdk.admin.Store.update/index.html.md) -- [list](undefined/references/js_sdk/admin/TaxProvider/methods/js_sdk.admin.TaxProvider.list/index.html.md) -- [create](undefined/references/js_sdk/admin/TaxRate/methods/js_sdk.admin.TaxRate.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/TaxRate/methods/js_sdk.admin.TaxRate.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/TaxRate/methods/js_sdk.admin.TaxRate.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/TaxRate/methods/js_sdk.admin.TaxRate.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/TaxRate/methods/js_sdk.admin.TaxRate.update/index.html.md) -- [create](undefined/references/js_sdk/admin/TaxRegion/methods/js_sdk.admin.TaxRegion.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/TaxRegion/methods/js_sdk.admin.TaxRegion.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/TaxRegion/methods/js_sdk.admin.TaxRegion.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/TaxRegion/methods/js_sdk.admin.TaxRegion.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/TaxRegion/methods/js_sdk.admin.TaxRegion.update/index.html.md) -- [create](undefined/references/js_sdk/admin/Upload/methods/js_sdk.admin.Upload.create/index.html.md) -- [delete](undefined/references/js_sdk/admin/Upload/methods/js_sdk.admin.Upload.delete/index.html.md) -- [presignedUrl](undefined/references/js_sdk/admin/Upload/methods/js_sdk.admin.Upload.presignedUrl/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/Upload/methods/js_sdk.admin.Upload.retrieve/index.html.md) -- [delete](undefined/references/js_sdk/admin/User/methods/js_sdk.admin.User.delete/index.html.md) -- [list](undefined/references/js_sdk/admin/User/methods/js_sdk.admin.User.list/index.html.md) -- [me](undefined/references/js_sdk/admin/User/methods/js_sdk.admin.User.me/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/User/methods/js_sdk.admin.User.retrieve/index.html.md) -- [update](undefined/references/js_sdk/admin/User/methods/js_sdk.admin.User.update/index.html.md) -- [columns](undefined/references/js_sdk/admin/Views/methods/js_sdk.admin.Views.columns/index.html.md) -- [createConfiguration](undefined/references/js_sdk/admin/Views/methods/js_sdk.admin.Views.createConfiguration/index.html.md) -- [deleteConfiguration](undefined/references/js_sdk/admin/Views/methods/js_sdk.admin.Views.deleteConfiguration/index.html.md) -- [listConfigurations](undefined/references/js_sdk/admin/Views/methods/js_sdk.admin.Views.listConfigurations/index.html.md) -- [retrieveActiveConfiguration](undefined/references/js_sdk/admin/Views/methods/js_sdk.admin.Views.retrieveActiveConfiguration/index.html.md) -- [retrieveConfiguration](undefined/references/js_sdk/admin/Views/methods/js_sdk.admin.Views.retrieveConfiguration/index.html.md) -- [setActiveConfiguration](undefined/references/js_sdk/admin/Views/methods/js_sdk.admin.Views.setActiveConfiguration/index.html.md) -- [updateConfiguration](undefined/references/js_sdk/admin/Views/methods/js_sdk.admin.Views.updateConfiguration/index.html.md) -- [list](undefined/references/js_sdk/admin/WorkflowExecution/methods/js_sdk.admin.WorkflowExecution.list/index.html.md) -- [retrieve](undefined/references/js_sdk/admin/WorkflowExecution/methods/js_sdk.admin.WorkflowExecution.retrieve/index.html.md) +- [batchSalesChannels](https://docs.medusajs.com/references/js_sdk/admin/ApiKey/methods/js_sdk.admin.ApiKey.batchSalesChannels/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/ApiKey/methods/js_sdk.admin.ApiKey.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/ApiKey/methods/js_sdk.admin.ApiKey.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/ApiKey/methods/js_sdk.admin.ApiKey.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/ApiKey/methods/js_sdk.admin.ApiKey.retrieve/index.html.md) +- [revoke](https://docs.medusajs.com/references/js_sdk/admin/ApiKey/methods/js_sdk.admin.ApiKey.revoke/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/ApiKey/methods/js_sdk.admin.ApiKey.update/index.html.md) +- [batchPromotions](https://docs.medusajs.com/references/js_sdk/admin/Campaign/methods/js_sdk.admin.Campaign.batchPromotions/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/Campaign/methods/js_sdk.admin.Campaign.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/Campaign/methods/js_sdk.admin.Campaign.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/Campaign/methods/js_sdk.admin.Campaign.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/Campaign/methods/js_sdk.admin.Campaign.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/Campaign/methods/js_sdk.admin.Campaign.update/index.html.md) +- [addInboundItems](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.addInboundItems/index.html.md) +- [addInboundShipping](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.addInboundShipping/index.html.md) +- [addItems](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.addItems/index.html.md) +- [addOutboundItems](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.addOutboundItems/index.html.md) +- [addOutboundShipping](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.addOutboundShipping/index.html.md) +- [cancel](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.cancel/index.html.md) +- [cancelRequest](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.cancelRequest/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.create/index.html.md) +- [deleteInboundShipping](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.deleteInboundShipping/index.html.md) +- [deleteOutboundShipping](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.deleteOutboundShipping/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.list/index.html.md) +- [removeInboundItem](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.removeInboundItem/index.html.md) +- [removeItem](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.removeItem/index.html.md) +- [removeOutboundItem](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.removeOutboundItem/index.html.md) +- [request](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.request/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.retrieve/index.html.md) +- [updateInboundItem](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.updateInboundItem/index.html.md) +- [updateInboundShipping](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.updateInboundShipping/index.html.md) +- [updateItem](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.updateItem/index.html.md) +- [updateOutboundItem](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.updateOutboundItem/index.html.md) +- [updateOutboundShipping](https://docs.medusajs.com/references/js_sdk/admin/Claim/methods/js_sdk.admin.Claim.updateOutboundShipping/index.html.md) +- [clearToken](https://docs.medusajs.com/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.clearToken/index.html.md) +- [clearToken\_](https://docs.medusajs.com/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.clearToken_/index.html.md) +- [fetch](https://docs.medusajs.com/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.fetch/index.html.md) +- [fetchStream](https://docs.medusajs.com/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.fetchStream/index.html.md) +- [getApiKeyHeader\_](https://docs.medusajs.com/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.getApiKeyHeader_/index.html.md) +- [getJwtHeader\_](https://docs.medusajs.com/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.getJwtHeader_/index.html.md) +- [getPublishableKeyHeader\_](https://docs.medusajs.com/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.getPublishableKeyHeader_/index.html.md) +- [getToken](https://docs.medusajs.com/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.getToken/index.html.md) +- [getTokenStorageInfo\_](https://docs.medusajs.com/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.getTokenStorageInfo_/index.html.md) +- [getToken\_](https://docs.medusajs.com/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.getToken_/index.html.md) +- [initClient](https://docs.medusajs.com/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.initClient/index.html.md) +- [setToken](https://docs.medusajs.com/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.setToken/index.html.md) +- [setToken\_](https://docs.medusajs.com/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.setToken_/index.html.md) +- [throwError\_](https://docs.medusajs.com/references/js_sdk/admin/Client/methods/js_sdk.admin.Client.throwError_/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/Currency/methods/js_sdk.admin.Currency.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/Currency/methods/js_sdk.admin.Currency.retrieve/index.html.md) +- [getItem](https://docs.medusajs.com/references/js_sdk/admin/CustomStorage/methods/js_sdk.admin.CustomStorage.getItem/index.html.md) +- [removeItem](https://docs.medusajs.com/references/js_sdk/admin/CustomStorage/methods/js_sdk.admin.CustomStorage.removeItem/index.html.md) +- [setItem](https://docs.medusajs.com/references/js_sdk/admin/CustomStorage/methods/js_sdk.admin.CustomStorage.setItem/index.html.md) +- [batchCustomerGroups](https://docs.medusajs.com/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.batchCustomerGroups/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.create/index.html.md) +- [createAddress](https://docs.medusajs.com/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.createAddress/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.delete/index.html.md) +- [deleteAddress](https://docs.medusajs.com/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.deleteAddress/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.list/index.html.md) +- [listAddresses](https://docs.medusajs.com/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.listAddresses/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.retrieve/index.html.md) +- [retrieveAddress](https://docs.medusajs.com/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.retrieveAddress/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.update/index.html.md) +- [updateAddress](https://docs.medusajs.com/references/js_sdk/admin/Customer/methods/js_sdk.admin.Customer.updateAddress/index.html.md) +- [batchCustomers](https://docs.medusajs.com/references/js_sdk/admin/CustomerGroup/methods/js_sdk.admin.CustomerGroup.batchCustomers/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/CustomerGroup/methods/js_sdk.admin.CustomerGroup.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/CustomerGroup/methods/js_sdk.admin.CustomerGroup.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/CustomerGroup/methods/js_sdk.admin.CustomerGroup.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/CustomerGroup/methods/js_sdk.admin.CustomerGroup.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/CustomerGroup/methods/js_sdk.admin.CustomerGroup.update/index.html.md) +- [addItems](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.addItems/index.html.md) +- [addPromotions](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.addPromotions/index.html.md) +- [addShippingMethod](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.addShippingMethod/index.html.md) +- [beginEdit](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.beginEdit/index.html.md) +- [cancelEdit](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.cancelEdit/index.html.md) +- [confirmEdit](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.confirmEdit/index.html.md) +- [convertToOrder](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.convertToOrder/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.list/index.html.md) +- [removeActionItem](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.removeActionItem/index.html.md) +- [removeActionShippingMethod](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.removeActionShippingMethod/index.html.md) +- [removePromotions](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.removePromotions/index.html.md) +- [removeShippingMethod](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.removeShippingMethod/index.html.md) +- [requestEdit](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.requestEdit/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.update/index.html.md) +- [updateActionItem](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.updateActionItem/index.html.md) +- [updateActionShippingMethod](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.updateActionShippingMethod/index.html.md) +- [updateItem](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.updateItem/index.html.md) +- [updateShippingMethod](https://docs.medusajs.com/references/js_sdk/admin/DraftOrder/methods/js_sdk.admin.DraftOrder.updateShippingMethod/index.html.md) +- [addInboundItems](https://docs.medusajs.com/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.addInboundItems/index.html.md) +- [addInboundShipping](https://docs.medusajs.com/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.addInboundShipping/index.html.md) +- [addOutboundItems](https://docs.medusajs.com/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.addOutboundItems/index.html.md) +- [addOutboundShipping](https://docs.medusajs.com/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.addOutboundShipping/index.html.md) +- [cancel](https://docs.medusajs.com/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.cancel/index.html.md) +- [cancelRequest](https://docs.medusajs.com/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.cancelRequest/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.create/index.html.md) +- [deleteInboundShipping](https://docs.medusajs.com/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.deleteInboundShipping/index.html.md) +- [deleteOutboundShipping](https://docs.medusajs.com/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.deleteOutboundShipping/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.list/index.html.md) +- [removeInboundItem](https://docs.medusajs.com/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.removeInboundItem/index.html.md) +- [removeOutboundItem](https://docs.medusajs.com/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.removeOutboundItem/index.html.md) +- [request](https://docs.medusajs.com/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.request/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.retrieve/index.html.md) +- [updateInboundItem](https://docs.medusajs.com/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.updateInboundItem/index.html.md) +- [updateInboundShipping](https://docs.medusajs.com/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.updateInboundShipping/index.html.md) +- [updateOutboundItem](https://docs.medusajs.com/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.updateOutboundItem/index.html.md) +- [updateOutboundShipping](https://docs.medusajs.com/references/js_sdk/admin/Exchange/methods/js_sdk.admin.Exchange.updateOutboundShipping/index.html.md) +- [cancel](https://docs.medusajs.com/references/js_sdk/admin/Fulfillment/methods/js_sdk.admin.Fulfillment.cancel/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/Fulfillment/methods/js_sdk.admin.Fulfillment.create/index.html.md) +- [createShipment](https://docs.medusajs.com/references/js_sdk/admin/Fulfillment/methods/js_sdk.admin.Fulfillment.createShipment/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/FulfillmentProvider/methods/js_sdk.admin.FulfillmentProvider.list/index.html.md) +- [listFulfillmentOptions](https://docs.medusajs.com/references/js_sdk/admin/FulfillmentProvider/methods/js_sdk.admin.FulfillmentProvider.listFulfillmentOptions/index.html.md) +- [createServiceZone](https://docs.medusajs.com/references/js_sdk/admin/FulfillmentSet/methods/js_sdk.admin.FulfillmentSet.createServiceZone/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/FulfillmentSet/methods/js_sdk.admin.FulfillmentSet.delete/index.html.md) +- [deleteServiceZone](https://docs.medusajs.com/references/js_sdk/admin/FulfillmentSet/methods/js_sdk.admin.FulfillmentSet.deleteServiceZone/index.html.md) +- [retrieveServiceZone](https://docs.medusajs.com/references/js_sdk/admin/FulfillmentSet/methods/js_sdk.admin.FulfillmentSet.retrieveServiceZone/index.html.md) +- [updateServiceZone](https://docs.medusajs.com/references/js_sdk/admin/FulfillmentSet/methods/js_sdk.admin.FulfillmentSet.updateServiceZone/index.html.md) +- [batchInventoryItemLocationLevels](https://docs.medusajs.com/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.batchInventoryItemLocationLevels/index.html.md) +- [batchInventoryItemsLocationLevels](https://docs.medusajs.com/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.batchInventoryItemsLocationLevels/index.html.md) +- [batchUpdateLevels](https://docs.medusajs.com/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.batchUpdateLevels/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.delete/index.html.md) +- [deleteLevel](https://docs.medusajs.com/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.deleteLevel/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.list/index.html.md) +- [listLevels](https://docs.medusajs.com/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.listLevels/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.update/index.html.md) +- [updateLevel](https://docs.medusajs.com/references/js_sdk/admin/InventoryItem/methods/js_sdk.admin.InventoryItem.updateLevel/index.html.md) +- [accept](https://docs.medusajs.com/references/js_sdk/admin/Invite/methods/js_sdk.admin.Invite.accept/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/Invite/methods/js_sdk.admin.Invite.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/Invite/methods/js_sdk.admin.Invite.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/Invite/methods/js_sdk.admin.Invite.list/index.html.md) +- [resend](https://docs.medusajs.com/references/js_sdk/admin/Invite/methods/js_sdk.admin.Invite.resend/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/Invite/methods/js_sdk.admin.Invite.retrieve/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/Notification/methods/js_sdk.admin.Notification.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/Notification/methods/js_sdk.admin.Notification.retrieve/index.html.md) +- [archive](https://docs.medusajs.com/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.archive/index.html.md) +- [cancel](https://docs.medusajs.com/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.cancel/index.html.md) +- [cancelFulfillment](https://docs.medusajs.com/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.cancelFulfillment/index.html.md) +- [cancelTransfer](https://docs.medusajs.com/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.cancelTransfer/index.html.md) +- [complete](https://docs.medusajs.com/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.complete/index.html.md) +- [createCreditLine](https://docs.medusajs.com/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.createCreditLine/index.html.md) +- [createFulfillment](https://docs.medusajs.com/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.createFulfillment/index.html.md) +- [createShipment](https://docs.medusajs.com/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.createShipment/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.list/index.html.md) +- [listChanges](https://docs.medusajs.com/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.listChanges/index.html.md) +- [listLineItems](https://docs.medusajs.com/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.listLineItems/index.html.md) +- [listShippingOptions](https://docs.medusajs.com/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.listShippingOptions/index.html.md) +- [markAsDelivered](https://docs.medusajs.com/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.markAsDelivered/index.html.md) +- [requestTransfer](https://docs.medusajs.com/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.requestTransfer/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.retrieve/index.html.md) +- [retrievePreview](https://docs.medusajs.com/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.retrievePreview/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/Order/methods/js_sdk.admin.Order.update/index.html.md) +- [addItems](https://docs.medusajs.com/references/js_sdk/admin/OrderEdit/methods/js_sdk.admin.OrderEdit.addItems/index.html.md) +- [cancelRequest](https://docs.medusajs.com/references/js_sdk/admin/OrderEdit/methods/js_sdk.admin.OrderEdit.cancelRequest/index.html.md) +- [confirm](https://docs.medusajs.com/references/js_sdk/admin/OrderEdit/methods/js_sdk.admin.OrderEdit.confirm/index.html.md) +- [initiateRequest](https://docs.medusajs.com/references/js_sdk/admin/OrderEdit/methods/js_sdk.admin.OrderEdit.initiateRequest/index.html.md) +- [removeAddedItem](https://docs.medusajs.com/references/js_sdk/admin/OrderEdit/methods/js_sdk.admin.OrderEdit.removeAddedItem/index.html.md) +- [request](https://docs.medusajs.com/references/js_sdk/admin/OrderEdit/methods/js_sdk.admin.OrderEdit.request/index.html.md) +- [updateAddedItem](https://docs.medusajs.com/references/js_sdk/admin/OrderEdit/methods/js_sdk.admin.OrderEdit.updateAddedItem/index.html.md) +- [updateOriginalItem](https://docs.medusajs.com/references/js_sdk/admin/OrderEdit/methods/js_sdk.admin.OrderEdit.updateOriginalItem/index.html.md) +- [capture](https://docs.medusajs.com/references/js_sdk/admin/Payment/methods/js_sdk.admin.Payment.capture/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/Payment/methods/js_sdk.admin.Payment.list/index.html.md) +- [listPaymentProviders](https://docs.medusajs.com/references/js_sdk/admin/Payment/methods/js_sdk.admin.Payment.listPaymentProviders/index.html.md) +- [refund](https://docs.medusajs.com/references/js_sdk/admin/Payment/methods/js_sdk.admin.Payment.refund/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/Payment/methods/js_sdk.admin.Payment.retrieve/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/PaymentCollection/methods/js_sdk.admin.PaymentCollection.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/PaymentCollection/methods/js_sdk.admin.PaymentCollection.delete/index.html.md) +- [markAsPaid](https://docs.medusajs.com/references/js_sdk/admin/PaymentCollection/methods/js_sdk.admin.PaymentCollection.markAsPaid/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/Plugin/methods/js_sdk.admin.Plugin.list/index.html.md) +- [batchPrices](https://docs.medusajs.com/references/js_sdk/admin/PriceList/methods/js_sdk.admin.PriceList.batchPrices/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/PriceList/methods/js_sdk.admin.PriceList.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/PriceList/methods/js_sdk.admin.PriceList.delete/index.html.md) +- [linkProducts](https://docs.medusajs.com/references/js_sdk/admin/PriceList/methods/js_sdk.admin.PriceList.linkProducts/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/PriceList/methods/js_sdk.admin.PriceList.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/PriceList/methods/js_sdk.admin.PriceList.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/PriceList/methods/js_sdk.admin.PriceList.update/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/PricePreference/methods/js_sdk.admin.PricePreference.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/PricePreference/methods/js_sdk.admin.PricePreference.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/PricePreference/methods/js_sdk.admin.PricePreference.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/PricePreference/methods/js_sdk.admin.PricePreference.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/PricePreference/methods/js_sdk.admin.PricePreference.update/index.html.md) +- [batch](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.batch/index.html.md) +- [batchVariantInventoryItems](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.batchVariantInventoryItems/index.html.md) +- [batchVariants](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.batchVariants/index.html.md) +- [confirmImport](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.confirmImport/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.create/index.html.md) +- [createImport](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.createImport/index.html.md) +- [createOption](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.createOption/index.html.md) +- [createVariant](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.createVariant/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.delete/index.html.md) +- [deleteOption](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.deleteOption/index.html.md) +- [deleteVariant](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.deleteVariant/index.html.md) +- [export](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.export/index.html.md) +- [import](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.import/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.list/index.html.md) +- [listOptions](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.listOptions/index.html.md) +- [listVariants](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.listVariants/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.retrieve/index.html.md) +- [retrieveOption](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.retrieveOption/index.html.md) +- [retrieveVariant](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.retrieveVariant/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.update/index.html.md) +- [updateOption](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.updateOption/index.html.md) +- [updateVariant](https://docs.medusajs.com/references/js_sdk/admin/Product/methods/js_sdk.admin.Product.updateVariant/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/ProductCategory/methods/js_sdk.admin.ProductCategory.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/ProductCategory/methods/js_sdk.admin.ProductCategory.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/ProductCategory/methods/js_sdk.admin.ProductCategory.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/ProductCategory/methods/js_sdk.admin.ProductCategory.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/ProductCategory/methods/js_sdk.admin.ProductCategory.update/index.html.md) +- [updateProducts](https://docs.medusajs.com/references/js_sdk/admin/ProductCategory/methods/js_sdk.admin.ProductCategory.updateProducts/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/ProductCollection/methods/js_sdk.admin.ProductCollection.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/ProductCollection/methods/js_sdk.admin.ProductCollection.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/ProductCollection/methods/js_sdk.admin.ProductCollection.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/ProductCollection/methods/js_sdk.admin.ProductCollection.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/ProductCollection/methods/js_sdk.admin.ProductCollection.update/index.html.md) +- [updateProducts](https://docs.medusajs.com/references/js_sdk/admin/ProductCollection/methods/js_sdk.admin.ProductCollection.updateProducts/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/ProductTag/methods/js_sdk.admin.ProductTag.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/ProductTag/methods/js_sdk.admin.ProductTag.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/ProductTag/methods/js_sdk.admin.ProductTag.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/ProductTag/methods/js_sdk.admin.ProductTag.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/ProductTag/methods/js_sdk.admin.ProductTag.update/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/ProductType/methods/js_sdk.admin.ProductType.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/ProductType/methods/js_sdk.admin.ProductType.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/ProductType/methods/js_sdk.admin.ProductType.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/ProductType/methods/js_sdk.admin.ProductType.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/ProductType/methods/js_sdk.admin.ProductType.update/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/ProductVariant/methods/js_sdk.admin.ProductVariant.list/index.html.md) +- [addRules](https://docs.medusajs.com/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.addRules/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.list/index.html.md) +- [listRuleAttributes](https://docs.medusajs.com/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.listRuleAttributes/index.html.md) +- [listRuleValues](https://docs.medusajs.com/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.listRuleValues/index.html.md) +- [listRules](https://docs.medusajs.com/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.listRules/index.html.md) +- [removeRules](https://docs.medusajs.com/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.removeRules/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.update/index.html.md) +- [updateRules](https://docs.medusajs.com/references/js_sdk/admin/Promotion/methods/js_sdk.admin.Promotion.updateRules/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/RefundReason/methods/js_sdk.admin.RefundReason.list/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/Region/methods/js_sdk.admin.Region.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/Region/methods/js_sdk.admin.Region.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/Region/methods/js_sdk.admin.Region.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/Region/methods/js_sdk.admin.Region.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/Region/methods/js_sdk.admin.Region.update/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/Reservation/methods/js_sdk.admin.Reservation.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/Reservation/methods/js_sdk.admin.Reservation.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/Reservation/methods/js_sdk.admin.Reservation.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/Reservation/methods/js_sdk.admin.Reservation.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/Reservation/methods/js_sdk.admin.Reservation.update/index.html.md) +- [addReturnItem](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.addReturnItem/index.html.md) +- [addReturnShipping](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.addReturnShipping/index.html.md) +- [cancel](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.cancel/index.html.md) +- [cancelReceive](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.cancelReceive/index.html.md) +- [cancelRequest](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.cancelRequest/index.html.md) +- [confirmReceive](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.confirmReceive/index.html.md) +- [confirmRequest](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.confirmRequest/index.html.md) +- [deleteReturnShipping](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.deleteReturnShipping/index.html.md) +- [dismissItems](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.dismissItems/index.html.md) +- [initiateReceive](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.initiateReceive/index.html.md) +- [initiateRequest](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.initiateRequest/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.list/index.html.md) +- [receiveItems](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.receiveItems/index.html.md) +- [removeDismissItem](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.removeDismissItem/index.html.md) +- [removeReceiveItem](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.removeReceiveItem/index.html.md) +- [removeReturnItem](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.removeReturnItem/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.retrieve/index.html.md) +- [updateDismissItem](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.updateDismissItem/index.html.md) +- [updateReceiveItem](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.updateReceiveItem/index.html.md) +- [updateRequest](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.updateRequest/index.html.md) +- [updateReturnItem](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.updateReturnItem/index.html.md) +- [updateReturnShipping](https://docs.medusajs.com/references/js_sdk/admin/Return/methods/js_sdk.admin.Return.updateReturnShipping/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/ReturnReason/methods/js_sdk.admin.ReturnReason.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/ReturnReason/methods/js_sdk.admin.ReturnReason.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/ReturnReason/methods/js_sdk.admin.ReturnReason.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/ReturnReason/methods/js_sdk.admin.ReturnReason.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/ReturnReason/methods/js_sdk.admin.ReturnReason.update/index.html.md) +- [batchProducts](https://docs.medusajs.com/references/js_sdk/admin/SalesChannel/methods/js_sdk.admin.SalesChannel.batchProducts/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/SalesChannel/methods/js_sdk.admin.SalesChannel.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/SalesChannel/methods/js_sdk.admin.SalesChannel.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/SalesChannel/methods/js_sdk.admin.SalesChannel.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/SalesChannel/methods/js_sdk.admin.SalesChannel.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/SalesChannel/methods/js_sdk.admin.SalesChannel.update/index.html.md) +- [updateProducts](https://docs.medusajs.com/references/js_sdk/admin/SalesChannel/methods/js_sdk.admin.SalesChannel.updateProducts/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/ShippingOption/methods/js_sdk.admin.ShippingOption.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/ShippingOption/methods/js_sdk.admin.ShippingOption.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/ShippingOption/methods/js_sdk.admin.ShippingOption.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/ShippingOption/methods/js_sdk.admin.ShippingOption.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/ShippingOption/methods/js_sdk.admin.ShippingOption.update/index.html.md) +- [updateRules](https://docs.medusajs.com/references/js_sdk/admin/ShippingOption/methods/js_sdk.admin.ShippingOption.updateRules/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/ShippingOptionType/methods/js_sdk.admin.ShippingOptionType.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/ShippingOptionType/methods/js_sdk.admin.ShippingOptionType.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/ShippingOptionType/methods/js_sdk.admin.ShippingOptionType.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/ShippingOptionType/methods/js_sdk.admin.ShippingOptionType.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/ShippingOptionType/methods/js_sdk.admin.ShippingOptionType.update/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/ShippingProfile/methods/js_sdk.admin.ShippingProfile.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/ShippingProfile/methods/js_sdk.admin.ShippingProfile.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/ShippingProfile/methods/js_sdk.admin.ShippingProfile.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/ShippingProfile/methods/js_sdk.admin.ShippingProfile.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/ShippingProfile/methods/js_sdk.admin.ShippingProfile.update/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/StockLocation/methods/js_sdk.admin.StockLocation.create/index.html.md) +- [createFulfillmentSet](https://docs.medusajs.com/references/js_sdk/admin/StockLocation/methods/js_sdk.admin.StockLocation.createFulfillmentSet/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/StockLocation/methods/js_sdk.admin.StockLocation.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/StockLocation/methods/js_sdk.admin.StockLocation.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/StockLocation/methods/js_sdk.admin.StockLocation.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/StockLocation/methods/js_sdk.admin.StockLocation.update/index.html.md) +- [updateFulfillmentProviders](https://docs.medusajs.com/references/js_sdk/admin/StockLocation/methods/js_sdk.admin.StockLocation.updateFulfillmentProviders/index.html.md) +- [updateSalesChannels](https://docs.medusajs.com/references/js_sdk/admin/StockLocation/methods/js_sdk.admin.StockLocation.updateSalesChannels/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/Store/methods/js_sdk.admin.Store.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/Store/methods/js_sdk.admin.Store.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/Store/methods/js_sdk.admin.Store.update/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/TaxProvider/methods/js_sdk.admin.TaxProvider.list/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/TaxRate/methods/js_sdk.admin.TaxRate.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/TaxRate/methods/js_sdk.admin.TaxRate.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/TaxRate/methods/js_sdk.admin.TaxRate.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/TaxRate/methods/js_sdk.admin.TaxRate.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/TaxRate/methods/js_sdk.admin.TaxRate.update/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/TaxRegion/methods/js_sdk.admin.TaxRegion.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/TaxRegion/methods/js_sdk.admin.TaxRegion.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/TaxRegion/methods/js_sdk.admin.TaxRegion.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/TaxRegion/methods/js_sdk.admin.TaxRegion.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/TaxRegion/methods/js_sdk.admin.TaxRegion.update/index.html.md) +- [create](https://docs.medusajs.com/references/js_sdk/admin/Upload/methods/js_sdk.admin.Upload.create/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/Upload/methods/js_sdk.admin.Upload.delete/index.html.md) +- [presignedUrl](https://docs.medusajs.com/references/js_sdk/admin/Upload/methods/js_sdk.admin.Upload.presignedUrl/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/Upload/methods/js_sdk.admin.Upload.retrieve/index.html.md) +- [delete](https://docs.medusajs.com/references/js_sdk/admin/User/methods/js_sdk.admin.User.delete/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/User/methods/js_sdk.admin.User.list/index.html.md) +- [me](https://docs.medusajs.com/references/js_sdk/admin/User/methods/js_sdk.admin.User.me/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/User/methods/js_sdk.admin.User.retrieve/index.html.md) +- [update](https://docs.medusajs.com/references/js_sdk/admin/User/methods/js_sdk.admin.User.update/index.html.md) +- [columns](https://docs.medusajs.com/references/js_sdk/admin/Views/methods/js_sdk.admin.Views.columns/index.html.md) +- [createConfiguration](https://docs.medusajs.com/references/js_sdk/admin/Views/methods/js_sdk.admin.Views.createConfiguration/index.html.md) +- [deleteConfiguration](https://docs.medusajs.com/references/js_sdk/admin/Views/methods/js_sdk.admin.Views.deleteConfiguration/index.html.md) +- [listConfigurations](https://docs.medusajs.com/references/js_sdk/admin/Views/methods/js_sdk.admin.Views.listConfigurations/index.html.md) +- [retrieveActiveConfiguration](https://docs.medusajs.com/references/js_sdk/admin/Views/methods/js_sdk.admin.Views.retrieveActiveConfiguration/index.html.md) +- [retrieveConfiguration](https://docs.medusajs.com/references/js_sdk/admin/Views/methods/js_sdk.admin.Views.retrieveConfiguration/index.html.md) +- [setActiveConfiguration](https://docs.medusajs.com/references/js_sdk/admin/Views/methods/js_sdk.admin.Views.setActiveConfiguration/index.html.md) +- [updateConfiguration](https://docs.medusajs.com/references/js_sdk/admin/Views/methods/js_sdk.admin.Views.updateConfiguration/index.html.md) +- [list](https://docs.medusajs.com/references/js_sdk/admin/WorkflowExecution/methods/js_sdk.admin.WorkflowExecution.list/index.html.md) +- [retrieve](https://docs.medusajs.com/references/js_sdk/admin/WorkflowExecution/methods/js_sdk.admin.WorkflowExecution.retrieve/index.html.md) ## JS SDK Auth -- [callback](undefined/references/js-sdk/auth/callback/index.html.md) -- [login](undefined/references/js-sdk/auth/login/index.html.md) -- [logout](undefined/references/js-sdk/auth/logout/index.html.md) -- [refresh](undefined/references/js-sdk/auth/refresh/index.html.md) -- [register](undefined/references/js-sdk/auth/register/index.html.md) -- [resetPassword](undefined/references/js-sdk/auth/resetPassword/index.html.md) -- [updateProvider](undefined/references/js-sdk/auth/updateProvider/index.html.md) +- [callback](https://docs.medusajs.com/references/js-sdk/auth/callback/index.html.md) +- [login](https://docs.medusajs.com/references/js-sdk/auth/login/index.html.md) +- [logout](https://docs.medusajs.com/references/js-sdk/auth/logout/index.html.md) +- [refresh](https://docs.medusajs.com/references/js-sdk/auth/refresh/index.html.md) +- [register](https://docs.medusajs.com/references/js-sdk/auth/register/index.html.md) +- [resetPassword](https://docs.medusajs.com/references/js-sdk/auth/resetPassword/index.html.md) +- [updateProvider](https://docs.medusajs.com/references/js-sdk/auth/updateProvider/index.html.md) ## JS SDK Store -- [cart](undefined/references/js-sdk/store/cart/index.html.md) -- [category](undefined/references/js-sdk/store/category/index.html.md) -- [collection](undefined/references/js-sdk/store/collection/index.html.md) -- [customer](undefined/references/js-sdk/store/customer/index.html.md) -- [fulfillment](undefined/references/js-sdk/store/fulfillment/index.html.md) -- [order](undefined/references/js-sdk/store/order/index.html.md) -- [payment](undefined/references/js-sdk/store/payment/index.html.md) -- [product](undefined/references/js-sdk/store/product/index.html.md) -- [region](undefined/references/js-sdk/store/region/index.html.md) +- [cart](https://docs.medusajs.com/references/js-sdk/store/cart/index.html.md) +- [category](https://docs.medusajs.com/references/js-sdk/store/category/index.html.md) +- [collection](https://docs.medusajs.com/references/js-sdk/store/collection/index.html.md) +- [customer](https://docs.medusajs.com/references/js-sdk/store/customer/index.html.md) +- [fulfillment](https://docs.medusajs.com/references/js-sdk/store/fulfillment/index.html.md) +- [order](https://docs.medusajs.com/references/js-sdk/store/order/index.html.md) +- [payment](https://docs.medusajs.com/references/js-sdk/store/payment/index.html.md) +- [product](https://docs.medusajs.com/references/js-sdk/store/product/index.html.md) +- [region](https://docs.medusajs.com/references/js-sdk/store/region/index.html.md) # Action Menu - Admin Components @@ -96132,7 +97315,7 @@ export const ActionMenu = ({ groups }: ActionMenuProps) => { } ``` -The `ActionMenu` component shows a three-dots icon (or `EllipsisHorizontal`) from the [Medusa Icons package](undefined/ui/icons/overview) in a button. +The `ActionMenu` component shows a three-dots icon (or `EllipsisHorizontal`) from the [Medusa Icons package](https://docs.medusajs.com/ui/icons/overview/index.html.md) in a button. When the button is clicked, a dropdown menu is shown with the actions passed in the props. @@ -96193,11 +97376,11 @@ export const config = defineWidgetConfig({ export default ProductWidget ``` -This widget also uses a [Container](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components/components/container) custom component. +This widget also uses a [Container](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/components/container/index.html.md) custom component. ### Use in Header -You can also use the action menu in the [Header](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components/components/header) component as part of its actions. +You can also use the action menu in the [Header](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/components/header/index.html.md) component as part of its actions. For example: @@ -96274,7 +97457,7 @@ export const Container = (props: ContainerProps) => { } ``` -The `Container` component re-uses the component from the [Medusa UI package](undefined/ui/components/container) and applies to it classes to match the Medusa Admin's design conventions. +The `Container` component re-uses the component from the [Medusa UI package](https://docs.medusajs.com/ui/components/container/index.html.md) and applies to it classes to match the Medusa Admin's design conventions. *** @@ -96304,24 +97487,24 @@ export const config = defineWidgetConfig({ export default ProductWidget ``` -This widget also uses a [Header](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components/components/header) custom component. +This widget also uses a [Header](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/components/header/index.html.md) custom component. # Data Table - Admin Components This component is available after [Medusa v2.4.0+](https://github.com/medusajs/medusa/releases/tag/v2.4.0). -The [DataTable component in Medusa UI](undefined/ui/components/data-table) allows you to display data in a table with sorting, filtering, and pagination. It's used across the Medusa Admin dashboard to showcase a list of items, such as a list of products. +The [DataTable component in Medusa UI](https://docs.medusajs.com/ui/components/data-table/index.html.md) allows you to display data in a table with sorting, filtering, and pagination. It's used across the Medusa Admin dashboard to showcase a list of items, such as a list of products. ![Example of a table in the product listing page](https://res.cloudinary.com/dza7lstvk/image/upload/v1728295658/Medusa%20Resources/list_ddt9zc.png) You can use this component in your Admin Extensions to display data in a table format, especially if you're retrieving them from API routes of the Medusa application. -This guide focuses on how to use the `DataTable` component while fetching data from the backend. Refer to the [Medusa UI documentation](undefined/ui/components/data-table) for detailed information about the DataTable component and its different usages. +This guide focuses on how to use the `DataTable` component while fetching data from the backend. Refer to the [Medusa UI documentation](https://docs.medusajs.com/ui/components/data-table/index.html.md) for detailed information about the DataTable component and its different usages. ## Example: DataTable with Data Fetching -In this example, you'll create a UI widget that shows the list of products retrieved from the [List Products API Route](undefined/api/admin#products_getproducts) in a data table with pagination, filtering, searching, and sorting. +In this example, you'll create a UI widget that shows the list of products retrieved from the [List Products API Route](https://docs.medusajs.com/api/admin#products_getproducts) in a data table with pagination, filtering, searching, and sorting. Start by initializing the columns in the data table. To do that, use the `createDataTableColumnHelper` from Medusa UI: @@ -96465,7 +97648,7 @@ You've also added two memoized variables: - `offset`: How many items to skip when fetching data based on the current page. - `statusFilters`: The selected status filters, if any. -Next, you'll fetch the products from the Medusa application. Assuming you have the JS SDK configured as explained in [this guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk), add the following imports at the top of the file: +Next, you'll fetch the products from the Medusa application. Assuming you have the JS SDK configured as explained in [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md), add the following imports at the top of the file: ```tsx title="src/admin/routes/custom/page.tsx" import { sdk } from "../../lib/config" @@ -96594,7 +97777,7 @@ import { SingleColumnLayout } from "../../layouts/single-column" import { Container } from "../../components/container" ``` -Aside from the `DataTable` component, you also import the [SingleColumnLayout](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components/layouts/single-column) and [Container](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components/components/container) components implemented in other Admin Component guides. These components ensure a style consistent to other pages in the admin dashboard. +Aside from the `DataTable` component, you also import the [SingleColumnLayout](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/layouts/single-column/index.html.md) and [Container](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/components/container/index.html.md) components implemented in other Admin Component guides. These components ensure a style consistent to other pages in the admin dashboard. Then, replace the `TODO` in the component with the following: @@ -96800,8 +97983,8 @@ In this guide, you'll learn how to create forms that match the Medusa Admin's de The Medusa Admin has two types of forms: -1. Create forms, created using the [FocusModal UI component](undefined/ui/components/focus-modal). -2. Edit or update forms, created using the [Drawer UI component](undefined/ui/components/drawer). +1. Create forms, created using the [FocusModal UI component](https://docs.medusajs.com/ui/components/focus-modal/index.html.md). +2. Edit or update forms, created using the [Drawer UI component](https://docs.medusajs.com/ui/components/drawer/index.html.md). This guide explains how to create these two form types following the Medusa Admin's conventions. @@ -96963,7 +98146,7 @@ You create the `CreateForm` component. For now, it uses `useForm` from `react-ho You also define a `handleSubmit` function to perform an action when the form is submitted. -You can replace the content of the function with sending a request to Medusa's routes. Refer to [this guide](undefined/docs/learn/fundamentals/admin/tips#send-requests-to-api-routes) for more details on how to do that. +You can replace the content of the function with sending a request to Medusa's routes. Refer to [this guide](https://docs.medusajs.com/docs/learn/fundamentals/admin/tips#send-requests-to-api-routes/index.html.md) for more details on how to do that. ### Render Components @@ -97093,7 +98276,7 @@ export const config = defineWidgetConfig({ export default ProductWidget ``` -This component uses the [Container](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components/components/container) and [Header](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components/components/header) custom components. +This component uses the [Container](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/components/container/index.html.md) and [Header](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/components/header/index.html.md) custom components. It will add at the top of a product's details page a new section, and in its header you'll find a Create button. If you click on it, it will open the focus modal with your form. @@ -97240,7 +98423,7 @@ You create the `EditForm` component. For now, it uses `useForm` from `react-hook You also define a `handleSubmit` function to perform an action when the form is submitted. -You can replace the content of the function with sending a request to Medusa's routes. Refer to [this guide](undefined/docs/learn/fundamentals/admin/tips#send-requests-to-api-routes) for more details on how to do that. +You can replace the content of the function with sending a request to Medusa's routes. Refer to [this guide](https://docs.medusajs.com/docs/learn/fundamentals/admin/tips#send-requests-to-api-routes/index.html.md) for more details on how to do that. ### Render Components @@ -97364,7 +98547,7 @@ export const config = defineWidgetConfig({ export default ProductWidget ``` -This component uses the [Container](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components/components/container) and [Header](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components/components/header) custom components. +This component uses the [Container](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/components/container/index.html.md) and [Header](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/components/header/index.html.md) custom components. It will add at the top of a product's details page a new section, and in its header you'll find an "Edit Item" button. If you click on it, it will open the drawer with your form. @@ -97451,7 +98634,7 @@ export const Header = ({ The `Header` component shows a title, and optionally a subtitle and action buttons. -The component also uses the [Action Menu](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components/components/action-menu) custom component. +The component also uses the [Action Menu](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/components/action-menu/index.html.md) custom component. It accepts the following props: @@ -97514,7 +98697,7 @@ export const config = defineWidgetConfig({ export default ProductWidget ``` -This widget also uses a [Container](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components/components/container) custom component. +This widget also uses a [Container](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/components/container/index.html.md) custom component. # JSON View - Admin Components @@ -97838,12 +99021,12 @@ export const config = defineWidgetConfig({ export default ProductWidget ``` -This widget also uses the [Container](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components/components/container) and [Header](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components/components/header) custom component. +This widget also uses the [Container](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/components/container/index.html.md) and [Header](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/components/header/index.html.md) custom component. # Table - Admin Components -If you're using [Medusa v2.4.0+](https://github.com/medusajs/medusa/releases/tag/v2.4.0), it's recommended to use the [Data Table](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components/components/data-table) component instead as it provides features for sorting, filtering, pagination, and more with a simpler API. +If you're using [Medusa v2.4.0+](https://github.com/medusajs/medusa/releases/tag/v2.4.0), it's recommended to use the [Data Table](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/components/data-table/index.html.md) component instead as it provides features for sorting, filtering, pagination, and more with a simpler API. You can use the `Table` component from Medusa UI to display data in a table. It's mostly recommended for simpler tables. @@ -97944,7 +99127,7 @@ export const Table = ({ } ``` -The `Table` component uses the component from the [UI package](undefined/ui/components/table), with additional styling and rendering of data. +The `Table` component uses the component from the [UI package](https://docs.medusajs.com/ui/components/table/index.html.md), with additional styling and rendering of data. It accepts the following props: @@ -98035,7 +99218,7 @@ This widget also uses the [Container](../container.mdx) custom component. This section shows you how to use the `Table` component when fetching data from the Medusa application's API routes. -Assuming you've set up the JS SDK as explained in [this guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk), create the UI route `src/admin/routes/custom/page.tsx` with the following content: +Assuming you've set up the JS SDK as explained in [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md), create the UI route `src/admin/routes/custom/page.tsx` with the following content: ```tsx title="src/admin/routes/custom/page.tsx" collapsibleLines="1-10" expandButtonLabel="Show Imports" highlights={tableExampleHighlights} import { defineRouteConfig } from "@medusajs/admin-sdk" @@ -98082,7 +99265,7 @@ In the `CustomPage` component, you define: Then, you use `useQuery` from [Tanstack Query](https://tanstack.com/query/latest) to retrieve products using the JS SDK. You pass `limit` and `offset` as query parameters, and you set the `queryKey`, which is used for caching and revalidation, to be based on the key `products`, along with the current limit and offset. So, whenever the `offset` variable changes, the request is sent again to retrieve the products of the current page. -You can change the query to send a request to a custom API route as explained in [this guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk#send-requests-to-custom-routes). +You can change the query to send a request to a custom API route as explained in [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk#send-requests-to-custom-routes/index.html.md). Do not install Tanstack Query as that will cause unexpected errors in your development. If you prefer installing it for better auto-completion in your code editor, make sure to install `v5.64.2` as a development dependency. @@ -98119,7 +99302,7 @@ return ( ) ``` -Aside from the `Table` component, this UI route also uses the [SingleColumnLayout](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components/layouts/single-column), [Container](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components/components/container), and [Header](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components/components/header) custom component. +Aside from the `Table` component, this UI route also uses the [SingleColumnLayout](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/layouts/single-column/index.html.md), [Container](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/components/container/index.html.md), and [Header](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/components/header/index.html.md) custom component. If `data` isn't `undefined`, you display the `Table` component passing it the following props: @@ -98190,7 +99373,7 @@ export const config = defineRouteConfig({ export default CustomPage ``` -This UI route also uses a [Container](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components/components/container) and a [Header]() custom components. +This UI route also uses a [Container](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/components/container/index.html.md) and a [Header]() custom components. # Two Column Layout - Admin Components @@ -98271,20 +99454,20 @@ export const config = defineRouteConfig({ export default CustomPage ``` -This UI route also uses [Container](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/admin-components/components/container) and [Header]() custom components. +This UI route also uses [Container](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/admin-components/components/container/index.html.md) and [Header]() custom components. # Admin Components & Layouts In this section of the documentation, you'll learn how to implement common Medusa Admin components and layouts. -These guides are useful to build components and layouts that follow the same design conventions as the Medusa Admin. The components and layouts are built on top of the [Medusa UI package](undefined/ui). +These guides are useful to build components and layouts that follow the same design conventions as the Medusa Admin. The components and layouts are built on top of the [Medusa UI package](https://docs.medusajs.com/ui/index.html.md). -Refer to the [Medusa UI documentation](undefined/ui) for a full list of components. +Refer to the [Medusa UI documentation](https://docs.medusajs.com/ui/index.html.md) for a full list of components. ## Layouts -These layout components allow you to set the layout of your [UI routes](undefined/docs/learn/fundamentals/admin/ui-routes) similar to the layouts used in the Medusa Admin. +These layout components allow you to set the layout of your [UI routes](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md) similar to the layouts used in the Medusa Admin. *** @@ -98372,7 +99555,7 @@ await postModuleService.deletePosts({ To delete records matching a set of filters, pass an object of filters as a parameter to the method. -Refer to the [Filtering](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference/tips/filtering) reference for more information on accepted filters and examples. +Refer to the [Filtering](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/tips/filtering/index.html.md) reference for more information on accepted filters and examples. # list Method - Service Factory Reference @@ -98403,7 +99586,7 @@ const posts = await postModuleService.listPosts({ To retrieve records matching a set of filters, pass an object of the filters as the first parameter. -Refer to the [Filtering](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference/tips/filtering) reference for more information on accepted filters and examples. +Refer to the [Filtering](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/tips/filtering/index.html.md) reference for more information on accepted filters and examples. ### Returns @@ -98413,7 +99596,7 @@ The method returns an array of the first `15` records matching the filters. ## Retrieve Relations -This applies to relations between data models of the same module. To retrieve linked records of different modules, use [Query](undefined/docs/learn/fundamentals/module-links/query). +This applies to relations between data models of the same module. To retrieve linked records of different modules, use [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md). ```ts const posts = await postModuleService.listPosts({}, { @@ -98526,7 +99709,7 @@ const [posts, count] = await postModuleService.listAndCountPosts({ To retrieve records matching a set of filters, pass an object of the filters as the first parameter. -Refer to the [Filtering](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference/tips/filtering) reference for more information on accepted filters and examples. +Refer to the [Filtering](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/tips/filtering/index.html.md) reference for more information on accepted filters and examples. ### Returns @@ -98539,7 +99722,7 @@ The method returns an array with two items: ## Retrieve Relations -This applies to relations between data models of the same module. To retrieve linked records of different modules, use [Query](undefined/docs/learn/fundamentals/module-links/query). +This applies to relations between data models of the same module. To retrieve linked records of different modules, use [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md). ```ts const [posts, count] = await postModuleService.listAndCountPosts({}, { @@ -98635,7 +99818,7 @@ The method returns an array with two items: # restore Method - Service Factory Reference -This method of a module's service restores one or more records of a data model that were [soft-deleted](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference/methods/soft-delete). +This method of a module's service restores one or more records of a data model that were [soft-deleted](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/methods/soft-delete/index.html.md). The method's name is of the format `restoreDataModel`, where `DataModel` is the plural pascal-case name of the data model. @@ -98705,7 +99888,7 @@ const restoredPosts = await postModuleService.restorePosts({ To restore records matching a set of filters, pass an object of filters as a parameter to the method. -Refer to the [Filtering](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference/tips/filtering) reference for more information on accepted filters and examples. +Refer to the [Filtering](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/tips/filtering/index.html.md) reference for more information on accepted filters and examples. ### Returns @@ -98746,7 +99929,7 @@ The method returns the record as an object. ## Retrieve a Record's Relations -This applies to relations between data models of the same module. To retrieve linked records of different modules, use [Query](undefined/docs/learn/fundamentals/module-links/query). +This applies to relations between data models of the same module. To retrieve linked records of different modules, use [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md). ```ts const post = await postModuleService.retrievePost("123", { @@ -98855,7 +100038,7 @@ const deletedPosts = await postModuleService.softDeletePosts({ To soft delete records matching a set of filters, pass an object of filters as a parameter to the method. -Refer to the [Filtering](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference/tips/filtering) reference for more information on accepted filters and examples. +Refer to the [Filtering](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/tips/filtering/index.html.md) reference for more information on accepted filters and examples. ### Returns @@ -98946,7 +100129,7 @@ To update records that match specified filters, pass an object with two properti In the example above, you update the `published_at` property of every post record whose name is `My Post`. -Refer to the [Filtering](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference/tips/filtering) reference for more information on accepted filters and examples. +Refer to the [Filtering](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/tips/filtering/index.html.md) reference for more information on accepted filters and examples. ### Returns @@ -98988,7 +100171,7 @@ To update records matching different sets of filters, pass an array of objects, In the example above, you update the `published_at` property of post records whose name is `My Post`, and update the `metadata` property of post records whose name is `Another Post`. -Refer to the [Filtering](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference/tips/filtering) reference for more information on accepted filters and examples. +Refer to the [Filtering](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/tips/filtering/index.html.md) reference for more information on accepted filters and examples. ### Returns @@ -99009,7 +100192,7 @@ const post = await postModuleService.updatePosts({ }) ``` -When you have a [JSON property](undefined/docs/learn/fundamentals/data-models/json-properties) in your data model, you can update it by adding, updating, or removing properties within that JSON object. Medusa will merge the properties you pass in the `update` method with the existing JSON object. +When you have a [JSON property](https://docs.medusajs.com/docs/learn/fundamentals/data-models/json-properties/index.html.md) in your data model, you can update it by adding, updating, or removing properties within that JSON object. Medusa will merge the properties you pass in the `update` method with the existing JSON object. ### Remove a Property from the JSON Property @@ -99027,14 +100210,14 @@ To remove a property from the JSON object, you can set its value to an empty str ### Learn More about Updating JSON Properties -Refer to the [JSON Properties](undefined/docs/learn/fundamentals/data-models/json-properties) documentation to learn more about how JSON properties work in Medusa and how to update them. +Refer to the [JSON Properties](https://docs.medusajs.com/docs/learn/fundamentals/data-models/json-properties/index.html.md) documentation to learn more about how JSON properties work in Medusa and how to update them. # Service Factory Reference This section of the documentation provides a reference to the methods generated for services extending the service factory (`MedusaService`) and how to use them. -Refer to the [Service Factory](undefined/docs/learn/fundamentals/modules/service-factory) documentation to learn more. +Refer to the [Service Factory](https://docs.medusajs.com/docs/learn/fundamentals/modules/service-factory/index.html.md) documentation to learn more. ## Method Names @@ -99059,7 +100242,7 @@ Some examples of method names: ### Internal Generated Service Methods -The internal services are useful when you need to perform database operations in loaders, as they're executed before the module's services are registered. Learn more in the [Module Container](undefined/docs/learn/fundamentals/modules/container) documentation. +The internal services are useful when you need to perform database operations in loaders, as they're executed before the module's services are registered. Learn more in the [Module Container](https://docs.medusajs.com/docs/learn/fundamentals/modules/container/index.html.md) documentation. For the internal services, the method names are only the operation name, without the data model name. @@ -99447,17 +100630,17 @@ You'll first be asked for the project's name. Then, when you're asked whether yo Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name, and the Next.js Starter Storefront in a directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more about Medusa's architecture in [this documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more about Medusa's architecture in [this documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterwards, you can log in with the new user and explore the dashboard. The Next.js Starter Storefront is also running at `http://localhost:8000`. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. ### b. Configure Stripe Module Provider -Next, you'll configure the [Stripe Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe) in your Medusa application. The Stripe Module Provider allows you to accept payments through Stripe in your Medusa application. +Next, you'll configure the [Stripe Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe/index.html.md) in your Medusa application. The Stripe Module Provider allows you to accept payments through Stripe in your Medusa application. ### Prerequisites @@ -99488,7 +100671,7 @@ module.exports = defineConfig({ }) ``` -For more details about other available options and the webhook URLs that Medusa provides, refer to the [Stripe Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe) documentation. +For more details about other available options and the webhook URLs that Medusa provides, refer to the [Stripe Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe/index.html.md) documentation. ### c. Set Environment Variables @@ -100079,7 +101262,7 @@ export const paymentInfoMap: Record< For every payment method you want to customize its display, add an entry in the `paymentInfoMap` object. The key should match the [type enum in Stripe's Payment Element](https://docs.stripe.com/api/payment_methods/object#payment_method_object-type), and the value is an object with the following properties: - `title`: The title to display for the payment method. -- `icon`: A JSX element representing the icon for the payment method. You can use icons from [Medusa UI](undefined/ui/icons/overview) or custom icons. +- `icon`: A JSX element representing the icon for the payment method. You can use icons from [Medusa UI](https://docs.medusajs.com/ui/icons/overview/index.html.md) or custom icons. ### Test it out @@ -100592,7 +101775,7 @@ When a customer uses a 3D Secure card, a pop-up will open prompting them to comp Webhook verification is useful to ensure that payment events are handled despite connection issues. The Stripe Module Provider in Medusa provides webhook verification out of the box, so you don't need to implement it yourself. -Learn more about the webhook API routes and how to configure them in the [Stripe Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe) guide. +Learn more about the webhook API routes and how to configure them in the [Stripe Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe/index.html.md) guide. ### Testing Declined Payments @@ -100611,11 +101794,11 @@ In some cases, you may need to revalidate the cache in the storefront when data You're free to choose the approach that works for your use case, custom requirements, and tech stack. The approach that Medusa recommends is: -1. Create a [subscriber](undefined/docs/learn/fundamentals/events-and-subscribers) in the Medusa application that listens for the event that triggers the data update. For example, you can listen to the `product.updated` event. +1. Create a [subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md) in the Medusa application that listens for the event that triggers the data update. For example, you can listen to the `product.updated` event. 2. In the subscriber, send a request to a custom endpoint in the Next.js Starter Storefront to trigger the cache revalidation. 3. Create the custom endpoint in the Next.js Starter Storefront that listens for the request from the subscriber and revalidates the cache. -Refer to the [Events Reference](undefined/references/events) for a full list of events that the Medusa application emits. +Refer to the [Events Reference](https://docs.medusajs.com/references/events/index.html.md) for a full list of events that the Medusa application emits. *** @@ -100699,7 +101882,7 @@ Medusa supports automated Return Merchandise Authorization (RMA) flows for order ## Summary -In this tutorial, you'll customize the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter) to let customers create return requests for their orders directly from the storefront. +In this tutorial, you'll customize the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) to let customers create return requests for their orders directly from the storefront. You can follow this tutorial whether you're new to Medusa or an advanced Medusa developer. @@ -100723,15 +101906,15 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose Yes. +You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose Yes. Afterward, the installation process will start, which will install the Medusa application in a directory with your project's name, and the Next.js Starter Storefront in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterward, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** @@ -100749,7 +101932,7 @@ cd ../medusa-returns-storefront # change based on your project name ### List Return Reasons Function -The first function sends a request to the [List Return Reasons](undefined/api/store#return-reasons_getreturnreasons) API route. It fetches the available return reasons, which customers can select from when creating a return request. +The first function sends a request to the [List Return Reasons](https://docs.medusajs.com/api/store#return-reasons_getreturnreasons) API route. It fetches the available return reasons, which customers can select from when creating a return request. Create the file `src/lib/data/returns.ts` with the following content: @@ -100786,7 +101969,7 @@ You add the `listReturnReasons` function. It sends a `GET` request to the `/stor ### List Return Shipping Options Function -Next, you'll add a function that sends a request to the [List Shipping Options](undefined/api/store#shipping-options_getshippingoptions) API route. It fetches the available shipping options for returns, which customers can select from when creating a return request. +Next, you'll add a function that sends a request to the [List Shipping Options](https://docs.medusajs.com/api/store#shipping-options_getshippingoptions) API route. It fetches the available shipping options for returns, which customers can select from when creating a return request. In the same `src/lib/data/returns.ts` file, add the following function: @@ -100825,7 +102008,7 @@ The API route accepts the following query parameters: ### Create Return Function -Finally, you'll add a function that sends a request to the [Create Return](undefined/api/store#returns_postreturns) API route. This creates a return request for an order. +Finally, you'll add a function that sends a request to the [Create Return](https://docs.medusajs.com/api/store#returns_postreturns) API route. This creates a return request for an order. In the same `src/lib/data/returns.ts` file, add the following function: @@ -101847,7 +103030,7 @@ Before you can test the return request page, you need to create return shipping 5. In the form, enter the shipping option's details and price. 6. Click "Save" to create the return shipping option. -You can learn more about creating a shipping option in the [Manage Locations](undefined/user-guide/settings/locations-and-shipping/locations) user guide. +You can learn more about creating a shipping option in the [Manage Locations](https://docs.medusajs.com/user-guide/settings/locations-and-shipping/locations/index.html.md) user guide. ![Form to create a return shipping option in the Medusa Admin](https://res.cloudinary.com/dza7lstvk/image/upload/v1758012545/Medusa%20Resources/CleanShot_2025-09-16_at_11.47.47_2x_fx6tan.png) @@ -101860,7 +103043,7 @@ Next, you need to create return reasons in the Medusa Admin. To do that: 3. In the form, enter the return reason's label and value. 4. Click "Save" to create the return reason. -You can learn more about creating return reasons in the [Manage Return Reasons](undefined/user-guide/settings/return-reasons) user guide. +You can learn more about creating return reasons in the [Manage Return Reasons](https://docs.medusajs.com/user-guide/settings/return-reasons/index.html.md) user guide. ![Form to create a return reason in the Medusa Admin](https://res.cloudinary.com/dza7lstvk/image/upload/v1758012657/Medusa%20Resources/CleanShot_2025-09-16_at_11.50.47_2x_qcrqj6.png) @@ -101894,7 +103077,7 @@ Finally, you need to deliver the items in the order from the Medusa Admin to mak The order's fulfillment status will change to "Delivered", and the items will become returnable. -Learn more about creating fulfillments and marking them as delivered in the [Manage Order Fulfillments](undefined/user-guide/orders/fulfillments) user guide. +Learn more about creating fulfillments and marking them as delivered in the [Manage Order Fulfillments](https://docs.medusajs.com/user-guide/orders/fulfillments/index.html.md) user guide. ![Order details page in the Medusa Admin showing the fulfillment status as "Delivered"](https://res.cloudinary.com/dza7lstvk/image/upload/v1758013188/Medusa%20Resources/CleanShot_2025-09-16_at_11.59.29_2x_tlqaoo.png) @@ -101930,15 +103113,15 @@ If you open the order's details page in the Medusa Admin, you'll see the request As a merchant, you can now handle return requests from the Medusa Admin. You can: -1. [Mark Return Items as Received](undefined/user-guide/orders/returns#mark-return-items-as-received). This is equivalent to approving the return request. This sets the return's status to "received" and restocks the returned items. +1. [Mark Return Items as Received](https://docs.medusajs.com/user-guide/orders/returns#mark-return-items-as-received/index.html.md). This is equivalent to approving the return request. This sets the return's status to "received" and restocks the returned items. ![Form to mark return items as received in the Medusa Admin](https://res.cloudinary.com/dza7lstvk/image/upload/v1758013778/Medusa%20Resources/CleanShot_2025-09-16_at_12.09.23_2x_r07tcb.png) -2. If you've previously captured the order's payment and there's an outstanding amount, you can [refund the outstanding amount](undefined/user-guide/orders/payments#refund-payment). +2. If you've previously captured the order's payment and there's an outstanding amount, you can [refund the outstanding amount](https://docs.medusajs.com/user-guide/orders/payments#refund-payment/index.html.md). ![Button to refund the outstanding amount in the Medusa Admin](https://res.cloudinary.com/dza7lstvk/image/upload/v1758014212/Medusa%20Resources/CleanShot_2025-09-16_at_12.16.35_2x_ibmkdq.png) -3. [Cancel a return request](undefined/user-guide/orders/returns#cancel-requested-return). This sets the return's status to "canceled". The customer can request a new return if needed. +3. [Cancel a return request](https://docs.medusajs.com/user-guide/orders/returns#cancel-requested-return/index.html.md). This sets the return's status to "canceled". The customer can request a new return if needed. ![Button to cancel a return request in the Medusa Admin](https://res.cloudinary.com/dza7lstvk/image/upload/v1758013651/Medusa%20Resources/CleanShot_2025-09-16_at_12.07.09_2x_husdak.png) @@ -101946,17 +103129,17 @@ As a merchant, you can now handle return requests from the Medusa Admin. You can You can customize the return request page to fit your storefront's design and requirements. You can also change how returns are created. For example, you can let guest customers request returns, set custom prices for return shipping options, or specify a stock location to return the items to. -Refer to the [Create Return API reference](undefined/api/api/store#returns_postreturns) to see the available parameters when creating a return request. +Refer to the [Create Return API reference](https://docs.medusajs.com/api/api/store#returns_postreturns) to see the available parameters when creating a return request. ### Learn More about Medusa -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). ### Troubleshooting -If you encounter issues during your development, check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting). +If you encounter issues during your development, check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/index.html.md). ### Getting Help @@ -101970,7 +103153,7 @@ If you encounter issues not covered in the troubleshooting guides:

Just Getting Started?

-Check out the [Medusa v2 Documentation](undefined/docs). +Check out the [Medusa v2 Documentation](https://docs.medusajs.com/docs/index.html.md).

Medusa JS SDK

@@ -101980,7 +103163,7 @@ To use Medusa's JS SDK library, install the following packages in your project ( npm install @medusajs/js-sdk@latest @medusajs/types@latest ``` -Learn more about the JS SDK and how to configure it in [this documentation](undefined/resources/js-sdk). +Learn more about the JS SDK and how to configure it in [this documentation](https://docs.medusajs.com/resources/js-sdk/index.html.md). ### Download Full Reference @@ -102330,6 +103513,14 @@ Download this reference as an OpenApi YAML file. You can import this file to too - [GET /admin/users/{id}](https://docs.medusajs.com/api/admin#users_getusersid) - [POST /admin/users/{id}](https://docs.medusajs.com/api/admin#users_postusersid) - [DELETE /admin/users/{id}](https://docs.medusajs.com/api/admin#users_deleteusersid) +- [GET /admin/views/{entity}/columns](https://docs.medusajs.com/api/admin#views_getviewsentitycolumns) +- [GET /admin/views/{entity}/configurations](https://docs.medusajs.com/api/admin#views_getviewsentityconfigurations) +- [POST /admin/views/{entity}/configurations](https://docs.medusajs.com/api/admin#views_postviewsentityconfigurations) +- [GET /admin/views/{entity}/configurations/active](https://docs.medusajs.com/api/admin#views_getviewsentityconfigurationsactive) +- [POST /admin/views/{entity}/configurations/active](https://docs.medusajs.com/api/admin#views_postviewsentityconfigurationsactive) +- [GET /admin/views/{entity}/configurations/{id}](https://docs.medusajs.com/api/admin#views_getviewsentityconfigurationsid) +- [POST /admin/views/{entity}/configurations/{id}](https://docs.medusajs.com/api/admin#views_postviewsentityconfigurationsid) +- [DELETE /admin/views/{entity}/configurations/{id}](https://docs.medusajs.com/api/admin#views_deleteviewsentityconfigurationsid) - [GET /admin/workflows-executions](https://docs.medusajs.com/api/admin#workflows-executions_getworkflowsexecutions) - [GET /admin/workflows-executions/{id}](https://docs.medusajs.com/api/admin#workflows-executions_getworkflowsexecutionsid) - [POST /admin/workflows-executions/{workflow_id}/run](https://docs.medusajs.com/api/admin#workflows-executions_postworkflowsexecutionsworkflow_idrun) @@ -102350,69 +103541,69 @@ Download this reference as an OpenApi YAML file. You can import this file to too ## Store API Reference -- [POST /auth/customer/{auth_provider}](undefined/api/store#auth_postactor_typeauth_provider) -- [POST /auth/customer/{auth_provider}/callback](undefined/api/store#auth_postactor_typeauth_providercallback) -- [POST /auth/customer/{auth_provider}/register](undefined/api/store#auth_postactor_typeauth_provider_register) -- [POST /auth/customer/{auth_provider}/reset-password](undefined/api/store#auth_postactor_typeauth_providerresetpassword) -- [POST /auth/customer/{auth_provider}/update](undefined/api/store#auth_postactor_typeauth_providerupdate) -- [POST /auth/session](undefined/api/store#auth_postsession) -- [DELETE /auth/session](undefined/api/store#auth_deletesession) -- [POST /auth/token/refresh](undefined/api/store#auth_postadminauthtokenrefresh) -- [POST /store/carts](undefined/api/store#carts_postcarts) -- [GET /store/carts/{id}](undefined/api/store#carts_getcartsid) -- [POST /store/carts/{id}](undefined/api/store#carts_postcartsid) -- [POST /store/carts/{id}/complete](undefined/api/store#carts_postcartsidcomplete) -- [POST /store/carts/{id}/customer](undefined/api/store#carts_postcartsidcustomer) -- [POST /store/carts/{id}/gift-cards](undefined/api/store#carts_postcartsidgiftcards) -- [DELETE /store/carts/{id}/gift-cards](undefined/api/store#carts_deletecartsidgiftcards) -- [POST /store/carts/{id}/line-items](undefined/api/store#carts_postcartsidlineitems) -- [POST /store/carts/{id}/line-items/{line_id}](undefined/api/store#carts_postcartsidlineitemsline_id) -- [DELETE /store/carts/{id}/line-items/{line_id}](undefined/api/store#carts_deletecartsidlineitemsline_id) -- [POST /store/carts/{id}/promotions](undefined/api/store#carts_postcartsidpromotions) -- [DELETE /store/carts/{id}/promotions](undefined/api/store#carts_deletecartsidpromotions) -- [POST /store/carts/{id}/shipping-methods](undefined/api/store#carts_postcartsidshippingmethods) -- [POST /store/carts/{id}/store-credits](undefined/api/store#carts_postcartsidstorecredits) -- [POST /store/carts/{id}/taxes](undefined/api/store#carts_postcartsidtaxes) -- [GET /store/collections](undefined/api/store#collections_getcollections) -- [GET /store/collections/{id}](undefined/api/store#collections_getcollectionsid) -- [GET /store/currencies](undefined/api/store#currencies_getcurrencies) -- [GET /store/currencies/{code}](undefined/api/store#currencies_getcurrenciescode) -- [POST /store/customers](undefined/api/store#customers_postcustomers) -- [GET /store/customers/me](undefined/api/store#customers_getcustomersme) -- [POST /store/customers/me](undefined/api/store#customers_postcustomersme) -- [GET /store/customers/me/addresses](undefined/api/store#customers_getcustomersmeaddresses) -- [POST /store/customers/me/addresses](undefined/api/store#customers_postcustomersmeaddresses) -- [GET /store/customers/me/addresses/{address_id}](undefined/api/store#customers_getcustomersmeaddressesaddress_id) -- [POST /store/customers/me/addresses/{address_id}](undefined/api/store#customers_postcustomersmeaddressesaddress_id) -- [DELETE /store/customers/me/addresses/{address_id}](undefined/api/store#customers_deletecustomersmeaddressesaddress_id) -- [GET /store/gift-cards/{idOrCode}](undefined/api/store#gift-cards_getgiftcardsidorcode) -- [POST /store/gift-cards/{idOrCode}/redeem](undefined/api/store#gift-cards_postgiftcardsidorcoderedeem) -- [GET /store/orders](undefined/api/store#orders_getorders) -- [GET /store/orders/{id}](undefined/api/store#orders_getordersid) -- [POST /store/orders/{id}/transfer/accept](undefined/api/store#orders_postordersidtransferaccept) -- [POST /store/orders/{id}/transfer/cancel](undefined/api/store#orders_postordersidtransfercancel) -- [POST /store/orders/{id}/transfer/decline](undefined/api/store#orders_postordersidtransferdecline) -- [POST /store/orders/{id}/transfer/request](undefined/api/store#orders_postordersidtransferrequest) -- [POST /store/payment-collections](undefined/api/store#payment-collections_postpaymentcollections) -- [POST /store/payment-collections/{id}/payment-sessions](undefined/api/store#payment-collections_postpaymentcollectionsidpaymentsessions) -- [GET /store/payment-providers](undefined/api/store#payment-providers_getpaymentproviders) -- [GET /store/product-categories](undefined/api/store#product-categories_getproductcategories) -- [GET /store/product-categories/{id}](undefined/api/store#product-categories_getproductcategoriesid) -- [GET /store/product-tags](undefined/api/store#product-tags_getproducttags) -- [GET /store/product-tags/{id}](undefined/api/store#product-tags_getproducttagsid) -- [GET /store/product-types](undefined/api/store#product-types_getproducttypes) -- [GET /store/product-types/{id}](undefined/api/store#product-types_getproducttypesid) -- [GET /store/products](undefined/api/store#products_getproducts) -- [GET /store/products/{id}](undefined/api/store#products_getproductsid) -- [GET /store/regions](undefined/api/store#regions_getregions) -- [GET /store/regions/{id}](undefined/api/store#regions_getregionsid) -- [GET /store/return-reasons](undefined/api/store#return-reasons_getreturnreasons) -- [GET /store/return-reasons/{id}](undefined/api/store#return-reasons_getreturnreasonsid) -- [POST /store/returns](undefined/api/store#returns_postreturns) -- [GET /store/shipping-options](undefined/api/store#shipping-options_getshippingoptions) -- [POST /store/shipping-options/{id}/calculate](undefined/api/store#shipping-options_postshippingoptionsidcalculate) -- [GET /store/store-credit-accounts](undefined/api/store#store-credit-accounts_getstorecreditaccounts) -- [GET /store/store-credit-accounts/{id}](undefined/api/store#store-credit-accounts_getstorecreditaccountsid) +- [POST /auth/customer/{auth_provider}](https://docs.medusajs.com/api/store#auth_postactor_typeauth_provider) +- [POST /auth/customer/{auth_provider}/callback](https://docs.medusajs.com/api/store#auth_postactor_typeauth_providercallback) +- [POST /auth/customer/{auth_provider}/register](https://docs.medusajs.com/api/store#auth_postactor_typeauth_provider_register) +- [POST /auth/customer/{auth_provider}/reset-password](https://docs.medusajs.com/api/store#auth_postactor_typeauth_providerresetpassword) +- [POST /auth/customer/{auth_provider}/update](https://docs.medusajs.com/api/store#auth_postactor_typeauth_providerupdate) +- [POST /auth/session](https://docs.medusajs.com/api/store#auth_postsession) +- [DELETE /auth/session](https://docs.medusajs.com/api/store#auth_deletesession) +- [POST /auth/token/refresh](https://docs.medusajs.com/api/store#auth_postadminauthtokenrefresh) +- [POST /store/carts](https://docs.medusajs.com/api/store#carts_postcarts) +- [GET /store/carts/{id}](https://docs.medusajs.com/api/store#carts_getcartsid) +- [POST /store/carts/{id}](https://docs.medusajs.com/api/store#carts_postcartsid) +- [POST /store/carts/{id}/complete](https://docs.medusajs.com/api/store#carts_postcartsidcomplete) +- [POST /store/carts/{id}/customer](https://docs.medusajs.com/api/store#carts_postcartsidcustomer) +- [POST /store/carts/{id}/gift-cards](https://docs.medusajs.com/api/store#carts_postcartsidgiftcards) +- [DELETE /store/carts/{id}/gift-cards](https://docs.medusajs.com/api/store#carts_deletecartsidgiftcards) +- [POST /store/carts/{id}/line-items](https://docs.medusajs.com/api/store#carts_postcartsidlineitems) +- [POST /store/carts/{id}/line-items/{line_id}](https://docs.medusajs.com/api/store#carts_postcartsidlineitemsline_id) +- [DELETE /store/carts/{id}/line-items/{line_id}](https://docs.medusajs.com/api/store#carts_deletecartsidlineitemsline_id) +- [POST /store/carts/{id}/promotions](https://docs.medusajs.com/api/store#carts_postcartsidpromotions) +- [DELETE /store/carts/{id}/promotions](https://docs.medusajs.com/api/store#carts_deletecartsidpromotions) +- [POST /store/carts/{id}/shipping-methods](https://docs.medusajs.com/api/store#carts_postcartsidshippingmethods) +- [POST /store/carts/{id}/store-credits](https://docs.medusajs.com/api/store#carts_postcartsidstorecredits) +- [POST /store/carts/{id}/taxes](https://docs.medusajs.com/api/store#carts_postcartsidtaxes) +- [GET /store/collections](https://docs.medusajs.com/api/store#collections_getcollections) +- [GET /store/collections/{id}](https://docs.medusajs.com/api/store#collections_getcollectionsid) +- [GET /store/currencies](https://docs.medusajs.com/api/store#currencies_getcurrencies) +- [GET /store/currencies/{code}](https://docs.medusajs.com/api/store#currencies_getcurrenciescode) +- [POST /store/customers](https://docs.medusajs.com/api/store#customers_postcustomers) +- [GET /store/customers/me](https://docs.medusajs.com/api/store#customers_getcustomersme) +- [POST /store/customers/me](https://docs.medusajs.com/api/store#customers_postcustomersme) +- [GET /store/customers/me/addresses](https://docs.medusajs.com/api/store#customers_getcustomersmeaddresses) +- [POST /store/customers/me/addresses](https://docs.medusajs.com/api/store#customers_postcustomersmeaddresses) +- [GET /store/customers/me/addresses/{address_id}](https://docs.medusajs.com/api/store#customers_getcustomersmeaddressesaddress_id) +- [POST /store/customers/me/addresses/{address_id}](https://docs.medusajs.com/api/store#customers_postcustomersmeaddressesaddress_id) +- [DELETE /store/customers/me/addresses/{address_id}](https://docs.medusajs.com/api/store#customers_deletecustomersmeaddressesaddress_id) +- [GET /store/gift-cards/{idOrCode}](https://docs.medusajs.com/api/store#gift-cards_getgiftcardsidorcode) +- [POST /store/gift-cards/{idOrCode}/redeem](https://docs.medusajs.com/api/store#gift-cards_postgiftcardsidorcoderedeem) +- [GET /store/orders](https://docs.medusajs.com/api/store#orders_getorders) +- [GET /store/orders/{id}](https://docs.medusajs.com/api/store#orders_getordersid) +- [POST /store/orders/{id}/transfer/accept](https://docs.medusajs.com/api/store#orders_postordersidtransferaccept) +- [POST /store/orders/{id}/transfer/cancel](https://docs.medusajs.com/api/store#orders_postordersidtransfercancel) +- [POST /store/orders/{id}/transfer/decline](https://docs.medusajs.com/api/store#orders_postordersidtransferdecline) +- [POST /store/orders/{id}/transfer/request](https://docs.medusajs.com/api/store#orders_postordersidtransferrequest) +- [POST /store/payment-collections](https://docs.medusajs.com/api/store#payment-collections_postpaymentcollections) +- [POST /store/payment-collections/{id}/payment-sessions](https://docs.medusajs.com/api/store#payment-collections_postpaymentcollectionsidpaymentsessions) +- [GET /store/payment-providers](https://docs.medusajs.com/api/store#payment-providers_getpaymentproviders) +- [GET /store/product-categories](https://docs.medusajs.com/api/store#product-categories_getproductcategories) +- [GET /store/product-categories/{id}](https://docs.medusajs.com/api/store#product-categories_getproductcategoriesid) +- [GET /store/product-tags](https://docs.medusajs.com/api/store#product-tags_getproducttags) +- [GET /store/product-tags/{id}](https://docs.medusajs.com/api/store#product-tags_getproducttagsid) +- [GET /store/product-types](https://docs.medusajs.com/api/store#product-types_getproducttypes) +- [GET /store/product-types/{id}](https://docs.medusajs.com/api/store#product-types_getproducttypesid) +- [GET /store/products](https://docs.medusajs.com/api/store#products_getproducts) +- [GET /store/products/{id}](https://docs.medusajs.com/api/store#products_getproductsid) +- [GET /store/regions](https://docs.medusajs.com/api/store#regions_getregions) +- [GET /store/regions/{id}](https://docs.medusajs.com/api/store#regions_getregionsid) +- [GET /store/return-reasons](https://docs.medusajs.com/api/store#return-reasons_getreturnreasons) +- [GET /store/return-reasons/{id}](https://docs.medusajs.com/api/store#return-reasons_getreturnreasonsid) +- [POST /store/returns](https://docs.medusajs.com/api/store#returns_postreturns) +- [GET /store/shipping-options](https://docs.medusajs.com/api/store#shipping-options_getshippingoptions) +- [POST /store/shipping-options/{id}/calculate](https://docs.medusajs.com/api/store#shipping-options_postshippingoptionsidcalculate) +- [GET /store/store-credit-accounts](https://docs.medusajs.com/api/store#store-credit-accounts_getstorecreditaccounts) +- [GET /store/store-credit-accounts/{id}](https://docs.medusajs.com/api/store#store-credit-accounts_getstorecreditaccountsid) # Alert @@ -103229,7 +104420,7 @@ This component is based on the \`div\` element and supports all of its props ## Usage Outside Medusa Admin -If you're using the `CodeBlock` component in a project other than the Medusa Admin, make sure to include the `TooltipProvider` somewhere up in your component tree, as the `CodeBlock.Header` component uses a [Tooltip](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/ui/app/components/tooltip#usage-outside-medusa-admin): +If you're using the `CodeBlock` component in a project other than the Medusa Admin, make sure to include the `TooltipProvider` somewhere up in your component tree, as the `CodeBlock.Header` component uses a [Tooltip](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/ui/app/components/tooltip#usage-outside-medusa-admin/index.html.md): ```tsx @@ -103545,7 +104736,7 @@ This component is based on the div element and supports all of its props ## Usage Outside Medusa Admin -If you're using the `Command` component in a project other than the Medusa Admin, make sure to include the `TooltipProvider` somewhere up in your component tree, as the `Command.Copy` component uses a [Tooltip](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/ui/app/components/tooltip#usage-outside-medusa-admin): +If you're using the `Command` component in a project other than the Medusa Admin, make sure to include the `TooltipProvider` somewhere up in your component tree, as the `Command.Copy` component uses a [Tooltip](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/ui/app/components/tooltip#usage-outside-medusa-admin/index.html.md): ```tsx @@ -103670,7 +104861,7 @@ This component is based on the \`button\` element and supports all of its props ## Usage Outside Medusa Admin -If you're using the `Copy` component in a project other than the Medusa Admin, make sure to include the `TooltipProvider` somewhere up in your component tree, as the `Copy` component uses a [Tooltip](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/ui/app/components/tooltip#usage-outside-medusa-admin): +If you're using the `Copy` component in a project other than the Medusa Admin, make sure to include the `TooltipProvider` somewhere up in your component tree, as the `Copy` component uses a [Tooltip](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/ui/app/components/tooltip#usage-outside-medusa-admin/index.html.md): ```tsx @@ -103901,7 +105092,7 @@ In this guide, you'll learn how to use the DataTable component. The `DataTable` component is useful if you're displaying large data with functionalities like pagination, filtering, sorting, and searching. It's also the recommended table component to use when creating customizations in the Medusa Admin. -This component is available after Medusa UI v4.0.4 (or Medusa v2.4.0). It is built on top of the [Table](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/ui/app/components/table) component. If you want a table with more control over its styling and functionality, use that component instead. +This component is available after Medusa UI v4.0.4 (or Medusa v2.4.0). It is built on top of the [Table](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/ui/app/components/table/index.html.md) component. If you want a table with more control over its styling and functionality, use that component instead. ```tsx import { createDataTableColumnHelper, useDataTable, DataTable, Heading } from "@medusajs/ui" @@ -108158,7 +109349,7 @@ export default function ProgressTabsDisabled() { A component that displays a dialog prompting the user for their approval. It's useful when confirming destructive actions. -This component is useful if you want to control the prompt's content, format, and design. For a simpler approach that follows Medusa's prompt format, refer to the [usePrompt hook](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/ui/app/hooks/use-prompt). +This component is useful if you want to control the prompt's content, format, and design. For a simpler approach that follows Medusa's prompt format, refer to the [usePrompt hook](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/ui/app/hooks/use-prompt/index.html.md). In this guide, you'll learn how to use the Prompt component. @@ -109032,7 +110223,7 @@ A component that displays data in a structured table format. In this guide, you'll learn how to use the Table component. -If you're looking to add a table to your Medusa Admin customizations with advanced features like filters, search, sorting, and bulk actions, refer to the [DataTable](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/ui/app/components/data-table) component instead. +If you're looking to add a table to your Medusa Admin customizations with advanced features like filters, search, sorting, and bulk actions, refer to the [DataTable](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/ui/app/components/data-table/index.html.md) component instead. ```tsx import { Table } from "@medusajs/ui" @@ -110206,7 +111397,7 @@ export const config = defineRouteConfig({ export default CustomPage ``` -In this example, you use the [Container](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/ui/app/components/container) and [Heading](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/ui/app/components/heading) components in the UI route. You also use the `ChatBubbleLeftRight` icon from the [Icons package](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/ui/app/icons/overview) for the UI route's sidebar item. +In this example, you use the [Container](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/ui/app/components/container/index.html.md) and [Heading](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/ui/app/components/heading/index.html.md) components in the UI route. You also use the `ChatBubbleLeftRight` icon from the [Icons package](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/ui/app/icons/overview/index.html.md) for the UI route's sidebar item. *** @@ -110214,9 +111405,9 @@ In this example, you use the [Container](undefined/Users/ters/Desktop/personal/f If you're building Medusa Admin customizations, check out the following documentation guides: -- [Admin Widgets](undefined/docs/learn/fundamentals/admin/widgets): Insert custom components into existing Medusa Admin pages. -- [Admin UI Routes](undefined/docs/learn/fundamentals/admin/ui-routes): Add new pages to the Medusa Admin. -- [Admin Components & Layouts](undefined/resources/admin-components): Use Medusa UI to implement common Medusa Admin components and layouts for a consistent design in your customizations. +- [Admin Widgets](https://docs.medusajs.com/docs/learn/fundamentals/admin/widgets/index.html.md): Insert custom components into existing Medusa Admin pages. +- [Admin UI Routes](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md): Add new pages to the Medusa Admin. +- [Admin Components & Layouts](https://docs.medusajs.com/resources/admin-components/index.html.md): Use Medusa UI to implement common Medusa Admin components and layouts for a consistent design in your customizations. # Install Medusa UI in Standalone Projects @@ -110225,7 +111416,7 @@ In this guide, you'll learn how to install and use Medusa UI in a standalone pro Medusa UI is a React UI library that, while intended for use within Medusa projects, can also be used in any React project. -The icons package is installed independently from Medusa UI. Learn how to install it in the [Icons](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/ui/app/icons/overview) guide. +The icons package is installed independently from Medusa UI. Learn how to install it in the [Icons](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/ui/app/icons/overview/index.html.md) guide. *** @@ -110363,10 +111554,10 @@ The page you were looking for isn't available. If you think this is a mistake, please [report this issue on GitHub](https://github.com/medusajs/medusa/issues/new?assignees=\&labels=type%3A+docs\&template=docs.yml). -- [Get Started Docs](undefined/) -- [Commerce Modules](undefined/resources/commerce-modules) -- [Admin API reference](undefined/api/admin) -- [Store API reference](undefined/api/store) +- [Get Started Docs](https://docs.medusajs.com//index.html.md) +- [Commerce Modules](https://docs.medusajs.com/resources/commerce-modules/index.html.md) +- [Admin API reference](https://docs.medusajs.com/api/admin) +- [Store API reference](https://docs.medusajs.com/api/store) # Medusa UI Documentation @@ -110395,7 +111586,7 @@ and can be installed separately. used in Medusa UI. - `@medusajs/icons` - Icons used in Medusa UI. -Learn how to install and use these packages either for [Medusa Admin](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/ui/app/installation/medusa-admin-extension) customizations or a [standalone project](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/ui/app/installation/standalone-project). +Learn how to install and use these packages either for [Medusa Admin](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/ui/app/installation/medusa-admin-extension/index.html.md) customizations or a [standalone project](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/ui/app/installation/standalone-project/index.html.md). *** @@ -110511,7 +111702,7 @@ Medusa has a ready-to-use B2B starter that you install and use in [this GitHub r In a B2B store, you provide different types of customers with relevant pricing, products, shopping experience, and more. -Medusa’s Commerce Modules, including [Sales Channel](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/sales-channel), [Customer](../../commerce-modules/), and [Pricing](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing) modules enable this setup out-of-the-box: +Medusa’s Commerce Modules, including [Sales Channel](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/sales-channel/index.html.md), [Customer](../../commerce-modules/), and [Pricing](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/index.html.md) modules enable this setup out-of-the-box: - **Sales Channel**: Use sales channels to set product availability per channel. In this case, create a B2B sales channel that includes only B2B products. - **Customer**: Use customer groups to organize your customers into different groups. Then, you can apply different prices for each group. @@ -110531,8 +111722,8 @@ Then, on the storefront, you retrieve only the B2B products for B2B customers, w You can create a sales channel through the Medusa Admin or Admin REST APIs. -- [Using Medusa Admin](undefined/user-guide/settings/sales-channels): Create the sales channel using the Medusa Admin. -- [Using Admin API](undefined/api/admin#sales-channels_postsaleschannels): Create the sales channel using the REST APIs. +- [Using Medusa Admin](https://docs.medusajs.com/user-guide/settings/sales-channels/index.html.md): Create the sales channel using the Medusa Admin. +- [Using Admin API](https://docs.medusajs.com/api/admin#sales-channels_postsaleschannels): Create the sales channel using the REST APIs. *** @@ -110549,13 +111740,13 @@ You can create a publishable API key through the Medusa Admin or the Admin REST ### Create Publishable API Key -- [Using Medusa Admin](undefined/user-guide/settings/developer/publishable-api-keys): Create the API key using the Medusa Admin. -- [Using Admin API](undefined/api/admin#api-keys_postapikeys): Create the API key using the REST APIs. +- [Using Medusa Admin](https://docs.medusajs.com/user-guide/settings/developer/publishable-api-keys/index.html.md): Create the API key using the Medusa Admin. +- [Using Admin API](https://docs.medusajs.com/api/admin#api-keys_postapikeys): Create the API key using the REST APIs. ### Associate Key with Sales Channel -- [Using Medusa Admin](undefined/user-guide/settings/developer/publishable-api-keys#manage-publishable-api-keys-sales-channels): Associate the key with the sales channel using the Medusa Admin. -- [Using Admin API](undefined/api/admin#api-keys_postapikeysidsaleschannels): Associate the key with the sales channel using the REST APIs. +- [Using Medusa Admin](https://docs.medusajs.com/user-guide/settings/developer/publishable-api-keys#manage-publishable-api-keys-sales-channels/index.html.md): Associate the key with the sales channel using the Medusa Admin. +- [Using Admin API](https://docs.medusajs.com/api/admin#api-keys_postapikeysidsaleschannels): Associate the key with the sales channel using the REST APIs. *** @@ -110567,13 +111758,13 @@ You can create new products or add existing ones to the B2B sales channel using ### Create Products -- [Using Medusa Admin](undefined/user-guide/products/create): Create the products using the Medusa Admin. -- [Using Admin API](undefined/api/admin#products_postproducts): Create the products using the REST APIs. +- [Using Medusa Admin](https://docs.medusajs.com/user-guide/products/create/index.html.md): Create the products using the Medusa Admin. +- [Using Admin API](https://docs.medusajs.com/api/admin#products_postproducts): Create the products using the REST APIs. ### Add Products to Sales Channel -- [Using Medusa Admin](undefined/user-guide/settings/sales-channels#manage-products-in-sales-channel): Create the products using the Medusa Admin. -- [Using Admin API](undefined/api/admin#sales-channels_postsaleschannelsidproductsbatchadd): Add the products to the sales channel using the REST APIs. +- [Using Medusa Admin](https://docs.medusajs.com/user-guide/settings/sales-channels#manage-products-in-sales-channel/index.html.md): Create the products using the Medusa Admin. +- [Using Admin API](https://docs.medusajs.com/api/admin#sales-channels_postsaleschannelsidproductsbatchadd): Add the products to the sales channel using the REST APIs. *** @@ -110587,13 +111778,13 @@ You can create a customer group for each B2B company, then add customers of that ### Create Customers -- [Using Medusa Admin](undefined/user-guide/customers/manage): Create customers using the Medusa Admin. -- [Using Admin API](undefined/api/admin#customers_postcustomers): Create customers using the REST APIs. +- [Using Medusa Admin](https://docs.medusajs.com/user-guide/customers/manage/index.html.md): Create customers using the Medusa Admin. +- [Using Admin API](https://docs.medusajs.com/api/admin#customers_postcustomers): Create customers using the REST APIs. ### Assign Customers to Groups -- [Using Medusa Admin](undefined/user-guide/customers/manage#manage-customers-groups): Assign customer to groups using the Medusa Admin. -- [Using Admin API](undefined/api/admin#customer-groups_postcustomergroupsidcustomersbatch): Assign customer to groups using the REST APIs. +- [Using Medusa Admin](https://docs.medusajs.com/user-guide/customers/manage#manage-customers-groups/index.html.md): Assign customer to groups using the Medusa Admin. +- [Using Admin API](https://docs.medusajs.com/api/admin#customer-groups_postcustomergroupsidcustomersbatch): Assign customer to groups using the REST APIs. ### Flexible Customizations: Create Custom Module @@ -110603,8 +111794,8 @@ For more complex use cases, you can create a custom module that introduces data Then, you can link those companies to existing customers and groups, allowing you to benefit from existing features like price lists for specific customer groups. -- [Create Module](undefined/docs/learn/fundamentals/modules): Learn how to create a module. -- [Define Module Links](undefined/docs/learn/fundamentals/module-links): Define links between data models. +- [Create Module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md): Learn how to create a module. +- [Define Module Links](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md): Define links between data models. *** @@ -110616,8 +111807,8 @@ For B2B use cases, you can use price lists to set different prices for each B2B You can create a price list using the Medusa Admin or the Admin REST APIs. Make sure to set the B2B customer group(s) as a condition. -- [Using Medusa Admin](undefined/user-guide/price-lists/create): Create price list using the Medusa Admin. -- [Using Admin API](undefined/api/admin#price-lists_postpricelists): Create price list using the REST APIs. +- [Using Medusa Admin](https://docs.medusajs.com/user-guide/price-lists/create/index.html.md): Create price list using the Medusa Admin. +- [Using Admin API](https://docs.medusajs.com/api/admin#price-lists_postpricelists): Create price list using the REST APIs. *** @@ -110633,10 +111824,10 @@ The Medusa Admin is an extensible application within your Medusa application. Yo - **UI Routes**: Adding new pages to the Medusa Admin, such as a page to manage companies and employees. - **Settings Pages**: Adding new pages to the Medusa Admin settings, such as a page to manage company settings. -- [Create Admin Widget](undefined/docs/learn/fundamentals/admin/widgets): Add widgets into existing admin pages. -- [Create Admin UI Routes](undefined/docs/learn/fundamentals/admin/ui-routes): Add new pages to your Medusa Admin. +- [Create Admin Widget](https://docs.medusajs.com/docs/learn/fundamentals/admin/widgets/index.html.md): Add widgets into existing admin pages. +- [Create Admin UI Routes](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md): Add new pages to your Medusa Admin. -[Create Admin Setting Page](undefined/docs/learn/fundamentals/admin/ui-routes#create-settings-page): Add new page to the Medusa Admin settings. +[Create Admin Setting Page](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes#create-settings-page/index.html.md): Add new page to the Medusa Admin settings. *** @@ -110648,19 +111839,19 @@ Alternatively, you can build your own storefront using the Medusa APIs. This hea In your storefront, you can use the publishable API key you associated with your B2B sales channel to ensure only B2B products are retrieved. -- [Next.js Starter Storefront](undefined/nextjs-starter): Learn how to install and customize the Next.js Starter Storefront. -- [Storefront Development](undefined/storefront-development): Find guides to build your own storefront. +- [Next.js Starter Storefront](https://docs.medusajs.com/nextjs-starter/index.html.md): Learn how to install and customize the Next.js Starter Storefront. +- [Storefront Development](https://docs.medusajs.com/storefront-development/index.html.md): Find guides to build your own storefront. -[Use Publishable API Keys](undefined/api/store#publishable-api-key): Learn how to use the publishable API key in client requests. +[Use Publishable API Keys](https://docs.medusajs.com/api/store#publishable-api-key): Learn how to use the publishable API key in client requests. # Implement Bundled Products in Medusa In this tutorial, you'll learn how to implement bundled products in Medusa. -When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules), which are available out-of-the-box. +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md), which are available out-of-the-box. -Medusa natively supports [inventory kits](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/inventory/inventory-kit), which can be used to create bundled products. However, inventory kits don't support all features of bundled products, such as fulfilling the products in the bundle separately. +Medusa natively supports [inventory kits](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/inventory/inventory-kit/index.html.md), which can be used to create bundled products. However, inventory kits don't support all features of bundled products, such as fulfilling the products in the bundle separately. In this tutorial, you'll use Medusa's customizable Framework to implement bundled products. By building the bundled products feature, you can expand on it based on what's necessary for your use case. @@ -110697,27 +111888,27 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose Yes. +You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose Yes. Afterward, the installation process will start, which will install the Medusa application in a directory with your project's name, and the Next.js Starter Storefront in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterward, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** ## Step 2: Create Bundled Product Module -In Medusa, you can build custom features in a [module](undefined/docs/learn/fundamentals/modules). A module is a reusable package with functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. +In Medusa, you can build custom features in a [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). A module is a reusable package with functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. In the module, you define the data models necessary for a feature and the logic to manage these data models. Later, you can build commerce flows around your module. In this step, you'll build a Bundled Product Module that defines the necessary data models to store and manage bundled products. -Refer to the [Modules documentation](undefined/docs/learn/fundamentals/modules) to learn more. +Refer to the [Modules documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) to learn more. ### Create Module Directory @@ -110727,7 +111918,7 @@ Modules are created under the `src/modules` directory of your Medusa application A data model represents a table in the database. You create data models using Medusa's Data Model Language (DML). It simplifies defining a table's columns, relations, and indexes with straightforward methods and configurations. -Refer to the [Data Models documentation](undefined/docs/learn/fundamentals/modules#1-create-data-model) to learn more. +Refer to the [Data Models documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#1-create-data-model/index.html.md) to learn more. For the Bundled Product Module, you need to define two data models: @@ -110757,7 +111948,7 @@ The `Bundle` data model has the following properties: - `title`: The bundle's title. - `items`: A one-to-many relation to the `BundleItem` data model, which you'll create next. -Learn more about defining data model properties in the [Property Types documentation](undefined/docs/learn/fundamentals/data-models/properties). +Learn more about defining data model properties in the [Property Types documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/properties/index.html.md). To create the `BundleItem` data model, create the file `src/modules/bundled-product/models/bundle-item.ts` with the following content: @@ -110780,7 +111971,7 @@ The `BundleItem` data model has the following properties: - `quantity`: The quantity of the item in the bundle. It defaults to `1`. - `bundle`: A many-to-one relation to the `Bundle` data model, which you defined earlier. -Learn more about defining data model relations in the [Relations documentation](undefined/docs/learn/fundamentals/data-models/relationships). +Learn more about defining data model relations in the [Relations documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/relationships/index.html.md). ### Create Module's Service @@ -110788,7 +111979,7 @@ You now have the necessary data models in the Bundled Product Module, but you'll A service is a TypeScript or JavaScript class that the module exports. In the service's methods, you can connect to the database, allowing you to manage your data models, or connect to a third-party service, which is useful if you're integrating with external services. -Refer to the [Module Service documentation](undefined/docs/learn/fundamentals/modules#2-create-service) to learn more. +Refer to the [Module Service documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#2-create-service/index.html.md) to learn more. To create the Bundled Product Module's service, create the file `src/modules/bundled-product/service.ts` with the following content: @@ -110808,7 +111999,7 @@ The `BundledProductModuleService` extends `MedusaService` from the Modules SDK w So, the `BundledProductModuleService` class now has methods like `createBundles` and `retrieveBundleItem`. -Find all methods generated by the `MedusaService` in [the Service Factory reference](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference). +Find all methods generated by the `MedusaService` in [the Service Factory reference](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/index.html.md). ### Export Module Definition @@ -110857,7 +112048,7 @@ Each object in the `modules` array has a `resolve` property, whose value is eith Since data models represent tables in the database, you define how they're created in the database with migrations. A migration is a TypeScript or JavaScript file that defines database changes made by a module. -Refer to the [Migrations documentation](undefined/docs/learn/fundamentals/modules#5-generate-migrations) to learn more. +Refer to the [Migrations documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#5-generate-migrations/index.html.md) to learn more. Medusa's CLI tool can generate the migrations for you. To generate a migration for the Bundled Product Module, run the following command in your Medusa application's directory: @@ -110883,14 +112074,14 @@ Medusa integrates modules into your application without implications or side eff Instead, Medusa provides the mechanism to define links between data models, and retrieve and manage linked records while maintaining module isolation. Links are useful to define associations between data models in different modules, or extend a model in another module to associate custom properties with it. -Refer to the [Module Isolation documentation](undefined/docs/learn/fundamentals/modules/isolation) to learn more. +Refer to the [Module Isolation documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md) to learn more. In this step, you'll define a link between: - The `Bundle` data model in the Bundled Product Module and the `Product` data model in the Products Module. This link will allow you to benefit from existing product features, like prices, sales channels, and more. - The `BundleItem` data model in the Bundled Product Module and the `Product` data model in the Products Module. This link will allow you to associate a bundle item with an existing product, where the customer chooses from their variants when purchasing the bundle. -Refer to the [Product Module's data models reference](undefined/references/product/models) to learn more about available data models in the Products Module. +Refer to the [Product Module's data models reference](https://docs.medusajs.com/references/product/models/index.html.md) to learn more about available data models in the Products Module. ### Bundle \<> Product Link @@ -110946,7 +112137,7 @@ npx medusa db:migrate This will create tables for both links in the database. The tables will later store the IDs of the linked records. -Refer to the [Module Links](undefined/docs/learn/fundamentals/module-links) documentation to learn more about defining links and link tables. +Refer to the [Module Links](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md) documentation to learn more about defining links and link tables. *** @@ -110954,20 +112145,20 @@ Refer to the [Module Links](undefined/docs/learn/fundamentals/module-links) docu You're now ready to start implementing bundled-product features. The first one you'll implement is the ability to create a bundled product. -To build custom commerce features in Medusa, you create a [workflow](undefined/docs/learn/fundamentals/workflows). A workflow is a series of queries and actions, called steps, that complete a task. By using workflows, you can track their executions' progress, define roll-back logic, and configure other advanced features. +To build custom commerce features in Medusa, you create a [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). A workflow is a series of queries and actions, called steps, that complete a task. By using workflows, you can track their executions' progress, define roll-back logic, and configure other advanced features. So, in this section, you'll learn how to create a workflow that creates a bundled product. Later, you'll execute this workflow in an API route. -Learn more about workflows in the [Workflows documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about workflows in the [Workflows documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). The workflow will have the following steps: - [createBundleStep](#createBundleStep): Create a bundle - [createBundleItemStep](#createBundleItemStep): Create the bundle items -- [createProductsWorkflow](undefined/references/medusa-workflows/createProductsWorkflow): Create the Medusa product associated with the bundle -- [createRemoteLinkStep](undefined/references/helper-steps/createRemoteLinkStep): Create the link between the bundle and the Medusa product -- [createRemoteLinkStep](undefined/references/helper-steps/createRemoteLinkStep): Create the link between the bundle items and the Medusa products -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the created bundle and its items. +- [createProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createProductsWorkflow/index.html.md): Create the Medusa product associated with the bundle +- [createRemoteLinkStep](https://docs.medusajs.com/references/helper-steps/createRemoteLinkStep/index.html.md): Create the link between the bundle and the Medusa product +- [createRemoteLinkStep](https://docs.medusajs.com/references/helper-steps/createRemoteLinkStep/index.html.md): Create the link between the bundle items and the Medusa products +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the created bundle and its items. You only need to implement the first two steps, as Medusa provides the rest in its `@medusajs/medusa/core-flows` package. @@ -111015,7 +112206,7 @@ You create a step with `createStep` from the Workflows SDK. It accepts two param 1. The step's unique name, which is `create-bundle`. 2. An async function that receives two parameters: - The step's input, which is in this case an object with the bundle's properties. - - An object that has properties including the [Medusa container](undefined/docs/learn/fundamentals/medusa-container), which is a registry of Framework and commerce tools that you can access in the step. + - An object that has properties including the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which is a registry of Framework and commerce tools that you can access in the step. In the step function, you resolve the Bundled Product Module's service from the Medusa container using its `resolve` method, passing it the module's name as a parameter. @@ -111026,7 +112217,7 @@ A step function must return a `StepResponse` instance. The `StepResponse` constr 1. The step's output, which is the bundle created. 2. Data to pass to the step's compensation function. -Learn more about creating a step in the [Workflow documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about creating a step in the [Workflow documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). #### Compensation Function @@ -111035,11 +112226,11 @@ The compensation function undoes the actions performed in a step. Then, if an er The compensation function accepts two parameters: 1. The data passed from the step in the second parameter of `StepResponse`, which in this case is the ID of the created bundle. -2. An object that has properties including the [Medusa container](undefined/docs/learn/fundamentals/medusa-container). +2. An object that has properties including the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). In the compensation function, you resolve the Bundled Product Module's service from the Medusa container and call the `deleteBundles` method to delete the bundle created in the step. -Refer to the [Compensation Function documentation](undefined/docs/learn/fundamentals/workflows/compensation-function) to learn more. +Refer to the [Compensation Function documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/compensation-function/index.html.md) to learn more. ### createBundleItemStep @@ -111190,10 +112381,10 @@ In the workflow's constructor function, you: 4. Create a link between the bundle and the Medusa product using the `createRemoteLinkStep`. - To create a link, you pass an array of objects. The keys of each object are the module names, and the values are objects with the IDs of the records to link. 5. Use `transform` to prepare the data to link bundle items to products. - - You must use the `transform` function whenever you want to manipulate data in a workflow, as Medusa creates an internal representation of the workflow when the application starts, not when the workflow is executed. Learn more in the [Transform Data documentation](undefined/docs/learn/fundamentals/workflows/variable-manipulation). + - You must use the `transform` function whenever you want to manipulate data in a workflow, as Medusa creates an internal representation of the workflow when the application starts, not when the workflow is executed. Learn more in the [Transform Data documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/variable-manipulation/index.html.md). 6. Create a link between the bundle items and the Medusa products using the `createRemoteLinkStep`. 7. Retrieve the bundle and its items using the `useQueryGraphStep`. - - `useQueryGraphStep` uses [Query](undefined/docs/learn/fundamentals/module-links/query), which allows you to retrieve data across modules. + - `useQueryGraphStep` uses [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), which allows you to retrieve data across modules. A workflow must return an instance of `WorkflowResponse`. The `WorkflowResponse` constructor accepts the workflow's output as a parameter, which is the created bundle. @@ -111203,11 +112394,11 @@ You'll test out this API route in a later step when you customize the Medusa Adm ## Step 5: Create Bundled Product API Route -Now that you have the logic to create a bundled product, you need to expose it so that frontend clients, such as the Medusa Admin, can use it. You do this by creating an [API route](undefined/docs/learn/fundamentals/api-routes). +Now that you have the logic to create a bundled product, you need to expose it so that frontend clients, such as the Medusa Admin, can use it. You do this by creating an [API route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). An API Route is an endpoint that exposes commerce features to external applications and clients, such as admin dashboards or storefronts. You'll create an API route at the path `/admin/bundled-products` that executes the workflow from the previous step. -Refer to the [API Routes documentation](undefined/docs/learn/fundamentals/api-routes) to learn more. +Refer to the [API Routes documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) to learn more. ### Implement API Route @@ -111278,11 +112469,11 @@ Finally, you return the created bundle in the response. ### Add Validation Middleware -Now that you have the API route, you need to enforce validation on requests send to the route. You can do this with a [middleware](undefined/docs/learn/fundamentals/api-routes/middlewares). +Now that you have the API route, you need to enforce validation on requests send to the route. You can do this with a [middleware](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md). A middleware is a function executed when a request is sent to an API Route. It's executed before the route handler. -Learn more in the [Middlewares documentation](undefined/docs/learn/fundamentals/api-routes/middlewares). +Learn more in the [Middlewares documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md). Middlewares are created in the `src/api/middlewares.ts` file. So create the file `src/api/middlewares.ts` with the following content: @@ -111349,7 +112540,7 @@ export async function GET( Since you export a `GET` route handler function, you expose a `GET` API route at `/admin/bundled-products`. -In the route handler, you resolve [Query](undefined/docs/learn/fundamentals/module-links/query) from the Medusa container. Then, you call its `graph` method to retrieve the bundles. +In the route handler, you resolve [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) from the Medusa container. Then, you call its `graph` method to retrieve the bundles. Notice that you pass to `query.graph` the `req.queryConfig` object. This object contains default query configurations related to pagination and the fields to be retrieved. You'll learn how to set the query configurations in a bit. @@ -111410,15 +112601,15 @@ Your API route is now ready for use. You'll test it out in the next step as you Now that you have the necessary routes for admin users to manage and view bundled products, you'll customize the Medusa Admin to allow admin users to use these features. -You can add a new page to the Medusa Admin dashboard using a [UI route](undefined/docs/learn/fundamentals/admin/ui-routes). A UI route is a React component that specifies the content to be shown in a new page in the Medusa Admin dashboard. +You can add a new page to the Medusa Admin dashboard using a [UI route](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md). A UI route is a React component that specifies the content to be shown in a new page in the Medusa Admin dashboard. You'll create a UI route to display the list of bundled products in the Medusa Admin. Later, you'll add a form to create a bundled product. -Learn more in the [UI Routes documentation](undefined/docs/learn/fundamentals/admin/ui-routes). +Learn more in the [UI Routes documentation](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md). ### Initialize JS SDK -Medusa provides a [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk) that you can use to send requests to the Medusa server from any client application, including your Medusa Admin customizations. +Medusa provides a [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md) that you can use to send requests to the Medusa server from any client application, including your Medusa Admin customizations. The JS SDK is installed by default in your Medusa application. To configure it, create the file `src/admin/lib/sdk.ts` with the following content: @@ -111467,7 +112658,7 @@ In a UI route's file, you must export: 1. A React component that defines the page's content. You'll add the content in a bit. 2. A configuration object that indicates the title and icon used in the sidebar for the page. -Next, you'll use the [DataTable](undefined/ui/components/data-table) component from Medusa UI to show the list of bundled products in a table. +Next, you'll use the [DataTable](https://docs.medusajs.com/ui/components/data-table/index.html.md) component from Medusa UI to show the list of bundled products in a table. Add the following before the `BundledProductsPage` component: @@ -111549,7 +112740,7 @@ You define the table's columns using `createDataTableColumnHelper` from Medusa U You also define a `limit` constant that indicates the maximum number of bundles to retrieve in a page. -Learn more about the `createDataTableColumnHelper` function in the [DataTable documentation](undefined/ui/components/data-table#columns-preparation). +Learn more about the `createDataTableColumnHelper` function in the [DataTable documentation](https://docs.medusajs.com/ui/components/data-table#columns-preparation/index.html.md). Next, replace the `BundledProductsPage` with the following implementation: @@ -111797,7 +112988,7 @@ You first define a mutation using the `useMutation` hook from Tanstack Query. Th Then, you define a `handleCreate` function that will be called when the user submits the form. In this function, you: - Create the bundled product using the `createBundledProduct` mutation. You pass it the details of the bundle, its product, and its items. - - Notice that you don't set the prices. You can use custom logic to set the prices, or [set the price](undefined/user-guide/products/variants#edit-product-variant-prices) from the bundle's associated product page. + - Notice that you don't set the prices. You can use custom logic to set the prices, or [set the price](https://docs.medusajs.com/user-guide/products/variants#edit-product-variant-prices/index.html.md) from the bundle's associated product page. - Close the modal and show a success message using the `toast` component from Medusa UI. ### Add Component for Each Item in the Form @@ -111929,7 +113120,7 @@ You define a `BundledProductItem` component that accepts the following props: - `fetchMoreProducts`: The function to fetch more products when the user scrolls to the end of the list. - `hasNextPage`: A boolean indicating whether there are more products to load. -In the component, you render the selector field using the [Select](undefined/ui/components/select) component from Medusa UI. You show the products as options in the select, and update the product ID in the `items` state variable whenever the user selects a product. +In the component, you render the selector field using the [Select](https://docs.medusajs.com/ui/components/select/index.html.md) component from Medusa UI. You show the products as options in the select, and update the product ID in the `items` state variable whenever the user selects a product. You also observe the last option in the list of products using the [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API). This allows you to fetch more products when the user scrolls to the end of the list. @@ -112010,7 +113201,7 @@ return ( ) ``` -You use the [FocusModal](undefined/ui/components/focus-modal) component from Medusa UI to show the form in a modal. The modal is opened when the "Create" button is clicked. +You use the [FocusModal](https://docs.medusajs.com/ui/components/focus-modal/index.html.md) component from Medusa UI to show the form in a modal. The modal is opened when the "Create" button is clicked. In the modal, you show an input field for the bundle title, and you show the list of bundle items using the `BundledProductItem` component. You also add a button to add new items to the bundle. @@ -112076,7 +113267,7 @@ In the associated product's page, you should: - Set the shipping profile the product belongs to. This will allow customers to select the appropriate shipping option for the bundle during checkout. - You can optionally edit other product details, such as the title, description, and images. -Learn more about editing a product in the [User Guide](undefined/user-guide/products/edit) +Learn more about editing a product in the [User Guide](https://docs.medusajs.com/user-guide/products/edit/index.html.md) ![Associated product page](https://res.cloudinary.com/dza7lstvk/image/upload/v1745923661/Medusa%20Resources/Screenshot_2025-04-29_at_1.46.52_PM_iuplxc.png) @@ -112101,10 +113292,10 @@ To implement the add-to-cart logic for bundled products, you will: The add-to-cart workflow for bundled products has the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the details of a bundle, its items, and their products and variants. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the details of a bundle, its items, and their products and variants. - [prepareBundleCartDataStep](#prepareBundleCartDataStep): Validate and prepare the items to be added to the cart. -- [addToCartWorkflow](undefined/references/medusa-workflows/addToCartWorkflow): Add the items in the bundle to the cart. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the details of the cart. +- [addToCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/addToCartWorkflow/index.html.md): Add the items in the bundle to the cart. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the details of the cart. You only need to implement the second step, as the other steps are provided by Medusa's `@medusajs/medusa/core-flows` package. @@ -112436,13 +113627,13 @@ export async function GET( You export a `GET` route handler, which exposes a `GET` API route at `/store/bundle-products/:id`. -In the route handler, you resolve [Query](undefined/docs/learn/fundamentals/module-links/query) from the Medusa container. +In the route handler, you resolve [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) from the Medusa container. Then, you use Query to retrieve the bundle with its items and their products, variants, and options. These are useful to display to the customer the options for each product to select from, which will result in selecting a variant for a bundle item. -To retrieve the correct price for each variant, you also pass a [Query Context](undefined/docs/learn/fundamentals/module-links/query-context) with the region ID and currency code that are passed as query parameters. This ensures that the prices are shown accurately to the customer. +To retrieve the correct price for each variant, you also pass a [Query Context](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query-context/index.html.md) with the region ID and currency code that are passed as query parameters. This ensures that the prices are shown accurately to the customer. -Refer to the [Get Product Variant Prices](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product/guides/price) guide to learn more about how to retrieve the prices of a product variant. +Refer to the [Get Product Variant Prices](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/guides/price/index.html.md) guide to learn more about how to retrieve the prices of a product variant. Finally, you return the bundle's details in the response. @@ -112452,7 +113643,7 @@ You'll use this API route next as you customize the storefront. ## Step 11: Show Bundled Product Details in Storefront -In this step, you'll customize the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter) you installed with the Medusa application to show a bundled product's items. +In this step, you'll customize the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) you installed with the Medusa application to show a bundled product's items. The Next.js Starter Storefront was installed in a separate directory from Medusa. The directory's name is `{your-project}-storefront`. @@ -113032,9 +114223,9 @@ You'll start by creating a workflow that implements the logic to remove a bundle The workflow has the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the details of the cart and its items. -- [deleteLineItemsWorkflow](undefined/references/medusa-workflows/deleteLineItemsWorkflow): Remove the items in the bundle from the cart. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the updated cart. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the details of the cart and its items. +- [deleteLineItemsWorkflow](https://docs.medusajs.com/references/medusa-workflows/deleteLineItemsWorkflow/index.html.md): Remove the items in the bundle from the cart. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the updated cart. Medusa provides all these steps and workflows in its `@medusajs/medusa/core-flows` package. So, you can create the workflow right away. @@ -113279,22 +114470,22 @@ Now that you have a working bundled product feature, you can customize it furthe - Customize the Next.js Starter Storefront to show the bundled products together in the cart, rather than seperately. - Use custom logic to set the price of the bundled product. -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). # Bundled Products Recipe This recipe provides the general steps to implement bundled products in your Medusa application. -Follow the step-by-step [Bundled Products Example](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/bundled-products/examples/standard) to learn how to implement bundled products in your Medusa application. +Follow the step-by-step [Bundled Products Example](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/bundled-products/examples/standard/index.html.md) to learn how to implement bundled products in your Medusa application. ## Overview Bundled products allow you to group multiple products into a single bundle that customers can purchase together. By using bundled products, you can offer items at a discounted price or fulfill items within the same bundle separately, among other features. -Medusa provides an [inventory kit](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/inventory/inventory-kit) feature that allows you to create bundled products. However, it doesn't support all bundled-product features. For example, you can't set a different price for the bundle, or fulfill items within the same bundle separately. +Medusa provides an [inventory kit](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/inventory/inventory-kit/index.html.md) feature that allows you to create bundled products. However, it doesn't support all bundled-product features. For example, you can't set a different price for the bundle, or fulfill items within the same bundle separately. To support more bundled-product features, you can customize the Medusa application by creating a Bundled Product Module and building flows around it. @@ -113306,7 +114497,7 @@ Your custom features and functionalities are implemented inside modules. The mod The module will hold your custom data models and the service implementing bundled-product-related features. -[How to Create a Module](undefined/docs/learn/fundamentals/modules): Learn how to create a module. +[How to Create a Module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md): Learn how to create a module. ### Create Custom Data Models @@ -113319,8 +114510,8 @@ For example, you can define: Then, you can link your custom data model to data models from other modules. For example, you can link the `BundleItem` model to the Product Module's `Product` data model. -- [How to Create a Data Model](undefined/docs/learn/fundamentals/modules#1-create-data-model): Learn how to create a data model. -- [Define Module Links](undefined/docs/learn/fundamentals/module-links): Define links between data models. +- [How to Create a Data Model](https://docs.medusajs.com/docs/learn/fundamentals/modules#1-create-data-model/index.html.md): Learn how to create a data model. +- [Define Module Links](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md): Define links between data models. ### Implement Data Management Features @@ -113328,7 +114519,7 @@ Your module’s main service holds data-management and other related features. T Medusa facilitates implementing data-management features using the service factory. Your module's main service can extend this service factory, and it generates data-management methods for your data models. -[Service Factory](undefined/docs/learn/fundamentals/modules/service-factory): Learn about the service factory and how to use it. +[Service Factory](https://docs.medusajs.com/docs/learn/fundamentals/modules/service-factory/index.html.md): Learn about the service factory and how to use it. *** @@ -113342,7 +114533,7 @@ You can implement workflows that create a bundled product, add bundled product t Then, you can utilize these workflows in other resources, such as an API route. -[Workflows](undefined/docs/learn/fundamentals/workflows): Learn how to create a workflow. +[Workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md): Learn how to create a workflow. *** @@ -113352,7 +114543,7 @@ API routes expose your features to external applications, such as the admin dash You can create custom API routes that expose the features you've built as workflows. For example, you can create an API route that allows merchants to list and create bundled products. -[API Routes](undefined/docs/learn/fundamentals/api-routes): Learn how to create an API route. +[API Routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md): Learn how to create an API route. *** @@ -113362,10 +114553,10 @@ If you've defined links between data models of two modules, you can manage them Use Link to create a link between two records, and use Query to fetch data across linked data models. -For example, you can define a link between a `Bundle` and a `Product` from the [Product Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product). Later, you can retrieve the product associated with the bundle using Query. +For example, you can define a link between a `Bundle` and a `Product` from the [Product Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/index.html.md). Later, you can retrieve the product associated with the bundle using Query. -- [How to Use Link](undefined/docs/learn/fundamentals/module-links/link): Learn how to link data models of different modules. -- [How to Use Query](undefined/docs/learn/fundamentals/module-links/query): Learn how to fetch data across modules with Medusa's Query. +- [How to Use Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md): Learn how to link data models of different modules. +- [How to Use Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md): Learn how to fetch data across modules with Medusa's Query. *** @@ -113375,8 +114566,8 @@ 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 manage bundled products. -- [Create a Widget](undefined/docs/learn/fundamentals/admin/widgets): Learn how to create a widget in the Medusa Admin. -- [Create UI Route](undefined/docs/learn/fundamentals/admin/ui-routes): Learn how to create a UI route in the Medusa Admin. +- [Create a Widget](https://docs.medusajs.com/docs/learn/fundamentals/admin/widgets/index.html.md): Learn how to create a widget in the Medusa Admin. +- [Create UI Route](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md): Learn how to create a UI route in the Medusa Admin. *** @@ -113388,8 +114579,8 @@ Medusa provides a Next.js Starter Storefront with standard commerce features inc Alternatively, you can build the storefront with your preferred tech stack. -- [Next.js Starter Storefront](undefined/nextjs-starter): Learn how to install and use the Next.js Starter Storefront. -- [Storefront Guides](undefined/storefront-development): Learn how to build a storefront for your Medusa application. +- [Next.js Starter Storefront](https://docs.medusajs.com/nextjs-starter/index.html.md): Learn how to install and use the Next.js Starter Storefront. +- [Storefront Guides](https://docs.medusajs.com/storefront-development/index.html.md): Learn how to build a storefront for your Medusa application. # Commerce Automation Recipe @@ -113412,7 +114603,7 @@ Then, you can listen to product-related events and notify subscribed customers w The following guide explains how to add restock notifications in your Medusa application: -[Restock Notification Guide](undefined/recipes/commerce-automation/restock-notification): Learn how to implement restock notifications in the Medusa application. +[Restock Notification Guide](https://docs.medusajs.com/recipes/commerce-automation/restock-notification/index.html.md): Learn how to implement restock notifications in the Medusa application. *** @@ -113428,17 +114619,17 @@ Medusa allows you to easily integrate with third-party services by creating a cu This approach allows you to interact with the third-party service within custom and existing flows, while maintaining data consistency across systems. You can then execute the wokflow when an event is triggered, such as when a customer places an order or requests a return. -- [Create Module](undefined/docs/learn/fundamentals/modules): Learn about how to create a custom module. -- [Create Workflow](undefined/docs/learn/fundamentals/workflows): Learn how to create a workflow. +- [Create Module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md): Learn about how to create a custom module. +- [Create Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md): Learn how to create a workflow. ### Automate Customer Notifications You can also automate sending notifications to customers when changes happen related to their orders, returns, exchanges, and more. -Medusa's Notification Module allows you to send notifications when an event is triggered, such as when a customer's order is updated. You can use third-party services, like [SendGrid](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid), to send emails to customers. +Medusa's Notification Module allows you to send notifications when an event is triggered, such as when a customer's order is updated. You can use third-party services, like [SendGrid](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid/index.html.md), to send emails to customers. -- [Notification Module](undefined/infrastructure-modules/notification): Learn about the Notification Module. -- [Create Subscriber](undefined/docs/learn/fundamentals/events-and-subscribers): Learn how to create a subscriber to handle events. +- [Notification Module](https://docs.medusajs.com/infrastructure-modules/notification/index.html.md): Learn about the Notification Module. +- [Create Subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md): Learn how to create a subscriber to handle events. *** @@ -113446,15 +114637,15 @@ Medusa's Notification Module allows you to send notifications when an event is t As your commerce store grows, you'll likely need to synchronize data across different systems. For example, you need to synchronize data with an ERP system or a data warehouse. -Refer to the [ERP](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/erp) recipe for a focused guide on how to integrate with an ERP system. +Refer to the [ERP](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/erp/index.html.md) recipe for a focused guide on how to integrate with an ERP system. To implement that, you can: - Create a workflow that implements the synchronization steps, along with retry and rollback logic. By using a workflow, you ensure data consistency across systems. - Create a scheduled job that executes the workflow automatically at the specified time pattern. -- [Create Workflow](undefined/docs/learn/fundamentals/workflows): Learn how to create a workflow. -- [Create a Scheduled Job](undefined/docs/learn/fundamentals/scheduled-jobs): Learn how to create a scheduled job. +- [Create Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md): Learn how to create a workflow. +- [Create a Scheduled Job](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs/index.html.md): Learn how to create a scheduled job. *** @@ -113470,8 +114661,8 @@ For example, you can automatically: To handle events within an order flow and automate actions, you can create a subscriber that listens to the relevant event. For example, you can create a subscriber that listens to the `order.placed` event and automatically creates a fulfillment if predefined conditions are met. -- [Create a Subscriber](undefined/docs/learn/fundamentals/events-and-subscribers): Learn how to create a subscriber in Medusa. -- [Events Reference](undefined/references/events): Check out triggered events by each Commerce Module. +- [Create a Subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md): Learn how to create a subscriber in Medusa. +- [Events Reference](https://docs.medusajs.com/references/events/index.html.md): Check out triggered events by each Commerce Module. *** @@ -113485,8 +114676,8 @@ 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. -- [Order Module](undefined/commerce-modules/order): Learn about the Order Module and its features. -- [Create a Subscriber](undefined/docs/learn/fundamentals/events-and-subscribers): Learn how to create a subscriber in Medusa. +- [Order Module](https://docs.medusajs.com/commerce-modules/order/index.html.md): Learn about the Order Module and its features. +- [Create a Subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md): Learn how to create a subscriber in Medusa. *** @@ -113504,10 +114695,10 @@ For example, to group customers with over twenty orders: 1. Create a subscriber that listens to the `order.placed` event. 2. If the customer has more than 20 orders, add them to the VIP customer group. -- [Customer Module](undefined/commerce-modules/customer): Learn about the Customer Module and its features. -- [Pricing Module](undefined/commerce-modules/pricing): Learn about the Pricing Module and its features. -- [Create a Subscriber](undefined/docs/learn/fundamentals/events-and-subscribers): Learn how to create a subscriber in Medusa. -- [Events Reference](undefined/references/events): Check out triggered events by each Commerce Module. +- [Customer Module](https://docs.medusajs.com/commerce-modules/customer/index.html.md): Learn about the Customer Module and its features. +- [Pricing Module](https://docs.medusajs.com/commerce-modules/pricing/index.html.md): Learn about the Pricing Module and its features. +- [Create a Subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md): Learn how to create a subscriber in Medusa. +- [Events Reference](https://docs.medusajs.com/references/events/index.html.md): Check out triggered events by each Commerce Module. *** @@ -113515,19 +114706,19 @@ For example, to group customers with over twenty orders: In your commerce store, you may utilize marketing strategies that encourage customers to make purchases. For example, you send a newsletter when new products are added to your store. -To do that, create a subscriber that listens to the `product.created`, and send an email to subscribed customers with tools like [SendGrid](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid). +To do that, create a subscriber that listens to the `product.created`, and send an email to subscribed customers with tools like [SendGrid](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid/index.html.md). 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. -- [Create a Subscriber](undefined/docs/learn/fundamentals/events-and-subscribers): Learn how to create a subscriber in Medusa. -- [Scheduled Jobs](undefined/docs/learn/fundamentals/scheduled-jobs): Learn how to create a scheduled job in Medusa. +- [Create a Subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md): Learn how to create a subscriber in Medusa. +- [Scheduled Jobs](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs/index.html.md): Learn how to create a scheduled job in Medusa. # Implement Restock Notifications in Medusa In this guide, you'll learn how to notify customers when a variant is restocked in Medusa. -When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules) which are available out-of-the-box. These features include managing the inventory of product variants in different stock locations and sales channels. +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md) which are available out-of-the-box. These features include managing the inventory of product variants in different stock locations and sales channels. Customers browsing your store may be interested in a product that is currently out of stock. To keep the customer interested in your store and encourage them to purchase the product in the future, you can build customizations around Medusa's commerce features to subscribe customers to receive a notification when the product is restocked. @@ -113558,15 +114749,15 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll first be asked for the project's name. You can also optionally choose to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter). +You'll first be asked for the project's name. You can also optionally choose to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md). Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name. If you chose to install the Next.js starter, it'll be installed in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more about Medusa's architecture in [this documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more about Medusa's architecture in [this documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credential and submit the form. Afterwards, you can login with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** @@ -113576,7 +114767,7 @@ To add custom tables to the database, which are called data models, you create a In this step, you'll create a Restock Module that adds a custom data model for restock notification subscriptions. In later steps, you'll store customer subscriptions in this data model. -Learn more about modules in [this documentation](undefined/docs/learn/fundamentals/modules). +Learn more about modules in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). ### Create Module Directory @@ -113588,7 +114779,7 @@ A module is created under the `src/modules` directory of your Medusa application A data model represents a table in the database. You create data models using Medusa's Data Model Language (DML). It simplifies defining a table's columns, relations, and indexes with straightforward methods and configurations. -Learn more about data models in [this documentation](undefined/docs/learn/fundamentals/modules#1-create-data-model). +Learn more about data models in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#1-create-data-model/index.html.md). In Medusa, you have sales channels that indicate the channels you sell your products through, such as online storefront or offline store. A product's variants have different inventory quantities across stock locations, which are associated with sales channels. @@ -113633,17 +114824,17 @@ In the data model, you define the following properties: 4. `email`: The email of the customer subscribed to the restock notification. 5. `customer_id`: The customer's ID in Medusa. This is nullable in case the customer is a guest. -Learn more about data model [properties](undefined/docs/learn/fundamentals/data-models/properties) and [relations](undefined/docs/learn/fundamentals/data-models/relationships). +Learn more about data model [properties](https://docs.medusajs.com/docs/learn/fundamentals/data-models/properties/index.html.md) and [relations](https://docs.medusajs.com/docs/learn/fundamentals/data-models/relationships/index.html.md). You also define a unique index on the `variant_id`, `sales_channel_id`, and `email` properties using the `indexes` method. -Learn more about data model indexes in [this documentation](undefined/docs/learn/fundamentals/data-models/index). +Learn more about data model indexes in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/index/index.html.md). ### Create Service You define data-management methods of your data models in a service. A service is a TypeScript or JavaScript class that the module exports. In the service's methods, you can perform database operations. -Learn more about services in [this documentation](undefined/docs/learn/fundamentals/modules#2-create-service). +Learn more about services in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#2-create-service/index.html.md). In this section, you'll create the Restock Module's service. Create the file `src/modules/restock/service.ts` with the following content: @@ -113664,7 +114855,7 @@ The `RestockModuleService` extends `MedusaService` from the Modules SDK which ge So, the `RestockModuleService` class now has methods like `createRestockSubscriptions` and `retrieveRestockSubscription`. -Find all methods generated by the `MedusaService` in [this reference](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference). +Find all methods generated by the `MedusaService` in [this reference](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/index.html.md). You'll use this service in a later method to store and manage restock subscriptions. @@ -113715,7 +114906,7 @@ Each object in the `modules` array has a `resolve` property, whose value is eith Since data models represent tables in the database, you define how they're created in the database with migrations. A migration is a TypeScript or JavaScript file that defines database changes made by a module. -Learn more about migrations in [this documentation](undefined/docs/learn/fundamentals/modules#5-generate-migrations). +Learn more about migrations in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#5-generate-migrations/index.html.md). Medusa's CLI tool generates the migrations for you. To generate a migration for the Restock Module, run the following command in your Medusa application's directory: @@ -113741,11 +114932,11 @@ The table of the Restock Module's data model are now created in the database. Since the `RestockSubscription` data model stores the product variant's ID, you may want to retrieve the product variant's details while retrieving a restock subscription record. -However, modules are [isolated](undefined/docs/learn/fundamentals/modules/isolation) to ensure they're re-usable and don't have side effects when integrated into the Medusa application. So, to build associations between modules, you define [module links](undefined/docs/learn/fundamentals/module-links). A Module link associates two modules' data models while maintaining module isolation. +However, modules are [isolated](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md) to ensure they're re-usable and don't have side effects when integrated into the Medusa application. So, to build associations between modules, you define [module links](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md). A Module link associates two modules' data models while maintaining module isolation. -In this section, you'll link the `RestockSubscription` data model to the [Product Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product)'s `ProductVariant` data model. +In this section, you'll link the `RestockSubscription` data model to the [Product Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/index.html.md)'s `ProductVariant` data model. -Learn more about module links in [this documentation](undefined/docs/learn/fundamentals/module-links). +Learn more about module links in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md). To define a link, create the file `src/links/restock-variant.ts` with the following content: @@ -113786,13 +114977,13 @@ A workflow is a series of queries and actions, called steps, that complete a tas In this section, you'll create a workflow that validates that a variant is out-of-stock in the customer's sales channel, then subscribes the customer to the variant's restock notification. Later, you'll execute this workflow in an endpoint that you use in a storefront. -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows) +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) The workflow has the following steps: - [validateVariantOutOfStockStep](#validatevariantoutofstockstep): Validate that the variant is out-of-stock, otherwise throw an error. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the restock subscription using Query if it exists. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the restock subscription using Query again to return it. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the restock subscription using Query if it exists. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the restock subscription using Query again to return it. The `useQueryGraphStep` is from Medusa's workflows package. So, you'll only implement the other steps. @@ -113874,7 +115065,7 @@ In the step, you resolve the Restock Module's service from the Medusa container. Then, you use the service's `createRestockSubscriptions` method, which was generated by `MedusaService`, to create the restock subscription. -Learn more about a service's generated methods in [this reference](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference). +Learn more about a service's generated methods in [this reference](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/index.html.md). Finally, you return the created restock subscription by passing it as a first parameter to `StepResponse`. The second parameter is data passed to the compensation function, which you'll learn about next. @@ -113882,7 +115073,7 @@ Finally, you return the created restock subscription by passing it as a first pa A compensation function defines the rollback logic of a step, and it's only executed if an error occurs in the workflow. This eliminates data inconsistency if an error occurs and the workflow can't finish execution successfully. -Learn more about compensation functions in [this documentation](undefined/docs/learn/fundamentals/workflows/compensation-function). +Learn more about compensation functions in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/compensation-function/index.html.md). Since the `createRestockSubscriptionStep` creates a restock subscription, you'll undo that in the compensation function. To add a compensation function, pass it as a third parameter to `createStep`: @@ -114031,11 +115222,11 @@ You create a workflow using `createWorkflow` from the Workflows SDK. It accepts It accepts as a second parameter a constructor function, which is the workflow's implementation. In the workflow, you: -- Use [transform](undefined/docs/learn/fundamentals/workflows/variable-manipulation) from the Workflows SDK to create a `customerId` variable. Its value is either the ID of the customer passed in the workflow's input if it's not `undefined`, or an empty string. -- Use [when-then](undefined/docs/learn/fundamentals/workflows/conditions) from the Workflows SDK that performs steps if a condition is met. If the customer's email isn't set in the workflow's input, you retrieve the customer using `useQueryGraphStep` by its ID. +- Use [transform](https://docs.medusajs.com/docs/learn/fundamentals/workflows/variable-manipulation/index.html.md) from the Workflows SDK to create a `customerId` variable. Its value is either the ID of the customer passed in the workflow's input if it's not `undefined`, or an empty string. +- Use [when-then](https://docs.medusajs.com/docs/learn/fundamentals/workflows/conditions/index.html.md) from the Workflows SDK that performs steps if a condition is met. If the customer's email isn't set in the workflow's input, you retrieve the customer using `useQueryGraphStep` by its ID. - Use `transform` again to create an `email` variable whose value is either the email passed in the workflow's input or the retrieved customer's email. -A workflow's constructor function has some constraints in implementation, which is why you need to use `transform` for variable manipulation and `when-then` to perform steps based on a condition. Learn more about these constraints in [this documentation](undefined/docs/learn/fundamentals/workflows/constructor-constraints). +A workflow's constructor function has some constraints in implementation, which is why you need to use `transform` for variable manipulation and `when-then` to perform steps based on a condition. Learn more about these constraints in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/constructor-constraints/index.html.md). Next, replace the `TODO` with the following: @@ -114096,7 +115287,7 @@ You add the following steps to the workflow: - `validateVariantOutOfStockStep` to validate that the variant is out of stock in the specified sales channel. If not, an error is thrown, halting the workflow's execution. - `useQueryGraphStep` to retrieve the restock subscription in case it already exists. -- Use [when-then](undefined/docs/learn/fundamentals/workflows/conditions) to perform an action if a condition is met. +- Use [when-then](https://docs.medusajs.com/docs/learn/fundamentals/workflows/conditions/index.html.md) to perform an action if a condition is met. - The first when-then block checks if the restock subscription doesn't exist, then creates it using the `createRestockSubscriptionStep`. - The second when-then block checks if the restock subscription already exists, then updates it using the `updateRestockSubscriptionStep`. - `useQueryGraphStep` again to retrieve the restock subscription before returning it. @@ -114113,7 +115304,7 @@ Now that you implemented the flow to subscribe customers to a variant's restock An API Route is an endpoint that exposes commerce features to external applications and clients, such as storefronts. You'll create an API route at the path `/store/restock-subscriptions` that executes the workflow from the previous step. -Learn more about API routes in [this documentation](undefined/docs/learn/fundamentals/api-routes). +Learn more about API routes in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). ### Implement API Route @@ -114231,7 +115422,7 @@ Next, you'll use this schema for validation. To use the Zod schema for validation, you apply the `validateAndTransformBody` middleware on the `/store/restock-subscriptions` route. A middleware is a function executed before the API route when a request is sent to it. -Learn more about middlewares in [this documentation](undefined/docs/learn/fundamentals/api-routes/middlewares). +Learn more about middlewares in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md). To apply middlewares, create the file `src/api/middlewares.ts` with the following content: @@ -114348,7 +115539,7 @@ The workflow has the following steps: - [getDistinctSubscriptionsStep](#getDistinctSubscriptionsStep): Retrieve restock subscriptions for distinct variant ID and sales channel pairings. - [getRestockedStep](#getrestockedstep): Filter out the restock subscriptions to retrieve only ones for restocked variants. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve restocked subscriptions for all subscribers using Query. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve restocked subscriptions for all subscribers using Query. - [sendRestockNotificationStep](#sendrestocknotificationstep): Send a notification to the subscribers of restock subscriptions. - [deleteRestockSubscriptionStep](#deleterestocksubscriptionstep): Delete the restock subscriptions from the database. @@ -114356,9 +115547,9 @@ The `useQueryGraphStep` is from Medusa's workflows. So, you'll only implement th ### Optional Prerequisite: Notification Module Provider -Within this workflow, you'll use Medusa's [Notification Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification) to send an email to the customer. +Within this workflow, you'll use Medusa's [Notification Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/index.html.md) to send an email to the customer. -The module delegates the email sending to a module provider, such as [SendGrid](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid) or [Resend](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/integrations/guides/resend). You can refer to their linked guides to set up either module providers. +The module delegates the email sending to a module provider, such as [SendGrid](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid/index.html.md) or [Resend](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/integrations/guides/resend/index.html.md). You can refer to their linked guides to set up either module providers. Alternatively, for development and debugging purposes, you can use the default Notification Module Provider that only logs a message in the terminal instead of sending an email. To do that, add the following to the `modules` array in `medusa-config.ts`: @@ -114652,7 +115843,7 @@ This workflow has the following steps: 1. `getDistinctSubscriptionsStep` to retrieve the restock subscriptions by distinct variant and sales channel ID pairings. 2. `getRestockedStep` to filter the subscriptions retrieved by the previous step and return only those whose variants have been restocked. -3. `useQueryGraphStep` to retrieve all subscriptions that have a restocked variant and sales channel ID pairing using [Query](undefined/docs/learn/fundamentals/module-links/query). Notice that in the specified `fields` you pass `product_variant.*`, which retrieves the details of the subscription's variant from the Product Module. This is possible due to the module link you created between the `RestockSubscription` and `ProductVariant` models in an earlier step. +3. `useQueryGraphStep` to retrieve all subscriptions that have a restocked variant and sales channel ID pairing using [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md). Notice that in the specified `fields` you pass `product_variant.*`, which retrieves the details of the subscription's variant from the Product Module. This is possible due to the module link you created between the `RestockSubscription` and `ProductVariant` models in an earlier step. 4. `sendRestockNotificationStep` to send the notification to the subscribers of the restocked variants. 5. `deleteRestockSubscriptionStep` to delete the restock subscriptions since their subscribers have been notified. @@ -114668,7 +115859,7 @@ Now that you've built the flow to send restock notifications, you want to check A scheduled job is an asynchronous function that the Medusa application runs at the schedule you specify during the Medusa application's runtime. Scheduled jobs are useful for automating tasks at a fixed schedule. -Learn more about scheduled jobs in [this documentation](undefined/docs/learn/fundamentals/scheduled-jobs). +Learn more about scheduled jobs in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs/index.html.md). In this step, you'll create a scheduled job that runs once a day to execute the `sendRestockNotificationsWorkflow` from the previous step. @@ -114748,11 +115939,11 @@ Attempting to send a notification to: 'customer@gmail.com' on the channel: 'emai ## Next Steps -You've now implemented restock notifications in Medusa. You can also customize the [storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter) to allow customers to subscribe to the restock notification using the new API route you added. +You've now implemented restock notifications in Medusa. You can also customize the [storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) to allow customers to subscribe to the restock notification using the new API route you added. -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). # Digital Products Recipe Example @@ -114790,15 +115981,15 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose Yes. +You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose Yes. Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name. If you chose to install the Next.js starter, it'll be installed in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more about Medusa's architecture in [this documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more about Medusa's architecture in [this documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credential and submit the form. Afterwards, you can login with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** @@ -114924,7 +116115,7 @@ class DigitalProductModuleService extends MedusaService({ export default DigitalProductModuleService ``` -The service extends the [service factory](undefined/docs/learn/fundamentals/modules/service-factory), which provides basic data-management features. +The service extends the [service factory](https://docs.medusajs.com/docs/learn/fundamentals/modules/service-factory/index.html.md), which provides basic data-management features. ### Create Module Definition @@ -114958,8 +116149,8 @@ module.exports = defineConfig({ ### Further Reads -- [How to Create a Module](undefined/docs/learn/fundamentals/modules) -- [How to Create a Data Model](undefined/docs/learn/fundamentals/modules#1-create-data-model) +- [How to Create a Module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) +- [How to Create a Data Model](https://docs.medusajs.com/docs/learn/fundamentals/modules#1-create-data-model/index.html.md) *** @@ -115020,7 +116211,7 @@ This defines a link between `DigitalProductOrder` and the Order Module’s `Orde ### Further Read -- [How to Define Module Links](undefined/docs/learn/fundamentals/module-links) +- [How to Define Module Links](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md) *** @@ -115128,8 +116319,8 @@ Make sure to replace `{token}` with the JWT token you retrieved. ### Further Reads -- [How to Create an API Route](undefined/docs/learn/fundamentals/api-routes) -- [Learn more about Query](undefined/docs/learn/fundamentals/module-links/query) +- [How to Create an API Route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) +- [Learn more about Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) *** @@ -115359,9 +116550,9 @@ You’ll test out the workflow in the next section. ### Further Reads -- [How to Create a Workflow](undefined/docs/learn/fundamentals/workflows) -- [What is the Compensation Function](undefined/docs/learn/fundamentals/workflows/compensation-function) -- [Learn more about Link functions](undefined/docs/learn/fundamentals/module-links/link) +- [How to Create a Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) +- [What is the Compensation Function](https://docs.medusajs.com/docs/learn/fundamentals/workflows/compensation-function/index.html.md) +- [Learn more about Link functions](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md) *** @@ -115471,7 +116662,7 @@ This adds a validation middleware to ensure that the body of `POST` requests sen ### Further Read -- [How to Create a Middleware](undefined/docs/learn/fundamentals/api-routes/middlewares) +- [How to Create a Middleware](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md) *** @@ -115479,7 +116670,7 @@ This adds a validation middleware to ensure that the body of `POST` requests sen To upload the digital product media files, use Medusa’s File Module. -Your Medusa application uses the local file module provider by default, which uploads files to a local directory. However, you can use other file module providers, such as the [S3 module provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/file/s3). +Your Medusa application uses the local file module provider by default, which uploads files to a local directory. However, you can use other file module providers, such as the [S3 module provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/file/s3/index.html.md). In this step, you’ll create an API route for uploading preview and main digital product media files. @@ -115778,8 +116969,8 @@ Once you log in, you’ll find a new sidebar item, “Digital Products.” If yo ### Further Reads -- [How to Create UI Routes](undefined/docs/learn/fundamentals/admin/ui-routes) -- [How to Create Admin Widgets](undefined/docs/learn/fundamentals/admin/widgets) +- [How to Create UI Routes](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md) +- [How to Create Admin Widgets](https://docs.medusajs.com/docs/learn/fundamentals/admin/widgets/index.html.md) *** @@ -116292,7 +117483,7 @@ The `deleteProductDigitalProductsWorkflow` receives the ID of the deleted produc When a product is deleted, Medusa emits a `product.deleted` event. You can handle this event with a subscriber. A subscriber is an asynchronous function that, when an event is emitted, is executed. You can implement in subscribers features that aren't essential to the original flow that emitted the event. -Learn more about subscribers in [this documentation](undefined/docs/learn/fundamentals/events-and-subscribers). +Learn more about subscribers in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md). So, you'll listen to the `product.deleted` event in a subscriber, and execute the workflow whenever the product is deleted. @@ -116327,7 +117518,7 @@ A subscriber file must export: The subscriber function receives as a parameter an object having the following properties: - `event`: An object containing the data payload of the emitted event. -- `container`: Instance of the [Medusa Container](undefined/docs/learn/fundamentals/medusa-container). +- `container`: Instance of the [Medusa Container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). In the subscriber, you execute the workflow by invoking it, passing the Medusa container as an input, then executing its `run` method. You pass the product's ID, which is received through the event's data payload, as an input to the workflow. @@ -116724,7 +117915,7 @@ In the route handler, you execute the `createDigitalProductOrderWorkflow` and re ### Test Cart Completion: Customize Next.js Starter Storefront -To test out the cart completion, you'll customize the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter) that you installed in the first step to use the new cart completion route to place an order. +To test out the cart completion, you'll customize the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) that you installed in the first step to use the new cart completion route to place an order. The Next.js Starter Storefront was installed in a separate directory from Medusa. The directory's name is `{your-project}-storefront`. @@ -116777,7 +117968,7 @@ In a later step, you’ll add an API route to allow customers to view and downlo ### Further Read -- [Conditions in Workflows with When-Then](undefined/docs/learn/fundamentals/workflows/conditions) +- [Conditions in Workflows with When-Then](https://docs.medusajs.com/docs/learn/fundamentals/workflows/conditions/index.html.md) *** @@ -116967,7 +118158,7 @@ In the workflow, you: In the `sendDigitalOrderNotificationStep`, you use a notification provider configured for the `email` channel to send the notification. -Check out the [Integrations page](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/integrations) to find Notification Module Providers. +Check out the [Integrations page](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/integrations/index.html.md) to find Notification Module Providers. For testing purposes, add to `medusa-config.ts` the following to use the Local Notification Module Provider: @@ -117247,13 +118438,13 @@ You’ll test out these API routes in the next step. ### Further Reads -- [What are protected API routes](undefined/docs/learn/fundamentals/api-routes/protected-routes) +- [What are protected API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/protected-routes/index.html.md) *** ## Step 17: Customize Next.js Starter -In this section, you’ll customize the [Next.js Starter storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter) to: +In this section, you’ll customize the [Next.js Starter storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) to: 1. Show a preview button on a digital product’s page to view the preview files. 2. Add a new tab in the customer’s dashboard to view their purchased digital products. @@ -117722,18 +118913,18 @@ The next steps of this example depend on your use case. This section provides so ### Storefront Development -Aside from customizing the Next.js Starter storefront, you can also create a custom storefront. Check out the [Storefront Development](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development) section to learn how to create a storefront. +Aside from customizing the Next.js Starter storefront, you can also create a custom storefront. Check out the [Storefront Development](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/index.html.md) section to learn how to create a storefront. ### Admin Development -In this recipe, you learned how to customize the admin with UI routes. You can also do further customization using widgets. Learn more in [this documentation](undefined/docs/learn/fundamentals/admin). +In this recipe, you learned how to customize the admin with UI routes. You can also do further customization using widgets. Learn more in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/admin/index.html.md). # Digital Products Recipe This recipe provides the general steps to implement digital products in your Medusa application. -Follow the step-by-step [Digital Products Example](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/digital-products/examples/standard) to learn how to implement digital products in your Medusa application. +Follow the step-by-step [Digital Products Example](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/digital-products/examples/standard/index.html.md) to learn how to implement digital products in your Medusa application. ## Overview @@ -117751,10 +118942,10 @@ A file module provider handles storage functionalities in Medusa. This includes You can use a file module provider to store and manage your digital products. -During development, you can use the Local File Module Provider, which is installed by default in your store. For production, you can use module providers like [S3](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/file/s3) or create your own. +During development, you can use the Local File Module Provider, which is installed by default in your store. For production, you can use module providers like [S3](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/file/s3/index.html.md) or create your own. -- [File Module Providers](undefined/infrastructure-modules/file): Check out available file module providers. -- [Create a File Module Provider](undefined/references/file-provider-module): Learn how to create a file module provider. +- [File Module Providers](https://docs.medusajs.com/infrastructure-modules/file/index.html.md): Check out available file module providers. +- [Create a File Module Provider](https://docs.medusajs.com/references/file-provider-module/index.html.md): Learn how to create a file module provider. *** @@ -117764,7 +118955,7 @@ Your custom features and functionalities are implemented inside modules. The mod You can create a custom module for digital products that holds your custom data models and the service implementing digital-product-related features. -[How to Create a Module](undefined/docs/learn/fundamentals/modules): Learn how to create a module. +[How to Create a Module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md): Learn how to create a module. ### Create Custom Data Model @@ -117772,8 +118963,8 @@ A data model represents a table in the database. You can define in your module d Then, you can link your custom data model to data models from other modules. For example, you can link the digital product model to the Product Module's `ProductVariant` data model. -- [How to Create a Data Model](undefined/docs/learn/fundamentals/modules#1-create-data-model): Learn how to create a data model. -- [Define Module Links](undefined/docs/learn/fundamentals/module-links): Define links between data models. +- [How to Create a Data Model](https://docs.medusajs.com/docs/learn/fundamentals/modules#1-create-data-model/index.html.md): Learn how to create a data model. +- [Define Module Links](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md): Define links between data models. ### Implement Data Management Features @@ -117781,7 +118972,7 @@ Your module’s main service holds data-management and other related features. T Medusa facilitates implementing data-management features using the service factory. Your module's main service can extend this service factory, and it generates data-management methods for your data models. -[Service Factory](undefined/docs/learn/fundamentals/modules/service-factory): Learn about the service factory and how to use it. +[Service Factory](https://docs.medusajs.com/docs/learn/fundamentals/modules/service-factory/index.html.md): Learn about the service factory and how to use it. *** @@ -117793,7 +118984,7 @@ Create workflows to implement these flows, then utilize these workflows in other In the workflow's steps, you can resolve the Digital Product Module's service and use its data-management methods to manage digital products. -[Workflows](undefined/docs/learn/fundamentals/workflows): Learn how to create a workflow. +[Workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md): Learn how to create a workflow. *** @@ -117803,7 +118994,7 @@ API routes expose your features to external applications, such as the admin dash You can create custom admin API routes that allow merchants to list and create digital products, and store API routes that allow customers to purchase and download digital products. -[API Routes](undefined/docs/learn/fundamentals/api-routes): Learn how to create an API route. +[API Routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md): Learn how to create an API route. *** @@ -117819,10 +119010,10 @@ The Medusa Admin is an extensible application within your Medusa application. Yo - **UI Routes**: Adding new pages to the Medusa Admin, such as a page to manage digital products. - **Settings Pages**: Adding new pages to the Medusa Admin settings, such as a page to manage digital product settings. -- [Create Admin Widget](undefined/docs/learn/fundamentals/admin/widgets): Add widgets into existing admin pages. -- [Create Admin UI Routes](undefined/docs/learn/fundamentals/admin/ui-routes): Add new pages to your Medusa Admin. +- [Create Admin Widget](https://docs.medusajs.com/docs/learn/fundamentals/admin/widgets/index.html.md): Add widgets into existing admin pages. +- [Create Admin UI Routes](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md): Add new pages to your Medusa Admin. -[Create Admin Setting Page](undefined/docs/learn/fundamentals/admin/ui-routes#create-settings-page): Add new page to the Medusa Admin settings. +[Create Admin Setting Page](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes#create-settings-page/index.html.md): Add new page to the Medusa Admin settings. *** @@ -117834,8 +119025,8 @@ The Fulfillment Module handles all logic related to fulfilling orders. It also s You can create a custom fulfillment module provider that implements the logic of delivering digital products to customers based on your use case. -- [Fulfillment Module](undefined/commerce-modules/fulfillment): Learn about the Fulfillment Module. -- [Create Fulfillment Module Provider](undefined/references/fulfillment/provider): Learn how to create a fulfillment module provider. +- [Fulfillment Module](https://docs.medusajs.com/commerce-modules/fulfillment/index.html.md): Learn about the Fulfillment Module. +- [Create Fulfillment Module Provider](https://docs.medusajs.com/references/fulfillment/provider/index.html.md): Learn how to create a fulfillment module provider. *** @@ -117847,8 +119038,8 @@ Medusa provides a Next.js Starter Storefront with standard commerce features inc Alternatively, you can build your own storefront using the Medusa APIs. This headless approach gives you the flexibility to build a custom storefront without limitations on which tech stack you use, or the design of the storefront. -- [Next.js Starter Storefront](undefined/nextjs-starter): Learn how to install and use the Next.js Starter Storefront. -- [Storefront Guides](undefined/storefront-development): Find guides to build your own storefront. +- [Next.js Starter Storefront](https://docs.medusajs.com/nextjs-starter/index.html.md): Learn how to install and use the Next.js Starter Storefront. +- [Storefront Guides](https://docs.medusajs.com/storefront-development/index.html.md): Find guides to build your own storefront. # Ecommerce Recipe @@ -117882,7 +119073,7 @@ npx create-medusa-app@latest --with-nextjs-starter This installs: - The Medusa application, which is composed of a Node.js server and a Medusa Admin dashboard. The dashboard opens right after the installation finishes, where you can create a user and start managing your store's data. -- A [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter) that connects to your Medusa application to provide customers with ecommerce features. +- A [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) that connects to your Medusa application to provide customers with ecommerce features. *** @@ -117890,15 +119081,15 @@ This installs: You can integrate third-party services and tools, customizing the architecture and commerce features of your store. -For example, you can integrate [Stripe](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe) to accept payments, or [SendGrid](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid) to send emails to customers. +For example, you can integrate [Stripe](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe/index.html.md) to accept payments, or [SendGrid](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid/index.html.md) to send emails to customers. -[Integrations](undefined/integrations): Check out available integrations for your Medusa application. +[Integrations](https://docs.medusajs.com/integrations/index.html.md): Check out available integrations for your Medusa application. *** ## Deploy the Medusa Application -The most efficient way to deploy your Medusa application is to use [Cloud](undefined/cloud). Cloud is our managed services offering that makes deploying and operating Medusa applications possible without having to worry about configuring, scaling, and maintaining infrastructure. Cloud hosts your server, Admin dashboard, database, and Redis instance. +The most efficient way to deploy your Medusa application is to use [Cloud](https://docs.medusajs.com/cloud/index.html.md). Cloud is our managed services offering that makes deploying and operating Medusa applications possible without having to worry about configuring, scaling, and maintaining infrastructure. Cloud hosts your server, Admin dashboard, database, and Redis instance. With Cloud, you maintain full customization control as you deploy your own modules and customizations directly from GitHub: @@ -117909,8 +119100,8 @@ With Cloud, you maintain full customization control as you deploy your own modul Our documentation also provides a step-by-step guides to deploy your Medusa application and the Next.js Starter Storefront. -- [Sign up for Cloud](undefined/cloud): Learn more about Cloud and sign up to get started. -- [Deployment Guides](undefined/deployment): Learn how to deploy the Medusa application and Next.js Starter Storefront. +- [Sign up for Cloud](https://docs.medusajs.com/cloud/index.html.md): Learn more about Cloud and sign up to get started. +- [Deployment Guides](https://docs.medusajs.com/deployment/index.html.md): Learn how to deploy the Medusa application and Next.js Starter Storefront. *** @@ -117918,7 +119109,7 @@ Our documentation also provides a step-by-step guides to deploy your Medusa appl Along with the extensive ecommerce features, Medusa also provides the architecture and Framework to customize your application and build custom features that are tailored for your business use case. -To learn how to develop customziations with Medusa, refer to the [Get Started](undefined/docs/learn) documentation. +To learn how to develop customziations with Medusa, refer to the [Get Started](https://docs.medusajs.com/docs/learn/index.html.md) documentation. # Integrate Odoo with Medusa @@ -117929,7 +119120,7 @@ When you install a Medusa application, you get a fully-fledged commerce platform Odoo is a suite of open-source business apps that covers all your business needs, including an ERP system. You can use Odoo to store products and their prices, manage orders, and more. -This guide will teach you how to implement the general integration between Medusa and Odoo. You will learn how to connect to Odoo's APIs and fetch data such as products. You can then expand on this integration to implement your business requirements. You can also refer to [this recipe](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/erp) to find general examples of ERP integration use cases and how to implement them. +This guide will teach you how to implement the general integration between Medusa and Odoo. You will learn how to connect to Odoo's APIs and fetch data such as products. You can then expand on this integration to implement your business requirements. You can also refer to [this recipe](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/erp/index.html.md) to find general examples of ERP integration use cases and how to implement them. *** @@ -117947,15 +119138,15 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You will first be asked for the project's name. You can also optionally choose to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter). +You will first be asked for the project's name. You can also optionally choose to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md). Afterward, the installation process will start, installing the Medusa application in a directory with your project's name. If you chose to install the Next.js starter, it'll be installed in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more about Medusa's architecture in [this documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more about Medusa's architecture in [this documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credential and submit the form. Afterwards, you can login with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** @@ -117975,11 +119166,11 @@ You will use this package in the next steps to connect to Odoo's APIs. ## Step 3: Create Odoo Module -To integrate third-party systems into Medusa, you create a custom [module](undefined/docs/learn/fundamentals/modules). A module is a re-usable package with functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. +To integrate third-party systems into Medusa, you create a custom [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). A module is a re-usable package with functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. In this step, you'll create an Odoo Module that provides the interface to connect to and interact with Odoo. You will later use this module when implementing the product syncing logic. -Learn more about modules in [this documentation](undefined/docs/learn/fundamentals/modules). +Learn more about modules in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). ### Create Module Directory @@ -117991,9 +119182,9 @@ A module is created under the `src/modules` directory of your Medusa application You define a module's functionalities in a service. A service is a TypeScript or JavaScript class that the module exports. In the service's methods, you can connect to the database, which is useful if your module defines tables in the database, or connect to a third-party service. -Medusa registers the module's service in the [Medusa container](undefined/docs/learn/fundamentals/medusa-container), allowing you to easily resolve the service from other customizations and use its methods. +Medusa registers the module's service in the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), allowing you to easily resolve the service from other customizations and use its methods. -The Medusa application registers resources, such as a module's service or the [logging tool](undefined/docs/learn/debugging-and-testing/logging), in the Medusa container so that you can resolve them from other customizations, as you'll see in later sections. Learn more about it in [this documentation](undefined/docs/learn/fundamentals/medusa-container). +The Medusa application registers resources, such as a module's service or the [logging tool](https://docs.medusajs.com/docs/learn/debugging-and-testing/logging/index.html.md), in the Medusa container so that you can resolve them from other customizations, as you'll see in later sections. Learn more about it in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). In this section, you'll create the Odoo Module's service and the methods necessary to connect to Odoo. @@ -118375,18 +119566,18 @@ You will test that the Odoo Module works as expected in the next steps. There are different use cases you can implement when integrating an ERP like Odoo. One of them is syncing products from the ERP to Medusa. This way, you can manage products in Odoo and have them reflected in your commerce platform. -To implement the syncing functionality, you need to create a [workflow](undefined/docs/learn/fundamentals/workflows). A workflow is a series of queries and actions, called steps, that complete a task. You construct a workflow similar to how you create a JavaScript function, but with additional features like defining rollback logic for each step, performing long actions asynchronously, and tracking the progress of the steps. +To implement the syncing functionality, you need to create a [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). A workflow is a series of queries and actions, called steps, that complete a task. You construct a workflow similar to how you create a JavaScript function, but with additional features like defining rollback logic for each step, performing long actions asynchronously, and tracking the progress of the steps. After defining the workflow, you can execute it in other customizations, such as periodically or when an event occurs. -In this section, you'll create a workflow that syncs products from Odoo to Medusa. Then, you'll execute that workflow once a day using a [scheduled job](undefined/docs/learn/fundamentals/scheduled-jobs). The workflow has the following steps: +In this section, you'll create a workflow that syncs products from Odoo to Medusa. Then, you'll execute that workflow once a day using a [scheduled job](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs/index.html.md). The workflow has the following steps: - [getProductsFromErp](#getProductsFromErp): Fetch products from Odoo -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Get Medusa store configurations to use when creating the products. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Get Medusa sales channels to use when creating the products. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Get Medusa shipping profiles to use when creating the products. -- [createProductsWorkflow](undefined/references/medusa-workflows/createProductsWorkflow): Create new products in Medusa. -- [updateProductsWorkflow](undefined/references/medusa-workflows/updateProductsWorkflow): Update existing products in Medusa. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Get Medusa store configurations to use when creating the products. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Get Medusa sales channels to use when creating the products. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Get Medusa shipping profiles to use when creating the products. +- [createProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createProductsWorkflow/index.html.md): Create new products in Medusa. +- [updateProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/updateProductsWorkflow/index.html.md): Update existing products in Medusa. The only step you'll need to implement is the `getProductsFromErp` step. The other steps are available through Medusa's `@medusajs/medusa/core-flows` package. @@ -118421,7 +119612,7 @@ You create a step using `createStep` from the Workflows SDK. It accepts two para 1. The step's name, which is `get-products-from-erp`. 2. An async function that executes the step's logic. The function receives two parameters: - The input data for the step, which are the pagination fields `offset` and `limit`. - - An object holding the workflow's context, including the [Medusa Container](undefined/docs/learn/fundamentals/medusa-container) that allows you to resolve Framework and commerce tools. + - An object holding the workflow's context, including the [Medusa Container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md) that allows you to resolve Framework and commerce tools. In this step, you resolve the Odoo Module's service from the container and use its `listProducts` method to fetch products from Odoo. You pass the pagination options from the input data to the method. @@ -118496,10 +119687,10 @@ You create a workflow using `createWorkflow` from the Workflows SDK. It accepts It accepts as a second parameter a constructor function, which is the workflow's implementation. The function receives the pagination options as a parameter. In the workflow, you: - Call the `getProductsFromErp` step to fetch products from Odoo. -- Use the [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep) to fetch the Medusa store configurations, sales channels, and shipping profiles. You'll use this data when creating the products in a later step. - - The `useQueryGraphStep` uses [Query](undefined/docs/learn/fundamentals/module-links/query), which is a tool that retrieves data across modules. +- Use the [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md) to fetch the Medusa store configurations, sales channels, and shipping profiles. You'll use this data when creating the products in a later step. + - The `useQueryGraphStep` uses [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md), which is a tool that retrieves data across modules. - To figure out which products need to be updated, you retrieve products filtered by their `external_id` field, which you'll set to the Odoo product's ID when you create the products next. - - Notice that you use `transform` from the Workflows SDK to create the external IDs filters. That's because data manipulation is not allowed in a workflow. You can learn more about this and other restrictions in [this documentation](undefined/docs/learn/fundamentals/workflows/constructor-constraints). + - Notice that you use `transform` from the Workflows SDK to create the external IDs filters. That's because data manipulation is not allowed in a workflow. You can learn more about this and other restrictions in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/constructor-constraints/index.html.md). Next, you need to prepare the products that should be created or updated. To do that, replace the `TODO` with the following: @@ -118657,7 +119848,7 @@ You can now execute this workflow in other customizations, such as a scheduled j ### Create Scheduled Job -In Medusa, you can run a task at a specified interval using a [scheduled job](undefined/docs/learn/fundamentals/scheduled-jobs). A scheduled job is an asynchronous function that runs at a regular interval during the Medusa application's runtime to perform tasks such as syncing products from Odoo to Medusa. +In Medusa, you can run a task at a specified interval using a [scheduled job](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs/index.html.md). A scheduled job is an asynchronous function that runs at a regular interval during the Medusa application's runtime to perform tasks such as syncing products from Odoo to Medusa. To create a scheduled job, create the file `src/jobs/sync-products-from-erp.ts` with the following content: @@ -118737,11 +119928,11 @@ If you encounter any issues, make sure the module options are set correctly as e ## Next Steps -You now have the foundation for integrating Odoo with Medusa. You can expand on this integration to implement more use cases, such as syncing orders, restricting purchases of products based on custom rules, and checking inventory in Odoo before adding to the cart. You can find the approach to implement these use cases in [this recipe](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/erp). +You now have the foundation for integrating Odoo with Medusa. You can expand on this integration to implement more use cases, such as syncing orders, restricting purchases of products based on custom rules, and checking inventory in Odoo before adding to the cart. You can find the approach to implement these use cases in [this recipe](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/erp/index.html.md). -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth learning of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). # Integrate ERP with Medusa @@ -118776,15 +119967,15 @@ If you don't have a Medusa application yet, you can install it with the followin npx create-medusa-app@latest ``` -You'll first be asked for the project's name. You can also optionally choose to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter). +You'll first be asked for the project's name. You can also optionally choose to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md). Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name. If you chose to install the Next.js starter, it'll be installed in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more about Medusa's architecture in [this documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more about Medusa's architecture in [this documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterwards, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** @@ -118792,7 +119983,7 @@ Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/for Before you start integrating the ERP system into existing or new flows in Medusa, you must build the integration layer that allows you to communicate with the ERP in your customizations. -In Medusa, you implement integrations or features around a single commerce domain in a [module](undefined/docs/learn/fundamentals/modules). A module is a reusable package that can interact with the database or external APIs. The module integrates into your Medusa application without side effects to the existing setup. +In Medusa, you implement integrations or features around a single commerce domain in a [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). A module is a reusable package that can interact with the database or external APIs. The module integrates into your Medusa application without side effects to the existing setup. So, you can create a module that exports a class called a service, and in that service, you implement the logic to connect to your ERP system, fetch data from it, and send data to it. The service may look like this: @@ -118823,7 +120014,7 @@ You can then use the module's service in the custom flows and customizations tha ### How to Create Module -Refer to [this documentation](undefined/docs/learn/fundamentals/modules) on how to create a module. You can also refer to the [Odoo Integration guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/erp/odoo) as an example of how to build a module that integrates an ERP into Medusa. +Refer to [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) on how to create a module. You can also refer to the [Odoo Integration guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/erp/odoo/index.html.md) as an example of how to build a module that integrates an ERP into Medusa. The rest of this recipe assumes you have an ERP Module with some methods to retrieve products, prices, and other relevant data. @@ -118837,9 +120028,9 @@ Syncing data between systems is a big challenge and it's often the pitfall of mo Medusa's workflows are a series of queries and actions, called steps, that complete a task. You construct a workflow similar to how you create a JavaScript function, but with additional features like defining rollback logic for each step, performing long actions asynchronously, and tracking the progress of the steps. You can then use these workflows in other customizations, such as: -- [API routes](undefined/docs/learn/fundamentals/api-routes) to allow clients to trigger the workflow's execution. -- [Subscribers](undefined/docs/learn/fundamentals/events-and-subscribers) to trigger the workflow when an event occurs. -- [Scheduled jobs](undefined/docs/learn/fundamentals/scheduled-jobs) to run the workflow periodically. +- [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) to allow clients to trigger the workflow's execution. +- [Subscribers](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md) to trigger the workflow when an event occurs. +- [Scheduled jobs](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs/index.html.md) to run the workflow periodically. So, to sync products from the ERP system to Medusa, you can create a custom workflow that fetches the products from the ERP system and adds them to Medusa. Then, you can create a scheduled job that syncs the products once a day, for example. @@ -118904,15 +120095,15 @@ export const syncFromErpWorkflow = createWorkflow( ) ``` -In the above file, you first create a `getProductsFromErpStep` that resolves the ERP Module's service from the [Medusa container](undefined/docs/learn/fundamentals/medusa-container), which is a registry of Framework and commerce tools, including your modules, that you can access in your customizations. You can then call the `getProducts` method in the ERP Module's service to fetch the products from the ERP and return them. +In the above file, you first create a `getProductsFromErpStep` that resolves the ERP Module's service from the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which is a registry of Framework and commerce tools, including your modules, that you can access in your customizations. You can then call the `getProducts` method in the ERP Module's service to fetch the products from the ERP and return them. Then, you create a `syncFromErpWorkflow` that executes the `getProductsFromErpStep` to get the products from the ERP, then prepare the products to be created in Medusa. For example, you can set the product's title, and specify its ID in the ERP using the `external_id` field. Also, assuming the ERP products have variants, you can map the variants to Medusa's format, setting the variant's title and its ERP ID in the metadata. Finally, you pass the products to be created to the `createProductsWorkflow`, which is a built-in Medusa workflow that creates products. -Learn more about creating workflows and steps in [this documentation](undefined/docs/learn/fundamentals/workflows). +Learn more about creating workflows and steps in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md). -Find a detailed example of implementing this workflow in the [Odoo Integration guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/erp/odoo). +Find a detailed example of implementing this workflow in the [Odoo Integration guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/erp/odoo/index.html.md). ### 2. Create Scheduled Job to Sync Products @@ -118938,7 +120129,7 @@ export const config = { You create a scheduled job that runs once a day, executing the `syncFromErpWorkflow` to sync the products from the ERP to Medusa. -Learn more about creating scheduled jobs in [this documentation](undefined/docs/learn/fundamentals/scheduled-jobs). +Learn more about creating scheduled jobs in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs/index.html.md). *** @@ -118948,7 +120139,7 @@ Consider you store products in an ERP system with fixed prices, or prices based To do that, you can build a custom workflow that uses the ERP Module to retrieve the custom price of a product variant, then add the product to the cart with that price. -You can also follow [this guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/examples/guides/custom-item-price) for a step-by-step guide on how to add items with custom prices to the cart. +You can also follow [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/examples/guides/custom-item-price/index.html.md) for a step-by-step guide on how to add items with custom prices to the cart. ### 1. Create Step to Get Variant Price @@ -118985,7 +120176,7 @@ export const getVariantErpPriceStep = createStep( You create the step using the `createStep` from the Workflows SDK. The step has a function that receives the variant's ID in the ERP, the currency code, and the quantity as input. -The function then resolves the ERP Module's service from the [Medusa container](undefined/docs/learn/fundamentals/medusa-container) and, assuming you have a `getErpPrice` method in your ERP Module's service, you call it to retrieve that price, and return it multiplied by the quantity. +The function then resolves the ERP Module's service from the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md) and, assuming you have a `getErpPrice` method in your ERP Module's service, you call it to retrieve that price, and return it multiplied by the quantity. ### 2. Create Custom Add-to-Cart Workflow @@ -119062,7 +120253,7 @@ export const addCustomToCartWorkflow = createWorkflow( ) ``` -In this workflow, you first fetch the details of the cart and the variant from the database using the [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep) that Medusa defines. +In this workflow, you first fetch the details of the cart and the variant from the database using the [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md) that Medusa defines. Then, you use the `getVariantErpPriceStep` you created to retrieve the price from the ERP. You pass it the variant's ERP ID, supposedly stored in the variant's metadata as shown in the [previous section](#1-create-workflow-to-sync-products), the cart's currency code, and the quantity of the item. @@ -119070,7 +120261,7 @@ Finally, you prepare the item to be added to the cart, setting the unit price to ### 3. Execute Workflow in API Route -To allow clients to add products to the cart with custom prices, you can create an [API route](undefined/docs/learn/fundamentals/api-routes) that exposes the workflow's functionality. An API Route is an endpoint that exposes commerce features to external applications and clients, such as storefronts. +To allow clients to add products to the cart with custom prices, you can create an [API route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) that exposes the workflow's functionality. An API Route is an endpoint that exposes commerce features to external applications and clients, such as storefronts. For example, you can create the following API route: @@ -119100,7 +120291,7 @@ export const POST = async ( In this API route, you receive the cart's ID from the route's parameters, and the item to be added to the cart from the request body. You then call the `addCustomToCartWorkflow` to add the item to the cart with the custom price. -Learn more about how to create an API route in [this documentation](undefined/docs/learn/fundamentals/api-routes). You can also add request body validation as explained in [this documentation](undefined/docs/learn/fundamentals/api-routes/validation). +Learn more about how to create an API route in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). You can also add request body validation as explained in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/validation/index.html.md). *** @@ -119108,9 +120299,9 @@ Learn more about how to create an API route in [this documentation](undefined/do Your ERP may store restrictions on who can purchase what products. For example, you may allow only some companies to purchase certain products. -Since Medusa implements the add-to-cart functionality within a workflow, it allows you to inject custom logic into the workflow using [workflow hooks](undefined/docs/learn/fundamentals/workflows/workflow-hooks). A workflow hook is a point in a workflow where you can inject a step and perform a custom functionality. +Since Medusa implements the add-to-cart functionality within a workflow, it allows you to inject custom logic into the workflow using [workflow hooks](https://docs.medusajs.com/docs/learn/fundamentals/workflows/workflow-hooks/index.html.md). A workflow hook is a point in a workflow where you can inject a step and perform a custom functionality. -So, to implement the use case of product-purchase restriction, you can use the `validate` hook of the `addToCartWorkflow` or the [completeCartWorkflow](undefined/references/medusa-workflows/completeCartWorkflow) to check if the customer is allowed to purchase the product. For example: +So, to implement the use case of product-purchase restriction, you can use the `validate` hook of the `addToCartWorkflow` or the [completeCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/completeCartWorkflow/index.html.md) to check if the customer is allowed to purchase the product. For example: ```ts title="src/workflows/hooks/validate-purchase.ts" import { MedusaError } from "@medusajs/framework/utils" @@ -119155,13 +120346,13 @@ addToCartWorkflow.hooks.validate( You consume a hook using the workflow's `hooks` property. In the above example, you consume the `validate` hook of the `addToCartWorkflow` to inject a step. -In the step, you resolve the ERP Module's service, the Product Module's service, and the Customer Module's service from the [Medusa container](undefined/docs/learn/fundamentals/medusa-container). You then retrieve the cart's customer and the product variants to be added to the cart. +In the step, you resolve the ERP Module's service, the Product Module's service, and the Customer Module's service from the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md). You then retrieve the cart's customer and the product variants to be added to the cart. Then, for each product variant, you use a `canCompanyPurchaseProduct` method in the ERP Module's service that checks if the customer's company is allowed to purchase the product. If not, you throw a `MedusaError` with a message that the company is not allowed to purchase the product. So, only customers who are allowed in the ERP system to purchase a product can add it to the cart. -Learn more about workflow hooks and how to consume them in [this documentation](undefined/docs/learn/fundamentals/workflows/workflow-hooks). +Learn more about workflow hooks and how to consume them in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/workflow-hooks/index.html.md). *** @@ -119171,7 +120362,7 @@ After a customer places an order in Medusa, you may want to sync the order to th As explained earlier, workflows facilitate the orchestration of operations across systems while maintaining data consistency. So, you can create two workflows: -1. A workflow that syncs the order from Medusa to the ERP system. You can execute this workflow in a [subscriber](undefined/docs/learn/fundamentals/events-and-subscribers) that is triggered when an order is created in Medusa. +1. A workflow that syncs the order from Medusa to the ERP system. You can execute this workflow in a [subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md) that is triggered when an order is created in Medusa. 2. A workflow that syncs the order from the ERP system back to Medusa. Then, you can create a webhook listener in Medusa that executes the workflow, and use the webhook in the ERP system to send order updates to Medusa. ### 1. Sync Order to ERP @@ -119252,7 +120443,7 @@ You first create a `syncOrderToErpStep` that receives an order's details, resolv Notice that you pass to `createStep` a third-parameter function. This is the compensation function that defines how to rollback changes. So, when an error occurs during the workflow's execution, the step deletes the order from the ERP system. This ensures that the data remains consistent across systems. -Learn more about the compensation function in [this documentation](undefined/docs/learn/fundamentals/workflows/compensation-function). +Learn more about the compensation function in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/compensation-function/index.html.md). Then, you create a `syncOrderToErpWorkflow` that retrieves the order's details from the database using the `useQueryGraphStep`, then executes the `syncOrderToErpStep` to sync the order to the ERP system. Finally, you update the order in Medusa to set the ERP order's ID in the `metadata` field. @@ -119286,7 +120477,7 @@ export const config: SubscriberConfig = { You create a subscriber that listens to the `order.placed` event. When the event is triggered, the subscriber executes the `syncOrderToErpWorkflow` to sync the order to the ERP system. -Learn more about events and subscribers in [this documentation](undefined/docs/learn/fundamentals/events-and-subscribers). +Learn more about events and subscribers in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md). ### 2. Sync Order from ERP to Medusa @@ -119383,7 +120574,7 @@ You configure the body parser of `POST` requests to the `/erp/order-updates` rou You can now receive webhook requests from your ERP system and sync the order data back to Medusa. -Learn more about middlewares in [this documentation](undefined/docs/learn/fundamentals/api-routes/middlewares). +Learn more about middlewares in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md). *** @@ -119391,7 +120582,7 @@ Learn more about middlewares in [this documentation](undefined/docs/learn/fundam An ERP system often manages the inventory of products, with the ability to track the stock levels and availability of products. When a customer is purchasing a product through Medusa, you want to ensure that the product is available in the ERP system before allowing the purchase. -Similar to the [product-purchase restriction](#restrict-purchase-with-custom-erp-rules) use case, you can use the `validate` hook of the `addToCartWorkflow` or the [completeCartWorkflow](undefined/references/medusa-workflows/completeCartWorkflow) to check the product's availability in the ERP system. For example: +Similar to the [product-purchase restriction](#restrict-purchase-with-custom-erp-rules) use case, you can use the `validate` hook of the `addToCartWorkflow` or the [completeCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/completeCartWorkflow/index.html.md) to check the product's availability in the ERP system. For example: ```ts title="src/workflows/hooks/validate-inventory.ts" import { MedusaError } from "@medusajs/framework/utils" @@ -119437,7 +120628,7 @@ So, only products that have sufficient quantity in the ERP system can be added t The use cases covered in this guide are some common ERP integration scenarios that you can implement with Medusa. However, you can implement more use cases based on your ERP system's capabilities and your business requirements. -Refer to the [main documentation](undefined/docs/learn) to learn more about Medusa's concepts and how to implement customizations. You can also use the feedback form at the end of this guide to suggest more use cases you'd like to see implemented. +Refer to the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md) to learn more about Medusa's concepts and how to implement customizations. You can also use the feedback form at the end of this guide to suggest more use cases you'd like to see implemented. # Marketplace Recipe: Restaurant-Delivery Example @@ -119473,15 +120664,15 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll first be asked for the project's name. You can also optionally choose to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter). +You'll first be asked for the project's name. You can also optionally choose to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md). Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name. If you chose to install the Next.js starter, it'll be installed in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more about Medusa's architecture in [this documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more about Medusa's architecture in [this documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credential and submit the form. Afterwards, you can login with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** @@ -119564,7 +120755,7 @@ class RestaurantModuleService extends MedusaService({ export default RestaurantModuleService ``` -The service extends the [service factory](undefined/docs/learn/fundamentals/modules/service-factory), which provides basic data-management features. +The service extends the [service factory](https://docs.medusajs.com/docs/learn/fundamentals/modules/service-factory/index.html.md), which provides basic data-management features. ### Create Restaurant Module Definition @@ -119598,8 +120789,8 @@ module.exports = defineConfig({ ### Further Reads -- [How to Create a Module](undefined/docs/learn/fundamentals/modules) -- [How to Create a Data Model](undefined/docs/learn/fundamentals/modules#1-create-data-model) +- [How to Create a Module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) +- [How to Create a Data Model](https://docs.medusajs.com/docs/learn/fundamentals/modules#1-create-data-model/index.html.md) *** @@ -119708,7 +120899,7 @@ class DeliveryModuleService extends MedusaService({ export default DeliveryModuleService ``` -The service extends the [service factory](undefined/docs/learn/fundamentals/modules/service-factory), which provides basic data-management features. +The service extends the [service factory](https://docs.medusajs.com/docs/learn/fundamentals/modules/service-factory/index.html.md), which provides basic data-management features. ### Create Delivery Module Definition @@ -119839,7 +121030,7 @@ This defines a link between the Delivery Module’s `delivery` data model and th ### Further Reads -- [How to Define Links](undefined/docs/learn/fundamentals/module-links) +- [How to Define Links](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md) *** @@ -120035,13 +121226,13 @@ curl -X POST 'http://localhost:9000/restaurants' \ The API route creates a restaurant and returns it. -If you’re calling this API route from a frontend client, make sure to set the [CORS middleware](undefined/docs/learn/fundamentals/api-routes/cors) on it since it’s not under the `/store` or `/admin` route prefixes. +If you’re calling this API route from a frontend client, make sure to set the [CORS middleware](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/cors/index.html.md) on it since it’s not under the `/store` or `/admin` route prefixes. ### Further Reads -- [How to Create a Workflow](undefined/docs/learn/fundamentals/workflows) -- [What is a Compensation Function](undefined/docs/learn/fundamentals/workflows/compensation-function) -- [How to Create an API route](undefined/docs/learn/fundamentals/api-routes) +- [How to Create a Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) +- [What is a Compensation Function](https://docs.medusajs.com/docs/learn/fundamentals/workflows/compensation-function/index.html.md) +- [How to Create an API route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) *** @@ -120112,8 +121303,8 @@ This returns the list of restaurants in the response. ### Further Reads -- [What is and how to use it](undefined/docs/learn/fundamentals/module-links/query) -- [How to Retrieve Prices for Product Variants](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/product/guides/price) +- [What is and how to use it](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) +- [How to Retrieve Prices for Product Variants](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/product/guides/price/index.html.md) *** @@ -120462,7 +121653,7 @@ This returns the created driver user. ### Further Reads -- [How to Create an Actor Type](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/create-actor-type) +- [How to Create an Actor Type](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/create-actor-type/index.html.md) *** @@ -120961,7 +122152,7 @@ In this step, you’ll create the workflow that handles the different stages of For example, when a restaurant finishes preparing the order’s items, this workflow creates a fulfillment for the order. -This workflow will be a [long-running workflow](undefined/docs/learn/fundamentals/workflows/long-running-workflow) that runs asynchronously in the background. Its async steps only succeed once an outside action sets its status, allowing the workflow to move to the next step. +This workflow will be a [long-running workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/long-running-workflow/index.html.md) that runs asynchronously in the background. Its async steps only succeed once an outside action sets its status, allowing the workflow to move to the next step. API routes that perform actions related to the delivery, which you’ll create later, will trigger the workflow to move to the next step. @@ -120975,7 +122166,7 @@ Steps that have a `*` next to their names are async steps. - [notifyRestaurantStep\*](#create-notifyRestaurantStep): An async step that omits an event to notify restaurants of the new order. - [awaitDriverClaimStep\*](#create-awaitDriverClaimStep): An async step that’s executed once the restaurant accepts the order. It waits until a driver claims the delivery. - [createOrderStep](#create-createOrderStep): Creates an order once a driver claims the delivery. It also returns links to be created by the next step. -- [createRemoteLinkStep](undefined/references/helper-steps/createRemoteLinkStep): Creates the links returned by the previous step between the order and delivery. This is from Medusa's core workflows. +- [createRemoteLinkStep](https://docs.medusajs.com/references/helper-steps/createRemoteLinkStep/index.html.md): Creates the links returned by the previous step between the order and delivery. This is from Medusa's core workflows. - [awaitStartPreparationStep\*](#create-awaitStartPreparationStep): An async step that waits until the restaurant changes the delivery’s status to \`restaurant\_preparing\`. - [awaitPreparationStep\*](#create-awaitPreparationStep): An async step that once the restaurant changes the delivery’s status to preparing, waits until the restaurant changes the delivery’s status to \`ready\_for\_pickup\`. - [createFulfillmentStep](#create-createFulfillmentStep): Creates a fulfillment after the restaurant changes the delivery’s status to \`ready\_for\_pickup\`. @@ -121392,7 +122583,7 @@ In the next steps, you’ll execute the workflow and see it in action as you add ### Further Reads -- [Long-Running Workflows](undefined/docs/learn/fundamentals/workflows/long-running-workflow) +- [Long-Running Workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/long-running-workflow/index.html.md) *** @@ -122482,7 +123673,7 @@ As the route sets the status of the `awaitDeliveryStep` to successful in the `ha In this step, you’ll learn how to implement real-time tracking of a delivery in a Next.js-based storefront. -You can use a custom Next.js project, or use Medusa's Next.js Starter storefront. If you haven't installed the Next.js Starter storefront in the first step, refer to [this documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter#approach-2-install-separately) to learn how to install it. +You can use a custom Next.js project, or use Medusa's Next.js Starter storefront. If you haven't installed the Next.js Starter storefront in the first step, refer to [this documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter#approach-2-install-separately/index.html.md) to learn how to install it. ### Subscribe Route @@ -122698,13 +123889,13 @@ The next steps of this example depend on your use case. This section provides so ### Admin Development -The Medusa Admin is extendable, allowing you to add widgets to existing pages or create new pages. Learn more about it in [this documentation](undefined/docs/learn/fundamentals/admin). +The Medusa Admin is extendable, allowing you to add widgets to existing pages or create new pages. Learn more about it in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/admin/index.html.md). ### Storefront Development Medusa provides a Next.js Starter storefront that you can customize to your use case. -You can also create a custom storefront. Check out the [Storefront Development](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development) section to learn how to create a storefront. +You can also create a custom storefront. Check out the [Storefront Development](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/index.html.md) section to learn how to create a storefront. # Marketplace Recipe: Vendors Example @@ -122744,25 +123935,25 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll first be asked for the project's name. You can also optionally choose to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter). +You'll first be asked for the project's name. You can also optionally choose to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md). Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name. If you chose to install the Next.js starter, it'll be installed in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more about Medusa's architecture in [this documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more about Medusa's architecture in [this documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credential and submit the form. Afterwards, you can login with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** ## Step 2: Create Marketplace Module -To add custom tables to the database, which are called data models, you create a [module](undefined/docs/learn/fundamentals/modules). A module is a re-usable package with functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. +To add custom tables to the database, which are called data models, you create a [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). A module is a re-usable package with functionalities related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. In this step, you'll create a Marketplace Module that holds the data models for a vendor and an admin and allows you to manage them. -Learn more about modules in [this documentation](undefined/docs/learn/fundamentals/modules). +Learn more about modules in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). ### Create Module Directory @@ -122772,7 +123963,7 @@ A module is created under the `src/modules` directory of your Medusa application A data model represents a table in the database. You create data models using Medusa's Data Model Language (DML). It simplifies defining a table's columns, relations, and indexes with straightforward methods and configurations. -Learn more about data models in [this documentation](undefined/docs/learn/fundamentals/modules#1-create-data-model). +Learn more about data models in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#1-create-data-model/index.html.md). In the Marketplace Module, you'll create two data models: @@ -122811,7 +124002,7 @@ You define the following properties for the `Vendor` data model: - `logo`: The logo image of a vendor. - `admins`: The admins of a vendor. It's a relation to the `VendorAdmin` data model which you'll create next. -Learn more about data model [properties](undefined/docs/learn/fundamentals/data-models/properties) and [relations](undefined/docs/learn/fundamentals/data-models/relationships). +Learn more about data model [properties](https://docs.medusajs.com/docs/learn/fundamentals/data-models/properties/index.html.md) and [relations](https://docs.medusajs.com/docs/learn/fundamentals/data-models/relationships/index.html.md). Then, to create the `VendorAdmin` data model, create the file `src/modules/marketplace/models/vendor-admin.ts` with the following content: @@ -122844,7 +124035,7 @@ The `VendorAdmin` data model has the following properties: You define data-management methods of your data models in a service. A service is a TypeScript or JavaScript class that the module exports. In the service's methods, you can perform database operations. -Learn more about services in [this documentation](undefined/docs/learn/fundamentals/modules#2-create-service). +Learn more about services in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#2-create-service/index.html.md). In this section, you'll create the Marketplace Module's service. Create the file `src/modules/marketplace/service.ts` with the following content: @@ -122865,7 +124056,7 @@ The `MarketplaceModuleService` extends `MedusaService` from the Modules SDK whic So, the `MarketplaceModuleService` class now has methods like `createVendors` and `retrieveVendorAdmin`. -Find all methods generated by the `MedusaService` in [this reference](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference). +Find all methods generated by the `MedusaService` in [this reference](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/index.html.md). You'll use this service in later steps to store and manage vendors and vendor admins. @@ -122914,7 +124105,7 @@ Each object in the `modules` array has a `resolve` property, whose value is eith Since data models represent tables in the database, you define how they're created in the database with migrations. A migration is a TypeScript or JavaScript file that defines database changes made by a module. -Learn more about migrations in [this documentation](undefined/docs/learn/fundamentals/modules#5-generate-migrations). +Learn more about migrations in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#5-generate-migrations/index.html.md). Medusa's CLI tool generates the migrations for you. To generate a migration for the Marketplace Module, run the following command in your Medusa application's directory: @@ -122934,19 +124125,19 @@ This will create the tables for the Marketplace Module's data models in the data ### Further Reads -- [How to Create a Module](undefined/docs/learn/fundamentals/modules) +- [How to Create a Module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) *** ## Step 3: Define Links to Product and Order Data Models -Modules are [isolated](undefined/docs/learn/fundamentals/modules/isolation) to ensure they're re-usable and don't have side effects when integrated into the Medusa application. So, to build associations between modules, you define [module links](undefined/docs/learn/fundamentals/module-links). A Module link associates two modules' data models while maintaining module isolation. +Modules are [isolated](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md) to ensure they're re-usable and don't have side effects when integrated into the Medusa application. So, to build associations between modules, you define [module links](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md). A Module link associates two modules' data models while maintaining module isolation. -Learn more about module links in [this documentation](undefined/docs/learn/fundamentals/module-links). +Learn more about module links in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md). Each vendor should have products and orders. So, in this step, you’ll define links between the `Vendor` data model and the `Product` and `Order` data models from the Product and Order modules, respectively. -If your use case requires linking the vendor to other data models, such as `SalesChannel` from the [Sales Channel Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/sales-channel), define those links in a similar manner. +If your use case requires linking the vendor to other data models, such as `SalesChannel` from the [Sales Channel Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/sales-channel/index.html.md), define those links in a similar manner. To define a link between the `Vendor` and `Product` data models, create the file `src/links/vendor-product.ts` with the following content: @@ -123001,7 +124192,7 @@ This command runs any pending migrations and syncs link definitions to the datab ### Further Read -- [How to Define Module Links](undefined/docs/learn/fundamentals/module-links) +- [How to Define Module Links](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md) *** @@ -123009,20 +124200,20 @@ This command runs any pending migrations and syncs link definitions to the datab Before proceeding further, you need to understand some concepts related to authenticating users, especially those of custom actor types. -An [actor type](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types#actor-types) is a type of user that can send an authenticated requests. Medusa has two default actor types: `customer` for customers, and `admin` for admin users. +An [actor type](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types#actor-types/index.html.md) is a type of user that can send an authenticated requests. Medusa has two default actor types: `customer` for customers, and `admin` for admin users. You can also create custom actor types, allowing you to authenticate your custom users to specific routes. In this recipe, your custom actor type would be the vendor's admin. When you create a user of the actor type (for example, a vendor admin), you must: 1. Retrieve a registration JWT token. Medusa has a `/auth/{actor_type}/emailpass/register` route to retrieve a registration JWT token for the specified actor type. -2. Create the user. This requires creating the user in the database, and associate an [auth identity](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types#what-is-an-auth-identity) with that user. An auth identity allows this user to later send authenticated requests. +2. Create the user. This requires creating the user in the database, and associate an [auth identity](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types#what-is-an-auth-identity/index.html.md) with that user. An auth identity allows this user to later send authenticated requests. 3. Retrieve an authenticated JWT token using Medusa's `/auth/{actor_type}/emailpass` route, which retrieves the token for the specified actor type if the credentials in the request body match a user in the database. In the next steps, you'll implement the logic to create a vendor and its admin around the above authentication flow. You can also refer to the following documentation pages to learn more about authentication in Medusa: -- [Auth Identities and Actor Types](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types) -- [Authentication Routes](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route) +- [Auth Identities and Actor Types](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types/index.html.md) +- [Authentication Routes](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route/index.html.md) *** @@ -123034,14 +124225,14 @@ A workflow is a series of queries and actions, called steps, that complete a tas In this step, you’ll create the workflow used to create a vendor and its admin. You'll use it in the next step in an API route. -Learn more about workflows in [this documentation](undefined/docs/learn/fundamentals/workflows) +Learn more about workflows in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) The workflow’s steps are: - [createVendorStep](#createvendorstep): Create the vendor. - [createVendorAdminStep](#createvendoradminstep): Create the vendor admin. -- [setAuthAppMetadataStep](undefined/references/medusa-workflows/steps/setAuthAppMetadataStep): Associate the vendor admin with its auth identity of actor type \`vendor\`. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the created vendor with its admins. +- [setAuthAppMetadataStep](https://docs.medusajs.com/references/medusa-workflows/steps/setAuthAppMetadataStep/index.html.md): Associate the vendor admin with its auth identity of actor type \`vendor\`. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the created vendor with its admins. Medusa provides the last two steps through its `@medusajs/medusa/core-flows` package. So, you only need to implement the first two steps. @@ -123095,7 +124286,7 @@ You create a step with `createStep` from the Workflows SDK. It accepts three par 1. The step's unique name, which is `create-vendor`. 2. An async function that receives two parameters: - An input object with the details of the vendor to create. - - The [Medusa container](undefined/docs/learn/fundamentals/medusa-container), which is a registry of Framework and commerce tools that you can access in the step. + - The [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which is a registry of Framework and commerce tools that you can access in the step. 3. An async compensation function. This function is only executed when an error occurs in the workflow. It undoes the changes made by the step. In the step function, you resolve the Marketplace Module's service from the container. Then, you use the service's generated `createVendors` method to create the vendor. @@ -123247,9 +124438,9 @@ In the workflow function, you run the following steps: 1. `createVendorStep` to create the vendor. 2. `createVendorAdminStep` to create the vendor admin. - - Notice that you use `transform` from the Workflows SDK to prepare the data you pass into the step. Medusa doesn't allow direct manipulation of variables within the worflow's constructor function. Learn more in the [Data Manipulation in Workflows documentation](undefined/docs/learn/fundamentals/workflows/variable-manipulation). + - Notice that you use `transform` from the Workflows SDK to prepare the data you pass into the step. Medusa doesn't allow direct manipulation of variables within the worflow's constructor function. Learn more in the [Data Manipulation in Workflows documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/variable-manipulation/index.html.md). 3. `setAuthAppMetadataStep` to associate the vendor admin with its auth identity of actor type `vendor`. This will allow the vendor admin to send authenticated requests afterwards. -4. `useQueryGraphStep` to retrieve the created vendor with its admins using [Query](undefined/docs/learn/fundamentals/module-links/query). Query allows you to retrieve data across modules. +4. `useQueryGraphStep` to retrieve the created vendor with its admins using [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md). Query allows you to retrieve data across modules. A workflow must return a `WorkflowResponse` instance. It accepts as a parameter the data to return, which is the vendor in this case. @@ -123257,10 +124448,10 @@ In the next step, you'll learn how to execute the workflow in an API route. ### Further Read -- [How to Create a Workflow](undefined/docs/learn/fundamentals/workflows) -- [What is an Actor Type](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types) -- [How to Create an Actor Type](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/create-actor-type) -- [What is a Compensation Function](undefined/docs/learn/fundamentals/workflows/compensation-function) +- [How to Create a Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) +- [What is an Actor Type](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/auth-identity-and-actor-types/index.html.md) +- [How to Create an Actor Type](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/create-actor-type/index.html.md) +- [What is a Compensation Function](https://docs.medusajs.com/docs/learn/fundamentals/workflows/compensation-function/index.html.md) *** @@ -123268,7 +124459,7 @@ In the next step, you'll learn how to execute the workflow in an API route. Now that you've implemented the logic to create a vendor, you'll expose this functionality in an API route. An API Route is an endpoint that exposes commerce features to external applications and clients, such as storefronts or custom dashboards. -Learn more about API routes in [this documentation](undefined/docs/learn/fundamentals/api-routes). +Learn more about API routes in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). ### Create API Route @@ -123354,7 +124545,7 @@ To ensure that incoming request bodies contain the required parameters, and that A middleware is a function executed before the API route when a request is sent to it. Middlewares are useful to restrict access to an API route based on validation or authentication requirements. -Learn more about middlewares in [this documentation](undefined/docs/learn/fundamentals/api-routes/middlewares). +Learn more about middlewares in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md). You define middlewares in Medusa in the `src/api/middlewares.ts` special file. So, create the file `src/api/middlewares.ts` with the following content: @@ -123426,7 +124617,7 @@ You can replace the email and password with other credentials. Then, to create a vendor and its admin, send a request to the `/vendors` API route, passing the token retrieved from the previous response in the request header: -Don't include a trailing slash at the end of the URL. Learn more [here](undefined/docs/learn/fundamentals/api-routes/middlewares). +Don't include a trailing slash at the end of the URL. Learn more [here](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md). ```bash curl -X POST 'http://localhost:9000/vendors' \ @@ -123462,9 +124653,9 @@ Use this token in the header of later requests that require authentication. ### Further Reads -- [How to Create an API route](undefined/docs/learn/fundamentals/api-routes) -- [How to Create a Middleware](undefined/docs/learn/fundamentals/api-routes/middlewares) -- [Learn more about the /auth route](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route) +- [How to Create an API route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) +- [How to Create a Middleware](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md) +- [Learn more about the /auth route](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/auth/authentication-route/index.html.md) *** @@ -123478,11 +124669,11 @@ In this step, you'll create a workflow that creates a product, then use that wor The workflow to create a product has the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the default sales channel in the store. -- [createProductsWorkflow](undefined/references/medusa-workflows/createProductsWorkflow): Create the product. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the admin's vendor ID. -- [createRemoteLinkStep](undefined/references/helper-steps/createRemoteLinkStep): Create a link between the vendor and the product. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the created product's details. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the default sales channel in the store. +- [createProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createProductsWorkflow/index.html.md): Create the product. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the admin's vendor ID. +- [createRemoteLinkStep](https://docs.medusajs.com/references/helper-steps/createRemoteLinkStep/index.html.md): Create a link between the vendor and the product. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the created product's details. The workflow's steps are all provided by Medusa's `@medusajs/medusa/core-flows` package. So, you can create the workflow right away. @@ -123602,7 +124793,7 @@ You retrieve the ID of the admin's vendor. Then, you prepare the data to create Medusa provides a `createRemoteLinkStep` that allows you to create links between records of different modules. The step accepts as a parameter an array of link objects, where each object has the module name as the key and the ID of the record to link as the value. The modules must be passed in the same order they were passed in to `defineLink`. -Refer to the [Link](undefined/docs/learn/fundamentals/module-links/link) documentation to learn more about creating links. +Refer to the [Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md) documentation to learn more about creating links. Finally, you retrieve the created product's details using Query and return the product. @@ -123668,7 +124859,7 @@ export default defineMiddlewares({ }) ``` -Similar to before, you apply the `validateAndTransformBody` middleware on the `POST /vendors/products` API route. You pass to the middleware the `AdminCreateProduct` schema that Medusa uses to validate the request body of the [Create Product Admin API Route](undefined/api/admin#products_postproducts). +Similar to before, you apply the `validateAndTransformBody` middleware on the `POST /vendors/products` API route. You pass to the middleware the `AdminCreateProduct` schema that Medusa uses to validate the request body of the [Create Product Admin API Route](https://docs.medusajs.com/api/admin#products_postproducts). ### Test it Out @@ -123717,8 +124908,8 @@ This will return the created product. In the next step, you'll add API routes to ### Further Reads -- [How to use Query](undefined/docs/learn/fundamentals/module-links/query) -- [How to use Link](undefined/docs/learn/fundamentals/module-links/link) +- [How to use Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) +- [How to use Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md) *** @@ -123778,8 +124969,8 @@ Make sure to replace `{token}` with the authenticated token of the vendor admin ### Further Reads -- [How to use Query](undefined/docs/learn/fundamentals/module-links/query) -- [How to use Link](undefined/docs/learn/fundamentals/module-links/link) +- [How to use Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) +- [How to use Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md) *** @@ -123787,12 +124978,12 @@ Make sure to replace `{token}` with the authenticated token of the vendor admin In this step, you’ll create a workflow that’s executed when the customer places an order. It has the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the cart's details. -- [completeCartWorkflow](undefined/references/medusa-workflows/completeCartWorkflow): Create the parent order from the cart. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the cart's details. +- [completeCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/completeCartWorkflow/index.html.md): Create the parent order from the cart. - [groupVendorItemsStep](#groupvendoritemssstep): Group the items by their vendor. -- [getOrderDetailWorkflow](undefined/references/medusa-workflows/getOrderDetailWorkflow): Retrieve the parent order's details. +- [getOrderDetailWorkflow](https://docs.medusajs.com/references/medusa-workflows/getOrderDetailWorkflow/index.html.md): Retrieve the parent order's details. - [createVendorOrdersStep](#createvendorordersstep): Create child orders for each vendor. -- [createRemoteLinkStep](undefined/references/helper-steps/createRemoteLinkStep): Create links between vendors and orders. +- [createRemoteLinkStep](https://docs.medusajs.com/references/helper-steps/createRemoteLinkStep/index.html.md): Create links between vendors and orders. You only need to implement the third and fourth steps, as Medusa provides the rest of the steps in its `@medusajs/medusa/core-flows` package. @@ -124211,7 +125402,7 @@ Since you expose a `POST` function, you're exposing a `POST` API route at `/stor ### Test it Out -To test this out, it’s recommended to install the [Next.js Starter storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter). +To test this out, it’s recommended to install the [Next.js Starter storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md). Then, you need to customize the storefront to use your complete cart API route rather than Medusa's. In `src/lib/data/cart.ts`, find the following lines in the `src/lib/data/cart.ts`: @@ -124244,7 +125435,7 @@ const cartRes = await sdk.client.fetch( Now, the checkout flow uses your custom API route to place the order instead of Medusa's. -Refer to the [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk) documentation to learn more about using it. +Refer to the [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md) documentation to learn more about using it. Try going through the checkout flow now, purchasing a product that you created for the vendor earlier. The order should be placed successfully. @@ -124337,7 +125528,7 @@ The next steps of this example depend on your use case. This section provides so ### Use Existing Features -If you want vendors to perform actions that are available for admin users through Medusa's [Admin API routes](undefined/api/admin), such as managing their orders, you need to recreate them similar to the create product API route you created earlier. +If you want vendors to perform actions that are available for admin users through Medusa's [Admin API routes](https://docs.medusajs.com/api/admin), such as managing their orders, you need to recreate them similar to the create product API route you created earlier. ### Link Other Data Models to Vendors @@ -124345,17 +125536,17 @@ Similar to linking an order and a product to a vendor, you can link other data m For example, you can link sales channels or other settings to vendors. -[Learn more about module links](undefined/docs/learn/fundamentals/module-links). +[Learn more about module links](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md). ### Storefront Development Medusa provides a Next.js Starter storefront, which you can customize to fit your specific use case. -You can also create a custom storefront. Check out the [Storefront Development](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development) section to learn how to create a storefront. +You can also create a custom storefront. Check out the [Storefront Development](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/index.html.md) section to learn how to create a storefront. ### Admin Development -The Medusa Admin is extendable, allowing you to add custom widgets to existing pages or create entirely new pages. For example, you can add a new page showing the list of vendors. Learn more about it in [this documentation](undefined/docs/learn/fundamentals/admin). +The Medusa Admin is extendable, allowing you to add custom widgets to existing pages or create entirely new pages. For example, you can add a new page showing the list of vendors. Learn more about it in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/admin/index.html.md). Only super admins can access the Medusa Admin, not vendor admins. So, if you need a dashboard specific to each vendor admin, you will need to build a custom dashboard with the necessary features. @@ -124370,7 +125561,7 @@ This recipe provides the general steps to implement a marketplace in your Medusa A marketplace is an online commerce store that allows different vendors to sell their products within the same commerce system. Customers can purchase products from any of these vendors, and vendors can manage their orders separately. -Medusa's [Framework](undefined/docs/learn/fundamentals/framework) for customizations facilitates building a marketplace. You can create a Marketplace Module that implements custom data models, such as vendors or sellers, and link those data models to existing ones such as products and orders. You also expose custom features using API routes, and implement complex flows using workflows. +Medusa's [Framework](https://docs.medusajs.com/docs/learn/fundamentals/framework/index.html.md) for customizations facilitates building a marketplace. You can create a Marketplace Module that implements custom data models, such as vendors or sellers, and link those data models to existing ones such as products and orders. You also expose custom features using API routes, and implement complex flows using workflows. [How Foraged built a custom marketplace with Medusa](https://medusajs.com/blog/foraged/). @@ -124382,8 +125573,8 @@ In a marketplace, a business or a vendor has a user, and they can use that user You can create a marketplace module that implements data models for vendors, their admins, and any other data models that fit your use case. -- [Create a Module](undefined/docs/learn/fundamentals/modules): Learn how to create a module. -- [Create Data Models](undefined/docs/learn/fundamentals/modules#1-create-data-model): Create data models in the module. +- [Create a Module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md): Learn how to create a module. +- [Create Data Models](https://docs.medusajs.com/docs/learn/fundamentals/modules#1-create-data-model/index.html.md): Create data models in the module. *** @@ -124393,7 +125584,7 @@ Since a vendor has products, orders, and other models based on your use case, yo For example, if you defined a vendor data model in a marketplace module, you can define a module link between the vendor and the Product Module's product data model. This builds an association between a vendor and their products, allowing you to query and manage products based on the vendor. -[Define a Module Link](undefined/docs/learn/fundamentals/module-links): Learn how to define a module link. +[Define a Module Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md): Learn how to define a module link. *** @@ -124405,19 +125596,19 @@ When you build these API routes, it's essential that you protect them to only al Medusa supports creating custom actor types that can be authenticated with your custom API routes. -- [Create API Routes](undefined/docs/learn/fundamentals/api-routes): Learn how to create an API Route in Medusa. -- [Create an Actor Type](undefined/commerce-modules/auth/create-actor-type): Learn how to create an actor type and authenticate it. +- [Create API Routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md): Learn how to create an API Route in Medusa. +- [Create an Actor Type](https://docs.medusajs.com/commerce-modules/auth/create-actor-type/index.html.md): Learn how to create an actor type and authenticate it. *** ## Split Orders Based on Vendors -If your use case allows a customer's orders to have items from different vendors, you can replicate the [Complete Cart API route](undefined/api/store#carts_postcartsidcomplete) to customize the order creation process. +If your use case allows a customer's orders to have items from different vendors, you can replicate the [Complete Cart API route](https://docs.medusajs.com/api/store#carts_postcartsidcomplete) to customize the order creation process. In the API route, you can create a workflow that splits the order into multiple orders, one for each vendor. A workflow is a series of steps that provide features like rollback and retry mechanisms. -- [Replicate API Routes](undefined/docs/learn/fundamentals/api-routes/override): Learn how to replicate an existing API route. -- [Create a Workflow](undefined/docs/learn/fundamentals/workflows): Learn how to create a workflow in Medusa. +- [Replicate API Routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/override/index.html.md): Learn how to replicate an existing API route. +- [Create a Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md): Learn how to create a workflow in Medusa. *** @@ -124433,10 +125624,10 @@ The Medusa Admin is an extensible application within your Medusa application. Yo - **UI Routes**: Adding new pages to the Medusa Admin, such as a page to manage vendors. - **Settings Pages**: Adding new pages to the Medusa Admin settings, such as a page to manage marketplace settings. -- [Create Admin Widget](undefined/docs/learn/fundamentals/admin/widgets): Add widgets into existing admin pages. -- [Create Admin UI Routes](undefined/docs/learn/fundamentals/admin/ui-routes): Add new pages to your Medusa Admin. +- [Create Admin Widget](https://docs.medusajs.com/docs/learn/fundamentals/admin/widgets/index.html.md): Add widgets into existing admin pages. +- [Create Admin UI Routes](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md): Add new pages to your Medusa Admin. -[Create Admin Setting Page](undefined/docs/learn/fundamentals/admin/ui-routes#create-settings-page): Add new page to the Medusa Admin settings. +[Create Admin Setting Page](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes#create-settings-page/index.html.md): Add new page to the Medusa Admin settings. *** @@ -124446,7 +125637,7 @@ For more complex use cases, customizing the Medusa Admin may not be enough to al In that case, you can build a custom dashboard for vendors that allows them to manage their data. This dashboard can interact with Medusa's Admin API and the custom API routes you created for vendors to provide a seamless experience. -[Medusa Admin APIs](undefined/api/admin): Learn about available APIs for the Medusa Admin. +[Medusa Admin APIs](https://docs.medusajs.com/api/admin): Learn about available APIs for the Medusa Admin. *** @@ -124456,8 +125647,8 @@ Medusa provides a Next.js Starter Storefront to use with your application. You c Alternatively, you can build your own storefront using the Medusa APIs. This headless approach gives you the flexibility to build a custom storefront without limitations on which tech stack you use, or the design of the storefront. -- [Next.js Starter Storefront](undefined/nextjs-starter): Learn how to install and customize the Next.js Starter Storefront. -- [Storefront Development](undefined/storefront-development): Find useful guides for creating a custom storefront. +- [Next.js Starter Storefront](https://docs.medusajs.com/nextjs-starter/index.html.md): Learn how to install and customize the Next.js Starter Storefront. +- [Storefront Development](https://docs.medusajs.com/storefront-development/index.html.md): Find useful guides for creating a custom storefront. # Multi-Region Store Recipe @@ -124488,8 +125679,8 @@ Merchants can define tax regions, which are tax-related settings for a specific During checkout, Medusa calculates the taxes using the tax region settings of the customer's region and selected country in their shipping address. -- [Using Medusa Admin](undefined/user-guide/settings/tax-regions): Learn how to manage tax regions in the Medusa Admin -- [Using Admin APIs](undefined/api/admin#tax-regions_posttaxregions): Manage tax regions using the Admin APIs. +- [Using Medusa Admin](https://docs.medusajs.com/user-guide/settings/tax-regions/index.html.md): Learn how to manage tax regions in the Medusa Admin +- [Using Admin APIs](https://docs.medusajs.com/api/admin#tax-regions_posttaxregions): Manage tax regions using the Admin APIs. ### Payment and Fulfillment Providers @@ -124501,10 +125692,10 @@ During checkout, customers only see the payment providers configured for the reg Medusa provides official module providers for payment and fulfillment. You can also create custom module providers. -- [Manage Payment Providers in Medusa Admin](undefined/user-guide/settings/regions): Learn how to manage providers in a region. -- [Manage Fulfillment Providers in Medusa Admin](undefined/user-guide/settings/locations-and-shipping/locations#manage-fulfillment-providers): Learn how to manage providers in a location. -- [Integrations](undefined/integrations): Check out available integrations, including payment module providers. -- [Create Fulfillment Module Provider](undefined/references/fulfillment/provider): Learn how to create a fulfillment module provider. +- [Manage Payment Providers in Medusa Admin](https://docs.medusajs.com/user-guide/settings/regions/index.html.md): Learn how to manage providers in a region. +- [Manage Fulfillment Providers in Medusa Admin](https://docs.medusajs.com/user-guide/settings/locations-and-shipping/locations#manage-fulfillment-providers/index.html.md): Learn how to manage providers in a location. +- [Integrations](https://docs.medusajs.com/integrations/index.html.md): Check out available integrations, including payment module providers. +- [Create Fulfillment Module Provider](https://docs.medusajs.com/references/fulfillment/provider/index.html.md): Learn how to create a fulfillment module provider. *** @@ -124514,19 +125705,19 @@ Merchants set the price of shipping options and product variants per currency an Using the tax-inclusive feature, merchants can also specify prices including taxes per currency and region. Medusa then calculates the tax amount applied to a line item in the cart based on the region's tax configurations. -- [Setting Variant Prices in Medusa Admin](undefined/user-guide/products/variants#edit-product-variant-prices): Learn how to set a variant's prices in Medusa Admin. -- [Display Variant Price in Storefront](undefined/storefront-development/products/price): Learn how to display the correct product price in a storefront. +- [Setting Variant Prices in Medusa Admin](https://docs.medusajs.com/user-guide/products/variants#edit-product-variant-prices/index.html.md): Learn how to set a variant's prices in Medusa Admin. +- [Display Variant Price in Storefront](https://docs.medusajs.com/storefront-development/products/price/index.html.md): Learn how to display the correct product price in a storefront. *** ## Multi-Warehouse Support -Medusa's [Inventory](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/inventory) and [Stock Location](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/stock-location) Modules provide multi-warehouse features that allow merchants to manage inventory across different locations. Merchants then control which location an item in an order is fulfilled from, allowing them to keep a correct inventory count across locations and sales channels. +Medusa's [Inventory](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/inventory/index.html.md) and [Stock Location](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/stock-location/index.html.md) Modules provide multi-warehouse features that allow merchants to manage inventory across different locations. Merchants then control which location an item in an order is fulfilled from, allowing them to keep a correct inventory count across locations and sales channels. A multi-regional setup lets merchants manage their inventory through Medusa across the different regions they serve. Customers are always shown accurate inventory information based on the location associated with their sales channel. -- [Manage Stock Locations](undefined/user-guide/settings/locations-and-shipping/locations): Learn how to manage stock locations in the Medusa Admin. -- [Manage Inventory](undefined/user-guide/inventory): Learn how to manage inventory in the Medusa Admin. +- [Manage Stock Locations](https://docs.medusajs.com/user-guide/settings/locations-and-shipping/locations/index.html.md): Learn how to manage stock locations in the Medusa Admin. +- [Manage Inventory](https://docs.medusajs.com/user-guide/inventory/index.html.md): Learn how to manage inventory in the Medusa Admin. *** @@ -124534,10 +125725,10 @@ A multi-regional setup lets merchants manage their inventory through Medusa acro By integrating a third-party Content Management Systems (CMS), you benefit from rich content features including managing your content in multiple languages. This allows you to cater to customers’ different languages in the regions you serve. -To integrate a third-party system, create a custom module whose main service connects to that third-party service. You can also follow the [Contentful integration guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/integrations/guides/contentful) to learn how to integrate Contentful and benefit from localization features. +To integrate a third-party system, create a custom module whose main service connects to that third-party service. You can also follow the [Contentful integration guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/integrations/guides/contentful/index.html.md) to learn how to integrate Contentful and benefit from localization features. -- [Create a Module](undefined/docs/learn/fundamentals/modules): Learn how to create a module in Medusa. -- [Integrate Contentful](undefined/integrations/guides/contentful): Integrate Contentful with Localization Features. +- [Create a Module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md): Learn how to create a module in Medusa. +- [Integrate Contentful](https://docs.medusajs.com/integrations/guides/contentful/index.html.md): Integrate Contentful with Localization Features. # Omnichannel Commerce Recipe @@ -124550,7 +125741,7 @@ Merchants selling across different channels need an efficient way to manage thei Omnichannel commerce also provides customers a seamless shopping experience, regardless of where they’re shopping. Whether they’re buying your products from your online store, a marketplace like Amazon, or through social media, you provide them with a good experience and handle orders consistently. -Medusa’s modular architecture facilitates building omnichannel commerce, as your server and storefront aren’t tightly coupled. You can also use the [Sales Channel Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/sales-channel)'s features to expand your business into other avenues like marketplaces and social commerce. +Medusa’s modular architecture facilitates building omnichannel commerce, as your server and storefront aren’t tightly coupled. You can also use the [Sales Channel Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/sales-channel/index.html.md)'s features to expand your business into other avenues like marketplaces and social commerce. *** @@ -124560,7 +125751,7 @@ When creating an omnichannel commerce, you build multiple webshops or mobile app Medusa's commerce features are available as REST APIs that storefronts can access to provide these features for customers. This separation also gives you freedom in choosing the tech stack of the storefronts you’re creating. -[Store REST APIs](undefined/api/store): Check out available Store REST APIs in Medusa. +[Store REST APIs](https://docs.medusajs.com/api/store): Check out available Store REST APIs in Medusa. *** @@ -124576,10 +125767,10 @@ Then, in the custom module, integrate with Amazon’s seller program. You can th Another channel that attracts customer sales is social media. You can create a custom module that integrates with social media apps to show your products and sell them to customers. -- [Sales Channels](undefined/commerce-modules/sales-channel): Learn about the Sales Channel Module. -- [Create a Module](undefined/docs/learn/fundamentals/modules): Learn how to create a module. +- [Sales Channels](https://docs.medusajs.com/commerce-modules/sales-channel/index.html.md): Learn about the Sales Channel Module. +- [Create a Module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md): Learn how to create a module. -[Create a Workflow](undefined/docs/learn/fundamentals/workflows#1-create-workflow): Learn how to create a workflow. +[Create a Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows#1-create-workflow/index.html.md): Learn how to create a workflow. *** @@ -124594,10 +125785,10 @@ Medusa’s architecture also makes it easier to integrate any third-party servic - Expose the workflow's features in API routes. - Send requests to these API routes from your storefront. -- [Create a Module](undefined/docs/learn/fundamentals/modules): Learn how to create a module. -- [Create a Workflow](undefined/docs/learn/fundamentals/workflows): Learn how to create a workflow. +- [Create a Module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md): Learn how to create a module. +- [Create a Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md): Learn how to create a workflow. -[Create API Route](undefined/docs/learn/fundamentals/api-routes): Learn how to create an API route. +[Create API Route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md): Learn how to create an API route. # Order Management System (OMS) Recipe @@ -124608,7 +125799,7 @@ This recipe provides an overview of Medusa's features and how to use it as an Or Building or integrating an OMS brings certain challenges: accepting orders from different sales channels, tracking inventory across the sales channels, integrating third-party fulfillment and payment providers with the OMS, and more. -Medusa's Commerce Modules and [Framework](undefined/docs/learn/fundamentals/framework) for customizations allows you to integrate it within a larger ecosystem. The Commerce Modules provide features to allow businesses to accept orders from any sales channel, benefit from multi-warehouse inventory features, and integrate third-party services for fulfillment, payment, and more. +Medusa's Commerce Modules and [Framework](https://docs.medusajs.com/docs/learn/fundamentals/framework/index.html.md) for customizations allows you to integrate it within a larger ecosystem. The Commerce Modules provide features to allow businesses to accept orders from any sales channel, benefit from multi-warehouse inventory features, and integrate third-party services for fulfillment, payment, and more. [How Siam Makro used Medusa an OMS](https://medusajs.com/blog/makro-pro/). @@ -124620,16 +125811,16 @@ Sales channels in your commerce ecosystem must route their orders into the OMS. ![Routing orders into Medusa OMS](https://res.cloudinary.com/dza7lstvk/image/upload/v1709032160/Medusa%20Book/oms-orders_zf5ta9.jpg) -Medusa's [Store REST APIs](undefined/api/store) let you integrate a checkout experience in any storefront. Alternatively, you can use Medusa's [Draft Order APIs](undefined/api/admin#draft-orders) to place an order without direct involvement from the customer, such as when placing an order through a POS. +Medusa's [Store REST APIs](https://docs.medusajs.com/api/store) let you integrate a checkout experience in any storefront. Alternatively, you can use Medusa's [Draft Order APIs](https://docs.medusajs.com/api/admin#draft-orders) to place an order without direct involvement from the customer, such as when placing an order through a POS. In addition, you can customize the Medusa application to accept orders through a third-party checkout system. This gives you more flexibility over adding orders to Medusa. For example, you can support importing orders into Medusa through a custom API Route that allows batch-inserting orders. Another example is creating a scheduled job that runs at a specified interval and imports orders from a third-party service. -- [Store REST APIs](undefined/api/store#carts): Learn how to use the Store REST APIs to create an order. -- [Create API Route](undefined/docs/learn/fundamentals/api-routes): Learn how to create a custom API Route. +- [Store REST APIs](https://docs.medusajs.com/api/store#carts): Learn how to use the Store REST APIs to create an order. +- [Create API Route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md): Learn how to create a custom API Route. -[Create Scheduled Jobs](undefined/docs/learn/fundamentals/scheduled-jobs): Learn how to create a scheduled job. +[Create Scheduled Jobs](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs/index.html.md): Learn how to create a scheduled job. *** @@ -124643,10 +125834,10 @@ Medusa uses the Fulfillment Module whenever a fulfillment action is performed, s In addition, you can create a subscriber that listens to fulfillment-related events, such as the `order.fulfillment_created` event, to perform actions with the third-party fulfillment provider. -- [Create a Fulfillment Module Provider](undefined/references/fulfillment/provider): Learn how to create a fulfillment provider in Medusa. -- [Order Events](undefined/references/order/events): Learn about the events emitted related to the Order Module +- [Create a Fulfillment Module Provider](https://docs.medusajs.com/references/fulfillment/provider/index.html.md): Learn how to create a fulfillment provider in Medusa. +- [Order Events](https://docs.medusajs.com/references/order/events/index.html.md): Learn about the events emitted related to the Order Module -[Create a Subscriber](undefined/docs/learn/fundamentals/events-and-subscribers): Learn about create a subscriber +[Create a Subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md): Learn about create a subscriber *** @@ -124656,10 +125847,10 @@ To integrate third-party payment providers with the Medusa application, you can In addition, you can create a subscriber that listen to payment-related events, such as the `payment.captured` event, to perform actions in the third-party payment provider. -- [Create a Payment Module Provider](undefined/references/payment/provider): Learn how to create a payment module provider. -- [Payment Events](undefined/references/payment/events): Learn about the events emitted related to the Payment Module +- [Create a Payment Module Provider](https://docs.medusajs.com/references/payment/provider/index.html.md): Learn how to create a payment module provider. +- [Payment Events](https://docs.medusajs.com/references/payment/events/index.html.md): Learn about the events emitted related to the Payment Module -[Create a Subscriber](undefined/docs/learn/fundamentals/events-and-subscribers): Learn about create a subscriber +[Create a Subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md): Learn about create a subscriber *** @@ -124671,10 +125862,10 @@ When an order is placed, the item's quantity is reserved from the stock location Once the item is fulfilled, the reserved quantity is deducted from the item's inventory quantity. -- [Inventory Module](undefined/commerce-modules/inventory): Learn about the Inventory Module's concepts and features. -- [Stock Location Module](undefined/commerce-modules/stock-location): Learn about the Stock Location Module's concepts and features. +- [Inventory Module](https://docs.medusajs.com/commerce-modules/inventory/index.html.md): Learn about the Inventory Module's concepts and features. +- [Stock Location Module](https://docs.medusajs.com/commerce-modules/stock-location/index.html.md): Learn about the Stock Location Module's concepts and features. -[Sales Channel Module](undefined/commerce-modules/sales-channel): Learn about the Sales Channel Module's concepts and features. +[Sales Channel Module](https://docs.medusajs.com/commerce-modules/sales-channel/index.html.md): Learn about the Sales Channel Module's concepts and features. *** @@ -124686,10 +125877,10 @@ When changes are made to an order by any of the mentioned actions, the changes a Medusa also emits events related to these actions, such as `order.return_requested`. So, you can build a workflow that performs actions with the third-party fulfillment and payment providers, then execute it in a subscriber that's triggered whenever the event is emitted. -- [Order Changes](undefined/commerce-modules/order/order-change): Learn about how to use order changes. -- [Order Events](undefined/references/order/events): Learn about the events emitted related to the Order Module -- [Create a Workflow](undefined/docs/learn/fundamentals/workflows): Learn how to create a workflow. -- [Create a Subscriber](undefined/docs/learn/fundamentals/events-and-subscribers): Learn about create a subscriber +- [Order Changes](https://docs.medusajs.com/commerce-modules/order/order-change/index.html.md): Learn about how to use order changes. +- [Order Events](https://docs.medusajs.com/references/order/events/index.html.md): Learn about the events emitted related to the Order Module +- [Create a Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md): Learn how to create a workflow. +- [Create a Subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md): Learn about create a subscriber # Recipes @@ -124698,19 +125889,19 @@ This section of the documentation provides recipes for common use cases with exa ## Recipes -- [Marketplace](undefined/recipes/marketplace) -- [Subscriptions](undefined/recipes/subscriptions) -- [Digital Products](undefined/recipes/digital-products) -- [Integrate ERP](undefined/recipes/erp) -- [B2B](undefined/recipes/b2b) -- [Bundled Products](undefined/recipes/bundled-products) -- [Commerce Automation](undefined/recipes/commerce-automation) -- [Ecommerce](undefined/recipes/ecommerce) -- [Multi-Region Store](undefined/recipes/multi-region-store) -- [Omnichannel Store](undefined/recipes/omnichannel) -- [OMS](undefined/recipes/oms) -- [Personalized Products](undefined/recipes/personalized-products) -- [POS](undefined/recipes/pos) +- [Marketplace](https://docs.medusajs.com/recipes/marketplace/index.html.md) +- [Subscriptions](https://docs.medusajs.com/recipes/subscriptions/index.html.md) +- [Digital Products](https://docs.medusajs.com/recipes/digital-products/index.html.md) +- [Integrate ERP](https://docs.medusajs.com/recipes/erp/index.html.md) +- [B2B](https://docs.medusajs.com/recipes/b2b/index.html.md) +- [Bundled Products](https://docs.medusajs.com/recipes/bundled-products/index.html.md) +- [Commerce Automation](https://docs.medusajs.com/recipes/commerce-automation/index.html.md) +- [Ecommerce](https://docs.medusajs.com/recipes/ecommerce/index.html.md) +- [Multi-Region Store](https://docs.medusajs.com/recipes/multi-region-store/index.html.md) +- [Omnichannel Store](https://docs.medusajs.com/recipes/omnichannel/index.html.md) +- [OMS](https://docs.medusajs.com/recipes/oms/index.html.md) +- [Personalized Products](https://docs.medusajs.com/recipes/personalized-products/index.html.md) +- [POS](https://docs.medusajs.com/recipes/pos/index.html.md) # Implement Personalized Products in Medusa @@ -124755,15 +125946,15 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose Yes. +You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose Yes. Afterward, the installation process will start, which will install the Medusa application in a directory with your project's name, and the Next.js Starter Storefront in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterward, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** @@ -124775,7 +125966,7 @@ When the customer adds the product variant to the cart, you'll store the persona When the customer places the order, the line items' `metadata` property are copied to the order's line items, allowing you to access the personalized data later. -So, to create a personalized product, you can just create a [regular product using the Medusa Admin](undefined/user-guide/products/create). +So, to create a personalized product, you can just create a [regular product using the Medusa Admin](https://docs.medusajs.com/user-guide/products/create/index.html.md). ### Differentiate Personalized Products @@ -124802,19 +125993,19 @@ If your use case doesn't require custom pricing, you can skip this step and just In this step, you'll implement the logic to calculate the custom price, then expose that logic to client applications. To do that, you will: -1. Create a [workflow](undefined/docs/learn/fundamentals/workflows) that calculates the price based on the height, width, and product variant's price. -2. Create an [API route](undefined/docs/learn/fundamentals/api-routes) that executes the workflow and returns the price. +1. Create a [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) that calculates the price based on the height, width, and product variant's price. +2. Create an [API route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) that executes the workflow and returns the price. ### a. Create a Workflow -A [workflow](undefined/docs/learn/fundamentals/workflows) is a series of queries and actions, called steps, that complete a task. A workflow is similar to a function, but it allows you to track its executions' progress, define roll-back logic, and configure other advanced features. +A [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) is a series of queries and actions, called steps, that complete a task. A workflow is similar to a function, but it allows you to track its executions' progress, define roll-back logic, and configure other advanced features. In Medusa, you implement your custom commerce flows in workflows. Then, you execute those workflows from other customizations, such as API routes. The workflow that calculates the personalized product variant's price will have the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Get the region's currency. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Get the product variant's original price. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Get the region's currency. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Get the product variant's original price. - [getCustomPriceStep](#getCustomPriceStep): Calculate the custom price based on the height, width, and product variant's price. Medusa provides the `useQueryGraphStep`, so you only need to implement the `getCustomPriceStep` step. @@ -124871,7 +126062,7 @@ You create a step with the `createStep` function. It accepts two parameters: 1. The step's unique name. 2. An async function that receives two parameters: - The step's input, which is an object with the variant's data and the `metadata` object containing the height and width values. - - An object that has properties including the [Medusa container](undefined/docs/learn/fundamentals/medusa-container), which is a registry of Framework and commerce tools that you can access in the step. + - An object that has properties including the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which is a registry of Framework and commerce tools that you can access in the step. In the step function, you first check if the product is personalized by checking the `is_personalized` flag in the product's metadata. If it is not personalized, you return the original price. @@ -124947,7 +126138,7 @@ It accepts as a second parameter a constructor function that holds the workflow' In the workflow, you: 1. Retrieve the region's currency code using the `useQueryGraphStep` step. This is necessary to calculate the variant's price in the correct currency. - - The `useQueryGraphStep` uses [Query](undefined/docs/learn/fundamentals/module-links/query) to retrieve data across modules. + - The `useQueryGraphStep` uses [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) to retrieve data across modules. 2. Retrieve the product variant with its calculated price using the `useQueryGraphStep`. 3. Calculate the custom price using the `getCustomPriceStep`, passing the variant and metadata as input. @@ -124959,7 +126150,7 @@ Now that you have the workflow that calculates the custom price, you can create An API route is created in a `route.ts` file under a sub-directory of the `src/api` directory. The path of the API route is the file's path relative to `src/api`. -Refer to the [API routes](undefined/docs/learn/fundamentals/api-routes) to learn more about them. +Refer to the [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) to learn more about them. Create the file `src/api/store/variants/[id]/price/route.ts` with the following content: @@ -125012,7 +126203,7 @@ Finally, you return the price in the response. ### c. Add Validation Middleware -To ensure that the API route receives the correct request body parameters, you can apply a [middleware](undefined/docs/learn/fundamentals/api-routes/middlewares) on the API route that validates incoming requests. +To ensure that the API route receives the correct request body parameters, you can apply a [middleware](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md) on the API route that validates incoming requests. To apply middlewares, create the file `src/api/middlewares.ts` with the following content: @@ -125037,7 +126228,7 @@ You apply Medusa's `validateAndTransformBody` middleware to `POST` requests sent The middleware function accepts a Zod schema used for validation. This is the schema you created in the API route's file. -Refer to the [Middlewares](undefined/docs/learn/fundamentals/api-routes/middlewares) documentation to learn more. +Refer to the [Middlewares](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md) documentation to learn more. You'll test out the API route when you customize the storefront in the next step. @@ -125045,7 +126236,7 @@ You'll test out the API route when you customize the storefront in the next step ## Step 4: Show Calculated Price in the Storefront -In this step, you'll customize the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter) to show a personalized product's custom price when the customer enters the height and width values. +In this step, you'll customize the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) to show a personalized product's custom price when the customer enters the height and width values. The Next.js Starter Storefront was installed in a separate directory from Medusa. The directory's name is `{your-project}-storefront`. @@ -125094,7 +126285,7 @@ export const getCustomVariantPrice = async ({ You create a `getCustomVariantPrice` function that accepts the variant's ID, the region's ID, and the `metadata` object containing the height and width values. -In the function, you use the [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk) to send a `POST` request to the `/store/variants/:id/price` API route you created in the previous step. The function returns the price from the response. +In the function, you use the [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md) to send a `POST` request to the `/store/variants/:id/price` API route you created in the previous step. The function returns the price from the response. ### b. Customize the Product Price Component @@ -125310,16 +126501,16 @@ When the customer adds a personalized product to the cart, you need to add the i So, you'll create a workflow that wraps around Medusa's existing add-to-cart logic to add the personalized product to the cart with the custom price. Then, you'll create an API route that executes this workflow. -If you're not using custom pricing, you can skip this step and keep on using Medusa's existing [Add-to-Cart API route](undefined/api/store#carts_postcartsidlineitems). +If you're not using custom pricing, you can skip this step and keep on using Medusa's existing [Add-to-Cart API route](https://docs.medusajs.com/api/store#carts_postcartsidlineitems). ### a. Create the Add-to-Cart Workflow The custom add-to-cart workflow will have the following steps: -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Get the cart's region. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Get the cart's region. - [getCustomPriceWorkflow](#getCustomPriceWorkflow): Get the custom price for the product variant. -- [addToCartWorkflow](undefined/references/medusa-workflows/addToCartWorkflow): Add the product variant to the cart with the custom price. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Get the cart's updated data. +- [addToCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/addToCartWorkflow/index.html.md): Add the product variant to the cart with the custom price. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Get the cart's updated data. You already have all the necessary steps within the workflow, so you create it right away. @@ -125402,7 +126593,7 @@ In the workflow, you: 1. Retrieve the cart's region using the `useQueryGraphStep`. 2. Calculate the custom price using the `getCustomPriceWorkflow` that you created earlier. 3. Prepare the data of the item to add to the cart. - - You use the `transform` function because direct data manipulation isn't allowed in workflows. Refer to the [Data Manipulation](undefined/docs/learn/fundamentals/workflows/variable-manipulation) guide to learn more. + - You use the `transform` function because direct data manipulation isn't allowed in workflows. Refer to the [Data Manipulation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/variable-manipulation/index.html.md) guide to learn more. 4. Add the item to the cart using the `addToCartWorkflow`. 5. Refetch the updated cart using the `useQueryGraphStep` to return the cart data in the workflow's response. @@ -125495,7 +126686,7 @@ You'll test out this API route when you customize the storefront in the next ste In this step, you'll ensure that the personalized products added to the cart include the height and width values in their `metadata` property. -Medusa's `addToCartWorkflow` workflow supports performing custom validation on the items being added to the cart using [workflow hooks](undefined/docs/learn/fundamentals/workflows/workflow-hooks). A workflow hook is a point in a workflow where you can inject custom functionality as a step function. +Medusa's `addToCartWorkflow` workflow supports performing custom validation on the items being added to the cart using [workflow hooks](https://docs.medusajs.com/docs/learn/fundamentals/workflows/workflow-hooks/index.html.md). A workflow hook is a point in a workflow where you can inject custom functionality as a step function. To consume the `validate` hook that runs before an item is added to the cart, create the file `src/workflows/hooks/validate-personalized-product.ts` with the following content: @@ -125536,14 +126727,14 @@ You consume the hook by calling `addToCartWorkflow.hooks.validate`, passing it a In the step function, you: -1. Resolve [Query](undefined/docs/learn/fundamentals/module-links/query) from the Medusa container to retrieve data across modules. +1. Resolve [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) from the Medusa container to retrieve data across modules. 2. Retrieve the product variants being added to the cart. 3. Loop through the items being added to the cart. 4. If an item's product is personalized, you validate that the `metadata` object contains the `height` and `width` values, and that they are valid numbers. Otherwise, you throw an error. If the hook throws an error, the `addToCartWorkflow` will not proceed with adding the item to the cart, and the error will be returned in the API response. -Refer to the [Workflow Hooks](undefined/docs/learn/fundamentals/workflows/workflow-hooks) documentation to learn more. +Refer to the [Workflow Hooks](https://docs.medusajs.com/docs/learn/fundamentals/workflows/workflow-hooks/index.html.md) documentation to learn more. You can test this out after customizing the storefront in the next section. @@ -125692,7 +126883,7 @@ In this step, you'll customize the Medusa Admin to show the personalized item's The Medusa Admin dashboard is extensible, allowing you to either inject custom components into existing pages, or create new pages. -In this case, you'll inject a custom component, called a [widget](undefined/docs/learn/fundamentals/admin/widgets), into the order details page. +In this case, you'll inject a custom component, called a [widget](https://docs.medusajs.com/docs/learn/fundamentals/admin/widgets/index.html.md), into the order details page. Widgets are created in a `.tsx` file under the `src/admin/widgets` directory. So, create the file `src/admin/widgets/order-personalized.tsx` with the following content: @@ -125777,17 +126968,17 @@ You've now implemented personalized products in Medusa, allowing customers to cu - Add more personalization options, such as text engraving. - Implement more complex pricing calculations based on additional metadata. -- Create a [custom fulfillment provider](undefined/references/fulfillment/provider) to handle personalized products differently during fulfillment. +- Create a [custom fulfillment provider](https://docs.medusajs.com/references/fulfillment/provider/index.html.md) to handle personalized products differently during fulfillment. ### Learn More about Medusa -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). ### Troubleshooting -If you encounter issues during your development, check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting). +If you encounter issues during your development, check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/index.html.md). ### Getting Help @@ -125801,7 +126992,7 @@ If you encounter issues not covered in the troubleshooting guides: This recipe provides the general steps to build personalized products in Medusa. -[Personalized Products Example](undefined/recipes/personalized-products/example): Find a complete example of personalized products in Medusa. +[Personalized Products Example](https://docs.medusajs.com/recipes/personalized-products/example/index.html.md): Find a complete example of personalized products in Medusa. ## Overview @@ -125836,8 +127027,8 @@ Two line items in the cart having different `metadata` attributes are not consid In more complex cases, you can create a custom module that stores and manages the personalization data models. You can also create a link between these data models and the `LineItem` data model. -- [Create a Module](undefined/docs/learn/fundamentals/modules): Learn how to create a module. -- [Define Module Link](undefined/docs/learn/fundamentals/module-links): Define link between data models. +- [Create a Module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md): Learn how to create a module. +- [Define Module Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md): Define link between data models. *** @@ -125849,8 +127040,8 @@ You can build a unique experience around your products that focuses on the custo Medusa provides a Next.js Starter Storefront with basic ecommerce functionalities that can be customized. You can also build your own storefront and use Medusa’s client libraries or Store API Routes to communicate with the Medusa application. -- [Next.js Starter Storefront](undefined/nextjs-starter): Learn how to install the Next.js Starter Storefront. -- [Storefront Development](undefined/storefront-development): Find guides to build your own storefront. +- [Next.js Starter Storefront](https://docs.medusajs.com/nextjs-starter/index.html.md): Learn how to install the Next.js Starter Storefront. +- [Storefront Development](https://docs.medusajs.com/storefront-development/index.html.md): Find guides to build your own storefront. *** @@ -125861,11 +127052,11 @@ If you store the personalized data using a custom module, you can: - Create a workflow that handles saving the personalization data. - Create a custom API Route that executes the workflow. - Call that API Route from the storefront after adding the item to the cart. -- Consume the `orderCreated` hook of the [completeCartWorkflow](undefined/references/medusa-workflows/completeCartWorkflow) to attach the personalized data to the Order Module's `LineItem` data model. +- Consume the `orderCreated` hook of the [completeCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/completeCartWorkflow/index.html.md) to attach the personalized data to the Order Module's `LineItem` data model. -- [Create a Workflow](undefined/docs/learn/fundamentals/workflows): Learn how to create a workflow. -- [Create API Route](undefined/docs/learn/fundamentals/api-routes): Learn how to create an API route. -- [Consume a Hook](undefined/docs/learn/fundamentals/workflows/workflow-hooks): Learn how to create a hook. +- [Create a Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md): Learn how to create a workflow. +- [Create API Route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md): Learn how to create an API route. +- [Consume a Hook](https://docs.medusajs.com/docs/learn/fundamentals/workflows/workflow-hooks/index.html.md): Learn how to create a hook. *** @@ -125877,8 +127068,8 @@ To fulfill your personalized products with a third-party service or custom logic The Fulfillment Module registers your fulfillment module provider to use it to fulfill orders. -- [Fulfillment Module](undefined/commerce-modules/fulfillment): Learn about the Fulfillment Module. -- [Create Fulfillment Module Provider](undefined/references/fulfillment/provider): Learn how to create a fulfillment module provider. +- [Fulfillment Module](https://docs.medusajs.com/commerce-modules/fulfillment/index.html.md): Learn about the Fulfillment Module. +- [Create Fulfillment Module Provider](https://docs.medusajs.com/references/fulfillment/provider/index.html.md): Learn how to create a fulfillment module provider. # Point-of-Sale (POS) Recipe @@ -125903,7 +127094,7 @@ Medusa's modular architecture removes any restrictions you may have while making ![POS Tech Stack](https://res.cloudinary.com/dza7lstvk/image/upload/v1709034046/Medusa%20Book/pos-tech-stack_fy8uiu.jpg) -[Admin REST APIs](undefined/api/admin): Check out available Admin REST APIs in Medusa. +[Admin REST APIs](https://docs.medusajs.com/api/admin): Check out available Admin REST APIs in Medusa. *** @@ -125911,14 +127102,14 @@ Medusa's modular architecture removes any restrictions you may have while making POS systems make the checkout process smoother by integrating a barcode scanner. Merchants scan a product by its barcode to check its details or add it to the customer's purchase. -The Product Module's [ProductVariant](undefined/references/product/models/ProductVariant) data model has the properties to implement this integration, mainly the `barcode` attribute. Other notable properties include `ean`, `upc`, and `hs_code`, among others. +The Product Module's [ProductVariant](https://docs.medusajs.com/references/product/models/ProductVariant/index.html.md) data model has the properties to implement this integration, mainly the `barcode` attribute. Other notable properties include `ean`, `upc`, and `hs_code`, among others. To search through product variants by their barcode, create a custom API Route and call it within your POS. ![Example flow of integrating a barcode scanner](https://res.cloudinary.com/dza7lstvk/image/upload/v1709034282/Medusa%20Book/pos-scan-barcode_a8j8ew.jpg) -- [Product Module](undefined/commerce-modules/product): Learn about the Product Module. -- [Create API Route](undefined/docs/learn/fundamentals/api-routes): Learn how to create an API Route. +- [Product Module](https://docs.medusajs.com/commerce-modules/product/index.html.md): Learn about the Product Module. +- [Create API Route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md): Learn how to create an API Route. *** @@ -125926,7 +127117,7 @@ To search through product variants by their barcode, create a custom API Route a As you manage an online and offline store, it's essential to separate inventory quantity across different locations. -Medusa's [Inventory](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/inventory), [Stock Location](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/stock-location), and [Sales Channel](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/sales-channel) modules allow merchants to manage the inventory items and their availability across locations and sales channels. +Medusa's [Inventory](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/inventory/index.html.md), [Stock Location](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/stock-location/index.html.md), and [Sales Channel](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/sales-channel/index.html.md) modules allow merchants to manage the inventory items and their availability across locations and sales channels. ![Using Multi-warehouse features with POS](https://res.cloudinary.com/dza7lstvk/image/upload/v1709034731/Medusa%20Book/pos-multiwarehouse_r1z48x.jpg) @@ -125936,25 +127127,25 @@ This also opens the door for other business opportunities, such as an endless ai Suppose a product isn't available in-store but is available in different warehouses. You can allow customers to purchase that item in-store and deliver it to their address. -- [Inventory Module](undefined/commerce-modules/inventory): Learn about the Inventory Module. -- [Stock Location Module](undefined/commerce-modules/stock-location): Learn about the Stock Location Module. +- [Inventory Module](https://docs.medusajs.com/commerce-modules/inventory/index.html.md): Learn about the Inventory Module. +- [Stock Location Module](https://docs.medusajs.com/commerce-modules/stock-location/index.html.md): Learn about the Stock Location Module. -[Sales Channel Module](undefined/commerce-modules/sales-channel): Learn about the Sales Channel Module. +[Sales Channel Module](https://docs.medusajs.com/commerce-modules/sales-channel/index.html.md): Learn about the Sales Channel Module. *** ## Build an Omni-channel Customer Experience -Using Medusa's [Customer Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/customer), you can retrieve a customer's details from the Medusa application and place an order on the POS under their account. The customer can then view their order details on their online profile as if they had placed the order online. +Using Medusa's [Customer Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/customer/index.html.md), you can retrieve a customer's details from the Medusa application and place an order on the POS under their account. The customer can then view their order details on their online profile as if they had placed the order online. -In addition, using Medusa's [Promotion Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/promotion), store operators can create promotions on the fly for customers using the POS system and apply them to their orders. +In addition, using Medusa's [Promotion Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/promotion/index.html.md), store operators can create promotions on the fly for customers using the POS system and apply them to their orders. You can also create custom modules to provide features for a better customer experience, such as a rewards system or loyalty points. -- [Loyalty Points Tutorial](undefined/how-to-tutorials/tutorials/loyalty-points): Learn how to create a loyalty points system. -- [Customer Module](undefined/commerce-modules/customer): Learn about the Customer Module. -- [Promotion Module](undefined/commerce-modules/promotion): Learn about the Promotion Module. -- [Create a Module](undefined/docs/learn/fundamentals/modules): Learn how to create a module. +- [Loyalty Points Tutorial](https://docs.medusajs.com/how-to-tutorials/tutorials/loyalty-points/index.html.md): Learn how to create a loyalty points system. +- [Customer Module](https://docs.medusajs.com/commerce-modules/customer/index.html.md): Learn about the Customer Module. +- [Promotion Module](https://docs.medusajs.com/commerce-modules/promotion/index.html.md): Learn about the Promotion Module. +- [Create a Module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md): Learn how to create a module. *** @@ -125962,12 +127153,12 @@ You can also create custom modules to provide features for a better customer exp Medusa's architecture allows you to integrate any third-party payment provider for your POS and online storefront. For example, you can integrate [Stripe Terminal](https://stripe.com/terminal) to accept in-store payments. -Once you accept the payment, you can place an order in the POS system using the [Draft Order APIs](undefined/api/admin#draft-orders). Draft orders provide similar features to an online checkout experience, including discounts, payment processing, and more. +Once you accept the payment, you can place an order in the POS system using the [Draft Order APIs](https://docs.medusajs.com/api/admin#draft-orders). Draft orders provide similar features to an online checkout experience, including discounts, payment processing, and more. Then, merchants can view all orders coming from different sales channels using the Medusa Admin. This keeps logistics and order handling consistent between online and in-store customers. -- [Create a Payment Module Provider](undefined/references/payment/provider): Learn how to create a payment module provider. -- [Admin REST APIs](undefined/api/admin): Check out available Admin REST APIs. +- [Create a Payment Module Provider](https://docs.medusajs.com/references/payment/provider/index.html.md): Learn how to create a payment module provider. +- [Admin REST APIs](https://docs.medusajs.com/api/admin): Check out available Admin REST APIs. # Subscriptions Recipe @@ -126011,19 +127202,19 @@ You'll first be asked for the project's name. Then, when you're asked whether yo Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name, and the Next.js Starter Storefront in a directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more about Medusa's architecture in [this documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more about Medusa's architecture in [this documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterwards, you can log in with the new user and explore the dashboard. The Next.js Starter Storefront is also running at `http://localhost:8000`. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** ## Step 2: Configure Stripe Module Provider -As mentioned in the introduction, you'll use Stripe as the payment provider for the subscription payments. In this step, you'll configure the [Stripe Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe) in your Medusa application. +As mentioned in the introduction, you'll use Stripe as the payment provider for the subscription payments. In this step, you'll configure the [Stripe Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe/index.html.md) in your Medusa application. ### Prerequisites @@ -126056,7 +127247,7 @@ module.exports = defineConfig({ The Medusa configurations accept a `modules` property to add modules to your application. You'll learn more about modules in the next section. -You add the Stripe Module Provider to the [Payment Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment)'s options. Learn more about these options in the [Payment Module's options documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/module-options). +You add the Stripe Module Provider to the [Payment Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/index.html.md)'s options. Learn more about these options in the [Payment Module's options documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/module-options/index.html.md). You also pass an `apiKey` option to the Stripe Module Provider and set its value to an environment variable. So, add the following to your `.env` file: @@ -126066,7 +127257,7 @@ STRIPE_API_KEY=sk_test_51J... Where `sk_test_51J...` is your Stripe Secret API Key. -Learn more about other Stripe options and configurations in the [Stripe Module Provider documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe). +Learn more about other Stripe options and configurations in the [Stripe Module Provider documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe/index.html.md). ### Enable Stripe in Regions @@ -126203,9 +127394,9 @@ module.exports = defineConfig({ ### Further Read -- [How to Create a Module](undefined/docs/learn/fundamentals/modules) -- [How to Create a Data Model](undefined/docs/learn/fundamentals/modules#1-create-data-model) -- [Learn more about the service factory](undefined/docs/learn/fundamentals/modules/service-factory). +- [How to Create a Module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) +- [How to Create a Data Model](https://docs.medusajs.com/docs/learn/fundamentals/modules#1-create-data-model/index.html.md) +- [Learn more about the service factory](https://docs.medusajs.com/docs/learn/fundamentals/modules/service-factory/index.html.md). *** @@ -126284,7 +127475,7 @@ This defines a list link to the `Order` data model since a subscription has mult ### Further Reads -- [How to Define a Link](undefined/docs/learn/fundamentals/module-links) +- [How to Define a Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md) *** @@ -126705,7 +127896,7 @@ export default createSubscriptionWorkflow This workflow accepts the cart’s ID, along with the subscription details. It executes the following steps: 1. `completeCartWorkflow` from `@medusajs/medusa/core-flows` that completes a cart and creates an order. -2. `useQueryGraphStep` from `@medusajs/medusa/core-flows` to retrieve the order's details. [Query](undefined/docs/learn/fundamentals/module-links/query) is a tool that allows you to retrieve data across modules. +2. `useQueryGraphStep` from `@medusajs/medusa/core-flows` to retrieve the order's details. [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) is a tool that allows you to retrieve data across modules. 3. `createSubscriptionStep`, which is the step you created previously. 4. `createRemoteLinkStep` from `@medusajs/medusa/core-flows`, which accepts links to create. These links are in the `linkDefs` array returned by the previous step. @@ -126713,9 +127904,9 @@ The workflow returns the created subscription and order. ### Further Reads -- [How to Create a Workflow](undefined/docs/learn/fundamentals/workflows) -- [Learn more about the compensation function](undefined/docs/learn/fundamentals/workflows/compensation-function) -- [How to use Link](undefined/docs/learn/fundamentals/module-links/link) +- [How to Create a Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) +- [Learn more about the compensation function](https://docs.medusajs.com/docs/learn/fundamentals/workflows/compensation-function/index.html.md) +- [How to use Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/link/index.html.md) *** @@ -126723,9 +127914,9 @@ The workflow returns the created subscription and order. To create a subscription when a customer completes their purchase, you need to expose an endpoint that executes the subscription workflow. To do that, you'll create an API route. -An [API Route](undefined/docs/learn/fundamentals/api-routes) is an endpoint that exposes commerce features to external applications and clients, such as storefronts. +An [API Route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) is an endpoint that exposes commerce features to external applications and clients, such as storefronts. -In this step, you’ll create a custom API route similar to the [Complete Cart API route](undefined/api/store#carts_postcartsidcomplete) that uses the workflow you previously created to complete the customer's purchase and create a subscription. +In this step, you’ll create a custom API route similar to the [Complete Cart API route](https://docs.medusajs.com/api/store#carts_postcartsidcomplete) that uses the workflow you previously created to complete the customer's purchase and create a subscription. Create the file `src/api/store/carts/[id]/subscribe/route.ts` with the following content: @@ -126794,23 +127985,23 @@ In the next step, you'll customize the Next.js Starter Storefront, allowing you ### Further Reads -- [How to Create an API Route](undefined/docs/learn/fundamentals/api-routes) +- [How to Create an API Route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) *** ## Intermission: Payment Flow Overview -Before continuing with the customizations, you must understand the payment changes you need to make to support subscriptions. In this guide, you'll get a general overview, but you can refer to the [Payment in Storefront documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development/checkout/payment) for more details. +Before continuing with the customizations, you must understand the payment changes you need to make to support subscriptions. In this guide, you'll get a general overview, but you can refer to the [Payment in Storefront documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/checkout/payment/index.html.md) for more details. -By default, the checkout flow requires you to create a [payment collection](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-collection), then a [payment session](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-session) in that collection. When you create the payment session, that subsequently performs the necessary action to initialize the payment in the payment provider. For example, it creates a payment intent in Stripe. +By default, the checkout flow requires you to create a [payment collection](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-collection/index.html.md), then a [payment session](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-session/index.html.md) in that collection. When you create the payment session, that subsequently performs the necessary action to initialize the payment in the payment provider. For example, it creates a payment intent in Stripe. ![Diagram showcasing payment flow overview](https://res.cloudinary.com/dza7lstvk/image/upload/v1740657136/Medusa%20Resources/subscriptions-stripe_ycw4ig.jpg) -To support subscriptions, you need to support capturing the payment each time the subscription renews. When creating the payment session using the [Initialize Payment Session API route](undefined/api/store#payment-collections_postpaymentcollectionsidpaymentsessions), you must pass the data that your payment provider requires to support capturing the payment again in the future. You can pass the data that the provider requires in the `data` property. +To support subscriptions, you need to support capturing the payment each time the subscription renews. When creating the payment session using the [Initialize Payment Session API route](https://docs.medusajs.com/api/store#payment-collections_postpaymentcollectionsidpaymentsessions), you must pass the data that your payment provider requires to support capturing the payment again in the future. You can pass the data that the provider requires in the `data` property. -If you're using a custom payment provider, you can handle that additional data in the [initiatePayment method](undefined/references/payment/provider#initiatepayment) of your provider's service. +If you're using a custom payment provider, you can handle that additional data in the [initiatePayment method](https://docs.medusajs.com/references/payment/provider#initiatepayment/index.html.md) of your provider's service. -When you create the payment session, Medusa creates an account holder for the customer. An account holder represents a customer's saved payment information, including saved methods, in a third-party provider and may hold data from that provider. Learn more in the [Account Holder](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/account-holder) documentation. +When you create the payment session, Medusa creates an account holder for the customer. An account holder represents a customer's saved payment information, including saved methods, in a third-party provider and may hold data from that provider. Learn more in the [Account Holder](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/account-holder/index.html.md) documentation. The account holder allows you to retrieve the saved payment method and use it to capture the payment when the subscription renews. You'll see how this works later when you implement the logic to renew the subscription. @@ -126818,7 +128009,7 @@ The account holder allows you to retrieve the saved payment method and use it to ## Step 9: Add Subscriptions to Next.js Starter Storefront -In this step, you'll customize the checkout flow in the [Next.js Starter storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), which you installed in the first step, to: +In this step, you'll customize the checkout flow in the [Next.js Starter storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), which you installed in the first step, to: 1. Add a subscription step to the checkout flow. 2. Pass the additional data that Stripe requires to later capture the payment when the subscription renews, as explained in the [Payment Flow Overview](#intermission-payment-flow-overview). @@ -127085,7 +128276,7 @@ In this step, you’ll add two API routes for admin users: ### List Subscriptions Admin API Route -The list subscriptions API route should allow clients to retrieve subscriptions with pagination. An API route can be configured to accept pagination fields, such as `limit` and `offset`, then use them with [Query](undefined/docs/learn/fundamentals/module-links/query) to paginate the retrieved data. +The list subscriptions API route should allow clients to retrieve subscriptions with pagination. An API route can be configured to accept pagination fields, such as `limit` and `offset`, then use them with [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) to paginate the retrieved data. You'll start with the API route. To create it, create the file `src/api/admin/subscriptions/route.ts` with the following content: @@ -127131,7 +128322,7 @@ These fields are useful for clients to paginate the subscriptions. ### Add Query Configuration Middleware -To configure the pagination and retrieved fields within the route handler, and to allow passing query parameters that change these configurations in the request, you need to add the `validateAndTransformQuery` [middleware](undefined/docs/learn/fundamentals/api-routes/middlewares) to the route. +To configure the pagination and retrieved fields within the route handler, and to allow passing query parameters that change these configurations in the request, you need to add the `validateAndTransformQuery` [middleware](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md) to the route. To add a middleware, create the file `src/api/middlewares.ts` with the following content: @@ -127184,7 +128375,7 @@ You add the `validateAndTransformQuery` middleware to `GET` requests sent to rou The middleware combines your default configurations with the query parameters in the request to determine the fields to retrieve and the pagination settings. -Refer to the [Request Query Configuration](undefined/docs/learn/fundamentals/module-links/query#request-query-configurations) documentation to learn more about this middleware and the query configurations. +Refer to the [Request Query Configuration](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query#request-query-configurations/index.html.md) documentation to learn more about this middleware and the query configurations. ### Get Subscription Admin API Route @@ -127281,7 +128472,7 @@ You define types for the subscription status and interval, as well as a `Subscri ### Configure JS SDK -Medusa provides a [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk) that facilitates sending requests to the server. You can use this SDK in any JavaScript client-side application, including your admin customizations. +Medusa provides a [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md) that facilitates sending requests to the server. You can use this SDK in any JavaScript client-side application, including your admin customizations. To configure the JS SDK, create the file `src/admin/lib/sdk.ts` with the following content: @@ -127303,11 +128494,11 @@ This initializes the SDK, setting the following options: - `debug`: A boolean indicating whether to log debug information. You use the Vite environment variable `DEV`. - `auth`: An object indicating the authentication type. You use the session authentication type, which is the recommended approach for admin customizations. -Learn more about other customizations in the [JS SDK documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk). +Learn more about other customizations in the [JS SDK documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md). ### Create Subscriptions List UI Route -You'll now create the subscriptions list UI route. Since you'll show the subscriptions in a table, you'll use the [DataTable component](undefined/ui/components/data-table) from Medusa UI. It facilitates displaying data in a tabular format with sorting, filtering, and pagination. +You'll now create the subscriptions list UI route. Since you'll show the subscriptions in a table, you'll use the [DataTable component](https://docs.medusajs.com/ui/components/data-table/index.html.md) from Medusa UI. It facilitates displaying data in a tabular format with sorting, filtering, and pagination. Start by creating the file `src/admin/routes/subscriptions/page.tsx` with the following content: @@ -127536,8 +128727,8 @@ To view a subscription’s details, click on its row, which opens the subscripti ### Further Reads -- [How to Create UI Routes](undefined/docs/learn/fundamentals/admin/ui-routes) -- [DataTable component](undefined/ui/components/data-table) +- [How to Create UI Routes](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md) +- [DataTable component](https://docs.medusajs.com/ui/components/data-table/index.html.md) *** @@ -127573,7 +128764,7 @@ You’ll only implement the third, sixth, and ninth steps. ### Create getPaymentMethodStep (Third Step) -To charge the customer using their payment method saved in Stripe, you need to retrieve that payment method. As explained in the [Payment Flow Overview](#intermission-payment-flow-overview), you customized the storefront to pass the `setup_future_usage` option to Stripe. So, the payment method was saved in Stripe and linked to the customer's [account holder](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/account-holder), allowing you to retrieve it later and re-capture the payment. +To charge the customer using their payment method saved in Stripe, you need to retrieve that payment method. As explained in the [Payment Flow Overview](#intermission-payment-flow-overview), you customized the storefront to pass the `setup_future_usage` option to Stripe. So, the payment method was saved in Stripe and linked to the customer's [account holder](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/account-holder/index.html.md), allowing you to retrieve it later and re-capture the payment. To create the step, create the file `src/workflows/create-subscription-order/steps/get-payment-method.ts` with the following content: @@ -128031,7 +129222,7 @@ The workflow runs the following steps: 1. `useQueryGraphStep` to retrieve the details of the cart linked to the subscription. 2. `createPaymentCollectionsStep` to create a payment collection using the same information in the cart. 3. `getPaymentMethodStep` to get the customer's saved payment method. -4. `createPaymentSessionsWorkflow` to create a payment session in the payment collection from the previous step. You prepare the data to create the payment session using [transform](undefined/docs/learn/fundamentals/workflows/variable-manipulation) from the Workflows SDK. +4. `createPaymentSessionsWorkflow` to create a payment session in the payment collection from the previous step. You prepare the data to create the payment session using [transform](https://docs.medusajs.com/docs/learn/fundamentals/workflows/variable-manipulation/index.html.md) from the Workflows SDK. - Since you're capturing the payment with Stripe, you must pass in the payment session's `data` object the following properties: - `payment_method`: the ID of the payment method saved in Stripe. - `off_session`: `true` to indicate that the payment is [off-session](https://docs.stripe.com/payments/payment-intents#future-usage). @@ -128044,13 +129235,13 @@ The workflow runs the following steps: 8. `capturePaymentStep` to capture the order’s payment. 9. `updateSubscriptionStep` to update the subscription’s `last_order_date` and `next_order_date`. -A workflow's constructor function has some constraints in implementation, which is why you need to use `transform` for data manipulation. Learn more about these constraints in [this documentation](undefined/docs/learn/fundamentals/workflows/constructor-constraints). +A workflow's constructor function has some constraints in implementation, which is why you need to use `transform` for data manipulation. Learn more about these constraints in [this documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/constructor-constraints/index.html.md). In the next step, you’ll execute the workflow in a scheduled job. ### Further Reads -- [Payment Module](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment) +- [Payment Module](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/index.html.md) *** @@ -128157,7 +129348,7 @@ This loops over the returned subscriptions and executes the `createSubscriptionO ### Further Reads -- [How to Create a Scheduled Job](undefined/docs/learn/fundamentals/scheduled-jobs) +- [How to Create a Scheduled Job](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs/index.html.md) *** @@ -128386,7 +129577,7 @@ curl -X POST 'http://localhost:9000/auth/customer/emailpass' \ Make sure to replace the `email` and `password` with the correct credentials. -If you don’t have a customer account, create one either using the Next.js Starter storefront or by following [this guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development/customers/register). +If you don’t have a customer account, create one either using the Next.js Starter storefront or by following [this guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/customers/register/index.html.md). Then, send a `GET` request to `/store/customers/me/subscriptions` to retrieve the customer’s subscriptions: @@ -128414,7 +129605,7 @@ The next steps of this example depend on your use case. This section provides so ### Use Existing Features -To manage the orders created for a subscription, or other functionalities, use Medusa’s existing [Admin API routes](undefined/api/admin). +To manage the orders created for a subscription, or other functionalities, use Medusa’s existing [Admin API routes](https://docs.medusajs.com/api/admin). ### Link Subscriptions to Other Data Models @@ -128424,7 +129615,7 @@ For example, you can link a subscription to a promotion to offer a subscription- ### Storefront Development -Medusa provides a Next.js Starter storefront that you can customize to your use case. You can also create a custom storefront. To learn how visit the [Storefront Development](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/storefront-development) section. +Medusa provides a Next.js Starter storefront that you can customize to your use case. You can also create a custom storefront. To learn how visit the [Storefront Development](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/storefront-development/index.html.md) section. # Subscriptions Recipe @@ -128437,7 +129628,7 @@ Subscription-based purchase allows customers to purchase products for a specifie For example, a customer can purchase a book subscription box for a period of three months. Each month, the payment is captured for that order and, if the payment is successful, the fulfillment is processed. -Medusa's [Framework](undefined/docs/learn/fundamentals/framework) for customizations facilitates building subscription-based purchases. You can create a Subscription Module that implements data models for subscriptions, and link those data models to existing ones such as products and orders. +Medusa's [Framework](https://docs.medusajs.com/docs/learn/fundamentals/framework/index.html.md) for customizations facilitates building subscription-based purchases. You can create a Subscription Module that implements data models for subscriptions, and link those data models to existing ones such as products and orders. You can also expose custom features using API routes, and implement complex flows using workflows. @@ -128453,8 +129644,8 @@ To store the subscription details, you can create a data model in a new subscrip You can link the subscription data model to models of other modules, such as the Order Module's `Order` data model. -- [Create a Module](undefined/docs/learn/fundamentals/modules): Learn how to create a module. -- [Create a Data Model](undefined/docs/learn/fundamentals/modules#1-create-data-model): Learn how to create a data model. +- [Create a Module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md): Learn how to create a module. +- [Create a Data Model](https://docs.medusajs.com/docs/learn/fundamentals/modules#1-create-data-model/index.html.md): Learn how to create a data model. *** @@ -128466,7 +129657,7 @@ For example, you can link the subscription data model to the Order Module's `Ord If you want to create subscriptions on the product level, you can link the subscription data model to the Product Module's `Product` data model. -[Define a Module Link](undefined/docs/learn/fundamentals/module-links): Learn how to define a module link. +[Define a Module Link](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md): Learn how to define a module link. *** @@ -128485,10 +129676,10 @@ Implementing the logic depends on your use case, but you'll mainly implement the 3. Create a scheduled job that checks daily for subscriptions that need renewal. 4. Create another scheduled job that checks daily for subscriptions that are expired. -- [Create a Workflow](undefined/docs/learn/fundamentals/workflows): Learn how to create a workflow. -- [Create an API Route](undefined/docs/learn/fundamentals/api-routes): Learn how to create an API route. +- [Create a Workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md): Learn how to create a workflow. +- [Create an API Route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md): Learn how to create an API route. -[Create a Scheduled Job](undefined/docs/learn/fundamentals/scheduled-jobs#1-create-a-scheduled-job): Learn how to create a scheduled job. +[Create a Scheduled Job](https://docs.medusajs.com/docs/learn/fundamentals/scheduled-jobs#1-create-a-scheduled-job/index.html.md): Learn how to create a scheduled job. ### Option 2: Using Stripe Subscriptions @@ -128496,9 +129687,9 @@ Stripe provides a [subscription payments feature](https://stripe.com/docs/billin This approach allows you to delegate the complications of implementing the subscription logic to Stripe, but doesn't support using other payment providers. -Although Medusa provides a [Stripe Payment Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe), it doesn't handle subscriptions. You can create a custom Stripe Subscription Module Provider instead. +Although Medusa provides a [Stripe Payment Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe/index.html.md), it doesn't handle subscriptions. You can create a custom Stripe Subscription Module Provider instead. -[Create Payment Module Provider](undefined/references/payment/provider): Learn how to create a payment module provider. +[Create Payment Module Provider](https://docs.medusajs.com/references/payment/provider/index.html.md): Learn how to create a payment module provider. *** @@ -128514,10 +129705,10 @@ The Medusa Admin is an extensible application within your Medusa application. Yo - **UI Routes**: Adding new pages to the Medusa Admin, such as a page to manage subscriptions. - **Settings Pages**: Adding new pages to the Medusa Admin settings, such as a page to manage subscription settings. -- [Create Admin Widget](undefined/docs/learn/fundamentals/admin/widgets): Add widgets into existing admin pages. -- [Create Admin UI Routes](undefined/docs/learn/fundamentals/admin/ui-routes): Add new pages to your Medusa Admin. +- [Create Admin Widget](https://docs.medusajs.com/docs/learn/fundamentals/admin/widgets/index.html.md): Add widgets into existing admin pages. +- [Create Admin UI Routes](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md): Add new pages to your Medusa Admin. -[Create Admin Setting Page](undefined/docs/learn/fundamentals/admin/ui-routes#create-settings-page): Add new page to the Medusa Admin settings. +[Create Admin Setting Page](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes#create-settings-page/index.html.md): Add new page to the Medusa Admin settings. *** @@ -128527,19 +129718,19 @@ Medusa provides a Next.js Starter Storefront to use with your application. You c Alternatively, you can build your own storefront using the Medusa APIs. This headless approach gives you the flexibility to build a custom storefront without limitations on which tech stack you use, or the design of the storefront. -- [Next.js Starter Storefront](undefined/nextjs-starter): Learn how to install and customize the Next.js Starter Storefront. -- [Storefront Development](undefined/storefront-development): Find guides to build your own storefront. +- [Next.js Starter Storefront](https://docs.medusajs.com/nextjs-starter/index.html.md): Learn how to install and customize the Next.js Starter Storefront. +- [Storefront Development](https://docs.medusajs.com/storefront-development/index.html.md): Find guides to build your own storefront. # Implement a Ticket Booking System with Medusa In this tutorial, you'll learn how to implement a ticket booking system using Medusa. -This tutorial is divided into two parts: this part that covers the backend and admin customizations, and a [storefront part](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/ticket-booking/example/storefront) that covers the Next.js Starter Storefront customizations. +This tutorial is divided into two parts: this part that covers the backend and admin customizations, and a [storefront part](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/ticket-booking/example/storefront/index.html.md) that covers the Next.js Starter Storefront customizations. -When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules) that are available out-of-the-box. +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. The Medusa application's commerce features are built around [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md) that are available out-of-the-box. -Medusa's [Framework](undefined/docs/learn/fundamentals/framework) facilitates customizing Medusa's core features for your specific use case, such as ticket booking. +Medusa's [Framework](https://docs.medusajs.com/docs/learn/fundamentals/framework/index.html.md) facilitates customizing Medusa's core features for your specific use case, such as ticket booking. This tutorial provides an approach to implement a ticket booking system using Medusa. Depending on your specific requirements, you might need to adjust the implementation details or explore a different approach. @@ -128552,7 +129743,7 @@ By following this tutorial, you will learn how to: - Customize the Medusa Admin to manage venues and shows or events. - Implement custom validation and flows for ticket booking. - Generate QR codes for tickets and verify them at the venue. -- [Extend the Next.js Starter Storefront to allow booking tickets and choosing seats](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/ticket-booking/example/storefront): This part of the tutorial is covered separately. +- [Extend the Next.js Starter Storefront to allow booking tickets and choosing seats](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/ticket-booking/example/storefront/index.html.md): This part of the tutorial is covered separately. ![Diagram showing the architecture of the ticket booking system with Medusa](https://res.cloudinary.com/dza7lstvk/image/upload/v1757512301/Medusa%20Resources/ticket-booking-diagram_egbpye.jpg) @@ -128575,25 +129766,25 @@ Start by installing the Medusa application on your machine with the following co npx create-medusa-app@latest ``` -You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter), choose Yes. +You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md), choose Yes. Afterward, the installation process will start, which will install the Medusa application in a directory with your project's name, and the Next.js Starter Storefront in a separate directory with the `{project-name}-storefront` name. -The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](undefined/docs/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](undefined/docs/learn/introduction/architecture). +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md). Learn more in [Medusa's Architecture documentation](https://docs.medusajs.com/docs/learn/introduction/architecture/index.html.md). Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterward, you can log in with the new user and explore the dashboard. -Check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors) for help. +Check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/create-medusa-app-errors/index.html.md) for help. *** ## Step 2: Create Ticket Booking Module -In Medusa, you can build custom features in a [module](undefined/docs/learn/fundamentals/modules). A module is a reusable package with the data models and functionality related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. +In Medusa, you can build custom features in a [module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md). A module is a reusable package with the data models and functionality related to a single feature or domain. Medusa integrates the module into your application without implications or side effects on your setup. In this step, you'll build a Ticket Booking Module that defines the data models and logic to manage venues and tickets. Later, you'll build commerce flows related to ticket booking around the module. -Refer to the [Modules documentation](undefined/docs/learn/fundamentals/modules) to learn more. +Refer to the [Modules documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md) to learn more. ### a. Create Module Directory @@ -128603,7 +129794,7 @@ Create the directory `src/modules/ticket-booking` that will hold the Ticket Book A data model represents a table in the database. You create data models using Medusa's Data Model Language (DML). It simplifies defining a table's columns, relations, and indexes with straightforward methods and configurations. -Refer to the [Data Models documentation](undefined/docs/learn/fundamentals/modules#1-create-data-model) to learn more. +Refer to the [Data Models documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#1-create-data-model/index.html.md) to learn more. You'll define data models to represent venues, tickets, and purchases. Later, you'll link these data models to Medusa's data models, such as products and orders. @@ -128639,7 +129830,7 @@ The `Venue` data model has the following properties: - `address`: The address of the venue. - `rows`: A one-to-many relation with the `VenueRow` data model, which you'll create next. -Learn more about defining data model properties in the [Property Types documentation](undefined/docs/learn/fundamentals/data-models/properties). +Learn more about defining data model properties in the [Property Types documentation](https://docs.medusajs.com/docs/learn/fundamentals/data-models/properties/index.html.md). #### VenueRow Model @@ -128830,7 +130021,7 @@ You can manage your module's data models in a service. A service is a TypeScript class that the module exports. In the service's methods, you can connect to the database, allowing you to manage your data models, or connect to third-party services, which is useful if you're integrating with external services. -Refer to the [Module Service documentation](undefined/docs/learn/fundamentals/modules#2-create-service) to learn more. +Refer to the [Module Service documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#2-create-service/index.html.md) to learn more. To create the Ticket Booking Module's service, create the file `src/modules/ticket-booking/service.ts` with the following content: @@ -128857,7 +130048,7 @@ The `TicketBookingModuleService` extends `MedusaService`, which generates a clas The `TicketBookingModuleService` class now has methods like `createTicketProducts` and `retrieveVenue`. -Find all methods generated by the `MedusaService` in [the Service Factory reference](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/service-factory-reference). +Find all methods generated by the `MedusaService` in [the Service Factory reference](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/service-factory-reference/index.html.md). ### d. Export Module Definition @@ -128906,7 +130097,7 @@ Each object in the `modules` array has a `resolve` property, whose value is eith Since data models represent tables in the database, you define how they're created in the database with migrations. A migration is a TypeScript class that defines database changes made by a module. -Refer to the [Migrations documentation](undefined/docs/learn/fundamentals/modules#5-generate-migrations) to learn more. +Refer to the [Migrations documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules#5-generate-migrations/index.html.md) to learn more. Medusa's CLI tool can generate the migrations for you. To generate a migration for the Ticket Booking Module, run the following command in your Medusa application's directory: @@ -128932,7 +130123,7 @@ Since Medusa isolates modules to integrate them into your application without si Instead, Medusa provides a mechanism to define links between data models and retrieve and manage linked records while maintaining module isolation. -Refer to the [Module Isolation documentation](undefined/docs/learn/fundamentals/modules/isolation) to learn more. +Refer to the [Module Isolation documentation](https://docs.medusajs.com/docs/learn/fundamentals/modules/isolation/index.html.md) to learn more. In this step, you'll define a link between the data models in the Ticket Booking Module and Medusa's Commerce Modules. @@ -128962,7 +130153,7 @@ You define a link using the `defineLink` function. It accepts two parameters: In later steps, you'll learn how this link allows you to retrieve and manage ticket products and their related Medusa products. -Refer to the [Module Links](undefined/docs/learn/fundamentals/module-links) documentation to learn more about defining links. +Refer to the [Module Links](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md) documentation to learn more about defining links. ### b. TicketProductVariant \<> ProductVariant Link @@ -129026,8 +130217,8 @@ In this step, you'll implement the logic to create a venue. When you build commerce features in Medusa that can be consumed by client applications, such as the Medusa Admin dashboard or storefront, you need to implement: -1. A [workflow](undefined/docs/learn/fundamentals/workflows) with steps that define the business logic of the feature. -2. An [API route](undefined/docs/learn/fundamentals/api-routes) that exposes the workflow's functionality to client applications. +1. A [workflow](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) with steps that define the business logic of the feature. +2. An [API route](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) that exposes the workflow's functionality to client applications. In this step, you'll implement the workflow and API route for creating a venue. @@ -129035,13 +130226,13 @@ In this step, you'll implement the workflow and API route for creating a venue. A workflow is a series of queries and actions, called steps, that complete a task. A workflow is similar to a function, but it allows you to track its executions' progress, define roll-back logic, and configure other advanced features. -Refer to the [Workflows documentation](undefined/docs/learn/fundamentals/workflows) to learn more. +Refer to the [Workflows documentation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md) to learn more. The workflow to create a venue will have the following steps: - [createVenueStep](#createVenueStep): Creates a venue. - [createVenueRowsStep](#createVenueRowsStep): Creates the venue's rows. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieves the created venue with its rows. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieves the created venue with its rows. The `useQueryGraphStep` is available through Medusa's `@medusajs/medusa/core-flows` package. You'll implement other steps in the workflow. @@ -129084,7 +130275,7 @@ You create a step with the `createStep` function. It accepts three parameters: 1. The step's unique name. 2. An async function that receives two parameters: - The step's input, which is an object with the `name` and `address` properties of the venue to create. - - An object that has properties including the [Medusa container](undefined/docs/learn/fundamentals/medusa-container), which is a registry of Framework and commerce tools that you can access in the step. + - An object that has properties including the [Medusa container](https://docs.medusajs.com/docs/learn/fundamentals/medusa-container/index.html.md), which is a registry of Framework and commerce tools that you can access in the step. 3. An async compensation function that undoes the actions performed by the step function. This function is only executed if an error occurs during the workflow's execution. In the step function, you resolve the Ticket Booking Module's service from the Medusa container using its `resolve` method, passing it the module's name as a parameter. @@ -129219,11 +130410,11 @@ In the workflow, you: 2. Prepare the data to create the venue's rows. 3. Create the venue's rows using the `createVenueRowsStep`. 4. Retrieve the created venue with its rows using the `useQueryGraphStep`. - - This step uses [Query](undefined/docs/learn/fundamentals/module-links/query) under the hood. It allows you to retrieve data across modules. + - This step uses [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) under the hood. It allows you to retrieve data across modules. A workflow must return an instance of `WorkflowResponse` that accepts the data to return to the workflow's executor. You return the created venue with its rows. -`transform` allows you to access the values of data during execution. Learn more in the [Data Manipulation](undefined/docs/learn/fundamentals/workflows/variable-manipulation) documentation. +`transform` allows you to access the values of data during execution. Learn more in the [Data Manipulation](https://docs.medusajs.com/docs/learn/fundamentals/workflows/variable-manipulation/index.html.md) documentation. ### b. Create Venue API Route @@ -129231,7 +130422,7 @@ Next, you'll create an API route that exposes the functionality of the `createVe An API route is created in a `route.ts` file under a sub-directory of the `src/api` directory. The path of the API route is the file's path relative to `src/api`. -Refer to the [API routes](undefined/docs/learn/fundamentals/api-routes) documentation to learn more about them. +Refer to the [API routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md) documentation to learn more about them. Create the file `src/api/admin/venues/route.ts` with the following content: @@ -129277,7 +130468,7 @@ You'll test this API route later when you customize the Medusa Admin. #### Add Validation Middleware for Create Venue API Route -To validate the body parameters of requests sent to the API route, you need to apply a [middleware](undefined/docs/learn/fundamentals/api-routes/middlewares). +To validate the body parameters of requests sent to the API route, you need to apply a [middleware](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md). To apply a middleware to a route, create the file `src/api/middlewares.ts` with the following content: @@ -129305,7 +130496,7 @@ You apply Medusa's `validateAndTransformBody` middleware to `POST` requests sent The middleware function accepts a Zod schema, which you created in the API route's file. -Refer to the [Middlewares](undefined/docs/learn/fundamentals/api-routes/middlewares) documentation to learn more. +Refer to the [Middlewares](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/middlewares/index.html.md) documentation to learn more. *** @@ -129389,7 +130580,7 @@ The middleware function accepts two parameters: - `isList`: Set to `true` to indicate that the API route returns a list of records. - `defaults`: An array of fields to return by default if the client doesn't specify any fields in the request. -Refer to the [Query](undefined/docs/learn/fundamentals/module-links/query#request-query-configurations) documentation to learn more about query request configurations. +Refer to the [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query#request-query-configurations/index.html.md) documentation to learn more about query request configurations. *** @@ -129399,13 +130590,13 @@ In this step, you'll customize the Medusa Admin to allow admin users to manage v The Medusa Admin dashboard is customizable, allowing you to insert widgets into existing pages, or create new pages. -Refer to the [Admin Development](undefined/docs/learn/fundamentals/admin) documentation to learn more. +Refer to the [Admin Development](https://docs.medusajs.com/docs/learn/fundamentals/admin/index.html.md) documentation to learn more. In this step, you'll create a new page or UI route in the Medusa Admin to view a list of venues and create new venues. ### a. Initialize JS SDK -To send requests to the Medusa server, you'll use the [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk). It's already installed in your Medusa project, but you need to initialize it before using it in your customizations. +To send requests to the Medusa server, you'll use the [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md). It's already installed in your Medusa project, but you need to initialize it before using it in your customizations. Create the file `src/admin/lib/sdk.ts` with the following content: @@ -129421,7 +130612,7 @@ export const sdk = new Medusa({ }) ``` -Learn more about the initialization options in the [JS SDK](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/js-sdk) reference. +Learn more about the initialization options in the [JS SDK](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/js-sdk/index.html.md) reference. ### b. Define Types @@ -129517,7 +130708,7 @@ A UI route file must export: - A React component as the default export. This component is rendered when the user navigates to the UI route. - A route configuration object defined using the `defineRouteConfig` function. This object configures the UI route's label and icon in the sidebar. -In the `VenuesPage` component, you'll display the list of venues in a [Data Table](undefined/ui/components/data-table) component. +In the `VenuesPage` component, you'll display the list of venues in a [Data Table](https://docs.medusajs.com/ui/components/data-table/index.html.md) component. To define the columns of the data table, add the following before the `VenuesPage` component: @@ -130186,13 +131377,13 @@ The workflow will also create inventory items for each variant, ensuring that cu The workflow will have the following steps: - [validateVenueAvailabilityStep](#validateVenueAvailabilityStep): Validates that the selected venue is available for the show date and time. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve default store configuration that are useful for creating the Medusa product. -- [createInventoryItemsWorkflow](undefined/references/medusa-workflows/createInventoryItemsWorkflow): Creates inventory items for the Medusa product. -- [createProductsWorkflow](undefined/references/medusa-workflows/createProductsWorkflow): Creates the Medusa product and its variants. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve default store configuration that are useful for creating the Medusa product. +- [createInventoryItemsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createInventoryItemsWorkflow/index.html.md): Creates inventory items for the Medusa product. +- [createProductsWorkflow](https://docs.medusajs.com/references/medusa-workflows/createProductsWorkflow/index.html.md): Creates the Medusa product and its variants. - [createTicketProductsStep](#createTicketProductsStep): Creates the ticket product. - [createTicketProductVariantsStep](#createTicketProductVariantsStep): Creates the ticket product variants. - [createRemoteLinkStep](#createRemoteLinkStep): Create links between the ticket product and variants and the Medusa product and variants. -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the created ticket product with its relations. +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the created ticket product with its relations. You only need to implement the `validateVenueAvailabilityStep`, `createTicketProductsStep`, and `createTicketProductVariantsStep` steps. The other steps are provided by Medusa. @@ -130403,7 +131594,7 @@ In the workflow, you validate the venue's availability using the `validateVenueA Then, you retrieve the default store configuration using the `useQueryGraphStep`. These configurations are useful when creating the Medusa inventory items and product. -Make sure you have [default location and sales channel set up in your Medusa store](undefined/user-guide/settings/store). +Make sure you have [default location and sales channel set up in your Medusa store](https://docs.medusajs.com/user-guide/settings/store/index.html.md). Next, you'll create inventory items for each variant before creating the Medusa product. Replace the `TODO` with the following: @@ -131249,7 +132440,7 @@ export const PricingStep = ({ You define the `PricingStep` component that accepts props for the selected venue, currency-region combinations, and prices. -In Medusa, you can set the price of a product variant in multiple currencies and regions. This allows you to sell products in different markets with localized pricing. Learn more in the [Pricing documentation](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules/pricing/concepts). +In Medusa, you can set the price of a product variant in multiple currencies and regions. This allows you to sell products in different markets with localized pricing. Learn more in the [Pricing documentation](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/pricing/concepts/index.html.md). In the component, if no venue is selected, you display a message prompting the user to select a venue in the previous step. @@ -131835,7 +133026,7 @@ You can edit the associated Medusa product to add images, descriptions, and othe In this step, you'll add custom validation to core cart operations that ensures a seat isn't purchased more than once for the same date. -Medusa implements cart operations in workflows. Specifically, you'll focus on the `addToCartWorkflow` and `completeCartWorkflow`. Medusa allows you to inject custom logic into workflows using [hooks](undefined/docs/learn/fundamentals/workflows/workflow-hooks). +Medusa implements cart operations in workflows. Specifically, you'll focus on the `addToCartWorkflow` and `completeCartWorkflow`. Medusa allows you to inject custom logic into workflows using [hooks](https://docs.medusajs.com/docs/learn/fundamentals/workflows/workflow-hooks/index.html.md). A workflow hook is a point in a workflow where you can inject custom functionality as a step function. @@ -132022,7 +133213,7 @@ completeCartWorkflow.hooks.validate( Similar to the previous hook, you consume the `validate` hook of the `completeCartWorkflow` to validate that no seat is purchased more than once for the same date. -You can test out both hooks when you [customize the storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/ticket-booking/example/storefront). +You can test out both hooks when you [customize the storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/ticket-booking/example/storefront/index.html.md). *** @@ -132034,11 +133225,11 @@ In this step, you'll create a custom complete cart workflow that wraps the defau The custom workflow that completes the cart has the following steps: -- [completeCartWorkflow](undefined/references/medusa-workflows/completeCartWorkflow): Complete the cart using Medusa's default completeCartWorkflow -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the cart details +- [completeCartWorkflow](https://docs.medusajs.com/references/medusa-workflows/completeCartWorkflow/index.html.md): Complete the cart using Medusa's default completeCartWorkflow +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the cart details - [createTicketPurchasesStep](#createTicketPurchasesStep): Create ticket purchases for each ticket product variant in the cart -- [createRemoteLinkStep](undefined/references/helper-steps/createRemoteLinkStep): Create links between the order and ticket purchases -- [useQueryGraphStep](undefined/references/helper-steps/useQueryGraphStep): Retrieve the order details +- [createRemoteLinkStep](https://docs.medusajs.com/references/helper-steps/createRemoteLinkStep/index.html.md): Create links between the order and ticket purchases +- [useQueryGraphStep](https://docs.medusajs.com/references/helper-steps/useQueryGraphStep/index.html.md): Retrieve the order details You only need to implement the `createTicketPurchasesStep` step, as the other steps and workflows are provided by Medusa. @@ -132279,13 +133470,13 @@ Since you export a `POST` route handler function, you expose a `POST` API route In the route handler, you execute the `completeCartWithTicketsWorkflow` and return the created order in the response. -You'll test out this API route when you [customize the storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/ticket-booking/example/storefront#update-cart-functions). +You'll test out this API route when you [customize the storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/ticket-booking/example/storefront#update-cart-functions/index.html.md). *** ## Step 12: Storefront API Routes -To [customize the storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/ticket-booking/example/storefront) in the next part, you need two API routes that the storefront will consume: +To [customize the storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/ticket-booking/example/storefront/index.html.md) in the next part, you need two API routes that the storefront will consume: 1. An API route to fetch the available dates for a ticket product. 2. An API route to fetch the seating layout for a venue, including details on which seats are already booked for a specific date. @@ -132542,10 +133733,10 @@ The last step is to send order confirmation emails to customers with their ticke To send an email in Medusa when an order is placed, you'll need: -- A [Notification Module Provider](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification) to handle sending emails. For example, [SendGrid](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid) or [Resend](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/integrations/guides/resend). +- A [Notification Module Provider](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/index.html.md) to handle sending emails. For example, [SendGrid](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid/index.html.md) or [Resend](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/integrations/guides/resend/index.html.md). - You also need to define an email template for the order confirmation email in the provider. - A method in the Ticket Booking Module's service that generates the ticket QR codes. -- A [Subscriber](undefined/docs/learn/fundamentals/events-and-subscribers) that listens to the `order.placed` event and sends an email with the order details. +- A [Subscriber](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md) that listens to the `order.placed` event and sends an email with the order details. - A workflow and API route to handle verifying scanned QR codes at the event entrance. ### a. Set Up Notification Module @@ -132579,7 +133770,7 @@ module.exports = defineConfig({ }) ``` -Make sure to set the `SENDGRID_API_KEY` and `SENDGRID_FROM` environment variables in your `.env` file, as explained in the [SendGrid Notification Module Provider guide](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid). +Make sure to set the `SENDGRID_API_KEY` and `SENDGRID_FROM` environment variables in your `.env` file, as explained in the [SendGrid Notification Module Provider guide](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid/index.html.md). You also need to define an email template for the order confirmation email in SendGrid. The following is a dynamic template you can use: @@ -132864,7 +134055,7 @@ In the subscriber, you: ### Test Order Confirmation Email -To test the order confirmation email, [customize the storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/ticket-booking/example/storefront) first. Then, start the Medusa application and the Next.js Starter Storefront. +To test the order confirmation email, [customize the storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/ticket-booking/example/storefront/index.html.md) first. Then, start the Medusa application and the Next.js Starter Storefront. Place an order with at least one ticket product. After placing the order, you'll see the following message in your Medusa application's terminal: @@ -133067,23 +134258,23 @@ If the ticket is valid, you'll receive a success response. Otherwise, you'll rec ## Next Steps -You've now implemented the ticket booking functionality in the backend. Follow the [Ticket Booking Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/ticket-booking/example/storefront) tutorial to customize the Next.js Starter Storefront for ticket booking. +You've now implemented the ticket booking functionality in the backend. Follow the [Ticket Booking Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/ticket-booking/example/storefront/index.html.md) tutorial to customize the Next.js Starter Storefront for ticket booking. You can expand on this tutorial by adding more features, such as: - Provide more management features for venues and ticket products, such as updating and deleting them. - Allow purchasing tickets for specific times in a day. -- Handle [order events](undefined/references/events#order-events), such as `order.canceled`, to make changes to ticket purchases. +- Handle [order events](https://docs.medusajs.com/references/events#order-events/index.html.md), such as `order.canceled`, to make changes to ticket purchases. ### Learn More about Medusa -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). ### Troubleshooting -If you encounter issues during your development, check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting). +If you encounter issues during your development, check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/index.html.md). ### Getting Help @@ -133095,7 +134286,7 @@ If you encounter issues not covered in the troubleshooting guides: # Customize Storefront for Ticket Booking -In this tutorial, you'll customize the Next.js Starter Storefront based on the [Ticket Booking system](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/ticket-booking/example) you implemented in the backend. +In this tutorial, you'll customize the Next.js Starter Storefront based on the [Ticket Booking system](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/ticket-booking/example/index.html.md) you implemented in the backend. ### Prerequisites @@ -133104,7 +134295,7 @@ In this tutorial, you'll customize the Next.js Starter Storefront based on the [ ## Summary -In this tutorial, you'll customize the [Next.js Starter Storefront](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/nextjs-starter) to support ticket booking: +In this tutorial, you'll customize the [Next.js Starter Storefront](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/nextjs-starter/index.html.md) to support ticket booking: 1. **Product Page**: Allow customers to choose a show date, select seats from a seating layout, and add tickets to the cart. 2. **Cart Page**: Display selected tickets with their seat numbers and show dates, and remove quantity controls for ticket items. @@ -133247,7 +134438,7 @@ Next, you'll customize the product page. This includes: ### Date Selector Component -The date selector component will fetch the available dates for a ticket product using the API route you created in the [backend part of the tutorial](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/ticket-booking/example#a-available-dates-api-route). Before creating the component, you'll add a server function to fetch the available dates. +The date selector component will fetch the available dates for a ticket product using the API route you created in the [backend part of the tutorial](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/ticket-booking/example#a-available-dates-api-route/index.html.md). Before creating the component, you'll add a server function to fetch the available dates. Create the file `src/lib/data/ticket-products.ts` with the following content: @@ -133475,7 +134666,7 @@ You also display a calendar to select a show date, and a button to pick seats th ### Seat Selector Component -The seat selector component will fetch the seating layout for a venue and date using the API route you created in the [backend part of the tutorial](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/ticket-booking/example#b-seating-layout-api-route). Before creating the component, you'll add a server function to fetch the seating layout. +The seat selector component will fetch the seating layout for a venue and date using the API route you created in the [backend part of the tutorial](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/ticket-booking/example#b-seating-layout-api-route/index.html.md). Before creating the component, you'll add a server function to fetch the seating layout. In `src/lib/data/ticket-products.ts`, add the following import at the top of the file: @@ -134782,7 +135973,7 @@ export async function setAddresses(currentState: unknown, formData: FormData) { This updates the function to only handle the billing address and email fields. It also redirects to the `payment` step of checkout instead of the `shipping` step. -Finally, you'll update the `placeOrder` function to use the custom cart completion API route you created in the [backend part of the tutorial](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/ticket-booking/example#custom-complete-cart-workflow). Replace the entire function with the following: +Finally, you'll update the `placeOrder` function to use the custom cart completion API route you created in the [backend part of the tutorial](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/ticket-booking/example#custom-complete-cart-workflow/index.html.md). Replace the entire function with the following: ```ts title="src/lib/data/cart.ts" export async function placeOrder(cartId?: string) { @@ -134983,13 +136174,13 @@ You've now customized the Next.js Starter Storefront to support ticket products. ### Learn More About Medusa -If you're new to Medusa, check out the [main documentation](undefined/docs/learn), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. +If you're new to Medusa, check out the [main documentation](https://docs.medusajs.com/docs/learn/index.html.md), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. -To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). ### Troubleshooting -If you encounter issues during your development, check out the [troubleshooting guides](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/troubleshooting). +If you encounter issues during your development, check out the [troubleshooting guides](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/troubleshooting/index.html.md). ### Getting Help @@ -135003,13 +136194,13 @@ If you encounter issues not covered in the troubleshooting guides: This recipe provides the general steps to implement a ticket booking system in your Medusa application. -Follow the step-by-step [Ticket Booking System Example](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/recipes/ticket-booking/example) to learn how to implement a ticket booking system in your Medusa application. +Follow the step-by-step [Ticket Booking System Example](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/recipes/ticket-booking/example/index.html.md) to learn how to implement a ticket booking system in your Medusa application. ## Overview A ticket booking system allows customers to book tickets for events, such as shows or sports games. By using a ticket booking system, you can manage shows, venues, and seat availability, among other features. -Medusa's [Framework](undefined/docs/learn/fundamentals/framework) facilitates building a ticket booking system on top of the existing commerce functionalities, such as products, pricing, inventory, carts, and orders. All of these are provided by Medusa's [Commerce Modules](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/commerce-modules). +Medusa's [Framework](https://docs.medusajs.com/docs/learn/fundamentals/framework/index.html.md) facilitates building a ticket booking system on top of the existing commerce functionalities, such as products, pricing, inventory, carts, and orders. All of these are provided by Medusa's [Commerce Modules](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/commerce-modules/index.html.md). To support ticket-booking features, you can customize the Medusa application by creating a Ticket Booking Module, linking its data models to Medusa's existing models, and building flows around the module. @@ -135021,7 +136212,7 @@ Your custom features and functionalities are implemented inside modules. The mod The module will hold your custom data models and the service implementing ticket-booking-related features. -[How to Create a Module](undefined/docs/learn/fundamentals/modules): Learn how to create a module. +[How to Create a Module](https://docs.medusajs.com/docs/learn/fundamentals/modules/index.html.md): Learn how to create a module. ### Create Custom Data Models @@ -135039,8 +136230,8 @@ Then, you can link your custom data model to data models from other modules. For - The `TicketProductVariant` model to the Product Module's `ProductVariant` data model, benefiting from existing features related to inventory and pricing. - The `TicketPurchase` model to the Order Module's `Order` data model, benefiting from existing features related to orders and payments. -- [How to Create a Data Model](undefined/docs/learn/fundamentals/modules#1-create-data-model): Learn how to create a data model. -- [Define Module Links](undefined/docs/learn/fundamentals/module-links): Define links between data models. +- [How to Create a Data Model](https://docs.medusajs.com/docs/learn/fundamentals/modules#1-create-data-model/index.html.md): Learn how to create a data model. +- [Define Module Links](https://docs.medusajs.com/docs/learn/fundamentals/module-links/index.html.md): Define links between data models. ### Implement Data Management Features @@ -135048,7 +136239,7 @@ Your module’s main service holds data-management and other related features. T Medusa facilitates implementing data-management features using the service factory. Your module's main service can extend this service factory, and it generates data-management methods for your data models. -[Service Factory](undefined/docs/learn/fundamentals/modules/service-factory): Learn about the service factory and how to use it. +[Service Factory](https://docs.medusajs.com/docs/learn/fundamentals/modules/service-factory/index.html.md): Learn about the service factory and how to use it. *** @@ -135062,8 +136253,8 @@ You can implement workflows that create venues and ticket products, complete car You can then utilize the API routes that execute these workflows in your client applications, such as your Medusa Admin customizations or your storefront. -- [Workflows](undefined/docs/learn/fundamentals/workflows): Learn how to create a workflow. -- [API Routes](undefined/docs/learn/fundamentals/api-routes): Learn how to create API routes. +- [Workflows](https://docs.medusajs.com/docs/learn/fundamentals/workflows/index.html.md): Learn how to create a workflow. +- [API Routes](https://docs.medusajs.com/docs/learn/fundamentals/api-routes/index.html.md): Learn how to create API routes. *** @@ -135075,8 +136266,8 @@ You can set up inventory items for ticket product variants based on show dates a This setup ensures that customers can only book tickets for available seats, preventing overbooking. -- [Inventory Module](undefined/commerce-modules/inventory): Learn about the Inventory Module and its features. -- [Product Variant Inventory](undefined/commerce-modules/product/variant-inventory): Learn how to manage product variant inventory. +- [Inventory Module](https://docs.medusajs.com/commerce-modules/inventory/index.html.md): Learn about the Inventory Module and its features. +- [Product Variant Inventory](https://docs.medusajs.com/commerce-modules/product/variant-inventory/index.html.md): Learn how to manage product variant inventory. *** @@ -135088,7 +136279,7 @@ You can disable shipping on ticket product variants by setting the `requires_shi Then, you can remove shipping-related steps from the checkout flow in the storefront. -[Configure Shipping Requirements](undefined/commerce-modules/product/selling-products#configure-shipping-requirements): Learn how to configure shipping requirements for product variants. +[Configure Shipping Requirements](https://docs.medusajs.com/commerce-modules/product/selling-products#configure-shipping-requirements/index.html.md): Learn how to configure shipping requirements for product variants. *** @@ -135098,8 +136289,8 @@ 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 that execute the workflows implementing ticket-booking-related features. -- [Create a Widget](undefined/docs/learn/fundamentals/admin/widgets): Learn how to create a widget in the Medusa Admin. -- [Create UI Route](undefined/docs/learn/fundamentals/admin/ui-routes): Learn how to create a UI route in the Medusa Admin. +- [Create a Widget](https://docs.medusajs.com/docs/learn/fundamentals/admin/widgets/index.html.md): Learn how to create a widget in the Medusa Admin. +- [Create UI Route](https://docs.medusajs.com/docs/learn/fundamentals/admin/ui-routes/index.html.md): Learn how to create a UI route in the Medusa Admin. *** @@ -135111,7 +136302,7 @@ Specifically, workflows like `addToCartWorkflow` and `completeCartWorkflow` prov For example, you can consume the `validate` hook in the `addToCartWorkflow` to check if the selected seat is available before adding a ticket product variant to the cart. -[Workflow Hooks](undefined/docs/learn/fundamentals/workflows/workflow-hooks): Learn how to use workflow hooks. +[Workflow Hooks](https://docs.medusajs.com/docs/learn/fundamentals/workflows/workflow-hooks/index.html.md): Learn how to use workflow hooks. *** @@ -135119,14 +136310,14 @@ For example, you can consume the `validate` hook in the `addToCartWorkflow` to c When an order is placed, Medusa emits an `order.placed` event. You can listen to this event in a subscriber, which is an asynchronous function executed in the background when its associated event is emitted. -In the subscriber, you can send an email using the Notification Module. You can register a Notification Module Provider, such as [SendGrid](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid) or [Resend](undefined/Users/ters/Desktop/personal/forks/medusa/www/apps/resources/app/integrations/guides/resend), that sends the email. +In the subscriber, you can send an email using the Notification Module. You can register a Notification Module Provider, such as [SendGrid](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/infrastructure-modules/notification/sendgrid/index.html.md) or [Resend](https://docs.medusajs.com/Users/shahednasser/medusa/www/apps/resources/app/integrations/guides/resend/index.html.md), that sends the email. You can include a QR code representing the ticket in the email, which you can generate using a library like `qrcode`. You can also implement an API route that verifies the QR code at the event entrance. -- [Events and Subscribers](undefined/docs/learn/fundamentals/events-and-subscribers): Learn how to create a subscriber. -- [Notification Module](undefined/infrastructure-modules/notification): Learn about available Notification Module Providers. +- [Events and Subscribers](https://docs.medusajs.com/docs/learn/fundamentals/events-and-subscribers/index.html.md): Learn how to create a subscriber. +- [Notification Module](https://docs.medusajs.com/infrastructure-modules/notification/index.html.md): Learn about available Notification Module Providers. *** @@ -135138,5 +136329,5 @@ Medusa provides a Next.js Starter Storefront with standard commerce features inc Alternatively, you can build the storefront with your preferred tech stack. -- [Next.js Starter Storefront](undefined/nextjs-starter): Learn how to install and use the Next.js Starter Storefront. -- [Storefront Guides](undefined/storefront-development): Learn how to build a storefront for your Medusa application. +- [Next.js Starter Storefront](https://docs.medusajs.com/nextjs-starter/index.html.md): Learn how to install and use the Next.js Starter Storefront. +- [Storefront Guides](https://docs.medusajs.com/storefront-development/index.html.md): Learn how to build a storefront for your Medusa application. diff --git a/www/apps/resources/app/integrations/guides/algolia/page.mdx b/www/apps/resources/app/integrations/guides/algolia/page.mdx index cb4f4b2d4a..8319aadbc9 100644 --- a/www/apps/resources/app/integrations/guides/algolia/page.mdx +++ b/www/apps/resources/app/integrations/guides/algolia/page.mdx @@ -183,7 +183,7 @@ If you want to index other types of data, such as product categories, you can ad A module's service receives the module's options as a second parameter in its constructor. In the constructor, you initialize the Algolia client using the module's options. - + A module has a container that holds all resources registered in that module, and you can access those resources in the first parameter of the constructor. Learn more about it in the [Module Container documentation](!docs!/learn/fundamentals/modules/container). @@ -535,7 +535,18 @@ export const syncProductsWorkflow = createWorkflow( ({ filters, limit, offset }: SyncProductsWorkflowInput) => { const { data, metadata } = useQueryGraphStep({ entity: "product", - fields: ["id", "title", "description", "handle", "thumbnail", "categories.*", "tags.*"], + fields: [ + "id", + "title", + "description", + "handle", + "thumbnail", + "categories.id", + "categories.name", + "categories.handle", + "tags.id", + "tags.value", + ], pagination: { take: limit, skip: offset, diff --git a/www/apps/resources/app/integrations/guides/meilisearch/page.mdx b/www/apps/resources/app/integrations/guides/meilisearch/page.mdx new file mode 100644 index 0000000000..6cc29bf6d1 --- /dev/null +++ b/www/apps/resources/app/integrations/guides/meilisearch/page.mdx @@ -0,0 +1,1247 @@ +--- +products: + - product +--- + +import { Card, Prerequisites, Details, WorkflowDiagram } from "docs-ui" +import { Github, PlaySolid } from "@medusajs/icons" + +export const metadata = { + title: `Integrate Meilisearch with Medusa`, +} + +# {metadata.title} + +In this tutorial, you'll learn how to integrate Meilisearch with Medusa to enable advanced search capabilities in your storefront. + +When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. Medusa's architecture supports integrating third-party services, such as search engines, allowing you to build custom features around core commerce flows. + +[Meilisearch](https://www.meilisearch.com/) is an open-source, fast, and relevant search engine that you can integrate with Medusa to enhance your storefront's search functionality. + +## Summary + +By following this tutorial, you'll learn how to: + +- Install and set up Medusa. +- Integrate Meilisearch into Medusa. +- Trigger Meilisearch reindexing when a product is created, updated, or deleted, or when an admin manually triggers a reindex. +- Customize the Next.js Starter Storefront to search for products through Meilisearch. + +You can follow this tutorial whether you're new to Medusa or an advanced Medusa developer. + +![Diagram illustrating the integration of Meilisearch with Medusa](https://res.cloudinary.com/dza7lstvk/image/upload/v1758091098/Medusa%20Resources/meilisearch-summary_bdig6e.jpg) + + + +--- + +## Step 1: Install a Medusa Application + + + +Start by installing the Medusa application on your machine with the following command: + +```bash +npx create-medusa-app@latest +``` + +You'll first be asked for the project's name. Then, when asked whether you want to install the [Next.js Starter Storefront](../../../nextjs-starter/page.mdx), choose "Yes." + +Afterwards, the installation process will start, which will install the Medusa application in a directory with your project's name and the Next.js Starter Storefront in a separate directory named `{project-name}-storefront`. + + + +The Medusa application is composed of a headless Node.js server and an admin dashboard. The storefront is installed or custom-built separately and connects to the Medusa application through its REST endpoints, called [API routes](!docs!/learn/fundamentals/api-routes). Learn more in [Medusa's Architecture documentation](!docs!/learn/introduction/architecture). + + + +Once the installation finishes successfully, the Medusa Admin dashboard will open with a form to create a new user. Enter the user's credentials and submit the form. Afterwards, you can log in with the new user and explore the dashboard. + + + +Check out the [troubleshooting guides](../../../troubleshooting/create-medusa-app-errors/page.mdx) for help. + + + +--- + +## Step 2: Create Meilisearch Module + + + +To integrate third-party services into Medusa, you create a custom module. A module is a reusable package with functionalities related to a single feature or domain. Medusa integrates the module into your application without side effects on your setup. + +In this step, you'll create a custom module that provides the necessary functionalities to integrate Meilisearch with Medusa. + + + +Refer to the [Modules documentation](!docs!/learn/fundamentals/modules) to learn more. + + + +Before building the module, you need to install Meilisearch's JavaScript client. Run the following command in your Medusa application's root directory: + +```bash npm2yarn +npm install meilisearch +``` + +### Create Module Directory + +A module is created under the `src/modules` directory of your Medusa application. So, create the directory `src/modules/meilisearch`. + +### Create Service + +You define a module's functionalities in a service. A service is a TypeScript or JavaScript class that the module exports. In the service's methods, you can connect to the database, which is useful if your module defines tables in the database, or connect to third-party services. + +In this section, you'll create the Meilisearch Module's service and the methods necessary to manage indexed products in Meilisearch and search through them. + +To create the Meilisearch Module's service, create the file `src/modules/meilisearch/service.ts` with the following content: + +```ts title="src/modules/meilisearch/service.ts" +const { Meilisearch } = require("meilisearch") +import { MedusaError } from "@medusajs/framework/utils" + +type MeilisearchOptions = { + host: string; + apiKey: string; + productIndexName: string; +} + +export type MeilisearchIndexType = "product" + +export default class MeilisearchModuleService { + private client: typeof Meilisearch + private options: MeilisearchOptions + + constructor({}, options: MeilisearchOptions) { + if (!options.host || !options.apiKey || !options.productIndexName) { + throw new MedusaError( + MedusaError.Types.INVALID_ARGUMENT, + "Meilisearch options are required" + ) + } + this.client = new Meilisearch({ + host: options.host, + apiKey: options.apiKey, + }) + this.options = options + } + + // TODO: Add methods +} +``` + +You export a class that serves as the Meilisearch Module's service. In the service, you define two properties: + +- `client`: An instance of the Meilisearch Client, which you'll use to perform actions with Meilisearch's API. +- `options`: An object of options that the module receives when it's registered, which you'll learn about later. The options contain: + - `apiKey`: The Meilisearch API key. + - `host`: The Meilisearch host. + - `productIndexName`: The name of the index where products are stored. + + + +If you want to index other types of data, such as product categories, you can add new properties for their index names in the `MeilisearchOptions` type. + + + +A module's service receives the module's options as a second parameter in its constructor. In the constructor, you initialize the Meilisearch client using the module's options. + + + +A module has a container that holds all resources registered in that module, and you can access those resources in the first parameter of the constructor. Learn more about it in the [Module Container documentation](!docs!/learn/fundamentals/modules/container). + + + +#### Index Data Method + +The first method you need to add to the service is a method that receives an array of data to add or update in Meilisearch's index. + +Add the following methods to the `MeilisearchModuleService` class: + +```ts title="src/modules/meilisearch/service.ts" +export default class MeilisearchModuleService { + // ... + async getIndexName(type: MeilisearchIndexType) { + switch (type) { + case "product": + return this.options.productIndexName + default: + throw new Error(`Invalid index type: ${type}`) + } + } + + async indexData(data: Record[], type: MeilisearchIndexType = "product") { + const indexName = await this.getIndexName(type) + const index = this.client.index(indexName) + + // Transform data to include id as primary key for Meilisearch + const documents = data.map((item) => ({ + ...item, + id: item.id, + })) + + await index.addDocuments(documents) + } +} +``` + +You define two methods: + +1. `getIndexName`: A method that receives an `MeilisearchIndexType` (defined in the previous snippet) and returns the index name for that type. In this case, you only have one type, `product`, so you return the product index name. + - If you want to index other types of data, you can add more cases to the switch statement. +2. `indexData`: A method that receives an array of data and an `MeilisearchIndexType`. The method indexes the data in the Meilisearch index for the given type. + +### Retrieve and Delete Methods + +The next methods you'll add to the service are methods to retrieve and delete data from the Meilisearch index. You'll use these later to keep the Meilisearch index in sync with Medusa. + +Add the following methods to the `MeilisearchModuleService` class: + +```ts title="src/modules/meilisearch/service.ts" +export default class MeilisearchModuleService { + // ... + + async retrieveFromIndex(documentIds: string[], type: MeilisearchIndexType = "product") { + const indexName = await this.getIndexName(type) + const index = this.client.index(indexName) + + const results = await Promise.all( + documentIds.map(async (id) => { + try { + return await index.getDocument(id) + } catch (error) { + // Document not found, return null + return null + } + }) + ) + + return results.filter(Boolean) + } + + async deleteFromIndex(documentIds: string[], type: MeilisearchIndexType = "product") { + const indexName = await this.getIndexName(type) + const index = this.client.index(indexName) + + await index.deleteDocuments(documentIds) + } +} +``` + +You define two methods: + +1. `retrieveFromIndex`: A method that receives an array of document IDs and a `MeilisearchIndexType`. The method retrieves the documents with the given IDs from the Meilisearch index. +2. `deleteFromIndex`: A method that receives an array of document IDs and a `MeilisearchIndexType`. The method deletes the documents with the given IDs from the Meilisearch index. + +#### Search Method + +The last method you'll implement is a method to search through the Meilisearch index. This method lets you expose search functionality to clients through Medusa's API routes. + +Add the following method to the `MeilisearchModuleService` class: + +```ts title="src/modules/meilisearch/service.ts" +export default class MeilisearchModuleService { + // ... + + async search(query: string, type: MeilisearchIndexType = "product") { + const indexName = await this.getIndexName(type) + const index = this.client.index(indexName) + + return await index.search(query) + } +} +``` + +The `search` method receives a query string and a `MeilisearchIndexType`. The method searches through the Meilisearch index for the given type, such as products, and returns the results. + + +### Export Module Definition + +The final piece of a module is its definition, which you export in an `index.ts` file at its root directory. This definition tells Medusa the name of the module and its service. + +So, create the file `src/modules/meilisearch/index.ts` with the following content: + +```ts title="src/modules/meilisearch/index.ts" +import { Module } from "@medusajs/framework/utils" +import MeilisearchModuleService from "./service" + +export const MEILISEARCH_MODULE = "meilisearch" + +export default Module(MEILISEARCH_MODULE, { + service: MeilisearchModuleService, +}) +``` + +You use the `Module` function from the Modules SDK to create the module's definition. It accepts two parameters: + +1. The module's name, which is `meilisearch`. +2. An object with a required property `service` indicating the module's service. + +You also export the module's name as `MEILISEARCH_MODULE` so you can reference it later. + +### Add Module to Medusa's Configurations + +Once you finish building the module, add it to Medusa's configurations to start using it. + +In `medusa-config.ts`, add a `modules` property and pass an array with your custom module: + +```ts title="medusa-config.ts" +module.exports = defineConfig({ + // ... + modules: [ + { + resolve: "./src/modules/meilisearch", + options: { + host: process.env.MEILISEARCH_HOST!, + apiKey: process.env.MEILISEARCH_API_KEY!, + productIndexName: process.env.MEILISEARCH_PRODUCT_INDEX_NAME!, + }, + }, + ], +}) +``` + +Each object in the `modules` array has a `resolve` property, whose value is either a path to the module's directory, or an `npm` package’s name. + +You also pass an `options` property with the module's options, including the Meilisearch host, API Key, and the product index name. + +### Add Environment Variables + +Before you can start using the Meilisearch Module, you need to set the environment variables for the Meilisearch host, API Key, and the product index name. + +Add the following environment variables to your `.env` file: + +```env +MEILISEARCH_HOST=your-meilisearch-host +MEILISEARCH_API_KEY=your-meilisearch-api-key +MEILISEARCH_PRODUCT_INDEX_NAME=your-product-index-name +``` +- `your-meilisearch-host` is the host of your Meilisearch instance. If you're running Meilisearch locally, it should be `http://127.0.0.1:7700`. +- `your-meilisearch-api-key` is the master key of your Meilisearch instance. If you're running Meilisearch locally, you should have set it when starting Meilisearch. If you're using Meilisearch Cloud, you can find it in the dashboard under "API Keys." Learn more in the [Meilisearch documentation](https://www.meilisearch.com/docs/learn/security/basic_security). +- `your-product-index-name` is the name of the index where you'll store products. You can choose any name you want. Even if the index doesn't exist, Meilisearch will create it when you add documents to it. + +Your module is now ready for use. You'll see how to use it in the next steps. + +--- + +## Step 3: Sync Products to Meilisearch Workflow + +To keep the Meilisearch index in sync with Medusa, you need to trigger indexing when products are created, updated, or deleted in Medusa. You can also allow admins to manually trigger a reindex. + +To implement the indexing functionality, you need to create a [workflow](!docs!/learn/fundamentals/workflows). A workflow is a series of actions, called steps, that complete a task. You construct a workflow like you construct a function, but it's a special function that allows you to track its executions' progress, define roll-back logic, and configure other advanced features. + + + +Learn more about workflows in the [Workflows documentation](!docs!/learn/fundamentals/workflows). + + + +In this step, you'll create a workflow that indexes products in Meilisearch. In the next steps, you'll learn how to use the workflow when products are created, updated, or deleted, or when admins manually trigger a reindex. + +The workflow has the following steps: + + + +Medusa provides the `useQueryGraphStep` in its `@medusajs/medusa/core-flows` package. You only need to implement the second step. + +### syncProductsStep + +In the second step of the workflow, you create or update indexes in Meilisearch for the products retrieved in the first step. + +To create the step, create the file `src/workflows/steps/sync-products.ts` with the following content: + +```ts title="src/workflows/steps/sync-products.ts" +import { ProductDTO } from "@medusajs/framework/types" +import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk" +import { MEILISEARCH_MODULE } from "../../modules/meilisearch" + +export type SyncProductsStepInput = { + products: ProductDTO[] +} + +export const syncProductsStep = createStep( + "sync-products", + async ({ products }: SyncProductsStepInput, { container }) => { + const meilisearchModuleService = container.resolve( + MEILISEARCH_MODULE + ) + const existingProducts = await meilisearchModuleService.retrieveFromIndex( + products.map((product) => product.id), + "product" + ) + const newProducts = products.filter((product) => !existingProducts.some( + (p) => p.id === product.id) + ) + await meilisearchModuleService.indexData( + products as unknown as Record[], + "product" + ) + + return new StepResponse(undefined, { + newProducts: newProducts.map((product) => product.id), + existingProducts, + }) + } + // TODO add compensation +) +``` + +You create a step with `createStep` from the Workflows SDK. It accepts two parameters: + +1. The step's unique name, which is `sync-products`. +2. An async function that receives two parameters: + - The step's input, which is an object holding an array of products to sync into Meilisearch. + - An object that has properties including the [Medusa container](!docs!/learn/fundamentals/medusa-container), which is a registry of Framework and commerce tools that you can access in the step. + +In the step function, you resolve the Meilisearch Module's service from the Medusa container using the name you exported in the module definition's file. + +Then, you retrieve the products that are already indexed in Meilisearch and determine which products are new. You'll learn why this is useful in a bit. + +Finally, you pass the products you received in the input to Meilisearch to create or update its indices. + +A step function must return a `StepResponse` instance. The `StepResponse` constructor accepts two parameters: + +1. The step's output, which in this case is `undefined`. +2. Data to pass to the step's compensation function. + +#### Compensation Function + +The compensation function undoes the actions performed in a step. Then, if an error occurs during the workflow's execution, the compensation functions of executed steps are called to roll back the changes. This mechanism ensures data consistency in your application, especially as you integrate external systems. + +To add a compensation function to a step, pass it as a third parameter to `createStep`: + +```ts title="src/workflows/steps/sync-products.ts" +export const syncProductsStep = createStep( + // ... + async (input, { container }) => { + if (!input) { + return + } + + const meilisearchModuleService = container.resolve( + MEILISEARCH_MODULE + ) + + if (input.newProducts) { + await meilisearchModuleService.deleteFromIndex( + input.newProducts, + "product" + ) + } + + if (input.existingProducts) { + await meilisearchModuleService.indexData( + input.existingProducts, + "product" + ) + } + } +) +``` + +The compensation function receives two parameters: + +1. The data you passed as a second parameter of `StepResponse` in the step function. +2. A context object similar to the step function that holds the Medusa container. + +In the compensation function, you resolve the Meilisearch Module's service from the container. Then, you delete from Meilisearch the products that were newly indexed and revert the existing products to their original data. + +### Add Sync Products Workflow + +You can now create the workflow that syncs products to Meilisearch. + +To create the workflow, create the file `src/workflows/sync-products.ts` with the following content: + +```ts title="src/workflows/sync-products.ts" +import { createWorkflow, WorkflowResponse } from "@medusajs/framework/workflows-sdk" +import { useQueryGraphStep } from "@medusajs/medusa/core-flows" +import { syncProductsStep, SyncProductsStepInput } from "./steps/sync-products" + +type SyncProductsWorkflowInput = { + filters?: Record + limit?: number + offset?: number +} + +export const syncProductsWorkflow = createWorkflow( + "sync-products", + ({ filters, limit, offset }: SyncProductsWorkflowInput) => { + const { data, metadata } = useQueryGraphStep({ + entity: "product", + fields: [ + "id", + "title", + "description", + "handle", + "thumbnail", + "categories.id", + "categories.name", + "categories.handle", + "tags.id", + "tags.value", + ], + pagination: { + take: limit, + skip: offset, + }, + filters: { + status: "published", + ...filters, + }, + }) + + syncProductsStep({ + products: data, + } as SyncProductsStepInput) + + return new WorkflowResponse({ + products: data, + metadata, + }) + } +) +``` + +You create a workflow using `createWorkflow` from the Workflows SDK. It accepts the workflow's unique name as a first parameter. + +It accepts as a second parameter a constructor function, which is the workflow's implementation. The function can accept input, which in this case is pagination and filter parameters for the products to retrieve. + +In the workflow's constructor function, you: + +1. Retrieve products from Medusa's database using `useQueryGraphStep`. This step uses Medusa's [Query](!docs!/learn/fundamentals/module-links/query) tool to retrieve data across modules. You pass it the pagination and filter parameters you received in the input. +2. Index the products in Meilisearch using `syncProductsStep`. You pass it the products you retrieved in the previous step. + +A workflow must return an instance of `WorkflowResponse`. The `WorkflowResponse` constructor accepts the workflow's output as a parameter, which is an object holding the retrieved products and their pagination details. + +In the next step, you'll learn how to execute this workflow. + +--- + +## Step 4: Trigger Meilisearch Sync Manually + +As mentioned earlier, you'll trigger the Meilisearch sync automatically when product events occur. You also want to allow admins to manually trigger a reindex. + +In this step, you'll add the functionality to trigger the `syncProductsWorkflow` manually from the Medusa Admin dashboard. This requires: + +1. Creating a subscriber that listens to a custom `meilisearch.sync` event to trigger syncing products to Meilisearch. +2. Creating an API route that the Medusa Admin dashboard can call to emit the `meilisearch.sync` event, which triggers the subscriber. +3. Adding a new page or UI route to the Medusa Admin dashboard to allow admins to trigger the reindex. + +### Create Products Sync Subscriber + +A subscriber is an asynchronous function that listens to one or more events and performs actions when these events are emitted. A subscriber is useful when syncing data across systems, as the operation can be time-consuming and should be performed in the background. + + + +Learn more about subscribers in the [Events and Subscribers documentation](!docs!/learn/fundamentals/events-and-subscribers). + + + +You create a subscriber in a TypeScript or JavaScript file under the `src/subscribers` directory. So, to create the subscriber that listens to the `meilisearch.sync` event, create the file `src/subscribers/meilisearch-sync.ts` with the following content: + +```ts title="src/subscribers/meilisearch-sync.ts" +import { + SubscriberArgs, + type SubscriberConfig, +} from "@medusajs/framework" +import { syncProductsWorkflow } from "../workflows/sync-products" + +export default async function meilisearchSyncHandler({ + container, +}: SubscriberArgs) { + const logger = container.resolve("logger") + + let hasMore = true + let offset = 0 + const limit = 50 + let totalIndexed = 0 + + logger.info("Starting product indexing...") + + while (hasMore) { + const { result: { products, metadata } } = await syncProductsWorkflow(container) + .run({ + input: { + limit, + offset, + }, + }) + + hasMore = offset + limit < (metadata?.count ?? 0) + offset += limit + totalIndexed += products.length + } + + logger.info(`Successfully indexed ${totalIndexed} products`) +} + +export const config: SubscriberConfig = { + event: "meilisearch.sync", +} +``` + +A subscriber file must export: + +1. An asynchronous function, which is the subscriber that is executed when the event is emitted. +2. A configuration object that holds the name of the event the subscriber listens to, which is `meilisearch.sync` in this case. + +The subscriber function receives an object as a parameter that has a `container` property, which is the Medusa container. + +In the subscriber function, you initialize variables to keep track of pagination and the total number of products indexed. + +Then, you start a loop that retrieves products in batches of 50. It indexes them in Meilisearch using the `syncProductsWorkflow`. Finally, you log the total number of products indexed. + +You'll learn how to emit the `meilisearch.sync` event next. + + + +If you want to sync other data types, you can do it in this subscriber as well. + + + +### Create API Route to Trigger Sync + +To allow the Medusa Admin dashboard to trigger the `meilisearch.sync` event, you need to create an API route that emits the event. + +An API Route is an endpoint that exposes commerce features to external applications and clients, such as storefronts. + + + +Learn more about API routes in [this documentation](!docs!/learn/fundamentals/api-routes). + + + +An API route is created in a `route.ts` file under a subdirectory of the `src/api` directory. The path of the API route is the file's path relative to `src/api`. + +So, to create an API route at the path `/admin/meilisearch/sync`, create the file `src/api/admin/meilisearch/sync/route.ts` with the following content: + +```ts title="src/api/admin/meilisearch/sync/route.ts" +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { Modules } from "@medusajs/framework/utils" + +export async function POST( + req: MedusaRequest, + res: MedusaResponse +) { + const eventModuleService = req.scope.resolve(Modules.EVENT_BUS) + await eventModuleService.emit({ + name: "meilisearch.sync", + data: {}, + }) + res.send({ + message: "Syncing data to Meilisearch", + }) +} + +``` + +Since you export a `POST` route handler function, you expose a `POST` API route at `/admin/meilisearch/sync`. The route handler function accepts two parameters: + +1. A request object with details and context on the request, such as body parameters or authenticated user details. +2. A response object to manipulate and send the response. + +In the route handler, you use the Medusa container that is available in the request object. You resolve the [Event Module](../../../infrastructure-modules/event/page.mdx). This module manages events and their subscribers. + +Then, you emit the `meilisearch.sync` event using the Event Module's `emit` method. You pass it the event name. + +Finally, you send a response with a message indicating that data is being synced to Meilisearch. + +### Add Meilisearch Sync Page to Admin Dashboard + +The last step is to add a new page to the admin dashboard. This page allows admins to trigger the reindex. You add a new page using a [UI Route](!docs!/learn/fundamentals/admin/ui-routes). + +A UI route is a React component that specifies the content to be shown in a new page in the Medusa Admin dashboard. You'll create a UI route to display a button that triggers the reindex when clicked. + + + +Learn more about UI routes in the [UI Routes documentation](!docs!/learn/fundamentals/admin/ui-routes). + + + +#### Configure JS SDK + +Before creating the UI route, you'll configure Medusa's [JS SDK](../../../js-sdk/page.mdx). You can use it to send requests to the Medusa server from any client application, including your Medusa Admin customizations. + +The JS SDK is installed by default in your Medusa application. To configure it, create the file `src/admin/lib/sdk.ts` with the following content: + +```ts title="src/admin/lib/sdk.ts" +import Medusa from "@medusajs/js-sdk" + +export const sdk = new Medusa({ + baseUrl: import.meta.env.VITE_BACKEND_URL || "/", + debug: import.meta.env.DEV, + auth: { + type: "session", + }, +}) +``` + +You create an instance of the JS SDK using the `Medusa` class from the JS SDK. You pass it an object having the following properties: + +- `baseUrl`: The base URL of the Medusa server. +- `debug`: A boolean indicating whether to log debug information into the console. +- `auth`: An object specifying the authentication type. When using the JS SDK for admin customizations, you use the `session` authentication type. + +#### Create UI Route + +You'll now create the UI route that displays a button to trigger the reindex. You create a UI route in a `page.tsx` file under a subdirectory of `src/admin/routes` directory. The file's path relative to `src/admin/routes` determines its path in the dashboard. + +So, to create a new page under the Settings section of the Medusa Admin, create the file `src/admin/routes/settings/meilisearch/page.tsx` with the following content: + +```tsx title="src/admin/routes/settings/meilisearch/page.tsx" +import { Container, Heading, Button, toast } from "@medusajs/ui" +import { useMutation } from "@tanstack/react-query" +import { sdk } from "../../../lib/sdk" +import { defineRouteConfig } from "@medusajs/admin-sdk" + +const MeilisearchPage = () => { + const { mutate, isPending } = useMutation({ + mutationFn: () => + sdk.client.fetch("/admin/meilisearch/sync", { + method: "POST", + }), + onSuccess: () => { + toast.success("Successfully triggered data sync to Meilisearch") + }, + onError: (err) => { + console.error(err) + toast.error("Failed to sync data to Meilisearch") + }, + }) + + const handleSync = () => { + mutate() + } + + return ( + +
+ Meilisearch Sync +
+
+ +
+
+ ) +} + +export const config = defineRouteConfig({ + label: "Meilisearch", +}) + +export default MeilisearchPage +``` + +A UI route's file must export: + +1. A React component that defines the content of the page. +2. A configuration object that specifies the route's label in the dashboard. This label is used to show a sidebar item for the new route. + +In the React component, you use `useMutation` hook from `@tanstack/react-query` to create a mutation that sends a `POST` request to the API route you created earlier. In the mutation function, you use the JS SDK to send the request. + +Then, in the return statement, you display a button that triggers the mutation when clicked, which sends a request to the API route you created earlier. + +### Test it Out + +You'll now test out the entire flow. Start by triggering the reindex manually from the Medusa Admin dashboard, then check the Meilisearch dashboard for the indexed products. + +Run the following command to start the Medusa application: + +```bash npm2yarn +npm run dev +``` + +Then, open the Medusa Admin at `http://localhost:9000/app` and log in with the credentials you set up in the first step. + + + +Can't remember the credentials? Learn how to create a user in the [Medusa CLI reference](../../../medusa-cli/commands/user/page.mdx). + + + +After you log in, go to Settings from the sidebar. You'll find a new "Meilisearch" item in the Settings' sidebar. If you click on it, you'll find the page you created with the button to sync products to Meilisearch. + +If you click on the button, the products will be synced to Meilisearch. + +![The Meilisearch Sync page in the Medusa Admin dashboard with a button to sync products to Meilisearch](https://res.cloudinary.com/dza7lstvk/image/upload/v1758094934/Medusa%20Resources/CleanShot_2025-09-17_at_10.41.51_2x_wph4pp.png) + +You can check that the sync ran and was completed by checking the Medusa logs in the terminal where you started the Medusa application. You should find the following messages: + +```bash +info: Processing meilisearch.sync which has 1 subscribers +info: Starting product indexing... +info: Successfully indexed 4 products +``` + +These messages indicate that the `meilisearch.sync` event was emitted, which triggered the subscriber you created to sync the products using the `syncProductsWorkflow`. + +Finally, you can check the Meilisearch dashboard to see the indexed products. Open the Meilisearch dashboard, either Cloud or local, and choose the index you specified for products in the environment variable `MEILISEARCH_PRODUCT_INDEX_NAME`. You'll find your Medusa products indexed there. + +![The Meilisearch dashboard showing the indexed products](https://res.cloudinary.com/dza7lstvk/image/upload/v1758095145/Medusa%20Resources/CleanShot_2025-09-17_at_10.45.29_2x_y8ytzf.png) + +--- + +## Step 5: Update Index on Product Changes + +You'll now automate the indexing of products whenever a change occurs. This includes when a product is created, updated, or deleted. + +Similar to before, you'll create subscribers to listen to these events. + +### Handle Create and Update Products + +The action to perform when a product is created or updated is the same. You'll use the `syncProductsWorkflow` to sync the product to Meilisearch. + +So, you only need one subscriber to handle these two events. To create the subscriber, create the file `src/subscribers/product-sync.ts` with the following content: + +```ts title="src/subscribers/product-sync.ts" +import { + SubscriberArgs, + type SubscriberConfig, +} from "@medusajs/framework" +import { syncProductsWorkflow } from "../workflows/sync-products" + +export default async function handleProductEvents({ + event: { data }, + container, +}: SubscriberArgs<{ id: string }>) { + await syncProductsWorkflow(container) + .run({ + input: { + filters: { + id: data.id, + }, + }, + }) +} + +export const config: SubscriberConfig = { + event: ["product.created", "product.updated"], +} +``` + +The subscriber listens to the `product.created` and `product.updated` events. When either of these events is emitted, the subscriber triggers the `syncProductsWorkflow` to sync the product to Meilisearch. + +When the `product.created` and `product.updated` events are emitted, the product's ID is passed in the event data payload. You can access this in the `event.data` property of the subscriber function's parameter. + +So, you pass the product's ID to the `syncProductsWorkflow` as a filter to retrieve only the product that was created or updated. + +#### Test it Out + +To test it out, start the Medusa application: + +```bash npm2yarn +npm run dev +``` + +Then, either create a product or update an existing one using the Medusa Admin dashboard. If you check the Meilisearch dashboard, you'll find that the product's index was created or updated. + +### Handle Product Deletion + +When a product is deleted, you need to remove it from the Meilisearch index. This requires a different action than creating or updating a product. You'll create a new workflow that deletes the product from Meilisearch, then create a subscriber that listens to the `product.deleted` event to trigger the workflow. + +#### Create Delete Product Step + +The workflow to delete a product from Meilisearch will have only one step that deletes products by their IDs from Meilisearch. + +So, create the step at `src/workflows/steps/delete-products-from-meilisearch.ts` with the following content: + +```ts title="src/workflows/steps/delete-products-from-meilisearch.ts" +import { + createStep, + StepResponse, +} from "@medusajs/framework/workflows-sdk" +import { MEILISEARCH_MODULE } from "../../modules/meilisearch" + +export type DeleteProductsFromMeilisearchStep = { + ids: string[] +} + +export const deleteProductsFromMeilisearchStep = createStep( + "delete-products-from-meilisearch-step", + async ( + { ids }: DeleteProductsFromMeilisearchStep, + { container } + ) => { + const meilisearchModuleService = container.resolve(MEILISEARCH_MODULE) + + const existingRecords = await meilisearchModuleService.retrieveFromIndex( + ids, + "product" + ) + await meilisearchModuleService.deleteFromIndex( + ids, + "product" + ) + + return new StepResponse(undefined, existingRecords) + }, + async (existingRecords, { container }) => { + if (!existingRecords) { + return + } + const meilisearchModuleService = container.resolve(MEILISEARCH_MODULE) + + await meilisearchModuleService.indexData( + existingRecords, + "product" + ) + } +) +``` + +The step receives the IDs of the products to delete as an input. + +In the step, you resolve the Meilisearch Module's service and retrieve the existing records from Meilisearch. This is useful to revert the deletion if an error occurs. + +Then, you delete the products from Meilisearch and pass the existing records to the compensation function. + +In the compensation function, you reindex the existing records if an error occurs. + +#### Create Delete Product Workflow + +You can now create the workflow that deletes products from Meilisearch. Create the file `src/workflows/delete-products-from-meilisearch.ts` with the following content: + +```ts title="src/workflows/delete-products-from-meilisearch.ts" +import { createWorkflow } from "@medusajs/framework/workflows-sdk" +import { deleteProductsFromMeilisearchStep } from "./steps/delete-products-from-meilisearch" + +type DeleteProductsFromMeilisearchWorkflowInput = { + ids: string[] +} + +export const deleteProductsFromMeilisearchWorkflow = createWorkflow( + "delete-products-from-meilisearch", + (input: DeleteProductsFromMeilisearchWorkflowInput) => { + deleteProductsFromMeilisearchStep(input) + } +) +``` + +The workflow receives an object with the IDs of the products to delete. It then executes the `deleteProductsFromMeilisearchStep` to delete the products from Meilisearch. + +#### Create Delete Product Subscriber + +Finally, you'll create the subscriber that listens to the `product.deleted` event to trigger the above workflow. + +Create the file `src/subscribers/product-delete.ts` with the following content: + +```ts title="src/subscribers/product-delete.ts" +import { + SubscriberArgs, + type SubscriberConfig, +} from "@medusajs/framework" +import { deleteProductsFromMeilisearchWorkflow } from "../workflows/delete-products-from-meilisearch" + +export default async function productDeleteHandler({ + event: { data }, + container, +}: SubscriberArgs<{ id: string }>) { + const logger = container.resolve("logger") + + logger.info(`Deleting product ${data.id} from Meilisearch`) + + await deleteProductsFromMeilisearchWorkflow(container) + .run({ + input: { + ids: [data.id], + }, + }) +} + +export const config: SubscriberConfig = { + event: "product.deleted", +} +``` + +The subscriber listens to the `product.deleted` event. When the event is emitted, the subscriber triggers the `deleteProductsFromMeilisearchWorkflow`, passing it the ID of the product to delete. + +#### Test it Out + +To test product deletion, start the Medusa application: + +```bash npm2yarn +npm run dev +``` + +Then, delete a product from the Medusa Admin dashboard. If you check the Meilisearch dashboard, you'll find that the product index was deleted there as well. + +--- + +## Step 6: Search Products in Next.js Starter Storefront + +The last step is to provide search functionalities to customers on your storefront. In the first step, you installed the [Next.js Starter Storefront](../../../nextjs-starter/page.mdx) along with the Medusa application. + +In this step, you'll customize the Next.js Starter Storefront to add search functionality. + + + +The Next.js Starter Storefront was installed in a separate directory from Medusa. The directory's name is `{your-project}-storefront`. + +So, if your Medusa application's directory is `medusa-search`, you can find the storefront by going back to the parent directory and changing to the `medusa-search-storefront` directory: + +```bash +cd ../medusa-search-storefront # change based on your project name +``` + + + +### Install Meilisearch Packages + +Before adding the implementation of search functionality, you need to install the Meilisearch packages necessary to add search functionality in your storefront. + +Run the following command in the directory of your Next.js Starter Storefront: + +```bash npm2yarn +npm install @meilisearch/instant-meilisearch react-instantsearch +``` + +This installs the Meilisearch InstantSearch JavaScript library and the React InstantSearch library. You'll use these to build the search functionality. + +### Add Search Client Configuration + +Next, you need to configure the Meilisearch search client. + +In `src/lib/config.ts`, add the following imports at the top of the file: + +```ts title="src/lib/config.ts" badgeLabel="Storefront" badgeColor="blue" +import { + instantMeiliSearch, +} from "@meilisearch/instant-meilisearch" +``` + +Then, add the following at the end of the file: + +```ts title="src/lib/config.ts" badgeLabel="Storefront" badgeColor="blue" +export const { searchClient } = instantMeiliSearch( + process.env.NEXT_PUBLIC_MEILISEARCH_HOST || "", + process.env.NEXT_PUBLIC_MEILISEARCH_API_KEY || "" +) +``` + +In the code above, you create a `searchClient` object that initializes the Meilisearch client with your Meilisearch host and API Key. + +### Set Environment Variables + +In the storefront's `.env.local` file, add the following Meilisearch-related environment variables: + +```plain badgeLabel="Storefront" badgeColor="blue" +NEXT_PUBLIC_MEILISEARCH_HOST=your_meilisearch_host +NEXT_PUBLIC_MEILISEARCH_API_KEY=your_meilisearch_api_key +NEXT_PUBLIC_MEILISEARCH_INDEX_NAME=your-products-index-name +``` + +Where: + +- `your_meilisearch_host` is your Meilisearch host, as explained in the [Add Environment Variables section](#add-environment-variables) earlier. +- `your_meilisearch_api_key` is your Meilisearch API key with search permissions. You can retrieve it as explained in the [Meilisearch Documentation](https://www.meilisearch.com/docs/learn/security/basic_security#obtaining-api-keys). +- `your-products-index-name` is the name of the index you created in Meilisearch to store the products. You can retrieve this as explained in the [Add Environment Variables section](#add-environment-variables) earlier. You'll use this variable later. + + + +Do not use the `masterKey` as the API key in the storefront, as it has all permissions, including write permissions. Only use an API key with search permissions. + + + +### Add Search Modal Component + +You'll now add a search modal component that customers can use to search for products. The search modal will display search results in real-time as the customer types in the search query. + +Later, you'll add the search modal to the navigation bar. This allows customers to open the search modal from any page. + +Create the file `src/modules/search/components/modal/index.tsx` with the following content: + +```tsx title="src/modules/search/components/modal/index.tsx" badgeLabel="Storefront" badgeColor="blue" +"use client" + +import React, { useEffect, useState } from "react" +import { Hits, InstantSearch, SearchBox } from "react-instantsearch" +import { searchClient } from "../../../../lib/config" +import Modal from "../../../common/components/modal" +import { Button } from "@medusajs/ui" +import Image from "next/image" +import Link from "next/link" +import { usePathname } from "next/navigation" + +type Hit = { + id: string; + title: string; + description: string; + handle: string; + thumbnail: string; + categories: { + id: string + name: string + handle: string + }[] + tags: { + id: string + value: string + }[] +} + +export default function SearchModal() { + const [isOpen, setIsOpen] = useState(false) + const pathname = usePathname() + + useEffect(() => { + setIsOpen(false) + }, [pathname]) + + return ( + <> +
+ +
+ setIsOpen(false)}> + + + + + + + ) +} + +const Hit = ({ hit }: { hit: Hit }) => { + return ( +
+ {hit.title} +
+

{hit.title}

+

{hit.description}

+
+ +
+ ) +} +``` + +You create a `SearchModal` component that displays a search box and search results using widgets from the `react-instantsearch` library. + +To display each result item (or hit), you create a `Hit` component. This component displays the product's title, description, and thumbnail. You also add a link to the product's page. + +Finally, you show the search modal when the customer clicks a "Search" button. You'll add this button to the navigation bar next. + +### Add Search Button to Navigation Bar + +The last step is to show the search button in the navigation bar. + +In `src/modules/layout/templates/nav/index.tsx`, add the following imports at the top of the file: + +```tsx title="src/modules/layout/templates/nav/index.tsx" badgeLabel="Storefront" badgeColor="blue" +import SearchModal from "@modules/search/components/modal" +``` + +Then, in the return statement of the `Nav` component, add the `SearchModal` component before the `div` surrounding the "Account" link: + +```tsx title="src/modules/layout/templates/nav/index.tsx" badgeLabel="Storefront" badgeColor="blue" + +``` + +The search button will now appear in the navigation bar before the Account link. + +### Test it Out + +To test out the storefront changes and the search API route, start the Medusa application: + +```bash npm2yarn +npm run dev +``` + +Then, start the Next.js Starter Storefront from its directory: + +```bash npm2yarn +npm run dev +``` + +Next, go to `localhost:8000`. You'll find a Search button at the top right of the navigation bar. If you click on it, you can search through your products. You can also click on a product to view its page. + +![The Next.js Starter Storefront showing the search modal with search results](https://res.cloudinary.com/dza7lstvk/image/upload/v1758096281/Medusa%20Resources/CleanShot_2025-09-17_at_11.04.26_2x_bhb9k7.png) + +--- + +## Next Steps + +You've now integrated Meilisearch with Medusa and added search functionality to your storefront. You can expand on these features to: + +- Add filters to the search results. You can do that using [react-instantsearch widgets](https://www.algolia.com/doc/guides/building-search-ui/widgets/showcase/react/). +- Support indexing other data types, such as product categories. You can create subscribers and workflows for categories similar to products. + +### Learn More about Medusa + +If you're new to Medusa, check out the [main documentation](!docs!/learn), where you'll get a more in-depth understanding of all the concepts you've used in this guide and more. + +To learn more about the commerce features that Medusa provides, check out Medusa's [Commerce Modules](../../../commerce-modules/page.mdx). + +### Troubleshooting + +If you encounter issues during your development, check out the [troubleshooting guides](../../../troubleshooting/page.mdx). + +### Getting Help + +If you encounter issues not covered in the troubleshooting guides: + +1. Visit the [Medusa GitHub repository](https://github.com/medusajs/medusa) to report issues or ask questions. +2. Join the [Medusa Discord community](https://discord.gg/medusajs) for real-time support from community members. diff --git a/www/apps/resources/app/integrations/page.mdx b/www/apps/resources/app/integrations/page.mdx index 01e38467e0..a70b2102bf 100644 --- a/www/apps/resources/app/integrations/page.mdx +++ b/www/apps/resources/app/integrations/page.mdx @@ -289,6 +289,14 @@ Integrate a search engine to index and search products or other types of data in variant: "blue", children: "Tutorial" } + }, + { + href: "/integrations/guides/meilisearch", + title: "Meilisearch", + badge: { + variant: "blue", + children: "Tutorial" + } } ]} className="mb-1" diff --git a/www/apps/resources/generated/edit-dates.mjs b/www/apps/resources/generated/edit-dates.mjs index 43c298a72b..89692b6a1f 100644 --- a/www/apps/resources/generated/edit-dates.mjs +++ b/www/apps/resources/generated/edit-dates.mjs @@ -103,7 +103,7 @@ export const generatedEditDates = { "app/deployment/admin/vercel/page.mdx": "2024-10-16T08:10:29.377Z", "app/deployment/storefront/vercel/page.mdx": "2025-05-20T07:51:40.712Z", "app/deployment/page.mdx": "2025-09-29T10:23:47.833Z", - "app/integrations/page.mdx": "2025-08-07T06:06:50.604Z", + "app/integrations/page.mdx": "2025-09-17T08:08:37.954Z", "app/medusa-cli/page.mdx": "2024-08-28T11:25:32.382Z", "app/medusa-container-resources/page.mdx": "2025-07-31T13:24:15.786Z", "app/medusa-workflows-reference/page.mdx": "2025-01-20T08:21:29.962Z", @@ -6047,7 +6047,7 @@ export const generatedEditDates = { "app/troubleshooting/workflow-errors/step-x-defined/page.mdx": "2025-03-21T07:09:02.741Z", "app/troubleshooting/workflow-errors/when-then/page.mdx": "2025-03-21T08:35:45.145Z", "app/how-to-tutorials/tutorials/abandoned-cart/page.mdx": "2025-06-26T11:45:57.112Z", - "app/integrations/guides/algolia/page.mdx": "2025-06-26T12:33:36.673Z", + "app/integrations/guides/algolia/page.mdx": "2025-09-17T07:36:03.845Z", "app/integrations/guides/magento/page.mdx": "2025-05-20T07:51:40.716Z", "app/js-sdk/auth/overview/page.mdx": "2025-03-28T08:05:32.622Z", "app/how-to-tutorials/tutorials/loyalty-points/page.mdx": "2025-06-26T11:58:07.874Z", @@ -6608,6 +6608,7 @@ export const generatedEditDates = { "references/core_flows/Locking/Steps_Locking/variables/core_flows.Locking.Steps_Locking.acquireLockStepId/page.mdx": "2025-09-15T09:52:14.218Z", "references/core_flows/Locking/Steps_Locking/variables/core_flows.Locking.Steps_Locking.releaseLockStepId/page.mdx": "2025-09-15T09:52:14.219Z", "references/core_flows/Locking/core_flows.Locking.Steps_Locking/page.mdx": "2025-09-15T09:52:14.217Z", + "app/integrations/guides/meilisearch/page.mdx": "2025-09-17T08:34:58.966Z", "app/nextjs-starter/guides/storefront-returns/page.mdx": "2025-09-22T06:02:00.580Z", "references/js_sdk/admin/Admin/properties/js_sdk.admin.Admin.views/page.mdx": "2025-09-18T17:04:59.240Z", "app/how-to-tutorials/tutorials/agentic-commerce/page.mdx": "2025-10-02T07:14:50.956Z", diff --git a/www/apps/resources/generated/files-map.mjs b/www/apps/resources/generated/files-map.mjs index b8af25e5d6..f2dfa01fec 100644 --- a/www/apps/resources/generated/files-map.mjs +++ b/www/apps/resources/generated/files-map.mjs @@ -923,6 +923,10 @@ export const filesMap = [ "filePath": "/www/apps/resources/app/integrations/guides/mailchimp/page.mdx", "pathname": "/integrations/guides/mailchimp" }, + { + "filePath": "/www/apps/resources/app/integrations/guides/meilisearch/page.mdx", + "pathname": "/integrations/guides/meilisearch" + }, { "filePath": "/www/apps/resources/app/integrations/guides/payload/page.mdx", "pathname": "/integrations/guides/payload" diff --git a/www/apps/resources/generated/generated-integrations-sidebar.mjs b/www/apps/resources/generated/generated-integrations-sidebar.mjs index 84cddeac35..2070d9eed9 100644 --- a/www/apps/resources/generated/generated-integrations-sidebar.mjs +++ b/www/apps/resources/generated/generated-integrations-sidebar.mjs @@ -257,10 +257,18 @@ const generatedgeneratedIntegrationsSidebarSidebar = { { "loaded": true, "isPathHref": true, - "type": "ref", + "type": "link", "path": "/integrations/guides/algolia", "title": "Algolia", "children": [] + }, + { + "loaded": true, + "isPathHref": true, + "type": "link", + "path": "/integrations/guides/meilisearch", + "title": "Meilisearch", + "children": [] } ] } diff --git a/www/apps/resources/sidebars/integrations.mjs b/www/apps/resources/sidebars/integrations.mjs index fde3f61d10..71c84dd181 100644 --- a/www/apps/resources/sidebars/integrations.mjs +++ b/www/apps/resources/sidebars/integrations.mjs @@ -174,10 +174,15 @@ export const integrationsSidebar = [ initialOpen: true, children: [ { - type: "ref", + type: "link", path: "/integrations/guides/algolia", title: "Algolia", }, + { + type: "link", + path: "/integrations/guides/meilisearch", + title: "Meilisearch", + }, ], }, ]