diff --git a/docs/.eslintrc.js b/docs/.eslintrc.js index 27a5e1fad2601..fb64f612c17da 100644 --- a/docs/.eslintrc.js +++ b/docs/.eslintrc.js @@ -37,7 +37,7 @@ module.exports = { "max-len": [ "error", { - code: 75, + code: 64, }, ], semi: ["error", "never"], @@ -86,7 +86,7 @@ module.exports = { }, ignorePatterns: [ 'docs/content/references/**', - 'docs/content/advanced/backend/subscribers/events-list.md' + 'docs/content/**/events-list.md' ], overrides: [ { diff --git a/docs/content/admin/development.md b/docs/content/admin/development.md index 5e11740947a8a..21d10cdb03857 100644 --- a/docs/content/admin/development.md +++ b/docs/content/admin/development.md @@ -25,7 +25,7 @@ In this document, you’ll learn how to: ### Required Tools -[Git CLI tool](../tutorial/0-set-up-your-development-environment.mdx#git) +[Git CLI tool](../development/backend/prepare-environment.mdx#git) ### Required Accounts @@ -102,4 +102,4 @@ If your forked repository doesn’t have any conflicts with the changes from the ## See Also - [Admin API reference](/api/admin). -- [Local development of the Medusa server](../usage/local-development.md). +- [Local development with Medusa](../development/fundamentals/local-development.md). diff --git a/docs/content/admin/quickstart.mdx b/docs/content/admin/quickstart.mdx index b1f4df545a5fa..0bf25070231d4 100644 --- a/docs/content/admin/quickstart.mdx +++ b/docs/content/admin/quickstart.mdx @@ -11,13 +11,13 @@ This document will guide you through setting up the Medusa admin in minutes, as ## Prerequisites -### Medusa Server +### Medusa Backend -The Medusa admin is connected to the Medusa server. So, make sure to install the Medusa server first before proceeding with the admin. You can check out the [quickstart guide to install the Medusa server](../quickstart/quick-start). +The Medusa admin is connected to the Medusa backend. So, make sure to install the Medusa backend first before proceeding with the admin. You can check out the [quickstart guide to install the Medusa backend](../development/backend/install.mdx). :::tip -If you’re not very familiar with Medusa’s architecture, you can learn more about it in the [Architecture Overview](../introduction#architecture-overview). +If you’re not very familiar with Medusa’s architecture, you can learn more about it in the [Architecture Overview](../development/fundamentals/architecture-overview.md). ::: @@ -37,8 +37,8 @@ You can install Node from the [official website](https://nodejs.org/en/). Instead of manually following this guide to install then later deploy the Medusa Admin, you can deploy the Medusa Admin to Netlify with this button: - - Deploy to Netlify + + Deploy to Netlify --- @@ -81,11 +81,11 @@ If you run into errors during the installation, check out [this troubleshooting ## Test it Out -Before running your Medusa admin, make sure that your Medusa server is running. +Before running your Medusa admin, make sure that your Medusa backend is running. :::tip -To run your Medusa server, go to the directory holding the server and run: +To run your Medusa backend, go to the directory holding the backend and run: ```bash npm2yarn npm run start @@ -107,7 +107,7 @@ Use your Medusa admin’s user credentials to log in. ### Demo Credentials -If you installed the demo data when you installed the Medusa server by using the `--seed` option or running: +If you installed the demo data when you installed the Medusa backend by using the `--seed` option or running: ```bash npm2yarn npm run seed @@ -125,7 +125,7 @@ Passwords in Medusa are hashed using the [scrypt-kdf](https://www.npmjs.com/pack ## Create a New Admin User -To create a new admin user from the command line, run the following command in the directory holding your Medusa server: +To create a new admin user from the command line, run the following command in the directory holding your Medusa backend: ```bash medusa user -e some@email.com -p some-password @@ -145,9 +145,9 @@ The default port is set in `package.json` in the `dev` script: If you wish to change the port you can simply change the `7000` to your desired port. -However, if you change your Medusa admin port, you need to change it in your Medusa server. The Medusa server has the Medusa admin and store URLs set in the configurations to avoid Cross-Origin Resource Sharing (CORS) issues. +However, if you change your Medusa admin port, you need to change it in your Medusa backend. The Medusa backend has the Medusa admin and store URLs set in the configurations to avoid Cross-Origin Resource Sharing (CORS) issues. -To change the URL of the Medusa admin in the server, add a new environment variable `ADMIN_CORS` or modify it if you already have it to your Admin URL: +To change the URL of the Medusa admin in the backend, add a new environment variable `ADMIN_CORS` or modify it if you already have it to your Admin URL: ```bash ADMIN_CORS= @@ -157,7 +157,7 @@ Make sure to replace `` with your URL. :::info -For more details about the Admin CORS configuration, check out the [Configure your Server documentation](../usage/configurations.md#admin-cors). +For more details about the Admin CORS configuration, check out the [Configure your Backend documentation](../development/backend/configurations.md#admin-cors). ::: @@ -167,12 +167,12 @@ For more details about the Admin CORS configuration, check out the [Configure yo Medusa admin provides a lot of ecommerce features including managing Return Merchandise Authorization (RMA) flows, store settings, products, orders, and much more. -You can learn more about Medusa admin and its features in the [User Guide](../user-guide/index.mdx). +You can learn more about Medusa admin and its features in the [User Guide](../user-guide.mdx). --- ## See Also - [Customize Medusa Admin](./development.md) -- Install the [Next.js](../starters/nextjs-medusa-starter.mdx) or [Gatsby](../starters/gatsby-medusa-starter.mdx) storefront starters. -- [Use `create-medusa-app` to install all of Medusa’s 3 components.](../usage/create-medusa-app.mdx) +- Install the [Next.js](../starters/nextjs-medusa-starter.mdx) storefront starter. +- [Use `create-medusa-app` to install all of Medusa’s 3 components.](../create-medusa-app.mdx) diff --git a/docs/content/advanced/backend/publishable-api-keys/index.md b/docs/content/advanced/backend/publishable-api-keys/index.md deleted file mode 100644 index b88e2cb616ffd..0000000000000 --- a/docs/content/advanced/backend/publishable-api-keys/index.md +++ /dev/null @@ -1,115 +0,0 @@ ---- -description: 'Learn what publishable API keys are and how they can be used in the Medusa server. Publishable API keys can be used to scope API calls with an API key.' ---- - -# Publishable API Keys Overview - -In this document, you’ll learn about Publishable API Keys and their usage. - -## Introduction - -While using Medusa’s APIs, you might have to pass some query parameters for certain resources with every or most requests. - -Taking Sales Channels as an example, you have to pass the Sales Channel’s ID as a query parameter to all the necessary endpoints, such as the List Products endpoint. - -This is a tedious and error-prone process. This is where Publishable API Keys are useful. - -Publishable API Keys can be used to scope API calls with an API key, determining what resources are retrieved when querying the API. Currently, they can be associated only with Sales Channels. - -For example, you can associate an API key with a B2B channel, then, on the storefront, retrieve only products available in that channel using the API key. - ---- - -## PublishableApiKey Entity Overview - -The `PublishableApiKey` entity represents a publishable API key that is stored in the database. Some of its important attributes include: - -- `id`: The ID of the publishable API key. This is the API key you’ll use in your API requests. -- `created_by`: The ID of the user that created this API key. -- `revoked_by`: The ID of the user that revoked this API key. A revoked publishable API key cannot be used in requests. - ---- - -## Relation to Other Entities - -### Sales Channels - -A publishable API key can be associated with more than one sales channel, and a sales channel can be associated with more than one publishable API key. - -The relation is represented by the entity `PublishableApiKeySalesChannel`. - ---- - -## Using Publishable API Keys in Requests - -:::note - -Publishable API keys are only for client-side use. They can be publicly accessible in your code, as they are not authorized for the Admin API. - -::: - -### Using Medusa JS Client - -When using [Medusa’s JS Client](../../../js-client/overview.md), you can pass it to the client only once when you create the instance of the client: - -```ts -const medusa = new Medusa({ - maxRetries: 3, - baseUrl: "https://api.example.com", - publishableApiKey, -}) -``` - -This will add the API key as in the header parameter `x-publishable-api-key` on all requests. - -You can also use the `setPublishableKey` method to set it at a later point: - -```ts -const medusa = new Medusa({ - // ... -}) - -// at a later point -medusa.setPublishableKey(publishableApiKey) -``` - -### Using Medusa React - -You can pass the publishable API key to the `MedusaProvider` component: - -```tsx -const App = () => { - return ( - - - - ) -} -``` - -Then, the API key will be passed in the header parameter `x-publishable-api-key` of every request. - -### Using Other Methods - -For other ways of sending requests to your Medusa server, such as using the Fetch API, you must pass `x-publishable-api-key` in the header of every request. Its value is the publishable API key’s `id`. - -```ts -fetch(`/store/products`, { - credentials: "include", - headers: { - "x-publishable-api-key": publishableApiKey, - }, -}) -``` - ---- - -## See Also - -- [How to manage publishable keys as an admin](../../admin/manage-publishable-api-keys.mdx) -- [Publishable API keys admin API reference](/api/admin/#tag/PublishableApiKey) diff --git a/docs/content/advanced/backend/services/overview.md b/docs/content/advanced/backend/services/overview.md deleted file mode 100644 index f1ed4b8175b01..0000000000000 --- a/docs/content/advanced/backend/services/overview.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -description: 'Learn what Services are in the Medusa server. Services represent bundled helper methods that you want to use across the server.' ---- - -# Services - -In this document, you'll learn about what Services are in Medusa. - -## What are Services - -Services in Medusa represent bundled helper methods that you want to use across your server. By convention, they represent a certain entity or functionality in your server. - -For example, you can use Medusa’s `productService` to get the list of products, as well as perform other functionalities related to products. There’s also an `authService` that provides functionalities like authenticating customers and users. - -Custom services are TypeScript or JavaScript files located in the `src/services` directory of your Medusa Server installation. Each service should be a class that extends the `TransactionBaseService` class from the core Medusa package `@medusajs/medusa`. - -Each file you create in `src/services` should hold one service and export it. - -The file name is important as it determines the name of the service when you need to use it elsewhere. The name of the service will be registered as the camel-case version of the file name + `Service` at the end of the name. - -For example, if the file name is `hello.ts`, the service will be registered as `helloService`. If the file name is `hello-world.ts`, the service name will be registered as `helloWorldService`. - -The registration name of the service is important, as you’ll be referring to it when you want to get access to the service using dependency injection or in routes. - ---- - -## See Also - -- [Create a Service](./create-service.md) -- [Services Reference](/references/services/classes/AuthService) diff --git a/docs/content/advanced/backend/upgrade-guides/admin/_category_.json b/docs/content/advanced/backend/upgrade-guides/admin/_category_.json deleted file mode 100644 index 62f8fbd27ea19..0000000000000 --- a/docs/content/advanced/backend/upgrade-guides/admin/_category_.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "position": 3, - "collapsed": true, - "link": null, - "label": "Medusa Admin", - "customProps": { - "sort": "desc" - } -} \ No newline at end of file diff --git a/docs/content/advanced/backend/upgrade-guides/index.mdx b/docs/content/advanced/backend/upgrade-guides/index.mdx deleted file mode 100644 index 219502a8f532d..0000000000000 --- a/docs/content/advanced/backend/upgrade-guides/index.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -hide_table_of_contents: true -description: 'Upgrade guides on how to update the Medusa server along with other Medusa components to the latest version.' ---- - -import DocCardList from '@theme/DocCardList'; -import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; -import filterListItems, { flattenList } from '@site/src/utils/filterListItems'; - -# Upgrade Guides - -Find in this page the upgrade guides that require necessary steps when upgrading to a new version. - -## Server - - - -## Medusa React - - - -## Admin - - \ No newline at end of file diff --git a/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-6.md b/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-6.md deleted file mode 100644 index bd3711da3b084..0000000000000 --- a/docs/content/advanced/backend/upgrade-guides/medusa-core/1-7-6.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -sidebar_position: 2 -description: 'Actions Required for v.1.7.6' ---- - -# v1.7.6 - -Version 1.7.6 of Medusa introduces some database schema changes which require running the migrations command. - -## Overview​ - -The latest versions of Medusa introduce the first implementations of Product Categories. The API layer of this feature is guarded by a [feature flag](../../feature-flags/toggle.md), but the changes to the database schema are not. - -This release introduces another migration for Product Categories. So, it is required to run migrations to ensure your server works as expected. - -## Actions Required​ - -### Run Migrations​ - -After updating your Medusa server and before running it, run the following command to run the latest migrations: - -```bash -medusa migrations run -``` diff --git a/docs/content/advanced/backend/upgrade-guides/medusa-core/_category_.json b/docs/content/advanced/backend/upgrade-guides/medusa-core/_category_.json deleted file mode 100644 index e2430d912e590..0000000000000 --- a/docs/content/advanced/backend/upgrade-guides/medusa-core/_category_.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "position": 1, - "collapsed": false, - "link": null, - "label": "Server", - "customProps": { - "sort": "desc" - } -} \ No newline at end of file diff --git a/docs/content/advanced/backend/upgrade-guides/medusa-react/_category_.json b/docs/content/advanced/backend/upgrade-guides/medusa-react/_category_.json deleted file mode 100644 index 5ef0b7dd9afd1..0000000000000 --- a/docs/content/advanced/backend/upgrade-guides/medusa-react/_category_.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "position": 2, - "collapsed": true, - "link": null, - "label": "Medusa React", - "customProps": { - "sort": "desc" - } -} \ No newline at end of file diff --git a/docs/content/cli/reference.md b/docs/content/cli/reference.md index f272fddd1efac..247fbe637fb09 100644 --- a/docs/content/cli/reference.md +++ b/docs/content/cli/reference.md @@ -1,5 +1,5 @@ --- -description: 'Learn how to install the Medusa CLI Tool. Medusa CLI Tool can be used to perform actions such as create a new Medusa server, run migrations, create a new admin user, and more.' +description: 'Learn how to install the Medusa CLI Tool. Medusa CLI Tool can be used to perform actions such as create a new Medusa backend, run migrations, create a new admin user, and more.' --- # CLI Reference @@ -10,7 +10,7 @@ This document serves as a reference to the Medusa CLI tool including how to inst The Medusa CLI serves as a tool that allows you to perform important commands while developing with Medusa. -To use Medusa, it is required to install the CLI tool as it is used to create a new Medusa server. +To use Medusa, it is required to install the CLI tool as it is used to create a new Medusa backend. --- @@ -57,7 +57,7 @@ Turn on verbose output for detailed logs. **Default:** `false` ```bash -medusa new test-server --verbose +medusa new my-backend --verbose ``` ### --no-color @@ -69,7 +69,7 @@ Turn off colors in the output. **Default:** `false` ```bash -medusa new test-server --no-color +medusa new my-backend --no-color ``` ### --json @@ -79,7 +79,7 @@ Turn on JSON logger. **Default:** `false` ```bash -medusa new test-server --json +medusa new my-backend --json ``` ### --version @@ -98,18 +98,18 @@ medusa --version ### new -Create a new Medusa server. +Create a new Medusa backend. ```bash -medusa new [ []] +medusa new [ []] ``` #### Arguments | Name | Description | Default | | --- | --- | --- | -| `server_name` | The name of the Medusa server. It will be used as the name of the directory created. | If not provided, you’ll be prompted to enter it. | -| `starter_url` | The URL of the starter to create the server from. | The default starter is used. | +| `backend_name` | The name of the Medusa backend. It will be used as the name of the directory created. | If not provided, you’ll be prompted to enter it. | +| `starter_url` | The URL of the starter to create the backend from. | The default starter is used. | #### Options @@ -128,7 +128,7 @@ medusa new [ []] ### develop -Start development server. This command watches files for any changes to rebuild the files and restart the server. +Start development backend. This command watches files for any changes to rebuild the files and restart the backend. ```bash medusa develop @@ -143,7 +143,7 @@ medusa develop ### start -Start development server. This command does not watch for file changes or restart the server. +Start development backend. This command does not watch for file changes or restart the backend. ```bash medusa start @@ -220,5 +220,5 @@ medusa telemetry ## See Also -- [Configure your Medusa server](../usage/configurations.md) -- [Set up your development environment](../tutorial/0-set-up-your-development-environment.mdx) +- [Configure Medusa](../development/backend/configurations.md) +- [Set up your development environment](../development/backend/prepare-environment.mdx) diff --git a/docs/content/contribution-guidelines.md b/docs/content/contribution-guidelines.md index 30d3fda39188d..3a2412be83442 100644 --- a/docs/content/contribution-guidelines.md +++ b/docs/content/contribution-guidelines.md @@ -77,7 +77,7 @@ In the body of the PR, explain clearly what the PR does. If the PR solves an iss ## Sidebar -When you add a new page to the documentation, you must add the new page in `www/docs/sidebars.js` under the `docsSidebar`. You can learn more about the syntax used [here](https://docusaurus.io/docs/sidebar/items). +When you add a new page to the documentation, you must add the new page in `www/docs/sidebars.js`. You can learn more about the syntax used [here](https://docusaurus.io/docs/sidebar/items). ### Terminology @@ -140,7 +140,7 @@ medusa.admin.uploads.create(file) // file is an instance of File ```bash -curl -L -X POST '/admin/uploads' \ +curl -L -X POST '/admin/uploads' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: text/csv' \ -F 'files=@""' diff --git a/docs/content/usage/create-medusa-app.mdx b/docs/content/create-medusa-app.mdx similarity index 72% rename from docs/content/usage/create-medusa-app.mdx rename to docs/content/create-medusa-app.mdx index b4a34714dcbae..716d0df120f54 100644 --- a/docs/content/usage/create-medusa-app.mdx +++ b/docs/content/create-medusa-app.mdx @@ -1,5 +1,5 @@ --- -description: 'Learn how to create a composable commerce platform using Medusa. This quickstart guide will help you set up your Medusa server, admin, and storefront all at once.' +description: 'Learn how to create a composable commerce platform using Medusa. This quickstart guide will help you set up your Medusa backend, admin, and storefront all at once.' addHowToData: true --- @@ -13,17 +13,17 @@ In this document, you’ll learn how to use `create-medusa-app` to create a Medu ## Overview -Medusa is composed of three different components: the headless server, the storefront, and the admin dashboard. +Medusa is composed of three different components: the headless backend, the storefront, and the admin dashboard. Medusa provides the necessary tools and resources to set up the three components separately. This ensures that developers have full freedom to choose their tech stack, as they can choose any framework for the storefront and admin dashboard. However, if you’re interested in using Medusa’s starters for the three components, you can make use of the `create-medusa-app` command instead of creating each separately. -When you run the `create-medusa-app` command, you’ll install a Medusa server, a Medusa admin, and optionally a storefront at the same time. +When you run the `create-medusa-app` command, you’ll install a Medusa backend, a Medusa admin, and optionally a storefront at the same time. :::note -If you instead want to quickly install and setup only a Medusa server, follow [this quickstart guide](../quickstart/quick-start.mdx). +If you instead want to quickly install and setup only a Medusa backend, follow [this quickstart guide](./development/backend/install.mdx). ::: @@ -43,13 +43,13 @@ You can install Node from the [official website](https://nodejs.org/en/). ### Git -Git is required for this setup. You can find instructions on how to install it from the [Set up your dev environment documentation](../tutorial/0-set-up-your-development-environment.mdx#git). +Git is required for this setup. You can find instructions on how to install it from the [Set up your dev environment documentation](./development/backend/prepare-environment.mdx#git). --- ## How to Create a Medusa Project -A Medusa project is composed of the server, storefront, and admin. +A Medusa project is composed of the backend, storefront, and admin. In your terminal, run the following command: @@ -74,11 +74,11 @@ In your terminal, run the following command: You’ll then be asked to enter the name of the directory you want the project to be installed in. You can either leave the default value `my-medusa-store` or enter a new name. -### Choose Medusa Server Starter +### Choose Medusa Backend Starter -Next, you’ll be asked to choose the Medusa server starter. The Medusa Server is created from a starter template. By default, it is created from the `medusa-starter-default` template. +Next, you’ll be asked to choose the Medusa backend starter. The Medusa Backend is created from a starter template. By default, it is created from the `medusa-starter-default` template. -You can either pick the default Medusa server starter, the Contentful starter or enter a starter URL by choosing `Other`: +You can either pick the default Medusa backend starter, the Contentful starter or enter a starter URL by choosing `Other`: ```bash noReport ? Which Medusa starter would you like to install? … @@ -87,7 +87,7 @@ You can either pick the default Medusa server starter, the Contentful starter or Other ``` -The server will be installed under the `backend` directory under the project directory. An SQLite database will be created inside that directory as well with demo data seeded into it. +The backend will be installed under the `backend` directory under the project directory. An SQLite database will be created inside that directory as well with demo data seeded into it. ### Choose Storefront Starter @@ -107,7 +107,7 @@ If you choose an option other than `None`, a storefront will be installed under :::tip -Learn more about the [Next.js](../starters/nextjs-medusa-starter.mdx) and [Gatsby](../starters/gatsby-medusa-starter.mdx) starter storefronts. +Learn more about the [Next.js starter storefront](./starters/nextjs-medusa-starter.mdx). ::: @@ -150,7 +150,7 @@ Inside the root project directory which was specified at the beginning of the in ```bash noReport /my-medusa-store /storefront // Medusa storefront starter - /backend // Medusa server + /backend // Medusa backend /admin // Medusa admin ``` @@ -158,6 +158,6 @@ Inside the root project directory which was specified at the beginning of the in ## What’s Next -- [Check out Medusa's features](../introduction.md#features) -- [Learn about server configurations](./configurations.md) -- [Set up your environment for advanced development](../tutorial/0-set-up-your-development-environment.mdx) +- [Check out Medusa's features](./modules/overview.mdx) +- [Learn about backend configurations](./development/backend/configurations.md) +- [Set up your environment for advanced development](./development/backend/prepare-environment.mdx) diff --git a/docs/content/deployments/admin/deploying-on-netlify.md b/docs/content/deployments/admin/deploying-on-netlify.md index 9b2241347037d..63b4855b08b38 100644 --- a/docs/content/deployments/admin/deploying-on-netlify.md +++ b/docs/content/deployments/admin/deploying-on-netlify.md @@ -19,7 +19,7 @@ Alternatively, you can use this button to deploy the Medusa Admin to Netlify dir Before proceeding with this documentation, it is assumed you already have a Medusa Admin installed locally. If not, please go through the [quickstart guide](../../admin/quickstart.mdx) first. -Additionally, this documentation does not cover how to deploy the Medusa server. If you want to deploy the Medusa server, check out one of the [deployment documentation related to the Medusa server](../server/index.mdx). +Additionally, this documentation does not cover how to deploy the Medusa backend. If you want to deploy the Medusa backend, check out one of the [deployment documentation related to the Medusa backend](../server/index.mdx). ### Needed Accounts @@ -34,7 +34,7 @@ If you want to use another Git Provider, it’s possible to follow along with th ### Required Tools -- Git’s CLI tool. You can follow [this documentation to learn how to install it for your operating system](../../tutorial/0-set-up-your-development-environment.mdx#git). +- Git’s CLI tool. You can follow [this documentation to learn how to install it for your operating system](../../development/backend/prepare-environment.mdx#git). --- @@ -118,11 +118,11 @@ Next, click the “Show advanced” button, which is above the “Deploy site” Under the “Advanced build settings” section click on the “New variable” button. This will show two inputs for the key and value of the environment variable. -For the first field enter the key `MEDUSA_BACKEND_URL` and for the value enter the URL of your Medusa server. +For the first field enter the key `MEDUSA_BACKEND_URL` and for the value enter the URL of your Medusa backend. :::caution -If you haven’t deployed your Medusa server yet, you can leave the value blank for now and add it later. However, you will not be able to log in to the Medusa Admin without deploying the Medusa server. +If you haven’t deployed your Medusa backend yet, you can leave the value blank for now and add it later. However, you will not be able to log in to the Medusa Admin without deploying the Medusa backend. ::: @@ -150,7 +150,7 @@ If you click on it, you’ll be redirected to the deployed admin website. :::note -Before you can use Medusa Admin, you must add the URL as an environment variable on your deployed Medusa server. Follow along in the [Configure Cross-Origin Resource Sharing (CORS) on the Medusa Server](#configure-cors-variable-on-the-medusa-server) section. +Before you can use Medusa Admin, you must add the URL as an environment variable on your deployed Medusa backend. Follow along in the [Configure Cross-Origin Resource Sharing (CORS) on the Medusa Backend](#configure-cors-variable-on-the-medusa-backend) section. ::: @@ -243,21 +243,21 @@ For the rest of the steps, you can keep most of the default values provided by N #### Set Environment Variables -After the previous command has finished running, your Netlify website will be created. The next step is to add an environment variable that points to your Medusa server. +After the previous command has finished running, your Netlify website will be created. The next step is to add an environment variable that points to your Medusa backend. :::caution -If you haven’t deployed your Medusa server yet, you can leave the value blank for now and add it later. However, you will not be able to log in to the dashboard or use it without deploying the Medusa server. +If you haven’t deployed your Medusa backend yet, you can leave the value blank for now and add it later. However, you will not be able to log in to the dashboard or use it without deploying the Medusa backend. ::: Run the following command to add the environment variable: ```bash -netlify env:set MEDUSA_BACKEND_URL "" +netlify env:set MEDUSA_BACKEND_URL "" ``` -Where `` is the URL of your Medusa server. +Where `` is the URL of your Medusa backend. :::note @@ -287,13 +287,13 @@ The Medusa Admin will then open in your browser. ![Medusa Admin Login](https://res.cloudinary.com/dza7lstvk/image/upload/v1668001604/Medusa%20Docs/Screenshots/XYqMCo9_hq1fsv.png) -Before you can use Medusa Admin, you must add the URL as an environment variable on your deployed Medusa server. +Before you can use Medusa Admin, you must add the URL as an environment variable on your deployed Medusa backend. --- -## Configure CORS Variable on the Medusa Server +## Configure CORS Variable on the Medusa Backend -To send requests to the Medusa server from the Medusa Admin, you must set the `ADMIN_CORS` environment variable on your server to the Medusa Admin’s URL. +To send requests to the Medusa backend from the Medusa Admin, you must set the `ADMIN_CORS` environment variable on your backend to the Medusa Admin’s URL. :::caution @@ -301,7 +301,7 @@ If you want to set a custom domain to your Medusa Admin website on Netlify, make ::: -On your Medusa server, add the following environment variable: +On your Medusa backend, add the following environment variable: ```bash ADMIN_CORS= @@ -309,11 +309,11 @@ ADMIN_CORS= Where `` is the URL of your Medusa Admin that you just deployed. -Then, restart your Medusa server. Once the server is running again, you can log in to the Medusa Admin and use it. +Then, restart your Medusa backend. Once the backend is running again, you can log in to the Medusa Admin and use it. --- ## See Also -- [Deploy your storefront](../storefront/index.mdx) -- [Configure your Medusa server](../../usage/configurations.md) +- [Deploy storefront](../storefront/index.mdx) +- [Configure Medusa backend](../../development/backend/configurations.md) diff --git a/docs/content/deployments/admin/index.mdx b/docs/content/deployments/admin/index.mdx index 23fccb107ee96..b5b820253689f 100644 --- a/docs/content/deployments/admin/index.mdx +++ b/docs/content/deployments/admin/index.mdx @@ -1,6 +1,6 @@ --- hide_table_of_contents: true -description: 'Learn how to deploy the Medusa Admin to different hosting providers to be used with a deployed Medusa server.' +description: 'Learn how to deploy the Medusa Admin to different hosting providers to be used with a deployed Medusa backend.' --- import DocCardList from '@theme/DocCardList'; diff --git a/docs/content/deployments/server/deploying-on-digital-ocean.md b/docs/content/deployments/server/deploying-on-digital-ocean.md index 438609b194c37..d891cde8aaf76 100644 --- a/docs/content/deployments/server/deploying-on-digital-ocean.md +++ b/docs/content/deployments/server/deploying-on-digital-ocean.md @@ -3,24 +3,24 @@ description: 'Learn step-by-step.' addHowToData: true --- -# Deploy Your Medusa Server to DigitalOcean Apps +# Deploy Your Medusa Backend to DigitalOcean Apps -In this document, you'll learn how to deploy your Medusa server to a DigitalOcean App. +In this document, you'll learn how to deploy your Medusa backend to a DigitalOcean App. -DigitalOcean is a reliable hosting provider that provides different ways to host websites and servers. One way to host a server is using their DigitalOcean App Platform. +DigitalOcean is a reliable hosting provider that provides different ways to host websites and servers. One way to host a backend is using their DigitalOcean App Platform. ## Prerequisites -### Medusa Server +### Medusa Backend -It is assumed that you already have a Medusa server installed locally. If you don’t, please follow the [quickstart guide](../../quickstart/quick-start.mdx). +It is assumed that you already have a Medusa backend installed locally. If you don’t, please follow the [quickstart guide](../../development/backend/install.mdx). -Furthermore, your Medusa server should be configured to work with PostgreSQL and Redis. You can follow the [Configure your Server documentation](../../usage/configurations.md) to learn how to do that. +Furthermore, your Medusa backend should be configured to work with PostgreSQL and Redis. You can follow the [Configure your Backend documentation](../../development/backend/configurations.md) to learn how to do that. ### Needed Accounts - A [DigitalOcean](https://cloud.digitalocean.com/registrations/new) account. You need to provide a payment method on sign up. -- A [GitHub](https://github.com/) account to create a repository to host your server’s codebase. +- A [GitHub](https://github.com/) account to create a repository to host your Medusa backend’s codebase. :::tip @@ -30,7 +30,7 @@ If you want to use another Git Provider supported by DigitalOcean, it’s possib ### Required Tools -- Git’s CLI tool. You can follow [this documentation to learn how to install it for your operating system](../../tutorial/0-set-up-your-development-environment.mdx#git). +- Git’s CLI tool. You can follow [this documentation to learn how to install it for your operating system](../../development/backend/prepare-environment.mdx#git). --- @@ -42,7 +42,7 @@ Change the `start` script in `package.json` to the following: "start": "medusa migrations run && medusa start" ``` -This ensures that Migrations are run everytime the Medusa server is restarted. +This ensures that Migrations are run everytime the Medusa backend is restarted. --- @@ -79,7 +79,7 @@ module.exports = { ## Create GitHub Repository -Before you can deploy your Medusa server you need to create a GitHub repository and push the code base to it. +Before you can deploy your Medusa backend you need to create a GitHub repository and push the code base to it. On GitHub, click the plus icon at the top right, then click New Repository. @@ -97,7 +97,7 @@ After creating the repository, you’ll be redirected to the repository’s page ![GitHub repository's URL](https://res.cloudinary.com/dza7lstvk/image/upload/v1668001818/Medusa%20Docs/Netlify/pHfSTuT_w544lr.png) -Copy the link. Then, open your terminal in the directory that holds your Medusa server codebase and run the following commands: +Copy the link. Then, open your terminal in the directory that holds your Medusa backend codebase and run the following commands: ```bash git init @@ -138,7 +138,7 @@ Additional inputs will show up to choose the Branch, Source Directory, and Autod ![Enter master for Branch input, backslash for Source Directory, and check Autodeploy](https://res.cloudinary.com/dza7lstvk/image/upload/v1668002055/Medusa%20Docs/Digital%20Ocean/kjk9E2B_qpwrx4.png) -If you host your Medusa server in a monorepo, you should change the Source Directory to the directory the server is available in the repository. Otherwise, it can be left as is. +If you host your Medusa backend in a monorepo, you should change the Source Directory to the directory the backend is available in the repository. Otherwise, it can be left as is. Once you’re done, click Next to move on to the next step. @@ -148,7 +148,7 @@ In the next step, you’ll see the resources to create. ![List of resources showing a docker resource and web service resource](https://res.cloudinary.com/dza7lstvk/image/upload/v1668002067/Medusa%20Docs/Digital%20Ocean/6TlpWB9_wfppc7.png) -If you have a Dockerfile available in the server’s codebase (which is available by default), you’ll have two resources showing. You can remove it by clicking on the trash icon at the right of the resource. +If you have a Dockerfile available in the backend’s codebase (which is available by default), you’ll have two resources showing. You can remove it by clicking on the trash icon at the right of the resource. By default, DigitalOcean hosts the web service in a sub-path of the domain name of the created App. To change it to the root of the domain, click on the edit icon at the right of the Web Service resource. @@ -176,7 +176,7 @@ Once you’re done, click Next to move on to the next step. ### Set Environment Variables -In this section, you’ll add environment variables that are essential to your Medusa server. +In this section, you’ll add environment variables that are essential to your Medusa backend. You should see two ways to add environment variables: Global or specific to the Web Service. @@ -221,7 +221,7 @@ In the final step, you can see a review of everything you created. If everything ### Create Redis Resource -While the server is being deployed, you can create the Redis resource. +While the backend is being deployed, you can create the Redis resource. Click the Create button at the top right and choose Database from the dropdown. @@ -253,7 +253,7 @@ Once you’re done click Attach Database. This will add the Redis database to th --- -## Test your Server +## Test your Backend Once the redeployment is complete, copy the URL of the App which can be found under the App’s name. @@ -265,9 +265,9 @@ Then, go to `/store/products`. If the deployment was successful, y --- -## Run Commands on Your Server +## Run Commands on Your Backend -To run commands on your server, you can access the console on the App’s page by choosing the Console tab. This opens a console in your browser where you can run commands on your server. +To run commands on your backend, you can access the console on the App’s page by choosing the Console tab. This opens a console in your browser where you can run commands on your backend. For example, you can run the following commands to create a new admin user: diff --git a/docs/content/deployments/server/deploying-on-heroku.mdx b/docs/content/deployments/server/deploying-on-heroku.mdx index 6869074a6c396..79428cdcc0671 100644 --- a/docs/content/deployments/server/deploying-on-heroku.mdx +++ b/docs/content/deployments/server/deploying-on-heroku.mdx @@ -7,14 +7,14 @@ import styles from '../deployment.module.css'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Deploy Your Medusa Server on Heroku +# Deploy Your Medusa Backend on Heroku -In this document, you'll learn how to deploy your Medusa server on Heroku. Heroku is a PaaS (Platform as a Service) that allows you to easily deploy your applications in the cloud. +In this document, you'll learn how to deploy your Medusa backend on Heroku. Heroku is a PaaS (Platform as a Service) that allows you to easily deploy your applications in the cloud. -Alternatively, you can use this button to deploy the Medusa server to Heroku directly: +Alternatively, you can use this button to deploy the Medusa backend to Heroku directly: - - Deploy to Heroku + + Deploy to Heroku
@@ -25,11 +25,11 @@ Alternatively, you can use this button to deploy the Medusa server to Heroku dir ## Prerequisites -### Medusa Server +### Medusa Backend -It is assumed that you already have a Medusa server installed locally. If you don’t, please follow the [quickstart guide](../../quickstart/quick-start.mdx). +It is assumed that you already have a Medusa backend installed locally. If you don’t, please follow the [quickstart guide](../../development/backend/install.mdx). -Furthermore, your Medusa server should be configured to work with PostgreSQL and Redis. You can follow the [Configure your Server documentation](../../usage/configurations.md) to learn how to do that. +Furthermore, your Medusa backend should be configured to work with PostgreSQL and Redis. You can follow the [Configure your Backend documentation](../../development/backend/configurations.md) to learn how to do that. ### Needed Accounts @@ -37,7 +37,7 @@ Furthermore, your Medusa server should be configured to work with PostgreSQL and ### Required Tools -- Git’s CLI tool. You can follow [this documentation to learn how to install it for your operating system](../../tutorial/0-set-up-your-development-environment.mdx#git). +- Git’s CLI tool. You can follow [this documentation to learn how to install it for your operating system](../../development/backend/prepare-environment.mdx#git). - Heroku's CLI tool. You can follow [Heroku's documentation to learn how to install it for your operating system](https://devcenter.heroku.com/articles/heroku-cli). --- @@ -56,7 +56,7 @@ Depending on your operating system, you must follow either the instructions in y ### 2. Create an App with Heroku -In the root directory of your Medusa server, run the following commands to create an app on Heroku and add it as a remote origin: +In the root directory of your Medusa backend, run the following commands to create an app on Heroku and add it as a remote origin: ```bash heroku create @@ -97,9 +97,9 @@ This uses the lowest plan in Stackhero Redis. You can check out [the plans and p ### 4. Configure Environment Variables on Heroku -Medusa requires a set of environment variables to be configured. You can learn more about Medusa's configurations in the [Configure your Medusa Server](../../usage/configurations.md) document. +Medusa requires a set of environment variables to be configured. You can learn more about Medusa's configurations in the [Configure your Medusa backend](../../development/backend/configurations.md) document. -Run the following commands in the root directory of your Medusa server to set some environment variables: +Run the following commands in the root directory of your Medusa backend to set some environment variables: ```bash heroku config:set NODE_ENV=production @@ -150,7 +150,7 @@ However, if you use another add-on, make sure to set the environment variable `D #### (Optional) Configure CORS Variables -Optionally, if you've deployed the admin dashboard and you want to ensure it can use the server's REST APIs, you must set the following environment variable: +Optionally, if you've deployed the admin dashboard and you want to ensure it can use the backend's REST APIs, you must set the following environment variable: ```bash heroku config:set ADMIN_CORS= @@ -158,7 +158,7 @@ heroku config:set ADMIN_CORS= Where `` is the URL of your admin dashboard. -Similarly, if you've deployed the storefront and you want to ensure it can use the server's REST APIs, you must set the following environment variable: +Similarly, if you've deployed the storefront and you want to ensure it can use the backend's REST APIs, you must set the following environment variable: ```bash heroku config:set STORE_CORS= @@ -166,9 +166,9 @@ heroku config:set STORE_CORS= Where `` is the URL of your storefront. -### 5. Configure Medusa Server +### 5. Configure Medusa Backend -Before jumping into the deployment, you need to configure your Medusa server to ensure it uses the previous environment variables and the recommended production configurations. +Before jumping into the deployment, you need to configure your Medusa backend to ensure it uses the previous environment variables and the recommended production configurations. #### medusa-config.js @@ -205,21 +205,21 @@ Update `scripts` to include the following scripts: }, ``` -### 6. Launch your Medusa Server +### 6. Launch your Medusa Backend Finally, commit and push all changes to Heroku: ```bash git add . -git commit -m "Deploy Medusa Server on Heroku" +git commit -m "Deploy Medusa Backend on Heroku" git push heroku HEAD:master ``` -This triggers a redeploy of the Medusa server with all the new configurations. +This triggers a redeploy of the Medusa backend with all the new configurations. -## Test your Server +## Test your Backend -To test your server, run the following command to retrieve the server's URL: +To test your backend, run the following command to retrieve the backend's URL: ```bash heroku apps:info -a @@ -227,13 +227,13 @@ heroku apps:info -a Where `` is the name of the app. You should see as the output a bunch of info of the app. -The server's URL is available under "Web URL". You can copy it and perform requests to it to test it out. +The backend's URL is available under "Web URL". You can copy it and perform requests to it to test it out. -For example, you can send a request to `/store/products` and you should receive a JSON response with the products in your store. +For example, you can send a request to `/store/products` and you should receive a JSON response with the products in your store. ### Troubleshooting: Inspect Build Logs -If an error occurs during the deployment, you can explore your Heroku app build logs using the following command in the root directory of your Medusa server: +If an error occurs during the deployment, you can explore your Heroku app build logs using the following command in the root directory of your Medusa backend: ```bash heroku logs -n 500000 --remote heroku --tail -a @@ -243,9 +243,9 @@ Where `` is the name of the app. --- -## Run Commands on Your Server +## Run Commands on Your Backend -To run commands on your server, you can use the following command: +To run commands on your backend, you can use the following command: ```bash heroku run -a -- diff --git a/docs/content/deployments/server/deploying-on-qovery.md b/docs/content/deployments/server/deploying-on-qovery.md index ac046b8fdd746..3e63f4320ec3d 100644 --- a/docs/content/deployments/server/deploying-on-qovery.md +++ b/docs/content/deployments/server/deploying-on-qovery.md @@ -3,9 +3,9 @@ description: 'Learn step-by-step.' addHowToData: true --- -# Deploy Your Medusa Server on Qovery +# Deploy Your Medusa Backend on Qovery -In this document, you'll learn how to deploy your Medusa server on Qovery with the help of Terraform. +In this document, you'll learn how to deploy your Medusa backend on Qovery with the help of Terraform. [Qovery](https://www.qovery.com/) is a Continuous Deployment Platform that provides you with the developer experience of Heroku on top of your cloud provider (For example, AWS, DigitalOcean). @@ -19,17 +19,17 @@ This tutorial explains how to deploy Medusa to a Qovery organization with an AWS ## Prerequisites -### Medusa Server +### Medusa Backend -It is assumed that you already have a Medusa server installed locally. If you don’t, please follow the [quickstart guide](../../quickstart/quick-start.mdx). +It is assumed that you already have a Medusa backend installed locally. If you don’t, please follow the [quickstart guide](../../development/backend/install.mdx). -Furthermore, your Medusa server should be configured to work with PostgreSQL and Redis. You can follow the [Configure your Server documentation](../../usage/configurations.md) to learn how to do that. +Furthermore, your Medusa backend should be configured to work with PostgreSQL and Redis. You can follow the [Configure your Backend documentation](../../development/backend/configurations.md) to learn how to do that. ### Needed Accounts - A [Qovery](https://start.qovery.com/) account with a created organization. Qovery provides a free plan that you can use. - An [AWS](https://aws.amazon.com/) account that you’ll connect to a Qovery cluster. -- A [GitHub](https://github.com/) account to create a repository to host your server’s codebase. +- A [GitHub](https://github.com/) account to create a repository to host your backend's codebase. :::tip @@ -39,7 +39,7 @@ If you want to use another [Git Provider supported by Qovery](https://hub.qovery ### Required Tools -- Git’s CLI tool. You can follow [this documentation to learn how to install it for your operating system](../../tutorial/0-set-up-your-development-environment.mdx#git). +- Git’s CLI tool. You can follow [this documentation to learn how to install it for your operating system](../../development/backend/prepare-environment.mdx#git). - Terraform’s CLI tool. You can follow [this guide to install it based on your operating system](https://www.terraform.io/downloads). - Qovery’s CLI tool. You can follow [this guide to install it based on your operating system](https://hub.qovery.com/docs/using-qovery/interface/cli/#install). @@ -47,7 +47,7 @@ If you want to use another [Git Provider supported by Qovery](https://hub.qovery ## Create GitHub Repository -Before you can deploy your Medusa server you need to create a GitHub repository and push the code base to it. +Before you can deploy your Medusa backend you need to create a GitHub repository and push the code base to it. On GitHub, click the plus icon at the top right, then click New Repository. @@ -65,7 +65,7 @@ After creating the repository, you’ll be redirected to the repository’s page ![An image of the GitHub URL in a new repository](https://res.cloudinary.com/dza7lstvk/image/upload/v1668001818/Medusa%20Docs/Netlify/pHfSTuT_w544lr.png) -Copy the link. Then, open your terminal in the directory that holds your Medusa server codebase and run the following commands: +Copy the link. Then, open your terminal in the directory that holds your Medusa backend codebase and run the following commands: ```bash git init @@ -88,7 +88,7 @@ After pushing the changes, you can find the files in your GitHub repository. ## Deploy to Qovery -In this section, you’ll learn how to deploy your Medusa server to Qovery with the help of Terraform. +In this section, you’ll learn how to deploy your Medusa backend to Qovery with the help of Terraform. ### Sign in Using Qovery CLI @@ -116,7 +116,7 @@ You’ll be prompted to choose an organization and add a name and description fo You need to add some variables to use for your Medusa deployment to Qovery. -In the root directory of your Medusa server, create the file `variables.tf` with the following content: +In the root directory of your Medusa backend, create the file `variables.tf` with the following content: ``` variable "qovery_organization_id" { @@ -245,19 +245,19 @@ git_root_path = "/" Here’s an explanation of each of the variables and how to retrieve their variables: -- `qovery_organization_id`: The ID of the Qovery organization to deploy the server to. It can be found by logging into your [Qovery Console](https://console.qovery.com/). You’ll be redirected to the organization’s main page with a URL of the format `https://console.qovery.com/platform/organization//projects`. Copy the `` in the URL to use as the value of this field. +- `qovery_organization_id`: The ID of the Qovery organization to deploy the backend to. It can be found by logging into your [Qovery Console](https://console.qovery.com/). You’ll be redirected to the organization’s main page with a URL of the format `https://console.qovery.com/platform/organization//projects`. Copy the `` in the URL to use as the value of this field. - `qovery_create_cluster`: A boolean value indicating whether a new cluster should be created or not. If you already have a cluster that you want to use, you can set the value to `false` and set the value of `qovery_cluster_id`. Otherwise, set the value to `true` and set the values of `aws_access_key_id`, `aws_secret_access_key`, and `aws_region`. - `qovery_cluster_id`: The ID of the existing cluster to use (if `qovery_create_cluster` is set to `false`). You can use [Qovery’s REST API](https://api-doc.qovery.com/#tag/Clusters/operation/listOrganizationCluster) to retrieve the cluster ID. You can use the token you generated earlier for the Bearer authorization token as explained [here](https://hub.qovery.com/docs/using-qovery/interface/cli/#generate-api-token). - `aws_access_key_id`, `aws_secret_access_key`, and `aws_region`: The credentials used to create the cluster (if `qovery_create_cluster` is set to `true`). You can refer to [this guide](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) to learn how to retrieve the `aws_access_key_id` and `aws_secret_access_key`. -- `medusa_jwt_secret`: The value of the JSON Web Token (JWT) Secret on your Medusa server. It’s recommended to use a strong randomly generated string. -- `medusa_cookie_secret`: The value of the Cookie Secret on your Medusa server. It’s recommended to use a strong randomly generated string. +- `medusa_jwt_secret`: The value of the JSON Web Token (JWT) Secret on your Medusa backend. It’s recommended to use a strong randomly generated string. +- `medusa_cookie_secret`: The value of the Cookie Secret on your Medusa backend. It’s recommended to use a strong randomly generated string. - `git_url`: The URL of the Git repository you created earlier. Make sure it ends with `.git`. - `git_branch`: The branch to use in the GitHub repo. By default it’s `master`. -- `git_root_path`: The root path of the Medusa server. By default, it’s `/`. If you are hosting your Medusa server in a monorepo in a nested directory, you need to change the value of this variable. +- `git_root_path`: The root path of the Medusa backend. By default, it’s `/`. If you are hosting your Medusa backend in a monorepo in a nested directory, you need to change the value of this variable. ### Add Terraform Configuration File -In the root directory of your Medusa server, create the file `main.tf` with the following content: +In the root directory of your Medusa backend, create the file `main.tf` with the following content: ```bash # Install the Qovery Terraform provider @@ -430,25 +430,25 @@ Finally, it creates the Medusa app and sets all the necessary environment variab :::tip -This deployment uses Docker. By default, you should have the files [`Dockerfile`](https://github.com/medusajs/medusa-starter-default/blob/master/Dockerfile) and [`docker-compose.yml`](https://github.com/medusajs/medusa-starter-default/blob/master/docker-compose.yml)` in the root of your Medusa server. +This deployment uses Docker. By default, you should have the files [`Dockerfile`](https://github.com/medusajs/medusa-starter-default/blob/master/Dockerfile) and [`docker-compose.yml`](https://github.com/medusajs/medusa-starter-default/blob/master/docker-compose.yml)` in the root of your Medusa backend. ::: ### Change develop.sh -The `Dockerfile` runs the file `develop.sh` to start the server. Change the content of `develop.sh` to the following: +The `Dockerfile` runs the file `develop.sh` to start the backend. Change the content of `develop.sh` to the following: ```bash #!/bin/bash -#Run migrations to ensure the database is updated +# Run migrations to ensure the database is updated medusa migrations run -#Start production server +# Run backend medusa start ``` -This makes sure the production server is started and not a development server. +This makes sure the production backend is started and not a development backend. ### Initialize Terraform @@ -480,19 +480,19 @@ If you run into any errors while running this command, you can just re-run it af --- -## Test your Server +## Test the Backend -Once the command finishes and the deployment is successful, you can access your server in the [Qovery Console](https://console.qovery.com/). Go to the project, environment, then the app that you created using Terraform and Qovery. In the app, click the Open button at the top right to open your website in a new tab. +Once the command finishes and the deployment is successful, you can access your backend in the [Qovery Console](https://console.qovery.com/). Go to the project, environment, then the app that you created using Terraform and Qovery. In the app, click the Open button at the top right to open your website in a new tab. ![open button at the top right](https://res.cloudinary.com/dza7lstvk/image/upload/v1668002245/Medusa%20Docs/Qovery/Ji59ZSJ_nrkpvb.png) -You can access any of the endpoints on your server using the server URL. For example, you can get the list of products using the endpoint `/store/products`. +You can access any of the endpoints on your backend using the backend URL. For example, you can get the list of products using the endpoint `/store/products`. --- -## Run Commands on Your Server +## Run Commands on the Backend -To run commands on your server, run the following command: +To run commands on the backend, run the following command: ```bash qovery shell @@ -500,7 +500,7 @@ qovery shell You’ll be asked to either confirm the existing context or choose a new context. -After choosing your Medusa app in the context, you should be able to execute any command in the directory of your Medusa server. For example, you can run the [`user` command using Medusa’s CLI tool to create a new user](../../cli/reference.md#user): +After choosing your Medusa app in the context, you should be able to execute any command in the directory of your Medusa backend. For example, you can run the [`user` command using Medusa’s CLI tool to create a new user](../../cli/reference.md#user): ```bash npm install @medusajs/medusa-cli -g diff --git a/docs/content/deployments/server/deploying-on-railway.md b/docs/content/deployments/server/deploying-on-railway.md index 96b1146bf2cda..136c061e8f56a 100644 --- a/docs/content/deployments/server/deploying-on-railway.md +++ b/docs/content/deployments/server/deploying-on-railway.md @@ -3,48 +3,48 @@ description: 'Learn step-by-step.' addHowToData: true --- -# Deploy Your Medusa Server to Railway +# Deploy Your Medusa Backend to Railway -In this document, you’ll learn how to deploy your Medusa server to Railway. +In this document, you’ll learn how to deploy your Medusa backend to Railway. ## What is Railway [Railway](https://railway.app/) is a hosting provider that you can use to deploy web applications and databases without having to worry about managing the full infrastructure. -Railway provides a free plan that allows you to deploy your Medusa server along with PostgreSQL and Redis databases. This is useful mainly for development and demo purposes. +Railway provides a free plan that allows you to deploy your Medusa backend along with PostgreSQL and Redis databases. This is useful mainly for development and demo purposes. --- ## Prerequisites -### Medusa Server +### Medusa Backend -It is assumed that you already have a Medusa server installed locally. If you don’t, please follow the [quickstart guide](../../quickstart/quick-start.mdx). +It is assumed that you already have a Medusa backend installed locally. If you don’t, please follow the [quickstart guide](../../development/backend/install.mdx). -Furthermore, your Medusa server should be configured to work with PostgreSQL and Redis. You can follow the [Configure your Server documentation](./../../usage/configurations.md) to learn how to do that. +Furthermore, your Medusa backend should be configured to work with PostgreSQL and Redis. You can follow the [Configure your Backend documentation](./../../development/backend/configurations.md) to learn how to do that. ### Needed Accounts - A [Railway](https://railway.app/) account. -- A [GitHub](https://github.com/) account to create a repository to host your server’s codebase. +- A [GitHub](https://github.com/) account to create a repository to host your backend's codebase. ### Required Tools -- Git’s CLI tool. You can follow [this documentation to learn how to install it for your operating system](./../../tutorial/0-set-up-your-development-environment.mdx#git). +- Git’s CLI tool. You can follow [this documentation to learn how to install it for your operating system](./../../development/backend/prepare-environment.mdx#git). --- -## Changes to Medusa Server Codebase +## Changes to Medusa Backend Codebase -By default, Railway looks for a Dockerfile in the root of the codebase. If there is one, it will try to deploy your server using it. +By default, Railway looks for a Dockerfile in the root of the codebase. If there is one, it will try to deploy your backend using it. -As this guide doesn't use Docker, make sure to delete `Dockerfile` from the root of your Medusa server. +As this guide doesn't use Docker, make sure to delete `Dockerfile` from the root of your Medusa backend. --- ## Create GitHub Repository -Before you can deploy your Medusa server you need to create a GitHub repository and push the code base to it. +Before you can deploy your Medusa backend you need to create a GitHub repository and push the code base to it. On GitHub, click the plus icon at the top right, then click New Repository. @@ -62,7 +62,7 @@ After creating the repository, you’ll be redirected to the repository’s page ![GitHub repository's URL](https://res.cloudinary.com/dza7lstvk/image/upload/v1668001818/Medusa%20Docs/Netlify/pHfSTuT_w544lr.png) -Copy the link. Then, open your terminal in the directory that holds your Medusa server codebase and run the following commands: +Copy the link. Then, open your terminal in the directory that holds your Medusa backend codebase and run the following commands: ```bash git init @@ -85,7 +85,7 @@ After pushing the changes, you can find the files in your GitHub repository. ## Deploy to Railway -In this section, you’ll create the PostgreSQL and Redis databases first, then deploy the server from the GitHub repository. +In this section, you’ll create the PostgreSQL and Redis databases first, then deploy the backend from the GitHub repository. ### Create the PostgreSQL Database @@ -118,7 +118,7 @@ To find the Redis database URL which you’ll need later: 2. Choose the Connect tab. 3. Copy the Redis Connection URL. -### Deploy the Medusa Server Repository +### Deploy the Medusa Backend Repository In the same project view: @@ -133,11 +133,11 @@ If the GitHub repositories in the dropdown are stuck on loading and aren't showi ::: -It will take the server a few minutes to deploy successfully. +It will take the backend a few minutes to deploy successfully. ### Configure Environment Variables -To configure the environment variables of your Medusa server: +To configure the environment variables of your Medusa backend: 1. Click on the GitHub repository’s card. 2. Choose the Variables tab. @@ -161,9 +161,9 @@ It’s highly recommended to use strong, randomly generated secrets for `JWT_SE ### Change Start Command -The start command is the command used to run the server. You’ll change it to run any available migrations, then run the Medusa server. This way if you create your own migrations or update the Medusa server, it's guaranteed that these migrations are run first before the server starts. +The start command is the command used to run the backend. You’ll change it to run any available migrations, then run the Medusa backend. This way if you create your own migrations or update the Medusa backend, it's guaranteed that these migrations are run first before the backend starts. -To change the start command of your Medusa server: +To change the start command of your Medusa backend: 1. Click on the GitHub repository’s card. 2. Click on the Settings tab and scroll down to the Service section. @@ -175,7 +175,7 @@ medusa migrations run && medusa develop ### Add Domain Name -The last step is to add a domain name to your Medusa server. To do that: +The last step is to add a domain name to your Medusa backend. To do that: 1. Click on the GitHub repository’s card. 2. Click on the Settings tab and scroll down to the Domains section. @@ -183,11 +183,11 @@ The last step is to add a domain name to your Medusa server. To do that: --- -## Test your Server +## Test the Backend -Every change you make to the settings redeploys the server. You can check the Deployments of the server by clicking on the GitHub repository’s card and choosing the Deployments tab. +Every change you make to the settings redeploys the backend. You can check the Deployments of the backend by clicking on the GitHub repository’s card and choosing the Deployments tab. -After the server is redeployed successfully, open the app in your browser using the domain name. For example, you can open the URL `/store/products` which will return the products available on your server. +After the backend is redeployed successfully, open the app in your browser using the domain name. For example, you can open the URL `/store/products` which will return the products available on your backend. :::tip @@ -199,7 +199,7 @@ If you generated a random domain, you can find it by clicking on the GitHub repo ## Troubleshooting -If you run into any issues or a problem with your deployed server, you can check the logs in your Railway container instance by: +If you run into any issues or a problem with your deployed backend, you can check the logs in your Railway container instance by: 1. Click on the GitHub repository’s card. 2. Click on the Deployments tab. @@ -207,11 +207,11 @@ If you run into any issues or a problem with your deployed server, you can check --- -## Run Commands on Server +## Run Commands on the Backend -To run commands on your server, you can use [Railway’s CLI tool to run a local shell and execute commands](https://docs.railway.app/develop/cli#local-shell). +To run commands on your backend, you can use [Railway’s CLI tool to run a local shell and execute commands](https://docs.railway.app/develop/cli#local-shell). -For example, you can run commands on the server to seed the database or create a new user using [Medusa’s CLI tool](../../cli/reference.md). +For example, you can run commands on the backend to seed the database or create a new user using [Medusa’s CLI tool](../../cli/reference.md). --- diff --git a/docs/content/deployments/server/index.mdx b/docs/content/deployments/server/index.mdx index c7f653ffa0d0d..931e45786c664 100644 --- a/docs/content/deployments/server/index.mdx +++ b/docs/content/deployments/server/index.mdx @@ -1,13 +1,13 @@ --- hide_table_of_contents: true -description: 'Learn how to deploy your Medusa server to different hosting providers including DigitalOcean, Heroku, Railway, and more.' +description: 'Learn how to deploy your Medusa backend to different hosting providers including DigitalOcean, Heroku, Railway, and more.' --- import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; -# Medusa Server Deployment Guides +# Medusa Backend Deployment Guides -Find in this page guides to deploy your Medusa server on different platforms. +Find in this page guides to deploy your Medusa backend on different platforms. \ No newline at end of file diff --git a/docs/content/deployments/storefront/deploying-gatsby-on-netlify.md b/docs/content/deployments/storefront/deploying-gatsby-on-netlify.md index 6480cd02bd54f..87e8a09fd238c 100644 --- a/docs/content/deployments/storefront/deploying-gatsby-on-netlify.md +++ b/docs/content/deployments/storefront/deploying-gatsby-on-netlify.md @@ -5,11 +5,17 @@ addHowToData: true # Deploy Gatsby Storefront on Netlify +:::note + +The Gatsby storefront has been deprecated and it's not recommended to use it moving forward. You can use the [Next.js storefront](../../starters/nextjs-medusa-starter.mdx) instead or build your own. + +::: + In this document, you’ll learn how to deploy the Gatsby Storefront on [Netlify](https://www.netlify.com/). Alternatively, you can use this button to deploy the Gatsby Storefront to Netlify directly: - + Deploy to Netlify @@ -19,9 +25,9 @@ Alternatively, you can use this button to deploy the Gatsby Storefront to Netlif ### Medusa Components -Before proceeding with this documentation, it is assumed you already have the Gatsby storefront installed locally. If not, please go through the [quickstart guide](../../starters/gatsby-medusa-starter.mdx) first. +Before proceeding with this documentation, it is assumed you already have the Gatsby storefront installed locally. -Additionally, this documentation does not cover how to deploy the Medusa server. If you want to deploy the Medusa server, [check out one of the deployment documentation related to the Medusa server](../server/index.mdx). +Additionally, this documentation does not cover how to deploy the Medusa backend. If you want to deploy the Medusa backend, [check out one of the deployment documentation related to the Medusa backend](../server/index.mdx). ### Needed Accounts @@ -36,7 +42,7 @@ If you want to use another Git Provider, it’s possible to follow along with th ### Required Tools -- Git’s CLI tool. You can follow [this documentation to learn how to install it for your operating system](../../tutorial/0-set-up-your-development-environment.mdx#git). +- Git’s CLI tool. You can follow [this documentation to learn how to install it for your operating system](../../development/backend/prepare-environment.mdx#git). --- @@ -113,11 +119,11 @@ In the form that shows, keep all fields the same and click on the “Show advanc Under the “Advanced build settings” section click on the “New variable” button. This will show two inputs for the key and value of the environment variable. -For the first field enter the key `GATSBY_MEDUSA_BACKEND_URL` and for the value enter the URL of your Medusa server. +For the first field enter the key `GATSBY_MEDUSA_BACKEND_URL` and for the value enter the URL of your Medusa backend. :::caution -If you haven’t deployed your Medusa server yet, you can leave the value blank for now and add it later. However, the build process for the Gatsby storefront will fail. +If you haven’t deployed your Medusa backend yet, you can leave the value blank for now and add it later. However, the build process for the Gatsby storefront will fail. ::: @@ -141,9 +147,9 @@ Once the deployment is done, you’ll find the URL in the place of the “Site d :::tip -If you haven’t added any products to your Medusa server, the build process might fail. It’s recommended to add some products to the server first in that case. +If you haven’t added any products to your Medusa backend, the build process might fail. It’s recommended to add some products to the backend first in that case. -Alternatively, you can seed the server with demo data by running this command in the root directory of the server: +Alternatively, you can seed the backend with demo data by running this command in the root directory of the backend: ```bash noReport medusa seed -f data/seed.json @@ -159,7 +165,7 @@ If you click on it, you’ll be redirected to the deployed storefront website. :::caution -At this point, you will face errors related to Cross-Origin Resource Sharing (CORS) while using the storefront. Before you start using the storefront, follow along the [Configure CORS on the Medusa Server section](#configure-cors-variable-on-the-medusa-server). +At this point, you will face errors related to Cross-Origin Resource Sharing (CORS) while using the storefront. Before you start using the storefront, follow along the [Configure CORS on the Medusa Backend section](#configure-cors-variable-on-the-medusa-backend). ::: @@ -240,21 +246,21 @@ For the rest of the steps, you can keep the default values provided by Netlify a #### Set Environment Variables -After the previous command has finished running, your Netlify website will be created. The next step is to add an environment variable that points to your Medusa server. +After the previous command has finished running, your Netlify website will be created. The next step is to add an environment variable that points to your Medusa backend. :::caution -If you haven’t deployed your Medusa server yet, you can leave the value blank for now and add it later. However, the build process for the Gatsby storefront will fail. +If you haven’t deployed your Medusa backend yet, you can leave the value blank for now and add it later. However, the build process for the Gatsby storefront will fail. ::: Run the following command to add the environment variable: ```bash -netlify env:set GATSBY_MEDUSA_BACKEND_URL "" +netlify env:set GATSBY_MEDUSA_BACKEND_URL "" ``` -Where `` is the URL of your Medusa server. +Where `` is the URL of your Medusa backend. :::note @@ -274,9 +280,9 @@ After the deployment has been completed, you should see a message saying “Depl :::tip -If you haven’t added any products to your Medusa server, the build process might fail. It’s recommended to add some products to the server first in that case. +If you haven’t added any products to your Medusa backend, the build process might fail. It’s recommended to add some products to the backend first in that case. -Alternatively, you can seed the server with demo data by running this command in the root directory of the server: +Alternatively, you can seed the backend with demo data by running this command in the root directory of the backend: ```bash noReport medusa seed -f data/seed.json @@ -296,13 +302,13 @@ The Gatsby storefront will then open in your browser. ![Gatsby Storefront](https://res.cloudinary.com/dza7lstvk/image/upload/v1668003089/Medusa%20Docs/Netlify/l08cBSA_yfj2rz.png) -Before you can use the Gatsby storefront, you must add the URL as an environment variable on your deployed Medusa server. +Before you can use the Gatsby storefront, you must add the URL as an environment variable on your deployed Medusa backend. --- -## Configure CORS Variable on the Medusa Server +## Configure CORS Variable on the Medusa Backend -To send requests to the Medusa server from the Gatsby storefront, you must set the `STORE_CORS` environment variable on your server to the Gatsby storefront’s URL. +To send requests to the Medusa backend from the Gatsby storefront, you must set the `STORE_CORS` environment variable on your backend to the Gatsby storefront’s URL. :::caution @@ -310,7 +316,7 @@ If you want to set a custom domain to your Gatsby storefront website on Netlify, ::: -On your Medusa server, add the following environment variable: +On your Medusa backend, add the following environment variable: ```bash STORE_CORS= @@ -318,11 +324,11 @@ STORE_CORS= Where `` is the URL of your Gatsby storefront that you just deployed. -Then, restart your Medusa server. Once the server is running again, you can use your Gatsby storefront. +Then, restart your Medusa backend. Once the backend is running again, you can use your Gatsby storefront. --- ## See Also - [Deploy the Medusa Admin](../admin/index.mdx) -- [Configure your Medusa server](../../usage/configurations.md) +- [Configure your Medusa backend](../../development/backend/configurations.md) diff --git a/docs/content/deployments/storefront/deploying-next-on-vercel.md b/docs/content/deployments/storefront/deploying-next-on-vercel.md new file mode 100644 index 0000000000000..a1fa0a93404bc --- /dev/null +++ b/docs/content/deployments/storefront/deploying-next-on-vercel.md @@ -0,0 +1,154 @@ +--- +description: 'Learn step-by-step.' +addHowToData: true +--- + +# Deploy Next.js Storefront on Vercel + +In this document, you’ll learn how to deploy the Next.js Storefront on Vercel. + +Alternatively, you can directly deploy the Next.js storefront to Vercel with this button. + + + Deploy with Vercel + + +## Prerequisites + +### Medusa Components + +It is assumed you already have installed the Next.js storefront locally. If not, please follow along with [this guide](../../starters/nextjs-medusa-starter.mdx) instead. + +It’s also assumed you already have the Medusa backend deployed, which the Next.js storefront interacts with. If not, you can check out one of the [deployment documentation related to the Medusa backend](../server/index.mdx). + +### Required Accounts + +- [Vercel Account](https://vercel.com) +- [GitHub Account](https://github.com/): Only required if you’re deploying through the Vercel website. + +:::note + +If you want to use another Git Provider, it’s possible to follow along with this guide, but you’ll have to perform the equivalent steps in your Git Provider. + +::: + +### Required Tools + +- [Git CLI](../../development/backend/prepare-environment.mdx): Only required if you’re deploying through the Vercel website. + +--- + +## Step 1: Create GitHub Repository + +:::note + +This step is only required if you’re deploying from the Vercel website. However, it’s highly recommended to connect your Vercel project to a Git repository for a better developer experience. + +::: + +Before you can deploy your Next.js storefront, you need to create a GitHub repository and push the code base to it. To do that: + +1. On GitHub, click the plus icon at the top right, then click New Repository. +2. You’ll then be redirected to a new page with a form. In the form, enter the Repository Name. +3. Scroll down and click Create repository. + +### Push Code to GitHub Repository + +The next step is to push the code to the GitHub repository you just created. + +After creating the repository, you’ll be redirected to the repository’s page. On that page, you should see a URL that you can copy to connect your repository to a local directory. + +Copy the link. Then, open your terminal in the directory that holds your Next.js storefront codebase and run the following commands: + +```bash +git init +git remote add origin +``` + +Where `` is the URL you just copied. + +Then, add, commit, and push the changes into the repository: + +```bash +git add . +git commit -m "initial commit" +git push origin master +``` + +After pushing the changes, you can find the files in your GitHub repository. + +--- + +## Step 2: Deploy to Vercel + +This section covers how to deploy the storefront, either using the Vercel website or using Vercel’s CLI tool. + +### Option 1: Using the Vercel Website + +This section explains how to deploy the storefront using the Vercel website: + +1. Open the [Vercel dashboard](https://vercel.com/dashboard) after logging in. +2. Click on the “Add New…” button next to the search bar. +3. Choose Project from the dropdown. +4. In the new page that opens, find the Git repository that holds your Next.js storefront and click on the Import button. If you haven’t connected your Vercel account to any Git provider, you must do that first. +5. In the Configure Project form: + 1. Open the Environment Variables collapsible, and add an environment variable with the name `NEXT_PUBLIC_MEDUSA_BACKEND_URL` and the value being the URL to your deployed Medusa Backend. + 2. You can optionally edit the Project Name. +6. Once you’re done, click on the “Deploy” button. + +This will start the deployment of the storefront. Once it’s done, you’ll be redirected to the main dashboard of your new project. + +:::note + +At this point, when you visit the storefront, you will face errors related to Cross-Origin Resource Sharing (CORS) while using the storefront. Before you start using the storefront, follow along the [Configure CORS on the Medusa Backend](#step-3-configure-cors-on-the-medusa-backend) section. + +::: + +### Option 2: Using Vercel’s CLI Tool + +This section explains how to deploy the storefront using the Vercel CLI tool. You should have the CLI tool installed first, as explained in [Vercel’s documentation](https://vercel.com/docs/cli). + +In the directory holding your storefront, run the following command to deploy your storefront: + +```bash +vercel --build-env NEXT_PUBLIC_MEDUSA_BACKEND_URL= +``` + +Where `` is the URL of your deployed Medusa backend. + +You’ll then be asked to log in if you haven’t already, and to choose the scope to deploy your project to. You can also decide to link the storefront to an existing project, or change the project’s name. + +When asked `In which directory is your code located?`, keep the default `./` and just press Enter. + +The project setup will then start. When asked if you want to modify the settings, answer `N` to keep the default settings. + +It will take a couple of minutes for the deployment to finish. The link to the storefront will be shown in the final output of the command. + +:::note + +At this point, when you visit the storefront, you will face errors related to Cross-Origin Resource Sharing (CORS) while using the storefront. Before you start using the storefront, follow along the [Configure CORS on the Medusa Backend](#step-3-configure-cors-on-the-medusa-backend) section. + +::: + +--- + +## Step 3: Configure CORS on the Medusa Backend + +To send requests to the Medusa backend from the Next.js storefront, you must set the `STORE_CORS` environment variable on your backend to the Next.js storefront’s URL. + +:::tip + +If you want to set a custom domain to your Next.js storefront website on Vercel, make sure to do it before this step. You can refer to this guide on [Vercel’s documentation](https://vercel.com/docs/concepts/projects/domains/add-a-domain). + +::: + +On your Medusa backend, add the following environment variable: + +```bash +STORE_CORS= +``` + +Where `` is the URL of your Next.js storefront that you just deployed. + +Then, restart your Medusa backend. Once the backend is running again, you can use your Next.js storefront. diff --git a/docs/content/deployments/storefront/index.mdx b/docs/content/deployments/storefront/index.mdx index 2c683ece3820f..65d6e0e6bbd05 100644 --- a/docs/content/deployments/storefront/index.mdx +++ b/docs/content/deployments/storefront/index.mdx @@ -1,6 +1,6 @@ --- hide_table_of_contents: true -description: 'Learn how to deploy your storefronts to different hosting providers to be used with a deployed Medusa server.' +description: 'Learn how to deploy your storefronts to different hosting providers to be used with a deployed Medusa backend.' --- import DocCardList from '@theme/DocCardList'; diff --git a/docs/content/usage/configurations.md b/docs/content/development/backend/configurations.md similarity index 84% rename from docs/content/usage/configurations.md rename to docs/content/development/backend/configurations.md index 514b8c6186548..9e2e56e31fbdc 100644 --- a/docs/content/usage/configurations.md +++ b/docs/content/development/backend/configurations.md @@ -1,20 +1,20 @@ --- -description: 'Learn about the different configurations available in a Medusa server. This includes configurations related to the database, CORS, plugins, redis, and more.' +description: 'Learn about the different configurations available in a Medusa backend. This includes configurations related to the database, CORS, plugins, redis, and more.' --- -# Configure Medusa Server +# Configure Medusa Backend -In this document, you’ll learn what configurations you can add to your Medusa server and how to add them. +In this document, you’ll learn what configurations you can add to your Medusa backend and how to add them. ## Prerequisites -This document assumes you already followed along with the [“Set up your development environment” documentation](../tutorial/0-set-up-your-development-environment.mdx) and have [installed a Medusa server](../quickstart/quick-start.mdx#create-a-medusa-server). +This document assumes you already followed along with the [“Set up your development environment” documentation](./prepare-environment.mdx) and have [installed a Medusa backend](./install.mdx#create-a-medusa-backend). --- ## Medusa Configurations File -The configurations for your Medusa server are in `medusa-config.js`. This includes database, Redis, and plugin configurations, among other configurations. +The configurations for your Medusa backend are in `medusa-config.js`. This includes database, Redis, and plugin configurations, among other configurations. Some of the configurations mentioned in this document are already defined in `medusa-config.js` with default values. It’s important that you know what these configurations are used for and how to set them. @@ -28,7 +28,7 @@ By default, Medusa loads environment variables from the system’s environment v :::info -This change in how environment variables are loaded was introduced in version 1.3.0. You can learn more in the [upgrade guide for version 1.3.0](../advanced/backend/upgrade-guides/medusa-core/1-3-0.md). +This change in how environment variables are loaded was introduced in version 1.3.0. You can learn more in the [upgrade guide for version 1.3.0](../../upgrade-guides/medusa-core/1-3-0.md). ::: @@ -158,11 +158,11 @@ It is recommended to set the Redis URL as an environment variable: REDIS_URL= ``` -Where `` is the URL of your Redis server. +Where `` is the URL of your Redis backend. :::info -You can learn more about Subscribers and events in the [Subscriber documentation](../advanced/backend/subscribers/create-subscriber.md). +You can learn more about Subscribers and events in the [Subscriber documentation](../events/create-subscriber.md). ::: @@ -193,7 +193,7 @@ Where `` is the JWT secret you want to use. :::caution -In a development environment, if this option is not set the default secret is “supersecret”. However, in production, if this option is not set an error will be thrown and your server will crash. +In a development environment, if this option is not set the default secret is “supersecret”. However, in production, if this option is not set an error will be thrown and your backend will crash. ::: @@ -224,7 +224,7 @@ Where `` is the Cookie secret you want to use. :::caution -In a development environment, if this option is not set the default secret is “supersecret”. However, in production, if this option is not set an error will be thrown and your server will crash. +In a development environment, if this option is not set the default secret is “supersecret”. However, in production, if this option is not set an error will be thrown and your backend will crash. ::: @@ -232,7 +232,7 @@ In a development environment, if this option is not set the default secret is ## CORS Configurations -Medusa uses Cross-Origin Resource Sharing (CORS) to only allow specific origins to access the server. +Medusa uses Cross-Origin Resource Sharing (CORS) to only allow specific origins to access the backend. The Admin and the Storefront have different CORS configurations that must be configured. @@ -241,7 +241,7 @@ The Admin and the Storefront have different CORS configurations that must be con For both of the Admin and the Storefront CORS configurations, the value is expected to be a string. This string can be a comma-separated list of accepted origins. Every origin in that list can be of the following types: 1. The accepted origin as is. For example, `http://localhost:8000`. -2. A regular expression pattern that can match more than one origin. For example, `*.example.com`. The regex pattern that the server tests for is `^([\/~@;%#'])(.*?)\1([gimsuy]*)$`. +2. A regular expression pattern that can match more than one origin. For example, `*.example.com`. The regex pattern that the backend tests for is `^([\/~@;%#'])(.*?)\1([gimsuy]*)$`. Here are some examples of common use cases: @@ -271,7 +271,7 @@ The examples above apply to both Admin and Store CORS. ### Admin CORS -To make sure your Admin dashboard can access the Medusa server’s admin endpoints, set this configuration: +To make sure your Admin dashboard can access the Medusa backend’s admin endpoints, set this configuration: ```jsx module.exports = { @@ -300,7 +300,7 @@ Make sure that the URL is without a backslash at the end. For example, you shoul ### Storefront CORS -To make sure your Storefront dashboard can access the Medusa server, set this configuration: +To make sure your Storefront dashboard can access the Medusa backend, set this configuration: ```jsx module.exports = { @@ -331,11 +331,11 @@ Make sure that the URL is without a backslash at the end. For example, you shoul ## Plugins -On your Medusa server, you can use Plugins to add custom features or integrate third-party services. For example, installing a plugin to use Stripe as a payment provider. +On your Medusa backend, you can use Plugins to add custom features or integrate third-party services. For example, installing a plugin to use Stripe as a payment provider. :::info -You can learn more about plugins in the [Plugins Overview documentation](../advanced/backend/plugins/overview.md). +You can learn more about plugins in the [Plugins Overview documentation](../plugins/overview.mdx). ::: @@ -387,6 +387,5 @@ It is recommended to use environment variables to store values of options instea ## See Also -- Check out the [Next.js](../starters/nextjs-medusa-starter.mdx) and [Gatsby](../starters/gatsby-medusa-starter.mdx) starter storefronts -- [Install the Medusa admin](../admin/quickstart.mdx) -- [Deploy the Medusa server](../deployments/server/index.mdx) +- [Medusa architecture overview](../fundamentals/architecture-overview.md) +- [Plugins](../plugins/overview.mdx) \ No newline at end of file diff --git a/docs/content/tutorial/development.module.css b/docs/content/development/backend/development.module.css similarity index 100% rename from docs/content/tutorial/development.module.css rename to docs/content/development/backend/development.module.css diff --git a/docs/content/development/backend/install.mdx b/docs/content/development/backend/install.mdx new file mode 100644 index 0000000000000..bc87ac1eea04c --- /dev/null +++ b/docs/content/development/backend/install.mdx @@ -0,0 +1,104 @@ +--- +description: 'This quickstart guide will help you set up a Medusa backend in three steps.' +addHowToData: true +--- + +import Feedback from '@site/src/components/Feedback'; + +# Install Medusa Backend + +This document will guide you through setting up your Medusa backend in a three steps. + +## Prerequisites + +### Node.js + +Medusa supports Node versions 14 and 16. You can check which version of Node you have by running the following command: + +```bash noReport +node -v +``` + +You can install Node from the [official website](https://nodejs.org/en/). + +### Git + +Git is required for this setup. You can find instructions on how to install it from the [Set up your dev environment documentation](../../development/backend/prepare-environment.mdx#git). + +--- + +## Create a Medusa Backend + +:::tip + +It is recommended to use [Yarn](https://yarnpkg.com/getting-started/install) for the installation process as it's much faster than using NPM. + +::: + +### 1. Install Medusa CLI + + ```bash npm2yarn + npm install @medusajs/medusa-cli -g + ``` + +:::note + +If you run into any errors while installing the CLI tool, check out the [troubleshooting guide](../../troubleshooting/cli-installation-errors.mdx). + +::: + +### 2. Create a new Medusa project + + ```bash noReport + medusa new my-medusa-store --seed + ``` + +### 3. Start your Medusa backend + + ```bash noReport + cd my-medusa-store + medusa develop + ``` + + + +### Test the Backend + +After these three steps and in only a couple of minutes, you now have a complete commerce engine running locally. You can test it out by sending a request using a tool like Postman or through the command line: + +```bash noReport +curl localhost:9000/store/products +``` + +--- + +## Next Steps + +### Learn about the Architecture + +Medusa backend is made up of different resources that make it a powerful server. Get an overview of them in the [Medusa Architecture Overview](../fundamentals/architecture-overview.md) documentation. + +### Set Up Development Environment + +For an optimal experience developing with Medusa and to make sure you can use its advanced functionalities, you'll need to install more tools such as Redis or PostgreSQL. + +Follow [this documentation to learn how to set up your development environment](../../development/backend/prepare-environment.mdx). + +### Backend Configurations + +It's important to configure your Medusa backend properly and learn how environment variables are loaded. + +You can learn more about configuring your backend and loading environment variables in the [Configure your Backend documentation](../../development/backend/configurations.md). + +### File Service Plugin + +To upload product images to your Medusa backend, you must install and configure one of the following file service plugins: + +- [MinIO](../../plugins/file-service/minio.md) (Recommended for local development) +- [S3](../../plugins/file-service/s3.md) +- [DigitalOcean Spaces](../../plugins/file-service/spaces.md) diff --git a/docs/content/tutorial/0-set-up-your-development-environment.mdx b/docs/content/development/backend/prepare-environment.mdx similarity index 80% rename from docs/content/tutorial/0-set-up-your-development-environment.mdx rename to docs/content/development/backend/prepare-environment.mdx index b4987fd38b9ff..f8e5d213d6e00 100644 --- a/docs/content/tutorial/0-set-up-your-development-environment.mdx +++ b/docs/content/development/backend/prepare-environment.mdx @@ -1,14 +1,14 @@ --- -description: 'Learn how to set up your development environment while using Medusa. This guide includes how to install Node.js, Git, Medusa CLI tool, PostgreSQL, and Redis.' +description: 'Learn how to prepare your development environment while using Medusa. This guide includes how to install Node.js, Git, Medusa CLI tool, PostgreSQL, and Redis.' --- import styles from './development.module.css'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Set up Development Environment +# Prepare Development Environment -This document will guide you to set up your development environment to efficiently and properly use Medusa. +This document will guide you to prepare your development environment to efficiently and properly use Medusa. ## Required Tools @@ -139,29 +139,29 @@ medusa -v :::note -If you run into any errors while installing the CLI tool, check out the [troubleshooting guide](../troubleshooting/cli-installation-errors.mdx). +If you run into any errors while installing the CLI tool, check out the [troubleshooting guide](../../troubleshooting/cli-installation-errors.mdx). ::: --- -## Install Medusa Server +## Install Medusa Backend -If you're not interested in installing the optional tools and want to get started quickly, check out the [quickstart guide](../quickstart/quick-start.mdx). +If you're not interested in installing the optional tools and want to get started with Medusa quickly, check out the [Medusa Backend Quickstart](./install.mdx). --- ## Optional Tools -These tools are not required to have to run a Medusa server, but it's highly recommended that you have them installed. +These tools are not required to have to run a Medusa backend, but it's highly recommended that you have them installed. ### PostgreSQL -Although you can use an SQLite database with Medusa which would require no necessary database installations, it is recommended to use a PostgreSQL database for your server. +Although you can use an SQLite database with Medusa which would require no necessary database installations, it is recommended to use a PostgreSQL database for your backend. :::tip -After installing PostgreSQL, check out the [Configure your Server documentation](../usage/configurations.md#postgresql-configurations) to learn how to configure PostgreSQL to work with Medusa. +After installing PostgreSQL, check out the [Configure your Backend documentation](./configurations.md#postgresql-configurations) to learn how to configure PostgreSQL to work with Medusa. ::: @@ -206,7 +206,7 @@ Where: - `--name` creates a new container named `postgres`. - `-e` creates environment variables `POSTGRES_USER`, `POSTGRES_PASSWORD` and `POSTGRES_DB`. These will be used to set up a database named `medusa-docker` with the username and password being `postgres`. -- `-p` maps the container port `5432` to the external host `5432`. This allows you to connect to the database server from outside of the container. +- `-p` maps the container port `5432` to the external host `5432`. This allows you to connect to the database backend from outside of the container. - `-d` enables Docker to run the container in the background. - The last section of the command, `postgres` grabs the latest postgres image from the Docker hub. @@ -215,13 +215,13 @@ Where: ### Redis -Medusa uses Redis as the event queue in the server. If you want to use subscribers to handle events such as when an order is placed and perform actions based on the events, then you need to install and configure Redis. +Medusa uses Redis as the event queue in the backend. If you want to use subscribers to handle events such as when an order is placed and perform actions based on the events, then you need to install and configure Redis. -If you don’t install and configure Redis with your Medusa server, then it will work without any events-related features. +If you don’t install and configure Redis with your Medusa backend, then it will work without any events-related features. :::tip -After installing Redis, check out the [Configure your Server documentation](../usage/configurations.md#redis) to learn how to configure Redis to work with Medusa. +After installing Redis, check out the [Configure your Backend documentation](./configurations.md#redis) to learn how to configure Redis to work with Medusa. ::: @@ -284,7 +284,5 @@ To install Redis without Homebrew you can check out [Redis’s guide on installi ## See Also -- [Install Medusa server](../quickstart/quick-start.mdx) -- [Configure your Medusa server](../usage/configurations.md). -- Install a storefront with [Next.js](../starters/nextjs-medusa-starter.mdx) or [Gatsby](./../starters/gatsby-medusa-starter.mdx). -- [Install the Medusa Admin](../admin/quickstart.mdx). +- [Install Medusa backend](./install.mdx) +- [Configure the Medusa backend](./configurations.md) diff --git a/docs/content/advanced/backend/batch-jobs/create.mdx b/docs/content/development/batch-jobs/create.mdx similarity index 78% rename from docs/content/advanced/backend/batch-jobs/create.mdx rename to docs/content/development/batch-jobs/create.mdx index 9bddb1f4ec6cb..0b80d7c9679b0 100644 --- a/docs/content/advanced/backend/batch-jobs/create.mdx +++ b/docs/content/development/batch-jobs/create.mdx @@ -1,5 +1,5 @@ --- -description: 'Learn how to create a batch job strategy in the Medusa server. This guide also includes how to test your batch job strategy.' +description: 'Learn how to create a batch job strategy in Medusa. This guide also includes how to test your batch job strategy.' addHowToData: true --- @@ -8,17 +8,17 @@ import TabItem from '@theme/TabItem'; # Create a Batch Job Strategy -In this document, you’ll learn how to create a batch job strategy on your Medusa server. +In this document, you’ll learn how to create a batch job strategy in Medusa. :::info -If you’re interested to learn more about what Batch Jobs are and how they work, check out [this documentation](./index.md). +If you’re interested to learn more about what Batch Jobs are and how they work, check out [this documentation](./index.mdx). ::: ## Overview -Batch jobs can be used to perform long tasks in the background of your Medusa server. Batch jobs are handled by batch job strategies. An example of a batch job strategy is the Import Products functionality. +Batch jobs can be used to perform long tasks in the background of your Medusa backend. Batch jobs are handled by batch job strategies. An example of a batch job strategy is the Import Products functionality. This documentation helps you learn how to create a batch job strategy. The batch job strategy used in this example changes the status of all draft products to `published`. @@ -28,15 +28,15 @@ This documentation helps you learn how to create a batch job strategy. The batch ### Medusa Components -It is assumed that you already have a Medusa server installed and set up. If not, you can follow our [quickstart guide](../../../quickstart/quick-start.mdx) to get started. +It is assumed that you already have a Medusa backend installed and set up. If not, you can follow our [quickstart guide](../backend/install.mdx) to get started. ### Redis -Redis is required for batch jobs to work. Make sure you [install Redis](../../../tutorial/0-set-up-your-development-environment.mdx#redis) and [configure it with your Medusa server](../../../usage/configurations.md#redis). +Redis is required for batch jobs to work. Make sure you [install Redis](../backend/prepare-environment.mdx#redis) and [configure it with your Medusa backend](../backend/configurations.md#redis). ### PostgreSQL -If you use SQLite during your development, it’s highly recommended that you use PostgreSQL when working with batch jobs. Learn how to [install PostgreSQL](../../../tutorial/0-set-up-your-development-environment.mdx#postgresql) and [configure it with your Medusa server](../../../usage/configurations.md#postgresql-configurations). +If you use SQLite during your development, it’s highly recommended that you use PostgreSQL when working with batch jobs. Learn how to [install PostgreSQL](../backend/prepare-environment.mdx#postgresql) and [configure it with your Medusa backend](../backend/configurations.md#postgresql-configurations). --- @@ -102,7 +102,7 @@ class PublishStrategy extends AbstractBatchJobStrategy { ### (Optional) prepareBatchJobForProcessing -Medusa runs this method before it creates the batch job to prepare the content of the batch job record in the database. It accepts two parameters: the batch job data sent in the body of the [Create Batch Job request](https://docs.medusajs.com/api/admin/#tag/Batch-Job/operation/PostBatchJobs), and the request instance. +Medusa runs this method before it creates the batch job to prepare the content of the batch job record in the database. It accepts two parameters: the batch job data sent in the body of the [Create Batch Job request](/api/admin/#tag/Batch-Job/operation/PostBatchJobs), and the request instance. Implementing this method is optional. For example: @@ -129,32 +129,34 @@ For example, this implementation of the `preProcessBatchJob` method calculates h class PublishStrategy extends AbstractBatchJobStrategy { // ... async preProcessBatchJob(batchJobId: string): Promise { - return await this.atomicPhase_(async (transactionManager) => { - const batchJob = (await this.batchJobService_ - .withTransaction(transactionManager) - .retrieve(batchJobId)) - - const count = await this.productService_ - .withTransaction(transactionManager) - .count({ - status: ProductStatus.DRAFT, - }) + return await this.atomicPhase_( + async (transactionManager) => { + const batchJob = (await this.batchJobService_ + .withTransaction(transactionManager) + .retrieve(batchJobId)) + + const count = await this.productService_ + .withTransaction(transactionManager) + .count({ + status: ProductStatus.DRAFT, + }) - await this.batchJobService_ - .withTransaction(transactionManager) - .update(batchJob, { - result: { - advancement_count: 0, - count, - stat_descriptors: [ - { - key: "product-publish-count", - name: "Number of products to publish", - message: `${count} product(s) will be published.`, - }, - ], - }, - }) + await this.batchJobService_ + .withTransaction(transactionManager) + .update(batchJob, { + result: { + advancement_count: 0, + count, + stat_descriptors: [ + { + key: "product-publish-count", + name: "Number of products to publish", + message: + `${count} product(s) will be published.`, + }, + ], + }, + }) }) } } @@ -272,7 +274,7 @@ class PublishStrategy extends AbstractBatchJobStrategy { ## 5. Run Build Command -After you create the batch job and before testing it out, you must run the build command in the directory of your Medusa server: +After you create the batch job and before testing it out, you must run the build command in the directory of your Medusa backend: ```bash npm run build @@ -282,7 +284,7 @@ npm run build ## Test your Batch Job Strategy -This section covers how to test and use your batch job strategy. Make sure to start your server first: +This section covers how to test and use your batch job strategy. Make sure to start your backend first: ```bash npm run start @@ -290,17 +292,17 @@ npm run start :::info -If your `start` script uses the `medusa develop` command, whenever you make changes in the `src` directory the `build` command will automatically run and the server will restart. +If your `start` script uses the `medusa develop` command, whenever you make changes in the `src` directory the `build` command will automatically run and the backend will restart. ::: -You must also use an authenticated user to send batch job requests. You can refer to the [authentication guide in the API reference](https://docs.medusajs.com/api/admin/#section/Authentication) for more details. +You must also use an authenticated user to send batch job requests. You can refer to the [authentication guide in the API reference](/api/admin/#section/Authentication) for more details. -If you follow along with the JS Client code snippets, make sure to [install and set it up first](../../../js-client/overview.md). +If you follow along with the JS Client code snippets, make sure to [install and set it up first](../../js-client/overview.md). ### Create Batch Job -The first step is to create a batch job using the [Create Batch Job endpoint](https://docs.medusajs.com/api/admin/#tag/Batch-Job/operation/PostBatchJobs). In the body of the request, you must set the `type` to the value of `batchType` in the batch job strategy you created. +The first step is to create a batch job using the [Create Batch Job endpoint](/api/admin/#tag/Batch-Job/operation/PostBatchJobs). In the body of the request, you must set the `type` to the value of `batchType` in the batch job strategy you created. For example, this creates a batch job of the type `publish-products`: @@ -322,7 +324,7 @@ medusa.admin.batchJobs.create({ ```jsx -fetch(`/admin/batch-jobs`, { +fetch(`/admin/batch-jobs`, { method: "POST", credentials: "include", headers: { @@ -344,7 +346,7 @@ fetch(`/admin/batch-jobs`, { ```bash -curl -L -X POST '/admin/batch-jobs' \ +curl -L -X POST '/admin/batch-jobs' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -359,7 +361,7 @@ curl -L -X POST '/admin/batch-jobs' \ You set the `dry_run` to `true` to disable automatic confirmation and running of the batch job. If you want the batch job to run automatically, you can remove this body parameter. -Make sure to replace `` with the server URL where applicable. +Make sure to replace `` with the backend URL where applicable. ### (Optional) Retrieve Batch Job @@ -379,7 +381,7 @@ medusa.admin.batchJobs.retrieve(batchJobId) ```jsx -fetch(`/admin/batch-jobs/${batchJobId}`, { +fetch(`/admin/batch-jobs/${batchJobId}`, { credentials: "include", }) .then((response) => response.json()) @@ -392,7 +394,7 @@ fetch(`/admin/batch-jobs/${batchJobId}`, { ```bash -curl -L -X GET '/admin/batch-jobs/' \ +curl -L -X GET '/admin/batch-jobs/' \ -H 'Authorization: Bearer ' # is the ID of the batch job ``` @@ -418,7 +420,7 @@ Based on the batch job strategy implemented in this documentation, the `result` ### Confirm Batch Job -To process the batch job, send a request to [confirm the batch job](https://docs.medusajs.com/api/admin/#tag/Batch-Job/operation/PostBatchJobsBatchJobConfirmProcessing): +To process the batch job, send a request to [confirm the batch job](/api/admin/#tag/Batch-Job/operation/PostBatchJobsBatchJobConfirmProcessing): @@ -434,7 +436,7 @@ medusa.admin.batchJobs.confirm(batchJobId) ```jsx -fetch(`/admin/batch-jobs/${batchJobId}/confirm`, { +fetch(`/admin/batch-jobs/${batchJobId}/confirm`, { method: "POST", credentials: "include", }) @@ -448,7 +450,7 @@ fetch(`/admin/batch-jobs/${batchJobId}/confirm`, { ```bash -curl -L -X POST '/admin/batch-jobs//confirm' \ +curl -L -X POST '/admin/batch-jobs//confirm' \ -H 'Authorization: Bearer ' # is the ID of the batch job ``` @@ -459,10 +461,3 @@ curl -L -X POST '/admin/batch-jobs//confirm' \ The batch job will start processing afterward. Based on the batch job strategy implemented in this documentation, draft products will be published. You can [retrieve the batch job](#optional-retrieve-batch-job) at any given point to check its status. - ---- - -## See Also - -- [Batch Jobs Overview](./index.md). -- [Import products using the Admin API](../../admin/import-products.mdx). diff --git a/docs/content/advanced/backend/batch-jobs/customize-import.md b/docs/content/development/batch-jobs/customize-import.md similarity index 79% rename from docs/content/advanced/backend/batch-jobs/customize-import.md rename to docs/content/development/batch-jobs/customize-import.md index 74ca818110476..5b1018b387b83 100644 --- a/docs/content/advanced/backend/batch-jobs/customize-import.md +++ b/docs/content/development/batch-jobs/customize-import.md @@ -19,15 +19,15 @@ Although this documentation specifically targets import strategies, you can use ### Medusa Components -It's assumed that you already have a Medusa server installed and set up. If not, you can follow our [quickstart guide](../../../quickstart/quick-start.mdx) to get started. +It's assumed that you already have a Medusa backend installed and set up. If not, you can follow our [quickstart guide](../backend/install.mdx) to get started. ### Redis -Redis is required for batch jobs to work. Make sure you [install Redis](../../../tutorial/0-set-up-your-development-environment.mdx#redis) and [configure it with your Medusa server](../../../usage/configurations.md#redis). +Redis is required for batch jobs to work. Make sure you [install Redis](../backend/prepare-environment.mdx#redis) and [configure it with your Medusa backend](../backend/configurations.md#redis). ### PostgreSQL -If you use SQLite during your development, it’s highly recommended that you use PostgreSQL when working with batch jobs. Learn how to [install PostgreSQL](../../../tutorial/0-set-up-your-development-environment.mdx#postgresql) and [configure it with your Medusa server](../../../usage/configurations.md#postgresql-configurations). +If you use SQLite during your development, it’s highly recommended that you use PostgreSQL when working with batch jobs. Learn how to [install PostgreSQL](../backend/prepare-environment.mdx#postgresql) and [configure it with your Medusa backend](../backend/configurations.md#postgresql-configurations). --- @@ -39,7 +39,7 @@ If you’re interested to learn more about batch job strategies and how they wor ### 1. Create a File -You must store batch job strategies in the `src/strategies` directory of your Medusa server. They are either TypeScript or JavaScript files. +You must store batch job strategies in the `src/strategies` directory of your Medusa backend. They are either TypeScript or JavaScript files. So, for example, you can create the file `src/strategies/import.ts`. @@ -111,21 +111,20 @@ npm run build Since you didn’t create a new batch job type and overwrote the functionality of the strategy, you can test out your functionality using the [same steps used with the default strategy](./create.mdx#test-your-batch-job-strategy). -Specifically, since you create batch jobs using the [Create Batch Job](https://docs.medusajs.com/api/admin/#tag/Batch-Job/operation/PostBatchJobs) endpoint which accepts the batch job type as a body parameter, you just need to send the same type you used for this field. In the example of this documentation, the `type` would be `product-import`. +Specifically, since you create batch jobs using the [Create Batch Job](/api/admin/#tag/Batch-Job/operation/PostBatchJobs) endpoint which accepts the batch job type as a body parameter, you just need to send the same type you used for this field. In the example of this documentation, the `type` would be `product-import`. -If you overwrote the import functionality, you can follow [these steps to learn how to import products using the Admin APIs](../../admin/import-products.mdx). +If you overwrote the import functionality, you can follow [these steps to learn how to import products using the Admin APIs](../../modules/products/admin/import-products.mdx). --- ## Create Custom Batch Job Strategy -If you don’t want to overwrite Medusa’s batch job strategy, you can create a custom batch job strategy with a different `batchType` value. Then, use that type when you send a request to [Create a Batch Job](https://docs.medusajs.com/api/admin/#tag/Batch-Job). +If you don’t want to overwrite Medusa’s batch job strategy, you can create a custom batch job strategy with a different `batchType` value. Then, use that type when you send a request to [Create a Batch Job](/api/admin/#tag/Batch-Job). -For more details on creating custom batch job strategies, please check out the [Create Batch Job Strategy documentation](create.mdx). +For more details on creating custom batch job strategies, please check out the [Create Batch Job Strategy documentation](./create.mdx). --- -## What’s Next +## See Also -- [Batch Jobs Overview](./index.md). -- [Use the Import Product APIs](../../admin/import-products.mdx). +- [Use the Import Product APIs](../../modules/products/admin/import-products.mdx). diff --git a/docs/content/advanced/backend/batch-jobs/index.md b/docs/content/development/batch-jobs/index.mdx similarity index 71% rename from docs/content/advanced/backend/batch-jobs/index.md rename to docs/content/development/batch-jobs/index.mdx index 88b61e4cd280a..d501386820437 100644 --- a/docs/content/advanced/backend/batch-jobs/index.md +++ b/docs/content/development/batch-jobs/index.mdx @@ -1,16 +1,19 @@ --- -description: 'Learn what batch jobs in the Medusa server are and their flow. Batch jobs are tasks that can be performed asynchronously and iteratively in the Medusa server.' +description: 'Learn what batch jobs in Medusa are and their flow. Batch jobs are tasks that can be performed asynchronously and iteratively in Medusa.' --- +import DocCardList from '@theme/DocCardList'; +import Icons from '@theme/Icon'; + # Batch Jobs In this document, you’ll learn what Batch Jobs are and how they work in Medusa. ## What are Batch Jobs -Batch Jobs are tasks that can be performed asynchronously and iteratively. They can be [created using the Admin API](https://docs.medusajs.com/api/admin/#tag/Batch-Job/operation/PostBatchJobs), then, once confirmed, they are processed asynchronously. +Batch Jobs are tasks that can be performed asynchronously and iteratively. They can be [created using the Admin API](/api/admin/#tag/Batch-Job/operation/PostBatchJobs), then, once confirmed, they are processed asynchronously. -Batch jobs require Redis, which Medusa uses as a queuing system to register and handle events. Every status change of a batch job triggers an event that can be handled using [subscribers](../subscribers/overview.md). +Batch jobs require Redis, which Medusa uses as a queuing system to register and handle events. Every status change of a batch job triggers an event that can be handled using [subscribers](../events/subscribers.mdx). Medusa uses batch jobs in its core to perform some asynchronous tasks. For example, the Export Products functionality uses batch jobs. @@ -18,7 +21,7 @@ You can also create a custom batch job or overwrite Medusa’s batch jobs. ### BatchJob Entity Overview -A batch job is stored in the database as a [BatchJob](https://docs.medusajs.com/references/entities/classes/BatchJob) entity. Some of its important attributes are: +A batch job is stored in the database as a [BatchJob](../../references/entities/classes/BatchJob) entity. Some of its important attributes are: - `status`: A string that determines the current status of the Batch Job. - `context`: An object that can be used to store configurations related to the batch job. For example, you can use it to store listing configurations such as the limit or offset of the list to be retrieved during the processing of the batch job. @@ -46,15 +49,15 @@ When you create a batch job strategy, the `batchType` class property indicates t A batch job’s flow from creation to completion is: -1. A batch job is created using the [Create Batch Job API endpoint](https://docs.medusajs.com/api/admin/#tag/Batch-Job/operation/PostBatchJobs). +1. A batch job is created using the [Create Batch Job API endpoint](/api/admin/#tag/Batch-Job/operation/PostBatchJobs). 2. Once the batch job is created, the batch job’s status is changed to `created` and the `batch.created` event is triggered by the `BatchJobService`. 3. The `BatchJobSubscriber` handles the `created` event. It resolves the batch job strategy based on the `type` of the batch job, then uses it to pre-process the batch job. After this, the batch job’s status is changed to `pre_processed`. Only when the batch job has the status `pre_processed` can be confirmed. -4. If `dry_run` is not set in the Create Batch Job request in step one or if it is set to `false`, the batch job will automatically be confirmed after processing. Otherwise, if `dry_run` is set to `true`, the batch job can be confirmed using the [Confirm Batch Job API](https://docs.medusajs.com/api/admin/#tag/Batch-Job/operation/PostBatchJobsBatchJobConfirmProcessing) endpoint. +4. If `dry_run` is not set in the Create Batch Job request in step one or if it is set to `false`, the batch job will automatically be confirmed after processing. Otherwise, if `dry_run` is set to `true`, the batch job can be confirmed using the [Confirm Batch Job API](/api/admin/#tag/Batch-Job/operation/PostBatchJobsBatchJobConfirmProcessing) endpoint. 5. Once the batch job is confirmed, the batch job’s status is changed to `confirmed` and the `batch.confirmed` event is triggered by the `BatchJobService`. 6. The `BatchJobSubscriber` handles the `confirmed` event. It resolves the batch job strategy, then uses it to process the batch job. 7. Once the batch job is processed succesfully, the batch job has the status `completed`. -You can track the progress of the batch job at any point using the [Retrieve Batch Job](https://docs.medusajs.com/api/admin/#tag/Batch-Job/operation/GetBatchJobsBatchJob) endpoint. +You can track the progress of the batch job at any point using the [Retrieve Batch Job](/api/admin/#tag/Batch-Job/operation/GetBatchJobsBatchJob) endpoint. :::info @@ -66,6 +69,27 @@ If the batch job fails at any point in this flow, its status is changed to `fail --- -## What’s Next - -- [Batch Job’s Events Reference](../subscribers/events-list.md#batch-jobs-events). +## Custom Development + +Developers can create custom batch jobs in the Medusa backend, a plugin, or in a Commerce Module. Developers can also customize existing batch job strategies in the core, such as the import strategy. + + \ No newline at end of file diff --git a/docs/content/advanced/backend/endpoints/add-middleware.md b/docs/content/development/endpoints/add-middleware.md similarity index 82% rename from docs/content/advanced/backend/endpoints/add-middleware.md rename to docs/content/development/endpoints/add-middleware.md index f4fc992b7a0b3..83e3808be99ec 100644 --- a/docs/content/advanced/backend/endpoints/add-middleware.md +++ b/docs/content/development/endpoints/add-middleware.md @@ -9,13 +9,13 @@ In this document, you’ll learn how to add a middleware to an existing or custo ## Overview -As the Medusa server is built on top of [Express](https://expressjs.com/), Express’s features can be utilized during your development with Medusa. +As the Medusa backend is built on top of [Express](https://expressjs.com/), Express’s features can be utilized during your development with Medusa. One feature in particular is adding a [middleware](http://expressjs.com/en/guide/using-middleware.html#using-middleware). A middleware is a function that has access to the request and response objects. A middleware can be used to perform an action when an endpoint is called or modify the response, among other usages. -You can add a middleware to an existing route in the Medusa server, a route in a plugin, or your custom routes. +You can add a middleware to an existing route in the Medusa backend, a route in a plugin, or your custom routes. --- @@ -25,7 +25,7 @@ Adding a middleware is very similar to adding a custom endpoint. The middleware :::info -Learn more about creating custom endpoints in [this documentation](./add.md). +Learn more about creating custom endpoints in [this documentation](./create.md). ::: @@ -38,8 +38,8 @@ export default () => { const router = Router() router.use("/store/products", (req, res, next) => { - // / perform an action when retrieving products - next() + // perform an action when retrieving products + next() }) return router @@ -60,9 +60,9 @@ You can learn more about Middlewares and their capabilities in [Express’s docu ## Building Files -Similar to custom endpoints, you must transpile the files under `src` into the `dist` directory for the server to load them. +Similar to custom endpoints, you must transpile the files under `src` into the `dist` directory for the backend to load them. -To do that, run the following command before running the Medusa server: +To do that, run the following command before running the Medusa backend: ```bash npm2yarn npm run build @@ -72,6 +72,5 @@ npm run build ## See Also -- [Create an Endpoint](./add.md) - [Store API reference](/api/store) - [Admin API reference](/api/admin) diff --git a/docs/content/advanced/backend/endpoints/add.md b/docs/content/development/endpoints/create.md similarity index 79% rename from docs/content/advanced/backend/endpoints/add.md rename to docs/content/development/endpoints/create.md index 5bd826f02775c..3d91d69270943 100644 --- a/docs/content/advanced/backend/endpoints/add.md +++ b/docs/content/development/endpoints/create.md @@ -1,15 +1,17 @@ --- -description: 'Learn how to create endpoints in the Medusa server. This guide also includes how to add CORS configurations, creating multiple endpoints, adding protected routes, and more.' +description: 'Learn how to create endpoints in Medusa. This guide also includes how to add CORS configurations, creating multiple endpoints, adding protected routes, and more.' addHowToData: true --- # How to Create Endpoints -In this document, you’ll learn how to create endpoints in your Medusa server. +In this document, you’ll learn how to create endpoints in Medusa. ## Overview -Custom endpoints reside under the `src/api` directory in your Medusa Backend. They're defined in a TypeScript or JavaScript file that is named `index` (for example, `index.ts`). This file should export a function that returns an Express router. +Custom endpoints are created under the `src/api` directory in your Medusa Backend. They're defined in a TypeScript or JavaScript file named `index` (for example, `index.ts`). This file should export a function that returns an Express router + +They're then transpiled into the `/dist/api` directory to be consumed. --- @@ -35,7 +37,7 @@ export default (rootDirectory, pluginOptions) => { This exports a function that returns an Express router. The function receives two parameters: -- `rootDirectory` is the absolute path to the root directory that your server is running from. +- `rootDirectory` is the absolute path to the root directory that your backend is running from. - `pluginOptions` is an object that has your plugin's options. If your API route is not implemented in a plugin, then it will be an empty object. ### Endpoints Path @@ -58,12 +60,17 @@ If you’re adding a storefront or admin endpoint and you want to access these e First, you need to import the necessary utility functions and types from Medusa's packages with the `cors` library: ```ts -import { getConfigFile, parseCorsOrigins } from "medusa-core-utils" -import { ConfigModule } from "@medusajs/medusa/dist/types/global" +import { + getConfigFile, + parseCorsOrigins, +} from "medusa-core-utils" +import { + ConfigModule, +} from "@medusajs/medusa/dist/types/global" import cors from "cors" ``` -Next, in the exported function, retrieve the CORS configurations of your server using the utility functions you imported: +Next, in the exported function, retrieve the CORS configurations of your backend using the utility functions you imported: ```ts export default (rootDirectory) => { @@ -114,18 +121,26 @@ You can add more than one endpoint in `src/api/index.ts`: ```ts title=src/api/index.ts router.options("/store/hello", cors(storeCorsOptions)) -router.get("/store/hello", cors(storeCorsOptions), (req, res) => { - res.json({ - message: "Welcome to Your Store!", - }) -}) +router.get( + "/store/hello", + cors(storeCorsOptions), + (req, res) => { + res.json({ + message: "Welcome to Your Store!", + }) + } +) router.options("/admin/hello", cors(adminCorsOptions)) -router.get("/admin/hello", cors(adminCorsOptions), (req, res) => { - res.json({ - message: "Welcome to Your Admin!", - }) -}) +router.get( + "/admin/hello", + cors(adminCorsOptions), + (req, res) => { + res.json({ + message: "Welcome to Your Admin!", + }) + } +) ``` ### Multiple Files @@ -144,11 +159,15 @@ export default (router) => { credentials: true, } router.options("/store/hello", cors(storeCorsOptions)) - router.get("/store/hello", cors(storeCorsOptions), (req, res) => { - res.json({ - message: "Welcome to Your Store!", - }) - }) + router.get( + "/store/hello", + cors(storeCorsOptions), + (req, res) => { + res.json({ + message: "Welcome to Your Store!", + }) + } + ) } ``` @@ -166,11 +185,15 @@ export default (router) => { credentials: true, } router.options("/admin/hello", cors(adminCorsOptions)) - router.get("/admin/hello", cors(adminCorsOptions), (req, res) => { - res.json({ - message: "Welcome to Your Admin!", - }) - }) + router.get( + "/admin/hello", + cors(adminCorsOptions), + (req, res) => { + res.json({ + message: "Welcome to Your Admin!", + }) + } + ) } ``` @@ -207,6 +230,8 @@ Protected routes are routes that should be accessible by logged-in customers or To make a storefront route protected, first, import the `authenticate-customer` middleware: + + ```ts import authenticate @@ -236,6 +261,8 @@ To disallow guest customers from accessing the endpoint, you can throw an error To make an admin route protected, first, import the `authenticate` middleware: + + ```ts import authenticate @@ -246,7 +273,10 @@ Then, add the middleware to your route: ```ts router.options("/admin/products/count", cors(corsOptions)) -router.get("/admin/products/count", cors(corsOptions), authenticate(), +router.get( + "/admin/products/count", + cors(corsOptions), + authenticate(), async (req, res) => { // access current user const id = req.user.userId @@ -271,7 +301,10 @@ You can retrieve any registered service in your endpoint using `req.scope.resol Here’s an example of an endpoint that retrieves the count of products in your store: ```ts -router.get("/admin/products/count", cors(corsOptions), authenticate(), +router.get( + "/admin/products/count", + cors(corsOptions), + authenticate(), (req, res) => { const productService = req.scope.resolve("productService") @@ -290,7 +323,9 @@ The `productService` has a `count` method that returns a Promise. This Promi ## Building Files -Custom endpoints must be transpiled and moved to the `dist` directory. This happens when you run your server using `medusa develop` and while it’s running, and when you run the following command: +Custom endpoints must be transpiled and moved to the `dist` directory before you can start consuming them. When you run your backend using the `medusa develop` command, it watches the files under `src` for any changes, then triggers the `build` command and restarts the server. + +The build isn't triggerd though when the backend first starts running. So, make sure to run the `build` command before starting the backend: ```bash npm2yarn npm run build @@ -300,7 +335,5 @@ npm run build ## See Also -- [Add a Middleware](./add-middleware.md) - [Storefront API Reference](/api/store) - [Admin API Reference](/api/admin) -- [Create a Service](./../services/create-service.md). diff --git a/docs/content/development/endpoints/overview.mdx b/docs/content/development/endpoints/overview.mdx new file mode 100644 index 0000000000000..edac3ed3d096d --- /dev/null +++ b/docs/content/development/endpoints/overview.mdx @@ -0,0 +1,76 @@ +--- +description: "Learn what endpoints are in Medusa. Endpoints are REST APIs that allow a frontend or external system to interact with the Backend." +--- + +import DocCardList from '@theme/DocCardList'; +import Icons from '@theme/Icon'; + +# Endpoints + +In this document, you’ll learn what endpoints are in Medusa. + +## Introduction + +The Medusa Backend is a web server built on top of [Express](https://expressjs.com/), a Node.js web framework. This provides developers with all the functionalities available within Express during development. One of those are endpoints. + +Endpoints are REST APIs that allow a frontend or an external system to interact with the Medusa Backend to retrieve and process data, or perform business logic. Endpoints are [Express routes](https://expressjs.com/en/starter/basic-routing.html). + +Each [Commerce Module](../../modules/overview.mdx) contains a set of endpoints specific to the functionalities that it provides. Since the core package that powers the Medusa Backend acts as an orchestrator of Commerce Modules and exposes their endpoints, the endpoints of each of these Commerce Modules are available within the Medusa Backend. + +The Commerce Modules provide two types of endpoints: Store APIs and Admin APIs. The Store APIs are typically accessed from the storefront. For example, you can use the Store APIs to show customers available products or implement a cart and checkout flow. + +The Admin APIs are typically accessed from an admin dashboard. For example, you can use the Admin APIs to allow admins to manage the store’s data such as products, orders, and so on. + + + +--- + +## Custom Development + +Aside from using the endpoints that Commerce Modules, developers can create their own REST APIs either directly in the Medusa Backend, in a plugin, or in a custom Commerce Module. + +:::tip + +As the core Medusa package is completely customizable, developers can also extend the functionality even further to implement GraphQL endpoints. + +::: + + \ No newline at end of file diff --git a/docs/content/advanced/backend/entities/index.md b/docs/content/development/entities/create.md similarity index 90% rename from docs/content/advanced/backend/entities/index.md rename to docs/content/development/entities/create.md index 2aaf8bf238fd1..4714bcc9d5277 100644 --- a/docs/content/advanced/backend/entities/index.md +++ b/docs/content/development/entities/create.md @@ -1,18 +1,23 @@ --- -description: 'Learn how to create an entity in the Medusa server. This guide also explains how to create a repository and access and delete the entity.' +description: 'Learn how to create an entity in Medusa. This guide also explains how to create a repository and access and delete the entity.' addHowToData: true --- # Create an Entity -In this document, you’ll learn how you can create an [Entity](overview.md). +In this document, you’ll learn how you can create an [Entity](./overview.mdx). ## Create the Entity To create an entity, create a TypeScript file in `src/models`. For example, here’s a `Post` entity defined in the file `src/models/post.ts`: ```ts title=src/models/post.ts -import { BeforeInsert, Column, Entity, PrimaryColumn } from "typeorm" +import { + BeforeInsert, + Column, + Entity, + PrimaryColumn, +} from "typeorm" import { BaseEntity } from "@medusajs/medusa" import { generateEntityId } from "@medusajs/medusa/dist/utils" @@ -51,7 +56,7 @@ You can learn more about what decorators and column types you can use in [Typeor Additionally, you must create a migration for your entity. Migrations are used to update the database schema with new tables or changes to existing tables. -You can learn more about Migrations, how to create them, and how to run them in the [Migration documentation](../migrations/overview.md). +You can learn more about Migrations, how to create them, and how to run them in the [Migration documentation](./migrations/overview.mdx). ### Create a Repository @@ -137,6 +142,5 @@ await postRepository.softDelete(post.id) ## See Also -- [Entities' reference](../../../references/entities/classes/Address.md) -- [Migrations Overview](../migrations/overview.md) -- [Create a Services](../services/create-service.md) +- [Migrations Overview](./migrations/overview.mdx) +- [Create a Plugin](../plugins/create.md) diff --git a/docs/content/advanced/backend/migrations/index.md b/docs/content/development/entities/migrations/create.md similarity index 84% rename from docs/content/advanced/backend/migrations/index.md rename to docs/content/development/entities/migrations/create.md index f82475a2633fd..6ccf2491262c6 100644 --- a/docs/content/advanced/backend/migrations/index.md +++ b/docs/content/development/entities/migrations/create.md @@ -1,11 +1,11 @@ --- -description: 'Learn how to create a migration in the Medusa server. This guide explains how to write and run migrations.' +description: 'Learn how to create a migration in Medusa. This guide explains how to write and run migrations.' addHowToData: true --- # How to Create Migrations -In this document, you’ll learn how to create a [Migration](overview.md) using [Typeorm](https://typeorm.io) on your Medusa server. +In this document, you’ll learn how to create a [Migration](./overview.mdx) using [Typeorm](https://typeorm.io) in Medusa. ## Step 1: Create Migration File @@ -17,7 +17,7 @@ npx typeorm migration:create -n UserChanged --dir src/migrations This will create the migration file in the path you specify. You can use this without the need to install Typeorm's CLI tool. You can then go ahead and make changes to it as necessary. -The migration file must be inside the `src/migrations` directory. When you run the build command, it will be transpiled into the directory `dist/migrations`. The `migrations run` command can only pick up migrations under the `dist/migrations` directory on a Medusa server. This applies to migrations created in a Medusa server, and not in a Medusa plugin. For plugins, check out the [Plugin's Structure section](../plugins/create.md). +The migration file must be inside the `src/migrations` directory. When you run the build command, it will be transpiled into the directory `dist/migrations`. The `migrations run` command can only pick up migrations under the `dist/migrations` directory on a Medusa backend. This applies to migrations created in a Medusa backend, and not in a Medusa plugin. For plugins, check out the [Plugin's Structure section](../../plugins/create.md).
Generating Migrations for Entities @@ -104,6 +104,6 @@ If you check your database now you should see that the change defined by the mig --- -## What’s Next +## See Also -- [Set up your development server](../../../tutorial/0-set-up-your-development-environment.mdx). +- [Create a Plugin](../../plugins/create.md) diff --git a/docs/content/advanced/backend/migrations/overview.md b/docs/content/development/entities/migrations/overview.mdx similarity index 55% rename from docs/content/advanced/backend/migrations/overview.md rename to docs/content/development/entities/migrations/overview.mdx index 1d60316be4dbe..c868fcbb4fb97 100644 --- a/docs/content/advanced/backend/migrations/overview.md +++ b/docs/content/development/entities/migrations/overview.mdx @@ -1,22 +1,25 @@ --- -description: 'Learn what Migrations are in the Medusa server and how to run them. Migrations are used to make changes to the database schema the Medusa server is linked to.' +description: 'Learn what Migrations are in Medusa and how to run them. Migrations are used to make changes to the database schema that Medusa is linked to.' --- +import DocCardList from '@theme/DocCardList'; +import Icons from '@theme/Icon'; + # Migrations In this document, you'll learn what Migrations are in Medusa. :::note -Medusa’s Migrations do not work with SQLite databases. They are intended to be used with PostgreSQL databases, which is the recommended Database for your Medusa production server. +Medusa’s Migrations do not work with SQLite databases. They are intended to be used with PostgreSQL databases, which is the recommended database for using Medusa in production. ::: ## What are Migrations -Migrations are scripts that are used to make additions or changes to your database schema. In Medusa, they are essential for both when you first install your server and for subsequent server upgrades later on. +Migrations are scripts that are used to make additions or changes to your database schema. In Medusa, they are essential for both when you first install your backend and for subsequent backend upgrades later on. -When you first create your Medusa server, the database schema used must have all the tables necessary for the server to run. +When you first create your Medusa backend, the database schema used must have all the tables necessary for the backend to run. When a new Medusa version introduces changes to the database schema, you'll have to run migrations to apply them to your own database. @@ -40,7 +43,7 @@ Using the Medusa CLI tool, you can run migrations with the following command: medusa migrations run ``` -This will check for any migrations that contain changes to your database schema that aren't applied yet and run them on your server. +This will check for any migrations that contain changes to your database schema that aren't applied yet and run them on your backend. ### Seed Command @@ -52,11 +55,31 @@ You can use the following command to seed your database: npm run seed ``` -This will use the underlying `seed` command provided by Medusa's CLI to seed your database with data from the file `data/seed.json` on your Medusa server. +This will use the underlying `seed` command provided by Medusa's CLI to seed your database with data from the file `data/seed.json` on your Medusa backend. --- -## See Also - -- [Create a migration](index.md) -- [Set up your development environment](../../../tutorial/set-up-your-development-environment) +## Custom Development + +Developers can create custom entities in the Medusa backend, a plugin, or in a Commerce Module, then ensure it reflects in the database using a migration. + + \ No newline at end of file diff --git a/docs/content/advanced/backend/entities/overview.md b/docs/content/development/entities/overview.mdx similarity index 67% rename from docs/content/advanced/backend/entities/overview.md rename to docs/content/development/entities/overview.mdx index 48c7f9f746773..1d3b095ae6ea9 100644 --- a/docs/content/advanced/backend/entities/overview.md +++ b/docs/content/development/entities/overview.mdx @@ -1,7 +1,10 @@ --- -description: 'Learn what entities are in the Medusa server. There are entities in the Medusa server, and developers can create custom entities.' +description: 'Learn what entities are in Medusa. There are entities defined in the Medusa backend, and developers can create custom entities.' --- +import DocCardList from '@theme/DocCardList'; +import Icons from '@theme/Icon'; + # Entities In this document, you'll learn what Entities are in Medusa. @@ -10,7 +13,7 @@ In this document, you'll learn what Entities are in Medusa. Entities in medusa represent tables in the database as classes. An example of this would be the `Order` entity which represents the `order` table in the database. Entities provide a uniform way of defining and interacting with data retrieved from the database. -Aside from Medusa’s core entities, you can also create your own entities to use in your Medusa server. Custom entities are TypeScript or JavaScript files located in the `src/models` directory of your Medusa server. +Aside from the entities in the Medusa core package, you can also create your own entities to use in your Medusa backend. Custom entities are TypeScript or JavaScript files located in the `src/models` directory of your Medusa backend. These entities are then transpiled to the `dist/models` directory to be used during the backend's runtime. Entities are TypeScript files and they are based on [Typeorm’s Entities](https://typeorm.io/entities) and use Typeorm decorators. @@ -65,7 +68,27 @@ If you want to remove a property from the `metadata` object, you can pass the `m --- -## See Also - -- [Create an entity](./index.md) -- [Entities' reference](../../../references/entities/classes/Address.md) \ No newline at end of file +## Custom Development + +Developers can create custom entities in the Medusa backend, a plugin, or in a Commerce Module, then ensure it reflects in the database using a migration. + + \ No newline at end of file diff --git a/docs/content/advanced/backend/subscribers/create-subscriber.md b/docs/content/development/events/create-subscriber.md similarity index 79% rename from docs/content/advanced/backend/subscribers/create-subscriber.md rename to docs/content/development/events/create-subscriber.md index 0dc3e6d8b95d8..5d6f29487205a 100644 --- a/docs/content/advanced/backend/subscribers/create-subscriber.md +++ b/docs/content/development/events/create-subscriber.md @@ -1,17 +1,17 @@ --- -description: 'Learn how to create a subscriber in the Medusa server. You can use subscribers to implement functionalities like sending an order confirmation email.' +description: 'Learn how to create a subscriber in Medusa. You can use subscribers to implement functionalities like sending an order confirmation email.' addHowToData: true --- # How to Create a Subscriber -In this document, you’ll learn how to create a [Subscriber](overview.md) in your Medusa server that listens to events to perform an action. +In this document, you’ll learn how to create a [Subscriber](./subscribers.mdx) in Medusa that listens to events to perform an action. ## Prerequisites Medusa's event system works by pushing data to a Queue that each handler then gets notified of. The queuing system is based on Redis, so it's required for subscribers to work. -You can learn how to [install Redis](../../../tutorial/0-set-up-your-development-environment.mdx#redis) and [configure it with Medusa](../../../usage/configurations.md#redis) before you get started. +You can learn how to [install Redis](../backend/prepare-environment.mdx#redis) and [configure it with Medusa](../backend/configurations.md#redis) before you get started. --- @@ -60,7 +60,10 @@ class OrderNotifierSubscriber { constructor({ productService, eventBusService }) { this.productService = productService - eventBusService.subscribe("order.placed", this.handleOrder) + eventBusService.subscribe( + "order.placed", + this.handleOrder + ) } // ... } @@ -88,5 +91,4 @@ When using attributes defined in the subscriber, such as the `productService` in ## See Also -- [Events reference](events-list.md) -- [Create a Service](../services/create-service) +- [Create a Plugin](../plugins/create.md) \ No newline at end of file diff --git a/docs/content/advanced/backend/subscribers/events-list.md b/docs/content/development/events/events-list.md similarity index 94% rename from docs/content/advanced/backend/subscribers/events-list.md rename to docs/content/development/events/events-list.md index 165b7184ffac8..5556e0c966cf9 100644 --- a/docs/content/advanced/backend/subscribers/events-list.md +++ b/docs/content/development/events/events-list.md @@ -8,7 +8,7 @@ This document details all events in Medusa, when they are triggered, and what da ## Prerequisites -It is assumed you’re already familiar with [Subscribers in Medusa and how to listen to events](create-subscriber.md). You can then use the name of events from this documentation in your subscriber to listen to events. +It is assumed you’re already familiar with [Subscribers in Medusa and how to listen to events](./create-subscriber.md). You can then use the name of events from this documentation in your subscriber to listen to events. --- @@ -1761,7 +1761,7 @@ Triggered when a payment is created. -The entire payment passed as an object. You can refer to the [Payment entity](../../../references/entities/classes/Payment.md) for an idea of what fields to expect. +The entire payment passed as an object. You can refer to the [Payment entity](../../references/entities/classes/Payment.md) for an idea of what fields to expect. @@ -1779,7 +1779,7 @@ Triggered when a payment is updated. -The entire payment passed as an object. You can refer to the [Payment entity](../../../references/entities/classes/Payment.md) for an idea of what fields to expect. +The entire payment passed as an object. You can refer to the [Payment entity](../../references/entities/classes/Payment.md) for an idea of what fields to expect. @@ -1797,7 +1797,7 @@ Triggered when a payment is captured. -The entire payment passed as an object. You can refer to the [Payment entity](../../../references/entities/classes/Payment.md) for an idea of what fields to expect. +The entire payment passed as an object. You can refer to the [Payment entity](../../references/entities/classes/Payment.md) for an idea of what fields to expect. @@ -1815,7 +1815,7 @@ Triggered when the capturing of a payment fails. -The entire payment passed as an object. You can refer to the [Payment entity](../../../references/entities/classes/Payment.md) for an idea of what fields to expect. +The entire payment passed as an object. You can refer to the [Payment entity](../../references/entities/classes/Payment.md) for an idea of what fields to expect. In addition, an error object is passed within the same object as the Payment provider: @@ -1847,7 +1847,7 @@ Triggered when a refund of a payment is created. -The entire refund passed as an object. You can refer to the [Refund entity](../../../references/entities/classes/Refund.md) for an idea of what fields to expect. +The entire refund passed as an object. You can refer to the [Refund entity](../../references/entities/classes/Refund.md) for an idea of what fields to expect. @@ -1865,7 +1865,7 @@ Triggered when a payment's refund fails. -The entire payment passed as an object. You can refer to the [Payment entity](../../../references/entities/classes/Payment.md) for an idea of what fields to expect. +The entire payment passed as an object. You can refer to the [Payment entity](../../references/entities/classes/Payment.md) for an idea of what fields to expect. @@ -1908,7 +1908,7 @@ Triggered when a payment collection is created. -The entire payment collection passed as an object. You can refer to the [Payment Collection entity](../../../references/entities/classes/PaymentCollection.md) for an idea of what fields to expect. +The entire payment collection passed as an object. You can refer to the [Payment Collection entity](../../references/entities/classes/PaymentCollection.md) for an idea of what fields to expect. @@ -1926,7 +1926,7 @@ Triggered when a payment collection is update. -The entire payment collection passed as an object. You can refer to the [Payment Collection entity](../../../references/entities/classes/PaymentCollection.md) for an idea of what fields to expect. +The entire payment collection passed as an object. You can refer to the [Payment Collection entity](../../references/entities/classes/PaymentCollection.md) for an idea of what fields to expect. @@ -1944,7 +1944,7 @@ Triggered when a payment collection is deleted. -The entire payment collection passed as an object. You can refer to the [Payment Collection entity](../../../references/entities/classes/PaymentCollection.md) for an idea of what fields to expect. +The entire payment collection passed as an object. You can refer to the [Payment Collection entity](../../references/entities/classes/PaymentCollection.md) for an idea of what fields to expect. @@ -1962,7 +1962,7 @@ Triggered when a payment collection is either marked authorized or its payment s -The entire payment collection passed as an object. You can refer to the [Payment Collection entity](../../../references/entities/classes/PaymentCollection.md) for an idea of what fields to expect. +The entire payment collection passed as an object. You can refer to the [Payment Collection entity](../../references/entities/classes/PaymentCollection.md) for an idea of what fields to expect. @@ -2029,7 +2029,7 @@ Triggered when a product and data associated with it (options, variant orders, e -The entire product passed as an object. You can refer to the [Product entity](../../../references/entities/classes/Product.md) for an idea of what fields to expect. +The entire product passed as an object. You can refer to the [Product entity](../../references/entities/classes/Product.md) for an idea of what fields to expect. In one case, when the `/admin/products/{id}` endpoint is used to update the product, the payload is an object of the following format: @@ -2442,17 +2442,6 @@ Object of the following format: This section holds all events related to sales channels. -:::note - -As of Medusa v1.3.5, Sales Channels are available but guarded by a feature flag. To use Sales Channels either: - -1. Enable the `MEDUSA_FF_SALES_CHANNELS` environment variable; -2. Or enable the `sales_channels` key in the Medusa server's settings. - -You can learn more about enabling it in the [feature flags](../feature-flags/toggle.md) documentation. - -::: - @@ -2969,6 +2958,6 @@ Object of the following format: ## See Also -- [Events architecture overview](../events/architecture.md) -- [Use services in subscribers](create-subscriber.md#using-services-in-subscribers) -- [Create a notification provider](../notification/overview.md) +- [Events architecture overview](./index.md) +- [Use services in subscribers](./create-subscriber.md#using-services-in-subscribers) +- [Create a notification provider](../notification/overview.mdx) diff --git a/docs/content/advanced/backend/events/architecture.md b/docs/content/development/events/index.md similarity index 88% rename from docs/content/advanced/backend/events/architecture.md rename to docs/content/development/events/index.md index 8714d1a0f5163..428112c402958 100644 --- a/docs/content/advanced/backend/events/architecture.md +++ b/docs/content/development/events/index.md @@ -14,7 +14,7 @@ Those events can be subscribed to using subscribers. When you subscribe to an ev :::info -You can learn more about subscribers and their use cases in the [Subscribers](../subscribers/overview.md) documentation. +You can learn more about subscribers and their use cases in the [Subscribers](./subscribers.mdx) documentation. ::: @@ -48,7 +48,8 @@ export default class EventBusService { async emit( eventName: string, data: T, - options: Record & EmitOptions = { attempts: 1 } + options: Record & + EmitOptions = { attempts: 1 } ): Promise } ``` @@ -111,7 +112,7 @@ In the constructor of a subscriber, you use the `EventBusService` to subscribe t :::note -You can learn more about how to create a subscriber in [this documentation](../subscribers/create-subscriber.md) +You can learn more about how to create a subscriber in [this documentation](./create-subscriber.md) ::: @@ -154,7 +155,7 @@ Here's what each of these options mean: ### Note on Subscriber IDs -If you have more than one handler methods attached to a single event, or if you have multiple server instances running, you must pass a subscriber ID as a third parameter to the `subscribe` method. This allows the `EventBusService` to differentiate between handler methods when retrying a failed one. +If you have more than one handler methods attached to a single event, or if you have multiple backend instances running, you must pass a subscriber ID as a third parameter to the `subscribe` method. This allows the `EventBusService` to differentiate between handler methods when retrying a failed one. If a subscriber ID is not passed on subscription, all handler methods are run again. This can lead to data inconsistencies or general unwanted behavior in your system. @@ -196,7 +197,7 @@ Transactions in Medusa ensure atomicity, consistency, isolation, and durability, -In many cases, [services](../services/overview.md) typically update resources in the database and emit an event within a transactional operation. To ensure that these events don't cause data inconsistencies (for example, a plugin subscribes to an event to contact a third-party service, but the transaction fails) the concept of a staged job is introduced. +In many cases, [services](../services/overview.mdx) typically update resources in the database and emit an event within a transactional operation. To ensure that these events don't cause data inconsistencies (for example, a plugin subscribes to an event to contact a third-party service, but the transaction fails) the concept of a staged job is introduced. Instead of events being processed immediately, they're stored in the database as a staged job until they're ready. In other words, until the transaction has succeeded. @@ -222,6 +223,5 @@ This pattern is heavily inspired by the [Transactionally-staged Job Drain descri ## See Also -- [Events reference](../subscribers/events-list.md) -- [Subscribers overview](../subscribers/overview.md) -- [How to create a subscriber](../subscribers/create-subscriber.md) \ No newline at end of file +- [Events reference](./events-list.md) +- [Create a subscriber](./create-subscriber.md) \ No newline at end of file diff --git a/docs/content/advanced/backend/subscribers/overview.md b/docs/content/development/events/subscribers.mdx similarity index 75% rename from docs/content/advanced/backend/subscribers/overview.md rename to docs/content/development/events/subscribers.mdx index 97b4355981cf3..5d8dec00f48e7 100644 --- a/docs/content/advanced/backend/subscribers/overview.md +++ b/docs/content/development/events/subscribers.mdx @@ -1,7 +1,10 @@ --- -description: 'Learn what subscribers are in the Medusa server. Subscribers are used to listen to triggered events to perform an action.' +description: 'Learn what subscribers are in Medusa. Subscribers are used to listen to triggered events to perform an action.' --- +import DocCard from '@theme/DocCard'; +import Icons from '@theme/Icon'; + # Subscribers In this document, you'll learn what Subscribers are in Medusa. @@ -12,7 +15,7 @@ In Medusa, there are events that are emitted when a certain action occurs. For e The purpose of these events is to allow other parts of the platform, or third-party integrations, to listen to those events and perform a certain action. That is done by creating subscribers. -Medusa's queuing and events system is handled by Redis. So, you must have [Redis configured](../../../tutorial/0-set-up-your-development-environment.mdx#redis) on your server to use subscribers. +Medusa's queuing and events system is handled by Redis. So, you must have [Redis configured](../backend/prepare-environment.mdx#redis) on your backend to use subscribers. --- @@ -36,8 +39,17 @@ Subscribers are useful in many use cases, including: --- -## See Also +## Custom Development + +Developers can create custom subscribers in the Medusa backend, a plugin, or in a Commerce Module. -- [Create a Subscriber](create-subscriber.md). -- [Events architecture overview](../events/architecture.md) -- [Events reference](events-list.md). + diff --git a/docs/content/development/feature-flags/overview.mdx b/docs/content/development/feature-flags/overview.mdx new file mode 100644 index 0000000000000..f44e290eb3a6f --- /dev/null +++ b/docs/content/development/feature-flags/overview.mdx @@ -0,0 +1,28 @@ +--- +description: "Learn what feature flags in Medusa. Feature flags are used in Medusa to guard beta features that aren’t ready for live and production applications." +--- + +import DocCard from '@theme/DocCard'; +import Icons from '@theme/Icon'; + +# Feature Flags + +In this document, you’ll learn what feature flags in Medusa. + +## Introduction + +Feature flags are used in Medusa to guard beta features that aren’t ready for live and production applications. This allows the Medusa team to keep publishing releases more frequently, while also working on necessary future features behind the scenes. To use these beta features, you must enable their feature flags. + +If a feature is guarded by a flag, entities, migrations, endpoints, and other resources associated with that feature are guarded by that flag as well. So, these resources will only be available to use in Medusa if you have enabled the associated feature flag. + +You can view a list of available feature flags that you can toggle in [the Medusa GitHub mono-repository](https://github.com/medusajs/medusa/tree/master/packages/medusa/src/loaders/feature-flags). In each feature flag file, you can find the default value of the feature flag, its name, environment variable name, and more. + + \ No newline at end of file diff --git a/docs/content/advanced/backend/feature-flags/toggle.md b/docs/content/development/feature-flags/toggle.md similarity index 55% rename from docs/content/advanced/backend/feature-flags/toggle.md rename to docs/content/development/feature-flags/toggle.md index ea371b9a78fa8..92133e001a3e7 100644 --- a/docs/content/advanced/backend/feature-flags/toggle.md +++ b/docs/content/development/feature-flags/toggle.md @@ -1,23 +1,11 @@ --- -description: 'Learn how to toggle feature flags in the Medusa server. This guide explains the steps required to toggle a feature flag.' +description: 'Learn how to toggle feature flags in Medusa. This guide explains the steps required to toggle a feature flag.' addHowToData: true --- # How to Toggle Feature Flags -In this document, you’ll learn about what feature flags are and how to toggle them. - -## Overview - -Feature flags are used in Medusa to guard beta features that aren’t ready for live and production servers. This allows the Medusa team to keep publishing releases more frequently, while also working on necessary future features behind the scenes. - -To use these beta features, you must enable their feature flags. - ---- - -## Available Feature Flags - -You can view a list of available feature flags that you can toggle in [the Medusa GitHub mono-repository](https://github.com/medusajs/medusa/tree/master/packages/medusa/src/loaders/feature-flags). In each feature flag file, you can find the default value of the feature flag, its name, environment variable name, and more. +In this document, you’ll learn about how to toggle feature flags. :::info @@ -25,8 +13,6 @@ If a feature flag is enabled/disabled by default, you don’t need to manually e ::: ---- - ## Enable Feature Flags :::caution @@ -47,9 +33,9 @@ For example, to enable the Tax-Inclusive Pricing beta feature, add the following MEDUSA_FF_TAX_INCLUSIVE_PRICING=true ``` -### Method Two: Using Server Settings +### Method Two: Using Backend Configurations -You can enable a feature by using the server settings in `medusa-config.js`. You can find [a feature flag’s key in the loader file](https://github.com/medusajs/medusa/tree/master/packages/medusa/src/loaders/feature-flags) it’s defined in. It is defined under the property `key` in the exported object. +You can enable a feature by using the backend configurations in `medusa-config.js`. You can find [a feature flag’s key in the loader file](https://github.com/medusajs/medusa/tree/master/packages/medusa/src/loaders/feature-flags) it’s defined in. It is defined under the property `key` in the exported object. For example, to enable the Tax-Inclusive Pricing beta feature, add the following to the exported object in `medusa-config.js`: @@ -64,9 +50,9 @@ module.exports = { ### Note About Precedence -The environment variable’s value has higher precedence over the server settings. So, if you use both these methods on your server, the value of the environment variable will be used. +The environment variable’s value has higher precedence over the backend configurations. So, if you use both these methods on your backend, the value of the environment variable will be used. -For example, if the value of the environment variable is set to `false`, but the value of the feature flag in the server settings is set to `true`, the feature flag will take the value of the environment variable and will be disabled. +For example, if the value of the environment variable is set to `false`, but the value of the feature flag in the backend configurations is set to `true`, the feature flag will take the value of the environment variable and will be disabled. ### Running Migrations @@ -86,7 +72,7 @@ You can learn more about migrations in this documentation. ## Disable Feature Flags -Disabling feature flags follows the same process as enabling the feature flags. All you have to do is change the value in the environment variables or the server settings to `false`. +Disabling feature flags follows the same process as enabling the feature flags. All you have to do is change the value in the environment variables or the backend configurations to `false`. Once you disable a feature flag, all endpoints, entities, services, or other related classes and functionalities are disabled. @@ -94,11 +80,4 @@ Once you disable a feature flag, all endpoints, entities, services, or other rel If you had the feature flag previously enabled, and you want to disable this feature flag completely, you might need to revert the migrations you ran when you enabled it. -You can follow [this documentation to learn how to revert the last migration you ran](https://docs.medusajs.com/cli/reference#migrations). - ---- - -## See Also - -- [Migrations Overview](../migrations/overview.md). -- [Configure your Medusa server](../../../usage/configurations.md). +You can follow [this documentation to learn how to revert the last migration you ran](../../cli/reference.md#migrations). \ No newline at end of file diff --git a/docs/content/development/file-service/overview.mdx b/docs/content/development/file-service/overview.mdx new file mode 100644 index 0000000000000..4ea5b6b05bd2d --- /dev/null +++ b/docs/content/development/file-service/overview.mdx @@ -0,0 +1,35 @@ +--- +description: "Learn what a file service is in Medusa. A file service defines how files are stored in the Medusa Backend." +--- + +import DocCard from '@theme/DocCard'; +import Icons from '@theme/Icon'; + +# File Service + +In this document, you’ll learn what a file service is in Medusa. + +## Introduction + +A file service defines how files are stored in the Medusa Backend. Those files include products’ images and files used to import or export data. + +Medusa Backend includes a default file service that acts as a placeholder, but does not actually perform any storage functionalities. So, you must either install one of the [existing file-service plugins](../../plugins/file-service/index.mdx), such as [MinIO](../../plugins/file-service/minio.md) or [S3](../../plugins/file-service/s3.md), or create your own file service if you want to utilize storage functionalities. + +A file service is a TypeScript or JavaScript class that extends the `AbstractFileService` class from the core `@medusajs/medusa` package. By extending this class, the file service must implement the necessary methods that take care of general upload and download functionalities. The Medusa Backend then uses these methods when necessary, for example, when a product image is uploaded. + +--- + +## Custom Development + +Developers can create a custom file service with the desired functionality directly within the Medusa Core, in a plugin, or in a Commerce Module. + + \ No newline at end of file diff --git a/docs/content/development/fundamentals/architecture-overview.md b/docs/content/development/fundamentals/architecture-overview.md new file mode 100644 index 0000000000000..a710d5a4004f7 --- /dev/null +++ b/docs/content/development/fundamentals/architecture-overview.md @@ -0,0 +1,27 @@ +--- +description: "Learn about Medusa's architecture and get a general overview of how all different tools work together." +--- + +# Medusa Architecture Overview + +In this document, you'll get an overview of Medusa's architecture to better understand how all resources and tools work together. + +## Architecture Overview + +Medusa's core package `@medusajs/medusa` is a Node.js backend built on top of [Express](https://expressjs.com/). It combines all the [**Commerce Modules**](../../modules/overview.mdx) that Medusa provides. Commerce Modules are ecommerce features that can be used as building blocks in an ecommerce ecosystem. Product is an example of a Commerce Module. + +![Medusa Core Architecture](https://res.cloudinary.com/dza7lstvk/image/upload/v1677607702/Medusa%20Docs/Diagrams/medusa-architecture-3_e385zk.jpg) + +The backend connects to a **database**, such as [PostgreSQL](https://www.postgresql.org/), to store the ecommerce store’s data. The tables in that database are represented by [**Entities**](../entities/overview.mdx), built on top of [Typeorm](https://typeorm.io/). Entities can also be reflected in the database using [**Migrations**](../entities/migrations/overview.mdx). + +The retrieval, manipulation, and other utility methods related to that entity are created inside a [**Service**](../services/overview.mdx). Services are TypeScript or JavaScript classes that, similar along with other resources, can be accessed throughout the Medusa backend through [**dependency injection**](./dependency-injection.md). + +The backend does not have any tightly-coupled frontend. Instead, it exposes [**Endpoints**](../endpoints/overview.mdx) which are REST APIs that frontends such as an admin or a storefront can use to communicate with the backend. Endpoints are [Express routes](https://expressjs.com/en/guide/routing.html). + +Medusa also uses an [**Events Architecture**](../events/index.md) to trigger and handle events. Events are triggered when a specific action occurs, such as when an order is placed. To manage this events system, Medusa connects to a service that implements a pub/sub model, such as [Redis](https://redis.io/). + +Events can be handled using [**Subscribers**](../events/subscribers.mdx). Subscribers are TypeScript or JavaScript classes that add their methods as handlers for specific events. These handler methods are only executed when an event is triggered. + +You can create any of the resources in the backend’s architecture, such as entities, endpoints, services, and more, as part of your custom development without directly modifying the backend itself. The Medusa backend uses **loaders** to load the backend’s resources, as well as your custom resources and resources in [**Plugins**](../plugins/overview.mdx). + +You can package your customizations into Plugins to reuse them in different Medusa backends or publish them for others to use. You can also install existing plugins into your Medusa backend. \ No newline at end of file diff --git a/docs/content/advanced/backend/dependency-container/index.md b/docs/content/development/fundamentals/dependency-injection.md similarity index 89% rename from docs/content/advanced/backend/dependency-container/index.md rename to docs/content/development/fundamentals/dependency-injection.md index 379821d342ac7..b33267448f098 100644 --- a/docs/content/advanced/backend/dependency-container/index.md +++ b/docs/content/development/fundamentals/dependency-injection.md @@ -2,9 +2,9 @@ description: 'Learn what the dependency container is and how to use it in Medusa. Learn also what dependency injection is, and what the resources regsitered and their names are.' --- -# Dependency Container +# Dependency Injection -In this document, you’ll learn what the dependency container is and how you can use it in Medusa. +In this document, you’ll learn what the dependency injection is and how you can use it in Medusa. ## Introduction @@ -16,25 +16,25 @@ Generally, all resources are registered in a container. Then, whenever a class d ### Medusa’s Dependency Container -Medusa uses a dependency container to register essential resources of your server. You can then access these resources in classes and endpoints using the dependency container. +Medusa uses a dependency container to register essential resources of the backend. You can then access these resources in classes and endpoints using the dependency container. -For example, if you create a custom service, you can access any other service registered in Medusa in your service’s constructor. That includes Medusa’s core services, services defined in plugins, or other services that you create on your server. +For example, if you create a custom service, you can access any other service registered in Medusa in your service’s constructor. That includes Medusa’s core services, services defined in plugins, or other services that you create on your backend. -You can load more than services in your Medusa server. You can load the Entity Manager, logger instance, and much more. +You can load more than services in your Medusa backend. You can load the Entity Manager, logger instance, and much more. ### MedusaContainer To manage dependency injections, Medusa uses [Awilix](https://github.com/jeffijoe/awilix). Awilix is an NPM package that implements dependency injection in Node.js projects. -When you run the Medusa server, a container of the type `MedusaContainer` is created. This type extends the [AwilixContainer](https://github.com/jeffijoe/awilix#the-awilixcontainer-object) object. +When you run the Medusa backend, a container of the type `MedusaContainer` is created. This type extends the [AwilixContainer](https://github.com/jeffijoe/awilix#the-awilixcontainer-object) object. -The server then registers all important resources in the container, which makes them accessible in classes and endpoints. +The backend then registers all important resources in the container, which makes them accessible in classes and endpoints. --- ## Registered Resources -The Medusa server scans the core Medusa package, plugins, and your files in the `dist` directory and registers the following resources: +The Medusa backend scans the core Medusa package, plugins, and your files in the `dist` directory and registers the following resources: :::note @@ -72,7 +72,7 @@ Configurations
-The configurations that are exported from medusa-config.js. +The configurations that are exported from `medusa-config.js`. @@ -560,7 +560,7 @@ Its camel-case name. ## Loading Resources -This section covers how to load resources that the Medusa server registers when it starts running. +This section covers how to load resources that the Medusa backend registers when it starts running. ### In Endpoints @@ -596,5 +596,5 @@ class OrderSubscriber { ## See Also -- [Create services](../services/create-service.md). -- [Create subscribers](../subscribers/create-subscriber.md). +- [Create services](../services/create-service.md) +- [Create subscribers](../events/create-subscriber.md) diff --git a/docs/content/usage/local-development.md b/docs/content/development/fundamentals/local-development.md similarity index 86% rename from docs/content/usage/local-development.md rename to docs/content/development/fundamentals/local-development.md index f47a2b2551e1a..f379d3a290656 100644 --- a/docs/content/usage/local-development.md +++ b/docs/content/development/fundamentals/local-development.md @@ -2,7 +2,7 @@ description: 'Learn how to perform local development in the Medusa monorepo. This includes how to use the dev CLI tool and perform unit, integration, and plugin tests.' --- -# Local Development of Medusa Server and Monorepo +# Local Development of Medusa Backend and Monorepo In this document, you’ll learn how to customize Medusa’s core and run tests. @@ -10,11 +10,11 @@ In this document, you’ll learn how to customize Medusa’s core and run tests. As an open-source platform, Medusa’s core can be completely customized. -Whether you want to implement something differently, introduce a new future as part of Medusa’s core or any of the other packages, or contribute to Medusa, this guide helps you learn how to run Medusa’s integration tests, as well as test your own Medusa core in a local server. +Whether you want to implement something differently, introduce a new future as part of Medusa’s core or any of the other packages, or contribute to Medusa, this guide helps you learn how to run Medusa’s integration tests, as well as test your own Medusa core in a local backend. ### Medusa Repository Overview -[Medusa’s repository on GitHub](https://github.com/medusajs/medusa) includes all packages related to Medusa under the [`packages` directory](https://github.com/medusajs/medusa/tree/master/packages). This includes the [core Medusa server](https://github.com/medusajs/medusa/tree/master/packages/medusa), the [JS Client](https://github.com/medusajs/medusa/tree/master/packages/medusa-js), the CLI tools, and much more. +[Medusa’s repository on GitHub](https://github.com/medusajs/medusa) includes all packages related to Medusa under the [`packages` directory](https://github.com/medusajs/medusa/tree/master/packages). This includes the [core Medusa package](https://github.com/medusajs/medusa/tree/master/packages/medusa), the [JS Client](https://github.com/medusajs/medusa/tree/master/packages/medusa-js), the CLI tools, and much more. All the packages are part of a [Yarn workspace](https://classic.yarnpkg.com/lang/en/docs/workspaces/). So, when you run a command in the root of the project, such as `yarn build`, it goes through all registered packages in the workspace under the `packages` directory and runs the `build` command in each of those packages. @@ -114,11 +114,11 @@ yarn test:integration:plugins --- -## Test in a Local Server +## Test in a Local Backend -Using Medusa’s dev CLI tool, you can test any changes you make to Medusa’s packages in a local server installation. This eliminates the need to publish these packages on NPM publicly to be able to use them. +Using Medusa’s dev CLI tool, you can test any changes you make to Medusa’s packages in a local backend installation. This eliminates the need to publish these packages on NPM publicly to be able to use them. -Medusa’s dev CLI tool scans and finds the Medusa packages used in your Medusa server. Then, it copies the files of these packages from the `packages` directory in the Medusa repository into the `node_modules` directory of your Medusa server. +Medusa’s dev CLI tool scans and finds the Medusa packages used in your Medusa backend. Then, it copies the files of these packages from the `packages` directory in the Medusa repository into the `node_modules` directory of your Medusa backend. :::info @@ -126,14 +126,14 @@ Medusa’s Dev CLI tool uses the [path you specified earlier](#set-the-location- ::: -### Copy Files to Local Server +### Copy Files to Local Backend -To test in a local server: +To test in a local backend: -1. Change to the directory of the server you want to test your changes in: +1. Change to the directory of the backend you want to test your changes in: ```bash -cd medusa-server +cd medusa-backend ``` 2\. Run the following command to copy the files from the `packages` directory of your Medusa repository into `node_modules`: @@ -148,7 +148,7 @@ By default, Medusa’s dev CLI runs in watch mode. So, it copies the files when While the above command is running, it's recommended to run the `watch` command inside the directory of every package you're making changes to. -The combination of these two commands running at the same time will compile the package into the `dist` directory of the package, then copy the compiled changes into your local server. +The combination of these two commands running at the same time will compile the package into the `dist` directory of the package, then copy the compiled changes into your local backend. For example, if you're making changes in the `medusa` package, run the following command inside the directory of the `medusa` package: @@ -190,5 +190,5 @@ medusa-dev --packages @medusajs/medusa-cli medusa-file-minio ## See Also -- [Create a Plugin](../advanced/backend/plugins/create.md) +- [Create a Plugin](../plugins/create.md) - [Contribution Guidelines](https://github.com/medusajs/medusa/blob/master/CONTRIBUTING.md) diff --git a/docs/content/advanced/backend/notification/how-to-create-notification-provider.md b/docs/content/development/notification/create-notification-provider.md similarity index 73% rename from docs/content/advanced/backend/notification/how-to-create-notification-provider.md rename to docs/content/development/notification/create-notification-provider.md index fc0c51d30326c..c072f30c475d2 100644 --- a/docs/content/advanced/backend/notification/how-to-create-notification-provider.md +++ b/docs/content/development/notification/create-notification-provider.md @@ -1,23 +1,23 @@ --- -description: 'Learn how to create a notification provider in the Medusa server. This guide explains the different methods available in a Notification provider.' +description: 'Learn how to create a notification provider in Medusa. This guide explains the different methods available in a Notification provider.' addHowToData: true --- # How to Create a Notification Provider -In this document, you’ll learn how to add a Notification Provider to your Medusa server. +In this document, you’ll learn how to create a Notification Provider in Medusa. :::note -If you’re unfamiliar with the Notification architecture in Medusa, it is recommended to check out the [architecture overview](overview.md) first. +If you’re unfamiliar with the Notification architecture in Medusa, it is recommended to check out the [architecture overview](./overview.mdx) first. ::: ## Prerequisites -Before you start creating a Notification Provider, you need to install a [Medusa server](../../../quickstart/quick-start.mdx). +Before you start creating a Notification Provider, you need to either install a [Medusa backend](../backend/install.mdx), or create it in a [plugin](../plugins/overview.mdx). -You also need to [setup Redis](../../../tutorial/0-set-up-your-development-environment.mdx#redis) and [configure it with the Medusa server](../../../usage/configurations.md#redis). +You also need to [setup Redis](../backend/prepare-environment.mdx#redis) and [configure it with the Medusa backend](../backend/configurations.md#redis) to test out the Notification provider. --- @@ -96,15 +96,15 @@ You can use the `constructor` of your Notification Provider to have access to You can also use the constructor to initialize your integration with the third-party provider. For example, if you use a client to connect to the third-party provider’s APIs, you can initialize it in the constructor and use it in other methods in the Service. -Additionally, if you’re creating your Notification Provider as an external plugin to be installed on any Medusa server and you want to access the options added for the plugin, you can access it in the constructor. The options are passed as a second parameter. +Additionally, if you’re creating your Notification Provider as an external plugin to be installed on any Medusa backend and you want to access the options added for the plugin, you can access it in the constructor. The options are passed as a second parameter. :::info -You can learn more about plugins and how to create them in the [Plugins](../plugins/overview.md) documentation. +You can learn more about plugins and how to create them in the [Plugins](../plugins/overview.mdx) documentation. ::: -Continuing on with the previous example, if you want to use the [`OrderService`](../../../references/services/classes/OrderService.md) later when sending notifications, you can inject it into the constructor: +Continuing on with the previous example, if you want to use the [`OrderService`](../../references/services/classes/OrderService.md) later when sending notifications, you can inject it into the constructor: ```ts import { @@ -132,7 +132,7 @@ class EmailSenderService extends AbstractNotificationService { ### sendNotification -When an event is triggered that your Notification Provider is registered as a handler for, the [`NotificationService`](../../../references/services/classes/NotificationService.md) in Medusa’s core will execute the `sendNotification` method of your Notification Provider. +When an event is triggered that your Notification Provider is registered as a handler for, the [`NotificationService`](../../references/services/classes/NotificationService.md) in Medusa’s core will execute the `sendNotification` method of your Notification Provider. In this method, you can perform the necessary operation to send the Notification. Following the example above, you can send an email to the customer when they place an order. @@ -140,11 +140,11 @@ This method receives three parameters: 1. `eventName`: This is the name of the event that was triggered. For example, `order.placed`. 2. `eventData`: This is the data payload of the event that was triggered. For example, if the `order.placed` event is triggered, the `eventData` object contains the property `id` which is the ID of the order that was placed. -3. `attachmentGenerator`: If you’ve previously attached a generator to the `NotificationService` using the [`registerAttachmentGenerator`](../../../references/services/classes/NotificationService.md#registerattachmentgenerator) method, you have access to it here. You can use the `attachmentGenerator` to generate on-demand invoices or other documents. The default value of this parameter is null. +3. `attachmentGenerator`: If you’ve previously attached a generator to the `NotificationService` using the [`registerAttachmentGenerator`](../../references/services/classes/NotificationService.md#registerattachmentgenerator) method, you have access to it here. You can use the `attachmentGenerator` to generate on-demand invoices or other documents. The default value of this parameter is null. :::info -You can learn more about what events are triggered in Medusa and their data payload in the [Events List](../subscribers/events-list.md) documentation. +You can learn more about what events are triggered in Medusa and their data payload in the [Events List](../events/events-list.md) documentation. ::: @@ -196,19 +196,19 @@ Finally, you return an object with the `to` property set to the customer email a :::note -The `to` and `data` properties are used in the `NotificationService` in Medusa’s core to create a new `Notification` record in the database. You can learn more about the `Notification` entity in the [Architecture Overview](overview.md#notification-entity-overview) documentation. +The `to` and `data` properties are used in the `NotificationService` in Medusa’s core to create a new `Notification` record in the database. You can learn more about the `Notification` entity in the [Architecture Overview](./overview.mdx#notification-entity-overview) documentation. ::: ### resendNotification -Using the [Resend Notification endpoint](https://docs.medusajs.com/api/admin/#tag/Notification/operation/PostNotificationsNotificationResend), an admin user can resend a Notification to the customer. The [`NotificationService`](../../../references/services/classes/NotificationService.md) in Medusa’s core then executes the `resendNotification` method in your Notification Provider. +Using the [Resend Notification endpoint](/api/admin/#tag/Notification/operation/PostNotificationsNotificationResend), an admin user can resend a Notification to the customer. The [`NotificationService`](../../references/services/classes/NotificationService.md) in Medusa’s core then executes the `resendNotification` method in your Notification Provider. This method receives three parameters: -1. `notification`: This is the original Notification record that was created after you sent the notification with `sendNotification`. You can get an overview of the entity and its attributes in the [architecture overview](overview.md#notification-entity-overview), but most notably it includes the `to` and `data` attributes which are populated originally using the `to` and `data` properties of the object you return in `sendNotification`. +1. `notification`: This is the original Notification record that was created after you sent the notification with `sendNotification`. You can get an overview of the entity and its attributes in the [architecture overview](./overview.mdx#notification-entity-overview), but most notably it includes the `to` and `data` attributes which are populated originally using the `to` and `data` properties of the object you return in `sendNotification`. 2. `config`: In the Resend Notification endpoint you may specify an alternative receiver of the notification using the `to` request body parameter. For example, you may want to resend the order confirmation email to a different email. If that’s the case, you have access to it in the `config` parameter object. Otherwise, `config` will be an empty object. -3. `attachmentGenerator`: If you’ve previously attached a generator to the Notification Service using the [`registerAttachmentGenerator`](../../../references/services/classes/NotificationService.md#registerattachmentgenerator) method, you have access to it here. You can use the `attachmentGenerator` to generate on-demand invoices or other documents. The default value of this parameter is null. +3. `attachmentGenerator`: If you’ve previously attached a generator to the Notification Service using the [`registerAttachmentGenerator`](../../references/services/classes/NotificationService.md#registerattachmentgenerator) method, you have access to it here. You can use the `attachmentGenerator` to generate on-demand invoices or other documents. The default value of this parameter is null. Similarly to the `sendNotification` method, this method must return an object containing two properties: @@ -229,7 +229,7 @@ class EmailSenderService extends AbstractNotificationService { status: string; data: Record; }> { - // check if the receiver of the notification should be changed + // check if the receiver should be changed const to: string = config.to ? config.to : notification.to // TODO resend the notification using the same data @@ -239,7 +239,7 @@ class EmailSenderService extends AbstractNotificationService { return { to, status: "done", - data: notification.data, // you can also make changes to the data + data: notification.data, // make changes to the data } } } @@ -253,7 +253,7 @@ Finally, you return an object with the `to` property set to the email (either ne :::note -The `to` and `data` properties are used in the `NotificationService` in Medusa’s core to create a new `Notification` record in the database. No changes are made to the original `Notification` record created after the `sendNotification` method. This new record is associated with the original `Notification` record using the `parent_id` attribute in the entity. You can learn more about the `Notification` entity in the [Architecture Overview](overview.md#notification-entity-overview) documentation. +The `to` and `data` properties are used in the `NotificationService` in Medusa’s core to create a new `Notification` record in the database. No changes are made to the original `Notification` record created after the `sendNotification` method. This new record is associated with the original `Notification` record using the `parent_id` attribute in the entity. You can learn more about the `Notification` entity in the [Architecture Overview](./overview.mdx#notification-entity-overview) documentation. ::: @@ -265,7 +265,7 @@ After creating your Notification Provider Service, you must create a Subscriber :::note -This section will not cover the basics of Subscribers. You can read the [Subscribers](../subscribers/create-subscriber.md) documentation to learn more about them and how to create them. +This section will not cover the basics of Subscribers. You can read the [Subscribers](../events/create-subscriber.md) documentation to learn more about them and how to create them. ::: @@ -274,7 +274,10 @@ Following the previous example, to make sure the `email-sender` Notification Pro ```ts title=src/subscribers/notification.js class NotificationSubscriber { constructor({ notificationService }) { - notificationService.subscribe("order.placed", "email-sender") + notificationService.subscribe( + "order.placed", + "email-sender" + ) } // ... } @@ -294,19 +297,19 @@ Notice that the value of the `identifier` static property defined in the `EmailS ## Test Sending Notifications with your Notification Provider -Make sure you've configured Redis with your Medusa server as explained in the Prerequisites section and that the Redis service is running. +Make sure you've configured Redis with your Medusa backend as explained in the [Prerequisites](#prerequisites) section and that the Redis service is running. -Then, start by running your Medusa server: +Then, start by running your Medusa backend: ```bash npm2yarn npm run start ``` -Then, place an order either using the [REST APIs](https://docs.medusajs.com/api/store) or using the storefront. +Then, place an order either using the [REST APIs](/api/store) or using the storefront. :::tip -If you don’t have a storefront installed you can get started with either the [Next.js](../../../starters/nextjs-medusa-starter.mdx) or [Gatsby](../../../starters/gatsby-medusa-starter.mdx) starter storefronts in minutes. +If you don’t have a storefront installed you can get started with the [Next.js](../../starters/nextjs-medusa-starter.mdx) starter storefront in minutes. ::: @@ -316,17 +319,17 @@ After placing an order, you can see in your console the message “Notification ## Test Resending Notifications with your Notification Provider -To test resending a notification, first, retrieve the ID of the notification you just sent using the [List Notifications admin endpoint](https://docs.medusajs.com/api/admin/#tag/Notification/operation/GetNotifications). You can pass as a body parameter the `to` or `event_name` parameters to filter out the notification you just sent. +To test resending a notification, first, retrieve the ID of the notification you just sent using the [List Notifications admin endpoint](/api/admin/#tag/Notification/operation/GetNotifications). You can pass as a body parameter the `to` or `event_name` parameters to filter out the notification you just sent. :::tip -You must be authenticated as an admin user before sending this request. You can use the [Authenticate a User](https://docs.medusajs.com/api/admin) endpoint to get authenticated. +You must be authenticated as an admin user before sending this request. You can use the [Authenticate a User](/api/admin) endpoint to get authenticated. ::: ![List Notifications Request](https://res.cloudinary.com/dza7lstvk/image/upload/v1668001650/Medusa%20Docs/Screenshots/iF1rZX1_msps2t.png) -Then, send a request to the [Resend Notification](https://docs.medusajs.com/api/admin/#tag/Notification/operation/PostNotificationsNotificationResend) endpoint using the ID retrieved from the previous request. You can pass the `to` parameter in the body to change the receiver of the notification. You should see the message “Notification Resent” in your console and if you implemented your own logic for resending the notification it will be resent. +Then, send a request to the [Resend Notification](/api/admin/#tag/Notification/operation/PostNotificationsNotificationResend) endpoint using the ID retrieved from the previous request. You can pass the `to` parameter in the body to change the receiver of the notification. You should see the message “Notification Resent” in your console and if you implemented your own logic for resending the notification it will be resent. ![Resend Notifications Request](https://res.cloudinary.com/dza7lstvk/image/upload/v1668001659/Medusa%20Docs/Screenshots/0zFfPed_og7one.png) @@ -336,8 +339,4 @@ This request returns the same notification object as the List Notifications endp ## See Also -- [Events reference](../subscribers/events-list.md) -- [SendGrid Plugin](../../../add-plugins/sendgrid.mdx) -- [Create a Subscriber](../subscribers/create-subscriber.md) -- [Create a Service](../services/create-service.md) - [Create a Plugin](../plugins/create.md) diff --git a/docs/content/advanced/backend/notification/overview.md b/docs/content/development/notification/overview.mdx similarity index 74% rename from docs/content/advanced/backend/notification/overview.md rename to docs/content/development/notification/overview.mdx index 3481c19ed843c..486551bf401b1 100644 --- a/docs/content/advanced/backend/notification/overview.md +++ b/docs/content/development/notification/overview.mdx @@ -2,6 +2,9 @@ description: 'Learn about the Notificaiton architecture in Medusa and the automation flow. The Notification Architecture is made up of the Notification Provider and Notification.' --- +import DocCard from '@theme/DocCard'; +import Icons from '@theme/Icon'; + # Notification Architecture Overview This document gives an overview of the notification architecture and how it works. @@ -22,11 +25,11 @@ An example of a notification provider is SendGrid. When an order is placed, the ### How Notification Provider is Created -A Notification Provider is essentially a Medusa [Service](../services/create-service.md) with a unique identifier, and it extends the [`NotificationService`](../../../references/services/classes/NotificationService.md) provided by the `medusa-interfaces` package. It can be created as part of a [Plugin](../plugins/overview.md), or it can be created just as a Service file in your Medusa server. +A Notification Provider is essentially a Medusa [Service](../services/create-service.md) with a unique identifier, and it extends the [`NotificationService`](../../references/services/classes/NotificationService.md) provided by the `medusa-interfaces` package. It can be created as part of a [Plugin](../plugins/overview.mdx), or it can be created just as a Service file in your Medusa backend. As a developer, you mainly work with the Notification Provider when integrating a third-party service that handles notifications in Medusa. -When you run your Medusa server, the Notification Provider is registered on your server if it isn’t already. This means that it will be inserted into the `notification_provider` table in your database. +When you run your Medusa backend, the Notification Provider is registered in your backend. If it's a new Notification Provider, it will be inserted into the `notification_provider` table in your database. ### NotificationProvider Entity Overview @@ -55,7 +58,7 @@ A Notification also represents a resent notification. So, when a notification is ### Notification Entity Overview -The two most important properties in the [`Notification`](../../../references/entities/classes/Notification.md) entity are the `to` and `data` properties. +The two most important properties in the [`Notification`](../../references/entities/classes/Notification.md) entity are the `to` and `data` properties. The `to` property is a string that represents the receiver of the Notification. For example, if the Notification was sent to an email address, the `to` property holds the email address the Notification was sent to. @@ -83,17 +86,24 @@ With Medusa you can create notifications as a reaction to a wide spectrum of eve An example of a flow that can be implemented using Medusa's Notification API is automated return flows: -- A customer requests a return by sending a `POST` request to the `/store/returns` endpoint. -- The Notification Provider listens to the `order.return_requested` event and sends an email to the customer with a return invoice and return label generated by the Fulfillment Provider. -- The customer returns the items triggering the `return.recieved` event. -- The Notification Provider listens to the `return.received` event and sends an email to the customer with confirmation that their items have been received and that a refund has been issued. +- A customer requests a return by sending a `POST` request to the `/store/returns` endpoint. +- The Notification Provider listens to the `order.return_requested` event and sends an email to the customer with a return invoice and return label generated by the Fulfillment Provider. +- The customer returns the items triggering the `return.recieved` event. +- The Notification Provider listens to the `return.received` event and sends an email to the customer with confirmation that their items have been received and that a refund has been issued. --- -## See Also +## Custom Development + +Developers can create custom notification providers in the Medusa backend, a plugin, or in a Commerce Module. -- [Create a Notification Provider](how-to-create-notification-provider.md) -- [Events reference](../subscribers/events-list.md) -- [SendGrid Plugin](../../../add-plugins/sendgrid.mdx) -- [Subscribers Overview](../subscribers/create-subscriber.md) -- [Services Overview](../services/create-service.md) + \ No newline at end of file diff --git a/docs/content/development/overview.mdx b/docs/content/development/overview.mdx new file mode 100644 index 0000000000000..843d3019bacef --- /dev/null +++ b/docs/content/development/overview.mdx @@ -0,0 +1,203 @@ +--- +description: "Learn about development with Medusa, fundamental concepts, and more." +hide_table_of_contents: true +--- + +import DocCardList from '@theme/DocCardList'; +import Icons from '@theme/Icon'; + +# Medusa Development + +This part of the documentation provides you with the fundamental concepts and guides that can help you build and customize commerce applications with Medusa. + +## Introduction + +Medusa is a set of tools that developers can use to build digital commerce applications. Whether you want to offer unique customer experiences, create powerful automations, or build rich commerce applications like marketplaces, Medusa provides all the necessary tools. + +Other ecommerce platforms offer a finite set of features accessible through an API. Medusa is different because it provides building blocks for businesses and developers to build commerce features. This means that you can extend your commerce API for your exact needs. + +Medusa's building blocks ship as NPM packages of the following types: + +- [Commerce Modules](../modules/overview.mdx), which are isolated commerce logic for different domains. For example, an Inventory Module. +- A core package responsible for orchestrating the different commerce modules and exposing REST APIs. + +--- + +## How Does Medusa Work + +The core package is the NPM package `@medusajs/medusa`. It's a Node.js server built with Express and other tools that offer functionalities for managing events, caching, job queues, and more. + +The core package has two main objectives. + +### Orchestrate Commerce Modules + +When you build a commerce application with Medusa, you’ll typically interact with more than one commerce module. The core package manages relationships between modules, and forwarding calls to modules at the right time during business logic execution. + +For example, imagine an Inventory module that contains lightweight logic to increment and decrement stock levels for a Stock-Keeping Unit (SKU). In a commerce application, you typically want to associate the stock levels with a specific product. Medusa offers both an Inventory module and a Product module, and the core package creates associations between these modules and executing the related business logic. So, the core package contains code similar to this: + +```ts +function handler(req, res) { + // ... + + // associate a product with an inventory item + const product = await productService.create(data) + const inventoryItem = await inventoryService.create( + inventoryData + ) + await productVariantInventoryService.associate( + product.id, + inventoryItem.id + ) + + // ... +} +``` + +### Expose REST APIs + +The goal of orchestrating the modules is to expose an API that client applications, like websites or apps, can consume. By default, Medusa’s core package exposes a REST API that offers commerce functionalities similar to what other platforms give you. + +The core package also holds the logic that allows developers to extend and add custom endpoints, among other available customizations. + +--- + +## Backend First Steps + + + +--- + +## Understanding Fundamental Concepts + +These concepts will guide you through your development and building customization with Medusa. + + + +--- + +## Medusa Use Cases + +To better understand how you can use Medusa, here are some common use cases that Medusa is the ideal solution for. + +### Ecommerce Building Blocks + +Developers can set up the core package and handpick the Commerce Modules they want to use. This gives them great flexibility in choosing the features they want to provide in their ecommerce store, while utilizing the powerful architecture in the core package. + +![Ecommerce Building Blocks](https://res.cloudinary.com/dza7lstvk/image/upload/v1678954316/Medusa%20Docs/Diagrams/ecommerce-building-blocks_llgnn2.jpg) + +Developers can modify and tailor the modules that Medusa offers to their use case. They can also create custom Modules to implement new features. All these modules become building blocks that shape their ecommerce system. + +### Medusa in Microservices Architectures + +Medusa’s Commerce Modules can be used in isolation from the core package and within a larger ecosystem. For example, you can use Medusa’s Cart module within a blog to allow readers to buy merch. + +![Medusa in Microservices Architecture](https://res.cloudinary.com/dza7lstvk/image/upload/v1678954316/Medusa%20Docs/Diagrams/microservices-architecture-use-case_vubgno.jpg) + +Developers can benefit from Medusa’s Modules that provide essential ecommerce features while maintaining the ecommerce ecosystem of their choice. Commerce Modules can be installed in your setup as NPM packages. + +### Vertical Ecommerce Platforms + +A Vertical Ecommerce Platform is a platform that provides features and functionalities specialized for a type of business sector. For example, a platform for pharmaceuticals. + +Developers can use Medusa to build a vertical ecommerce platform as it provides the stepping stones that eliminate the need to reinvent the wheel for basic ecommerce features, but are customizable enough to be changed for their use case. + +### Out-of-Box APIs + +Since Medusa’s Commerce Modules are NPM packages, they can be installed and used in any JavaScript project. + +By installing a Module in your project and expose its APIs based on the framework you’re using, you can get ecommerce REST APIs right from your frontend framework without having to create a separate project. + +### Full-Fledged Ecommerce System + +Developers can use Medusa’s toolkit to create their ecommerce system. With the use of the [create-medusa-app](../create-medusa-app.mdx) command, developers can set up a Medusa Backend, Medusa admin, and a storefront. + +![Full-Fledged Ecommerce System](https://res.cloudinary.com/dza7lstvk/image/upload/v1678954316/Medusa%20Docs/Diagrams/fully-fledged-ecom_qqwraq.jpg) + +Developers can still benefit from customization opportunities here that Medusa provides. This includes creating resources such as endpoints and services, creating plugins, integrating third-party services, create a custom storefront, and more. + +### Your Own Use Case + +Medusa’s vision is to allow developers to build anything they want using it. There are no limitations to what you can build and the ideas you can come up with. If you have an idea, you can use Medusa’s tools to start building it. \ No newline at end of file diff --git a/docs/content/advanced/backend/plugins/create.md b/docs/content/development/plugins/create.md similarity index 76% rename from docs/content/advanced/backend/plugins/create.md rename to docs/content/development/plugins/create.md index f70ff779a6ec7..50f58d6ce4f49 100644 --- a/docs/content/advanced/backend/plugins/create.md +++ b/docs/content/development/plugins/create.md @@ -5,7 +5,7 @@ addHowToData: true # How to Create a Plugin -In this document, you’ll learn how to create a plugin and some tips for develoment. If you’re interested to learn more about what plugins are and where to find available official and community plugins, check out the [overview document](overview.md). +In this document, you’ll learn how to create a plugin and some tips for develoment. If you’re interested to learn more about what plugins are and where to find available official and community plugins, check out the [overview document](./overview.mdx). ## Prerequisites @@ -17,7 +17,7 @@ npm install @medusajs/medusa-cli -g :::note -If you run into any errors while installing the CLI tool, check out the [troubleshooting guide](../../../troubleshooting/cli-installation-errors.mdx). +If you run into any errors while installing the CLI tool, check out the [troubleshooting guide](../../troubleshooting/cli-installation-errors.mdx). ::: @@ -41,7 +41,7 @@ By convention, all plugin names start with `medusa` followed by a descriptive na ### Change Dependencies -A basic Medusa server installed with the `medusa new` command has dependencies similar to this: +A basic Medusa backend installed with the `medusa new` command has dependencies similar to this: ```json title=package.json "dependencies": { @@ -61,7 +61,7 @@ A basic Medusa server installed with the `medusa new` command has dependencies s } ``` -For a plugin, some dependencies are not necessary. You can remove the packages `medusa-fulfillment-manual`, `medusa-payment-manual`, and `medusa-payment-stripe` as they are fulfillment and payment plugins necessary for a Medusa server, but not for a plugin. +For a plugin, some dependencies are not necessary. You can remove the packages `medusa-fulfillment-manual`, `medusa-payment-manual`, and `medusa-payment-stripe` as they are fulfillment and payment plugins necessary for a Medusa backend, but not for a plugin. Additionally, you can remove `@medusajs/medusa-cli` as you don’t need to use the Medusa CLI while developing a plugin. @@ -102,11 +102,11 @@ Now, You can start developing your plugin. This can include adding services, end While developing your plugin, you can create your TypeScript or JavaScript files under the `src` directory. This includes creating services, endpoints, migrations, etc... -However, before you test the changes on a Medusa server or publish your plugin, you must transpile your files, which moves them into the root of your plugin directory. +However, before you test the changes on a Medusa backend or publish your plugin, you must transpile your files, which moves them into the root of your plugin directory. For example, if you have an endpoint in `src/api/index.js`, after running the `build` or `watch` commands [as defined earlier](#change-scripts), the file should be transpiled into `api/index.js` in your plugin's root. -If files and directories aren't placed in the root of your plugin, the Medusa server won't detect or load them. +If files and directories aren't placed in the root of your plugin, the Medusa backend won't detect or load them. An example of a plugin's directory before testing or publishing: @@ -139,11 +139,11 @@ medusa-plugin-custom This guide doesn't cover how to create different files and components. If you’re interested in learning how to do that, you can check out these guides: -- How to [create endpoints](../endpoints/add.md) +- How to [create endpoints](../endpoints/create.md) - How to [create a service](../services/create-service.md) -- How to [create a subscriber](../subscribers/create-subscriber.md) -- How to [create an entity](./../entities/index.md) -- How to [create a migration](../migrations/index.md) +- How to [create a subscriber](../events/create-subscriber.md) +- How to [create an entity](../entities/create.md) +- How to [create a migration](../entities/migrations/create.md) --- @@ -151,7 +151,7 @@ This guide doesn't cover how to create different files and components. If you’ Plugins often allow developers that will later use them to enter their own configuration. For example, you can allow developers to specify the API key of a service you’re integrating. -To pass a plugin its configurations on a Medusa server, you have to add it to the `plugins` array in `medusa-config.js`: +To pass a plugin its configurations on a Medusa backend, you have to add it to the `plugins` array in `medusa-config.js`: ```jsx title=medusa-config.js const plugins = [ @@ -189,7 +189,8 @@ export default (rootDirectory, options) => { router.get("/hello-world", (req, res) => { res.json({ - message: `Welcome to ${options.name ? options.name : "Medusa"}!`, + message: + `Welcome to ${options.name ? options.name : "Medusa"}!`, }) }) @@ -207,7 +208,7 @@ Make sure to include in the README of your plugin the configurations that can be ## Test Your Plugin -While you develop your plugin, you’ll need to test it on an actual Medusa server. This can be done by using the [npm link](https://docs.npmjs.com/cli/v8/commands/npm-link) command. +While you develop your plugin, you’ll need to test it on an actual Medusa backend. This can be done by using the [npm link](https://docs.npmjs.com/cli/v8/commands/npm-link) command. In the root of your plugin directory, run the following command: @@ -215,7 +216,7 @@ In the root of your plugin directory, run the following command: npm link ``` -Then, change to the directory of the Medusa server you want to test the plugin on and run the following command: +Then, change to the directory of the Medusa backend you want to test the plugin on and run the following command: ```bash npm2yarn npm link medusa-plugin-custom @@ -223,7 +224,7 @@ npm link medusa-plugin-custom Where `medusa-plugin-custom` is the package name of your plugin. -After linking to your plugin in a local Medusa server, either run the `build` or `watch` commands in your plugin directory: +After linking to your plugin in a local Medusa backend, either run the `build` or `watch` commands in your plugin directory: ```bash npm2yarn # in the directory of the plugin @@ -253,11 +254,11 @@ const plugins = [ :::note -If your plugin has migrations, you must run them before you start the server. Check out the [Migrations guide](../migrations/overview.md#migrate-command) for more details. +If your plugin has migrations, you must run them before you start the backend. Check out the [Migrations guide](../entities/migrations/overview.mdx#migrate-command) for more details. ::: -Finally, start your server and test your plugin’s functionalities: +Finally, start your backend and test your plugin’s functionalities: ```bash npm2yarn npm run start @@ -270,9 +271,9 @@ npm run start Please make sure that your plugin is following the correct structure. If the error persists then please try the following fix: ```bash npm2yarn -cd /node_modules/medusa-interfaces +cd /node_modules/medusa-interfaces npm link -cd /node_modules/@medusajs/medusa +cd /node_modules/@medusajs/medusa npm link cd rm -rf node_modules/medusa-interfaces @@ -280,30 +281,30 @@ rm -rf node_modules/@medusajs/medusa npm link medusa-interfaces npm link @medusajs/medusa npm link -cd +cd npm link your-plugin ``` -Where `` is the path to your Medusa server and `` is the path to your plugin. +Where `` is the path to your Medusa backend and `` is the path to your plugin. This links the `medusa-interfaces` and `@medusajs/medusa` packages from your `medusa-backend` to your plugin directory and then links your plugin to your `medusa-backend`. #### APIs not loading -If the APIs you added to your Medussa server are not loading then please try the following steps: +If the APIs you added to your Medussa backend are not loading then please try the following steps: ```bash npm2yarn cd rm -rf node_modules -cd /node_modules/ +cd /node_modules/ npm install cd npm run build -cd +cd npm run start ``` -Where `` is the path to your Medusa server, `` is the path to your plugin and `` is the name of your plugin as it is in your plugin `package.json` file. +Where `` is the path to your Medusa backend, `` is the path to your plugin and `` is the name of your plugin as it is in your plugin `package.json` file. :::note @@ -318,11 +319,3 @@ It is safe to ignore any `cross-env: command not found` error you may receive. Once you're done with the development of the plugin, you can publish it to NPM so that other Medusa developers and users can use it. Please refer to [this guide on required steps to publish a plugin](./publish.md). - ---- - -## See Also - -- [Available official plugins](https://github.com/medusajs/medusa/tree/master/packages) -- [Services reference](references/services/../../../../../references/services/classes/AuthService.md) -- [Events reference](../subscribers/events-list.md) diff --git a/docs/content/advanced/backend/plugins/overview.md b/docs/content/development/plugins/overview.mdx similarity index 67% rename from docs/content/advanced/backend/plugins/overview.md rename to docs/content/development/plugins/overview.mdx index 74b430230a5a5..04661efaabf81 100644 --- a/docs/content/advanced/backend/plugins/overview.md +++ b/docs/content/development/plugins/overview.mdx @@ -1,7 +1,10 @@ --- -description: 'Learn what Plugins are and how they are used in Medusa. Plugins are re-usable customizations that can be added to a Medusa server.' +description: 'Learn what Plugins are and how they are used in Medusa. Plugins are re-usable customizations that can be added to a Medusa backend.' --- +import DocCardList from '@theme/DocCardList'; +import Icons from '@theme/Icon'; + # Plugins In this document, you’ll get an overview of plugins in Medusa, where to find them, and how to install them. If you want to learn how to create a plugin, check out [this guide](create.md) instead. @@ -12,11 +15,11 @@ Medusa was built with flexibility and extendibility in mind. All different compo Developers can use plugins to take advantage of this abstraction, flexibility, and extendibility. Plugins allow developers to implement custom features or integrate third-party services into Medusa. -For example, if you want to use Stripe as a payment provider in your store, then you can install the Stripe plugin on your server and use it. +For example, if you want to use Stripe as a payment provider in your store, then you can install the Stripe plugin on your backend and use it. An alternative approach is developing a custom way of handling payment on your ecommerce store. Both approaches are achievable by either creating a plugin or using an existing plugin. -Plugins run within the same process as the core Medusa server eliminating the need for extra server capacity, infrastructure, and maintenance. As a result, plugins can use all other services as dependencies and access the database. +Plugins run within the same process as the core Medusa backend eliminating the need for extra backend capacity, infrastructure, and maintenance. As a result, plugins can use all other services as dependencies and access the database. --- @@ -24,7 +27,7 @@ Plugins run within the same process as the core Medusa server eliminating the ne ### Official Plugins -Medusa has official plugins that cover different aspects and functionalities such as payment, Content Management System (CMS), fulfillment, and notifications. You can check out the available plugins under the [packages directory in the Medusa repository on GitHub](https://github.com/medusajs/medusa/tree/master/packages). +Medusa has official plugins that cover different aspects and functionalities such as payment, Content Management System (CMS), fulfillment, and notifications. You can check out the available plugins under the [Plugins section of this documentation](../../plugins/overview.mdx). :::tip @@ -40,7 +43,7 @@ You can also check the [Awesome Medusa repository](https://github.com/adrien2p/a ## How to Install a Plugin -To install an existing plugin, in your Medusa server run the following command: +To install an existing plugin, in your Medusa backend run the following command: ```bash npm2yarn npm install @@ -56,8 +59,27 @@ For community plugins, please refer to the installation instructions of that plu --- -## See Also - -- [Create a plugin](create.md) -- [Publish a plugin](publish.md) -- [Create a fulfillment provider](../shipping/add-fulfillment-provider.md) or a [payment provider](../payment/how-to-create-payment-provider.md) +## Custom Development + +Developers can create plugins and reuse them across different Medusa backends. They can also share them with the community to help out other developers. + + \ No newline at end of file diff --git a/docs/content/advanced/backend/plugins/publish.md b/docs/content/development/plugins/publish.md similarity index 96% rename from docs/content/advanced/backend/plugins/publish.md rename to docs/content/development/plugins/publish.md index c8af392320572..27bc03c340369 100644 --- a/docs/content/advanced/backend/plugins/publish.md +++ b/docs/content/development/plugins/publish.md @@ -34,7 +34,7 @@ Before publishing your plugin, make sure you've set the following fields in your - `medusa-plugin-shipping`: For plugins that add shipping functionalities or integrations. - `medusa-plugin-storage`: For plugins that add a file service or storage integration. - `medusa-plugin-source`: For plugins that help migrate or import data into Medusa from another platform. - - `medusa-plugin-storefront`: For storefronts that can be integrated with a Medusa server. + - `medusa-plugin-storefront`: For storefronts that can be integrated with a Medusa backend. - `medusa-plugin-other`: For any other type of plugin. ### Scripts in package.json @@ -131,7 +131,7 @@ Your package is then published on NPM and everyone can use it and install it. ### Install Plugin -To install your published plugin, you can run the following command on any Medusa server project: +To install your published plugin, you can run the following command on any Medusa backend project: ```bash npm2yarn npm install medusa-plugin-custom @@ -151,10 +151,4 @@ Then, publish the new update: ```bash npm publish -``` - ---- - -## See Also - -- [Available official plugins](https://github.com/medusajs/medusa/tree/master/packages) \ No newline at end of file +``` \ No newline at end of file diff --git a/docs/content/advanced/admin/manage-publishable-api-keys.mdx b/docs/content/development/publishable-api-keys/admin/manage-publishable-api-keys.mdx similarity index 85% rename from docs/content/advanced/admin/manage-publishable-api-keys.mdx rename to docs/content/development/publishable-api-keys/admin/manage-publishable-api-keys.mdx index bbfb3e006b4b7..a3b519579bff8 100644 --- a/docs/content/advanced/admin/manage-publishable-api-keys.mdx +++ b/docs/content/development/publishable-api-keys/admin/manage-publishable-api-keys.mdx @@ -37,19 +37,19 @@ You want to use or implement the following admin functionalities: ### Medusa Components -It is assumed that you already have a Medusa server installed and set up. If not, you can follow the [quickstart guide](../../quickstart/quick-start.mdx) to get started. +It is assumed that you already have a Medusa backend installed and set up. If not, you can follow the [quickstart guide](../../backend/install.mdx) to get started. ### JS Client -This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client, among other methods. +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, among other methods. -If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../js-client/overview.md) installed and have [created an instance of the client](../../js-client/overview.md#configuration). +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../../js-client/overview.md) installed and have [created an instance of the client](../../../js-client/overview.md#configuration). ### Medusa React -This guide also includes code snippets to send requests to your Medusa server using Medusa React, among other methods. +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. -If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../medusa-react/overview.md#usage). +If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). ### Authenticated Admin User @@ -81,7 +81,8 @@ import { PublishableApiKey } from "@medusajs/medusa" import { useAdminPublishableApiKeys } from "medusa-react" const PublishabelApiKeys = () => { - const { publishable_api_keys, isLoading } = useAdminPublishableApiKeys() + const { publishable_api_keys, isLoading } = + useAdminPublishableApiKeys() return (
@@ -89,11 +90,14 @@ const PublishabelApiKeys = () => { {publishable_api_keys && !publishable_api_keys.length && ( No Publishable API Keys )} - {publishable_api_keys && publishable_api_keys.length > 0 && ( + {publishable_api_keys && + publishable_api_keys.length > 0 && (
    {publishable_api_keys.map( (publishableApiKey: PublishableApiKey) => ( -
  • {publishableApiKey.title}
  • +
  • + {publishableApiKey.title} +
  • ) )}
@@ -109,7 +113,7 @@ export default PublishabelApiKeys ```ts -fetch(`/admin/publishable-api-keys`, { +fetch(`/admin/publishable-api-keys`, { credentials: "include", }) .then((response) => response.json()) @@ -122,7 +126,7 @@ fetch(`/admin/publishable-api-keys`, { ```bash -curl -L -X GET '/admin/publishable-api-keys' \ +curl -L -X GET '/admin/publishable-api-keys' \ -H 'Authorization: Bearer ' ``` @@ -188,7 +192,7 @@ export default CreatePublishableApiKey ```ts -fetch(`/admin/publishable-api-keys`, { +fetch(`/admin/publishable-api-keys`, { method: "POST", credentials: "include", headers: { @@ -208,7 +212,7 @@ fetch(`/admin/publishable-api-keys`, { ```bash -curl -L -X POST '/admin/publishable-api-keys' \ +curl -L -X POST '/admin/publishable-api-keys' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -248,7 +252,9 @@ medusa.admin.publishableApiKeys.update(publishableApiKeyId, { import { useAdminUpdatePublishableApiKey } from "medusa-react" const UpdatePublishableApiKey = () => { - const updateKey = useAdminUpdatePublishableApiKey(publishableApiKeyId) + const updateKey = useAdminUpdatePublishableApiKey( + publishableApiKeyId + ) // ... const handleUpdate = (title: string) => { @@ -266,8 +272,10 @@ export default UpdatePublishableApiKey + + ```ts -fetch(`/admin/publishable-api-keys/${publishableApiKeyId}`, { +fetch(`/admin/publishable-api-keys/${publishableApiKeyId}`, { method: "POST", credentials: "include", headers: { @@ -287,7 +295,7 @@ fetch(`/admin/publishable-api-keys/${publishableApiKeyId}`, { ```bash -curl -L -X POST '/admin/publishable-api-keys/' \ +curl -L -X POST '/admin/publishable-api-keys/' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -327,7 +335,9 @@ medusa.admin.publishableApiKeys.revoke(publishableApiKeyId) import { useAdminRevokePublishableApiKey } from "medusa-react" const PublishableApiKey = () => { - const revokeKey = useAdminRevokePublishableApiKey(publishableApiKeyId) + const revokeKey = useAdminRevokePublishableApiKey( + publishableApiKeyId + ) // ... const handleRevoke = () => { @@ -343,9 +353,11 @@ export default PublishableApiKey + + ```ts fetch( - `/admin/publishable-api-keys/${publishableApiKeyId}/revoke`, + `/admin/publishable-api-keys/${publishableApiKeyId}/revoke`, { method: "POST", credentials: "include", @@ -361,7 +373,7 @@ fetch( ```bash -curl -L -X POST '/admin/publishable-api-keys//revoke' \ +curl -L -X POST '/admin/publishable-api-keys//revoke' \ -H 'Authorization: Bearer ' ``` @@ -393,7 +405,9 @@ medusa.admin.publishableApiKeys.delete(publishableApiKeyId) import { useAdminDeletePublishableApiKey } from "medusa-react" const PublishableApiKey = () => { - const deleteKey = useAdminDeletePublishableApiKey(publishableApiKeyId) + const deleteKey = useAdminDeletePublishableApiKey( + publishableApiKeyId + ) // ... const handleDelete = () => { @@ -409,8 +423,10 @@ export default PublishableApiKey + + ```ts -fetch(`/admin/publishable-api-keys/${publishableApiKeyId}`, { +fetch(`/admin/publishable-api-keys/${publishableApiKeyId}`, { method: "DELETE", credentials: "include", }) @@ -424,7 +440,7 @@ fetch(`/admin/publishable-api-keys/${publishableApiKeyId}`, { ```bash -curl -L -X DELETE '/admin/publishable-api-keys/' \ +curl -L -X DELETE '/admin/publishable-api-keys/' \ -H 'Authorization: Bearer ' ``` @@ -453,7 +469,8 @@ You can retrieve the list of sales channels associated with a publishable API ke ```ts -medusa.admin.publishableApiKeys.listSalesChannels(publishableApiKeyId) +medusa.admin.publishableApiKeys + .listSalesChannels(publishableApiKeyId) .then(({ sales_channels }) => { console.log(sales_channels) }) @@ -464,7 +481,9 @@ medusa.admin.publishableApiKeys.listSalesChannels(publishableApiKeyId) ```tsx import { SalesChannel } from "@medusajs/medusa" -import { useAdminPublishableApiKeySalesChannels } from "medusa-react" +import { + useAdminPublishableApiKeySalesChannels, +} from "medusa-react" const SalesChannels = () => { const { sales_channels, isLoading } = @@ -499,7 +518,7 @@ export default SalesChannels ```ts fetch( - `/admin/publishable-api-keys/${publishableApiKeyId}/sales-channels`, + `/admin/publishable-api-keys/${publishableApiKeyId}/sales-channels`, { credentials: "include", } @@ -514,7 +533,7 @@ fetch( ```bash -curl -L -X GET '/admin/publishable-api-keys//sales-channels' \ +curl -L -X GET '/admin/publishable-api-keys//sales-channels' \ -H 'Authorization: Bearer ' ``` @@ -552,12 +571,15 @@ medusa.admin.publishableApiKeys.addSalesChannelsBatch( ```tsx -import { useAdminAddPublishableKeySalesChannelsBatch } from "medusa-react" +import { + useAdminAddPublishableKeySalesChannelsBatch, +} from "medusa-react" const PublishableApiKey = () => { - const addSalesChannels = useAdminAddPublishableKeySalesChannelsBatch( - publishableApiKeyId - ) + const addSalesChannels = + useAdminAddPublishableKeySalesChannelsBatch( + publishableApiKeyId + ) // ... const handleAdd = (salesChannelId: string) => { @@ -583,7 +605,7 @@ export default PublishableApiKey ```ts fetch( - `/admin/publishable-api-keys/${publishableApiKeyId}/sales-channels/batch`, + `/admin/publishable-api-keys/${publishableApiKeyId}/sales-channels/batch`, { method: "POST", credentials: "include", @@ -609,7 +631,7 @@ fetch( ```bash -curl -L -X POST '/admin/publishable-api-keys//sales-channels/batch' \ +curl -L -X POST '/admin/publishable-api-keys//sales-channels/batch' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -693,7 +715,7 @@ export default PublishableApiKey ```ts fetch( - `/admin/publishable-api-keys/${publishableApiKeyId}/sales-channels/batch`, + `/admin/publishable-api-keys/${publishableApiKeyId}/sales-channels/batch`, { method: "DELETE", credentials: "include", @@ -719,7 +741,7 @@ fetch( ```bash -curl -L -X DELETE '/admin/publishable-api-keys//sales-channels/batch' \ +curl -L -X DELETE '/admin/publishable-api-keys//sales-channels/batch' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -746,5 +768,4 @@ This request returns the updated publishable API key in the response. ## See Also -- [Publishable API key overview](../backend/publishable-api-keys/index.md) -- [Publishable API key admin API reference](/api/admin/#tag/PublishableApiKey) +- [Use publishable API keys in client requests](../storefront/use-in-requests.md) diff --git a/docs/content/development/publishable-api-keys/index.mdx b/docs/content/development/publishable-api-keys/index.mdx new file mode 100644 index 0000000000000..d123f3bcfd8a9 --- /dev/null +++ b/docs/content/development/publishable-api-keys/index.mdx @@ -0,0 +1,69 @@ +--- +description: 'Learn what publishable API keys are and how they can be used in the Medusa backend. Publishable API keys can be used to scope API calls with an API key.' +--- + +import DocCardList from '@theme/DocCardList'; +import Icons from '@theme/Icon'; + +# Publishable API Keys + +In this document, you’ll learn about Publishable API Keys and their architecture. + +## Introduction + +While using Medusa’s APIs, you might have to pass some query parameters for certain resources with every or most requests. + +Taking Sales Channels as an example, you have to pass the Sales Channel’s ID as a query parameter to all the necessary endpoints, such as the List Products endpoint. + +This is a tedious and error-prone process. This is where Publishable API Keys are useful. + +Publishable API Keys can be used to scope API calls with an API key, determining what resources are retrieved when querying the API. Currently, they can be associated only with Sales Channels. + +For example, you can associate an API key with a B2B channel, then, on the storefront, retrieve only products available in that channel using the API key. + +--- + +## PublishableApiKey Entity Overview + +The `PublishableApiKey` entity represents a publishable API key that is stored in the database. Some of its important attributes include: + +- `id`: The ID of the publishable API key. This is the API key you’ll use in your API requests. +- `created_by`: The ID of the user that created this API key. +- `revoked_by`: The ID of the user that revoked this API key. A revoked publishable API key cannot be used in requests. + +--- + +## Relation to Other Entities + +### Sales Channels + +A publishable API key can be associated with more than one sales channel, and a sales channel can be associated with more than one publishable API key. + +The relation is represented by the entity `PublishableApiKeySalesChannel`. + +--- + +## Custom Development + +Developers can manage Publishable API Keys and use them when making requests to the Store APIs. + + \ No newline at end of file diff --git a/docs/content/development/publishable-api-keys/storefront/use-in-requests.md b/docs/content/development/publishable-api-keys/storefront/use-in-requests.md new file mode 100644 index 0000000000000..dbf3031f50176 --- /dev/null +++ b/docs/content/development/publishable-api-keys/storefront/use-in-requests.md @@ -0,0 +1,78 @@ +--- +description: 'Learn how to use Publishable API Keys in Client Requests using Medusa JS Client, Medusa React, or other methods.' +--- + +# Use Publishable API Keys in Client Requests + +In this document, you'll learn how to use Publishable API Keys in client requests. + +:::note + +[Publishable API keys](../index.mdx) are only for client-side use. They can be publicly accessible in your code, as they are not authorized for the Admin API. + +::: + +## Using Medusa JS Client + +When using [Medusa’s JS Client](../../../js-client/overview.md), you can pass it to the client only once when you create the instance of the client: + +```ts +const medusa = new Medusa({ + maxRetries: 3, + baseUrl: "https://api.example.com", + publishableApiKey, +}) +``` + +This will add the API key as in the header parameter `x-publishable-api-key` on all requests. + +You can also use the `setPublishableKey` method to set it at a later point: + +```ts +const medusa = new Medusa({ + // ... +}) + +// at a later point +medusa.setPublishableKey(publishableApiKey) +``` + +## Using Medusa React + +You can pass the publishable API key to the `MedusaProvider` component: + +```tsx +const App = () => { + return ( + + + + ) +} +``` + +Then, the API key will be passed in the header parameter `x-publishable-api-key` of every request. + +## Using Other Methods + +For other ways of sending requests to your Medusa backend, such as using the Fetch API, you must pass `x-publishable-api-key` in the header of every request. Its value is the publishable API key’s `id`. + +```ts +fetch(`/store/products`, { + credentials: "include", + headers: { + "x-publishable-api-key": publishableApiKey, + }, +}) +``` + +--- + +## See Also + +- [Manage publishable keys as an admin](../admin/manage-publishable-api-keys.mdx) \ No newline at end of file diff --git a/docs/content/advanced/backend/scheduled-jobs/create.md b/docs/content/development/scheduled-jobs/create.md similarity index 74% rename from docs/content/advanced/backend/scheduled-jobs/create.md rename to docs/content/development/scheduled-jobs/create.md index f7c0438a6fc8f..7a70e73839e54 100644 --- a/docs/content/advanced/backend/scheduled-jobs/create.md +++ b/docs/content/development/scheduled-jobs/create.md @@ -1,5 +1,5 @@ --- -description: 'Learn how to create a scheduled job in the Medusa server. The scheduled job in this example will simply change the status of draft products to published.' +description: 'Learn how to create a scheduled job in Medusa. The scheduled job in this example will simply change the status of draft products to published.' addHowToData: true --- @@ -9,9 +9,9 @@ In this document, you’ll learn how to create a scheduled job in Medusa. ## Overview -Medusa allows you to create scheduled jobs that run at specific times during your server’s lifetime. For example, you can synchronize your inventory with an Enterprise Resource Planning (ERP) system once a day. +Medusa allows you to create scheduled jobs that run at specific times during your backend's lifetime. For example, you can synchronize your inventory with an Enterprise Resource Planning (ERP) system once a day. -This guide explains how to create a scheduled job on your Medusa server. The scheduled job in this example will simply change the status of draft products to `published`. +This guide explains how to create a scheduled job on your Medusa backend. The scheduled job in this example will simply change the status of draft products to `published`. --- @@ -19,11 +19,11 @@ This guide explains how to create a scheduled job on your Medusa server. The sch ### Medusa Components -It is assumed that you already have a Medusa server installed and set up. If not, you can follow the [quickstart guide](../../../quickstart/quick-start.mdx) to get started. +It is assumed that you already have a Medusa backend installed and set up. If not, you can follow the [quickstart guide](../backend/install.mdx) to get started. ### Redis -Redis is required for scheduled jobs to work. Make sure you [install Redis](../../../tutorial/0-set-up-your-development-environment.mdx#redis) and [configure it with your Medusa server](../../../usage/configurations.md#redis). +Redis is required for scheduled jobs to work. Make sure you [install Redis](../../development/backend/prepare-environment.mdx#redis) and [configure it with your Medusa backend](../../development/backend/configurations.md#redis). --- @@ -43,8 +43,12 @@ To create a scheduled job, add the following code in the file you created, which ```ts title=src/loaders/publish.ts const publishJob = async (container, options) => { - const jobSchedulerService = container.resolve("jobSchedulerService") - jobSchedulerService.create("publish-products", {}, "0 0 * * *", + const jobSchedulerService = + container.resolve("jobSchedulerService") + jobSchedulerService.create( + "publish-products", + {}, + "0 0 * * *", async () => { // job to execute const productService = container.resolve("productService") @@ -77,7 +81,7 @@ You then resolve the `JobSchedulerService` and use the `jobSchedulerService.crea - The first parameter is a unique name to give to the scheduled job. In the example above, you use the name `publish-products`; - The second parameter is an object which can be used to [pass data to the job](#pass-data-to-the-scheduled-job); - The third parameter is the scheduled job expression pattern. In this example, it will execute the scheduled job once a day at 12 AM. -- The fourth parameter is the function to execute. This is where you add the code to execute once the scheduled job runs. In this example, you retrieve the draft products using the [ProductService](../../../references/services/classes/ProductService.md) and update the status of each of these products to `published`. +- The fourth parameter is the function to execute. This is where you add the code to execute once the scheduled job runs. In this example, you retrieve the draft products using the [ProductService](../../references/services/classes/ProductService.md) and update the status of each of these products to `published`. :::tip @@ -104,23 +108,23 @@ jobSchedulerService.create("publish-products", { --- -## 3. Run Medusa Server +## 3. Run Medusa Backend :::info -Cron Jobs only run while the Medusa server is running. +Cron Jobs only run while the Medusa backend is running. ::: -In your terminal run the following command to run your Medusa server: +In your terminal run the following command to run your Medusa backend: ```bash npm2yarn npm run start ``` -This builds your code under the `src` directory into the `dist` directory, then runs the Medusa server. +This builds your code under the `src` directory into the `dist` directory, then runs the Medusa backend. -If the scheduled job was registered successfully, you should see a message similar to this logged on your Medusa server: +If the scheduled job was registered successfully, you should see a message similar to this logged on your Medusa backend: ```bash Registering publish-products @@ -128,15 +132,15 @@ Registering publish-products Where `publish-products` is the unique name you provided to the scheduled job. -Once it is time to run your scheduled job based on the scheduled job expression pattern, the scheduled job will run and you can see it logged on your Medusa server. +Once it is time to run your scheduled job based on the scheduled job expression pattern, the scheduled job will run and you can see it logged on your Medusa backend. -For example, the above scheduled job will run at 12 AM and, when it runs, you can see the following logged on your Medusa server: +For example, the above scheduled job will run at 12 AM and, when it runs, you can see the following logged on your Medusa backend: ```bash noReport info: Processing scheduled job: publish-products ``` -If you log anything in the scheduled job, for example using `console.log`, or if any errors are thrown, it’ll also be logged on your Medusa server. +If you log anything in the scheduled job, for example using `console.log`, or if any errors are thrown, it’ll also be logged on your Medusa backend. :::tip @@ -148,4 +152,4 @@ To test the previous example out instantly, you can change the scheduled job exp ## See Also -- [Services Overview](../services/overview.md). +- [Create a Plugin](../plugins/create.md) \ No newline at end of file diff --git a/docs/content/development/scheduled-jobs/overview.mdx b/docs/content/development/scheduled-jobs/overview.mdx new file mode 100644 index 0000000000000..d9ee10fb40ce8 --- /dev/null +++ b/docs/content/development/scheduled-jobs/overview.mdx @@ -0,0 +1,40 @@ +--- +description: "Learn what scheduled jobs are in Medusa. Scheduled jobs (also known as cron jobs) are tasks performed at a specific time in the Medusa Backend." +--- + +import DocCard from '@theme/DocCard'; +import Icons from '@theme/Icon'; + +# Scheduled Jobs + +In this document, you’ll learn what scheduled jobs are in Medusa. + +## Introduction + +Scheduled jobs (also known as cron jobs) are tasks performed at a specific time while the Medusa Backend is running. They’re used to perform asynchronous tasks in the background. + +For example, you can synchronize your inventory with an Enterprise Resource Planning (ERP) system once a day using a scheduled job. + +In the Medusa Backend, the scheduled jobs queue is implemented using [Redis](https://redis.io/) and [Bull](https://www.npmjs.com/package/bull). So, for scheduled jobs to work, you must have [Redis enabled](../../development/backend/configurations.md#redis). + +:::tip + +Future versions of Medusa will allow switching out Redis and using a different pub/sub service. + +::: + +--- + +## Custom Development + +Developers can create an unlimited number of scheduled jobs within the Medusa Backend, a plugin, or a custom Commerce Module. + + \ No newline at end of file diff --git a/docs/content/advanced/backend/services/create-service.md b/docs/content/development/services/create-service.md similarity index 91% rename from docs/content/advanced/backend/services/create-service.md rename to docs/content/development/services/create-service.md index 7dfeabfd6de9a..3c5450e5d3a5a 100644 --- a/docs/content/advanced/backend/services/create-service.md +++ b/docs/content/development/services/create-service.md @@ -5,7 +5,7 @@ addHowToData: true # Create a Service -In this document, you’ll learn how you can create a [Service](./overview.md) and use it across your Medusa server just like any of the core services. +In this document, you’ll learn how you can create a [Service](./overview.mdx) and use it across your Medusa backend just like any of the core services. ## Implementation @@ -63,7 +63,7 @@ class HelloService extends TransactionBaseService { ## Use a Service -In this section, you'll learn how to use services throughout your Medusa server. This includes both Medusa's services and your custom services. +In this section, you'll learn how to use services throughout your Medusa backend. This includes both Medusa's services and your custom services. :::note @@ -118,5 +118,4 @@ class MySubscriber { ## See Also -- [Services Reference](/references/services/classes/AuthService) -- [Create an Endpoint](../endpoints/add.md) +- [Create a Plugin](../plugins/create.md) diff --git a/docs/content/development/services/overview.mdx b/docs/content/development/services/overview.mdx new file mode 100644 index 0000000000000..a066fccdd32a1 --- /dev/null +++ b/docs/content/development/services/overview.mdx @@ -0,0 +1,49 @@ +--- +description: 'Learn what Services are in Medusa. Services represent bundled helper methods that you want to use across your commerce application.' +--- + +import DocCard from '@theme/DocCard'; +import Icons from '@theme/Icon'; + +# Services + +In this document, you'll learn about what Services are in Medusa. + +## What are Services + +Services in Medusa represent bundled helper methods that you want to use across your commerce application. By convention, they represent a certain entity or functionality in Medusa. + +For example, you can use Medusa’s `productService` to get the list of products, as well as perform other functionalities related to products. There’s also an `authService` that provides functionalities like authenticating customers and users. + +In the Medusa backend, custom services are TypeScript or JavaScript files located in the `src/services` directory. Each service should be a class that extends the `TransactionBaseService` class from the core Medusa package `@medusajs/medusa`. Each file you create in `src/services` should hold one service and export it. + +The file name is important as it determines the name of the service when you need to use it elsewhere. The name of the service will be registered as the camel-case version of the file name + `Service` at the end of the name. + +For example, if the file name is `hello.ts`, the service will be registered as `helloService`. If the file name is `hello-world.ts`, the service name will be registered as `helloWorldService`. + +The registration name of the service is important, as you’ll be referring to it when you want to get access to the service using dependency injection or in routes. + +The service must then be transpiled using the `build` command, which moves them to the `dist` directory, to be used across your commerce application. + +:::tip + +If you're creating a service in a plugin, learn more about the required structure [here](../plugins/create.md#plugin-structure). + +::: + +--- + +## Custom Development + +Developers can create custom services in the Medusa backend, a plugin, or in a Commerce Module. + + \ No newline at end of file diff --git a/docs/content/development/strategies/overview.mdx b/docs/content/development/strategies/overview.mdx new file mode 100644 index 0000000000000..10656385982da --- /dev/null +++ b/docs/content/development/strategies/overview.mdx @@ -0,0 +1,68 @@ +--- +description: "Learn what a Strategy is in Medusa. A strategy is an isolated piece of business logic that can be overridden and customized." +--- + +import DocCardList from '@theme/DocCardList'; +import Icons from '@theme/Icon'; + +# Strategy + +In this document, you’ll learn what a Strategy is in Medusa. + +## Introduction + +A strategy is an isolated piece of business logic that can be overridden and customized. It’s a TypeScript or JavaScript class that doesn’t have to follow a specific definition, but performs only a single functionality. + +For example, in the core `@medusajs/medusa` package, strategies are used to implement functionalities like cart completion and product import. + +These strategy classes are then resolved in endpoints, services, or wherever needed using dependency injection and used to perform their designated functionality. + +For example, the `CartCompletionStrategy` is resolved in the Complete Cart endpoint that is defined in the core `@medusajs/medusa` package. It’s then used to complete the cart and place the order: + +```ts +export default async (req, res) => { + // ... + const completionStrat: AbstractCartCompletionStrategy = + req.scope.resolve( + "cartCompletionStrategy" + ) + + const { + response_code, + response_body, + } = await completionStrat.complete( + id, + idempotencyKey, + req.request_context + ) + + res.status(response_code).json(response_body) +} +``` + +Developers can override these strategies defined in the core to customize their functionality. Dependency injection then resolves the strategy (in the code example above, `CartCompletionStrategy`) to the custom strategy that the developer created. Then, the method (in the code example above, `complete`) of the custom strategy will be executed instead of the one defined in the core package. + +## Custom Development + + \ No newline at end of file diff --git a/docs/content/homepage.mdx b/docs/content/homepage.mdx index af9d5428c5b93..a77b8a6d9fc15 100644 --- a/docs/content/homepage.mdx +++ b/docs/content/homepage.mdx @@ -8,163 +8,191 @@ hide_footer: true --- import DocCardList from '@theme/DocCardList'; +import DocCard from '@theme/DocCard'; +import Icons from '@theme/Icon'; # Medusa Documentation -Get an overview of Medusa's features, integrations, and how to use them. +Medusa is a set of commerce tools and modules that can be used to build unique commerce experiences. -## Medusa basics +Medusa provides the essential building blocks that developers can put together to create a powerful commerce store. Developers have full control over their tech stack and the logic behind the commerce features. -Learn about Medusa basic features and kickstart your ecommerce project. + + +## Explore Medusa + +## Medusa Toolkit + + + + -## Most popular - -Best of the greatest. - - + + + +## What's New + +Learn about all the new features and enhancements in Medusa. + + \ No newline at end of file + }, +]} /> + + + +## Need Help? + + + +If you’re still not sure that Medusa is the right solution for you, you can get in-touch with the core Medusa team over at [Discord](https://discord.gg/medusajs) and get help from the community. \ No newline at end of file diff --git a/docs/content/introduction.md b/docs/content/introduction.md deleted file mode 100644 index b203ed7381b1a..0000000000000 --- a/docs/content/introduction.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -description: 'Medusa is composed of three architectures: Medusa server, admin dashboard, and storefront. It also provides advanced ecommerce features such as order management and automated RMA flows.' ---- - -# Overview - -## Architecture - -Medusa is composed of three components: The Medusa server, the admin dashboard, and the storefront. - -![Medusa's Architecture](https://res.cloudinary.com/dza7lstvk/image/upload/v1667999772/Medusa%20Docs/Diagrams/ZHvM2bu_td4rnx.png) - -### Medusa Server - -The Medusa server is a headless backend built on Node.js. This is the main component that holds all the logic and data of the store. Your admin dashboard and storefront interact with the backend to retrieve, create, and modify data through REST APIs. - -Your Medusa server will include all functionalities related to your store’s checkout workflow. That includes cart management, shipping and payment providers, user management, and more. It also allows you to configure your store including your store’s region, tax rules, discounts, gift cards, and more. - -### Admin Dashboard - -The admin dashboard is accessible by store operators. Store operators can use the admin dashboard to view, create, and modify data such as orders and products. - -Medusa provides a beautiful [admin dashboard](https://demo.medusajs.com) that you can use right off the bat. Medusa's admin dashboard provides a lot of functionalities to manage your store including Order management, Product management, User management, and more. - -You can also create your own admin dashboard by utilizing the [Admin REST APIs](https://docs.medusajs.com/api/admin). - -### Storefront - -Your customers use the Storefront to view products and make orders. Medusa provides two storefronts, one built with [Next.js](https://docs.medusajs.com/starters/nextjs-medusa-starter) and one with [Gatsby](https://docs.medusajs.com/starters/gatsby-medusa-starter). You are also free to create your own storefront using the [Storefront REST APIs](https://docs.medusajs.com/api/store/). - ---- - -## Features - -- [Orders, Exchanges, and Returns](./user-guide/orders/index.md): Aside from the standard order management that comes with ecommerce platforms, Medusa also provides an easy and automated way to manage swaps, returns, and claims. -- [Customers and Customer Groups](./user-guide/customers/index.md): Manage Customers and assign them to customer groups. -- [Products and Collections](./user-guide/products/index.mdx): Add products with extensive customization settings and sort them into collections. -- [Region](./user-guide/regions/index.md): Configure and manage multiple regions and currencies all from one platform. -- [Plugins](./advanced/backend/plugins/overview.md): Easily integrate fulfillment providers, payment providers, notification services, and many other custom tools and third-party services. -- [PriceList](./user-guide/price-lists/index.md) and [Discounts](./user-guide/discounts/): Advanced pricing for products with conditions based on the amount in the cart or promotions and discounts. -- [Taxes](./user-guide/taxes/index.md): Advanced tax configurations specific to multiple regions, with the capability of specifying taxes for specific products. -- [Sales Channels](./user-guide/sales-channels/index.md): Create multiple sales channels and control which sales channels products are available in. -- [Bulk Import](./user-guide/products/import.mdx): Bulk import strategies for different entities including [products](./advanced/admin/import-products.mdx) and [price lists](./advanced/admin/import-prices.mdx). -- [Bulk Export](./user-guide/products/export.mdx): Bulk export strategies for different entities including [products](./user-guide/products/export.mdx) and [orders](./user-guide/orders/export.mdx). -- Complete Customization Capabilities: Aside from all the features that Medusa provides, it is completely customizable providing capabilities to create custom [endpoints](./advanced/backend/endpoints/add.md), [services](./advanced/backend/services/create-service.md), [subscribers](./advanced/backend/subscribers/create-subscriber.md), [batch job strategies](./advanced/backend/batch-jobs/create.mdx), and much more! - ---- - -## See Also - -- [Quickstart guide](./quickstart/quick-start.mdx) -- [Install the Next.js Storefront](./starters/nextjs-medusa-starter.mdx) -- [Install Medusa Admin](./admin/quickstart.mdx) \ No newline at end of file diff --git a/docs/content/medusa-react/overview.md b/docs/content/medusa-react/overview.md index 254895487eec2..44a7229013f05 100644 --- a/docs/content/medusa-react/overview.md +++ b/docs/content/medusa-react/overview.md @@ -1,10 +1,10 @@ --- -description: 'Learn how to install Medusa React in a React storefront. Medusa React is a React library that provides a set of utilities and hooks for interactive with the Medusa server.' +description: 'Learn how to install Medusa React in a React storefront. Medusa React is a React library that provides a set of utilities and hooks for interactive with the Medusa backend.' --- # Medusa React -[Medusa React](https://www.npmjs.com/package/medusa-react) is a React library that provides a set of utilities and hooks for interacting seamlessly with the Medusa server. It can be used to build custom React-based storefronts or admin dashboards. +[Medusa React](https://www.npmjs.com/package/medusa-react) is a React library that provides a set of utilities and hooks for interacting seamlessly with the Medusa backend. It can be used to build custom React-based storefronts or admin dashboards. :::tip @@ -46,7 +46,7 @@ To use the hooks exposed by Medusa React, you need to include the `MedusaProvi The `MedusaProvider` requires two props: -1. `baseUrl`: The URL to your Medusa server +1. `baseUrl`: The URL to your Medusa backend 2. `queryClientProviderProps`: An object used to set the Tanstack Query client. The object requires a `client` property, which should be an instance of [QueryClient](https://tanstack.com/query/v4/docs/react/reference/QueryClient). For example: @@ -88,9 +88,9 @@ You can also pass the following props to Medusa Provider: ### Queries -To fetch data from the Medusa server (in other words, perform `GET` requests), you can use [Queries](https://tanstack.com/query/v4/docs/react/guides/queries). Query hooks simply wrap around Tanstack Query's `useQuery` hook to fetch data from your medusa server. +To fetch data from the Medusa backend (in other words, perform `GET` requests), you can use [Queries](https://tanstack.com/query/v4/docs/react/guides/queries). Query hooks simply wrap around Tanstack Query's `useQuery` hook to fetch data from your medusa backend. -For example, to fetch products from your Medusa server: +For example, to fetch products from your Medusa backend: ```tsx title=src/Products.ts import { Product } from "@medusajs/medusa" @@ -133,7 +133,7 @@ You can learn more about using queries in [Tanstack Query’s documentation](htt ### Mutations -To create, update, or delete data on the Medusa server (in other words, perform `POST`, `PUT`, and `DELETE` requests), you can use [Mutations](https://tanstack.com/query/v4/docs/react/guides/mutations). Mutation hooks wrap around Tanstack Query's `useMutation` to mutate data on your medusa server. +To create, update, or delete data on the Medusa backend (in other words, perform `POST`, `PUT`, and `DELETE` requests), you can use [Mutations](https://tanstack.com/query/v4/docs/react/guides/mutations). Mutation hooks wrap around Tanstack Query's `useMutation` to mutate data on your medusa backend. For example, to create a cart: @@ -166,7 +166,7 @@ export default Cart In the example above, you import the `useCreateCart` hook from `medusa-react`. This hook, and every other mutation hook exposed by `medusa-react`, returns everything that [useMutation](https://tanstack.com/query/v4/docs/react/reference/useMutation) returns. You can also pass the same options you would pass to `useMutation` to mutation hooks exposed by `medusa-react`. -To create a cart, you call the `createCart.mutate` method. In the underlying logic, this method sends a `POST` request to the Medusa server to create a cart. +To create a cart, you call the `createCart.mutate` method. In the underlying logic, this method sends a `POST` request to the Medusa backend to create a cart. If the request accepts any parameters, they can be passed as parameters to the `mutate` request. For example: @@ -200,8 +200,8 @@ This utility function can be used to compute the price of a variant for a region It accepts an object with the following properties: -- `variant`: A variant object retrieved from the Medusa server. It should mainly include the `prices` array in the object. -- `region`: A region object retrieved from the Medusa server. +- `variant`: A variant object retrieved from the Medusa backend. It should mainly include the `prices` array in the object. +- `region`: A region object retrieved from the Medusa backend. - `includeTaxes`: (optional) A boolean value that indicates whether the computed price should include taxes or not. The default value is `true`. - `minimumFractionDigits`: (optional) The minimum number of fraction digits to use when formatting the price. This is passed as an option to `Intl.NumberFormat` in the underlying layer. You can learn more about this method’s options in [MDN’s documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#parameters). - `maximumFractionDigits`: (optional) The maximum number of fraction digits to use when formatting the price. This is passed as an option to `Intl.NumberFormat` which is used within the utility method. You can learn more about this method’s options in [MDN’s documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#parameters). @@ -243,8 +243,8 @@ This utility function can be used to compute the price of a variant for a region It accepts an object with the following properties: -- `variant`: A variant object retrieved from the Medusa server. It should mainly include the `prices` array in the variant. -- `region`: A region object retrieved from the Medusa server. +- `variant`: A variant object retrieved from the Medusa backend. It should mainly include the `prices` array in the variant. +- `region`: A region object retrieved from the Medusa backend. - `includeTaxes`: (optional) A boolean value that indicates whether the computed price should include taxes or not. The default value is `true`. For example: @@ -286,7 +286,7 @@ The main difference between this utility function and `formatVariantPrice` is th It accepts an object with the following properties: - `amount`: A number that should be used for computation. -- `region`: A region object retrieved from the Medusa server. +- `region`: A region object retrieved from the Medusa backend. - `includeTaxes`: (optional) A boolean value that indicates whether the computed price should include taxes or not. The default value is `true`. - `minimumFractionDigits`: (optional) The minimum number of fraction digits to use when formatting the price. This is passed as an option to `Intl.NumberFormat` in the underlying layer. You can learn more about this method’s options in [MDN’s documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#parameters). - `maximumFractionDigits`: (optional) The maximum number of fraction digits to use when formatting the price. This is passed as an option to `Intl.NumberFormat` which is used within the utility method. You can learn more about this method’s options in [MDN’s documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#parameters). @@ -319,7 +319,7 @@ The main difference between this utility function and `computeVariantPrice` is t It accepts an object with the following properties: - `amount`: A number that should be used for computation. -- `region`: A region object retrieved from the Medusa server. +- `region`: A region object retrieved from the Medusa backend. - `includeTaxes`: (optional) A boolean value that indicates whether the computed price should include taxes or not. The default value is `true`. For example: @@ -354,7 +354,7 @@ To facilitate building custom storefronts, `medusa-react` also exposes a `CartP ### CartProvider -`CartProvider` makes use of some of the hooks already exposed by `medusa-react` to perform cart operations on the Medusa server. You can use it to create a cart, start the checkout flow, authorize payment sessions, and so on. +`CartProvider` makes use of some of the hooks already exposed by `medusa-react` to perform cart operations on the Medusa backend. You can use it to create a cart, start the checkout flow, authorize payment sessions, and so on. It also manages one single global piece of state which represents a cart, exactly like the one created on your medusa backend. @@ -432,7 +432,7 @@ const Cart = () => { export default Cart ``` -In the example above, you retrieve the `createCart` mutation and `cart` state object using the `useCart` hook. If the `cart` is not set, a button is shown. When the button is clicked, the `createCart` mutation is executed, which interacts with the server and creates a new cart. +In the example above, you retrieve the `createCart` mutation and `cart` state object using the `useCart` hook. If the `cart` is not set, a button is shown. When the button is clicked, the `createCart` mutation is executed, which interacts with the backend and creates a new cart. After the cart is created, the `cart` state variable is set and its ID is shown instead of the button. @@ -444,9 +444,9 @@ The example above does not store in the browser the ID of the cart created, so t ### SessionProvider -Unlike the `CartProvider`, `SessionProvider` never interacts with the Medusa server. It can be used to implement the user experience related to managing a cart’s items. Its state variables are JavaScript objects living in the browser, but are in no way communicated with the server. +Unlike the `CartProvider`, `SessionProvider` never interacts with the Medusa backend. It can be used to implement the user experience related to managing a cart’s items. Its state variables are JavaScript objects living in the browser, but are in no way communicated with the backend. -You can use the `SessionProvider` as a lightweight client-side cart functionality. It’s not stored in any database or on the Medusa server. +You can use the `SessionProvider` as a lightweight client-side cart functionality. It’s not stored in any database or on the Medusa backend. To use `SessionProvider`, you first have to insert it somewhere in your component tree below the `MedusaProvider`. diff --git a/docs/content/advanced/backend/shipping/add-fulfillment-provider.md b/docs/content/modules/carts-and-checkout/backend/add-fulfillment-provider.md similarity index 84% rename from docs/content/advanced/backend/shipping/add-fulfillment-provider.md rename to docs/content/modules/carts-and-checkout/backend/add-fulfillment-provider.md index a451aafc839fb..3ba9c30c8beb1 100644 --- a/docs/content/advanced/backend/shipping/add-fulfillment-provider.md +++ b/docs/content/modules/carts-and-checkout/backend/add-fulfillment-provider.md @@ -1,19 +1,19 @@ --- -description: 'Learn how to create a fulfillment provider in the Medusa server. This guide explains the different methods in the fulfillment provider.' +description: 'Learn how to create a fulfillment provider in the Medusa backend. This guide explains the different methods in the fulfillment provider.' addHowToData: true --- # How to Add a Fulfillment Provider -In this document, you’ll learn how to add a fulfillment provider to a Medusa server. If you’re unfamiliar with the Shipping architecture in Medusa, make sure to [check out the overview first](overview.md). +In this document, you’ll learn how to add a fulfillment provider to a Medusa backend. If you’re unfamiliar with the Shipping architecture in Medusa, make sure to [check out the overview first](../shipping.md). ## Overview A fulfillment provider is the shipping provider used to fulfill orders and deliver them to customers. An example of a fulfillment provider is FedEx. -By default, a Medusa Server has a `manual` fulfillment provider which has minimal implementation. It allows you to accept orders and fulfill them manually. However, you can integrate any fulfillment provider into Medusa, and your fulfillment provider can interact with third-party shipping providers. +By default, a Medusa Backend has a `manual` fulfillment provider which has minimal implementation. It allows you to accept orders and fulfill them manually. However, you can integrate any fulfillment provider into Medusa, and your fulfillment provider can interact with third-party shipping providers. -Adding a fulfillment provider is as simple as creating one [service](../services/create-service.md) file in `src/services`. A fulfillment provider is essentially a service that extends the `FulfillmentService`. It requires implementing 4 methods: +Adding a fulfillment provider is as simple as creating one [service](../../../development/services/create-service.md) file in `src/services`. A fulfillment provider is essentially a service that extends the `FulfillmentService`. It requires implementing 4 methods: 1. `getFulfillmentOptions`: used to retrieve available fulfillment options provided by this fulfillment provider. 2. `validateOption`: used to validate the shipping option when it’s being created by the admin. @@ -22,7 +22,7 @@ Adding a fulfillment provider is as simple as creating one [service](../services Also, the fulfillment provider class should have a static property `identifier`. It is the name that will be used to install and refer to the fulfillment provider throughout Medusa. -Fulfillment providers are loaded and installed on the server startup. +Fulfillment providers are loaded and installed on the backend startup. --- @@ -44,7 +44,7 @@ Fulfillment provider services must extend the `FulfillmentService` class importe :::note -Following the naming convention of Services, the name of the file should be the slug name of the fulfillment provider, and the name of the class should be the camel case name of the fulfillment provider suffixed with “Service”. You can learn more in the [service documentation](../services/create-service.md). +Following the naming convention of Services, the name of the file should be the slug name of the fulfillment provider, and the name of the class should be the camel case name of the fulfillment provider suffixed with “Service”. You can learn more in the [service documentation](../../../development/services/create-service.md). ::: @@ -54,7 +54,7 @@ As mentioned in the overview, fulfillment providers should have a static `identi The `FulfillmentProvider` entity has 2 properties: `identifier` and `is_installed`. The `identifier` property in the class will be used when the fulfillment provider is created in the database. -The value of this property will also be used to reference the fulfillment provider throughout Medusa. For example, it is used to [add a fulfillment provider](https://docs.medusajs.com/api/admin/#tag/Region/operation/PostRegionsRegionFulfillmentProviders) to a region. +The value of this property will also be used to reference the fulfillment provider throughout Medusa. For example, it is used to [add a fulfillment provider](/api/admin/#tag/Region/operation/PostRegionsRegionFulfillmentProviders) to a region. ```ts import { FulfillmentService } from "medusa-interfaces" @@ -72,7 +72,7 @@ You can use the `constructor` of your fulfillment provider to have access to dif You can also use the constructor to initialize your integration with the third-party provider. For example, if you use a client to connect to the third-party provider’s APIs, you can initialize it in the constructor and use it in other methods in the service. -Additionally, if you’re creating your fulfillment provider as an external plugin to be installed on any Medusa server and you want to access the options added for the plugin, you can access it in the constructor. The options are passed as a second parameter. +Additionally, if you’re creating your fulfillment provider as an external plugin to be installed on any Medusa backend and you want to access the options added for the plugin, you can access it in the constructor. The options are passed as a second parameter. For example: @@ -118,7 +118,7 @@ For that reason, the fulfillment option doesn't have any required structure and ### validateOption -Once the admin creates the shipping option, the data will be validated first using this method in the underlying fulfillment provider of that shipping option. This method is called when a `POST` request is sent to [`/admin/shipping-options`](https://docs.medusajs.com/api/admin/#tag/Shipping-Option/operation/PostShippingOptions). +Once the admin creates the shipping option, the data will be validated first using this method in the underlying fulfillment provider of that shipping option. This method is called when a `POST` request is sent to [`/admin/shipping-options`](/api/admin/#tag/Shipping-Option/operation/PostShippingOptions). This method accepts the `data` object that is sent in the body of the request. You can use this data to validate the shipping option before it is saved. @@ -141,7 +141,7 @@ If your fulfillment provider does not need to run any validation, you can simply When the customer chooses a shipping option on checkout, the shipping option and its data are validated before the shipping method is created. -`validateFulfillmentOption` is called when a `POST` request is sent to [`/carts/:id/shipping-methods`](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCartsCartShippingMethod). +`validateFulfillmentOption` is called when a `POST` request is sent to [`/carts/:id/shipping-methods`](/api/store/#tag/Cart/operation/PostCartsCartShippingMethod). This method accepts three parameters: @@ -221,7 +221,7 @@ If this method returns `true`, that means that the price should be calculated dy If the method returns `false`, an error is thrown as it means the selected shipping option can only be chosen if the price type is set to `flat_rate`. -This method receives as a parameter the `data` object sent with the request that [creates the shipping option.](https://docs.medusajs.com/api/admin/#tag/Shipping-Option/operation/PostShippingOptions) You can use this data to determine whether the shipping option should be calculated or not. This is useful if the fulfillment provider you are integrating has both flat rate and dynamically priced fulfillment options. +This method receives as a parameter the `data` object sent with the request that [creates the shipping option.](/api/admin/#tag/Shipping-Option/operation/PostShippingOptions) You can use this data to determine whether the shipping option should be calculated or not. This is useful if the fulfillment provider you are integrating has both flat rate and dynamically priced fulfillment options. For example: @@ -241,7 +241,7 @@ This method is called on checkout when the shipping method is being created if t This method receives three parameters: 1. The `data` parameter of the selected shipping option. -2. The `data` parameter sent with [the request](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCartsCartShippingMethod). +2. The `data` parameter sent with [the request](/api/store/#tag/Cart/operation/PostCartsCartShippingMethod). 3. The customer’s cart data. If your fulfillment provider does not provide any dynamically calculated rates you can keep the function empty: @@ -270,7 +270,7 @@ class MyFulfillmentService extends FulfillmentService { Fulfillment providers can also be used to return products. A shipping option can be used for returns if the `is_return` property is `true` or if an admin creates a Return Shipping Option from the settings. -This method is called when the admin [creates a return request](https://docs.medusajs.com/api/admin/#tag/Order/operation/PostOrdersOrderReturns) for an order or when the customer [creates a return of their order](https://docs.medusajs.com/api/store/#tag/Return/operation/PostReturns). +This method is called when the admin [creates a return request](/api/admin/#tag/Order/operation/PostOrdersOrderReturns) for an order or when the customer [creates a return of their order](/api/store/#tag/Return/operation/PostReturns). It gives you access to the return being created in case you need to perform any additional actions with the third-party provider. diff --git a/docs/content/advanced/backend/payment/how-to-create-payment-provider.md b/docs/content/modules/carts-and-checkout/backend/add-payment-provider.md similarity index 85% rename from docs/content/advanced/backend/payment/how-to-create-payment-provider.md rename to docs/content/modules/carts-and-checkout/backend/add-payment-provider.md index 46406c3618082..f129f59afc1a7 100644 --- a/docs/content/advanced/backend/payment/how-to-create-payment-provider.md +++ b/docs/content/modules/carts-and-checkout/backend/add-payment-provider.md @@ -1,11 +1,11 @@ --- -description: 'Learn how to create a payment provider in the Medusa server. This guide explains the different methods available in a fulfillment provider.' +description: 'Learn how to create a payment provider in the Medusa backend. This guide explains the different methods available in a fulfillment provider.' addHowToData: true --- # How to Create a Payment Provider -In this document, you’ll learn how to add a Payment Provider to your Medusa server. If you’re unfamiliar with the Payment architecture in Medusa, make sure to check out the [overview](./overview.md) first. +In this document, you’ll learn how to add a Payment Provider to your Medusa backend. If you’re unfamiliar with the Payment architecture in Medusa, make sure to check out the [overview](../payment.md) first. ## Overview @@ -13,13 +13,13 @@ A Payment Provider is the payment method used to authorize, capture, and refund By default, Medusa has a [manual payment provider](https://github.com/medusajs/medusa/tree/master/packages/medusa-payment-manual) that has minimal implementation. It can be synonymous with a Cash on Delivery payment method. It allows store operators to manage the payment themselves but still keep track of its different stages on Medusa. -Adding a Payment Provider is as simple as creating a [service](../services/create-service.md) file in `src/services`. A Payment Provider is essentially a service that extends `AbstractPaymentService` from the core Medusa package `@medusajs/medusa`. +Adding a Payment Provider is as simple as creating a [service](../../../development/services/create-service.md) file in `src/services`. A Payment Provider is essentially a service that extends `AbstractPaymentService` from the core Medusa package `@medusajs/medusa`. -Payment Provider Services must have a static property `identifier`. It's the name that will be used to install and refer to the Payment Provider in the Medusa server. +Payment Provider Services must have a static property `identifier`. It's the name that will be used to install and refer to the Payment Provider in the Medusa backend. :::tip -Payment Providers are loaded and installed at the server startup. +Payment Providers are loaded and installed at the backend startup. ::: @@ -29,7 +29,7 @@ The Payment Provider service is also required to implement the following methods 2. `retrievePayment`: Used to retrieve payment data from the third-party provider, if there’s any. 3. `getStatus`: Used to get the status of a Payment or Payment Session. 4. `updatePayment`: Used to update the Payment Session whenever the cart and its related data are updated. -5. `updatePaymentData`: Used to update the `data` field of Payment Sessions. Specifically called when a request is sent to the [Update Payment Session](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCartsCartPaymentSessionUpdate) endpoint. +5. `updatePaymentData`: Used to update the `data` field of Payment Sessions. Specifically called when a request is sent to the [Update Payment Session](/api/store/#tag/Cart/operation/PostCartsCartPaymentSessionUpdate) endpoint. 6. `deletePayment`: Used to perform any action necessary before a Payment Session is deleted. 7. `authorizePayment`: Used to authorize the payment amount of the cart before the order or swap is created. 8. `getPaymentData`: Used to retrieve the data that should be stored in the `data` field of a new Payment instance after the payment amount has been authorized. @@ -45,7 +45,7 @@ All these methods must be declared async in the Payment Provider Service. These methods are used at different points in the Checkout flow as well as when processing the order after it’s placed. -![Checkout Flow - Payment](https://res.cloudinary.com/dza7lstvk/image/upload/v1668001750/Medusa%20Docs/Diagrams/WeDr0ph_idcrir.jpg) +![Checkout Flow - Payment](https://res.cloudinary.com/dza7lstvk/image/upload/v1677770739/Medusa%20Docs/Diagrams/checkout-payment_rouet2.png) --- @@ -68,7 +68,9 @@ class MyPaymentService extends AbstractPaymentService { protected manager_: EntityManager protected transactionManager_: EntityManager | undefined - async getPaymentData(paymentSession: PaymentSession): Promise { + async getPaymentData( + paymentSession: PaymentSession + ): Promise { throw new Error("Method not implemented.") } async updatePaymentData( @@ -94,7 +96,10 @@ class MyPaymentService extends AbstractPaymentService { async authorizePayment( paymentSession: PaymentSession, context: Data - ): Promise<{ data: PaymentSessionData; status: PaymentSessionStatus }> { + ): Promise<{ + data: PaymentSessionData; + status: PaymentSessionStatus + }> { throw new Error("Method not implemented.") } async capturePayment(payment: Payment): Promise { @@ -109,7 +114,9 @@ class MyPaymentService extends AbstractPaymentService { async cancelPayment(payment: Payment): Promise { throw new Error("Method not implemented.") } - async deletePayment(paymentSession: PaymentSession): Promise { + async deletePayment( + paymentSession: PaymentSession + ): Promise { throw new Error("Method not implemented.") } async getStatus(data: Data): Promise { @@ -127,7 +134,7 @@ Payment Providers must extend `AbstractPaymentService` from the core Medusa pack :::tip -Following the naming convention of Services, the name of the file should be the slug name of the Payment Provider, and the name of the class should be the camel case name of the Payment Provider suffixed with “Service”. In the example above, the name of the file should be `my-payment.js`. You can learn more in the [service documentation](../services/create-service.md). +Following the naming convention of Services, the name of the file should be the slug name of the Payment Provider, and the name of the class should be the camel case name of the Payment Provider suffixed with “Service”. In the example above, the name of the file should be `my-payment.js`. You can learn more in the [service documentation](../../../development/services/create-service.md). ::: @@ -137,7 +144,7 @@ As mentioned in the overview, Payment Providers should have a static `identifie The `PaymentProvider` entity has 2 properties: `identifier` and `is_installed`. The value of the `identifier` property in the class will be used when the Payment Provider is created in the database. -The value of this property will also be used to reference the Payment Provider throughout the Medusa server. For example, the identifier is used when a [Payment Session in a cart is selected on checkout](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCartsCartPaymentSession). +The value of this property will also be used to reference the Payment Provider throughout the Medusa backend. For example, the identifier is used when a [Payment Session in a cart is selected on checkout](/api/store/#tag/Cart/operation/PostCartsCartPaymentSession). ### constructor @@ -145,7 +152,7 @@ You can use the `constructor` of your Payment Provider to have access to diffe You can also use the constructor to initialize your integration with the third-party provider. For example, if you use a client to connect to the third-party provider’s APIs, you can initialize it in the constructor and use it in other methods in the service. -Additionally, if you’re creating your Payment Provider as an external plugin to be installed on any Medusa server and you want to access the options added for the plugin, you can access it in the constructor. The options are passed as a second parameter: +Additionally, if you’re creating your Payment Provider as an external plugin to be installed on any Medusa backend and you want to access the options added for the plugin, you can access it in the constructor. The options are passed as a second parameter: ```ts class MyPaymentService extends AbstractPaymentService { @@ -160,7 +167,7 @@ class MyPaymentService extends AbstractPaymentService { ### createPayment -This method is called during checkout when [Payment Sessions are initialized](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCartsCartPaymentSessions) to present payment options to the customer. It is used to allow you to make any necessary calls to the third-party provider to initialize the payment. +This method is called during checkout when [Payment Sessions are initialized](/api/store/#tag/Cart/operation/PostCartsCartPaymentSessions) to present payment options to the customer. It is used to allow you to make any necessary calls to the third-party provider to initialize the payment. For example, in Stripe this method is used to initialize a Payment Intent for the customer. @@ -192,20 +199,25 @@ This method must return an object of type `PaymentSessionResponse`. It should ha ```ts type PaymentSessionResponse = { - update_requests: { customer_metadata: Record } + update_requests: { + customer_metadata: Record + } session_data: Record } ``` Where: -- `session_data` is the data that is going to be stored in the `data` field of the Payment Session to be created. As mentioned in the [Architecture Overview](./overview.md), the `data` field is useful to hold any data required by the third-party provider to process the payment or retrieve its details at a later point. +- `session_data` is the data that is going to be stored in the `data` field of the Payment Session to be created. As mentioned in the [Architecture Overview](../payment.md), the `data` field is useful to hold any data required by the third-party provider to process the payment or retrieve its details at a later point. - `update_requests` is an object that can be used to pass data from the payment provider plugin to the core to update internal resources. Currently, it only has one attribute `customer_metadata` which allows updating the `metadata` field of the customer. An example of a minimal implementation of `createPayment`: ```ts -import { PaymentContext, PaymentSessionResponse } from "@medusajs/medusa" +import { + PaymentContext, + PaymentSessionResponse, +} from "@medusajs/medusa" class MyPaymentService extends AbstractPaymentService { // ... @@ -281,7 +293,7 @@ This code block assumes the status is stored in the `data` field as demonstrated ### updatePayment -This method is used to perform any necessary updates on the payment. This method is called whenever the cart or any of its related data is updated. For example, when a [line item is added to the cart](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCartsCartLineItems) or when a [shipping method is selected](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCartsCartShippingMethod). +This method is used to perform any necessary updates on the payment. This method is called whenever the cart or any of its related data is updated. For example, when a [line item is added to the cart](/api/store/#tag/Cart/operation/PostCartsCartLineItems) or when a [shipping method is selected](/api/store/#tag/Cart/operation/PostCartsCartShippingMethod). :::tip @@ -319,14 +331,16 @@ This method must return an object of type `PaymentSessionResponse`. It should ha ```ts type PaymentSessionResponse = { - update_requests: { customer_metadata: Record } + update_requests: { + customer_metadata: Record + } session_data: Record } ``` Where: -- `session_data` is the data that is going to be stored in the `data` field of the Payment Session to be created. As mentioned in the [Architecture Overview](./overview.md), the `data` field is useful to hold any data required by the third-party provider to process the payment or retrieve its details at a later point. +- `session_data` is the data that is going to be stored in the `data` field of the Payment Session to be created. As mentioned in the [Architecture Overview](../payment.md), the `data` field is useful to hold any data required by the third-party provider to process the payment or retrieve its details at a later point. - `update_requests` is an object that can be used to request from the Medusa core to update internal resources. Currently, it only has one attribute `customer_metadata` which allows updating the `metadata` field of the customer. An example of a minimal implementation of `updatePayment`: @@ -357,7 +371,7 @@ class MyPaymentService extends AbstractPaymentService { ### updatePaymentData -This method is used to update the `data` field of a Payment Session. Particularly, it is called when a request is sent to the [Update Payment Session](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCartsCartPaymentSessionUpdate) endpoint. This endpoint receives a `data` object in the body of the request that should be used to update the existing `data` field of the Payment Session. +This method is used to update the `data` field of a Payment Session. Particularly, it is called when a request is sent to the [Update Payment Session](/api/store/#tag/Cart/operation/PostCartsCartPaymentSessionUpdate) endpoint. This endpoint receives a `data` object in the body of the request that should be used to update the existing `data` field of the Payment Session. This method accepts the current `data` field of the Payment Session as the first parameter, and the new `data` field sent in the body request as the second parameter. @@ -386,8 +400,8 @@ class MyPaymentService extends AbstractPaymentService { This method is used to perform any actions necessary before a Payment Session is deleted. The Payment Session is deleted in one of the following cases: -1. When a request is sent to [delete the Payment Session](https://docs.medusajs.com/api/store/#tag/Cart/operation/DeleteCartsCartPaymentSessionsSession). -2. When the [Payment Session is refreshed](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCartsCartPaymentSessionsSession). The Payment Session is deleted so that a newer one is initialized instead. +1. When a request is sent to [delete the Payment Session](/api/store/#tag/Cart/operation/DeleteCartsCartPaymentSessionsSession). +2. When the [Payment Session is refreshed](/api/store/#tag/Cart/operation/PostCartsCartPaymentSessionsSession). The Payment Session is deleted so that a newer one is initialized instead. 3. When the Payment Provider is no longer available. This generally happens when the store operator removes it from the available Payment Provider in the admin. 4. When the region of the store is changed based on the cart information and the Payment Provider is not available in the new region. @@ -403,7 +417,9 @@ import { PaymentSession } from "@medusajs/medusa" class MyPaymentService extends AbstractPaymentService { // ... - async deletePayment(paymentSession: PaymentSession): Promise { + async deletePayment( + paymentSession: PaymentSession + ): Promise { return } } @@ -411,7 +427,7 @@ class MyPaymentService extends AbstractPaymentService { ### authorizePayment -This method is used to authorize payment using the Payment Session for an order. This is called when the [cart is completed](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCartsCartComplete) and before the order is created. +This method is used to authorize payment using the Payment Session for an order. This is called when the [cart is completed](/api/store/#tag/Cart/operation/PostCartsCartComplete) and before the order is created. This method is also used for authorizing payments of a swap of an order. @@ -430,7 +446,7 @@ The payment authorization status is determined using the `getStatus` method as m This method accepts the Payment Session as an object for its first parameter, and a `context` object as a second parameter. The `context` object contains the following properties: 1. `ip`: The customer’s IP. -2. `idempotency_key`: The [Idempotency Key](./overview.md#idempotency-key) that is associated with the current cart. It is useful when retrying payments, retrying checkout at a failed point, or for payments that require additional actions from the customer. +2. `idempotency_key`: The [Idempotency Key](../payment.md#idempotency-key) that is associated with the current cart. It is useful when retrying payments, retrying checkout at a failed point, or for payments that require additional actions from the customer. This method must return an object containing the property `status` which is a string that indicates the current status of the payment, and the property `data` which is an object containing any additional information required to perform additional payment processing such as capturing the payment. The values of both of these properties are stored in the Payment Session’s `status` and `data` fields respectively. @@ -452,7 +468,10 @@ class MyPaymentService extends AbstractPaymentService { async authorizePayment( paymentSession: PaymentSession, context: Data - ): Promise<{ data: PaymentSessionData; status: PaymentSessionStatus }> { + ): Promise<{ + data: PaymentSessionData; + status: PaymentSessionStatus + }> { return { status: PaymentSessionStatus.AUTHORIZED, data: { @@ -479,7 +498,9 @@ import { Data, PaymentSession } from "@medusajs/medusa" class MyPaymentService extends AbstractPaymentService { // ... - async getPaymentData(paymentSession: PaymentSession): Promise { + async getPaymentData( + paymentSession: PaymentSession + ): Promise { return paymentSession.data } } @@ -583,7 +604,7 @@ class MyPaymentService extends AbstractPaymentService { This method can be added to your Payment Provider service if your third-party provider supports saving the customer’s payment methods. Please note that in Medusa there is no way to save payment methods. -This method is called when a request is sent to [Retrieve Saved Payment Methods](https://docs.medusajs.com/api/store/#tag/Customer/operation/GetCustomersCustomerPaymentMethods). +This method is called when a request is sent to [Retrieve Saved Payment Methods](/api/store/#tag/Customer/operation/GetCustomersCustomerPaymentMethods). This method accepts the customer as an object for its first parameter. @@ -591,7 +612,7 @@ This method returns an array of saved payment methods retrieved from the third-p :::note -If you’re using Medusa’s [Next.js](../../../starters/nextjs-medusa-starter.mdx) or [Gatsby](../../../starters/gatsby-medusa-starter.mdx) storefront starters, note that the presentation of this method is not implemented. You’ll need to implement the UI and pages for this method based on your implementation and the provider you are using. +If you’re using Medusa’s [Next.js](../../../starters/nextjs-medusa-starter.mdx) storefront starter, note that the presentation of this method is not implemented. You’ll need to implement the UI and pages for this method based on your implementation and the provider you are using. ::: @@ -604,11 +625,14 @@ import { Customer, Data } from "@medusajs/medusa" class MyPaymentService extends AbstractPaymentService { // ... /** - * Fetches a customers saved payment methods if registered in Stripe. + * Fetches a customers saved payment methods + * if they're saved in Stripe. * @param {object} customer - customer to fetch saved cards for * @return {Promise>} saved payments methods */ - async retrieveSavedMethods(customer: Customer): Promise { + async retrieveSavedMethods( + customer: Customer + ): Promise { if (customer.metadata && customer.metadata.stripe_id) { const methods = await this.stripe_.paymentMethods.list({ customer: customer.metadata.stripe_id, @@ -628,4 +652,3 @@ class MyPaymentService extends AbstractPaymentService { ## See Also - Implementation Examples: [Stripe](https://github.com/medusajs/medusa/tree/2e6622ec5d0ae19d1782e583e099000f0a93b051/packages/medusa-payment-stripe) and [PayPal](https://github.com/medusajs/medusa/tree/2e6622ec5d0ae19d1782e583e099000f0a93b051/packages/medusa-payment-paypal) payment providers. -- [Implement checkout flow on the storefront](./../../storefront/how-to-implement-checkout-flow.mdx). diff --git a/docs/content/modules/carts-and-checkout/overview.mdx b/docs/content/modules/carts-and-checkout/overview.mdx new file mode 100644 index 0000000000000..edd410f467f3d --- /dev/null +++ b/docs/content/modules/carts-and-checkout/overview.mdx @@ -0,0 +1,172 @@ +--- +description: "A cart is a virtual shopping basket that customers can use to pick products they want to purchase. Learn about the available features and guides." +--- + +import DocCardList from '@theme/DocCardList'; +import Icons from '@theme/Icon'; + +# Carts and Checkout + +A cart is a virtual shopping basket that customers can use to pick products they want to purchase. Checkout is the process of the customer placing an order. This overview introduces the available features related to carts and checkout. + +## Features + +### Cart Management + +Customers can manage their cart including adding, updating, and removing items from the cart. + + + +### Shipping and Payment + +Developers can integrate any third-party provider or custom logic to offer shipping and payment options for customers during checkout. They can integrate them using existing plugins or by creating their own. + +Admins can specify available shipping and payment providers during checkout for customers based on their [Region](../regions-and-currencies/overview.mdx). + + + +### Checkout Flow + +Developers can implement a seamless checkout flow that include steps related to shipping and payment, tax calculation, and more. + +Customers can place orders using the checkout flow. + + + +--- + +## Understand the Architecture + +Learn how cart-related entities are build, their relation to other modules, and more. + + + +--- + +## Related Modules + +Discover Carts and Checkout’s relation to other modules in Medusa + + \ No newline at end of file diff --git a/docs/content/advanced/backend/payment/overview.md b/docs/content/modules/carts-and-checkout/payment.md similarity index 81% rename from docs/content/advanced/backend/payment/overview.md rename to docs/content/modules/carts-and-checkout/payment.md index f146244bdce3b..b345c8ea9bedc 100644 --- a/docs/content/advanced/backend/payment/overview.md +++ b/docs/content/modules/carts-and-checkout/payment.md @@ -1,5 +1,5 @@ --- -description: 'Learn about the payment architecture in the Medusa server. The payment architecture refers to all operations in the ecommerce store related to processing payments.' +description: 'Learn about the payment architecture in the Medusa backend. The payment architecture refers to all operations in the ecommerce store related to processing payments.' --- # Payment Architecture Overview @@ -30,13 +30,13 @@ Payment Providers can also be related to a custom way of handling payment operat ### How Payment Provider is Created -A Payment Provider is essentially a Medusa [service](../services/create-service.md) with a unique identifier, and it extends the ``AbstractPaymentService` from the core Medusa package `@medusajs/medusa`. It can be created as part of a [plugin](../plugins/overview.md), or it can be created just as a service file in your Medusa server. +A Payment Provider is essentially a Medusa [service](../../development/services/create-service.md) with a unique identifier, and it extends the ``AbstractPaymentService` from the core Medusa package `@medusajs/medusa`. It can be created as part of a [plugin](../../development/plugins/overview.mdx), or it can be created just as a service file in your Medusa backend. As a developer, you will mainly work with the Payment Provider when integrating a payment method in Medusa. -When you run your Medusa server, the Payment Provider will be registered on your server if it hasn’t been already. +When you run your Medusa backend, the Payment Provider will be registered on your backend if it hasn’t been already. -Once the Payment Provider is added to the server, the store operator will be able to choose on the [Medusa Admin](../../../admin/quickstart.mdx) the payment providers available in a region. These payment providers are shown to the customer at checkout to choose from and use. +Once the Payment Provider is added to the backend, the store operator will be able to choose on the [Medusa Admin](../../admin/quickstart.mdx) the payment providers available in a region. These payment providers are shown to the customer at checkout to choose from and use. :::caution @@ -46,7 +46,7 @@ It’s important to choose a payment provider in the list of payment providers i ### PaymentProvider Entity Overview -The [`PaymentProvider`](../../../references/entities/classes/PaymentProvider.md) entity only has 2 attributes: `is_installed` to indicate if the payment provider is installed and its value is a boolean; and `id` which is the unique identifier that you define in the Payment Provider service. +The [`PaymentProvider`](../../references/entities/classes/PaymentProvider.md) entity only has 2 attributes: `is_installed` to indicate if the payment provider is installed and its value is a boolean; and `id` which is the unique identifier that you define in the Payment Provider service. --- @@ -70,7 +70,7 @@ Among the Payment Sessions available only one will be selected based on the cust ### PaymentSession Entity Overview -The [`PaymentSession`](../../../references/entities/classes/PaymentSession.md) entity belongs to a `Cart`. This is the customer‘s cart that was used for checkout which lead to the creation of the Payment Session. +The [`PaymentSession`](../../references/entities/classes/PaymentSession.md) entity belongs to a `Cart`. This is the customer‘s cart that was used for checkout which lead to the creation of the Payment Session. The `PaymentSession` also belongs to a `PaymentProvider`. This is the Payment Provider that was used to create the Payment Session and that controls it for further actions like authorizing the payment. @@ -104,7 +104,7 @@ When the store operator then chooses to capture the order from the Medusa Admin, ### Payment Entity Overview -The [`Payment`](../../../references/entities/classes/Payment.md) entity belongs to the `Cart` that it was originally created from when the customer’s payment was authorized. It also belongs to an `Order` once it’s placed. Additionally, it belongs to a `PaymentProvider` which is the payment provider that the customer chose on checkout. +The [`Payment`](../../references/entities/classes/Payment.md) entity belongs to the `Cart` that it was originally created from when the customer’s payment was authorized. It also belongs to an `Order` once it’s placed. Additionally, it belongs to a `PaymentProvider` which is the payment provider that the customer chose on checkout. In case a `Swap` is created for an order, `Payment` will be associated with that swap to handle payment operations related to it. @@ -124,7 +124,7 @@ That Idempotency Key is then set in the header under the `Idempotency-Key` respo If an error occurs or the purchase is interrupted at any step, the client can retry the payment by adding the Idempotency Key of the cart as the `Idempotency-Key` header field in their subsequent requests. -The server wraps each essential part of the checkout completion in its own step and stores the current step of checkout with its associated Idempotency Key. +The backend wraps each essential part of the checkout completion in its own step and stores the current step of checkout with its associated Idempotency Key. If then the request is interrupted for any reason or the payment fails, the client can retry completing the check out using the Idempotency Key, and the flow will continue from the last stored step. @@ -134,5 +134,5 @@ This prevents any payment issues from occurring with the customers and allows fo ## See Also -- [Create a Payment Provider](./how-to-create-payment-provider.md) -- [Implement the checkout flow in the storefront](./../../storefront/how-to-implement-checkout-flow.mdx) +- [Available Payment Plugins](../../plugins/payment/index.mdx) +- [Create a Payment Provider](./backend/add-payment-provider.md) \ No newline at end of file diff --git a/docs/content/advanced/backend/shipping/overview.md b/docs/content/modules/carts-and-checkout/shipping.md similarity index 83% rename from docs/content/advanced/backend/shipping/overview.md rename to docs/content/modules/carts-and-checkout/shipping.md index a12fb128d76bd..bb64b96451345 100644 --- a/docs/content/advanced/backend/shipping/overview.md +++ b/docs/content/modules/carts-and-checkout/shipping.md @@ -1,5 +1,5 @@ --- -description: 'Learn how the shipping architecture is implemented in the Medusa server. This includes an overview of what the Fulfillment Provider, Shipping Profile, Shipping Option, and Shipping Methods.' +description: 'Learn how the shipping architecture is implemented in the Medusa backend. This includes an overview of what the Fulfillment Provider, Shipping Profile, Shipping Option, and Shipping Methods.' --- # Shipping Architecture Overview @@ -18,12 +18,12 @@ It’s also constructed to support multiple regions, provide different shipment ## Summary -- **Fulfillment Provider:** Fulfillment providers are plugins or [Services](../services/create-service.md) used to ship the products to your customers, whether physically or virtually. An example of a fulfillment provider would be FedEx. +- **Fulfillment Provider:** Fulfillment providers are plugins or [Services](../../development/services/create-service.md) used to ship the products to your customers, whether physically or virtually. An example of a fulfillment provider would be FedEx. - **Shipping Profiles:** created by the admin. They are used to group products that should be shipped in a different manner than the default. Shipping profiles can have multiple shipping options. - **Shipping Options:** created by the admin and belong to a shipping profile. They are specific to certain regions and can have cart conditions. They use an underlying fulfillment provider. Once a customer checks out, they can choose the shipping option that’s available and most relevant to them. - **Shipping Method:** created when the customer chooses a shipping option on checkout. The shipping method is basically a copy of the shipping option, but with values specific to the customer and the cart it’s associated with. When the order is placed, the shipping method will then be associated with the order and fulfilled based on the integration with the fulfillment provider. -![Shipping Architecture](https://res.cloudinary.com/dza7lstvk/image/upload/v1668001762/Medusa%20Docs/Diagrams/QII2Hvn_vjkrdy.png) +![Shipping Architecture](https://res.cloudinary.com/dza7lstvk/image/upload/v1677698747/Medusa%20Docs/Diagrams/shipping-architecture_oszxhj.jpg) --- @@ -39,17 +39,17 @@ Fulfillment Providers can also be related to a custom way of handling fulfillmen ### How Fulfillment Provider is Created -A Fulfillment Provider is essentially a Medusa [Service](../services/create-service.md) with a unique identifier, and it extends the `FulfillmentService` provided by the `medusa-interfaces` package. It can be created as part of a [plugin](../plugins/overview.md), or it can be created just as a Service file in your Medusa server. +A Fulfillment Provider is essentially a Medusa [Service](../../development/services/create-service.md) with a unique identifier, and it extends the `FulfillmentService` provided by the `medusa-interfaces` package. It can be created as part of a [plugin](../../development/plugins/overview.mdx), or it can be created just as a Service file in your Medusa backend. As a developer, you will mainly work with the Fulfillment Provider when integrating a fulfillment method in Medusa. -When you run your Medusa server, the Fulfillment Provider will be registered on your server if it hasn’t been already. +When you run your Medusa backend, the Fulfillment Provider will be registered on your backend if it hasn’t been already. -Once the Fulfillment Provider is added to the server, the store operator will be able to associate on the [Medusa Admin](../../../quickstart/quick-start.mdx) the Fulfillment Provider with shipping options. +Once the Fulfillment Provider is added to the backend, the store operator will be able to associate on the [Medusa Admin](../../development/backend/install.mdx) the Fulfillment Provider with shipping options. ### FulfillmentProvider Entity Overview -The [`FulfillmentProvider`](../../../references/entities/classes/FulfillmentProvider.md) entity only has 2 attributes: `is_installed` to indicate if the fulfillment provider is installed and its value is a boolean; and `id` which is the unique identifier that you define in the Fulfillment Provider Service. +The [`FulfillmentProvider`](../../references/entities/classes/FulfillmentProvider.md) entity only has 2 attributes: `is_installed` to indicate if the fulfillment provider is installed and its value is a boolean; and `id` which is the unique identifier that you define in the Fulfillment Provider Service. --- @@ -73,7 +73,7 @@ For example, shipping heavy items might be more expensive than others, which wou ### ShippingProfile Entity Overview -The [`ShippingProfile`](../../../references/entities/classes/ShippingProfile.md) entity can have a set of `Product` instances. These would be the products the shipping profile is providing shipping options for. +The [`ShippingProfile`](../../references/entities/classes/ShippingProfile.md) entity can have a set of `Product` instances. These would be the products the shipping profile is providing shipping options for. The `ShippingProfile` has a `type` attribute that can be `default`, `gift_card`, or `custom`. @@ -101,7 +101,7 @@ Think of a shipping option as a template defined by the admin that indicates wha ### ShippingOption Entity Overview -The [`ShippingOption`](../../../references/entities/classes/ShippingOption.md) entity belongs to the `ShippingProfile` entity. +The [`ShippingOption`](../../references/entities/classes/ShippingOption.md) entity belongs to the `ShippingProfile` entity. The `ShippingOption` entity also belongs to a `FulfillmentProvider`. This can be either a custom third-party provider or one of Medusa’s default fulfillment providers. @@ -139,7 +139,7 @@ This separation allows for developers to implement the custom integration with t A lot of the shipping method’s attributes are similar to the shipping option’s attribute. -The [`ShippingMethod`](../../../references/entities/classes/ShippingMethod.md) entity belongs to a `ShippingOption`. +The [`ShippingMethod`](../../references/entities/classes/ShippingMethod.md) entity belongs to a `ShippingOption`. Similar to the `data` attribute explained for the `ShippingOption` entity, a `ShippingMethod` has a similar `data` attribute that includes all the data to be sent to the fulfillment provider when fulfilling the order. @@ -153,5 +153,5 @@ The `ShippingMethod` instance holds a `price` attribute, which will either b ## See Also -- [Create a Fulfillment Provider](./add-fulfillment-provider.md) +- [Create a Fulfillment Provider](./backend/add-fulfillment-provider.md) - [Available shipping plugins](https://github.com/medusajs/medusa/tree/master/packages) diff --git a/docs/content/guides/carts-in-medusa.mdx b/docs/content/modules/carts-and-checkout/storefront/implement-cart.mdx similarity index 87% rename from docs/content/guides/carts-in-medusa.mdx rename to docs/content/modules/carts-and-checkout/storefront/implement-cart.mdx index 5e3357024b74a..b70387bb2b730 100644 --- a/docs/content/guides/carts-in-medusa.mdx +++ b/docs/content/modules/carts-and-checkout/storefront/implement-cart.mdx @@ -18,7 +18,7 @@ This document helps you understand how to add the cart functionality to your sto :::note -This document does not cover implementing the checkout flow. You can refer to [this documentation instead to learn how to implement the checkout flow](../advanced/storefront/how-to-implement-checkout-flow.mdx). +This document does not cover implementing the checkout flow. You can refer to [this documentation instead to learn how to implement the checkout flow](./implement-checkout-flow.mdx). ::: @@ -28,23 +28,23 @@ This document does not cover implementing the checkout flow. You can refer to [t ### Medusa Components -It's assumed that you already have a Medusa server installed and set up. If not, you can follow our [quickstart guide](../quickstart/quick-start.mdx) to get started. +It's assumed that you already have a Medusa backend installed and set up. If not, you can follow our [quickstart guide](../../../development/backend/install.mdx) to get started. -It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install either the [Next.js](../starters/nextjs-medusa-starter.mdx) or [Gatsby](../starters/gatsby-medusa-starter.mdx) storefronts. +It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install the [Next.js starter storefront](../../../starters/nextjs-medusa-starter.mdx). ### JS Client -This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client, among other methods. +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, among other methods. -If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../js-client/overview.md) and have [created an instance of the client](../js-client/overview.md#configuration). +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../../../js-client/overview.md) and have [created an instance of the client](../../../js-client/overview.md#configuration). ### Medusa React -This guide also includes code snippets to send requests to your Medusa server using Medusa React, among other methods. +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. -If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../medusa-react/overview.md#usage). +If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). -It's also assumed you already have [used CartProvider higher in your component tree](../medusa-react/overview.md#cartprovider). +It's also assumed you already have [used CartProvider higher in your component tree](../../../medusa-react/overview.md#cartprovider). --- @@ -77,7 +77,9 @@ const Cart = () => { createCart.mutate( {}, // create an empty cart { - onSuccess: ({ cart }) => localStorage.setItem("cart_id", cart.id), + onSuccess: ({ cart }) => { + localStorage.setItem("cart_id", cart.id) + }, } ) } @@ -92,7 +94,7 @@ export default Cart ```ts -fetch(`/store/carts`, { +fetch(`/store/carts`, { method: "POST", credentials: "include", }) @@ -142,7 +144,9 @@ const Cart = () => { region_id, }, { - onSuccess: ({ cart }) => localStorage.setItem("cart_id", cart.id), + onSuccess: ({ cart }) => { + localStorage.setItem("cart_id", cart.id) + }, } ) } @@ -157,7 +161,7 @@ export default Cart ```jsx -fetch(`/store/carts`, { +fetch(`/store/carts`, { method: "POST", credentials: "include", headers: { @@ -178,7 +182,7 @@ fetch(`/store/carts`, { -Check out the [API Reference](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCart) for a full list of available request body parameters. +Check out the [API Reference](/api/store/#tag/Cart/operation/PostCart) for a full list of available request body parameters. :::note @@ -228,7 +232,7 @@ export default Cart const id = localStorage.getItem("cart_id") if (id) { - fetch(`/store/carts/${id}`, { + fetch(`/store/carts/${id}`, { credentials: "include", }) .then((response) => response.json()) @@ -241,7 +245,7 @@ if (id) { This request accepts the ID of the cart as a path parameter and returns the cart of that ID. -You can run this code snippet every time the storefront is opened. If a customer has a cart ID stored in their local storage, it’s loaded from the server. +You can run this code snippet every time the storefront is opened. If a customer has a cart ID stored in their local storage, it’s loaded from the backend. :::tip @@ -294,7 +298,7 @@ export default Cart ```ts -fetch(`/store/carts/${cartId}`, { +fetch(`/store/carts/${cartId}`, { method: "POST", credentials: "include", headers: { @@ -315,7 +319,7 @@ This request accepts the ID of the cart as a path parameter. In its body, you ca It returns the updated cart. -Check out the full list of available request body parameters in the [API Reference](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCartsCart). +Check out the full list of available request body parameters in the [API Reference](/api/store/#tag/Cart/operation/PostCartsCart). ### Associate a Logged-In Customer with the Cart @@ -360,7 +364,7 @@ export default Cart ```ts -fetch(`/store/carts/${cartId}`, { +fetch(`/store/carts/${cartId}`, { method: "POST", credentials: "include", headers: { @@ -422,7 +426,7 @@ export default Cart ```ts -fetch(`/store/carts/${cartId}`, { +fetch(`/store/carts/${cartId}`, { method: "POST", credentials: "include", headers: { @@ -484,7 +488,7 @@ export default Cart ```jsx -fetch(`/store/carts/${cartId}/line-items`, { +fetch(`/store/carts/${cartId}/line-items`, { method: "POST", credentials: "include", headers: { @@ -557,8 +561,10 @@ export default Cart + + ```ts -fetch(`/store/carts/${cartId}/line-items/${lineItemId}`, { +fetch(`/store/carts/${cartId}/line-items/${lineItemId}`, { method: "POST", credentials: "include", headers: { @@ -619,8 +625,10 @@ export default Cart + + ```ts -fetch(`/store/carts/${cartId}/line-items/${lineItemId}`, { +fetch(`/store/carts/${cartId}/line-items/${lineItemId}`, { method: "DELETE", credentials: "include", }) @@ -639,5 +647,4 @@ It returns the updated cart. ## See Also -- [Implement the checkout flow in your storefront](../advanced/storefront/how-to-implement-checkout-flow.mdx) -- [Medusa JS Client Overview](../js-client/overview.md) +- [Implement the checkout flow in your storefront](./implement-checkout-flow.mdx) \ No newline at end of file diff --git a/docs/content/advanced/storefront/how-to-implement-checkout-flow.mdx b/docs/content/modules/carts-and-checkout/storefront/implement-checkout-flow.mdx similarity index 76% rename from docs/content/advanced/storefront/how-to-implement-checkout-flow.mdx rename to docs/content/modules/carts-and-checkout/storefront/implement-checkout-flow.mdx index 22d66d070ff31..bf0df098107c6 100644 --- a/docs/content/advanced/storefront/how-to-implement-checkout-flow.mdx +++ b/docs/content/modules/carts-and-checkout/storefront/implement-checkout-flow.mdx @@ -18,7 +18,7 @@ This document will take you through the general process of a checkout flow. You :::note -It’s recommended to go through the [Shipping Architecture Overview](../backend/shipping/overview.md) and [Payment Architecture Overview](../backend/payment/overview.md) first to have a better understanding of Medusa’s architecture. +It’s recommended to go through the [Shipping Architecture Overview](../shipping.md) and [Payment Architecture Overview](../payment.md) first to have a better understanding of Medusa’s architecture. ::: @@ -28,29 +28,29 @@ It’s recommended to go through the [Shipping Architecture Overview](../backend ### Medusa Components -It's assumed that you already have a Medusa server installed and set up. If not, you can follow our [quickstart guide](../../quickstart/quick-start.mdx) to get started. +It's assumed that you already have a Medusa backend installed and set up. If not, you can follow our [quickstart guide](../../../development/backend/install.mdx) to get started. -It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install either the [Next.js](../../starters/nextjs-medusa-starter.mdx) or [Gatsby](../../starters/gatsby-medusa-starter.mdx) storefronts. +It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install the [Next.js starter storefront](../../../starters/nextjs-medusa-starter.mdx). ### JS Client -This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client and JavaScript’s Fetch API. +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client and JavaScript’s Fetch API. -If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../../js-client/overview.md) and have [created an instance of the client](../../js-client/overview.md#configuration). +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../../../js-client/overview.md) and have [created an instance of the client](../../../js-client/overview.md#configuration). ### Medusa React -This guide also includes code snippets to send requests to your Medusa server using Medusa React, among other methods. +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. -If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../medusa-react/overview.md#usage). +If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). -It's also assumed you already have [used CartProvider higher in your component tree](../../medusa-react/overview.md#cartprovider). +It's also assumed you already have [used CartProvider higher in your component tree](../../../medusa-react/overview.md#cartprovider). ### Previous Steps This document assumes you’ve already taken care of the add-to-cart flow. So, you should have a [cart created](/api/store/#tag/Cart/operation/PostCart) for the customer with at least [one product in it](/api/store/#tag/Cart/operation/PostCartsCartLineItems). -You can learn how to implement the cart flow using [this documentation](../../guides/carts-in-medusa.mdx). +You can learn how to implement the cart flow using [this documentation](./implement-cart.mdx). --- @@ -96,22 +96,23 @@ const Cart = () => { const { updateCart } = useCart() - const addShippingAddress = (address: Record) => { - updateCart.mutate({ - shipping_address: { - company: address.company, - first_name: address.first_name, - last_name: address.last_name, - address_1: address.address_1, - address_2: address.address_2, - city: address.city, - country_code: address.country_code, - province: address.province, - postal_code: address.postal_code, - phone: address.phone, - }, - }) - } + const addShippingAddress = + (address: Record) => { + updateCart.mutate({ + shipping_address: { + company: address.company, + first_name: address.first_name, + last_name: address.last_name, + address_1: address.address_1, + address_2: address.address_2, + city: address.city, + country_code: address.country_code, + province: address.province, + postal_code: address.postal_code, + phone: address.phone, + }, + }) + } // ... } @@ -123,7 +124,7 @@ export default Cart ```ts -fetch(`/store/carts/${cartId}`, { +fetch(`/store/carts/${cartId}`, { method: "POST", credentials: "include", body: JSON.stringify({ @@ -161,7 +162,7 @@ The request returns the updated cart, with the new shipping address available in ### List Shipping Options -After updating the cart with the customer’s address, the list of available [shipping options](../backend/shipping/overview.md#shipping-option) for that cart might change. So, you should retrieve the updated list of options. +After updating the cart with the customer’s address, the list of available [shipping options](../shipping.md#shipping-option) for that cart might change. So, you should retrieve the updated list of options. You can retrieve the list of shipping options by sending a `GET` request to the [Retrieve Shipping Options for Cart API](/api/store/#tag/Shipping-Option/operation/GetShippingOptionsCartId) endpoint: @@ -187,7 +188,8 @@ type Props = { } const ShippingOptions = ({ cartId }: Props) => { - const { shipping_options, isLoading } = useCartShippingOptions(cartId) + const { shipping_options, isLoading } = + useCartShippingOptions(cartId) return (
@@ -197,9 +199,13 @@ const ShippingOptions = ({ cartId }: Props) => { )} {shipping_options && (
    - {shipping_options.map((shipping_option: ShippingOption) => ( -
  • {shipping_option.name}
  • - ))} + {shipping_options.map( + (shipping_option: ShippingOption) => ( +
  • + {shipping_option.name} +
  • + ) + )}
)}
@@ -213,7 +219,7 @@ export default ShippingOptions ```ts -fetch(`/store/shipping-options/${cartId}`, { +fetch(`/store/shipping-options/${cartId}`, { credentials: "include", }) .then((response) => response.json()) @@ -229,7 +235,7 @@ The request accepts the ID of the cart as a path parameter. It returns the array ### Choose Shipping Option -Once the customer chooses one of the available shipping options, send a `POST` request to the [Add a Shipping Method](/api/store/#tag/Cart/operation/PostCartsCartShippingMethod) API endpoint. This will create a [shipping method](../backend/shipping/overview.md#shipping-method) based on the shipping option chosen and will associate it with the customer’s cart: +Once the customer chooses one of the available shipping options, send a `POST` request to the [Add a Shipping Method](/api/store/#tag/Cart/operation/PostCartsCartShippingMethod) API endpoint. This will create a [shipping method](../shipping.md#shipping-method) based on the shipping option chosen and will associate it with the customer’s cart: @@ -270,11 +276,11 @@ export default ShippingOptions ```ts -fetch(`/store/carts/${cartId}/shipping-methods`, { +fetch(`/store/carts/${cartId}/shipping-methods`, { method: "POST", credentials: "include", body: JSON.stringify({ - option_id: shippingOptionId, // the ID of the selected option + option_id: shippingOptionId, // ID of the selected option }), headers: { "Content-Type": "application/json", @@ -301,7 +307,7 @@ In this step, the customer generally chooses a payment method to complete their ### Initialize Payment Sessions -When the page opens and before the payment providers are displayed to the customer to choose from, you must initialize the [payment sessions](./../backend/payment/overview.md#payment-session) for the current cart. Each payment provider will have a payment session associated with it. These payment sessions will be used later when the customer chooses the payment provider they want to complete their purchase with. +When the page opens and before the payment providers are displayed to the customer to choose from, you must initialize the [payment sessions](../payment.md#payment-session) for the current cart. Each payment provider will have a payment session associated with it. These payment sessions will be used later when the customer chooses the payment provider they want to complete their purchase with. To initialize the payment sessions, send a `POST` request to the [Initialize Payment Sessions](/api/store/#tag/Cart/operation/PostCartsCartPaymentSessions) API endpoint: @@ -332,11 +338,17 @@ const PaymentProviders = () => { return (
- {!cart?.payment_sessions.length && No payment providers} + {!cart?.payment_sessions.length && ( + No payment providers + )}
    - {cart?.payment_sessions.map((paymentSession: PaymentSession) => ( -
  • {paymentSession.provider_id}
  • - ))} + {cart?.payment_sessions.map( + (paymentSession: PaymentSession) => ( +
  • + {paymentSession.provider_id} +
  • + ) + )}
) @@ -349,7 +361,7 @@ export default PaymentProviders ```ts -fetch(`/store/carts/${cartId}/payment-sessions`, { +fetch(`/store/carts/${cartId}/payment-sessions`, { method: "POST", credentials: "include", }) @@ -407,11 +419,11 @@ export default PaymentProviders ```ts -fetch(`/store/carts/${cartId}/payment-session`, { +fetch(`/store/carts/${cartId}/payment-session`, { method: "POST", credentials: "include", body: JSON.stringify({ - // retrieved from the payment session selected by the customer + // the payment session selected by the customer provider_id: paymentProviderId, }), headers: { @@ -439,7 +451,7 @@ If you have one payment provider or if only one payment provider is available fo ### Update Payment Session -This step is optional and is only necessary for some payment providers. As mentioned in the [Payment Architecture](../backend/payment/overview.md#overview) documentation, the `PaymentSession` model has a `data` attribute that holds any data required for the Payment Provider to perform payment operations such as capturing payment. +This step is optional and is only necessary for some payment providers. As mentioned in the [Payment Architecture](../payment.md#overview) documentation, the `PaymentSession` model has a `data` attribute that holds any data required for the Payment Provider to perform payment operations such as capturing payment. If you need to update that data at any point before the purchase is made, send a request to [Update a Payment Session](/api/store/#tag/Cart/operation/PostCartsCartPaymentSessionUpdate) API endpoint: @@ -494,7 +506,7 @@ export default PaymentProviders ```ts fetch( - `/store/carts/${cartId}/payment-sessions/${paymentProviderId}`, + `/store/carts/${cartId}/payment-sessions/${paymentProviderId}`, { method: "POST", credentials: "include", @@ -525,7 +537,7 @@ It returns the updated cart. You can access the payment session's data on `cart. ### Complete Cart -The last step is to place the order by completing the cart. When you complete the cart, your Medusa server will try to authorize the payment first, then place the order if the authorization is successful. So, you should perform any necessary action with your payment provider first to make sure the authorization is successful when you send the request to complete the cart. +The last step is to place the order by completing the cart. When you complete the cart, your Medusa backend will try to authorize the payment first, then place the order if the authorization is successful. So, you should perform any necessary action with your payment provider first to make sure the authorization is successful when you send the request to complete the cart. To complete a cart, send a `POST` request to the [Complete a Cart](/api/store/#tag/Cart/operation/PostCartsCartComplete) API endpoint: @@ -564,7 +576,7 @@ export default Cart ```ts -fetch(`/store/carts/${cartId}/complete`, { +fetch(`/store/carts/${cartId}/complete`, { method: "POST", credentials: "include", headers: { @@ -584,13 +596,4 @@ This request accepts the ID of the cart as a path parameter. The request returns two properties: `type` and `data`. If the order was placed successfully, `type` will be `order` and `data` will be the order's data. -If an error occurred while placing the order, `type` will be `cart` and `data` will be the cart's data. - ---- - -## See Also - -- [Medusa JS Client Overview](../../js-client/overview.md). -- Check out available plugins for popular payment providers such as [Stripe](../../add-plugins/stripe.md) and [PayPal](/add-plugins/paypal.md). -- [Payment Architecture](../backend/payment/overview.md) -- [Shipping Architecture](../backend/shipping/overview.md) +If an error occurred while placing the order, `type` will be `cart` and `data` will be the cart's data. \ No newline at end of file diff --git a/docs/content/advanced/admin/use-customergroups-api.mdx b/docs/content/modules/customers/admin/manage-customer-groups.mdx similarity index 78% rename from docs/content/advanced/admin/use-customergroups-api.mdx rename to docs/content/modules/customers/admin/manage-customer-groups.mdx index d528d35188c5a..4b6a3e3829fd9 100644 --- a/docs/content/advanced/admin/use-customergroups-api.mdx +++ b/docs/content/modules/customers/admin/manage-customer-groups.mdx @@ -24,25 +24,25 @@ This guide covers how to use these APIs to perform these tasks. ### Medusa Components -It is assumed that you already have a Medusa server installed and set up. If not, you can follow our [quickstart guide](../../quickstart/quick-start.mdx) to get started. +It is assumed that you already have a Medusa backend installed and set up. If not, you can follow our [quickstart guide](../../../development/backend/install.mdx) to get started. ### JS Client -This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client, among other methods. +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, among other methods. -If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../js-client/overview.md) installed and have [created an instance of the client](../../js-client/overview.md#configuration). +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../../js-client/overview.md) installed and have [created an instance of the client](../../../js-client/overview.md#configuration). ### Medusa React -This guide also includes code snippets to send requests to your Medusa server using Medusa React, among other methods. +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. -If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../medusa-react/overview.md#usage). +If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). ### Authenticated Admin User You must be an authenticated admin user before following along with the steps in the tutorial. -You can learn more about [authenticating as an admin user in the API reference](https://docs.medusajs.com/api/admin/#section/Authentication). +You can learn more about [authenticating as an admin user in the API reference](/api/admin/#section/Authentication). --- @@ -94,7 +94,7 @@ export default CreateCustomerGroup ```ts -fetch(`/admin/customer-groups`, { +fetch(`/admin/customer-groups`, { method: "POST", credentials: "include", headers: { @@ -114,7 +114,7 @@ fetch(`/admin/customer-groups`, { ```bash -curl -L -X POST '/admin/customer-groups' \ +curl -L -X POST '/admin/customer-groups' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -151,7 +151,10 @@ import { CustomerGroup } from "@medusajs/medusa" import { useAdminCustomerGroups } from "medusa-react" const CustomerGroups = () => { - const { customer_groups, isLoading } = useAdminCustomerGroups() + const { + customer_groups, + isLoading, + } = useAdminCustomerGroups() return (
@@ -161,9 +164,13 @@ const CustomerGroups = () => { )} {customer_groups && customer_groups.length > 0 && (
    - {customer_groups.map((customerGroup: CustomerGroup) => ( -
  • {customerGroup.name}
  • - ))} + {customer_groups.map( + (customerGroup: CustomerGroup) => ( +
  • + {customerGroup.name} +
  • + ) + )}
)}
@@ -177,7 +184,7 @@ export default CustomerGroups ```ts -fetch(`/admin/customer-groups`, { +fetch(`/admin/customer-groups`, { credentials: "include", }) .then((response) => response.json()) @@ -190,7 +197,7 @@ fetch(`/admin/customer-groups`, { ```bash -curl -L -X GET '/admin/customer-groups' \ +curl -L -X GET '/admin/customer-groups' \ -H 'Authorization: Bearer ' ``` @@ -199,7 +206,7 @@ curl -L -X GET '/admin/customer-groups' \ This request returns an array of customer groups, as well as pagination fields. -You can also pass filters and other selection query parameters to the request. Check out the [API reference](https://docs.medusajs.com/api/admin/#tag/Customer-Group/operation/GetCustomerGroups) for more details on available query parameters. +You can also pass filters and other selection query parameters to the request. Check out the [API reference](/api/admin/#tag/Customer-Group/operation/GetCustomerGroups) for more details on available query parameters. --- @@ -243,9 +250,12 @@ export default CustomerGroup ```ts -fetch(`/admin/customer-groups/${customerGroupId}`, { - credentials: "include", -}) +fetch( + `/admin/customer-groups/${customerGroupId}`, + { + credentials: "include", + } +) .then((response) => response.json()) .then(({ customer_group }) => { console.log(customer_group.id) @@ -256,7 +266,7 @@ fetch(`/admin/customer-groups/${customerGroupId}`, { ```bash -curl -L -X GET '/admin/customer-groups/' \ +curl -L -X GET '/admin/customer-groups/' \ -H 'Authorization: Bearer ' ``` @@ -292,7 +302,9 @@ medusa.admin.customerGroups.update(customerGroupId, { import { useAdminUpdateCustomerGroup } from "medusa-react" const UpdateCustomerGroup = () => { - const updateCustomerGroup = useAdminUpdateCustomerGroup(customerGroupId) + const updateCustomerGroup = useAdminUpdateCustomerGroup( + customerGroupId + ) // .. const handleUpdate = () => { @@ -317,18 +329,21 @@ export default UpdateCustomerGroup ```ts -fetch(`/admin/customer-groups/${customerGroupId}`, { - method: "POST", - credentials: "include", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - metadata: { - is_seller: true, - }, - }), -}) +fetch( + `/admin/customer-groups/${customerGroupId}`, + { + method: "POST", + credentials: "include", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + metadata: { + is_seller: true, + }, + }), + } +) .then((response) => response.json()) .then(({ customer_group }) => { console.log(customer_group.id) @@ -339,7 +354,7 @@ fetch(`/admin/customer-groups/${customerGroupId}`, { ```bash -curl -L -X POST '/admin/customer-groups/' \ +curl -L -X POST '/admin/customer-groups/' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -377,7 +392,9 @@ medusa.admin.customerGroups.delete(customerGroupId) import { useAdminDeleteCustomerGroup } from "medusa-react" const CustomerGroup = () => { - const deleteCustomerGroup = useAdminDeleteCustomerGroup(customerGroupId) + const deleteCustomerGroup = useAdminDeleteCustomerGroup( + customerGroupId + ) // ... const handleDeleteCustomerGroup = () => { @@ -394,10 +411,13 @@ export default CustomerGroup ```ts -fetch(`/admin/customer-groups/${customerGroupId}`, { - method: "DELETE", - credentials: "include", -}) +fetch( + `/admin/customer-groups/${customerGroupId}`, + { + method: "DELETE", + credentials: "include", + } +) .then((response) => response.json()) .then(({ id, object, deleted }) => { console.log(id) @@ -408,7 +428,7 @@ fetch(`/admin/customer-groups/${customerGroupId}`, { ```bash -curl -L -X DELETE '/admin/customer-groups/' \ +curl -L -X DELETE '/admin/customer-groups/' \ -H 'Authorization: Bearer ' ``` @@ -445,10 +465,14 @@ medusa.admin.customerGroups.addCustomers(customerGroupId, { ```tsx -import { useAdminAddCustomersToCustomerGroup } from "medusa-react" +import { + useAdminAddCustomersToCustomerGroup, +} from "medusa-react" const CustomerGroup = () => { - const addCustomers = useAdminAddCustomersToCustomerGroup(customerGroupId) + const addCustomers = useAdminAddCustomersToCustomerGroup( + customerGroupId + ) // ... const handleAddCustomers= (customerId: string) => { @@ -470,9 +494,11 @@ export default CustomerGroup + + ```ts fetch( - `/admin/customer-groups/${customerGroupId}/customers/batch`, + `/admin/customer-groups/${customerGroupId}/customers/batch`, { method: "POST", credentials: "include", @@ -498,7 +524,7 @@ fetch( ```bash -curl -L -X POST '/admin/customer-groups//customers/batch' \ +curl -L -X POST '/admin/customer-groups//customers/batch' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -537,14 +563,19 @@ import { Customer } from "@medusajs/medusa" import { useAdminCustomerGroupCustomers } from "medusa-react" const CustomerGroup = () => { - const { customers, isLoading } = useAdminCustomerGroupCustomers( + const { + customers, + isLoading, + } = useAdminCustomerGroupCustomers( customerGroupId ) return (
{isLoading && Loading...} - {customers && !customers.length && No customers} + {customers && !customers.length && ( + No customers + )} {customers && customers.length > 0 && (
    {customers.map((customer: Customer) => ( @@ -562,8 +593,10 @@ export default CustomerGroup + + ```ts -fetch(`/admin/customer-groups/${customerGroupId}/customers`, { +fetch(`/admin/customer-groups/${customerGroupId}/customers`, { credentials: "include", }) .then((response) => response.json()) @@ -576,7 +609,7 @@ fetch(`/admin/customer-groups/${customerGroupId}/customers`, { ```bash -curl -L -X GET '/admin/customer-groups//customers' \ +curl -L -X GET '/admin/customer-groups//customers' \ -H 'Authorization: Bearer ' ``` @@ -599,13 +632,16 @@ You can remove customers from a customer group by sending a request to the Remov ```ts -medusa.admin.customerGroups.removeCustomers(customer_group_id, { - customer_ids: [ - { - id: customer_id, - }, - ], -}) +medusa.admin.customerGroups.removeCustomers( + customer_group_id, + { + customer_ids: [ + { + id: customer_id, + }, + ], + } +) .then(({ customer_group }) => { console.log(customer_group.id) }) @@ -616,12 +652,15 @@ medusa.admin.customerGroups.removeCustomers(customer_group_id, { ```tsx import { Customer } from "@medusajs/medusa" -import { useAdminRemoveCustomersFromCustomerGroup } from "medusa-react" +import { + useAdminRemoveCustomersFromCustomerGroup, +} from "medusa-react" const CustomerGroup = () => { - const removeCustomers = useAdminRemoveCustomersFromCustomerGroup( - customerGroupId - ) + const removeCustomers = + useAdminRemoveCustomersFromCustomerGroup( + customerGroupId + ) // ... const handleRemoveCustomer = (customer_id: string) => { @@ -643,9 +682,11 @@ export default CustomerGroup + + ```ts fetch( - `/admin/customer-groups/${customerGroupId}/customers/batch`, + `/admin/customer-groups/${customerGroupId}/customers/batch`, { method: "DELETE", credentials: "include", @@ -671,7 +712,7 @@ fetch( ```bash -curl -L -X DELETE '/admin/customer-groups//customers/batch' \ +curl -L -X DELETE '/admin/customer-groups//customers/batch' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -694,11 +735,4 @@ This request returns the customer group. ## Use Customer Groups as Conditions in a Price List -When you create or update a price list, you can specify one or more customer groups as conditions for the price list. You can learn how to do that in the [PriceList API documentation](../backend/price-lists/use-api.mdx). - ---- - -## See Also - -- [Customer Groups Overview](../backend/customer-groups/index.md). -- [Use Sales Channels Admin APIs](../backend/sales-channels/manage-admin.mdx). \ No newline at end of file +When you create or update a price list, you can specify one or more customer groups as conditions for the price list. You can learn how to do that in the [PriceList API documentation](../../price-lists/admin/manage-price-lists.mdx). \ No newline at end of file diff --git a/docs/content/advanced/admin/manage-customers.mdx b/docs/content/modules/customers/admin/manage-customers.mdx similarity index 86% rename from docs/content/advanced/admin/manage-customers.mdx rename to docs/content/modules/customers/admin/manage-customers.mdx index 3c4cb10665ea4..a43bf9ab28f19 100644 --- a/docs/content/advanced/admin/manage-customers.mdx +++ b/docs/content/modules/customers/admin/manage-customers.mdx @@ -28,19 +28,19 @@ You want to add or use the following admin functionalities: ### Medusa Components -It is assumed that you already have a Medusa server installed and set up. If not, you can follow the [quickstart guide](../../quickstart/quick-start.mdx) to get started. +It is assumed that you already have a Medusa backend installed and set up. If not, you can follow the [quickstart guide](../../../development/backend/install.mdx) to get started. ### JS Client -This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client, JavaScript’s Fetch API, or cURL. +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, JavaScript’s Fetch API, or cURL. -If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../js-client/overview.md) installed and have [created an instance of the client](../../js-client/overview.md#configuration). +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../../js-client/overview.md) installed and have [created an instance of the client](../../../js-client/overview.md#configuration). ### Medusa React -This guide also includes code snippets to send requests to your Medusa server using Medusa React, among other methods. +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. -If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../medusa-react/overview.md#usage). +If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). ### Authenticated Admin User @@ -77,7 +77,9 @@ const Customers = () => { return (
    {isLoading && Loading...} - {customers && !customers.length && No customers} + {customers && !customers.length && ( + No customers + )} {customers && customers.length > 0 && (
      {customers.map((customer: Customer) => ( @@ -96,7 +98,7 @@ export default Customers ```ts -fetch(`/admin/customers`, { +fetch(`/admin/customers`, { credentials: "include", }) .then((response) => response.json()) @@ -109,7 +111,7 @@ fetch(`/admin/customers`, { ```bash -curl -L -X GET '/admin/customers' \ +curl -L -X GET '/admin/customers' \ -H 'Authorization: Bearer ' ``` @@ -190,7 +192,7 @@ export default CreateCustomer ```ts -fetch(`/admin/customers`, { +fetch(`/admin/customers`, { method: "POST", credentials: "include", headers: { @@ -213,7 +215,7 @@ fetch(`/admin/customers`, { ```bash -curl -L -X POST '/admin/customers' \ +curl -L -X POST '/admin/customers' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -294,7 +296,7 @@ export default UpdateCustomer ```ts -fetch(`/admin/customers/${customerId}`, { +fetch(`/admin/customers/${customerId}`, { method: "POST", credentials: "include", headers: { @@ -314,7 +316,7 @@ fetch(`/admin/customers/${customerId}`, { ```bash -curl -L -X POST '/admin/customers/' \ +curl -L -X POST '/admin/customers/' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -333,7 +335,4 @@ This request returns the updated customer object in the response. ## See Also -- [Manage customer groups](./use-customergroups-api.mdx) -- [Customers admin API reference](/api/admin) -- [Customers overview](../backend/customers/index.md) -- [Implement customer profiles in the storefront](../storefront/customer-profiles.mdx) +- [Implement customer profiles in the storefront](../storefront/implement-customer-profiles.mdx) diff --git a/docs/content/advanced/backend/customer-groups/index.md b/docs/content/modules/customers/customer-groups.md similarity index 85% rename from docs/content/advanced/backend/customer-groups/index.md rename to docs/content/modules/customers/customer-groups.md index 194040eb31723..ba629c926d40f 100644 --- a/docs/content/advanced/backend/customer-groups/index.md +++ b/docs/content/modules/customers/customer-groups.md @@ -1,5 +1,5 @@ --- -description: 'Learn what Customer Groups are and how they can be used in the Medusa server. Customer Groups allow to combine customers with similar attributes into a single group.' +description: 'Learn what Customer Groups are and how they can be used in the Medusa backend. Customer Groups allow to combine customers with similar attributes into a single group.' --- # Customer Groups @@ -24,7 +24,7 @@ The customer groups feature can be used in a variety of use cases including: ## CustomerGroup Entity Overview -A customer group is stored in the database as a [CustomerGroup](../../../references/entities/classes/CustomerGroup.md) entity. This entity has two attributes other than the `id`: `name` and `metadata`. +A customer group is stored in the database as a [CustomerGroup](../../references/entities/classes/CustomerGroup.md) entity. This entity has two attributes other than the `id`: `name` and `metadata`. Similar to all entities in Medusa, you can use the `metadata` object attribute to store any custom data you want. For example, you can add some flag or tag to the customer group for a custom use case: @@ -60,5 +60,4 @@ The relation between the `PriceList` and `CustomerGroup` entities is available o ## See Also -- [Manage customer groups using the Admin APIs](../../admin/use-customergroups-api.mdx). -- [Price Lists Overview](../price-lists/index.md). +- [Manage customer groups using the Admin APIs](./admin/manage-customer-groups.mdx) diff --git a/docs/content/advanced/backend/customers/index.md b/docs/content/modules/customers/customers.md similarity index 91% rename from docs/content/advanced/backend/customers/index.md rename to docs/content/modules/customers/customers.md index cd2cbcc641369..c51915d0fe763 100644 --- a/docs/content/advanced/backend/customers/index.md +++ b/docs/content/modules/customers/customers.md @@ -34,7 +34,7 @@ In the example mentioned above, after the unregistered customer places an order :::info -This architecture allows creating the Claim Order flow, where a registered customer can claim an order they placed as an unregistered customer. You can learn more about it in [this documentation](../../storefront/implement-claim-order.mdx). +This architecture allows creating the Claim Order flow, where a registered customer can claim an order they placed as an unregistered customer. You can learn more about it in [this documentation](../orders/storefront/implement-claim-order.mdx). ::: @@ -48,7 +48,7 @@ Customer groups allow dividing customers into groups of similar attributes, then :::info -You can learn more about customer groups in [this documentation](../customer-groups/index.md). +You can learn more about customer groups in [this documentation](./customer-groups.md). ::: @@ -77,6 +77,5 @@ The relation between the `Customer` and `Address` entities is available on both ## See Also -- [Implement customer profiles in the storefront](../../storefront/customer-profiles.mdx) -- [Manage customers using the admin APIs](../../admin/manage-customers.mdx) -- Customers [Admin](/api/admin/#tag/Customer) and [Storefront](/api/store/#tag/Customer) API References +- [Implement customer profiles in the storefront](./storefront/implement-customer-profiles.mdx) +- [Manage customers using the admin APIs](./admin/manage-customers.mdx) diff --git a/docs/content/modules/customers/overview.mdx b/docs/content/modules/customers/overview.mdx new file mode 100644 index 0000000000000..116e9d8dbc2ea --- /dev/null +++ b/docs/content/modules/customers/overview.mdx @@ -0,0 +1,160 @@ +--- +description: "Customers are individuals that make purchases in your store. Learn about the available features and guides." +--- + +import DocCardList from '@theme/DocCardList'; +import Icons from '@theme/Icon'; + +# Customers + +Customers are individuals that make purchases in your store. This overview introduces the available features related to customers. + +:::note + +Not a developer? Check out the [Customers user guide](../../user-guide/customers/index.md). + +::: + +## Features + +### Customer Accounts + +Customers can make purchases as guests, or they can create an account. + +When a customer creates an account, they can manage their details and review their order history. + +An admin can manage all customers and their details. + + + +### Customer Groups + +Admins can segment customers or assign them to different customer groups. This can be useful for marketing purposes. + +For example, an admin can specify a different pricing or special discounts for specific customer groups. + + + +--- + +## Understand the Architecture + +Learn how Customer-related entities are built, their relation to other modules, and more. + + + +--- + +## Related Modules + +Discover Customers’ relation to other modules in Medusa. + + \ No newline at end of file diff --git a/docs/content/advanced/storefront/customer-profiles.mdx b/docs/content/modules/customers/storefront/implement-customer-profiles.mdx similarity index 89% rename from docs/content/advanced/storefront/customer-profiles.mdx rename to docs/content/modules/customers/storefront/implement-customer-profiles.mdx index 7f6e23620fa53..ca84bcfeffc4a 100644 --- a/docs/content/advanced/storefront/customer-profiles.mdx +++ b/docs/content/modules/customers/storefront/implement-customer-profiles.mdx @@ -36,21 +36,21 @@ You can use Medusa’s Store APIs to achieve more functionalities as well. Check ### Medusa Components -It's assumed that you already have a Medusa server installed and set up. If not, you can follow the [quickstart guide](../../quickstart/quick-start.mdx) to get started. +It's assumed that you already have a Medusa backend installed and set up. If not, you can follow the [quickstart guide](../../../development/backend/install.mdx) to get started. -It's also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install either the [Next.js](../../starters/nextjs-medusa-starter.mdx) or [Gatsby](../../starters/gatsby-medusa-starter.mdx) storefronts. +It's also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install the [Next.js starter storefront](../../../starters/nextjs-medusa-starter.mdx). ### JS Client -This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client, among other methods. +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, among other methods. -If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../../js-client/overview.md) and have [created an instance of the client](../../js-client/overview.md#configuration). +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../../../js-client/overview.md) and have [created an instance of the client](../../../js-client/overview.md#configuration). ### Medusa React -This guide also includes code snippets to send requests to your Medusa server using Medusa React, among other methods. +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. -If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../medusa-react/overview.md#usage). +If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). --- @@ -111,7 +111,7 @@ export default RegisterCustomer ```ts -fetch(`/store/customers`, { +fetch(`/store/customers`, { method: "POST", credentials: "include", headers: { @@ -169,7 +169,7 @@ medusa.auth.authenticate({ ```ts -fetch(`/store/auth`, { +fetch(`/store/auth`, { method: "POST", credentials: "include", headers: { @@ -215,7 +215,7 @@ medusa.auth.deleteSession() ```ts -fetch(`/store/auth`, { +fetch(`/store/auth`, { method: "DELETE", credentials: "include", }) @@ -260,7 +260,7 @@ medusa.customers.generatePasswordToken({ ```ts -fetch(`/store/customers/password-token`, { +fetch(`/store/customers/password-token`, { method: "POST", credentials: "include", headers: { @@ -287,7 +287,7 @@ If the request has been processed successfully, it returns a `204` status code i :::note -If the customer doesn’t receive an email after this request, make sure that you’ve set up a Notification provider like [SendGrid](../../add-plugins/sendgrid.mdx) successfully. You also need to add a subscriber that handles the [customer.password_reset](../backend/subscribers/events-list.md#customer-events) event and sends the email. +If the customer doesn’t receive an email after this request, make sure that you’ve set up a Notification provider like [SendGrid](../../../plugins/notifications/sendgrid.mdx) successfully. You also need to add a subscriber that handles the [customer.password_reset](../../../development/events/events-list.md#customer-events) event and sends the email. ::: @@ -315,7 +315,7 @@ medusa.customers.resetPassword({ ```ts -fetch(`/store/customers/password-reset`, { +fetch(`/store/customers/password-reset`, { method: "POST", credentials: "include", headers: { @@ -398,7 +398,7 @@ export default UpdateCustomer ```ts -fetch(`/store/customers/me`, { +fetch(`/store/customers/me`, { method: "POST", credentials: "include", headers: { @@ -465,7 +465,7 @@ medusa.customers.addresses.addAddress({ ```ts -fetch(`/store/customers/me/addresses`, { +fetch(`/store/customers/me/addresses`, { method: "POST", credentials: "include", headers: { @@ -529,16 +529,18 @@ medusa.customers.addresses.updateAddress(addressId, { ```ts -fetch(`/store/customers/me/addresses/${addressId}`, { - method: "POST", - credentials: "include", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - first_name, - }), -}) +fetch(`/store/customers/me/addresses/${addressId}`, + { + method: "POST", + credentials: "include", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + first_name, + }), + } +) .then((response) => response.json()) .then(({ customer }) => { console.log(customer.id) @@ -570,10 +572,12 @@ medusa.customers.addresses.deleteAddress(addressId) ```ts -fetch(`/store/customers/me/addresses/${addressId}`, { - method: "DELETE", - credentials: "include", -}) +fetch(`/store/customers/me/addresses/${addressId}`, + { + method: "DELETE", + credentials: "include", + } +) .then((response) => response.json()) .then(({ customer }) => { console.log(customer.id) @@ -636,7 +640,7 @@ export default Orders ```ts -fetch(`/store/customers/me/orders`, { +fetch(`/store/customers/me/orders`, { credentials: "include", }) .then((response) => response.json()) @@ -661,13 +665,4 @@ It returns the following data in the response: You can learn more about pagination in the [API reference](/api/store/#section/Pagination). -::: - ---- - -## See Also - -- [Implement order-claim flow](./implement-claim-order.mdx) -- [Customers Store API reference](/api/store) -- [Customers overview](../backend/customers/index.md) -- [Manage customers using the admin APIs](../admin/manage-customers.mdx) +::: \ No newline at end of file diff --git a/docs/content/advanced/admin/manage-discounts.mdx b/docs/content/modules/discounts/admin/manage-discounts.mdx similarity index 84% rename from docs/content/advanced/admin/manage-discounts.mdx rename to docs/content/modules/discounts/admin/manage-discounts.mdx index 9b02a7911b5f5..91f394056bca1 100644 --- a/docs/content/advanced/admin/manage-discounts.mdx +++ b/docs/content/modules/discounts/admin/manage-discounts.mdx @@ -12,7 +12,7 @@ In this document, you’ll learn how to use the Admin’s Discount APIs to manag :::tip -If you want to learn about the Discount architecture in-depth, check out the [Discount Architecture](../backend/discounts/index.md) documentation instead. +If you want to learn about the Discount architecture in-depth, check out the [Discount Architecture](../discounts.md) documentation instead. ::: @@ -40,19 +40,19 @@ You can use Medusa’s Admin APIs to achieve more functionalities as well. Check ### Medusa Components -It is assumed that you already have a Medusa server installed and set up. If not, you can follow the [quickstart guide](../../quickstart/quick-start.mdx) to get started. +It is assumed that you already have a Medusa backend installed and set up. If not, you can follow the [quickstart guide](../../../development/backend/install.mdx) to get started. ### JS Client -This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client, JavaScript’s Fetch API, or cURL. +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, JavaScript’s Fetch API, or cURL. -If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../js-client/overview.md) installed and have [created an instance of the client](../../js-client/overview.md#configuration). +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../../js-client/overview.md) installed and have [created an instance of the client](../../../js-client/overview.md#configuration). ### Medusa React -This guide also includes code snippets to send requests to your Medusa server using Medusa React, among other methods. +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. -If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../medusa-react/overview.md#usage). +If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). ### Authenticated Admin User @@ -70,7 +70,10 @@ You can create a discount by sending a request to the [Create Discount](/api/adm ```ts -import { AllocationType, DiscountRuleType } from "@medusajs/medusa" +import { + AllocationType, + DiscountRuleType, +} from "@medusajs/medusa" // ... medusa.admin.discounts.create({ code, @@ -94,8 +97,13 @@ medusa.admin.discounts.create({ ```tsx -import { useAdminCreateDiscount } from "medusa-react" -import { AllocationType, DiscountRuleType } from "@medusajs/medusa" +import { + useAdminCreateDiscount, +} from "medusa-react" +import { + AllocationType, + DiscountRuleType, +} from "@medusajs/medusa" const CreateDiscount = () => { const createDiscount = useAdminCreateDiscount() @@ -128,7 +136,7 @@ export default CreateDiscount ```ts -fetch(`/admin/discounts`, { +fetch(`/admin/discounts`, { method: "POST", credentials: "include", headers: { @@ -158,7 +166,7 @@ fetch(`/admin/discounts`, { ```bash -curl -L -X POST '/admin/discounts' \ +curl -L -X POST '/admin/discounts' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -183,9 +191,9 @@ This request accepts [many request-body parameters](/api/admin/#tag/Discount/ope - `code`: This parameter is required. It is a unique code. The customer redeems the discount using this code. - `rule`: This parameter is required. It is an object having at least the following fields: - - `type`: A string indicating the type of discount. It can be `fixed`, `percentage`, or `free_shipping`. When using the Medusa JS Client, you must use the enum type [DiscountRuleType](../../references/js-client/enums/internal.discountruletype/) for the value. + - `type`: A string indicating the type of discount. It can be `fixed`, `percentage`, or `free_shipping`. When using the Medusa JS Client, you must use the enum type [DiscountRuleType](../../../references/js-client/enums/internal.discountruletype/) for the value. - `value`: A number indicating the value of the discount. If the discount type is `fixed`, then it will be the fixed amount to discount from the cart’s totals or its items. If the discount type is `percentage`, then it will be the percentage to discount from the items in the cart. If the type is `free_shipping`, it has no effect and can be set to `0`. - - `allocation`: A string indicating how the discount should be applied. Can be `item` or `total`. If the type is not `fixed`, then this has no effect. When using the Medusa JS Client, you must use the enum type [AllocationType](../../references/js-client/enums/internal.allocationtype/) for the value. + - `allocation`: A string indicating how the discount should be applied. Can be `item` or `total`. If the type is not `fixed`, then this has no effect. When using the Medusa JS Client, you must use the enum type [AllocationType](../../../references/js-client/enums/internal.allocationtype/) for the value. - `regions`: An array of region IDs this discount can be used in. If the type of discount is `fixed`, only one region can be passed. This request returns the full `discount` object. @@ -237,7 +245,7 @@ export default UpdateDiscount ```ts -fetch(`/admin/discounts/${discountId}`, { +fetch(`/admin/discounts/${discountId}`, { method: "POST", credentials: "include", headers: { @@ -257,7 +265,7 @@ fetch(`/admin/discounts/${discountId}`, { ```bash -curl -L -X POST '/admin/discounts/' \ +curl -L -X POST '/admin/discounts/' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -282,7 +290,7 @@ This updates the discount’s information and returns the full updated `discount :::tip -You can learn more about conditions and conditions types in the [Discount Architecture](../backend/discounts/index.md) documentation. +You can learn more about conditions and conditions types in the [Discount Architecture](../discounts.md) documentation. ::: @@ -313,7 +321,9 @@ import { useAdminDiscountCreateCondition } from "medusa-react" import { DiscountConditionOperator } from "@medusajs/medusa" const Discount = () => { - const createCondition = useAdminDiscountCreateCondition(discount_id) + const createCondition = useAdminDiscountCreateCondition( + discount_id + ) // ... const handleCreateCondition = ( @@ -339,19 +349,21 @@ export default Discount ```ts -fetch(`/admin/discounts/${discountId}/conditions`, { - method: "POST", - credentials: "include", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - operator: "in", - products: [ - productId, - ], - }), -}) +fetch(`/admin/discounts/${discountId}/conditions`, + { + method: "POST", + credentials: "include", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + operator: "in", + products: [ + productId, + ], + }), + } +) .then((response) => response.json()) .then(({ discount }) => { console.log(discount.id) @@ -362,7 +374,7 @@ fetch(`/admin/discounts/${discountId}/conditions`, { ```bash -curl -L -X POST '/admin/discounts//conditions' \ +curl -L -X POST '/admin/discounts//conditions' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -401,11 +413,18 @@ You can retrieve a condition and its resources by sending a request to the [Get ```ts -medusa.admin.discounts.getCondition(discountId, conditionId, { - expand: "products", -}) +medusa.admin.discounts.getCondition( + discountId, + conditionId, + { + expand: "products", + } +) .then(({ discount_condition }) => { - console.log(discount_condition.id, discount_condition.products) + console.log( + discount_condition.id, + discount_condition.products + ) }) ``` @@ -417,7 +436,10 @@ import { useAdminGetDiscountCondition } from "medusa-react" import { Product } from "@medusajs/medusa" const DiscountCondition = () => { - const { discount_condition, isLoading } = useAdminGetDiscountCondition( + const { + discount_condition, + isLoading, + } = useAdminGetDiscountCondition( discount_id, conditionId ) @@ -430,9 +452,11 @@ const DiscountCondition = () => { <> {discount_condition.id}
        - {discount_condition.products.map((product: Product) => ( -
      • {product.title}
      • - ))} + {discount_condition.products.map( + (product: Product) => ( +
      • {product.title}
      • + ) + )}
      )} @@ -448,7 +472,7 @@ export default DiscountCondition ```ts fetch( - `/admin/discounts/${discountId}` + + `/admin/discounts/${discountId}` + `/conditions/${conditionId}&expand=products`, { credentials: "include", @@ -456,7 +480,10 @@ fetch( ) .then((response) => response.json()) .then(({ discount_condition }) => { - console.log(discount_condition.id, discount_condition.products) + console.log( + discount_condition.id, + discount_condition.products + ) }) ``` @@ -464,7 +491,7 @@ fetch( ```bash -curl -L -X GET '/admin/discounts//conditions/&expand=products' \ +curl -L -X GET '/admin/discounts//conditions/&expand=products' \ -H 'Authorization: Bearer ' ``` @@ -487,12 +514,15 @@ For example, to update the products in a condition: ```ts -medusa.admin.discounts.updateCondition(discountId, conditionId, { - products: [ - productId1, - productId2, - ], -}) +medusa.admin.discounts.updateCondition( + discountId, + conditionId, { + products: [ + productId1, + productId2, + ], + } +) .then(({ discount }) => { console.log(discount.id) }) @@ -527,9 +557,11 @@ export default DiscountCondition + + ```ts fetch( - `/admin/discounts/${discountId}/conditions/${conditionId}`, + `/admin/discounts/${discountId}/conditions/${conditionId}`, { method: "POST", credentials: "include", @@ -554,7 +586,7 @@ fetch( ```bash -curl -L -X POST '/admin/discounts//conditions/' \ +curl -L -X POST '/admin/discounts//conditions/' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -582,7 +614,10 @@ You can delete a condition by sending a request to the [Delete Condition](/api/a ```ts -medusa.admin.discounts.deleteCondition(discountId, conditionId) +medusa.admin.discounts.deleteCondition( + discountId, + conditionId +) .then(({ discount }) => { console.log(discount) }) @@ -595,7 +630,9 @@ medusa.admin.discounts.deleteCondition(discountId, conditionId) import { useAdminDiscountRemoveCondition } from "medusa-react" const Discount = () => { - const deleteCondition = useAdminDiscountRemoveCondition(discount_id) + const deleteCondition = useAdminDiscountRemoveCondition( + discount_id + ) // ... const handleUpdateCondition = (conditionId: string) => { @@ -611,9 +648,11 @@ export default Discount + + ```ts fetch( - `/admin/discounts/${discountId}/conditions/${conditionId}`, + `/admin/discounts/${discountId}/conditions/${conditionId}`, { method: "DELETE", credentials: "include", @@ -629,7 +668,7 @@ fetch( ```bash -curl -L -X DELETE '/admin/discounts//conditions/' \ +curl -L -X DELETE '/admin/discounts//conditions/' \ -H 'Authorization: Bearer ' ``` @@ -680,7 +719,7 @@ export default Discount ```ts -fetch(`/admin/discounts/${discountId}`, { +fetch(`/admin/discounts/${discountId}`, { method: "DELETE", credentials: "include", }) @@ -694,7 +733,7 @@ fetch(`/admin/discounts/${discountId}`, { ```bash -curl -L -X DELETE '/admin/discounts/' \ +curl -L -X DELETE '/admin/discounts/' \ -H 'Authorization: Bearer ' ``` @@ -713,5 +752,4 @@ It returns in the response the following fields: ## See Also -- [Discounts API reference](/api/admin/#tag/Discount) - [Use Discounts on the storefront](../storefront/use-discounts-in-checkout.mdx) diff --git a/docs/content/advanced/backend/discounts/index.md b/docs/content/modules/discounts/discounts.md similarity index 82% rename from docs/content/advanced/backend/discounts/index.md rename to docs/content/modules/discounts/discounts.md index 66867c16ca6e3..6c6cee0a85185 100644 --- a/docs/content/advanced/backend/discounts/index.md +++ b/docs/content/modules/discounts/discounts.md @@ -1,5 +1,5 @@ --- -description: 'Learn about the discount architecture in the Medusa server. Discounts are used to offer promotions to the user for marketing purposes.' +description: 'Learn about the discount architecture in the Medusa backend. Discounts are used to offer promotions to the user for marketing purposes.' --- # Discounts Architecture @@ -32,7 +32,7 @@ Discounts can be used in many use cases including: ## Discount Entity Overview -A discount is represented by the [`Discount`](../../../references/entities/classes/Discount.md) entity. Some of its important attributes are: +A discount is represented by the [`Discount`](../../references/entities/classes/Discount.md) entity. Some of its important attributes are: - `code` is a unique code that you specify when you create the discount. Customers use this code to apply the discount during checkout. The code can only include upper-case letters and numbers. - `rule_id` is the ID of the rule of this discount. The `rule` attribute is the expanded object of the `DiscountRule` entity. You can use the `rule` attribute to get details regarding the discount type. You can learn more about this in the [`DiscountRule` entity overview](#discountrule-entity-overview) later. @@ -54,7 +54,7 @@ The `is_dynamic` attribute in the `Discount` entity is a boolean value that dete ## DiscountRule Entity Overview -Every `Discount` entity belongs to a [`DiscountRule`](./../../../references/entities/classes/DiscountRule.md) entity. `DiscountRule` includes details such as the type of discount, the amount to be discounted, and more. +Every `Discount` entity belongs to a [`DiscountRule`](../../references/entities/classes/DiscountRule.md) entity. `DiscountRule` includes details such as the type of discount, the amount to be discounted, and more. Some of the `DiscountRule` entity’s important attributes are: @@ -71,7 +71,7 @@ Some of the `DiscountRule` entity’s important attributes are: A discount can optionally have discount conditions. Discount conditions are used to further add limitations on when the discount can be applied. -A [`DiscountCondition`](../../../references/entities/classes/DiscountCondition.md) belongs to a `DiscountRule` entity. The `discount_rule_id` attribute indicates the ID of the `DiscountRule` it belongs to. +A [`DiscountCondition`](../../references/entities/classes/DiscountCondition.md) belongs to a `DiscountRule` entity. The `discount_rule_id` attribute indicates the ID of the `DiscountRule` it belongs to. Discount conditions have an attribute `type` that indicates the condition’s type. Its value must be one of the following: @@ -92,17 +92,17 @@ Discount conditions also have an attribute `operator` that indicates how the con Based on the value of `type`, one of the following relations can be used to retrieve the condition’s items: -- `products` is an array of products that this condition applies to if the condition’s `type` is `products`. Each item of the array would be a [`DiscountConditionProduct`](../../../references/entities/classes/DiscountConditionProduct.md). -- `product_types` is an array of product types that this condition applies to if the condition’s `type` is `product_types`. Each item of the array would be a [`DiscountConditionProductType`](../../../references/entities/classes/DiscountConditionProductType.md). -- `product_collections` is an array of product types that this condition applies to if the condition’s `type` is `product_collections`. Each item of the array would be a [`DiscountConditionProductCollection`](../../../references/entities/classes/DiscountConditionProductCollection.md). -- `product_tags` is an array of product types that this condition applies to if the condition’s `type` is `product_tags`. Each item of the array would be a [`DiscountConditionProductTag`](../../../references/entities/classes/DiscountConditionProductTag.md). -- `customer_groups` is an array of product types that this condition applies to if the condition’s `type` is `customer_groups`. Each item of the array would be a [`DiscountConditionCustomerGroup`](../../../references/entities/classes/DiscountConditionCustomerGroup.md). +- `products` is an array of products that this condition applies to if the condition’s `type` is `products`. Each item of the array would be a [`DiscountConditionProduct`](../../references/entities/classes/DiscountConditionProduct.md). +- `product_types` is an array of product types that this condition applies to if the condition’s `type` is `product_types`. Each item of the array would be a [`DiscountConditionProductType`](../../references/entities/classes/DiscountConditionProductType.md). +- `product_collections` is an array of product types that this condition applies to if the condition’s `type` is `product_collections`. Each item of the array would be a [`DiscountConditionProductCollection`](../../references/entities/classes/DiscountConditionProductCollection.md). +- `product_tags` is an array of product types that this condition applies to if the condition’s `type` is `product_tags`. Each item of the array would be a [`DiscountConditionProductTag`](../../references/entities/classes/DiscountConditionProductTag.md). +- `customer_groups` is an array of product types that this condition applies to if the condition’s `type` is `customer_groups`. Each item of the array would be a [`DiscountConditionCustomerGroup`](../../references/entities/classes/DiscountConditionCustomerGroup.md). -![Discounts Architecture](https://res.cloudinary.com/dza7lstvk/image/upload/v1669900544/Medusa%20Docs/Diagrams/discounts_cdxec1.jpg) +![Discounts Architecture](https://res.cloudinary.com/dza7lstvk/image/upload/v1678372360/Medusa%20Docs/Diagrams/discounts_ioivrl.png) --- ## See Also -- [Create a discount using the admin APIs](../../admin/manage-discounts.mdx) -- [Use discounts on the storefront](../../storefront/use-discounts-in-checkout.mdx) +- [Manage discounts using the admin APIs](./admin/manage-discounts.mdx) +- [Use discounts on the storefront](./storefront/use-discounts-in-checkout.mdx) diff --git a/docs/content/modules/discounts/overview.mdx b/docs/content/modules/discounts/overview.mdx new file mode 100644 index 0000000000000..67c3b69141007 --- /dev/null +++ b/docs/content/modules/discounts/overview.mdx @@ -0,0 +1,113 @@ +--- +description: "Discounts are deductions in the checkout total that are generally used for marketing and promotional purposes. Learn about the available features and guides." +--- + +import DocCardList from '@theme/DocCardList'; +import DocCard from '@theme/DocCard'; +import Icons from '@theme/Icon'; + +# Discounts + +Discounts are deductions in the checkout total that are generally used for marketing and promotional purposes. This overview introduces the available features related to discounts. + +:::note + +Not a developer? Check out the [Discounts user guide](../../user-guide/discounts/index.md). + +::: + +## Features + +### Discounts Management + +Admins can create discounts with various conditions and rules that can be used to deduct a fixed or percentage amount from the cart total, or that can be used for free shipping. + + + +### Applying Discounts during Checkout + +Customers can benefit from discounts by using a discount code during checkout. + + + +--- + +## Understand the Architecture + +Learn how discount-related entities and concepts are built, their relation to other modules, and more. + + + +--- + +## Related Modules + +Discover Discount’s relation to other modules in Medusa + + \ No newline at end of file diff --git a/docs/content/advanced/storefront/use-discounts-in-checkout.mdx b/docs/content/modules/discounts/storefront/use-discounts-in-checkout.mdx similarity index 86% rename from docs/content/advanced/storefront/use-discounts-in-checkout.mdx rename to docs/content/modules/discounts/storefront/use-discounts-in-checkout.mdx index 19ed4c924285b..8b2b4afad185b 100644 --- a/docs/content/advanced/storefront/use-discounts-in-checkout.mdx +++ b/docs/content/modules/discounts/storefront/use-discounts-in-checkout.mdx @@ -12,7 +12,7 @@ In this document, learn how to use discounts during checkout on the storefront. :::info -You can check out the [Discounts Architecture documentation](../backend/discounts/index.md) to learn more about how discounts work. +You can check out the [Discounts Architecture documentation](../discounts.md) to learn more about how discounts work. ::: @@ -32,29 +32,29 @@ You want to implement discount functionality in your store to allow customers to ### Medusa Components -It's assumed that you already have a Medusa server installed and set up. If not, you can follow the [quickstart guide](../../quickstart/quick-start.mdx) to get started. +It's assumed that you already have a Medusa backend installed and set up. If not, you can follow the [quickstart guide](../../../development/backend/install.mdx) to get started. -It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install either the [Next.js](../../starters/nextjs-medusa-starter.mdx) or [Gatsby](../../starters/gatsby-medusa-starter.mdx) storefronts. +It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install the [Next.js starter storefront](../../../starters/nextjs-medusa-starter.mdx). ### JS Client -This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client, among other methods. +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, among other methods. -If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../../js-client/overview.md) and have [created an instance of the client](../../js-client/overview.md#configuration). +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../../../js-client/overview.md) and have [created an instance of the client](../../../js-client/overview.md#configuration). ### Medusa React -This guide also includes code snippets to send requests to your Medusa server using Medusa React, among other methods. +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. -If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../medusa-react/overview.md#usage). +If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). -It's also assumed you already have [used CartProvider higher in your component tree](../../medusa-react/overview.md#cartprovider). +It's also assumed you already have [used CartProvider higher in your component tree](../../../medusa-react/overview.md#cartprovider). ### Previous Steps This document assumes you’ve already taken care of the add-to-cart flow. So, you should have a [cart created](/api/store/#tag/Cart/operation/PostCart) for the customer with at least [one product in it](/api/store/#tag/Cart/operation/PostCartsCartLineItems). -You can learn how to implement the cart flow using [this documentation](../../guides/carts-in-medusa.mdx). +You can learn how to implement the cart flow using [this documentation](../../../modules/carts-and-checkout/storefront/implement-cart.mdx). --- @@ -115,7 +115,7 @@ export default Cart ```ts -fetch(`/store/carts/${cartId}`, { +fetch(`/store/carts/${cartId}`, { method: "POST", credentials: "include", body: JSON.stringify({ @@ -146,7 +146,7 @@ This request requires the customer’s cart ID as a path parameter. In the body :::info -Customers can add more than one discount to their cart. +Customers can add more than one discount to their cart, however, only one non-free shipping discount is allowed per cart. ::: @@ -269,7 +269,7 @@ medusa.carts.deleteDiscount(cartId, code) ```ts -fetch(`/store/carts/${cartId}/discounts/${code}`, { +fetch(`/store/carts/${cartId}/discounts/${code}`, { method: "DELETE", credentials: "include", }) @@ -285,10 +285,3 @@ fetch(`/store/carts/${cartId}/discounts/${code}`, { This request accepts the cart ID and the code of the discount to remove. If the discount is removed successfully, the request returns the updated cart object, where you won’t find the discount in the `discounts` array anymore. The totals of the cart and its items will be updated as well. - ---- - -## See Also - -- [Implement the checkout flow in a storefront](./how-to-implement-checkout-flow.mdx). -- [Manage discounts using the admin APIs](../admin/manage-discounts.mdx). diff --git a/docs/content/advanced/admin/manage-gift-cards.mdx b/docs/content/modules/gift-cards/admin/manage-gift-cards.mdx similarity index 89% rename from docs/content/advanced/admin/manage-gift-cards.mdx rename to docs/content/modules/gift-cards/admin/manage-gift-cards.mdx index c90930c2bcce0..655913cdee1e8 100644 --- a/docs/content/advanced/admin/manage-gift-cards.mdx +++ b/docs/content/modules/gift-cards/admin/manage-gift-cards.mdx @@ -12,7 +12,7 @@ In this document, you’ll learn how to manage gift cards using the admin APIs. :::note -You can learn more about what gift cards are and how they’re used in [this documentation](../backend/gift-cards/index.md) +You can learn more about what gift cards are and how they’re used in [this documentation](../gift-cards.md) ::: @@ -33,19 +33,19 @@ You want to add or use the following admin functionalities: ### Medusa Components -It is assumed that you already have a Medusa server installed and set up. If not, you can follow the [quickstart guide](../../quickstart/quick-start.mdx) to get started. +It is assumed that you already have a Medusa backend installed and set up. If not, you can follow the [quickstart guide](../../../development/backend/install.mdx) to get started. ### JS Client -This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client, among other methods. +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, among other methods. -If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../js-client/overview.md) installed and have [created an instance of the client](../../js-client/overview.md#configuration). +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../../js-client/overview.md) installed and have [created an instance of the client](../../../js-client/overview.md#configuration). ### Medusa React -This guide also includes code snippets to send requests to your Medusa server using Medusa React, among other methods. +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. -If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../medusa-react/overview.md#usage). +If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). ### Authenticated Admin User @@ -87,7 +87,9 @@ medusa.admin.products.list({ ```tsx import { Product } from "@medusajs/medusa" -import { PricedProduct } from "@medusajs/medusa/dist/types/pricing" +import { + PricedProduct, +} from "@medusajs/medusa/dist/types/pricing" import { useAdminProducts } from "medusa-react" const GiftCard = () => { @@ -100,12 +102,16 @@ const GiftCard = () => { {isLoading && Loading...} {products && products.length > 0 && (
        - {products.map((product: (Product | PricedProduct)) => ( -
      • {product.title}
      • - ))} + {products.map( + (product: (Product | PricedProduct)) => ( +
      • {product.title}
      • + ) + )}
      )} - {products && !products.length && No Gift Cards} + {products && !products.length && ( + No Gift Cards + )}
    ) } @@ -117,7 +123,7 @@ export default GiftCard ```ts -fetch(`/admin/products?is_giftcard=true`, { +fetch(`/admin/products?is_giftcard=true`, { credentials: "include", }) .then((response) => response.json()) @@ -135,7 +141,7 @@ fetch(`/admin/products?is_giftcard=true`, { ```bash -curl -L -X GET '/admin/products?is_giftcard=true' \ +curl -L -X GET '/admin/products?is_giftcard=true' \ -H 'Authorization: Bearer ' ``` @@ -244,7 +250,7 @@ export default CreateGiftCard ```ts -fetch(`/admin/products`, { +fetch(`/admin/products`, { method: "POST", credentials: "include", headers: { @@ -290,7 +296,7 @@ fetch(`/admin/products`, { ```bash -curl -L -X POST '/admin/products' \ +curl -L -X POST '/admin/products' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -383,7 +389,7 @@ export default UpdateGiftCard ```ts -fetch(`/admin/products/${giftCardId}`, { +fetch(`/admin/products/${giftCardId}`, { method: "POST", credentials: "include", headers: { @@ -403,7 +409,7 @@ fetch(`/admin/products/${giftCardId}`, { ```bash -curl -L -X POST '/admin/products/' \ +curl -L -X POST '/admin/products/' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -458,7 +464,7 @@ export default GiftCard ```ts -fetch(`/admin/products/${giftCardId}`, { +fetch(`/admin/products/${giftCardId}`, { method: "DELETE", credentials: "include", }) @@ -472,7 +478,7 @@ fetch(`/admin/products/${giftCardId}`, { ```bash -curl -L -X DELETE '/admin/products/' \ +curl -L -X DELETE '/admin/products/' \ -H 'Authorization: Bearer ' ``` @@ -541,7 +547,7 @@ export default CustomGiftCards ```ts -fetch(`/admin/gift-cards`, { +fetch(`/admin/gift-cards`, { credentials: "include", }) .then((response) => response.json()) @@ -554,7 +560,7 @@ fetch(`/admin/gift-cards`, { ```bash -curl -L -X GET '/admin/gift-cards' \ +curl -L -X GET '/admin/gift-cards' \ -H 'Authorization: Bearer ' ``` @@ -611,7 +617,7 @@ export default CreateCustomGiftCards ```ts -fetch(`/admin/gift-cards`, { +fetch(`/admin/gift-cards`, { method: "POST", credentials: "include", headers: { @@ -632,7 +638,7 @@ fetch(`/admin/gift-cards`, { ```bash -curl -L -X POST '/admin/gift-cards' \ +curl -L -X POST '/admin/gift-cards' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -675,7 +681,9 @@ medusa.admin.giftCards.update(giftCardId, { import { useAdminUpdateGiftCard } from "medusa-react" const UpdateCustomGiftCards = () => { - const updateGiftCard = useAdminUpdateGiftCard(customGiftCardId) + const updateGiftCard = useAdminUpdateGiftCard( + customGiftCardId + ) // ... const handleUpdate = (regionId: string) => { @@ -694,7 +702,7 @@ export default UpdateCustomGiftCards ```ts -fetch(`/admin/gift-cards/${giftCardId}`, { +fetch(`/admin/gift-cards/${giftCardId}`, { method: "POST", credentials: "include", headers: { @@ -714,7 +722,7 @@ fetch(`/admin/gift-cards/${giftCardId}`, { ```bash -curl -L -X POST '/admin/gift-cards/' \ +curl -L -X POST '/admin/gift-cards/' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -752,7 +760,9 @@ medusa.admin.giftCards.delete(giftCardId) import { useAdminDeleteGiftCard } from "medusa-react" const CustomGiftCard = () => { - const deleteGiftCard = useAdminDeleteGiftCard(customGiftCardId) + const deleteGiftCard = useAdminDeleteGiftCard( + customGiftCardId + ) // ... const handleDelete = () => { @@ -769,7 +779,7 @@ export default CustomGiftCard ```ts -fetch(`/admin/gift-cards/${giftCardId}`, { +fetch(`/admin/gift-cards/${giftCardId}`, { method: "DELETE", credentials: "include", }) @@ -783,7 +793,7 @@ fetch(`/admin/gift-cards/${giftCardId}`, { ```bash -curl -L -X DELETE '/admin/gift-card/' \ +curl -L -X DELETE '/admin/gift-card/' \ -H 'Authorization: Bearer ' ``` @@ -802,7 +812,4 @@ It returns the following fields in the response: ## See Also -- [Gift cards overview](../backend/gift-cards/index.md) -- [Use gift cards on the storefront](../storefront/use-gift-cards.mdx) -- [Send the customer a gift card](../ecommerce/send-gift-card-to-customer.md) -- Gift cards [store](/api/store/#tag/Gift-Card) and [admin](/api/admin/#tag/Gift-Card) APIs +- [Use gift cards on the storefront](../storefront/use-gift-cards.mdx) \ No newline at end of file diff --git a/docs/content/advanced/ecommerce/send-gift-card-to-customer.md b/docs/content/modules/gift-cards/backend/send-gift-card-to-customer.md similarity index 71% rename from docs/content/advanced/ecommerce/send-gift-card-to-customer.md rename to docs/content/modules/gift-cards/backend/send-gift-card-to-customer.md index f76d7a6e57b8c..979c8e465f3f5 100644 --- a/docs/content/advanced/ecommerce/send-gift-card-to-customer.md +++ b/docs/content/modules/gift-cards/backend/send-gift-card-to-customer.md @@ -17,7 +17,7 @@ This document shows you how to track when a gift card has been purchased so that :::tip -You can alternatively use the [SendGrid](../../add-plugins/sendgrid.mdx) plugin, which handles sending the email automatically. +You can alternatively use the [SendGrid](../../../plugins/notifications/sendgrid.mdx) plugin, which handles sending the email automatically. ::: @@ -27,15 +27,15 @@ You can alternatively use the [SendGrid](../../add-plugins/sendgrid.mdx) plugin, ### Medusa Components -It's assumed that you already have a Medusa server installed and set up. If not, you can follow the [quickstart guide](../../quickstart/quick-start.mdx) to get started. +It's assumed that you already have a Medusa backend installed and set up. If not, you can follow the [quickstart guide](../../../development/backend/install.mdx) to get started. ### Redis -Redis is required for batch jobs to work. Make sure you [install Redis](../../tutorial/0-set-up-your-development-environment.mdx#redis) and [configure it with your Medusa server](../../usage/configurations.md#redis). +Redis is required for batch jobs to work. Make sure you [install Redis](../../../development/backend/prepare-environment.mdx#redis) and [configure it with the Medusa backend](../../../development/backend/configurations.md#redis). ### Notification Provider -To send an email or another type of notification method, you must have a notification provider installed or configured. You can either install an existing plugin or [create your own](../backend/notification/how-to-create-notification-provider.md). +To send an email or another type of notification method, you must have a notification provider installed or configured. You can either install an existing plugin or [create your own](../../../development/notification/create-notification-provider.md). --- @@ -45,7 +45,7 @@ To subscribe to and handle an event, you must create a subscriber. :::info -You can learn more about subscribers in the [Subscribers](../backend/subscribers/overview.md) documentation. +You can learn more about subscribers in the [Subscribers](../../../development/events/subscribers.mdx) documentation. ::: @@ -69,7 +69,7 @@ You’ll be adding in the next step the necessary dependencies to the subscriber :::info -You can learn more about [dependency injection](../backend/dependency-container/index.md) in this documentation. +You can learn more about [dependency injection](../../../development/fundamentals/dependency-injection.md) in this documentation. ::: @@ -108,7 +108,7 @@ Where `` is the identifier for your notificati :::info -You can learn more about handling events with the Notification Service using [this documentation](../backend/notification/how-to-create-notification-provider.md). +You can learn more about handling events with the Notification Service using [this documentation](../../../development/notification/create-notification-provider.md). ::: @@ -117,7 +117,10 @@ You can learn more about handling events with the Notification Service using [th If the notification provider you’re using isn’t configured to handle this event, or you want to implement some other custom logic, you can subscribe to the event using the `EventBusService`: ```ts title=src/subscribers/gift-card.ts -import { EventBusService, GiftCardService } from "@medusajs/medusa" +import { + EventBusService, + GiftCardService, +} from "@medusajs/medusa" type InjectedDependencies = { eventBusService: EventBusService @@ -127,13 +130,19 @@ type InjectedDependencies = { class GiftCardSubscriber { giftCardService: GiftCardService - constructor({ eventBusService, giftCardService }: InjectedDependencies) { + constructor({ + eventBusService, + giftCardService, + }: InjectedDependencies) { this.giftCardService = giftCardService - eventBusService.subscribe("gift_card.created", this.handleGiftCard) + eventBusService.subscribe( + "gift_card.created", this.handleGiftCard) } handleGiftCard = async (data) => { - const giftCard = await this.giftCardService.retrieve(data.id) + const giftCard = await this.giftCardService.retrieve( + data.id + ) // TODO send customer the gift card code } } @@ -143,12 +152,4 @@ export default GiftCardSubscriber When using this method, you’ll have to handle the logic of sending the code to the customer inside the handler function, which in this case is `handleGiftCard`. -The `handleGiftCard` event receives a `data` object as a parameter. This object holds the `id` property which is the ID of the gift card. You can retrieve the full gift card object using the [GiftCardService](../../references/services/classes/GiftCardService.md) - ---- - -## See Also - -- [Subscribers overview](../backend/subscribers/overview.md) -- [Notification architecture overview](../backend/notification/overview.md) -- [Gift cards overview](../backend/gift-cards/index.md) \ No newline at end of file +The `handleGiftCard` event receives a `data` object as a parameter. This object holds the `id` property which is the ID of the gift card. You can retrieve the full gift card object using the [GiftCardService](../../../references/services/classes/GiftCardService.md) \ No newline at end of file diff --git a/docs/content/advanced/backend/gift-cards/index.md b/docs/content/modules/gift-cards/gift-cards.md similarity index 86% rename from docs/content/advanced/backend/gift-cards/index.md rename to docs/content/modules/gift-cards/gift-cards.md index 7d213ec70c6a3..205af0add50bb 100644 --- a/docs/content/advanced/backend/gift-cards/index.md +++ b/docs/content/modules/gift-cards/gift-cards.md @@ -1,5 +1,5 @@ --- -description: 'Learn what gift cards are and how they work in the Medusa server. Learn about the relations between Gift Cards and other entities.' +description: 'Learn what gift cards are and how they work in the Medusa backend. Learn about the relations between Gift Cards and other entities.' --- # Gift Cards @@ -34,7 +34,7 @@ As custom gift cards can be used once they’re created, they’re also represen ## GiftCard Entity Overview -Some of the [GiftCard](../../../references/entities/classes/GiftCard.md) entity’s attributes are: +Some of the [GiftCard](../../references/entities/classes/GiftCard.md) entity’s attributes are: - `code`: a unique string of random characters. This is the code that the customer can use during their checkout to redeem the gift card. - `value`: The amount of the gift card. This is the amount the customer purchased, or was gifted in the case of custom gift cards. @@ -70,7 +70,6 @@ You can also access the gift cards used in an order by expanding the `gift_cards ## See Also -- Gift cards [store](/api/store/#tag/Gift-Card) and [admin](/api/admin/#tag/Gift-Card) APIs -- [How to manage gift cards using admin APIs](../../admin/manage-gift-cards.mdx) -- [How to use gift cards in the storefront](../../storefront/use-gift-cards.mdx) -- [How to send the customer a gift card](../../ecommerce/send-gift-card-to-customer.md) +- [Manage gift cards using admin APIs](./admin/manage-gift-cards.mdx) +- [Use gift cards in the storefront](./storefront/use-gift-cards.mdx) +- [Send the customer a gift card](./backend/send-gift-card-to-customer.md) diff --git a/docs/content/modules/gift-cards/overview.mdx b/docs/content/modules/gift-cards/overview.mdx new file mode 100644 index 0000000000000..13421b7b6a834 --- /dev/null +++ b/docs/content/modules/gift-cards/overview.mdx @@ -0,0 +1,149 @@ +--- +description: "Gift cards are prepaid codes that can be purchased and used during checkout as an alternative to payment methods or to receive a discount. Learn about the available features and guides." +--- + +import DocCardList from '@theme/DocCardList'; +import DocCard from '@theme/DocCard'; +import Icons from '@theme/Icon'; + +# Gift Cards + +Gift cards are prepaid codes that can be purchased and used during checkout as an alternative to payment methods or to receive a discount. This overview introduces the available features related to gift cards. + +:::note + +Not a developer? Check out the [Gift Cards user guide](../../user-guide/gift-cards/index.md). + +::: + +## Features + +### Gift Card Management + +Admins can manage their main gift card with unlimited denominations. + + + +### Gift Card Purchasing + +Customers can view the gift card and purchase it on the storefront. Customers can also use the gift card during checkout to deduct the gift card’s balance from the checkout total. + +Developers can implement custom logic to send the gift card to the customer. They can alternatively implement a Shipping Profile that specifically handles the fulfillment of gift cards. + + + +### Custom Gift Cards + +Admins can create custom gift cards that are sent to specific customers. These customers can then use the gift card during checkout, the same way they would if they purchased one. + + + +--- + +## Understand the Architecture + +Learn how gift card related entities and concepts are built, their relation to other modules, and more. + + + +--- + +## Related Modules + +Discover Gift Card's relation to other modules in Medusa + + \ No newline at end of file diff --git a/docs/content/advanced/storefront/use-gift-cards.mdx b/docs/content/modules/gift-cards/storefront/use-gift-cards.mdx similarity index 84% rename from docs/content/advanced/storefront/use-gift-cards.mdx rename to docs/content/modules/gift-cards/storefront/use-gift-cards.mdx index 81c346d016c31..b634aa690bc37 100644 --- a/docs/content/advanced/storefront/use-gift-cards.mdx +++ b/docs/content/modules/gift-cards/storefront/use-gift-cards.mdx @@ -28,29 +28,29 @@ You want to implement the following features in a storefront: ### Medusa Components -It's assumed that you already have a Medusa server installed and set up. If not, you can follow the [quickstart guide](../../quickstart/quick-start.mdx) to get started. +It's assumed that you already have a Medusa backend installed and set up. If not, you can follow the [quickstart guide](../../../development/backend/install.mdx) to get started. -It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install either the [Next.js](../../starters/nextjs-medusa-starter.mdx) or [Gatsby](../../starters/gatsby-medusa-starter.mdx) storefronts. +It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install the [Next.js starter storefront](../../../starters/nextjs-medusa-starter.mdx). ### JS Client -This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client, among other methods. +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, among other methods. -If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../../js-client/overview.md) and have [created an instance of the client](../../js-client/overview.md#configuration). +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../../../js-client/overview.md) and have [created an instance of the client](../../../js-client/overview.md#configuration). ### Medusa React -This guide also includes code snippets to send requests to your Medusa server using Medusa React, among other methods. +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. -If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../medusa-react/overview.md#usage). +If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). -For requests that use the cart, it's also assumed you already have [used CartProvider higher in your component tree](../../medusa-react/overview.md#cartprovider). +For requests that use the cart, it's also assumed you already have [used CartProvider higher in your component tree](../../../medusa-react/overview.md#cartprovider). ### Previous Steps To use gift cards, you must have a gift card created first. You can follow this documentation to learn how to do it using the admin APIs. -In addition, this document doesn't cover how to implement checkout functionality. You can follow [this document](./how-to-implement-checkout-flow.mdx) to learn how to implement that. +In addition, this document doesn't cover how to implement checkout functionality. You can follow [this document](../../carts-and-checkout/storefront/implement-checkout-flow.mdx) to learn how to implement that. --- @@ -99,7 +99,9 @@ const GiftCard = () => { ))}
)} - {products && !products.length && No Gift Cards} + {products && !products.length && ( + No Gift Cards + )}
) } @@ -111,7 +113,7 @@ export default GiftCard ```ts -fetch(`/store/products?is_giftcard=true`, { +fetch(`/store/products?is_giftcard=true`, { credentials: "include", }) .then((response) => response.json()) @@ -186,7 +188,7 @@ export default GiftCard ```ts -fetch(`/store/gift-cards/${code}`, { +fetch(`/store/gift-cards/${code}`, { credentials: "include", }) .then((response) => response.json()) @@ -273,7 +275,7 @@ export default Cart ```ts -fetch(`/store/cart/${cartId}`, { +fetch(`/store/cart/${cartId}`, { method: "POST", credentials: "include", headers: { @@ -318,13 +320,4 @@ You can show the details of the applied gift cards by accessing `cart.gift_cards You can also use the following properties to display changes on the cart’s totals: - `gift_card_total`: The total amount applied by all the gift cards. -- `gift_card_tax_total`: The total tax applied for all gift cards. - ---- - -## See Also - -- [Gift cards overview](../backend/gift-cards/index.md) -- [Manage gift cards using admin APIs](../admin/manage-gift-cards.mdx) -- [Send the customer a gift card](../ecommerce/send-gift-card-to-customer.md) -- Gift cards [store](/api/store/#tag/Gift-Card) and [admin](/api/admin/#tag/Gift-Card) APIs +- `gift_card_tax_total`: The total tax applied for all gift cards. \ No newline at end of file diff --git a/docs/content/advanced/admin/order-edit.mdx b/docs/content/modules/orders/admin/edit-order.mdx similarity index 87% rename from docs/content/advanced/admin/order-edit.mdx rename to docs/content/modules/orders/admin/edit-order.mdx index f5048ceaaf787..dad0e2e27ae4b 100644 --- a/docs/content/advanced/admin/order-edit.mdx +++ b/docs/content/modules/orders/admin/edit-order.mdx @@ -26,7 +26,7 @@ The Order Edit can then either be confirmed using the Storefront API as a custom The changes are only reflected on the original order once the Order Edit is confirmed. -![Order edit documentation](https://res.cloudinary.com/dza7lstvk/image/upload/v1671719712/Medusa%20Docs/Diagrams/Order_Edits_xvquwc.jpg) +![Order edit flow](https://res.cloudinary.com/dza7lstvk/image/upload/v1677782269/Medusa%20Docs/Diagrams/order-edit_mcnfc3.jpg) ### Scenario @@ -50,19 +50,19 @@ You can perform other functionalities related to order editing. To learn more, c ### Medusa Components -It is assumed that you already have a Medusa server installed and set up. If not, you can follow our [quickstart guide](../../quickstart/quick-start.mdx) to get started. +It is assumed that you already have a Medusa backend installed and set up. If not, you can follow our [quickstart guide](../../../development/backend/install.mdx) to get started. ### JS Client -This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client, among other methods. +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, among other methods. -If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../js-client/overview.md) installed and have [created an instance of the client](../../js-client/overview.md#configuration). +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../../js-client/overview.md) installed and have [created an instance of the client](../../../js-client/overview.md#configuration). ### Medusa React -This guide also includes code snippets to send requests to your Medusa server using Medusa React, among other methods. +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. -If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../medusa-react/overview.md#usage). +If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). ### Authenticated Admin User @@ -119,7 +119,7 @@ export default OrderEdit ```ts -fetch(`/admin/order-edits`, { +fetch(`/admin/order-edits`, { method: "POST", credentials: "include", headers: { @@ -139,7 +139,7 @@ fetch(`/admin/order-edits`, { ```bash -curl -L -X POST '/admin/order-edits' \ +curl -L -X POST '/admin/order-edits' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -198,12 +198,13 @@ import { useAdminOrderEditAddLineItem } from "medusa-react" const OrderEdit = () => { const addLineItem = useAdminOrderEditAddLineItem(orderEditId) - const handleAddLineItem = (quantity: number, variantId: string) => { - addLineItem.mutate({ - quantity, - variant_id: variantId, - }) - } + const handleAddLineItem = + (quantity: number, variantId: string) => { + addLineItem.mutate({ + quantity, + variant_id: variantId, + }) + } // ... } @@ -215,7 +216,7 @@ export default OrderEdit ```ts -fetch(`/admin/order-edits/${orderEditId}/items`, { +fetch(`/admin/order-edits/${orderEditId}/items`, { method: "POST", credentials: "include", headers: { @@ -236,7 +237,7 @@ fetch(`/admin/order-edits/${orderEditId}/items`, { ```bash -curl -L -X POST '/admin/order-edits//items' \ +curl -L -X POST '/admin/order-edits//items' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -299,8 +300,10 @@ export default OrderEdit + + ```ts -fetch(`/admin/order-edits/${orderEditId}/items/${itemId}`, { +fetch(`/admin/order-edits/${orderEditId}/items/${itemId}`, { method: "POST", credentials: "include", headers: { @@ -320,7 +323,7 @@ fetch(`/admin/order-edits/${orderEditId}/items/${itemId}`, { ```bash -curl -L -X POST '/admin/order-edits//items/' \ +curl -L -X POST '/admin/order-edits//items/' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -376,8 +379,10 @@ export default OrderEdit + + ```ts -fetch(`/admin/order-edits/${orderEditId}/items/${itemId}`, { +fetch(`/admin/order-edits/${orderEditId}/items/${itemId}`, { method: "DELETE", credentials: "include", }) @@ -391,7 +396,7 @@ fetch(`/admin/order-edits/${orderEditId}/items/${itemId}`, { ```bash -curl -L -X DELETE '/admin/order-edits//items/' \ +curl -L -X DELETE '/admin/order-edits//items/' \ -H 'Authorization: Bearer ' ``` @@ -445,9 +450,11 @@ export default OrderEdit + + ```ts fetch( - `/admin/order-edits/${orderEditId}/changes/${changeId}`, + `/admin/order-edits/${orderEditId}/changes/${changeId}`, { method: "DELETE", credentials: "include", @@ -463,7 +470,7 @@ fetch( ```bash -curl -L -X DELETE '/admin/order-edits//changes/' \ +curl -L -X DELETE '/admin/order-edits//changes/' \ -H 'Authorization: Bearer ' ``` @@ -492,7 +499,10 @@ To move an Order Edit into the request state, send a request to the [Request Con ```ts medusa.admin.orderEdits.requestConfirmation(orderEditId) .then(({ order_edit }) => { - console.log(order_edit.requested_at, order_edit.requested_by) + console.log( + order_edit.requested_at, + order_edit.requested_by + ) }) ``` @@ -500,7 +510,9 @@ medusa.admin.orderEdits.requestConfirmation(orderEditId) ```tsx -import { useAdminRequestOrderEditConfirmation } from "medusa-react" +import { + useAdminRequestOrderEditConfirmation, +} from "medusa-react" const OrderEdit = () => { const requestOrderConfirmation = @@ -521,8 +533,10 @@ export default OrderEdit + + ```ts -fetch(`/admin/order-edits/${orderEditId}/request`, { +fetch(`/admin/order-edits/${orderEditId}/request`, { method: "POST", credentials: "include", }) @@ -536,7 +550,7 @@ fetch(`/admin/order-edits/${orderEditId}/request`, { ```bash -curl -L -X POST '/admin/order-edits//request' \ +curl -L -X POST '/admin/order-edits//request' \ -H 'Authorization: Bearer ' ``` @@ -552,7 +566,7 @@ It returns the Order Edit object. You can access the following properties relate :::tip -💡 This request triggers the event `order-edit.requested`. You can use a subscriber to send an email to the customer with a link to view the order edit on the storefront. You can learn more in the [Events reference](../backend/subscribers/events-list.md). +💡 This request triggers the event `order-edit.requested`. You can use a subscriber to send an email to the customer with a link to view the order edit on the storefront. You can learn more in the [Events reference](../../../development/events/events-list.md). ::: @@ -607,8 +621,10 @@ export default OrderEdit + + ```ts -fetch(`/admin/order-edits/${orderEditId}/confirm`, { +fetch(`/admin/order-edits/${orderEditId}/confirm`, { method: "POST", credentials: "include", }) @@ -622,7 +638,7 @@ fetch(`/admin/order-edits/${orderEditId}/confirm`, { ```bash -curl -L -X POST '/admin/order-edits//confirm' \ +curl -L -X POST '/admin/order-edits//confirm' \ -H 'Authorization: Bearer ' ``` @@ -673,7 +689,9 @@ medusa.admin.payments.capturePayment(paymentId) import { useAdminPaymentsCapturePayment } from "medusa-react" const OrderEditPayment = () => { - const capturePayment = useAdminPaymentsCapturePayment(paymentId) + const capturePayment = useAdminPaymentsCapturePayment( + paymentId + ) const handleCapturePayment = () => { capturePayment.mutate() @@ -689,7 +707,7 @@ export default OrderEditPayment ```ts -fetch(`/admin/payments/${paymentId}/capture`, { +fetch(`/admin/payments/${paymentId}/capture`, { method: "POST", credentials: "include", }) @@ -703,7 +721,7 @@ fetch(`/admin/payments/${paymentId}/capture`, { ```bash -curl -L -X POST '/admin/payments//capture' \ +curl -L -X POST '/admin/payments//capture' \ -H 'Authorization: Bearer ' ``` @@ -746,12 +764,13 @@ import { RefundReason } from "@medusajs/medusa" const OrderEditPayment = () => { const refundPayment = useAdminPaymentsRefundPayment(paymentId) - const handleRefundPayment = (amount: number, reason: RefundReason) => { - refundPayment.mutate({ - amount, - reason, - }) - } + const handleRefundPayment = + (amount: number, reason: RefundReason) => { + refundPayment.mutate({ + amount, + reason, + }) + } // ... } @@ -763,7 +782,7 @@ export default OrderEditPayment ```ts -fetch(`/admin/payments/${paymentId}/refund`, { +fetch(`/admin/payments/${paymentId}/refund`, { method: "POST", credentials: "include", headers: { @@ -784,7 +803,7 @@ fetch(`/admin/payments/${paymentId}/refund`, { ```bash -curl -L -X POST '/admin/payments//refund' \ +curl -L -X POST '/admin/payments//refund' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -820,5 +839,4 @@ It returns in the response the full Refund object. ## See Also -- [Handle order edits on the storefront](../storefront/handle-order-edits). -- [Order Edits API reference](/api/admin/#tag/OrderEdit). +- [Handle order edits on the storefront](../storefront/handle-order-edits.mdx) diff --git a/docs/content/advanced/ecommerce/handle-order-claim-event.md b/docs/content/modules/orders/backend/handle-order-claim-event.md similarity index 75% rename from docs/content/advanced/ecommerce/handle-order-claim-event.md rename to docs/content/modules/orders/backend/handle-order-claim-event.md index c067c70a9a887..23e610023396d 100644 --- a/docs/content/advanced/ecommerce/handle-order-claim-event.md +++ b/docs/content/modules/orders/backend/handle-order-claim-event.md @@ -1,5 +1,5 @@ --- -description: 'Learn how to handle the order claim event in the Medusa server. When the event is triggered, you can send an email to the customer to inform them about it.' +description: 'Learn how to handle the order claim event in the Medusa backend. When the event is triggered, you can send an email to the customer to inform them about it.' addHowToData: true --- @@ -13,11 +13,11 @@ When a guest customer places an order, the order is not associated with a custom After the customer registers, later on, they can claim that order by providing the order’s ID. -When the customer requests to claim the order, the event `order-update-token.created` is triggered on the Medusa server. This event should be used to send the customer a confirmation email. +When the customer requests to claim the order, the event `order-update-token.created` is triggered on the Medusa backend. This event should be used to send the customer a confirmation email. ### What You’ll Learn -In this document, you’ll learn how to handle the `order-update-token.created` event on the server to send the customer a confirmation email. +In this document, you’ll learn how to handle the `order-update-token.created` event on the backend to send the customer a confirmation email. --- @@ -25,17 +25,17 @@ In this document, you’ll learn how to handle the `order-update-token.created` ### Medusa Components -It's assumed that you already have a Medusa server installed and set up. If not, you can follow the [quickstart guide](../../quickstart/quick-start.mdx) to get started. +It's assumed that you already have a Medusa backend installed and set up. If not, you can follow the [quickstart guide](../../../development/backend/install.mdx) to get started. ### Redis -Redis is required for batch jobs to work. Make sure you [install Redis](../../tutorial/0-set-up-your-development-environment.mdx#redis) and [configure it with your Medusa server](../../usage/configurations.md#redis). +Redis is required for batch jobs to work. Make sure you [install Redis](../../../development/backend/prepare-environment.mdx#redis) and [configure it with the Medusa backend](../../../development/backend/configurations.md#redis). ### Notification Provider -To send an email or another type of notification method, you must have a notification provider installed or configured. You can either install an existing plugin or [create your own](../backend/notification/how-to-create-notification-provider.md). +To send an email or another type of notification method, you must have a notification provider installed or configured. You can either install an existing plugin or [create your own](../../../development/notification/create-notification-provider.md). -This document has an example using the [SendGrid](../../add-plugins/sendgrid.mdx) plugin. +This document has an example using the [SendGrid](../../../plugins/notifications/sendgrid.mdx) plugin. --- @@ -45,7 +45,7 @@ To subscribe to and handle an event, you must create a subscriber. :::tip -You can learn more about subscribers in the [Subscribers](../backend/subscribers/overview.md) documentation. +You can learn more about subscribers in the [Subscribers](../../../development/events/subscribers.mdx) documentation. ::: @@ -69,7 +69,7 @@ You’ll be adding in the next step the necessary dependencies to the subscriber :::info -You can learn more about [dependency injection](../backend/dependency-container/index.md) in this documentation. +You can learn more about [dependency injection](../../../development/fundamentals/dependency-injection.md) in this documentation. ::: @@ -108,7 +108,7 @@ Where `` is the identifier for your notificati :::info -You can learn more about handling events with the Notification Service using [this documentation](../backend/notification/how-to-create-notification-provider.md). +You can learn more about handling events with the Notification Service using [this documentation](../../../development/notification/create-notification-provider.md). ::: @@ -150,7 +150,7 @@ The `handleRequestClaimOrder` event receives a `data` object as a parameter. Thi In this method, you should typically send an email to the customer’s old email. In the email, you should link to a page in your storefront and pass the `token` as a parameter. -The page would then send a request to the server to verify that the `token` is valid and associate the order with the customer. You can read more about how to implement this in your storefront in [this documentation](../storefront/implement-claim-order.mdx). +The page would then send a request to the backend to verify that the `token` is valid and associate the order with the customer. You can read more about how to implement this in your storefront in [this documentation](../storefront/implement-claim-order.mdx). --- @@ -158,6 +158,8 @@ The page would then send a request to the server to verify that the `token` is v For example, you can implement this subscriber to send emails using SendGrid: + + ```ts title=src/subscribers/claim-order.ts import { EventBusService } from "@medusajs/medusa" @@ -169,7 +171,10 @@ type InjectedDependencies = { class ClaimOrderSubscriber { protected sendGridService: any - constructor({ eventBusService, sendgridService }: InjectedDependencies) { + constructor({ + eventBusService, + sendgridService, + }: InjectedDependencies) { this.sendGridService = sendgridService eventBusService.subscribe( "order-update-token.created", diff --git a/docs/content/modules/orders/overview.mdx b/docs/content/modules/orders/overview.mdx new file mode 100644 index 0000000000000..8a357a8326d48 --- /dev/null +++ b/docs/content/modules/orders/overview.mdx @@ -0,0 +1,357 @@ +--- +description: "Customers place orders to purchase products from an ecommerce business. Learn about the available features and guides." +--- + +import DocCardList from '@theme/DocCardList'; +import Icons from '@theme/Icon'; + +# Orders + +Customers place orders to purchase products from an ecommerce business. This overview introduces the available features related to orders. + +:::note + +Not a developer? Check out the [Orders user guide](../../user-guide/orders/index.md). + +::: + +## Features + +### Order Management + +Admins can manage orders placed by customers, including capturing payment and fulfilling items in the order. Admins can also export orders into CSV files. + +Customers can view their previous orders. + + + + + +### Edit Orders + +Admins can perform edits on items in an order, such as add, remove, or update items. Admins can request confirmation from the customer or force apply the edit. + +Customers can review order edit requests and authorize additional payments if necessary. + + + +### Draft Orders + +Admins can create draft orders that don’t require involvement from a customer. They can specify all details including items in the order, payment method, and more. + + + +### Returns, Swaps, and Claims + +Admins can return order items, or create swaps to return an item to be replaced by a new one. + +Customers can also request to return or swap items. This allows for implementing an automated Return Merchandise Authorization (RMA) flow. + + + +--- + +## Understand the Architecture + +Learn how order-related entities are built, their relation to other modules, and more. + + + +--- + +## Related Modules + +Discover Order’s relation to other modules in Medusa + + diff --git a/docs/content/advanced/storefront/handle-order-edits.mdx b/docs/content/modules/orders/storefront/handle-order-edits.mdx similarity index 87% rename from docs/content/advanced/storefront/handle-order-edits.mdx rename to docs/content/modules/orders/storefront/handle-order-edits.mdx index 69a2034cc9efb..c3e60c6a8022b 100644 --- a/docs/content/advanced/storefront/handle-order-edits.mdx +++ b/docs/content/modules/orders/storefront/handle-order-edits.mdx @@ -22,7 +22,7 @@ This guide focuses on how to use the Storefront APIs to implement the flow that :::note -You can check out how to implement order editing using the Admin APIs in [this documentation](../admin/order-edit.mdx). +You can check out how to implement order editing using the Admin APIs in [this documentation](../admin/edit-order.mdx). ::: @@ -46,21 +46,21 @@ You can perform other functionalities related to order editing. To learn more, c ### Medusa Components -It's assumed that you already have a Medusa server installed and set up. If not, you can follow our [quickstart guide](../../quickstart/quick-start.mdx) to get started. +It's assumed that you already have a Medusa backend installed and set up. If not, you can follow our [quickstart guide](../../../development/backend/install.mdx) to get started. -It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install either the [Next.js](../../starters/nextjs-medusa-starter.mdx) or [Gatsby](../../starters/gatsby-medusa-starter.mdx) storefronts. +It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install the [Next.js starter storefront](../../../starters/nextjs-medusa-starter.mdx). ### JS Client -This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client and JavaScript’s Fetch API. +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client and JavaScript’s Fetch API. -If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../../js-client/overview.md) and have [created an instance of the client](../../js-client/overview.md#configuration). +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../../../js-client/overview.md) and have [created an instance of the client](../../../js-client/overview.md#configuration). ### Medusa React -This guide also includes code snippets to send requests to your Medusa server using Medusa React, among other methods. +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. -If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../medusa-react/overview.md#usage). +If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). ### Previous Steps @@ -102,7 +102,7 @@ export default OrderEdit ```ts -fetch(`/store/order-edits/${orderEditId}`) +fetch(`/store/order-edits/${orderEditId}`) .then((response) => response.json()) .then(({ order_edit }) => { console.log(order_edit.changes) @@ -161,7 +161,9 @@ Here’s an example of how you can use this data to show the customer the reques } {itemChange.type === "added" && New Item} - {itemChange.type === "removed" && Removed Item} + {itemChange.type === "removed" && ( + Removed Item + )} {itemChange.type === "edited" && Edited Item @@ -201,6 +203,8 @@ If `difference_due` is greater than 0, then additional payment from the customer + + ```ts medusa.paymentCollections.managePaymentSession(paymentCollectionId, { provider_id, @@ -217,7 +221,9 @@ medusa.paymentCollections.managePaymentSession(paymentCollectionId, { import { useManagePaymentSession } from "medusa-react" const OrderEditPayment = () => { - const managePaymentSession = useManagePaymentSession(paymentCollectionId) + const managePaymentSession = useManagePaymentSession( + paymentCollectionId + ) // ... const handleAdditionalPayment = (provider_id: string) => { @@ -235,9 +241,11 @@ export default OrderEditPayment + + ```ts fetch( - `/store/payment-collections/${paymentCollectionId}/sessions`, + `/store/payment-collections/${paymentCollectionId}/sessions`, { method: "POST", credentials: "include", @@ -265,8 +273,12 @@ fetch( ```ts -medusa.paymentCollection - .authorizePaymentSession(paymentCollectionId, paymentSessionId) +medusa + .paymentCollection + .authorizePaymentSession( + paymentCollectionId, + paymentSessionId + ) .then(({ payment_session }) => { console.log(payment_session.id) }) @@ -297,9 +309,11 @@ export default OrderEditPayment + + ```ts fetch( - `/store/payment-collection/${paymentCollectionId}` + + `/store/payment-collection/${paymentCollectionId}` + `/sessions/${paymentSessionId}/authorize`, { method: "POST", @@ -356,8 +370,10 @@ export default OrderEdit + + ```ts -fetch(`/store/order-edits/${orderEditId}/complete`, { +fetch(`/store/order-edits/${orderEditId}/complete`, { method: "POST", credentials: "include", }) @@ -426,16 +442,19 @@ export default OrderEdit ```ts -fetch(`/store/order-edits/${orderEditId}/decline`, { - method: "POST", - credentials: "include", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - decline_reason: "I am not satisfied", - }), -}) +fetch( + `/store/order-edits/${orderEditId}/decline`, + { + method: "POST", + credentials: "include", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + decline_reason: "I am not satisfied", + }), + } +) .then((response) => response.json()) .then(({ order_edit }) => { console.log(order_edit.declined_at) @@ -455,5 +474,4 @@ If the Order Edit is declined, the changes requested in the Order Edit aren't re ## See Also -- [Order Edit API reference](/api/store/#tag/OrderEdit) -- [Edit an order using Admin APIs](../admin/order-edit.mdx) +- [Edit an order using Admin APIs](../admin/edit-order.mdx) diff --git a/docs/content/advanced/storefront/implement-claim-order.mdx b/docs/content/modules/orders/storefront/implement-claim-order.mdx similarity index 79% rename from docs/content/advanced/storefront/implement-claim-order.mdx rename to docs/content/modules/orders/storefront/implement-claim-order.mdx index 7ff038a86afb8..8951cc3d026c3 100644 --- a/docs/content/advanced/storefront/implement-claim-order.mdx +++ b/docs/content/modules/orders/storefront/implement-claim-order.mdx @@ -12,7 +12,7 @@ In this document, you’ll learn how to implement the claim order flow in a stor :::note -This flow was added starting from Medusa v1.7. You can learn more about upgrading in the [upgrade guide](../backend/upgrade-guides/medusa-core/1-7-0.md). +This flow was added starting from Medusa v1.7. You can learn more about upgrading in the [upgrade guide](../../../upgrade-guides/medusa-core/1-7-0.md). ::: @@ -28,7 +28,7 @@ The email should contain a link to a page in the storefront, and the link should The customer must then click the link in the email they received. If the token is valid, the order will be associated with the customer. -![Claim Order Flow](https://res.cloudinary.com/dza7lstvk/image/upload/v1671040165/Medusa%20Docs/Diagrams/Claim_Order_Flow_ybf2ok.jpg) +![Claim Order Flow](https://res.cloudinary.com/dza7lstvk/image/upload/v1677782439/Medusa%20Docs/Diagrams/claim-order-workflow_m6oybo.jpg) ### What You’ll Learn @@ -43,31 +43,31 @@ In this document, you’ll learn how to implement two parts of this flow: ### Medusa Components -It's assumed that you already have a Medusa server installed and set up. If not, you can follow the [quickstart guide](../../quickstart/quick-start.mdx) to get started. +It's assumed that you already have a Medusa backend installed and set up. If not, you can follow the [quickstart guide](../../../development/backend/install.mdx) to get started. -It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install either the [Next.js](../../starters/nextjs-medusa-starter.mdx) or [Gatsby](../../starters/gatsby-medusa-starter.mdx) storefronts. +It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install the [Next.js starter storefront](../../../starters/nextjs-medusa-starter.mdx). ### JS Client -This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client, among other methods. +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, among other methods. -If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../../js-client/overview.md) and have [created an instance of the client](../../js-client/overview.md#configuration). +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../../../js-client/overview.md) and have [created an instance of the client](../../../js-client/overview.md#configuration). ### Medusa React -This guide also includes code snippets to send requests to your Medusa server using Medusa React, among other methods. +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. -If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../medusa-react/overview.md#usage). +If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). ### Handle Order Claim Request Event When the customer requests to claim the order, an event will be triggered. You should subscribe to this event to send a confirmation email to the customer when the event is triggered. -You can learn how to implement this flow in [this documentation](../ecommerce/handle-order-claim-event.md). +You can learn how to implement this flow in [this documentation](../backend/handle-order-claim-event.md). ### Previous Steps -It is assumed you already have an order placed by a guest customer. You can refer to the [Cart](../../guides/carts-in-medusa.mdx) and [Checkout](./how-to-implement-checkout-flow.mdx) implementation documentation to learn how to implement them in your storefront. +It is assumed you already have an order placed by a guest customer. You can refer to the [Cart](../../carts-and-checkout/storefront/implement-cart) and [Checkout](../../carts-and-checkout/storefront/implement-checkout-flow.mdx) implementation documentation to learn how to implement them in your storefront. In addition, it is assumed you already have a logged-in customer before performing the steps in this document. You can refer to the [API reference](/api/store/#tag/Auth/operation/PostAuth) for more details on that. @@ -100,7 +100,7 @@ medusa.orders.claimOrders({ ```ts -fetch(`/store/orders/batch/customer/token`, { +fetch(`/store/orders/batch/customer/token`, { method: "POST", credentials: "include", body: JSON.stringify({ @@ -178,7 +178,7 @@ export default ClaimOrder ```ts -fetch(`/store/orders/customer/confirm`, { +fetch(`/store/orders/customer/confirm`, { method: "POST", credentials: "include", body: JSON.stringify({ @@ -207,4 +207,4 @@ If the verification is successful, the order will now be associated with the cus ## See Also -- [Send a confirmation email to claim an order](../ecommerce/handle-order-claim-event.md) +- [Send a confirmation email to claim an order](../backend/handle-order-claim-event.md) diff --git a/docs/content/modules/overview.mdx b/docs/content/modules/overview.mdx new file mode 100644 index 0000000000000..f2357f501f9d8 --- /dev/null +++ b/docs/content/modules/overview.mdx @@ -0,0 +1,247 @@ +--- +description: 'Learn about the ecommerce features that Medusa provides including order management, product management, multi region and currency support, and more.' +hide_table_of_contents: true +--- + +import DocCardList from '@theme/DocCardList' +import Icons from '@theme/Icon' +import LargeCardList from '@site/src/components/LargeCardList' +import LargeCard from '@site/src/components/LargeCard' + +# Commerce Modules + +Medusa offers ecommerce features essential to all types of businesses as Commerce Modules. Starting from the basic products management and order management, to the more advanced automated return and exchange flows. + +This part of the documentation covers Medusa’s ecommerce features and how they can be used. It also includes guides that help developers utilize these features to create unique digital experiences. + +## Feature Highlights + +This section gives an overview of the features available in Medusa. You can learn more about other available features by following the guides in this documentation. + +### Optimized Shopping and Fulfillment Experience + +Medusa provides the necessary features to build a customizable shopping experience for your customers. Medusa also offers features optimized for business operations to manage their orders effeciently. + + + + + - Process orders' payments and fulfillments with custom logic or third-party providers. + - Create one or multiple fulfillments for items in the order. + - Edit an order to add, update, or delete its items. + - Handle and automate order returns, exchanges, and refunds. + - Create draft orders without direct involvement from the customer. + + + + + + - Accept payments with payment providers including Stripe and PayPal. + - Calculate taxes of a cart through custom logic or third-party tax providers. + - Allow customers to apply discount codes and gift cards during checkout. + - Fully customize the frontend experience of the checkout process. + + + + + + - Allow orders from both registered and unregisterd customers. + - Allow customers to create return or exchange requests from the storefront for better customer experience. + - Assign customers different groups for segmentation and specify different pricing for customer groups. + + + + + +### Advanced Product Configurations and Management + +Medusa's products configuration allows managing products of different types including products with options and gift cards. Medusa also includes advanced features related to pricing and discounts. + + + + + - Create products with unlimited variants and options. + - Organize products into nested categories of different heirarchies. + - Associate products with collections, types, and tags. + - Manage a product’s inventory, pricing, sales channels, and more. + - Import and export products to and from Medusa using CSV files. + + + + + + - Offer your customers a gift card with unlimited denominations. + - Set denomination prices per currency to cater for different regions. + - Send custom gift cards to specific customers for marketing purposes. + - Manage a custom gift card's balance amount. + + + + + + - Create discounts and deals with advanced conditions and rules such as minimum cart quantity or specific products. + - Offer free shipping, fixed discount, or percentage discount. + - Override product prices using price lists and set special conditions such as specific customer groups. + - Import prices into a price list from a CSV file. + + + + + +### Ready Configurations for International Selling + +Medusa's multi-region setup and sales channels allow businesses to sell internationally and sell across platforms. Medusa allows configuring regions differently to cater for different markets across the globe. + + + + + - Create an unlimited number of regions, each associated with a currency and at least one country. + - Manage each region’s settings including payment providers, shipping options, and more. + - Set prices for products and shipping options specific to a currency or a region. + + + + + + - Specify different tax providers for different regions. + - Create tax providers using custom logic or third-party integrations. + - Customize tax configurations using tax rates and tax overrides. + - Enable tax-inclusive pricing for automatic tax-rate calculations during checkout. + + + + + + - Create sales channels for your different platforms such as web, mobile, or marketplaces. + - Specify the availability of products for each sales channel. + - Associate orders with each sales channel for better handling and logistics. + - Associate API keys with sales channels for easier development. + + + + + +## Get Additional Help + +If you have any questions about Medusa, its features, and development with it, feel free to reach out to the core team and the community behind Medusa on [Discord](https://discord.gg/medusajs). + +## Popular Guides + + \ No newline at end of file diff --git a/docs/content/advanced/admin/import-prices.mdx b/docs/content/modules/price-lists/admin/import-prices.mdx similarity index 80% rename from docs/content/advanced/admin/import-prices.mdx rename to docs/content/modules/price-lists/admin/import-prices.mdx index 8c0f6b3221bdf..de12ed0fd061e 100644 --- a/docs/content/advanced/admin/import-prices.mdx +++ b/docs/content/modules/price-lists/admin/import-prices.mdx @@ -12,7 +12,7 @@ In this document, you’ll learn how to bulk import prices into a price list usi ## Overview -Using Medusa’s [Batch Job Admin APIs](https://docs.medusajs.com/api/admin/#tag/Batch-Job), you can import prices into a price list. +Using Medusa’s [Batch Job Admin APIs](/api/admin/#tag/Batch-Job), you can import prices into a price list. :::caution @@ -26,46 +26,46 @@ Importing prices into a price list removes all existing prices in the price list ### Medusa Components -It is assumed that you already have a Medusa server installed and set up. If not, you can follow our [quickstart guide](../../quickstart/quick-start.mdx) to get started. +It is assumed that you already have a Medusa backend installed and set up. If not, you can follow our [quickstart guide](../../../development/backend/install.mdx) to get started. ### Redis -Redis is required for batch jobs to work. Make sure you [install Redis](../../tutorial/0-set-up-your-development-environment.mdx#redis) and [configure it with your Medusa server](./../../usage/configurations.md#redis). +Redis is required for batch jobs to work. Make sure you [install Redis](../../../development/backend/prepare-environment.mdx#redis) and [configure it with the Medusa backend](../../../development/backend/configurations.md#redis). ### File Service Plugin -Part of the process of importing prices is uploading a CSV file. This requires a file service plugin to be installed on your server. If you don’t have any installed, you can install one of the following options: +Part of the process of importing prices is uploading a CSV file. This requires a file service plugin to be installed on your backend. If you don’t have any installed, you can install one of the following options: -- [MinIO](../../add-plugins/minio.md) (At least version `1.1.0`) -- [Spaces](../../add-plugins/spaces.md) +- [MinIO](../../../plugins/file-service/minio.md) (At least version `1.1.0`) +- [Spaces](../../../plugins/file-service/spaces.md) ### CSV File -You must have a CSV file that you will use to import prices into your Medusa server. You can check [this CSV example file](https://medusa-doc-files.s3.amazonaws.com/price-list-import-template.csv) to see which format is required for your import. +You must have a CSV file that you will use to import prices into your Medusa backend. You can check [this CSV example file](https://medusa-doc-files.s3.amazonaws.com/price-list-import-template.csv) to see which format is required for your import. ### JS Client -This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client, among other methods. +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, among other methods. -If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../js-client/overview.md) installed and have [created an instance of the client](../../js-client/overview.md#configuration). +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../../js-client/overview.md) installed and have [created an instance of the client](../../../js-client/overview.md#configuration). ### Medusa React -This guide also includes code snippets to send requests to your Medusa server using Medusa React, among other methods. +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. -If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../medusa-react/overview.md#usage). +If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). ### Authenticated Admin User You must be an authenticated admin user before following along with the steps in the tutorial. -You can learn more about [authenticating as an admin user in the API reference](https://docs.medusajs.com/api/admin/#section/Authentication). +You can learn more about [authenticating as an admin user in the API reference](/api/admin/#section/Authentication). ### Created Price List Before importing the prices, you must have a price list to import them to. -You can use the [Create Price List](https://docs.medusajs.com/api/admin/#tag/Price-List/operation/PostPriceListsPriceList) endpoint, or follow the [how-to guide to learn how to create and manage price lists using the Admin API](../backend/price-lists/use-api.mdx). +You can use the [Create Price List](/api/admin/#tag/Price-List/operation/PostPriceListsPriceList) endpoint, or follow the [how-to guide to learn how to create and manage price lists using the Admin API](./manage-price-lists.mdx). --- @@ -73,7 +73,7 @@ You can use the [Create Price List](https://docs.medusajs.com/api/admin/#tag/Pri The first step is to upload the CSV file to import prices from. -You can do that by sending the following request to the [Upload Files](https://docs.medusajs.com/api/admin/#tag/Upload/operation/PostUploads) endpoint: +You can do that by sending the following request to the [Upload Files](/api/admin/#tag/Upload/operation/PostUploads) endpoint: @@ -112,7 +112,7 @@ export default ImportPrices const formData = new FormData() formData.append("files", file) // file is an instance of File -fetch(`/admin/uploads`, { +fetch(`/admin/uploads`, { method: "POST", credentials: "include", headers: { @@ -130,7 +130,7 @@ fetch(`/admin/uploads`, { ```bash -curl -L -X POST '/admin/uploads' \ +curl -L -X POST '/admin/uploads' \ -H 'Authorization: Bearer {api_token}' \ -H 'Content-Type: text/csv' \ -F 'files=@""' @@ -147,7 +147,7 @@ This request returns an array of uploads. Each item in the array is an object th To start a new price import, you must create a batch job. -You can do that by sending the following request to the [Create a Batch Job](https://docs.medusajs.com/api/admin/#tag/Batch-Job/operation/PostBatchJobs) endpoint: +You can do that by sending the following request to the [Create a Batch Job](/api/admin/#tag/Batch-Job/operation/PostBatchJobs) endpoint: @@ -196,7 +196,7 @@ export default ImportPrices ```ts -fetch(`/admin/batch-jobs`, { +fetch(`/admin/batch-jobs`, { method: "POST", credentials: "include", headers: { @@ -221,7 +221,7 @@ fetch(`/admin/batch-jobs`, { ```bash -curl -L -X POST '/admin/batch-jobs' \ +curl -L -X POST '/admin/batch-jobs' \ -H 'Authorization: Bearer {api_token}' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -304,7 +304,7 @@ export default ImportPrices ```ts -fetch(`/admin/batch-jobs/${batchJobId}`, { +fetch(`/admin/batch-jobs/${batchJobId}`, { credentials: "include", }) .then((response) => response.json()) @@ -317,7 +317,7 @@ fetch(`/admin/batch-jobs/${batchJobId}`, { ```bash -curl -L -X GET '/admin/batch-jobs/' \ +curl -L -X GET '/admin/batch-jobs/' \ -H 'Authorization: Bearer {api_token}' # is the ID of the batch job ``` @@ -387,7 +387,7 @@ export default ImportPrices ```ts -fetch(`/admin/batch-jobs/${batchJobId}/confirm`, { +fetch(`/admin/batch-jobs/${batchJobId}/confirm`, { method: "POST", credentials: "include", }) @@ -401,7 +401,7 @@ fetch(`/admin/batch-jobs/${batchJobId}/confirm`, { ```bash -curl -L -X POST '/admin/batch-jobs//confirm' \ +curl -L -X POST '/admin/batch-jobs//confirm' \ -H 'Authorization: Bearer {api_token}' # is the ID of the batch job ``` @@ -423,5 +423,5 @@ After confirming the batch job, you can check the status while it is processing ## See Also -- [Batch Jobs Overview](../backend/batch-jobs/index.md) -- [Batch Jobs API Reference](https://docs.medusajs.com/api/admin/#tag/Batch-Job) +- [Batch Jobs Overview](../../../development/batch-jobs/index.mdx) +- [Batch Jobs API Reference](/api/admin/#tag/Batch-Job) diff --git a/docs/content/advanced/backend/price-lists/use-api.mdx b/docs/content/modules/price-lists/admin/manage-price-lists.mdx similarity index 78% rename from docs/content/advanced/backend/price-lists/use-api.mdx rename to docs/content/modules/price-lists/admin/manage-price-lists.mdx index 85c2141af2ddf..a7df8fd5dac01 100644 --- a/docs/content/advanced/backend/price-lists/use-api.mdx +++ b/docs/content/modules/price-lists/admin/manage-price-lists.mdx @@ -6,13 +6,13 @@ addHowToData: true import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# How to Manage PriceLists +# How to Manage Price Lists In this document, you’ll learn how to use the PriceList Admin APIs to create, update, and manage prices in a price list. :::note -This document doesn't cover what price lists are and their basics. If you’re interested to learn about that, check out [this documentation](./index.md) instead. +This document doesn't cover what price lists are and their basics. If you’re interested to learn about that, check out [this documentation](../price-lists.md) instead. ::: @@ -20,17 +20,17 @@ This document doesn't cover what price lists are and their basics. If you’re i ### Medusa Components -It is assumed that you already have a Medusa server installed and set up. If not, you can follow our [quickstart guide](../../../quickstart/quick-start.mdx) to get started. +It is assumed that you already have a Medusa backend installed and set up. If not, you can follow our [quickstart guide](../../../development/backend/install.mdx) to get started. ### JS Client -This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client, JavaScript’s Fetch API, or cURL. +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, JavaScript’s Fetch API, or cURL. If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../../js-client/overview.md) installed and [have created an instance of the client](../../../js-client/overview.md#configuration). ### Medusa React -This guide also includes code snippets to send requests to your Medusa server using Medusa React, among other methods. +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). @@ -38,7 +38,7 @@ If you follow the Medusa React code blocks, it's assumed you already have [Medus You must be an authenticated admin user before following along with the steps in the tutorial. -You can learn more about [authenticating as an admin user in the API reference](https://docs.medusajs.com/api/admin/#section/Authentication). +You can learn more about [authenticating as an admin user in the API reference](/api/admin/#section/Authentication). --- @@ -80,7 +80,10 @@ For example, sending the following request creates a price list with two prices: ```jsx -import { PriceListStatus, PriceListType } from "@medusajs/medusa" +import { + PriceListStatus, + PriceListType, +} from "@medusajs/medusa" medusa.admin.priceLists.create({ name: "New Price List", @@ -111,7 +114,10 @@ medusa.admin.priceLists.create({ ```tsx -import { PriceListStatus, PriceListType } from "@medusajs/medusa" +import { + PriceListStatus, + PriceListType, +} from "@medusajs/medusa" import { useAdminCreatePriceList } from "medusa-react" const CreatePriceList = () => { @@ -151,7 +157,7 @@ export default CreatePriceList ```jsx -fetch(`/admin/price-lists`, { +fetch(`/admin/price-lists`, { method: "POST", credentials: "include", headers: { @@ -188,7 +194,7 @@ fetch(`/admin/price-lists`, { ```bash -curl -L -X POST '/admin/price-lists' \ +curl -L -X POST '/admin/price-lists' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -218,7 +224,7 @@ curl -L -X POST '/admin/price-lists' \ This request returns the created price list. -You can check the full list of request body parameters in the [API reference](https://docs.medusajs.com/api/admin/#tag/Price-List/operation/PostPriceListsPriceList). +You can check the full list of request body parameters in the [API reference](/api/admin/#tag/Price-List/operation/PostPriceListsPriceList). --- @@ -244,7 +250,10 @@ import { CustomerGroup } from "@medusajs/medusa" import { useAdminPriceList } from "medusa-react" const PriceList = () => { - const { price_list, isLoading } = useAdminPriceList(priceListId) + const { + price_list, + isLoading, + } = useAdminPriceList(priceListId) return (
@@ -261,7 +270,7 @@ export default PriceList ```jsx -fetch(`/admin/price-lists/${priceListId}`, { +fetch(`/admin/price-lists/${priceListId}`, { credentials: "include", }) .then((response) => response.json()) @@ -274,7 +283,7 @@ fetch(`/admin/price-lists/${priceListId}`, { ```bash -curl -L -X GET '/admin/price-lists/{id}' \ +curl -L -X GET '/admin/price-lists/{id}' \ -H 'Authorization: Bearer ' ``` @@ -285,7 +294,7 @@ curl -L -X GET '/admin/price-lists/{id}' \ ## Update a Price List -After creating a price list, you can update all of its fields including its status, prices, and more using the [Update Price List](https://docs.medusajs.com/api/admin/#tag/Price-List/operation/PostPriceListsPriceListPriceList) endpoint. +After creating a price list, you can update all of its fields including its status, prices, and more using the [Update Price List](/api/admin/#tag/Price-List/operation/PostPriceListsPriceListPriceList) endpoint. For example, by sending the following request the end date of the price list will be updated: @@ -305,7 +314,10 @@ medusa.admin.priceLists.update(priceListId, { ```tsx -import { PriceListStatus, PriceListType } from "@medusajs/medusa" +import { + PriceListStatus, + PriceListType, +} from "@medusajs/medusa" import { useAdminUpdatePriceList } from "medusa-react" const CreatePriceList = () => { @@ -328,7 +340,7 @@ export default CreatePriceList ```jsx -fetch(`/admin/price-lists/${priceListId}`, { +fetch(`/admin/price-lists/${priceListId}`, { method: "POST", credentials: "include", headers: { @@ -348,7 +360,7 @@ fetch(`/admin/price-lists/${priceListId}`, { ```bash -curl -L -X POST '/admin/price-lists/' \ +curl -L -X POST '/admin/price-lists/' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -361,7 +373,7 @@ curl -L -X POST '/admin/price-lists/' \ This request returns the updated price list. -For a full list of request body parameters, check out the [API reference](https://docs.medusajs.com/api/admin/#tag/Price-List/operation/PostPriceListsPriceListPriceList). +For a full list of request body parameters, check out the [API reference](/api/admin/#tag/Price-List/operation/PostPriceListsPriceListPriceList). --- @@ -369,7 +381,7 @@ For a full list of request body parameters, check out the [API reference](https: ### Add Prices -You can add prices to your price list after creating it using the [Update Prices](https://docs.medusajs.com/api/admin/#tag/Price-List/operation/PostPriceListsPriceListPricesBatch) endpoint. +You can add prices to your price list after creating it using the [Update Prices](/api/admin/#tag/Price-List/operation/PostPriceListsPriceListPricesBatch) endpoint. You can also set the `override` request body parameter to `true` to replace the existing prices in the price list. @@ -424,8 +436,10 @@ export default PriceList + + ```jsx -fetch(`/admin/price-lists/${priceListId}/prices/batch`, { +fetch(`/admin/price-lists/${priceListId}/prices/batch`, { method: "POST", credentials: "include", headers: { @@ -451,7 +465,7 @@ fetch(`/admin/price-lists/${priceListId}/prices/batch`, { ```bash -curl -L -X POST '/admin/price-lists/' \ +curl -L -X POST '/admin/price-lists/' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -470,27 +484,32 @@ curl -L -X POST '/admin/price-lists/' \ This request returns the price list with the updated prices. -For a full list of request body parameters, check out the [API reference](https://docs.medusajs.com/api/admin/#tag/Price-List/operation/PostPriceListsPriceListPricesBatch). +For a full list of request body parameters, check out the [API reference](/api/admin/#tag/Price-List/operation/PostPriceListsPriceListPricesBatch). ### Delete a Product’s Prices -You can delete all the prices of a product’s variants using the [Delete Product Prices](https://docs.medusajs.com/api/admin/#tag/Price-List/operation/DeletePriceListsPriceListProductsProductPrices) endpoint: +You can delete all the prices of a product’s variants using the [Delete Product Prices](/api/admin/#tag/Price-List/operation/DeletePriceListsPriceListProductsProductPrices) endpoint: -```jsx -medusa.admin.priceLists.deleteProductPrices(priceListId, productId) -.then(({ ids, object, deleted }) => { - console.log(ids.length) -}) +```tsx +medusa + .admin + .priceLists + .deleteProductPrices(priceListId, productId) + .then(({ ids, object, deleted }) => { + console.log(ids.length) + }) ``` ```tsx -import { useAdminDeletePriceListProductPrices } from "medusa-react" +import { + useAdminDeletePriceListProductPrices, +} from "medusa-react" const PriceList = () => { const deletePrices = useAdminDeletePriceListProductPrices( @@ -516,7 +535,7 @@ export default PriceList ```jsx fetch( - `/admin/price-lists/${priceListId}/products/${productId}/prices`, + `/admin/price-lists/${priceListId}/products/${productId}/prices`, { method: "DELETE", credentials: "include", @@ -532,7 +551,7 @@ fetch( ```bash -curl -L -X DELETE '/admin/price-lists//products//prices' \ +curl -L -X DELETE '/admin/price-lists//products//prices' \ -H 'Authorization: Bearer ' ``` @@ -543,29 +562,35 @@ This request returns the IDs of the deleted prices. ### Delete a Variant’s Prices -You can delete all the prices of a variant using the [Delete Variant Prices](https://docs.medusajs.com/api/admin/#tag/Price-List/operation/DeletePriceListsPriceListVariantsVariantPrices) endpoint: +You can delete all the prices of a variant using the [Delete Variant Prices](/api/admin/#tag/Price-List/operation/DeletePriceListsPriceListVariantsVariantPrices) endpoint: -```jsx -medusa.admin.priceLists.deleteVariantPrices(priceListId, variantId) -.then(({ ids, object, deleted }) => { - console.log(ids) -}) +```tsx +medusa + .admin + .priceLists + .deleteVariantPrices(priceListId, variantId) + .then(({ ids, object, deleted }) => { + console.log(ids) + }) ``` ```tsx -import { useAdminDeletePriceListVariantPrices } from "medusa-react" +import { + useAdminDeletePriceListVariantPrices, +} from "medusa-react" const PriceList = () => { - const deleteVariantPrices = useAdminDeletePriceListVariantPrices( - priceListId, - variantId - ) + const deleteVariantPrices = + useAdminDeletePriceListVariantPrices( + priceListId, + variantId + ) // ... const handleDeletePrices = () => { @@ -585,7 +610,7 @@ export default PriceList ```jsx fetch( - `/admin/price-lists/${priceListId}/variants/${variantId}/prices`, + `/admin/price-lists/${priceListId}/variants/${variantId}/prices`, { method: "DELETE", credentials: "include", @@ -601,7 +626,7 @@ fetch( ```bash -curl -L -X DELETE '/admin/price-lists//variants//prices' \ +curl -L -X DELETE '/admin/price-lists//variants//prices' \ -H 'Authorization: Bearer ' ``` @@ -614,7 +639,7 @@ This request returns the IDs of the deleted prices. ## Delete Price List -You can delete a price list, and subsequently all prices defined in it, using the [Delete Price List](https://docs.medusajs.com/api/admin/#tag/Price-List/operation/DeletePriceListsPriceList) endpoint: +You can delete a price list, and subsequently all prices defined in it, using the [Delete Price List](/api/admin/#tag/Price-List/operation/DeletePriceListsPriceList) endpoint: @@ -650,7 +675,7 @@ export default PriceList ```jsx -fetch(`/admin/price-lists/${priceListId}`, { +fetch(`/admin/price-lists/${priceListId}`, { method: "DELETE", credentials: "include", }) @@ -664,18 +689,11 @@ fetch(`/admin/price-lists/${priceListId}`, { ```bash -curl -L -X DELETE '/admin/price-lists/' \ +curl -L -X DELETE '/admin/price-lists/' \ -H 'Authorization: Bearer ' ``` -This request returns the ID of the deleted price list. - ---- - -## See Also - -- [Price Lists Overview](./index.md). -- [Price Selection Strategy Overview](../price-selection-strategy/index.md). +This request returns the ID of the deleted price list. \ No newline at end of file diff --git a/docs/content/advanced/backend/price-selection-strategy/override.md b/docs/content/modules/price-lists/backend/override-price-selection-strategy.md similarity index 54% rename from docs/content/advanced/backend/price-selection-strategy/override.md rename to docs/content/modules/price-lists/backend/override-price-selection-strategy.md index 2fa519151a1ab..cff333bad01ce 100644 --- a/docs/content/advanced/backend/price-selection-strategy/override.md +++ b/docs/content/modules/price-lists/backend/override-price-selection-strategy.md @@ -9,13 +9,13 @@ In this document, you’ll learn how to override Medusa’s price selection stra :::note -If you’re interested in learning what a price selection strategy is and how it works, check out [this documentation](./index.md) instead. +If you’re interested in learning what a price selection strategy is and how it works, check out [this documentation](../price-selection-strategy.md) instead. ::: ## 1. Create Class -Create a TypeScript or JavaScript file in `src/strategies` of your Medusa server project with a class that extends the `AbstractPriceSelectionStrategy` class: +Create a TypeScript or JavaScript file in `src/strategies` of your Medusa backend project with a class that extends the `AbstractPriceSelectionStrategy` class: ```ts title=src/strategies/price.ts import { @@ -27,22 +27,24 @@ import { import { EntityManager } from "typeorm" -export default class MyStrategy extends AbstractPriceSelectionStrategy { +export default class MyStrategy extends + AbstractPriceSelectionStrategy { + withTransaction( + manager: EntityManager + ): IPriceSelectionStrategy { + if (!manager) { + return this + } - withTransaction(manager: EntityManager): IPriceSelectionStrategy { - if (!manager) { - return this + return new MyStrategy() } - return new MyStrategy() - } - - async calculateVariantPrice( - variant_id: string, - context: PriceSelectionContext - ): Promise { - // TODO - } + async calculateVariantPrice( + variant_id: string, + context: PriceSelectionContext + ): Promise { + // TODO + } } ``` @@ -57,26 +59,29 @@ import { PriceSelectionResult, } from "@medusajs/medusa" -export default class MyStrategy extends AbstractPriceSelectionStrategy { - private customerService: CustomerService - - constructor({ - customerService, - }) { - super() - this.customerService = customerService - } +export default class MyStrategy extends + AbstractPriceSelectionStrategy { + private customerService: CustomerService - withTransaction(manager: EntityManager): IPriceSelectionStrategy { - if (!manager) { - return this + constructor({ + customerService, + }) { + super() + this.customerService = customerService } - return new MyStrategy({ - customerService: this.customerService, - }) - } - // ... + withTransaction( + manager: EntityManager + ): IPriceSelectionStrategy { + if (!manager) { + return this + } + + return new MyStrategy({ + customerService: this.customerService, + }) + } + // ... } ``` @@ -86,7 +91,7 @@ export default class MyStrategy extends AbstractPriceSelectionStrategy { Implement the price selection strategy you want inside the `calculateVariantPrice` method. -This method accepts the variant ID as a first parameter and the [context](./index.md#context-object) object as a second parameter. +This method accepts the variant ID as a first parameter and the [context](../price-selection-strategy.md#context-object) object as a second parameter. This method must return an object having the following fields: @@ -98,7 +103,7 @@ This method must return an object having the following fields: } ``` -You can learn more about optional properties and the meaning behind every property [here](./index.md#calculatevariantprice-method). +You can learn more about optional properties and the meaning behind every property [here](../price-selection-strategy.md#calculatevariantprice-method). --- @@ -114,16 +119,10 @@ npm run build ## Test it Out -Run your server to test it out: +Run your backend to test it out: ```bash npm2yarn npm run start ``` -Then, try out your strategy using any of the [Products](https://docs.medusajs.com/api/store/#tag/Product) or [Carts](https://docs.medusajs.com/api/store/#tag/Cart) endpoints which include retrieving product variants and line items respectively. You should then see the prices in the response based on your implemented strategy. - ---- - -## See Also - -- [Price List Selection Strategy Overview](./index.md) +Then, try out your strategy using any of the [Products](/api/store/#tag/Product) or [Carts](/api/store/#tag/Cart) endpoints which include retrieving product variants and line items respectively. You should then see the prices in the response based on your implemented strategy. \ No newline at end of file diff --git a/docs/content/modules/price-lists/overview.mdx b/docs/content/modules/price-lists/overview.mdx new file mode 100644 index 0000000000000..3c050577da442 --- /dev/null +++ b/docs/content/modules/price-lists/overview.mdx @@ -0,0 +1,145 @@ +--- +description: "Price Lists are special prices applied to products based on a set of conditions. Learn about the available features and guides." +--- + +import DocCardList from '@theme/DocCardList'; +import DocCard from '@theme/DocCard'; +import Icons from '@theme/Icon'; + +# Price Lists + +Price Lists are special prices applied to products based on a set of conditions. This overview introduces the available features related to price lists. + +:::note + +Looking for Discounts? You can find the [Discounts guide here](../discounts/overview.mdx). + +::: + +## Features + +### Price Lists Management + +Admins can manage price lists to add special prices for products based on defined conditions, such as the group of the customer viewing the product. The price list can be used for a sale or to override prices of some products. + +Developers can change the default logic behind how prices are selected to be shown to the customer. + + + +### Import Prices + +Admins can import prices into a price list from CSV files. + +Developers can import the prices from CSV files using the Admin APIs. They can also customize the import strategy. + + + +--- + +## Understand the Architecture + +Learn how price list-related entities and concepts are built, their relation to other modules, and more. + + + +--- + +## Related Modules + +Discover Price List’s relation to other modules in Medusa + + \ No newline at end of file diff --git a/docs/content/advanced/backend/price-lists/index.md b/docs/content/modules/price-lists/price-lists.md similarity index 83% rename from docs/content/advanced/backend/price-lists/index.md rename to docs/content/modules/price-lists/price-lists.md index 1e29901a1ec69..a86bda9b167c3 100644 --- a/docs/content/advanced/backend/price-lists/index.md +++ b/docs/content/modules/price-lists/price-lists.md @@ -1,5 +1,5 @@ --- -description: 'Learn what price lists are and how they work in a Medusa server. Price Lists can be used to override product prices based on different conditions.' +description: 'Learn what price lists are and how they work in a Medusa backend. Price Lists can be used to override product prices based on different conditions.' --- # Price Lists @@ -20,7 +20,7 @@ Price lists can be used for a variety of use cases including: ### Price List Entity Overview -A price list is stored in the database as a [PriceList](../../../references/entities/classes/PriceList.md) entity. Some of its important attributes are: +A price list is stored in the database as a [PriceList](../../references/entities/classes/PriceList.md) entity. Some of its important attributes are: - `type`: The price list's type. Can be either a `sale` or an `override`. - `status`: The status of the price list. Can be `active` or `draft`. If a price list is a `draft`, its prices won't be applied even if its conditions are met. @@ -45,7 +45,7 @@ You can use any of the following conditions: ## How are Price Lists Applied -When a product or a line item is retrieved or manipulated on the storefront, Medusa determines its price using a Price Selection Strategy. The price selection strategy determines the best price to apply in a given [context](../price-selection-strategy/index.md#context-object). Part of determining the price depends on the price list. +When a product or a line item is retrieved or manipulated on the storefront, Medusa determines its price using a Price Selection Strategy. The price selection strategy determines the best price to apply in a given [context](./price-selection-strategy.md#context-object). Part of determining the price depends on the price list. :::info @@ -59,9 +59,9 @@ When the strategy calculates the prices of a product variant, it retrieves both The original price depends on the selected region or currency code in the current context, where the region has higher precedence. -The calculated price is the lowest price among all retrieved prices. Retrieved prices can include the original price and the price lists that can be applied. Prices are retrieved based on the [context](../price-selection-strategy/index.md#context-object). +The calculated price is the lowest price among all retrieved prices. Retrieved prices can include the original price and the price lists that can be applied. Prices are retrieved based on the [context](./price-selection-strategy.md#context-object). -In the [Get Product](https://docs.medusajs.com/api/store/#tag/Product/operation/GetProductsProduct) and [List Product](https://docs.medusajs.com/api/store/#tag/Product/operation/GetProducts) endpoints, you must pass either the `region_id` or `currency_code` to retrieve the correct prices, as they are part of the price selection strategy context. +In the [Get Product](/api/store/#tag/Product/operation/GetProductsProduct) and [List Product](/api/store/#tag/Product/operation/GetProducts) endpoints, you must pass either the `region_id` or `currency_code` to retrieve the correct prices, as they are part of the price selection strategy context. Each variant in the response has the following properties: @@ -87,5 +87,5 @@ Since the line item belongs to a cart, there’s no need to pass the `region_id` ## See Also -- [Price Selection Strategy Overview](../price-selection-strategy/index.md). -- [Use the PriceList Admin APIs](./use-api.mdx). +- [Price Selection Strategy Overview](./price-selection-strategy.md) +- [Manage price lists using the admin APIs](./admin/manage-price-lists.mdx) diff --git a/docs/content/advanced/backend/price-selection-strategy/index.md b/docs/content/modules/price-lists/price-selection-strategy.md similarity index 91% rename from docs/content/advanced/backend/price-selection-strategy/index.md rename to docs/content/modules/price-lists/price-selection-strategy.md index d8f15eac9db59..8ef13d3ccc7ea 100644 --- a/docs/content/advanced/backend/price-selection-strategy/index.md +++ b/docs/content/modules/price-lists/price-selection-strategy.md @@ -1,5 +1,5 @@ --- -description: 'Learn what the price selection strategy is in the Medusa server. The price selection strategy retrieves the best price for a product variant for a specific context.' +description: 'Learn what the price selection strategy is in the Medusa backend. The price selection strategy retrieves the best price for a product variant for a specific context.' --- # Price Selection Strategy @@ -8,7 +8,7 @@ In this document, you’ll learn what a price selection strategy is. :::note -If you’re interested to learn how to override the price selection strategy, check out [this documentation](./override.md) instead. +If you’re interested to learn how to override the price selection strategy, check out [this documentation](./backend/override-price-selection-strategy.md) instead. ::: @@ -46,7 +46,7 @@ It returns an object with the following properties: :::info -You can learn more about price lists and how they’re used in [this documentation](../price-lists/index.md). +You can learn more about price lists and how they’re used in [this documentation](./price-lists.md). ::: @@ -66,5 +66,4 @@ The context that is passed to the `calculateVariantPrice` method is an object th ## See Also -- [Override the Price Selection Strategy](./override.md) -- [Price Lists Overview](./../price-lists/index.md) +- [Override the Price Selection Strategy](./backend/override-price-selection-strategy.md) \ No newline at end of file diff --git a/docs/content/advanced/admin/import-products.mdx b/docs/content/modules/products/admin/import-products.mdx similarity index 79% rename from docs/content/advanced/admin/import-products.mdx rename to docs/content/modules/products/admin/import-products.mdx index 02a37597e74b8..9aaace58aaff9 100644 --- a/docs/content/advanced/admin/import-products.mdx +++ b/docs/content/modules/products/admin/import-products.mdx @@ -8,11 +8,11 @@ import TabItem from '@theme/TabItem'; # How to Bulk Import Products -In this document, you’ll learn how to use the Admin APIs to bulk import products into a Medusa server. +In this document, you’ll learn how to use the Admin APIs to bulk import products into a Medusa backend. ## Overview -Using Medusa’s [Batch Job Admin APIs](https://docs.medusajs.com/api/admin/#tag/Batch-Job), you can import products into your Medusa server. This will either add new products or update existing products. +Using Medusa’s [Batch Job Admin APIs](/api/admin/#tag/Batch-Job), you can import products into your Medusa backend. This will either add new products or update existing products. --- @@ -20,40 +20,40 @@ Using Medusa’s [Batch Job Admin APIs](https://docs.medusajs.com/api/admin/#tag ### Medusa Components -It is assumed that you already have a Medusa server installed and set up. If not, you can follow the [quickstart guide](../../quickstart/quick-start.mdx) to get started. +It is assumed that you already have a Medusa backend installed and set up. If not, you can follow the [quickstart guide](../../../development/backend/install.mdx) to get started. ### Redis -Redis is required for batch jobs to work. Make sure you [install Redis](../../tutorial/0-set-up-your-development-environment.mdx#redis) and [configure it with your Medusa server](./../../usage/configurations.md#redis). +Redis is required for batch jobs to work. Make sure you [install Redis](../../../development/backend/prepare-environment.mdx#redis) and [configure it with the Medusa backend](../../../development/backend/configurations.md#redis). ### File Service Plugin -Part of the process of importing products is uploading a CSV file. This requires a file service plugin to be installed on your server. If you don’t have any installed, you can install one of the following options: +Part of the process of importing products is uploading a CSV file. This requires a file service plugin to be installed on your backend. If you don’t have any installed, you can install one of the following options: -- [MinIO](../../add-plugins/minio.md) (At least version `1.1.0`) -- [Spaces](../../add-plugins/spaces.md) +- [MinIO](../../../plugins/file-service/minio.md) (At least version `1.1.0`) +- [Spaces](../../../plugins/file-service/spaces.md) ### CSV File -You must have a CSV file that you will use to import products into your Medusa server. You can check [this CSV example file](https://medusa-doc-files.s3.amazonaws.com/product-import-1.3.8.csv) to see which format is required for your import. +You must have a CSV file that you will use to import products into your Medusa backend. You can check [this CSV example file](https://medusa-doc-files.s3.amazonaws.com/product-import-1.3.8.csv) to see which format is required for your import. :::note -If you have Sales Channels enabled on your server, you must use [this CSV example file](https://medusa-doc-files.s3.amazonaws.com/product-import-sales-channels.csv) instead. +If you have Sales Channels enabled on your backend, you must use [this CSV example file](https://medusa-doc-files.s3.amazonaws.com/product-import-sales-channels.csv) instead. ::: ### JS Client -This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client, among other methods. +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, among other methods. -If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../js-client/overview.md) installed and have [created an instance of the client](../../js-client/overview.md#configuration). +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../../js-client/overview.md) installed and have [created an instance of the client](../../../js-client/overview.md#configuration). ### Medusa React -This guide also includes code snippets to send requests to your Medusa server using Medusa React, among other methods. +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. -If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../medusa-react/overview.md#usage). +If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). ### Authenticated Admin User @@ -67,7 +67,7 @@ You can learn more about [authenticating as an admin user in the API reference]( The first step is to upload the CSV file that you want to import products. -You can do that by sending the following request to the [Upload Files](https://docs.medusajs.com/api/admin/#tag/Upload/operation/PostUploads) endpoint: +You can do that by sending the following request to the [Upload Files](/api/admin/#tag/Upload/operation/PostUploads) endpoint: @@ -106,7 +106,7 @@ export default ImportProducts const formData = new FormData() formData.append("files", file) // file is an instance of File -fetch(`/admin/uploads`, { +fetch(`/admin/uploads`, { method: "POST", credentials: "include", headers: { @@ -124,7 +124,7 @@ fetch(`/admin/uploads`, { ```bash -curl -L -X POST '/admin/uploads' \ +curl -L -X POST '/admin/uploads' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: text/csv' \ -F 'files=@""' @@ -141,7 +141,7 @@ This request returns an array of uploads. Each item in the array is an object th To start a new product import, you must create a batch job. -You can do that by sending the following request to the [Create a Batch Job](https://docs.medusajs.com/api/admin/#tag/Batch-Job/operation/PostBatchJobs) endpoint: +You can do that by sending the following request to the [Create a Batch Job](/api/admin/#tag/Batch-Job/operation/PostBatchJobs) endpoint: @@ -189,7 +189,7 @@ export default ImportProducts ```ts -fetch(`/admin/batch-jobs`, { +fetch(`/admin/batch-jobs`, { method: "POST", credentials: "include", headers: { @@ -213,7 +213,7 @@ fetch(`/admin/batch-jobs`, { ```bash -curl -L -X POST '/admin/batch-jobs' \ +curl -L -X POST '/admin/batch-jobs' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -292,7 +292,7 @@ export default ImportProducts ```ts -fetch(`/admin/batch-jobs/${batchJobId}`, { +fetch(`/admin/batch-jobs/${batchJobId}`, { credentials: "include", }) .then((response) => response.json()) @@ -305,7 +305,7 @@ fetch(`/admin/batch-jobs/${batchJobId}`, { ```bash -curl -L -X GET '/admin/batch-jobs/' \ +curl -L -X GET '/admin/batch-jobs/' \ -H 'Authorization: Bearer ' # is the ID of the batch job ``` @@ -337,7 +337,7 @@ Here’s an example of the `result` property: ## 3. Confirm Batch Job -A batch job can be confirmed only once the batch job has the status `pre_processed`. Once you confirm a batch job, the product import will start which will create or update products on your server. +A batch job can be confirmed only once the batch job has the status `pre_processed`. Once you confirm a batch job, the product import will start which will create or update products on your backend. To confirm a batch job send the following request: @@ -375,7 +375,7 @@ export default ImportProducts ```ts -fetch(`/admin/batch-jobs/${batchJobId}/confirm`, { +fetch(`/admin/batch-jobs/${batchJobId}/confirm`, { method: "POST", credentials: "include", }) @@ -389,7 +389,7 @@ fetch(`/admin/batch-jobs/${batchJobId}/confirm`, { ```bash -curl -L -X POST '/admin/batch-jobs//confirm' \ +curl -L -X POST '/admin/batch-jobs//confirm' \ -H 'Authorization: Bearer ' # is the ID of the batch job ``` @@ -411,5 +411,4 @@ After confirming the batch job, you can check the status while it is processing ## See Also -- [Batch Jobs Overview](../backend/batch-jobs/index.md) -- [Batch Jobs API Reference](https://docs.medusajs.com/api/admin/#tag/Batch-Job) +- [Batch Jobs Overview](../../../development/batch-jobs/index.mdx) diff --git a/docs/content/modules/products/overview.mdx b/docs/content/modules/products/overview.mdx new file mode 100644 index 0000000000000..72ddbbff7f5ba --- /dev/null +++ b/docs/content/modules/products/overview.mdx @@ -0,0 +1,221 @@ +--- +description: "Products are items or services that businesses sell to their customers. Learn about the available features and guides." +--- + +import DocCardList from '@theme/DocCardList'; +import Icons from '@theme/Icon'; + +# Products + +Products are items or services that businesses sell to their customers. This overview introduces the available features related to products. + +:::note + +💡 Not a developer? Check out the [Products user guide](../../user-guide/products/manage.mdx). + +::: + +## Features + +### Products Management + +Admins can manage unlimited amount of products and their variants. They can manage the product’s details including their pricing, inventory, and more. + + + +### Product Organization + +Admins can organize products into collections, tags, types, and more. + +Customers can use this organization to filter products while browsing them. + + + +### Product Import and Export + +Admins can bulk import and export products using CSV files. This facilitates moving data from other ecommerce platforms to Medusa. + + + +--- + +## Understand the Architecture + +Learn how product-related entities are build, their relation to other modules, and more. + + + +--- + +## Related Modules + +Discover Products’ relation to other modules in Medusa + + + + \ No newline at end of file diff --git a/docs/content/advanced/admin/manage-regions.mdx b/docs/content/modules/regions-and-currencies/admin/manage-regions.mdx similarity index 90% rename from docs/content/advanced/admin/manage-regions.mdx rename to docs/content/modules/regions-and-currencies/admin/manage-regions.mdx index 2e217e1594665..43d3d3844ebdb 100644 --- a/docs/content/advanced/admin/manage-regions.mdx +++ b/docs/content/modules/regions-and-currencies/admin/manage-regions.mdx @@ -36,19 +36,19 @@ You can use Medusa’s Admin APIs to achieve more functionalities as well. Check ### Medusa Components -It is assumed that you already have a Medusa server installed and set up. If not, you can follow the [quickstart guide](../../quickstart/quick-start.mdx) to get started. +It is assumed that you already have a Medusa backend installed and set up. If not, you can follow the [quickstart guide](../../../development/backend/install.mdx) to get started. ### JS Client -This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client, among other methods. +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, among other methods. -If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../js-client/overview.md) installed and have [created an instance of the client](../../js-client/overview.md#configuration). +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../../js-client/overview.md) installed and have [created an instance of the client](../../../js-client/overview.md#configuration). ### Medusa React -This guide also includes code snippets to send requests to your Medusa server using Medusa React, among other methods. +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. -If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../medusa-react/overview.md#usage). +If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). ### Authenticated Admin User @@ -60,7 +60,7 @@ You can learn more about [authenticating as an admin user in the API reference]( ## List Regions -You can retrieve regions available on your server using the [List Regions](/api/admin/#tag/Region/operation/GetRegions) endpoint: +You can retrieve regions available on your backend using the [List Regions](/api/admin/#tag/Region/operation/GetRegions) endpoint: @@ -105,7 +105,7 @@ export default Regions ```ts -fetch(`/admin/regions`, { +fetch(`/admin/regions`, { credentials: "include", }) .then((response) => response.json()) @@ -119,7 +119,7 @@ fetch(`/admin/regions`, { ```bash -curl -L -X GET '/admin/regions' \ +curl -L -X GET '/admin/regions' \ -H 'Authorization: Bearer ' ``` @@ -196,7 +196,7 @@ export default CreateRegion ```ts -fetch(`/admin/regions`, { +fetch(`/admin/regions`, { credentials: "include", method: "POST", body: JSON.stringify({ @@ -224,7 +224,7 @@ fetch(`/admin/regions`, { ```bash -curl -L -X POST '/admin/regions' \ +curl -L -X POST '/admin/regions' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -311,7 +311,7 @@ export default UpdateRegion ```ts -fetch(`/admin/regions/${regionId}`, { +fetch(`/admin/regions/${regionId}`, { credentials: "include", method: "POST", body: JSON.stringify({ @@ -331,7 +331,7 @@ fetch(`/admin/regions/${regionId}`, { ```bash -curl -L -X POST '/admin/regions/' \ +curl -L -X POST '/admin/regions/' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -413,7 +413,7 @@ export default Region ```ts -fetch(`/admin/shipping-options`, { +fetch(`/admin/shipping-options`, { credentials: "include", method: "POST", body: JSON.stringify({ @@ -436,7 +436,7 @@ fetch(`/admin/shipping-options`, { ```bash -curl -L -X POST '/admin/shipping-options' \ +curl -L -X POST '/admin/shipping-options' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -513,7 +513,7 @@ export default Region ```ts -fetch(`/admin/regions/${regionId}`, { +fetch(`/admin/regions/${regionId}`, { credentials: "include", method: "DELETE", }) @@ -527,7 +527,7 @@ fetch(`/admin/regions/${regionId}`, { ```bash -curl -L -X DELETE '/admin/regions/' \ +curl -L -X DELETE '/admin/regions/' \ -H 'Authorization: Bearer ' ``` @@ -544,5 +544,4 @@ This request requires the region ID as a path parameter. It deletes the region a ## See Also -- [Regions Overview](../backend/regions/overview.md) -- [Use Regions on the storefront](../storefront/use-regions.mdx) \ No newline at end of file +- [Use regions on the storefront](../storefront/use-regions.mdx) \ No newline at end of file diff --git a/docs/content/modules/regions-and-currencies/overview.mdx b/docs/content/modules/regions-and-currencies/overview.mdx new file mode 100644 index 0000000000000..56b1f740bb05b --- /dev/null +++ b/docs/content/modules/regions-and-currencies/overview.mdx @@ -0,0 +1,157 @@ +--- +description: "Regions and currencies are essential components in a Medusa ecommerce store. Learn about the available features and guides." +--- + +import DocCardList from '@theme/DocCardList'; +import Icons from '@theme/Icon'; + +# Regions and Currencies + +Regions are essential to your Medusa ecommerce store. They represent different countries or regions your ecommerce store serves customers in. This overview introduces the available features related to regions and currencies. + +:::note + +Not a developer? Check out the [Regions user guide](../../user-guide/regions/index.md). + +::: + +## Features + +### Multi-Region Support and Management + +In Medusa, you can create an unlimited number of regions. A region can be associated with one or more country. + +For example, you can create a region to represent the European region, and associate European countries with that region. You can also create a region that represents each of these countries on their own. + +Each region can have its own settings such as the currency, payment providers, tax providers, and more. + + + +### Multi-Currency Support + +A currency can be associated with one or more regions. When setting prices for products, you can specify a price per currency and per region. + +You have complete control over the format and value of the price of a product per currency and per region. This flexibility removes the restriction of being tied to a predefined conversion rate, which often leads to prices badly-formatted on the storefront. + + + +### Region Switcher in the Storefront + +Your customers can choose the region that matches their location. This would automatically show the correct product prices to the customer with the currency of that region. + +During checkout, customers will only see the available shipping options and payment providers in their region. Taxes are also calculated based on that region. This ensures a seamless checkout experience tailored for every region. + + + +--- + +## Understand the Architecture + +Learn how Regions and Currencies are built, their relation to other modules, and more. + + + +--- + +## Related Modules + +Discover Regions and Currencies' relation to other modules in Medusa. + + diff --git a/docs/content/advanced/backend/regions/overview.md b/docs/content/modules/regions-and-currencies/regions.md similarity index 82% rename from docs/content/advanced/backend/regions/overview.md rename to docs/content/modules/regions-and-currencies/regions.md index 798108f402242..d24c01422d40f 100644 --- a/docs/content/advanced/backend/regions/overview.md +++ b/docs/content/modules/regions-and-currencies/regions.md @@ -1,14 +1,14 @@ --- -description: 'Learn about what Regions are and how they are used in a Medusa server. Regions represent at least one country on the Medusa server.' +description: 'Learn about what Regions are and how they are used in a Medusa backend. Regions represent at least one country on the Medusa backend.' --- -# Regions Overview +# Regions Architecture -In this document, you’ll learn about Regions and their importance in your Medusa server. +In this document, you’ll learn about the Region entity and its architecture. ## Introduction -Regions represent at least one country on your Medusa server. They're used to define different business logic and configurations for a set of countries. +Regions represent at least one country on your Medusa backend. They're used to define different business logic and configurations for a set of countries. For example, you can enable one payment provider for region A, and a different payment provider for region B. Customers can then use the payment provider enabled in their region. @@ -43,23 +43,23 @@ There is no limit on how many regions you can create, and regions can share simi ## Region Entity Overview -A region is stored in the database as a [Region](../../../references/entities/classes/Region.md) entity. Some of its important attributes are: +A region is stored in the database as a [Region](../../references/entities/classes/Region.md) entity. Some of its important attributes are: - `name`: The name of the region. Customers will see this name on the storefront. - `tax_rate`: A number that indicates the tax rate. The tax rate is a percentage. - `tax_code`: An optional string that is used as the code for the default tax rate. - `gift_cards_taxable`: A boolean value that indicates whether gift cards in a region are taxable or not. -- `automatic_taxes`: A boolean value that indicates whether taxes should be calculated during checkout automatically or manually for that region. You can learn more about manually calculating taxes in [this documentation](../taxes/manual-calculation.md). +- `automatic_taxes`: A boolean value that indicates whether taxes should be calculated during checkout automatically or manually for that region. You can learn more about manually calculating taxes in [this documentation](../taxes/storefront/manual-calculation.md). --- ## Relations to Other Entities -As regions are a core part of your Medusa server, there are many relations to other entities. +As regions are a core part of your Medusa backend, there are many relations to other entities. This section covers relations to entities that make up the configurations of a region. -![Regions Relations Overview](https://res.cloudinary.com/dza7lstvk/image/upload/v1671465082/Medusa%20Docs/Diagrams/Regions_cg8hsi.jpg) +![Regions Relations Overview](https://res.cloudinary.com/dza7lstvk/image/upload/v1677487695/Medusa%20Docs/Diagrams/regions-architecture_v50h9d.jpg) ### Country @@ -92,7 +92,7 @@ The relation is available on a region by expanding the `payment_providers` relat :::info -Both shipping options and return shipping options are represented by the `ShippingOption` entity. You can learn more in the [Shipping Architecture documentation](../shipping/overview.md#shipping-option). +Both shipping options and return shipping options are represented by the `ShippingOption` entity. You can learn more in the [Shipping Architecture documentation](../carts-and-checkout/shipping.md#shipping-option). ::: @@ -117,5 +117,5 @@ The relation between the `Region` and `TaxRate` entities is available on both en ## See Also -- [Use Regions in a storefront](../../storefront/use-regions.mdx). -- [Use Regions in the admin](../../admin/manage-regions.mdx). +- [Use regions in a storefront](./storefront/use-regions.mdx) +- [Use regions in the admin](./admin/manage-regions.mdx) diff --git a/docs/content/advanced/storefront/use-regions.mdx b/docs/content/modules/regions-and-currencies/storefront/use-regions.mdx similarity index 81% rename from docs/content/advanced/storefront/use-regions.mdx rename to docs/content/modules/regions-and-currencies/storefront/use-regions.mdx index 6b16b7b2ffa64..5e9984936459f 100644 --- a/docs/content/advanced/storefront/use-regions.mdx +++ b/docs/content/modules/regions-and-currencies/storefront/use-regions.mdx @@ -28,23 +28,23 @@ You want to implement the following in your storefront: ### Medusa Components -It's assumed that you already have a Medusa server installed and set up. If not, you can follow our [quickstart guide](../../quickstart/quick-start.mdx) to get started. +It's assumed that you already have a Medusa backend installed and set up. If not, you can follow our [quickstart guide](../../../development/backend/install.mdx) to get started. -It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install either the [Next.js](../../starters/nextjs-medusa-starter.mdx) or [Gatsby](../../starters/gatsby-medusa-starter.mdx) storefronts. +It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install the [Next.js starter storefront](../../../starters/nextjs-medusa-starter.mdx). ### JS Client -This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client, among other methods. +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, among other methods. -If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../../js-client/overview.md) and have [created an instance of the client](../../js-client/overview.md#configuration). +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../../../js-client/overview.md) and have [created an instance of the client](../../../js-client/overview.md#configuration). ### Medusa React -This guide also includes code snippets to send requests to your Medusa server using Medusa React, among other methods. +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. -If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../medusa-react/overview.md#usage). +If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). -For requests that use the cart, it's also assumed you already have [used CartProvider higher in your component tree](../../medusa-react/overview.md#cartprovider). +For requests that use the cart, it's also assumed you already have [used CartProvider higher in your component tree](../../../medusa-react/overview.md#cartprovider). --- @@ -98,7 +98,7 @@ export default Regions ```ts -fetch(`/store/regions`, { +fetch(`/store/regions`, { credentials: "include", }) .then((response) => response.json()) @@ -163,7 +163,7 @@ export default Product ```ts -fetch(`/store/products?region_id=${regionId}`, { +fetch(`/store/products?region_id=${regionId}`, { credentials: "include", }) .then((response) => response.json()) @@ -190,7 +190,7 @@ You can set the cart’s region while creating it and later on by updating it. :::tip -You can learn how to implement cart functionalities in your storefront in [this documentation](../../guides/carts-in-medusa.mdx). +You can learn how to implement cart functionalities in your storefront in [this documentation](../../carts-and-checkout/storefront/implement-cart.mdx). ::: @@ -235,7 +235,7 @@ export default Cart ```ts -fetch(`/store/carts/${cartId}`, { +fetch(`/store/carts/${cartId}`, { method: "POST", credentials: "include", body: JSON.stringify({ @@ -253,11 +253,4 @@ fetch(`/store/carts/${cartId}`, { In this example, you send a request to the [Update Cart](/api/store/#tag/Cart/operation/PostCartsCart) endpoint. In the request’s body, you pass the parameter `region_id` and set its value to the selected region’s ID. It is assumed that you have the ID of the region stored in the variable `regionId`. -This request returns the full object of the updated cart. - ---- - -## See Also - -- [Implement cart functionalities in your storefront](../../guides/carts-in-medusa.mdx) -- [Implement checkout in your storefront](./how-to-implement-checkout-flow.mdx) +This request returns the full object of the updated cart. \ No newline at end of file diff --git a/docs/content/advanced/backend/sales-channels/manage-admin.mdx b/docs/content/modules/sales-channels/admin/manage.mdx similarity index 84% rename from docs/content/advanced/backend/sales-channels/manage-admin.mdx rename to docs/content/modules/sales-channels/admin/manage.mdx index 0a4df8d6efbea..37a8c960362f0 100644 --- a/docs/content/advanced/backend/sales-channels/manage-admin.mdx +++ b/docs/content/modules/sales-channels/admin/manage.mdx @@ -12,7 +12,7 @@ In this document, you’ll learn how to manage sales channels and their products :::note -If you’re looking to learn more in-depth about what Sales Channels are and how they work, check out [this documentation](./index.md) instead. +If you’re looking to learn more in-depth about what Sales Channels are and how they work, check out [this documentation](../sales-channels.md) instead. ::: @@ -28,17 +28,17 @@ This guide explains how to perform all these operations using the Admin APIs. ### Medusa Components -It's assumed that you already have a Medusa server installed and set up. If not, you can follow our [quickstart guide](../../../quickstart/quick-start.mdx) to get started. +It's assumed that you already have a Medusa backend installed and set up. If not, you can follow our [quickstart guide](../../../development/backend/install.mdx) to get started. ### JS Client -This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client, among other methods. +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, among other methods. If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../../../js-client/overview.md) and [have created an instance of the client](../../../js-client/overview.md#configuration). ### Medusa React -This guide also includes code snippets to send requests to your Medusa server using Medusa React, among other methods. +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). @@ -46,7 +46,7 @@ If you follow the Medusa React code blocks, it's assumed you already have [Medus You must be an authenticated admin user before following along with the steps in this guide. -You can learn more about [authenticating as an admin user in the API reference](https://docs.medusajs.com/api/admin/#section/Authentication). +You can learn more about [authenticating as an admin user in the API reference](/api/admin/#section/Authentication). --- @@ -94,7 +94,7 @@ export default CreateSalesChannel ```ts -fetch(`/admin/sales-channels`, { +fetch(`/admin/sales-channels`, { method: "POST", credentials: "include", headers: { @@ -115,7 +115,7 @@ fetch(`/admin/sales-channels`, { ```bash -curl -L -X POST '/admin/sales-channels' \ +curl -L -X POST '/admin/sales-channels' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -181,7 +181,7 @@ export default SalesChannels ```ts -fetch(`/admin/sales-channels`, { +fetch(`/admin/sales-channels`, { credentials: "include", }) .then((response) => response.json()) @@ -194,14 +194,14 @@ fetch(`/admin/sales-channels`, { ```bash -curl -L -X GET '/admin/sales-channels' \ +curl -L -X GET '/admin/sales-channels' \ -H 'Authorization: Bearer ' ``` -This request returns an array of all sales channels in your store. You can also pass query parameters to filter or customize the pagination of the results. Check out [the API Reference for a full list of query parameters.](https://docs.medusajs.com/api/admin/#tag/Sales-Channel/operation/GetSalesChannels) +This request returns an array of all sales channels in your store. You can also pass query parameters to filter or customize the pagination of the results. Check out [the API Reference for a full list of query parameters.](/api/admin/#tag/Sales-Channel/operation/GetSalesChannels) --- @@ -226,7 +226,10 @@ medusa.admin.salesChannels.retrieve(salesChannelId) import { useAdminSalesChannel } from "medusa-react" const SalesChannel = () => { - const { sales_channel, isLoading } = useAdminSalesChannel(salesChannelId) + const { + sales_channel, + isLoading, + } = useAdminSalesChannel(salesChannelId) return (
@@ -243,7 +246,7 @@ export default SalesChannel ```ts -fetch(`/admin/sales-channels/${salesChannelId}`, { +fetch(`/admin/sales-channels/${salesChannelId}`, { credentials: "include", }) .then((response) => response.json()) @@ -256,7 +259,7 @@ fetch(`/admin/sales-channels/${salesChannelId}`, { ```bash -curl -L -X GET '/admin/sales-channels/' \ +curl -L -X GET '/admin/sales-channels/' \ -H 'Authorization: Bearer ' ``` @@ -290,7 +293,9 @@ medusa.admin.salesChannels.update(salesChannelId, { import { useAdminUpdateSalesChannel } from "medusa-react" const UpdateSalesChannel = () => { - const updateSalesChannel = useAdminUpdateSalesChannel(salesChannelId) + const updateSalesChannel = useAdminUpdateSalesChannel( + salesChannelId + ) // ... const handleUpdate = () => { @@ -309,7 +314,7 @@ export default UpdateSalesChannel ```ts -fetch(`/admin/sales-channels/${salesChannelId}`, { +fetch(`/admin/sales-channels/${salesChannelId}`, { method: "POST", credentials: "include", headers: { @@ -329,7 +334,7 @@ fetch(`/admin/sales-channels/${salesChannelId}`, { ```bash -curl -L -X POST '/admin/sales-channels/' \ +curl -L -X POST '/admin/sales-channels/' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -344,7 +349,7 @@ In this example, you enable a sales channel by changing the value of the `is_dis This request returns the updated sales channel. -You can check out [the API Reference for a full list of body parameters](https://docs.medusajs.com/api/admin/#tag/Sales-Channel/operation/PostSalesChannelsSalesChannel) that you can pass to this request. +You can check out [the API Reference for a full list of body parameters](/api/admin/#tag/Sales-Channel/operation/PostSalesChannelsSalesChannel) that you can pass to this request. --- @@ -369,7 +374,9 @@ medusa.admin.salesChannels.delete(salesChannelId) import { useAdminDeleteSalesChannel } from "medusa-react" const SalesChannel = () => { - const deleteSalesChannel = useAdminDeleteSalesChannel(salesChannelId) + const deleteSalesChannel = useAdminDeleteSalesChannel( + salesChannelId + ) // ... const handleDelete = () => { @@ -386,7 +393,7 @@ export default SalesChannel ```ts -fetch(`/admin/sales-channels/${salesChannelId}`, { +fetch(`/admin/sales-channels/${salesChannelId}`, { method: "DELETE", credentials: "include", }) @@ -400,7 +407,7 @@ fetch(`/admin/sales-channels/${salesChannelId}`, { ```bash -curl -L -X DELETE '/admin/sales-channels/' \ +curl -L -X DELETE '/admin/sales-channels/' \ -H 'Authorization: Bearer ' ``` @@ -440,7 +447,9 @@ medusa.admin.salesChannels.addProducts(salesChannelId, { import { useAdminAddProductsToSalesChannel } from "medusa-react" const SalesChannel = () => { - const addProducts = useAdminAddProductsToSalesChannel(salesChannelId) + const addProducts = useAdminAddProductsToSalesChannel( + salesChannelId + ) // ... const handleAddProducts = (productId: string) => { @@ -462,9 +471,11 @@ export default SalesChannel + + ```ts fetch( - `/admin/sales-channels/${salesChannelId}/products/batch`, + `/admin/sales-channels/${salesChannelId}/products/batch`, { method: "POST", credentials: "include", @@ -490,7 +501,7 @@ fetch( ```bash -curl -L -X POST '/admin/sales-channels//products/batch' \ +curl -L -X POST '/admin/sales-channels//products/batch' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -532,7 +543,9 @@ medusa.admin.products.list({ ```tsx import { Product } from "@medusajs/medusa" -import { PricedProduct } from "@medusajs/medusa/dist/types/pricing" +import { + PricedProduct, +} from "@medusajs/medusa/dist/types/pricing" import { useAdminProducts } from "medusa-react" const SalesChannelProducts = () => { @@ -545,12 +558,16 @@ const SalesChannelProducts = () => { {isLoading && Loading...} {products && products.length > 0 && (
    - {products.map((product: (Product | PricedProduct)) => ( -
  • {product.title}
  • - ))} + {products.map( + (product: (Product | PricedProduct)) => ( +
  • {product.title}
  • + ) + )}
)} - {products && !products.length && No Products} + {products && !products.length && ( + No Products + )}
) } @@ -561,9 +578,11 @@ export default SalesChannelProducts
+ + ```ts fetch( - `/admin/products?sales_channel_id[0]=${salesChannelId}`, + `/admin/products?sales_channel_id[0]=${salesChannelId}`, { credentials: "include", } @@ -578,7 +597,7 @@ fetch( ```bash -curl -L -X GET '/admin/products?sales_channel_id[0]=' \ +curl -L -X GET '/admin/products?sales_channel_id[0]=' \ -H 'Authorization: Bearer ' ``` @@ -600,6 +619,8 @@ You can delete a product from a sales channel by sending a request to the Sales + + ```ts medusa.admin.salesChannels.removeProducts(salesChannelId, { product_ids: [ @@ -617,7 +638,9 @@ medusa.admin.salesChannels.removeProducts(salesChannelId, { ```tsx -import { useAdminDeleteProductsFromSalesChannel } from "medusa-react" +import { + useAdminDeleteProductsFromSalesChannel, +} from "medusa-react" const SalesChannel = () => { const deleteProducts = useAdminDeleteProductsFromSalesChannel( @@ -644,9 +667,11 @@ export default SalesChannel + + ```ts fetch( - `/admin/sales-channels/${salesChannelId}/products/batch`, + `/admin/sales-channels/${salesChannelId}/products/batch`, { method: "DELETE", credentials: "include", @@ -672,7 +697,7 @@ fetch( ```bash -curl -L -X DELETE '/admin/sales-channels//products/batch' \ +curl -L -X DELETE '/admin/sales-channels//products/batch' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ @@ -748,8 +773,10 @@ export default SalesChannelOrders + + ```ts -fetch(`/admin/orders?sales_channel_id[0]=${salesChannelId}`, { +fetch(`/admin/orders?sales_channel_id[0]=${salesChannelId}`, { credentials: "include", }) .then((response) => response.json()) @@ -762,17 +789,11 @@ fetch(`/admin/orders?sales_channel_id[0]=${salesChannelId}`, { ```bash -curl -L -X GET '/admin/orders?sales_channel_id[0]=' \ +curl -L -X GET '/admin/orders?sales_channel_id[0]=' \ -H 'Authorization: Bearer ' ``` -The request returns an array of orders that are associated with the specified sales channel. - ---- - -## See Also - -- [Sales Channels Overview](./index.md). \ No newline at end of file +The request returns an array of orders that are associated with the specified sales channel. \ No newline at end of file diff --git a/docs/content/modules/sales-channels/overview.mdx b/docs/content/modules/sales-channels/overview.mdx new file mode 100644 index 0000000000000..193ccc7811a20 --- /dev/null +++ b/docs/content/modules/sales-channels/overview.mdx @@ -0,0 +1,124 @@ +--- +description: "Sales channels are different methods a business offers its products for purchase for the customers. Learn about the available features and guides." +--- + +import DocCardList from '@theme/DocCardList'; +import DocCard from '@theme/DocCard'; +import Icons from '@theme/Icon'; + +# Sales Channels + +Sales channels are different methods a business offers its products for purchase for the customers. This overview introduces the available features related to sales channels. + +:::note + +Not a developer? Check out the [Sales Channels user guide](../../user-guide/sales-channels/index.md). + +::: + +## Features + +### Sales Channel Management + +Admins can manage sales channels, creating an unlimited number of them. They specify the products’ availability for each sales channel. + + + +### Sales Channels for Each Platform + +Developers can associate a platform with a sales channel. For example, associating a storefront with a web sales channel. Only products available in that sales channel will be shown, and all orders placed on that sales channel will be associated with it. + +Admins can filter orders by a sales channel. This would allow them to handle orders coming from each sales channel differently. + + + +--- + +## Understand the Architecture + +Learn how sales channel related entities and concepts are built, their relation to other modules, and more. + + + +--- + +## Related Modules + +Discover Sales Channel’s relation to other modules in Medusa. + + \ No newline at end of file diff --git a/docs/content/advanced/backend/sales-channels/index.md b/docs/content/modules/sales-channels/sales-channels.md similarity index 56% rename from docs/content/advanced/backend/sales-channels/index.md rename to docs/content/modules/sales-channels/sales-channels.md index f4d4f07d0fe9b..77722ea0ca00f 100644 --- a/docs/content/advanced/backend/sales-channels/index.md +++ b/docs/content/modules/sales-channels/sales-channels.md @@ -24,7 +24,7 @@ The sales channel feature can be used in a variety of use cases including: ## SalesChannel Entity Overview -A sales channel is stored in the database as a [SalesChannel](../../../references/entities/classes/SalesChannel.md) entity. Some of its important attributes are: +A sales channel is stored in the database as a [SalesChannel](../../references/entities/classes/SalesChannel.md) entity. Some of its important attributes are: - `name`: The name of the sales channel. - `is_disabled`: A boolean value indicating of the Sales Channel is disabled or not. @@ -35,15 +35,15 @@ A sales channel is stored in the database as a [SalesChannel](../../../reference ### Store -A store has a default sales channel. When you first run your Medusa server or seed your database, a default sales channel is created, if it doesn’t exist, and associated with the store. +A store has a default sales channel. When you first run your Medusa backend or seed your database, a default sales channel is created, if it doesn’t exist, and associated with the store. -The relation is implemented in the [Store](../../../references/entities/classes/Store.md) entity. You can access the default sales channel of a store by expanding the `default_sales_channel` relation and using `store.default_sales_channel`. You can also access the ID of the default sales channel using `store.default_sales_channel_id`. +The relation is implemented in the [Store](../../references/entities/classes/Store.md) entity. You can access the default sales channel of a store by expanding the `default_sales_channel` relation and using `store.default_sales_channel`. You can also access the ID of the default sales channel using `store.default_sales_channel_id`. ### Product Products can be available in more than one sales channel. You can then filter products by a sales channel using the Storefront and Admin APIs. -The relation is implemented in the [Product](../../../references/entities/classes/Product.md) entity. You can access the sales channels a product is available in by expanding the `sales_channels` relation and using `product.sales_channels`. +The relation is implemented in the [Product](../../references/entities/classes/Product.md) entity. You can access the sales channels a product is available in by expanding the `sales_channels` relation and using `product.sales_channels`. ### Cart @@ -51,17 +51,17 @@ When you create a cart, you can optionally specify the sales channel it belongs A cart can belong to only one sales channel. Only products that belong to the same sales channel as the cart can be added to it. -The relation is implemented in the [Cart](../../../references/entities/classes/Cart.md) entity. You can access the sales channel a cart is associated with by expanding the `sales_channel` relation and using `cart.sales_channel`. You can also access the ID of the sales channel using `cart.sales_channel_id`. +The relation is implemented in the [Cart](../../references/entities/classes/Cart.md) entity. You can access the sales channel a cart is associated with by expanding the `sales_channel` relation and using `cart.sales_channel`. You can also access the ID of the sales channel using `cart.sales_channel_id`. ### Order Orders can optionally be associated with a sales channel. You can filter orders by a sales channel using the Storefront and Admin APIs. -The relation is implemented in the [Order](../../../references/entities/classes/Order.md) entity. You can access the sales channel an order is associated with by expanding the `sales_channel` relation and using `order.sales_channel`. You can also access the ID of the sales channel using `order.sales_channel_id`. +The relation is implemented in the [Order](../../references/entities/classes/Order.md) entity. You can access the sales channel an order is associated with by expanding the `sales_channel` relation and using `order.sales_channel`. You can also access the ID of the sales channel using `order.sales_channel_id`. --- ## See Also -- [Manage Sales Channels using the Admin APIs](./manage-admin.mdx) -- [Sales Channel’s Admin APIs Reference](/api/admin/#tag/Sales-Channel) +- [Manage sales channels using the admin APIs](./admin/manage.mdx) +- [Use sales channels in the storefront](./storefront/use-sales-channels.mdx) \ No newline at end of file diff --git a/docs/content/advanced/storefront/use-sales-channels.mdx b/docs/content/modules/sales-channels/storefront/use-sales-channels.mdx similarity index 76% rename from docs/content/advanced/storefront/use-sales-channels.mdx rename to docs/content/modules/sales-channels/storefront/use-sales-channels.mdx index 55a37e047d993..0f1e2f45fac96 100644 --- a/docs/content/advanced/storefront/use-sales-channels.mdx +++ b/docs/content/modules/sales-channels/storefront/use-sales-channels.mdx @@ -22,8 +22,8 @@ This guide covers how to pass the sales channel ID into different requests to re An alternative approach is to use Publishable API keys. You can learn how to use them in the following documents: -- [Using publishable API keys in requests](../backend/publishable-api-keys/index.md) -- Managing publishable API keys using [admin APIs](../admin/manage-publishable-api-keys.mdx) or using [Medusa Admin](../../user-guide/settings/publishable-api-keys.mdx) +- [Using publishable API keys in requests](../../../development/publishable-api-keys/index.mdx) +- Managing publishable API keys using [admin APIs](../../../development/publishable-api-keys/admin/manage-publishable-api-keys.mdx) or using [Medusa Admin](../../../user-guide/settings/publishable-api-keys.mdx) --- @@ -31,23 +31,23 @@ An alternative approach is to use Publishable API keys. You can learn how to use ### Medusa Components -It's assumed that you already have a Medusa server installed and set up. If not, you can follow our [quickstart guide](../../quickstart/quick-start.mdx) to get started. +It's assumed that you already have a Medusa backend installed and set up. If not, you can follow our [quickstart guide](../../../development/backend/install.mdx) to get started. -It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install either the [Next.js](../../starters/nextjs-medusa-starter.mdx) or [Gatsby](../../starters/gatsby-medusa-starter.mdx) storefronts. +It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install the [Next.js starter storefront](../../../starters/nextjs-medusa-starter.mdx). ### JS Client -This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client, among other methods. +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, among other methods. -If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../../js-client/overview.md) and have [created an instance of the client](../../js-client/overview.md#configuration). +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../../../js-client/overview.md) and have [created an instance of the client](../../../js-client/overview.md#configuration). ### Medusa React -This guide also includes code snippets to send requests to your Medusa server using Medusa React, among other methods. +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. -If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../medusa-react/overview.md#usage). +If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). -For requests that use the cart, it's also assumed you already have [used CartProvider higher in your component tree](../../medusa-react/overview.md#cartprovider). +For requests that use the cart, it's also assumed you already have [used CartProvider higher in your component tree](../../../medusa-react/overview.md#cartprovider). --- @@ -104,8 +104,10 @@ export default Products + + ```ts -fetch(`/store/products?sales_channel_id[0]=${salesChannelId}`) +fetch(`/store/products?sales_channel_id[0]=${salesChannelId}`) .then((response) => response.json()) .then(({ products, limit, offset, count }) => { console.log(products.length) @@ -155,7 +157,9 @@ const Cart = () => { sales_channel_id: salesChannelId, }, { - onSuccess: ({ cart }) => localStorage.setItem("cart_id", cart.id), + onSuccess: ({ cart }) => { + localStorage.setItem("cart_id", cart.id) + }, } ) } @@ -170,7 +174,7 @@ export default Cart ```ts -fetch(`/store/carts`, { +fetch(`/store/carts`, { method: "POST", headers: { "Content-Type": "application/json", @@ -233,7 +237,7 @@ export default Cart ```ts -fetch(`/store/carts/${cartId}`, { +fetch(`/store/carts/${cartId}`, { method: "POST", headers: { "Content-Type": "application/json", @@ -249,11 +253,4 @@ fetch(`/store/carts/${cartId}`, {
-The request returns the updated cart. - ---- - -## See Also - -- [Implement the Cart functionality in a storefront](../../guides/carts-in-medusa.mdx) -- [Implement the Checkout functionality in a storefront](./how-to-implement-checkout-flow.mdx) +The request returns the updated cart. \ No newline at end of file diff --git a/docs/content/advanced/backend/taxes/inclusive-pricing.md b/docs/content/modules/taxes/inclusive-pricing.md similarity index 89% rename from docs/content/advanced/backend/taxes/inclusive-pricing.md rename to docs/content/modules/taxes/inclusive-pricing.md index 3941226103f6c..2240d4fd6e16d 100644 --- a/docs/content/advanced/backend/taxes/inclusive-pricing.md +++ b/docs/content/modules/taxes/inclusive-pricing.md @@ -11,9 +11,9 @@ In this document, you’ll learn how tax-inclusive pricing works in Medusa. Tax Inclusive Pricing is currently in beta mode and guarded by a feature flag. To use Tax-Inclusive Pricing either: 1. Enable the `MEDUSA_FF_TAX_INCLUSIVE_PRICING` environment variable; -2. Or enable the `tax_inclusive_pricing` key in the Medusa server's settings. +2. Or enable the `tax_inclusive_pricing` key in the Medusa backend's settings. -You can learn more about enabling it in the [feature flags](../feature-flags/toggle.md) documentation. +You can learn more about enabling it in the [feature flags](../../development/feature-flags/toggle.md) documentation. ::: @@ -31,7 +31,7 @@ Then, Medusa handles calculating the tax amount using the tax rate and the tax-i Tax inclusivity can be toggled for regions, currencies, price lists, and shipping options either during creation or while editing. This is represented by the boolean attribute `includes_tax` available in the entities `Region`, `Currency`, `PriceList`, and `ShippingOption`. By default, this attribute is set to `false`. -If you want to enable or disable this attribute for any of these entities, you can use the create or update endpoints related to these entities as shown in the [Admin API reference](https://docs.medusajs.com/api/admin/). +If you want to enable or disable this attribute for any of these entities, you can use the create or update endpoints related to these entities as shown in the [Admin API reference](/api/admin/). The value set for these entities can affect whether line items and shipping methods are tax inclusive or not. @@ -54,7 +54,7 @@ The `LineItem` entity also has the `includes_tax` attribute. The value of this f :::info -When a shipping option is selected, a shipping method is created based on that shipping option. You can learn more about this in the [Shipping Architecture documentation](../shipping/overview.md). +When a shipping option is selected, a shipping method is created based on that shipping option. You can learn more about this in the [Shipping Architecture documentation](../carts-and-checkout/shipping.md). ::: @@ -82,13 +82,13 @@ This section covers at which point tax amounts are calculated for different enti :::note -If you have disabled the automatic calculation of taxes in a region, you must [manually calculate the taxes of the line items and the cart](manual-calculation.md). Otherwise, taxes will not be calculated or retrieved during checkout for each entity mentioned here. +If you have disabled the automatic calculation of taxes in a region, you must [manually calculate the taxes of the line items and the cart](./storefront/manual-calculation.md). Otherwise, taxes will not be calculated or retrieved during checkout for each entity mentioned here. ::: ### Products -Taxes are calculated for each product variant either when a [single product is retrieved](https://docs.medusajs.com/api/store/#tag/Product/operation/GetProductsProduct) or a [list of products is retrieved](https://docs.medusajs.com/api/store/#tag/Product/operation/GetProducts). +Taxes are calculated for each product variant either when a [single product is retrieved](/api/store/#tag/Product/operation/GetProductsProduct) or a [list of products is retrieved](/api/store/#tag/Product/operation/GetProducts). Among the pricing fields retrieved for each variant, the following fields are relevant to taxes: @@ -148,7 +148,7 @@ Here is an example of these fields when tax inclusivity is enabled for both the ### Line Item -The taxes of line items are calculated and retrieved whenever the [cart is retrieved or updated](https://docs.medusajs.com/api/store/#tag/Cart). +The taxes of line items are calculated and retrieved whenever the [cart is retrieved or updated](/api/store/#tag/Cart). Each line item returned in any of the cart’s requests has total fields related to the price of the line item and its taxes. Among those fields, the following are relevant to tax-inclusive pricing: @@ -172,7 +172,7 @@ Finally, `original_tax_total` undergoes the same `tax_total` calculation, howeve ### Shipping Options -Taxes for Shipping Options are calculated and retrieved when the [list of shipping options is retrieved](https://docs.medusajs.com/api/store/#tag/Shipping-Option). +Taxes for Shipping Options are calculated and retrieved when the [list of shipping options is retrieved](/api/store/#tag/Shipping-Option). Among the returned fields for each shipping option, the following are relevant to each of their pricing and taxes: @@ -186,9 +186,9 @@ If tax inclusivity is enabled for the shipping option, `amount` and `price_incl_ Carts and Orders have the same total fields relevant for taxes. -A cart’s totals, including its taxes, are calculated and retrieved whenever the cart is [updated or retrieved](https://docs.medusajs.com/api/store/#tag/Cart). +A cart’s totals, including its taxes, are calculated and retrieved whenever the cart is [updated or retrieved](/api/store/#tag/Cart). -An order’s totals, including its taxes, are calculated and retrieved whenever the order is retrieved both on the [storefront](https://docs.medusajs.com/api/store/#tag/Order) and on the [admin](https://docs.medusajs.com/api/admin/#tag/Order). +An order’s totals, including its taxes, are calculated and retrieved whenever the order is retrieved both on the [storefront](/api/store/#tag/Order) and on the [admin](/api/admin/#tag/Order). The relevant fields are: @@ -203,5 +203,4 @@ During the calculation of the totals of different components of the cart or orde ## See Also -- [Calculate taxes manually](manual-calculation.md) -- [Storefront API reference](/api/store) +- [Calculate taxes manually](./storefront/manual-calculation.md) diff --git a/docs/content/modules/taxes/overview.mdx b/docs/content/modules/taxes/overview.mdx new file mode 100644 index 0000000000000..d011e5ed71292 --- /dev/null +++ b/docs/content/modules/taxes/overview.mdx @@ -0,0 +1,197 @@ +--- +description: "Taxes are additional costs or fees imposed by a government for goods or services. Learn about the available features and guides." +--- + +import DocCardList from '@theme/DocCardList'; +import Icons from '@theme/Icon'; + +# Taxes + +Taxes are additional costs or fees imposed by a government for goods or services. This overview introduces the available features related to taxes. + +:::note + +Not a developer? Check out the [Taxes user guide](../../user-guide/taxes/index.md). + +::: + +## Features + +### Tax Providers + +Developers can integrate third-party tax providers or implement custom tax-provider logic. + +Admins can specify the tax provider for a specific region. + +Customers can view calculated taxes during their checkout process. + + + + + +### Tax Rates and Overrides + +Admins can create additional tax rates aside from the default tax rate. They can also specify overrides of tax rates for specific products, product types, or shipping options. + +Customers can review order edit requests and authorize additional payments if necessary. + + + +### Tax-Inclusive Pricing + +Admins can enable tax-inclusive pricing for a region or currency. This would automatically calculate the taxes applied on a product for that region or currency. + + + +--- + +## Understand the Architecture + +Learn how tax-related entities and concepts are built, their relation to other modules, and more. + + + +--- + +## Related Modules + +Discover Taxes' relation to other modules in Medusa. + + diff --git a/docs/content/advanced/backend/taxes/manual-calculation.md b/docs/content/modules/taxes/storefront/manual-calculation.md similarity index 73% rename from docs/content/advanced/backend/taxes/manual-calculation.md rename to docs/content/modules/taxes/storefront/manual-calculation.md index 0e8b246a46bd6..461fd04c8c138 100644 --- a/docs/content/advanced/backend/taxes/manual-calculation.md +++ b/docs/content/modules/taxes/storefront/manual-calculation.md @@ -1,5 +1,5 @@ --- -description: 'Learn how to manually calculate taxes during checkout in the Medusa server. There are different methods including using endpoints or services.' +description: 'Learn how to manually calculate taxes during checkout in the Medusa backend. There are different methods including using endpoints or services.' addHowToData: true --- @@ -21,7 +21,7 @@ This section explores different ways you can calculate taxes based on your purpo ### Use Calculate Cart Taxes Endpoint -The [Calculate Cart Taxes](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCartsCartTaxes) endpoint forces the calculation of taxes for a cart during checkout. This bypasses the option set in admin to not calculate taxes automatically, which results in sending requests to the tax provider. +The [Calculate Cart Taxes](/api/store/#tag/Cart/operation/PostCartsCartTaxes) endpoint forces the calculation of taxes for a cart during checkout. This bypasses the option set in admin to not calculate taxes automatically, which results in sending requests to the tax provider. This calculates and retrieves the taxes on the cart and each of the line items in that cart. @@ -33,13 +33,19 @@ You can, however, force calculating the taxes of the cart by passing in the thir For example: -```jsx -cartService.retrieve("cart_01G8Z...", { }, { force_taxes: true }) +```ts +cartService.retrieve( + "cart_01G8Z...", + { }, + { + force_taxes: true, + } +) ``` :::tip -You can learn how to [retrieve and use services](../services/create-service.md#using-your-custom-service) in this documentation. +You can learn how to [retrieve and use services](../../../development/services/create-service.md#using-your-custom-service) in this documentation. ::: @@ -83,13 +89,6 @@ const itemTotals = await totalsService :::tip -You can learn how to [retrieve and use services](../services/create-service.md#using-your-custom-service) in this documentation. - -::: - ---- - -## See Also +You can learn how to [retrieve and use services](../../../development/services/create-service.md#using-your-custom-service) in this documentation. -- [Tax-Inclusive Pricing Overview](inclusive-pricing.md) -- [CartsService](../../../references/services/classes/CartService.md) and [TotalsService](../../../references/services/classes/TotalsService.md) +::: \ No newline at end of file diff --git a/docs/content/modules/users/overview.mdx b/docs/content/modules/users/overview.mdx new file mode 100644 index 0000000000000..f9686500403cd --- /dev/null +++ b/docs/content/modules/users/overview.mdx @@ -0,0 +1,134 @@ +--- +description: "Users are admins that can manage the ecommerce store’s data and operations. Learn about the available features and guides." +--- + +import DocCardList from '@theme/DocCardList'; +import Icons from '@theme/Icon'; + +# Users + +Users are admins that can manage the ecommerce store’s data and operations. This overview introduces the available features related to users. + +:::note + +Not a developer? Check out the [Users user guide](../../user-guide/users/index.md). + +::: + +## Features + +### Team Management + +There can be more than one admin in the team managing the ecommerce store. Admins can manage other users in that team. + +Admins can also manage their profile details. + + + +### User Invites + +Admins can invite users to join their team. Invites can be resent, accepted, or removed. + +- Admin: Manage Invites +- User Guide: Manage Invites +- Backend: Send Invite + + + +--- + +## Understand the Architecture + +Learn how user-related entities and concepts are built, their relation to other modules, and more. + + \ No newline at end of file diff --git a/docs/content/plugins/analytics/index.mdx b/docs/content/plugins/analytics/index.mdx new file mode 100644 index 0000000000000..4ff3018c3fe59 --- /dev/null +++ b/docs/content/plugins/analytics/index.mdx @@ -0,0 +1,5 @@ +import DocCardList from '@theme/DocCardList'; + +# Analytics Plugins + + \ No newline at end of file diff --git a/docs/content/add-plugins/segment.md b/docs/content/plugins/analytics/segment.md similarity index 77% rename from docs/content/add-plugins/segment.md rename to docs/content/plugins/analytics/segment.md index 028e297483d0e..045b48f83910a 100644 --- a/docs/content/add-plugins/segment.md +++ b/docs/content/plugins/analytics/segment.md @@ -1,5 +1,5 @@ --- -description: 'Learn how to integrate Segment with the Medusa server. Learn how to add custom tracking with Segment and Medusa.' +description: 'Learn how to integrate Segment with the Medusa backend. Learn how to add custom tracking with Segment and Medusa.' addHowToData: true --- @@ -37,7 +37,7 @@ By default, the Segment plugin tracks the following events: :::tip -Check out the [Event Reference](../advanced/backend/subscribers/events-list.md) to learn about all available events in Medusa. +Check out the [Event Reference](../../development/events/events-list.md) to learn about all available events in Medusa. ::: @@ -45,11 +45,11 @@ Check out the [Event Reference](../advanced/backend/subscribers/events-list.md) ## Prerequisites -### Medusa Server +### Medusa Backend -It is assumed you already have a Medusa server installed. If not, please follow the [Quickstart guide](../quickstart/quick-start.mdx) to get started in minutes. +It is assumed you already have a Medusa backend installed. If not, please follow the [Quickstart guide](../../development/backend/install.mdx) to get started in minutes. -In addition, make sure to have Redis installed and configured with your Medusa server. If not, follow [this documentation](../tutorial/0-set-up-your-development-environment.mdx#redis) to install Redis and then [configure it](../usage/configurations.md#redis). +In addition, make sure to have Redis installed and configured with your Medusa backend. If not, follow [this documentation](../../development/backend/prepare-environment.mdx#redis) to install Redis and then [configure it](../../development/backend/configurations.md#redis). ### Segment Account @@ -63,9 +63,9 @@ On your Segment dashboard, choose Catalog from the sidebar under Connections. ![Under Connections in the sidebar choose Catalog](https://res.cloudinary.com/dza7lstvk/image/upload/v1668000661/Medusa%20Docs/Segment/rAeJkP3_ybyutz.png) -Then, in the catalog list find the Server category and choose Node.js from the list. +Then, in the catalog list find the Backend category and choose Node.js from the list. -![Choose Node.js under the Server category](https://res.cloudinary.com/dza7lstvk/image/upload/v1668000672/Medusa%20Docs/Segment/6RxQbW6_wjphte.png) +![Choose Node.js under the Backend category](https://res.cloudinary.com/dza7lstvk/image/upload/v1668000672/Medusa%20Docs/Segment/6RxQbW6_wjphte.png) This opens a new side menu. In the side menu, click on Add Source. @@ -75,7 +75,7 @@ This opens a new page to create a Node.js source. Enter the name of the source t ![Enter a name under the Name field then click on the Add Source button](https://res.cloudinary.com/dza7lstvk/image/upload/v1668000693/Medusa%20Docs/Segment/u2hzkB5_t59yhj.png) -On the new source dashboard, you should find a Write Key. You’ll use this key in the next section after you install the Segment plugin on your Medusa server. +On the new source dashboard, you should find a Write Key. You’ll use this key in the next section after you install the Segment plugin on your Medusa backend. ![The Write Key is available on the new source's page](https://res.cloudinary.com/dza7lstvk/image/upload/v1668000708/Medusa%20Docs/Segment/OTJVsz7_v95qla.png) @@ -97,7 +97,7 @@ The process of integrating each destination is different, so you must follow the ## Install the Segment Plugin -In the directory of your Medusa server, run the following command to install the Segment plugin: +In the directory of your Medusa backend, run the following command to install the Segment plugin: ```bash npm2yarn npm install medusa-plugin-segment @@ -129,13 +129,13 @@ const plugins = [ ## Test the Plugin -Run your server with the following command: +Run your backend with the following command: ```bash npm2yarn npm run start ``` -Then, try triggering one of the [mentioned events earlier in this document](#events-that-the-segment-plugin-tracks). For example, you can place an order either using the [REST APIs](https://docs.medusajs.com/api/store) or using the [Next.js](../starters/nextjs-medusa-starter.mdx) or [Gatsby](../starters/gatsby-medusa-starter.mdx) storefronts. +Then, try triggering one of the [mentioned events earlier in this document](#events-that-the-segment-plugin-tracks). For example, you can place an order either using the [REST APIs](https://docs.medusajs.com/api/store) or using the [Next.js starter storefront](../../starters/nextjs-medusa-starter.mdx). After you place an order, on the Segment source that you created, click on the Debugger tab. You should see at least one event triggered for each order you place. If you click on the event, you can see the order details are passed to the event. @@ -162,7 +162,10 @@ class CustomerSubscriber { constructor({ segmentService, eventBusService }) { this.segmentService = segmentService - eventBusService.subscribe("customer.created", this.handleCustomer) + eventBusService.subscribe( + "customer.created", + this.handleCustomer + ) } handleCustomer = async (data) => { @@ -184,7 +187,7 @@ You resolve the `SegmentService` using dependency injection. Then, when the `cus :::info -Services can be resolved and used in Subscribers, endpoints, and other Services. Learn [how to resolve services in the Services documentation](../advanced/backend/services/create-service.md#using-your-custom-service). +Services can be resolved and used in Subscribers, endpoints, and other Services. Learn [how to resolve services in the Services documentation](../../development/services/create-service.md#using-your-custom-service). ::: @@ -192,11 +195,11 @@ Services can be resolved and used in Subscribers, endpoints, and other Services. If you want to pass additional data to Segment, pass them under the `properties` object key. -The `SegmentServer` also provides the method `identify` to tie a user to their actions or specific traits. +The `SegmentService` also provides the method `identify` to tie a user to their actions or specific traits. ### Test Custom Tracking -After adding the above subscriber, run your server again if it isn’t running and create a customer using the REST APIs or one of the Medusa storefronts. If you check the Debugger in your Segment source, you should see a new event “Customer Created” tracked. If you click on it, you’ll see the data you passed to the `track` method. +After adding the above subscriber, run your backend again if it isn’t running and create a customer using the REST APIs or one of the Medusa storefronts. If you check the Debugger in your Segment source, you should see a new event “Customer Created” tracked. If you click on it, you’ll see the data you passed to the `track` method. ![The customer created event is recoreded on the Segment source](https://res.cloudinary.com/dza7lstvk/image/upload/v1668000759/Medusa%20Docs/Segment/4LD41xE_qungdw.png) @@ -204,7 +207,7 @@ After adding the above subscriber, run your server again if it isn’t running a ## See Also -- [Services Overview](../advanced/backend/services/create-service.md) -- [Subscribers Overview](../advanced/backend/subscribers/create-subscriber.md) -- [Events Reference](../advanced/backend/subscribers/events-list.md) -- [Deploy the Medusa server](../deployments/server/index.mdx) +- [Services Overview](../../development/services/create-service.md) +- [Subscribers Overview](../../development/events/create-subscriber.md) +- [Events Reference](../../development/events/events-list.md) +- [Deploy the Medusa backend](../../deployments/server/index.mdx) diff --git a/docs/content/add-plugins/contentful/customize-contentful.md b/docs/content/plugins/cms/contentful/customize-contentful.md similarity index 88% rename from docs/content/add-plugins/contentful/customize-contentful.md rename to docs/content/plugins/cms/contentful/customize-contentful.md index 15967dda4f14d..f392e1cd0f7c2 100644 --- a/docs/content/add-plugins/contentful/customize-contentful.md +++ b/docs/content/plugins/cms/contentful/customize-contentful.md @@ -11,7 +11,7 @@ In this document, you’ll learn how to customize the Contentful integration wit Part of what makes the integration between Medusa and Contentful powerful is that it’s completely customizable. -On the server, you can create Contentful migrations that allow you to add or edit Content Types in Contentful. Although this can be done through Contentful’s interface, this solution allows you to create a reusable codebase for your store that is independent of a specific Contentful Space. +On the backend, you can create Contentful migrations that allow you to add or edit Content Types in Contentful. Although this can be done through Contentful’s interface, this solution allows you to create a reusable codebase for your store that is independent of a specific Contentful Space. On your storefront, you can add any necessary components that can render the Content Types you create. @@ -21,13 +21,13 @@ As an example to explain this process, in this documentation, you’ll create a ## Prerequisites -It’s assumed you already have set up a Medusa server integrated with Contentful and have a Gatsby storefront integrated with Contentful. If not, [please follow this documentation first](index.md). +It’s assumed you already have set up a Medusa backend integrated with Contentful and have a Gatsby storefront integrated with Contentful. If not, [please follow this documentation first](index.md). --- ## Create a Contentful Migration -The Contentful migrations are located in the `contentful-migrations` directory in the Medusa Contentful server starter. So, if you want to create your own Contentful migrations, you can create them under that directory. +The Contentful migrations are located in the `contentful-migrations` directory in the Medusa Contentful backend starter. So, if you want to create your own Contentful migrations, you can create them under that directory. Here’s an example of a migration created in a new file `contentful-migrations/rich-text.js`: @@ -56,8 +56,14 @@ const migration = async () => { .name("Rich Text") .displayField("title") - richText.createField("title").name("Title (Internal)").type("Symbol") - richText.createField("body").name("Body").type("RichText") + richText + .createField("title") + .name("Title (Internal)") + .type("Symbol") + richText + .createField("body") + .name("Body") + .type("RichText") // edit Page content model const page = migration.editContentType("page") @@ -67,7 +73,9 @@ const migration = async () => { linkType: "Entry", validations: [ { - linkContentType: ["hero", "tileSection", "richText"], + linkContentType: [ + "hero", "tileSection", "richText", + ], }, ], }) @@ -177,7 +185,9 @@ To render the Rich Text content you created in the previous example, create the ```jsx title=src/components/rich-text/rich-text.js import React from "react" -import { renderRichText } from "gatsby-source-contentful/rich-text" +import { + renderRichText, +} from "gatsby-source-contentful/rich-text" const RichText = ({ data }) => { return ( @@ -247,7 +257,7 @@ export const query = graphql` ### Test Rich Text in Page Content -To test this out, run your Medusa server by running this command in its directory: +To test this out, run your Medusa backend by running this command in its directory: ```bash npm run start @@ -335,5 +345,5 @@ Restart the Gatsby storefront then open a product that you added Rich Text conte ## See Also -- Deploy your Medusa server to [Heroku](../../deployments/server/deploying-on-heroku.mdx), [Qovery](../../deployments/server/deploying-on-qovery.md), or [DigitalOcean](../../deployments/server/deploying-on-digital-ocean.md). -- [How to deploy your Gatsby storefront to Netlify](../../deployments/storefront/deploying-gatsby-on-netlify.md). +- Deploy your Medusa backend to [Heroku](../../../deployments/server/deploying-on-heroku.mdx), [Qovery](../../../deployments/server/deploying-on-qovery.md), or [DigitalOcean](../../../deployments/server/deploying-on-digital-ocean.md). +- [How to deploy your Gatsby storefront to Netlify](../../../deployments/storefront/deploying-gatsby-on-netlify.md). diff --git a/docs/content/add-plugins/contentful/index.md b/docs/content/plugins/cms/contentful/index.md similarity index 80% rename from docs/content/add-plugins/contentful/index.md rename to docs/content/plugins/cms/contentful/index.md index 295ffa8560ee4..8be4da78fb998 100644 --- a/docs/content/add-plugins/contentful/index.md +++ b/docs/content/plugins/cms/contentful/index.md @@ -1,11 +1,11 @@ --- -description: 'Learn how to integrate Contentful with the Medusa server and a Gatsby storefront. Contentful is a headless CMS server that provides rich CMS functionalities.' +description: 'Learn how to integrate Contentful with the Medusa backend and a Gatsby storefront. Contentful is a headless CMS backend that provides rich CMS functionalities.' addHowToData: true --- # Contentful -In this document, you’ll learn how to integrate a Medusa server with Contentful to add rich Content Management System (CMS) functionalities +In this document, you’ll learn how to integrate a Medusa backend with Contentful to add rich Content Management System (CMS) functionalities ## Overview @@ -23,25 +23,25 @@ By integrating Contentful to Medusa, you can benefit from powerful features in y ### Required Tools -- PostgreSQL with an empty database created. You can follow [this documentation to learn how to install it for your operating system](../../tutorial/0-set-up-your-development-environment.mdx#postgres). -- Redis. You can follow [this documentation to learn how to install it for your operating system](../../tutorial/0-set-up-your-development-environment.mdx#redis). -- Git’s CLI tool. You can follow [this documentation to learn how to install it for your operating system](../../tutorial/0-set-up-your-development-environment.mdx#git). +- PostgreSQL with an empty database created. You can follow [this documentation to learn how to install it for your operating system](../../../development/backend/prepare-environment.mdx#postgres). +- Redis. You can follow [this documentation to learn how to install it for your operating system](../../../development/backend/prepare-environment.mdx#redis). +- Git’s CLI tool. You can follow [this documentation to learn how to install it for your operating system](../../../development/backend/prepare-environment.mdx#git). - Gatsby’s CLI tool. You can follow [this documentation to install it](https://www.gatsbyjs.com/docs/reference/gatsby-cli/#how-to-use-gatsby-cli). -- Medusa’s CLI tool. You can follow [this documentation to install it](../../cli/reference.md#how-to-install-cli-tool). +- Medusa’s CLI tool. You can follow [this documentation to install it](../../../cli/reference.md#how-to-install-cli-tool). --- -## Install Medusa Server Using Contentful Starter +## Install Medusa Backend Using Contentful Starter -Instead of using the default Medusa Server starter, you must use the [Contentful starter](https://github.com/medusajs/medusa-starter-contentful) to install a server that is ready to be used with Contentful. This server contains all the necessary files to make the integration work. +Instead of using the default Medusa backend starter, you must use the [Contentful starter](https://github.com/medusajs/medusa-starter-contentful) to install a backend that is ready to be used with Contentful. This backend contains all the necessary files to make the integration work. -In your terminal, run the following command to install the server: +In your terminal, run the following command to install the backend: ```bash medusa new medusa-contentful https://github.com/medusajs/medusa-starter-contentful ``` -This installs a new Medusa server in the directory `medusa-contentful`. +This installs a new Medusa backend in the directory `medusa-contentful`. ### Add Contentful Environment Variables @@ -168,7 +168,7 @@ After this command finishes running, in your Contentful Space dashboard click on ### (Optional) Seed Medusa Database -This step seeds your Medusa database with demo data to easily add products as well as other data to your Medusa server. +This step seeds your Medusa database with demo data to easily add products as well as other data to your Medusa backend. Run the following command to seed the Medusa database: @@ -176,9 +176,9 @@ Run the following command to seed the Medusa database: npm run seed ``` -### Start the Server +### Start the Backend -To start the server run the following command: +To start the backend run the following command: ```bash npm run start @@ -188,13 +188,13 @@ If you seeded the database with demo data, you should see that events related to ![Seed the database](https://res.cloudinary.com/dza7lstvk/image/upload/v1668001440/Medusa%20Docs/Contentful/ci4accp_okaro3.png) -The Contentful integration ensures a two-way sync between the Medusa server and Contentful. So, when new products are added to Medusa, these products will be added to your Contentful Space as well. +The Contentful integration ensures a two-way sync between the Medusa backend and Contentful. So, when new products are added to Medusa, these products will be added to your Contentful Space as well. --- ## (Optional) Add Products with the Medusa Admin -Using the Medusa admin, you can add products to your Medusa server. This will trigger product events that subsequently add these products to Contentful. +Using the Medusa admin, you can add products to your Medusa backend. This will trigger product events that subsequently add these products to Contentful. --- @@ -202,7 +202,7 @@ Using the Medusa admin, you can add products to your Medusa server. This will tr ### Publish Products -Products added through the integration with the Medusa server are by default saved as drafts. To show them on the storefront, you must set them as published. +Products added through the integration with the Medusa backend are by default saved as drafts. To show them on the storefront, you must set them as published. To do that, open your Contentful Space Dashboard and click on Content in the Navigation bar. Then, change Any to Product in the select field next to the search bar. This shows only the content of the type Product, rather than all content. @@ -234,9 +234,9 @@ Once you’re done adding products, click on Publish changes in the right sideba ## Setup Gatsby Storefront -In this section, you’ll set up the Gatsby storefront of your Medusa server. +In this section, you’ll set up the Gatsby storefront of your Medusa backend. -In your terminal in a different directory of the Medusa server, run the following command: +In your terminal in a different directory of the Medusa backend, run the following command: ```bash gatsby new medusa-contentful-storefront https://github.com/medusajs/medusa-contentful-storefront @@ -259,7 +259,7 @@ CONTENTFUL_SPACE_ID= CONTENTFUL_ACCESS_TOKEN= ``` -The value of `CONTENTFUL_SPACE_ID` is the same value you [retrieved while setting up the Medusa server](#value-of-contentful_space_id). +The value of `CONTENTFUL_SPACE_ID` is the same value you [retrieved while setting up the Medusa backend](#value-of-contentful_space_id). To retrieve the value of `CONTENTFUL_ACCESS_TOKEN`, on your Contentful Space dashboard click on Settings then API keys. Then, choose the API key you created in the previous section. @@ -269,7 +269,7 @@ You should find the field "Content Delivery API - access token”. Copy its valu ### Start Storefront -Make sure the Medusa server is still running. Then, start the storefront: +Make sure the Medusa backend is still running. Then, start the storefront: ```bash npm run start @@ -295,9 +295,9 @@ If you make changes to the data while your Gatsby storefront is running, the cha ## What’s Next -Learn [How to customize your Contentful server and storefront](./customize-contentful.md). +Learn [How to customize your Contentful backend and storefront](./customize-contentful.md). ## See Also -- How to deploy your Medusa server to [Heroku](../../deployments/server/deploying-on-heroku.mdx), [Qovery](../../deployments/server/deploying-on-qovery.md), or [DigitalOcean](../../deployments/server/deploying-on-digital-ocean.md). -- [How to deploy your Gatsby storefront to Netlify](../../deployments/storefront/deploying-gatsby-on-netlify.md). +- How to deploy your Medusa backend to [Heroku](../../../deployments/server/deploying-on-heroku.mdx), [Qovery](../../../deployments/server/deploying-on-qovery.md), or [DigitalOcean](../../../deployments/server/deploying-on-digital-ocean.md). +- [How to deploy your Gatsby storefront to Netlify](../../../deployments/storefront/deploying-gatsby-on-netlify.md). diff --git a/docs/content/plugins/cms/index.mdx b/docs/content/plugins/cms/index.mdx new file mode 100644 index 0000000000000..b12b03b35a96d --- /dev/null +++ b/docs/content/plugins/cms/index.mdx @@ -0,0 +1,5 @@ +import DocCardList from '@theme/DocCardList'; + +# CMS Plugins + + \ No newline at end of file diff --git a/docs/content/add-plugins/strapi.md b/docs/content/plugins/cms/strapi.md similarity index 59% rename from docs/content/add-plugins/strapi.md rename to docs/content/plugins/cms/strapi.md index 9c9b2f57b4ed3..80d731df631c2 100644 --- a/docs/content/add-plugins/strapi.md +++ b/docs/content/plugins/cms/strapi.md @@ -1,5 +1,5 @@ --- -description: 'Learn how to integrate Strapi with the Medusa server. Learn how to install the plugin and test two-way sync between the ecommerce and CMS services.' +description: 'Learn how to integrate Strapi with the Medusa backend. Learn how to install the plugin and test two-way sync between the ecommerce and CMS services.' addHowToData: true --- @@ -25,11 +25,11 @@ By integrating Strapi to Medusa, you can benefit from powerful features in your ### Medusa CLI -[Medusa’s CLI tool](../cli/reference.md#how-to-install-cli-tool) is required to set up a new Medusa server. +[Medusa’s CLI tool](../../cli/reference.md#how-to-install-cli-tool) is required to set up a new Medusa backend. ### Redis -Redis is required for the Strapi plugin to work as expected on your Medusa server. If you don’t have it installed, you can learn [how to install it in this documentation](../tutorial/0-set-up-your-development-environment.mdx#redis). +Redis is required for the Strapi plugin to work as expected on your Medusa backend. If you don’t have it installed, you can learn [how to install it in this documentation](../../development/backend/prepare-environment.mdx#redis). --- @@ -43,7 +43,7 @@ npx create-strapi-app strapi-medusa --template shahednasser/strapi-medusa-templa This creates the Strapi project in the directory `strapi-medusa`. -Once the installation is finished, the Strapi development server will run on `localhost:1337`. A new page will also open in your default browser to create a new admin user and log in. +Once the installation is finished, the Strapi development backend will run on `localhost:1337`. A new page will also open in your default browser to create a new admin user and log in. ![Create User Form in Strapi](https://res.cloudinary.com/dza7lstvk/image/upload/v1668001083/Medusa%20Docs/Strapi/9pFE1Ij_h2dicv.png) @@ -65,7 +65,7 @@ Enter the user’s username, email, and password. Once you’re done, click on t ## Modify Permissions -By default, created users have the “Authenticated” role. Before you start using the Strapi plugin on your Medusa server, you must modify this role’s permissions to allow making changes to Medusa’s models in Strapi. +By default, created users have the “Authenticated” role. Before you start using the Strapi plugin on your Medusa backend, you must modify this role’s permissions to allow making changes to Medusa’s models in Strapi. On your Strapi dashboard, go to Settings → Roles → Authenticated. Then, under the Permissions section, expand the accordion of each content model type and check the Select All checkbox. @@ -75,25 +75,25 @@ Once you’re done, click the Save button at the top right. --- -## Create Medusa Server +## Create Medusa Backend :::note -You can use the Strapi plugin on an existing Medusa server, however, existing data (such as existing products) will not be imported. Only newer data will be imported. +You can use the Strapi plugin on an existing Medusa backend, however, existing data (such as existing products) will not be imported. Only newer data will be imported. ::: -To create your Medusa server, run the following command: +To create your Medusa backend, run the following command: ```bash -medusa new medusa-server --seed +medusa new medusa-backend --seed ``` The `--seed` flag creates an SQLite database and seeds it with some demo data. -### Configure your Server +### Configure your Backend -Once the command is done executing, change to the newly created `medusa-server` directory. Then, in `medusa-config.js`, change the exported object at the end of the file to enable Redis: +Once the command is done executing, change to the newly created `medusa-backend` directory. Then, in `medusa-config.js`, change the exported object at the end of the file to enable Redis: ```jsx title=medusa-config.js module.exports = { @@ -105,11 +105,11 @@ module.exports = { } ``` -This uses the default Redis configurations. If you want to learn more about configuring Redis, [check out this documentation](../usage/configurations.md#redis). +This uses the default Redis configurations. If you want to learn more about configuring Redis, [check out this documentation](../../development/backend/configurations.md#redis). :::tip -It is also recommended to use PostgreSQL for an optimal experience, however, it is not required. Learn how to [install](../tutorial/0-set-up-your-development-environment.mdx#postgres) and [configure](../usage/configurations.md#postgresql-configurations) it on your Medusa server. +It is also recommended to use PostgreSQL for an optimal experience, however, it is not required. Learn how to [install](../../development/backend/prepare-environment.mdx#postgres) and [configure](../../development/backend/configurations.md#postgresql-configurations) it on your Medusa backend. ::: @@ -117,7 +117,7 @@ It is also recommended to use PostgreSQL for an optimal experience, however, it ## Install the Strapi Plugin -In the directory of your Medusa server, run the following command to install the Strapi plugin: +In the directory of your Medusa backend, run the following command to install the Strapi plugin: ```bash npm2yarn npm install medusa-plugin-strapi @@ -137,9 +137,9 @@ Where: - `` is either the email address or username of the user you created in the previous step. - `` is the password of the user you created in the previous step. -- `` is the protocol of your Strapi server. If you’re using a local Strapi server, set this to `http`. The default value is `https`. -- `` is the URL of your Strapi server. By default, the URL is `localhost`. -- `` is the port the Strapi server runs on. By default, the port is `1337`. +- `` is the protocol of your Strapi backend. If you’re using a local Strapi backend, set this to `http`. The default value is `https`. +- `` is the URL of your Strapi backend. By default, the URL is `localhost`. +- `` is the port the Strapi backend runs on. By default, the port is `1337`. Finally, open `medusa-config.js` and add the following new item to the `plugins` array: @@ -161,39 +161,39 @@ const plugins = [ --- -## Run Medusa Server +## Run Medusa Backend -Make sure the Strapi server is still running. If not, you can run the following command to run the Strapi server in the directory of the Strapi project: +Make sure the Strapi backend is still running. If not, you can run the following command to run the Strapi backend in the directory of the Strapi project: ```bash npm2yarn npm run develop ``` -Then, in the directory of your Medusa server, run the following command to start the Medusa server: +Then, in the directory of your Medusa backend, run the following command to start the Medusa backend: ```bash npm2yarn npm run start ``` -Once you start your Medusa server, if you ran the `--seed` command when you created your Medusa server, you’ll see that `product.created` events have been triggered along with similar events. This will update Strapi with the products you seeded. +Once you start your Medusa backend, if you ran the `--seed` command when you created your Medusa backend, you’ll see that `product.created` events have been triggered along with similar events. This will update Strapi with the products you seeded. --- ## Test Two-Way Sync -This plugin ensures a two-way sync between the Medusa server and the Strapi server. So, if you update data on Strapi, it will be reflected on your Medusa server, and vice-versa. +This plugin ensures a two-way sync between the Medusa backend and the Strapi backend. So, if you update data on Strapi, it will be reflected on your Medusa backend, and vice-versa. ### Update Products on Strapi -Try updating any products on Strapi by going to Content Manager → Products and choosing a product from the list. Then, make changes to the product and click Save. If you view the products on your server now, either using the [REST APIs](https://docs.medusajs.com/api/admin/#tag/Product/operation/GetProducts) or using [the Medusa Admin](../user-guide/products/index.mdx), you’ll see that the product has been updated. +Try updating any products on Strapi by going to Content Manager → Products and choosing a product from the list. Then, make changes to the product and click Save. If you view the products on your backend now, either using the [REST APIs](/api/admin/#tag/Product/operation/GetProducts) or using [the Medusa Admin](../../user-guide/products/index.mdx), you’ll see that the product has been updated. ### Update Products on Medusa -If you try to update products on Medusa either using the [REST APIs](https://docs.medusajs.com/api/admin/#tag/Product/operation/PostProductsProduct) or using [the Medusa Admin](../user-guide/products/manage.mdx), you’ll see that the product is also updated on Strapi. +If you try to update products on Medusa either using the [REST APIs](/api/admin/#tag/Product/operation/PostProductsProduct) or using [the Medusa Admin](../../user-guide/products/manage.mdx), you’ll see that the product is also updated on Strapi. --- ## See Also -- [Deploy the Medusa server](../deployments/server/index.mdx) -- [Create your own plugin](../advanced/backend/plugins/create.md) +- [Deploy the Medusa backend](../../deployments/server/index.mdx) +- [Create your own plugin](../../development/plugins/create.md) diff --git a/docs/content/plugins/file-service/index.mdx b/docs/content/plugins/file-service/index.mdx new file mode 100644 index 0000000000000..8f512e2f3f982 --- /dev/null +++ b/docs/content/plugins/file-service/index.mdx @@ -0,0 +1,5 @@ +import DocCardList from '@theme/DocCardList'; + +# File Service Plugins + + \ No newline at end of file diff --git a/docs/content/add-plugins/minio.md b/docs/content/plugins/file-service/minio.md similarity index 73% rename from docs/content/add-plugins/minio.md rename to docs/content/plugins/file-service/minio.md index ed5ac5fd9ba4d..a89eb074eda45 100644 --- a/docs/content/add-plugins/minio.md +++ b/docs/content/plugins/file-service/minio.md @@ -1,11 +1,11 @@ --- -description: 'Learn how to integrate MinIO with the Medusa server. Learn how to install the MinIO plugin on the Medusa server and configure it.' +description: 'Learn how to integrate MinIO with the Medusa backend. Learn how to install the MinIO plugin on the Medusa backend and configure it.' addHowToData: true --- # MinIO -This document will guide you through installing the MinIO file service plugin on your Medusa server. +This document will guide you through installing the MinIO file service plugin on your Medusa backend. ## Overview @@ -17,7 +17,7 @@ Medusa provides three different options to handle your file storage. This docume ## Prerequisites -A Medusa server is required to be set up before following along with this document. You can follow the [quickstart guide](../quickstart/quick-start.mdx) to get started in minutes. +A Medusa backend is required to be set up before following along with this document. You can follow the [quickstart guide](../../development/backend/install.mdx) to get started in minutes. --- @@ -25,21 +25,21 @@ A Medusa server is required to be set up before following along with this docume You can follow [MinIO’s guide to install it](https://docs.min.io/minio/baremetal/quickstart/quickstart.html) on your machine based on your operating system. -After installing it, make sure MinIO is always running when your Medusa server is running. It’s recommended that you set up an alias to quickly start the MinIO server as instructed at the end of the installation guides in MinIO. +After installing it, make sure MinIO is always running when your Medusa backend is running. It’s recommended that you set up an alias to quickly start the MinIO backend as instructed at the end of the installation guides in MinIO. ### Change MinIO port -In MinIO’s documentation, port `9000` is used for the address of the MinIO server. However, this collides with the port for the Medusa server. You must change the port for MinIO to another one (for example, port `9001`). +In MinIO’s documentation, port `9000` is used for the address of the MinIO backend. However, this collides with the port for the Medusa backend. You must change the port for MinIO to another one (for example, port `9001`). After setting up and installing MinIO on your system/sub-system, you can run the following command to change MinIO port to `9001` (or any other available port) instead of `9000` to avoid the port clash: ```bash -minio server ~/minio --console-address :9090 --address :9001 +minio backend ~/minio --console-address :9090 --address :9001 ``` ### Create a MinIO bucket -After installing MinIO and logging into the Console, you can create a bucket that will store the files of your Medusa server by following these steps: +After installing MinIO and logging into the Console, you can create a bucket that will store the files of your Medusa backend by following these steps: 1. Click on the “Create Bucket” button 2. For the Bucket Name field, enter a name for the bucket. By MinIO’s requirement, the name can only consist of lower case characters, numbers, dots (`.`), and hyphens (`-`). @@ -73,7 +73,7 @@ You will not be able to access the Secret Key after closing the pop-up. So, make ## Plugin Installation -In the directory of your Medusa server, run the following command to install the MinIO plugin: +In the directory of your Medusa backend, run the following command to install the MinIO plugin: ```bash npm2yarn npm install medusa-file-minio @@ -88,7 +88,7 @@ MINIO_ACCESS_KEY= MINIO_SECRET_KEY= ``` -Where `` is the URL of your MinIO server, `` is the name of the bucket you created earlier, and `` and `` are the keys you generated in the previous section. +Where `` is the URL of your MinIO backend, `` is the name of the bucket you created earlier, and `` and `` are the keys you generated in the previous section. Finally, configure your `medusa-config.js` to include the plugin with the required options: @@ -117,7 +117,7 @@ If you have multiple storage plugins configured, the last plugin declared in the ## Test it Out -Run your Medusa server alongside the [Medusa Admin](../admin/quickstart.mdx) to try out your new file service. Upon editing or creating products, you can now upload thumbnails and images, that are stored in a MinIO server. +Run your Medusa backend alongside the [Medusa Admin](../../admin/quickstart.mdx) to try out your new file service. Upon editing or creating products, you can now upload thumbnails and images, that are stored in a MinIO backend. ![Image Uploaded on Admin](https://res.cloudinary.com/dza7lstvk/image/upload/v1668000429/Medusa%20Docs/MinIO/alabX2i_dzg2mh.png) @@ -139,7 +139,7 @@ To create a private bucket, follow along the [steps mentioned earlier](#create-a ### Add Private Bucket Environment Variable -Add the following environment variable on your Medusa server: +Add the following environment variable on your Medusa backend: ```bash MINIO_PRIVATE_BUCKET=exports @@ -182,8 +182,10 @@ const plugins = [ resolve: `medusa-file-minio`, options: { // ... - private_access_key_id: process.env.MINIO_PRIVATE_ACCESS_KEY, - private_secret_access_key: process.env.MINIO_PRIVATE_SECRET_KEY, + private_access_key_id: + process.env.MINIO_PRIVATE_ACCESS_KEY, + private_secret_access_key: + process.env.MINIO_PRIVATE_SECRET_KEY, }, }, ] @@ -193,7 +195,7 @@ const plugins = [ ## Next.js Storefront Configuration -If you’re using a [Next.js](../starters/nextjs-medusa-starter.mdx) storefront, you need to add an additional configuration that adds the MinIO domain name into the configured images domain names. This is because all URLs of product images will be from the MinIO server. +If you’re using a [Next.js](../../starters/nextjs-medusa-starter.mdx) storefront, you need to add an additional configuration that adds the MinIO domain name into the configured images domain names. This is because all URLs of product images will be from the MinIO backend. If this configuration is not added, you’ll receive the error ["next/image Un-configured Host”](https://nextjs.org/docs/messages/next-image-unconfigured-host). @@ -215,10 +217,10 @@ module.exports = withStoreConfig({ }) ``` -Where `127.0.0.1` is the domain of your local MinIO server. +Where `127.0.0.1` is the domain of your local MinIO backend. --- ## See Also -- Check out [more plugins](https://github.com/medusajs/medusa/tree/master/packages) you can add to your store. +- Check out [more plugins](../overview.mdx) you can add to your store. diff --git a/docs/content/add-plugins/s3.md b/docs/content/plugins/file-service/s3.md similarity index 86% rename from docs/content/add-plugins/s3.md rename to docs/content/plugins/file-service/s3.md index 0350ad172ec12..4b7d50d283cd0 100644 --- a/docs/content/add-plugins/s3.md +++ b/docs/content/plugins/file-service/s3.md @@ -1,25 +1,25 @@ --- -description: 'Learn how to integrate the S3 plugin with the Medusa server. Learn how to configure and use S3 to store images related to the Medusa server.' +description: 'Learn how to integrate the S3 plugin with the Medusa backend. Learn how to configure and use S3 to store images related to the Medusa backend.' addHowToData: true --- # S3 -In this document, you’ll learn how to install the [S3 plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-file-s3) on your Medusa server and use it for storage. +In this document, you’ll learn how to install the [S3 plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-file-s3) on your Medusa backend and use it for storage. ## Overview To manage images in Medusa, you need a file service plugin responsible for hosting the images. Without a file service plugin, you will face issues while working with Medusa, such as when uploading images for products. -Medusa provides three different options to handle your file storage. This document focuses on using [S3](https://aws.amazon.com/s3/) to store your Medusa server’s images. +Medusa provides three different options to handle your file storage. This document focuses on using [S3](https://aws.amazon.com/s3/) to store images and files uploaded to the Medusa backend. --- ## Prerequisites -### Medusa Server +### Medusa Backend -A Medusa server is required to be set up before following along with this document. You can follow the [quickstart guide](../quickstart/quick-start.mdx) to get started in minutes. +A Medusa backend is required to be set up before following along with this document. You can follow the [quickstart guide](../../development/backend/install.mdx) to get started in minutes. ### Required Accounts @@ -95,7 +95,7 @@ You must obtain access keys for your user as you’ll use them to integrate the ## Install the S3 Plugin -In the directory of your Medusa server, run the following command to install the S3 Plugin: +In the directory of your Medusa backend, run the following command to install the S3 Plugin: ```bash npm2yarn npm install medusa-file-s3 @@ -174,13 +174,13 @@ If you have multiple storage plugins configured, the last plugin declared in the ## Test the S3 Plugin -Run your Medusa server with the following command: +Run your Medusa backend with the following command: ```bash npm2yarn npm run start ``` -Then, you can either test the plugin using the [REST APIs](https://docs.medusajs.com/api/store) or using the [Medusa Admin](../admin/quickstart.mdx). +Then, you can either test the plugin using the [REST APIs](/api/store) or using the [Medusa Admin](../../admin/quickstart.mdx). On the Medusa Admin, create a new product and, in the Images section, upload an image then click Save. If the integration was successful, the product image will be uploaded successfully. @@ -194,7 +194,7 @@ You can also check that the image was uploaded on the S3 bucket’s page. ## Next.js Storefront Configuration -If you’re using a [Next.js](../starters/nextjs-medusa-starter.mdx) storefront, you need to add an additional configuration that adds the S3 bucket domain name into the configured images’ domain names. This is because all URLs of product images will be from the S3 bucket. +If you’re using a [Next.js](../../starters/nextjs-medusa-starter.mdx) storefront, you need to add an additional configuration that adds the S3 bucket domain name into the configured images’ domain names. This is because all URLs of product images will be from the S3 bucket. If this configuration is not added, you’ll receive the error ["next/image Un-configured Host”](https://nextjs.org/docs/messages/next-image-unconfigured-host). @@ -222,6 +222,6 @@ Where `` is the name of the S3 bucket you’re using. ## See Also -- Check out [more plugins](https://github.com/medusajs/medusa/tree/master/packages) you can add to your store. -- [Deploy the Medusa server](../deployments/server/index.mdx) -- Install the [Next.js](../starters/nextjs-medusa-starter.mdx) or [Gatsby](../starters/gatsby-medusa-starter.mdx) storefronts. +- Check out [more plugins](../overview.mdx) you can add to your store. +- [Deploy the Medusa backend](../../deployments/server/index.mdx) +- Install the [Next.js](../../starters/nextjs-medusa-starter.mdx) starter storefront. diff --git a/docs/content/add-plugins/spaces.md b/docs/content/plugins/file-service/spaces.md similarity index 81% rename from docs/content/add-plugins/spaces.md rename to docs/content/plugins/file-service/spaces.md index 9c33be443b225..923265c1499c5 100644 --- a/docs/content/add-plugins/spaces.md +++ b/docs/content/plugins/file-service/spaces.md @@ -1,11 +1,11 @@ --- -description: 'Learn how to integrate Spaces with the Medusa server. Learn how to install and configure the Spaces plugin on the Medusa server.' +description: 'Learn how to integrate Spaces with the Medusa backend. Learn how to install and configure the Spaces plugin on the Medusa backend.' addHowToData: true --- # Spaces -In this document, you’ll learn how to install the [Spaces plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-file-spaces) on your Medusa server and use it for storage. +In this document, you’ll learn how to install the [Spaces plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-file-spaces) on your Medusa backend and use it for storage.
)} {submittedFeedback && ( -
- {submitMessage} +
+
+ {submitMessage} + {possibleSolutions.length > 0 && ( +
+ If you faced a problem, here are some possible solutions from GitHub: + + Explore more issues in + the GitHub repository + + +
+ )} +
)} diff --git a/www/docs/src/components/Intro/Intro.js b/www/docs/src/components/Intro/Intro.js deleted file mode 100644 index 76fb929b6bd46..0000000000000 --- a/www/docs/src/components/Intro/Intro.js +++ /dev/null @@ -1,50 +0,0 @@ -import React from "react" -import Link from "@docusaurus/Link" -import CodeBlock from "@theme/CodeBlock" -import styles from "./intro.module.css" - -const Intro = ({ title, desc }) => { - return ( -
-

Documentation

-

{title}

-

Quickstart

-

{desc}

- - {`yarn global add @medusajs/medusa-cli -medusa new my-awesome-store`} - -
- - Quickstart Guide → - -
-
- - Set up your own local environment → - -
-
- - Create your very own Medusa server → - -
-
- - Explore plugins → - -
-
- ) -} - -export default Intro diff --git a/www/docs/src/components/Intro/index.js b/www/docs/src/components/Intro/index.js deleted file mode 100644 index c76753ed6dece..0000000000000 --- a/www/docs/src/components/Intro/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default as Intro } from "./Intro" diff --git a/www/docs/src/components/Intro/intro.module.css b/www/docs/src/components/Intro/intro.module.css deleted file mode 100644 index c7cad4e5dee76..0000000000000 --- a/www/docs/src/components/Intro/intro.module.css +++ /dev/null @@ -1,17 +0,0 @@ -.title { - font-size: 24px; -} - -.description { - font-size: 20px; -} - -.docsLink { - font-size: 20px; -} - -@media screen and (max-width: 966px) { - .docsLink { - font-size: 16px; - } -} diff --git a/www/docs/src/components/LargeCard/index.css b/www/docs/src/components/LargeCard/index.css new file mode 100644 index 0000000000000..ad789d764c231 --- /dev/null +++ b/www/docs/src/components/LargeCard/index.css @@ -0,0 +1,130 @@ +.large-card { + background-color: var(--large-card-bg); + border: 1px solid var(--large-card-border-color); + border-radius: var(--ifm-global-radius); + padding: calc(var(--ifm-base-margin-vertical) * 3) var(--ifm-base-spacing) calc(var(--ifm-base-margin-vertical) / 2); + display: flex; + flex-direction: column; + justify-content: space-between; + margin-bottom: var(--ifm-base-margin-vertical); + position: relative; +} + +.large-card:not(.large-card-soon):hover, +.large-card:not(.large-card-soon):hover:before { + background-color: var(--large-card-bg-hover); +} + +.large-card-soon:hover a { + pointer-events: none; +} + +.large-card-soon:hover .large-card-title, +.large-card-soon:hover .large-card-content { + color: var(--medusa-text-disabled); +} + +.large-card:before, +.large-card:after { + content: ''; + position: absolute; + left: 0; + width: 100%; + border-radius: var(--ifm-global-radius); +} + +.large-card:before { + z-index: 1; + height: calc(var(--ifm-base-margin-vertical) * 4); + top: 0; + background-image: var(--large-card-bg-image); + background-color: var(--large-card-bg); +} + +.large-card:nth-child(3n+1):before { + background-position-x: 2%; + background-position-y: 52%; +} + +.large-card:nth-child(3n + 2):before { + background-position-x: 19%; + background-position-y: 16%; +} + +.large-card:nth-child(3n + 3):before { + background-position-x: 17%; + background-position-y: 50%; +} + +.large-card:after { + z-index: 2; + left: 0; + top: calc(var(--ifm-base-margin-vertical) * 2); + height: calc(var(--ifm-base-margin-vertical) * 2); + background: var(--large-card-fade-effect); +} + +.large-card:not(.large-card-soon):hover:after { + background: var(--large-card-fade-effect-hover); +} + +.large-card > * { + z-index: 3; +} + +.large-card-bordered-icon-wrapper { + --bordered-padding: var(--large-card-icon-wrapper-padding); + + margin-bottom: calc(var(--ifm-base-margin-vertical) / 2); +} + +.large-card-icon-wrapper { + --bordered-inside-padding: var(--large-card-icon-inside-padding); +} + +.large-card-icon { + width: var(--large-card-icon-size); + height: var(--large-card-icon-size); +} + +.large-card-heading { + margin-bottom: calc(var(--ifm-base-margin-vertical) / 4); +} + +.large-card-title { + color: var(--ifm-color-primary); + font-size: var(--medusa-label-regular-plus-size); + line-height: var(--medusa-label-regular-plus-line-height); + font-weight: var(--medusa-label-regular-plus-font-weight); +} + +.large-card-content { + font-size: var(--medusa-body-regular-size); + line-height: var(--medusa-body-regular-line-height); + font-weight: var(--medusa-body-regular-font-weight); +} + +.large-card-title, +.large-card-content { + transition: all var(--ifm-transition-fast) ease; +} + +.large-card-content ul { + padding-left: var(--ifm-base-spacing); +} + +.large-card-link { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 4; + border-radius: var(--ifm-global-radius); +} + +.large-card-badge { + position: absolute; + top: calc(var(--ifm-base-margin-vertical) / 2); + right: var(--ifm-base-spacing); +} \ No newline at end of file diff --git a/www/docs/src/components/LargeCard/index.js b/www/docs/src/components/LargeCard/index.js new file mode 100644 index 0000000000000..2e71fe7b0ecc0 --- /dev/null +++ b/www/docs/src/components/LargeCard/index.js @@ -0,0 +1,43 @@ +import React from "react" +import './index.css' +import BorderedIcon from "../BorderedIcon" +import clsx from 'clsx'; +import Badge from "../Badge"; + +export default function LargeCard ({ + Icon, + image, + title, + action: { + href + }, + isSoon = false, + children +}) { + return ( +
+
+ {isSoon && Guide coming soon} + {(Icon || image) && ( + + )} +
+ {title} +
+
+ {children} +
+
+ +
+ ) +} \ No newline at end of file diff --git a/www/docs/src/components/LargeCardList/index.js b/www/docs/src/components/LargeCardList/index.js new file mode 100644 index 0000000000000..fdff136255c34 --- /dev/null +++ b/www/docs/src/components/LargeCardList/index.js @@ -0,0 +1,10 @@ +import React from "react" +import clsx from 'clsx' + +export default function LargeCardList ({ colSize, className, children }) { + return ( +
+ {children} +
+ ) +} \ No newline at end of file diff --git a/www/docs/src/components/QueryNote/index.js b/www/docs/src/components/QueryNote/index.js new file mode 100644 index 0000000000000..9f160fec5d475 --- /dev/null +++ b/www/docs/src/components/QueryNote/index.js @@ -0,0 +1,25 @@ +import React from "react"; +import { useQueryStringValue } from "@docusaurus/theme-common/internal" +import Admonition from "@theme/Admonition" + +export default function QueryNote ({ + query: { + key, + value = '' + }, + //admonition props + admonition, + children +}) { + const queryValue = useQueryStringValue(key) + + return ( + <> + {queryValue === value && ( + + {children} + + )} + + ) +} \ No newline at end of file diff --git a/www/docs/src/css/_card.css b/www/docs/src/css/_card.css index 994c441fec387..c9ecb552ad0db 100644 --- a/www/docs/src/css/_card.css +++ b/www/docs/src/css/_card.css @@ -1,10 +1,17 @@ -.markdown p + .cards-grid { - margin-top: var(--ifm-base-margin-vertical); +.card { + background-color: var(--ifm-card-bg); + border: 1px solid var(--ifm-card-bg-hover) !important; + border-radius: var(--ifm-global-radius); +} + +img.card-icon { + width: var(--ifm-card-icon-size); + height: var(--ifm-card-icon-size); } .cards-grid { display: grid; - column-gap: 16px; + column-gap: var(--ifm-base-spacing); grid-auto-rows: 1fr; } @@ -12,33 +19,52 @@ grid-template-columns: repeat(2, 1fr); } -.box-link, -.box-link:hover { - color: #0a3149; -} +.card-highlighted { + --bordered-inside-padding: 6px; -.card-highlight { position: relative; - overflow: visible; + margin-bottom: calc(var(--ifm-base-margin-vertical) * 2); +} + +.card-highlighted { + background-color: var(--ifm-card-bg); } -.card-highlight:after { +/* html[data-theme="dark"] .card-highlighted::before, +html[data-theme="dark"] .card-highlighted::after { content: ''; - width: 100%; - height: 2px; - position:absolute; - bottom: -1px; + position: absolute; + top: 0; left: 0; - background: var(--ifm-primary-gradient); + width: 100%; + height: 100%; + background-repeat: no-repeat; + background-size: cover; +} */ + +/* html[data-theme="dark"] .card-highlighted::before { + z-index: -2; + background-color: var(--ifm-card-bg); + background-image: url('/img/stardust.png'); + transition: all var(--ifm-transition-fast) ease; +} + +html[data-theme="dark"] .card-highlighted::after { + z-index: -1; + background-image: url('/img/light-beam.png'); +} */ + +.card-highlighted:hover { + background-color: var(--ifm-card-bg-hover); } -html:not([data-theme=dark]) .card { - border: 1px solid #cbcbcb; - border-radius: 8px; +.card + p { + margin-top: var(--ifm-base-margin-vertical); } -html[data-theme="dark"] .card { - border: 1px solid var(--ifm-color-primary); +.card-wrapper:hover > [class*=cardSoon] [class*=cardTitle], +.card-wrapper:hover > [class*=cardSoon] [class*=cardDescription] { + color: var(--medusa-text-disabled); } @media screen and (min-width: 992px) { @@ -53,6 +79,27 @@ html[data-theme="dark"] .card { } } +@media screen and (min-width: 768px) { + .card-highlighted [class*=cardDescription] { + width: 50%; + } + + .card-highlighted::before { + content: ''; + position: absolute; + top: 0; + right: 0; + width: 50%; + height: 100%; + } + + .card-highlighted::before { + background-repeat: no-repeat; + background-size: cover; + background-image: var(--ifm-card-highlighted-bg-image); + } +} + @media screen and (max-width: 767px) { .cards-grid.grid-4 { grid-template-columns: repeat(1, 1fr); diff --git a/www/docs/src/css/_code.css b/www/docs/src/css/_code.css index 5e36501b68e54..0a2ba61295b19 100644 --- a/www/docs/src/css/_code.css +++ b/www/docs/src/css/_code.css @@ -1,10 +1,16 @@ -/* [data-theme="dark"] pre code { - background-color: var(--ifm-code-background); -} */ - code { border: 1px solid var(--ifm-code-border-color); color: var(--ifm-code-color); + line-height: var(--medusa-body-regular-line-height); +} + +[data-tooltip-content]:hover code { + background-color: var(--ifm-code-background-hover); +} + +[data-tooltip-content] > span:active > code, +[data-tooltip-content] > span:focus > code { + background-color: var(--ifm-code-background-pressed); } .inline-code-copy { @@ -15,17 +21,6 @@ code { color: var(--ifm-code-color) } -.docusaurus-highlight-code-line { - background-color: rgba(0, 0, 0, 0.1); - display: block; - margin: 0 calc(-1 * var(--ifm-pre-padding)); - padding: 0 var(--ifm-pre-padding); -} - -html[data-theme="dark"] .docusaurus-highlight-code-line { - background-color: rgba(0, 0, 0, 0.3); -} - .prism-code { background-color: none; word-break: break-word; @@ -38,23 +33,16 @@ html[data-theme="dark"] .docusaurus-highlight-code-line { outline: none !important; } -[data-theme="dark"] .theme-doc-markdown a.card:hover { - color: rgba(255, 255, 255, 0.8); - text-decoration: none; -} - .code-tabs { position: relative; } .code-header { - padding: 12px 16px; -} - -.code-header { - background-color: #161616; + padding: 12px var(--ifm-base-spacing); + background-color: var(--medusa-code-tabs-bg); display: flex; justify-content: space-between; + align-items: center; border-radius: var(--ifm-code-border-radius) var(--ifm-code-border-radius) 0px 0px; } @@ -64,9 +52,10 @@ html[data-theme="dark"] .docusaurus-highlight-code-line { .code-tabs .tabs__item { color: var(--ifm-code-tabs-color); - font-weight: 600; - font-size: 13px; - padding: 0 12px; + font-size: var(--medusa-label-small-plus-size); + font-weight: var(--medusa-label-small-plus-font-weight); + line-height: var(--medusa-label-small-plus-line-height); + padding: 4px 12px; border: 1px solid transparent; white-space: nowrap; border-radius: 99999px; @@ -77,16 +66,23 @@ html[data-theme="dark"] .docusaurus-highlight-code-line { } .code-title { - font-size: 13px; - line-height: var(--ifm-line-height-base); + font-size: var(--medusa-label-small-plus-size); + font-weight: var(--medusa-label-small-plus-font-weight); + line-height: var(--medusa-label-small-plus-line-height); color: var(--ifm-code-title-color); } +.code-tabs-ul-wrapper { + position: relative; + overflow: auto; +} + +.code-tabs-ul-wrapper .tabs__item { + z-index: 2; +} + .code-tabs .tabs__item--active { - border-color: #393939; - background-color: var(--ifm-code-tabs-active-bg); color: var(--ifm-code-tabs-active-color); - font-size: 13px; } .theme-code-block:not(.no-header-block), @@ -103,19 +99,22 @@ html[data-theme="dark"] .docusaurus-highlight-code-line { } .code-action { + --ifm-icon-color: var(--medusa-code-block-action); + background-color: transparent; border: none; padding: 4px; cursor: pointer; - border-radius: 8px; + border-radius: var(--ifm-global-radius); } -.code-action:hover { - background-color: var(--ifm-code-action-hover-bg); +.code-action:hover, +.tabs__item:hover { + background-color: var(--ifm-code-action-hover-bg) !important; } .code-action:not(:first-child) { - margin-left: 8px; + margin-left: calc(var(--ifm-base-spacing) / 2); } a.code-action { @@ -124,39 +123,19 @@ a.code-action { align-items: center; } -.code-action img { - height: 20px; - width: 20px; -} - -/* .theme-code-block:not(.no-header-block) [class*=buttonGroup] { - display: none; -} */ - -.theme-code-block [class*=buttonGroup] button { - opacity: 1 !important; - border: none; -} - .copy-action { cursor: pointer; } -[data-theme="dark"] .code-header, -[data-theme="dark"] .theme-code-block { - border: 1px solid var(--ifm-code-border-color); +.code-header, +.theme-code-block { + border: 1px solid var(--ifm-code-block-border-color); } -[data-theme="dark"] .code-header { +.code-header { border-bottom: none; } -html:not([data-theme="dark"]) .theme-code-block:not(.no-header-block) { - --ifm-code-border-color: #393939; - - border-top: 1px solid var(--ifm-code-border-color); -} - .theme-code-block.no-header-block code:not(.thin-code), .theme-code-block:not(.no-header-block) code { padding: var(--ifm-pre-padding); @@ -164,6 +143,12 @@ html:not([data-theme="dark"]) .theme-code-block:not(.no-header-block) { .theme-code-block.no-header-block .thin-code { padding: calc(var(--ifm-pre-padding) / 2); + padding-left: var(--ifm-pre-padding); +} + +[class*=codeLineNumber] { + color: var(--ifm-code-line-number-color); + padding-left: 0 !important; } @media screen and (min-width: 568px) { @@ -172,13 +157,14 @@ html:not([data-theme="dark"]) .theme-code-block:not(.no-header-block) { } .prism-code:after { + border-radius: var(--ifm-global-radius); content: ''; position: absolute; right: 0; top: 0; width: calc(10% + 24px); height: 100%; - background: linear-gradient(90deg, #17171700, #262626 24px); + background: linear-gradient(90deg, var(--ifm-pre-background-transparent), var(--ifm-pre-background) 24px); } .prism-code:not(:hover)::-webkit-scrollbar-thumb, @@ -190,9 +176,23 @@ html:not([data-theme="dark"]) .theme-code-block:not(.no-header-block) { .prism-code:hover::-webkit-scrollbar-track { opacity: 1; } + + .code-tabs-ul-wrapper .code-tab-selector { + position: absolute; + border: 1px solid var(--medusa-code-tab-border); + background-color: var(--ifm-code-tabs-active-bg); + transition: all var(--ifm-transition-fast) ease; + top: 0; + z-index: 1; + border-radius: 99999px; + } } @media screen and (max-width: 567px) { + .code-tabs .tabs__item--active { + border: 1px solid var(--medusa-code-tab-border); + background-color: var(--ifm-code-tabs-active-bg); + } .code-action { visibility: hidden; } diff --git a/www/docs/src/css/_dark.css b/www/docs/src/css/_dark.css deleted file mode 100644 index dcaba15459836..0000000000000 --- a/www/docs/src/css/_dark.css +++ /dev/null @@ -1,74 +0,0 @@ -/* color mode button */ -.color-mode-tabs { - background-color: var(--mode-tabs-bg); - border-radius: 8px; - display: flex; - flex-direction: row; - align-items: center; - padding-left: 2px !important; - padding-right: 2px !important; -} - -.color-mode-tabs.mobile { - width: fit-content; -} - -.pill-button { - border-radius: 6px; - box-shadow: none; - cursor: pointer; - box-sizing: content-box; - padding-top: 2px; - padding-bottom: 2px; - font-size: 12px; - font-weight: 500; - line-height: 24px; - height: calc(100% - 8px); - padding-left: 0; - padding-right: 0; -} - -.pill-button:not(.active) { - color: var(--mode-button-text-color); - border: none; - background-color: transparent; -} - -.pill-button.active { - color: var(--mode-button-active-text-color); - background-color: var(--mode-button-active-bg); - border: 1px solid var(--mode-button-active-border-color); -} - -/* some style rules for dark mode */ - -[data-theme="dark"] .breadcrumbs__item--active a { - background-color: var(--ifm-color-gray-800) !important; - color: var(--ifm-color-primary-lightest) !important; - font-weight: bold; -} - -[data-theme="dark"] a:hover { - color: var(--ifm-menu-active); -} - -@media screen and (min-width: 992px) { - .color-mode-tabs { - height: 32px; - } - - .pill-button { - width: 64px; - } -} - -@media screen and (max-width: 991px) { - .color-mode-tabs { - max-width: 100%; - } - - .pill-button { - padding-left: 5px; - padding-right: 5px; - } -} \ No newline at end of file diff --git a/www/docs/src/css/_docsearch.css b/www/docs/src/css/_docsearch.css index 81a4430bb8f44..b823ebea6c9b2 100644 --- a/www/docs/src/css/_docsearch.css +++ b/www/docs/src/css/_docsearch.css @@ -1,66 +1,56 @@ -.DocSearch { - --docsearch-searchbox-focus-background: var(--docsearch-searchbox-background); -} - -html:not([data-theme="dark"]) .DocSearch { - --ifm-search-bar-border-color: #E5E7EB; - --docsearch-searchbox-background: #F9FAFB; -} - -[data-theme="dark"] .DocSearch { - --ifm-search-bar-border-color: #2D2D2D; - --docsearch-searchbox-background: #222222; -} - /* Search Modal */ .DocSearch-Modal { - border-radius: 8px !important; + border: 1px solid var(--docsearch-modal-border-color); + border-radius: var(--ifm-global-radius) !important; position: relative; } -/* .DocSearch-Modal:after { - content: ''; - position: absolute; - bottom: 0; - left: 0; - width: 100%; - height: 64px; - background: var(--docsearch-modal-fade-bg); - border-radius: 8px !important; - z-index: 99; -} */ - -.DocSearch-HitsFooter { - z-index: 100; -} - -[data-theme="dark"] .DocSearch-Form { - --docsearch-searchbox-focus-background: #2D2D2D; +.DocSearch-SearchBar { + padding: 0 !important } .DocSearch-Form { - border-radius: 8px !important; - border: 1px solid; -} + --docsearch-spacing: var(--docsearch-spacing-x); + --docsearch-searchbox-height: var(--docsearch-modal-searchbox-height); + --docsearch-searchbox-shadow: var(--docsearch-modal-searchbox-focus-background); + --docsearch-searchbox-focus-background: var(--docsearch-modal-background); -.DocSearch-MagnifierLabel, .DocSearch-Reset { - width: 20px; - height: 20px; + border-radius: var(--ifm-global-radius) var(--ifm-global-radius) 0 0 !important; + border-bottom: 1px solid; } .DocSearch-LoadingIndicator svg, .DocSearch-MagnifierLabel svg { - width: 15px !important; - height: 15px !important; + width: 20px !important; + height: 20px !important; } .DocSearch-Input { - font-size: var(--ifm-font-size-base) !important; + font-size: var(--medusa-body-regular-size) !important; + line-height: var(--medusa-body-regular-line-height) !important; + font-weight: var(--medusa-body-regular-font-weight) !important; + padding-left: var(--ifm-base-spacing) !important; } .DocSearch-Input::placeholder, .DocSearch-Input:-ms-input-placeholder, .DocSearch-Input::-ms-input-placeholder { - color: #9CA3AF; + color: var(--docsearch-placeholder-color); +} + +.DocSearch-Dropdown { + padding: 0 0 var(--docsearch-footer-height) 0 !important; + max-height: calc(var(--docsearch-modal-height) - var(--docsearch-modal-searchbox-height)) !important; +} + +.DocSearch-Hit-source { + margin: 0 !important; + font-size: var(--medusa-label-small-plus-size) !important; + line-height: var(--medusa-label-small-plus-line-height) !important; + font-weight: var(--medusa-label-small-plus-font-weight) !important; + text-transform: uppercase; + color: var(--docsearch-source-color); + border-bottom: 1px solid var(--docsearch-hit-border-color); + padding: var(--docsearch-source-spacing) !important; } .DocSearch-Footer { @@ -68,12 +58,18 @@ html:not([data-theme="dark"]) .DocSearch { } .DocSearch-Hit { - margin-bottom: 12px; - padding-bottom: 0 !important; + padding: 0 !important; } -.DocSearch-Hit-icon { - position: relative; +.DocSearch-Hit:not(.DocSearch-Hit--Child) .DocSearch-Hit-icon { + width: 40px !important; + height: 40px !important; + padding: 2px; + border: 1px solid var(--medusa-border-strong); + border-radius: var(--ifm-global-radius); + display: flex; + justify-content: center; + align-items: center; } .DocSearch-Hit-icon svg { @@ -81,27 +77,34 @@ html:not([data-theme="dark"]) .DocSearch { } .DocSearch-Hit:not(.DocSearch-Hit--Child) .DocSearch-Hit-icon::before { - width: 100%; - height: 100%; + width: 32px; + height: 32px; content: ''; - background-image: url('/img/search-hit.png'); background-repeat: no-repeat; background-position: center; background-size: contain; - position: absolute; - top: 0; - left: 0; } -.DocSearch-Hit-Container { - align-items: flex-start !important; +[data-theme="dark"] .DocSearch-Hit:not(.DocSearch-Hit--Child) .DocSearch-Hit-icon::before { + background-image: url('/img/search-hit.svg'); +} + +html:not([data-theme="dark"]) .DocSearch-Hit:not(.DocSearch-Hit--Child) .DocSearch-Hit-icon::before { + background-image: url('/img/search-hit-light.svg'); +} + +.DocSearch-Hit--Child .DocSearch-Hit-icon { + display: none; } .DocSearch-Hit a { - padding: 18px 16px !important; + padding: var(--docsearch-spacing) !important; box-shadow: none !important; - border-radius: 8px !important; - border: 1px solid var(--docsearch-hit-border-color); + border-radius: 0 !important; +} + +.DocSearch-Hit:not(:last-of-type) a { + border-bottom: 1px solid var(--docsearch-hit-border-color); } .DocSearch-Hit-content-wrapper { @@ -111,56 +114,165 @@ html:not([data-theme="dark"]) .DocSearch { .DocSearch-Hit-title, .DocSearch-Hit-title mark { color: var(--docsearch-hit-title-color) !important; - font-weight: 600 !important; + font-size: var(--medusa-label-small-plus-size) !important; + line-height: var(--medusa-label-small-plus-line-height) !important; + font-weight: var(--medusa-label-small-plus-font-weight) !important; } -.DocSearch-Hit-title, -.DocSearch-Hit-path, -.DocSearch-Hit-source { - font-size: var(--ifm-font-size-base) !important; - line-height: var(--ifm-line-height-base); +.DocSearch-Hit-path { + color: var(--docsearch-muted-color) !important; + font-size: var(--medusa-label-small-size) !important; + line-height: var(--medusa-label-small-line-height) !important; + font-weight: var(--medusa-label-small-font-weight) !important; +} + +.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-path { + --docsearch-hit-active-color: var(--docsearch-muted-color); } .DocSearch-Hit[aria-selected=true] a { background-color: var(--docsearch-hit-active-bg) !important; } -.DocSearch-Hit-action { - align-self: center; +.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-content-wrapper + .DocSearch-Hit-action:last-child { + height: 24px; + width: 24px; + border: 1px solid var(--medusa-border-strong); + border-radius: var(--ifm-global-radius); + background-color: var(--docsearch-modal-background); + padding: 2px; + display: flex; + justify-content: center; + align-items: center; } -.DocSearch-Hit-action svg, -.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-action svg { - color: var(--docsearch-hit-icon-color) !important; +.DocSearch-Hit-content-wrapper + .DocSearch-Hit-action:last-child svg, +.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-content-wrapper + .DocSearch-Hit-action:last-child svg { + display: none; } -.DocSearch-Hit[aria-selected=true] span.DocSearch-Hit-path { - color: var(--docsearch-highlight-color) !important; +.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-content-wrapper + .DocSearch-Hit-action:last-child::before { + content: ''; + height: 20px; + width: 20px; + background-image: url('/img/search-hit-arrow.svg'); + background-repeat: no-repeat; + background-position: center; + background-size: contain; +} + +[data-theme="dark"] .DocSearch-Hit[aria-selected=true] .DocSearch-Hit-content-wrapper + .DocSearch-Hit-action:last-child::before { + background-image: url('/img/search-hit-arrow.svg'); +} + +html:not([data-theme="dark"]) .DocSearch-Hit[aria-selected=true] .DocSearch-Hit-content-wrapper + .DocSearch-Hit-action:last-child::before { + background-image: url('/img/search-hit-arrow-light.svg'); } .DocSearch-Hit[aria-selected=true] mark { text-decoration: none !important; } -.DocSearch-Hit-source { - margin-bottom: 12px !important; +.DocSearch-Hit-Tree { + color: var(--docsearch-tree-color); +} + +.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Tree { + color: var(--docsearch-tree-hover-color); +} + +.DocSearch-HitsFooter { + z-index: 100; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: var(--docsearch-footer-height); + background-color: var(--docsearch-modal-background); + border-top: 1px solid var(--docsearch-modal-border-color); +} + +.DocSearch-HitsFooter a { + border-bottom: none !important; +} + +.DocSearch-Reset { + border-radius: var(--ifm-global-radius) !important; + transition: all var(--ifm-transition-fast) ease; +} + +.DocSearch-Reset:hover { + background-color: var(--medusa-bg-base-hover); +} + +.DocSearch-Hits:last-of-type { + margin-bottom: 0 !important; +} + +/* Modal no results */ + +.DocSearch-NoResults .DocSearch-Screen-Icon { + width: 20px; + height: 20px; + padding: 0 !important; + display: flex; + justify-content: center; + align-items: center; + margin: 0 auto calc(var(--ifm-base-margin-vertical) / 2) auto; +} + +.DocSearch-NoResults .DocSearch-Screen-Icon svg { + display: none; +} + +.DocSearch-NoResults .DocSearch-Screen-Icon::before { + content: ''; + width: 100%; + height: 100%; + background-repeat: no-repeat; + background-position: center; + background-size: contain; +} + +[data-theme="dark"] .DocSearch-NoResults .DocSearch-Screen-Icon::before { + background-image: url('/img/search-no-result.svg'); +} + +html:not([data-theme="dark"]) .DocSearch-NoResults .DocSearch-Screen-Icon::before { + background-image: url('/img/search-no-result-light.svg'); } -.DocSearch-Hits:first-child .DocSearch-Hit-source { - margin-top: 12px !important +.DocSearch-NoResults .DocSearch-Title { + font-size: var(--medusa-label-small-size) !important; + line-height: var(--medusa-label-small-line-height) !important; + font-weight: var(--medusa-label-small-font-weight) !important; + padding-left: var(--ifm-base-spacing) !important; } -.DocSearch-Hits .DocSearch-Hit-source { - padding-top: 0 !important; +.DocSearch-NoResults-Prefill-List { + text-align: center; + font-size: var(--medusa-label-small-plus-size) !important; + line-height: var(--medusa-label-small-plus-line-height) !important; + font-weight: var(--medusa-label-small-plus-font-weight) !important; + padding-left: var(--ifm-base-spacing) !important; +} + +.DocSearch-NoResults-Prefill-List li::marker { + content: ''; +} + +.DocSearch-NoResults-Prefill-List li button { + color: var(--ifm-link-color); } /* Search Bar */ .DocSearch-Button { width: 100%; - border-radius: 8px !important; - border: 1px solid var(--ifm-search-bar-border-color) !important; - padding: 8px !important; + height: 100% !important; + border-radius: var(--ifm-global-radius) !important; + border: 1px solid var(--docsearch-searchbox-border-color) !important; + padding: 6px 6px 6px 8px !important; } span.DocSearch-Button-Key { @@ -171,35 +283,56 @@ span.DocSearch-Button-Key { z-index: 1001 !important; } -html:not([data-theme="dark"]) .DocSearch-Button .DocSearch-Search-Icon { - --docsearch-text-color: #9CA3AF; +.DocSearch-Button .DocSearch-Search-Icon { + visibility: hidden; } -[data-theme="dark"] .DocSearch-Button .DocSearch-Search-Icon { - --docsearch-text-color: #737373; +.DocSearch-Button { + position: relative; } -.DocSearch-Button .DocSearch-Search-Icon { - width: 16px; - height: 16px; +.DocSearch-Button-Container:before { + content: ''; + height: 20px; + width: 20px; + position: absolute; + left: 8px; + top: 5px; + background-image: url('/static/img/magnifying-glass.svg'); + background-repeat: no-repeat; } .DocSearch-Button-Placeholder { - font-size: 13px !important; color: var(--docsearch-placeholder-color); + padding-left: calc(var(--ifm-base-spacing) / 2) !important; + font-size: var(--medusa-label-small-size) !important; + line-height: var(--medusa-label-small-line-height) !important; + font-weight: var(--medusa-label-small-font-weight) !important; +} + +.DocSearch-Button-Keys { + width: fit-content; + min-width: unset !important; } .DocSearch-Button-Key { box-shadow: none !important; - border-radius: 4px !important; - font-weight: 600 !important; - font-size: 12px !important; - line-height: 20px !important; + border-radius: 6px !important; + font-size: var(--medusa-label-x-small-plus-size) !important; + line-height: var(--medusa-label-x-small-plus-line-height) !important; + font-weight: var(--medusa-label-x-small-plus-font-weight) !important; font-family: var(--ifm-font-family-base) !important; vertical-align: middle; padding: 2px !important; - height: 20px !important; - width: 20px !important; + border: 1px solid var(--medusa-border-strong) !important; +} + +.DocSearch-Button-Key:not(:last-child) { + margin-right: 4px !important; +} + +.DocSearch-Button-Key:last-child { + margin-right: 0 !important; } .DocSearch-Button:active, .DocSearch-Button:focus, .DocSearch-Button:hover, @@ -207,13 +340,17 @@ html:not([data-theme="dark"]) .DocSearch-Button .DocSearch-Search-Icon { border-color: var(--docsearch-searchbox-border-color) !important; } -@media screen and (min-width: 992px) { - .navbar__items [class*=searchBox] { - display: none; - } +/* Search Page */ +.search-page-wrapper article[class*=searchResultItem] { + max-width: unset !important; +} - .DocSearch-Button .DocSearch-Search-Icon { - margin-right: 8px; +@media screen and (min-width: 992px) { + [class*=searchBox] { + width: var(--docsearch-searchbox-width); + max-width: var(--docsearch-searchbox-width); + height: var(--docsearch-searchbox-height) !important; + padding: 0 !important; } } @@ -230,4 +367,17 @@ html:not([data-theme="dark"]) .DocSearch-Button .DocSearch-Search-Icon { .DocSearch-Button:focus, .DocSearch-Button:hover { box-shadow: none !important; } +} + +@media screen and (min-width: 768px) { + .DocSearch-Modal { + margin: unset !important; + width: var(--docsearch-modal-width); + } + + .DocSearch-Container { + display: flex; + justify-content: center; + align-items: center; + } } \ No newline at end of file diff --git a/www/docs/src/css/_docspage.css b/www/docs/src/css/_docspage.css index 3196e2df365c5..b9c4cf9f1ac0c 100644 --- a/www/docs/src/css/_docspage.css +++ b/www/docs/src/css/_docspage.css @@ -1,3 +1,9 @@ +.main-wrapper { + max-width: var(--ifm-max-content-width); + margin-left: auto; + margin-right: auto; +} + .theme-doc-breadcrumbs { display: none; } @@ -7,7 +13,11 @@ article { } .padding-top--md { - padding-top: 2rem !important; + padding-top: 48px !important; +} + +.margin-bottom--lg { + margin-bottom: calc(var(--ifm-base-margin-vertical) / 2) !important; } .pagination-nav { @@ -16,22 +26,33 @@ article { max-width: var(--ifm-docs-page-max-width); } -.col { - margin-top: 10px !important; -} - details summary { cursor: pointer; } +.reference-table { + display: table !important; + table-layout: fixed; + width: 100%; +} + +.reference-table p { + --ifm-paragraph-margin-bottom: 0; +} + +.reference-table th:nth-child(1), +.reference-table td:nth-child(1) { + width: 30%; +} + .reference-table th:nth-child(2), .reference-table td:nth-child(2) { - width: 40%; + width: 30%; } .reference-table th:nth-child(3), .reference-table td:nth-child(3) { - width: 50%; + width: 40%; } .reference-table .tooltip-container code { @@ -44,6 +65,10 @@ details summary { white-space: break-spaces; } +.reference-table [class*=codeBlockLinesWithNumbering] { + display: block !important; +} + .container:not(.footer-container) { padding-top: 38px !important; max-width: 100% !important; @@ -54,14 +79,13 @@ details summary { } /* User Guide Styling */ -html[data-theme="dark"] kbd { - --ifm-color-emphasis-0: var(--ifm-color-gray-200); -} - kbd { - --ifm-color-emphasis-800: var(--ifm-color-gray-800); - font: 100% var(--ifm-font-family-monospace) !important; + background-color: var(--medusa-bg-component) !important; + color: var(--medusa-text-subtle) !important; + border-radius: 6px !important; + border-color: var(--medusa-border-strong) !important; + box-shadow: none !important; } .ui-icon { @@ -73,7 +97,6 @@ kbd { .markdown-doc-wrapper { margin: 0 auto; max-width: var(--ifm-container-width); - padding: 0 var(--ifm-spacing-horizontal); width: 100%; margin-left: auto !important; } @@ -92,45 +115,44 @@ kbd { padding-top: var(--ifm-base-margin-vertical); } -html:not([data-theme="dark"]) .doc-footer { - --ifm-doc-footer-border-color: #E5E7EB; -} - -[data-theme="dark"] .doc-footer { - --ifm-doc-footer-border-color: #3E3F41; -} - .theme-edit-this-page { display: inline-flex; flex-direction: row; justify-content: center; align-items: center; - font-size: 12px; - line-height: 20px; - padding: 6px 16px; - border-radius: 8px; + padding: 6px 12px; + border-radius: var(--ifm-global-radius); cursor: pointer; - font-weight: 600; - background-color: var(--ifm-primary-btn-background-color); - border: 1px solid var(--ifm-primary-btn-border-color); + background-color: var(--ifm-secondary-btn-background-color); + border: 1px solid var(--ifm-secondary-btn-border-color); + font-size: var(--medusa-label-small-plus-size); + line-height: var(--medusa-label-small-plus-line-height); + font-weight: var(--medusa-label-small-plus-font-weight); } .theme-edit-this-page:hover { + background-color: var(--ifm-secondary-btn-hover-background-color); text-decoration: none; } .theme-edit-this-page, .theme-edit-this-page:hover { - color: var(--ifm-primary-btn-color); + color: var(--ifm-secondary-btn-color); +} + +.theme-edit-this-page:focus { + box-shadow: var(--ifm-secondary-btn-focused-shadow); } .theme-last-updated { font-style: normal; - font-size: 12px; + font-size: var(--medusa-label-small-plus-size); + line-height: var(--medusa-label-small-plus-line-height); } +.theme-last-updated, .theme-last-updated b { - font-weight: 600 !important; + font-weight: 400 !important; } .medium-zoom-overlay { @@ -149,16 +171,35 @@ details > div { --docusaurus-details-decoration-color: transparent !important; } -@media (min-width: 1440px) { +.row--justify-end { + justify-content: flex-end; +} + +.docs-page-container { + padding-left: 0 !important; + padding-right: 0 !important; +} + +@media screen and (min-width: 1419px) { + .main-wrapper { + min-width: var(--ifm-max-content-width); + } +} + +@media screen and (max-width: 1418px) { + .main-wrapper { + width: 100%; + } +} + +@media screen and (min-width: 992px) { .markdown-doc-wrapper { - max-width: var(--ifm-container-width-xl) !important; + padding: 0 calc(var(--ifm-spacing-horizontal) * 4); } } -@media screen and (min-width: 966px) { - [class*=docItemContainer] > article { - margin-left: 50px; - margin-right: 50px; - max-width: none +@media screen and (max-width: 991px) { + .markdown-doc-wrapper { + padding: 0 var(--ifm-spacing-horizontal); } } \ No newline at end of file diff --git a/www/docs/src/css/_footer.css b/www/docs/src/css/_footer.css index f261c8dd2a101..256d92401215f 100644 --- a/www/docs/src/css/_footer.css +++ b/www/docs/src/css/_footer.css @@ -1,48 +1,27 @@ -.footer__title { - font-weight: 600 !important; - margin-bottom: 16px; -} - -.footer__item:not(:last-child) { - margin-bottom: 8px; -} - footer.footer { - background-color: transparent !important; border-top: 1px solid var(--ifm-footer-border-color); - padding-top: calc(var(--ifm-base-margin-vertical) * 2); - padding-bottom: calc(var(--ifm-base-margin-vertical) * 3); + padding-top: 108px; + padding-bottom: calc(var(--ifm-base-margin-vertical) * 2); + margin-top: var(--ifm-base-margin-vertical); } .footer-container { display: flex; + padding-left: 0 !important; + padding-right: 0 !important; } -.logo-container { - display: flex; - align-items: center; -} - -.footer__copyright { - margin-left: 16px; -} - -.footer__link-item { - line-height: var(--ifm-line-height-base); - font-size: var(--ifm-font-size-base); -} - -html:not([data-theme="dark"]) .footer__item svg { - color: #9CA3AF; +.footer-container .col { + padding-left: 0 !important; + padding-right: 0 !important; } -[data-theme="dark"] .footer__item svg { - color: #737373; +footer .social-links { + --ifm-icon-color: var(--ifm-footer-social-icons-color); } -.social-logo-container { - display: flex; - flex-direction: column; +footer .social-link:hover { + --ifm-icon-color: var(--ifm-footer-social-icons-color-hover); } .social-links { @@ -51,28 +30,7 @@ html:not([data-theme="dark"]) .footer__item svg { } .social-link:not(:first-child) { - margin-left: 16px; -} - -.discord-icon { - width: 18px; - height: 14px; -} - -.twitter-icon { - width: 18px; - height: 16px; -} - -.github-icon { - width: 18px; - height: 18px; -} - -@media screen and (min-width: 992px) { - .social-logo-container { - justify-content: space-between; - } + margin-left: var(--ifm-base-spacing); } @media screen and (max-width: 991px) { @@ -80,6 +38,10 @@ html:not([data-theme="dark"]) .footer__item svg { flex-direction: column; } + .footer-container .row--justify-end { + justify-content: start; + } + .logo-container { margin-bottom: var(--ifm-base-margin-vertical); } diff --git a/www/docs/src/css/_medusa.css b/www/docs/src/css/_medusa.css new file mode 100644 index 0000000000000..25512d5c3bcf5 --- /dev/null +++ b/www/docs/src/css/_medusa.css @@ -0,0 +1,207 @@ +/** Light theme/default **/ +:root { + /** Backgrounds **/ + --medusa-bg-subtle: #F8F9FA; + --medusa-bg-subtle-hover: #F1F3F5; + --medusa-bg-subtle-pressed: #ECEEF0; + --medusa-bg-base: #FFFFFF; + --medusa-bg-base-hover: #F8F9FA; + --medusa-bg-base-pressed: #F1F3F5; + --medusa-bg-component: #F1F3F5; + --medusa-bg-field: #F8F9FA; + --medusa-bg-field-hover: #F1F3F5; + --medusa-bg-highlight: #EDE9FE; + --medusa-bg-toggle-off: #C1C8CD; + --medusa-bg-overlay: rgba(17, 24, 28, 0.4); + --medusa-bg-interactive: #6E56CF; + + /** Borders **/ + --medusa-border-base: #E6E8EB; + --medusa-border-strong: #D7DBDF; + --medusa-border-focus: #6E56CF; + --medusa-border-focus-inset: #FFFFFF; + --medusa-border-interactive: #6E56CF; + + /** Text **/ + --medusa-text-base: #11181C; + --medusa-text-subtle: #687076; + --medusa-text-placeholder: #889096; + --medusa-text-disabled: #C1C8CD; + --medusa-text-on-color: #FFFFFF; + --medusa-text-interactive: #6E56CF; + --medusa-text-interactive-hover: #644FC1; + --medusa-text-error: #E5484D; + + /** Buttons **/ + --medusa-button-primary: #6E56CF; + --medusa-button-primary-hover: #644FC1; + --medusa-button-primary-pressed: #5746AF; + --medusa-button-secondary: #FFFFFF; + --medusa-button-secondary-hover: #F8F9FA; + --medusa-button-secondary-pressed: #F1F3F5; + --medusa-button-danger: #E5484D; + --medusa-button-danger-hover: #DC3D43; + --medusa-button-danger-pressed: #CD2B31; + --medusa-button-danger-text: var(--medusa-text-on-color); + --medusa-button-success: #30A46C; + --medusa-button-success-text: var(--medusa-text-on-color); + + /** Icons **/ + --medusa-icon-primary: #11181C; + --medusa-icon-secondary: #687076; + --medusa-icon-placeholder: #889096; + --medusa-icon-disabled: #C1C8CD; + --medusa-icon-on-color: #FFFFFF; + --medusa-icon-interactive: #6E56CF; + --medusa-icon-interactive-hover: #644FC1; + --medusa-icon-error: #E5484D; + + /** Support Info **/ + --medusa-support-error: #E5484D; + --medusa-support-warning: #FFB224; + --medusa-support-success: #30A46C; + --medusa-support-info: #0091FF; + + /** Code Block **/ + --medusa-code-block: #1C1C1F; + --medusa-code-block-transparent: #1C1C1F00; + --medusa-code-block-border: #2E2E32; + --medusa-code-block-action: #706F78; + + /** Code Tabs **/ + --medusa-code-tabs-bg: #161616; + --medusa-code-tab: #1C1C1F; + --medusa-code-tab-hover: rgba(141, 141, 141, 0.16); + --medusa-code-tab-border: #3E3E44; + --medusa-code-tab-text: #7E7D86; + --medusa-code-tab-active-text: #EDEDEF; + --medusa-code-tab-title: #7E7D86; + + /** Tooltip **/ + --medusa-tooltip: var(--medusa-bg-base); + --medusa-tooltip-border: var(--medusa-border-base); + --medusa-tooltip-shadow: var(--medusa-shadow-overlay); + --medusa-tooltip-text: var(--medusa-text-subtle); + + /** Shadow **/ + --medusa-shadow-overlay: 0px 2px 16px rgba(0, 0, 0, 0.08); + --medusa-shadow-field-focused: 0px 0px 0px 4px #EDE9FE; + --medusa-shadow-button-focused: 0px 0px 0px 2px #FFFFFF, 0px 0px 0px 4px #6E56CF; + + /** Typography **/ + --medusa-body-regular-plus-size: 14px; + --medusa-body-regular-plus-line-height: 24px; + --medusa-body-regular-plus-font-weight: 500; + --medusa-body-regular-size: 14px; + --medusa-body-regular-line-height: 24px; + --medusa-body-regular-font-weight: 400; + --medusa-h1-size: 32px; + --medusa-h1-line-height: 44px; + --medusa-h1-weight: 500; + --medusa-h2-size: 24px; + --medusa-h2-line-height: 32px; + --medusa-h2-weight: 500; + --medusa-h3-size: 18px; + --medusa-h3-line-height: 28px; + --medusa-h3-weight: 500; + --medusa-label-large-plus-size: 16px; + --medusa-label-large-plus-line-height: 20px; + --medusa-label-large-plus-font-weight: 500; + --medusa-label-regular-plus-size: 14px; + --medusa-label-regular-plus-line-height: 20px; + --medusa-label-regular-plus-font-weight: 500; + --medusa-label-regular-size: 14px; + --medusa-label-regular-line-height: 20px; + --medusa-label-regular-font-weight: 400; + --medusa-label-small-plus-size: 13px; + --medusa-label-small-plus-line-height: 20px; + --medusa-label-small-plus-font-weight: 500; + --medusa-label-small-size: 13px; + --medusa-label-small-line-height: 20px; + --medusa-label-small-font-weight: 400; + --medusa-label-x-small-plus-size: 12px; + --medusa-label-x-small-plus-line-height: 20px; + --medusa-label-x-small-plus-font-weight: 500; + + /** Tags **/ + --medusa-tag-purple-bg: #EDE9FE; + --medusa-tag-purple-bg-hover: #E4DEFC; + --medusa-tag-purple-text: #5746AF; + --medusa-tag-purple-icon: #6E56CF; + --medusa-tag-purple-border: #D7CFF9; + --medusa-tag-orange-bg: #FFECBC; + --medusa-tag-orange-bg-hover: #FFE3A2; + --medusa-tag-orange-text: #AD5700; + --medusa-tag-orange-icon: #FFB224; + --medusa-tag-orange-border: #FFD386; +} + +/** Dark theme **/ +html[data-theme="dark"] { + /** Backgrounds **/ + --medusa-bg-subtle: #161618; + --medusa-bg-subtle-hover: #1C1C1F; + --medusa-bg-subtle-pressed: #232326; + --medusa-bg-base: #1C1C1F; + --medusa-bg-base-hover: #232326; + --medusa-bg-base-pressed: #28282C; + --medusa-bg-component: #2E2E32; + --medusa-bg-field: #232326; + --medusa-bg-field-hover: #28282C; + --medusa-bg-highlight: #2C2250; + --medusa-bg-toggle-off: #3E3E44; + --medusa-bg-overlay: rgba(22, 22, 24, 0.7); + --medusa-bg-interactive: #6E56CF; + + /** Borders **/ + --medusa-border-base: #2E2E32; + --medusa-border-strong: #3E3E44; + --medusa-border-focus: #6E56CF; + --medusa-border-focus-inset: #1C1C1F; + --medusa-border-interactive: #6E56CF; + + /** Text **/ + --medusa-text-base: #EDEDEF; + --medusa-text-subtle: #7E7D86; + --medusa-text-placeholder: #706F78; + --medusa-text-disabled: #504F57; + --medusa-text-on-color: #FFFFFF; + --medusa-text-interactive: #7C66DC; + --medusa-text-interactive-hover: #9E8CFC; + --medusa-text-error: #E5484D; + + /** Buttons **/ + --medusa-button-primary: #6E56CF; + --medusa-button-primary-hover: #7C66DC; + --medusa-button-primary-pressed: #9E8CFC; + --medusa-button-secondary: #232326; + --medusa-button-secondary-hover: #2E2E32; + --medusa-button-secondary-pressed: #2E2E32; + + /** Icons **/ + --medusa-icon-primary: #EDEDEF; + --medusa-icon-secondary: #7E7D86; + --medusa-icon-placeholder: #706F78; + --medusa-icon-disabled: #504F57; + --medusa-icon-on-color: #FFFFFF; + --medusa-icon-interactive: #7C66DC; + --medusa-icon-interactive-hover: #9E8CFC; + --medusa-icon-error: #E5484D; + + /** Shadow **/ + --medusa-shadow-overlay: 0px 2px 16px rgba(0, 0, 0, 0.32); + --medusa-shadow-field-focused: 0px 0px 0px 4px #2C2250; + --medusa-shadow-button-focused: 0px 0px 0px 2px #1C1C1F, 0px 0px 0px 4px #6E56CF; + + /** Tags **/ + --medusa-tag-purple-bg: #2C2250; + --medusa-tag-purple-bg-hover: #32275F; + --medusa-tag-purple-text: #9E8CFC; + --medusa-tag-purple-icon: #6E56CF; + --medusa-tag-purple-border: #392C72; + --medusa-tag-orange-bg: #3F2200; + --medusa-tag-orange-bg-hover: #4A2900; + --medusa-tag-orange-text: #F1A10D; + --medusa-tag-orange-icon: #FFB224; + --medusa-tag-orange-border: #573300; +} \ No newline at end of file diff --git a/www/docs/src/css/_navbar.css b/www/docs/src/css/_navbar.css index 80d15ac1c51c3..882cbe385af5f 100644 --- a/www/docs/src/css/_navbar.css +++ b/www/docs/src/css/_navbar.css @@ -1,89 +1,88 @@ -html[data-theme="dark"] .navbar-github-link:before { - background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") - no-repeat; -} - .navbar { z-index: calc(var(--ifm-z-index-overlay) - 1); - padding-top: var(--ifm-navbar-padding-top); - padding-bottom: var(--ifm-navbar-padding-bottom); + padding: 0; } @supports ((-webkit-backdrop-filter: none) or (backdrop-filter: none)) { - .navbar:not(.navbar-sidebar--show) { + html:not(.plugin-redoc) .navbar:not(.navbar-sidebar--show) { background: none; - backdrop-filter: blur(14px); + backdrop-filter: blur(12px); } } -.navbar-github-link:before { - content: ""; - width: 24px; - height: 24px; - display: flex; - background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") - no-repeat; +.navbar__link { + font-size: var(--medusa-label-small-plus-size); + line-height: var(--medusa-label-small-plus-line-height); + font-weight: var(--medusa-label-small-plus-font-weight); } -.navbar__link svg { - display: none; +.navbar__inner { + max-width: var(--ifm-max-content-width); + margin-left: auto; + margin-right: auto; + padding: var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal); } -.navbar__link { - font-size: 13px; - line-height: 24px; +.navbar__brand { + margin-right: calc(var(--ifm-base-spacing) * 2); } -.navbar__item { - padding-top: 0; - padding-bottom: 0; +.navbar__logo { + height: var(--ifm-logo-height); + width: var(--ifm-logo-width); + display: flex; + justify-content: center; + align-items: center; + margin-right: 0 !important; } -.navbar__items { - max-height: 100%; +[class*=colorModeToggle], +.navbar-link-icon { + background-color: var(--medusa-button-secondary); + border: 1px solid var(--medusa-border-base); + border-radius: var(--ifm-global-radius); + width: 32px !important; + height: 32px !important; } -.navbar__item.dropdown > .navbar__link, -.external-link .navbar__item { - vertical-align: text-top; +[class*=toggleButton]:hover, +.navbar-link-icon:hover { + background-color: var(--medusa-button-secondary-hover) !important; } -.navbar__logo { - height: 24px; - width: 24px; +[class*=toggleButton] { + --ifm-icon-color: var(--ifm-color-mode-icon-color) +} + +.navbar-link-icon { display: flex; justify-content: center; align-items: center; } -.navbar__logo { - height: auto; +[class*=colorModeToggle] { + margin-left: var(--ifm-navbar-item-padding-horizontal); + margin-right: 12px; } -.navbar__link--active { - font-weight: 600; +[class*=toggleButton] { + border-radius: var(--ifm-global-radius) !important; } - - -@media screen and (min-width: 992px) { - .navbar .right-divider { - height: 100%; - } - .navbar .right-divider:after { - content: ''; +@media screen and (min-width: 992px) { + .navbar .divider { height: 20px; width: 1px; - margin-left: 12px; + margin-left: var(--ifm-navbar-item-padding-horizontal); + margin-right: var(--ifm-navbar-item-padding-horizontal); display: inline-block; vertical-align: middle; + background-color: var(--ifm-navbar-divider-color); } +} - html:not([data-theme="dark"]) .navbar .right-divider:after { - background-color: #D1D5DB; - } - - [data-theme="dark"] .navbar .right-divider:after { - background-color: #393939; +@media screen and (max-width: 991px) { + .navbar-actions { + display: none; } } \ No newline at end of file diff --git a/www/docs/src/css/_note.css b/www/docs/src/css/_note.css index 7396034bf2f16..6a8ebd5b7b677 100644 --- a/www/docs/src/css/_note.css +++ b/www/docs/src/css/_note.css @@ -1,14 +1,14 @@ .alert { - padding: 16px; + padding: var(--ifm-base-spacing); border: 1px solid var(--ifm-note-border-color) !important; background-color: var(--ifm-note-background); - border-radius: 8px; + border-radius: var(--ifm-global-radius); box-shadow: none; } .alert p > code { - padding-left: 8px; - padding-right: 8px; + padding-left: calc(var(--ifm-base-spacing) / 2); + padding-right: calc(var(--ifm-base-spacing) / 2); font-size: 14px !important; } @@ -16,14 +16,9 @@ text-decoration: none; } -html:not([data-theme="dark"]) [class*=alert--] { - --ifm-code-background: #F9FAFB !important; - --ifm-alert-background-color-highlight: #F9FAFB !important; - --ifm-link-color: #4B5563 !important; -} - -[data-theme="dark"] [class*=alert--] { - --ifm-code-background: #222222 !important; - --ifm-alert-background-color-highlight: #222222 !important; - --ifm-link-color: #8A8A8A !important; +[class*=alert--] { + --ifm-code-background: var(--medusa-bg-base) !important; + --ifm-alert-background-color-highlight: var(--ifm-background-surface-color) !important; + --ifm-link-color: var(--ifm-color-primary) !important; + --ifm-link-hover-color: var(--ifm-color-content) !important; } \ No newline at end of file diff --git a/www/docs/src/css/_redocly.css b/www/docs/src/css/_redocly.css index 444601f526745..17d10505dfec4 100644 --- a/www/docs/src/css/_redocly.css +++ b/www/docs/src/css/_redocly.css @@ -1,33 +1,133 @@ -html[data-theme="dark"] .redocusaurus .expanded + tr > td > div { - background-color: var(--ifm-medusa-gray); +.redocusaurus .expanded + tr > td > div { + background-color: var(--ifm-background-surface-color) !important; +} + +.redocusaurus table tbody tr table, +.redocusaurus table tbody tr table tbody tr { + background-color: transparent !important; } .redocusaurus a { color: var(--ifm-link-color) !important; } -.redocusaurus [data-section-id] > div:nth-child(2) pre { +.redocusaurus pre, +.redocusaurus .react-tabs__tab-panel--selected, +.redocusaurus [data-section-id] > div:nth-child(2) > div > button, +.redocusaurus div[id^='tag'] > div > div:nth-child(2) > div:nth-child(1) > div:nth-child(2) { + background-color: var(--medusa-code-block) !important; +} + +[data-theme="dark"] .redocusaurus [data-section-id] > div:nth-child(2) > div > button, +.redocusaurus div[id^='tag'] > div > div:nth-child(2) > div:nth-child(1) > div:nth-child(2) > div > div:nth-child(2) > div { + border-color: var(--medusa-border-strong) !important; +} + +.redocusaurus [data-section-id] > div:nth-child(2) > div > button { + border-radius: var(--ifm-global-radius) var(--ifm-global-radius) 0 0 !important; +} + +.redocusaurus [data-section-id] > div:nth-child(2) > div > button + div > div > div > div { + color: var(--ifm-color-primary) !important; +} + +.redocusaurus [data-section-id] > div:nth-child(2) .react-tabs__tab pre { background-color: transparent !important; - margin-top: 10px; + margin-top: calc(var(--ifm-base-margin-vertical) / 2); } -html[data-theme="dark"] .redocusaurus h5 + svg { - fill: #fff; +.redocusaurus h5 + svg { + fill: var(--ifm-icon-color); } -html[data-theme="dark"] .redocusaurus h2 + div + div > div + div { +.redocusaurus h2 + div + div > div + div { padding: 8px 9.6px; + background-color: var(--ifm-background-surface-color); } -html[data-theme="dark"] .redocusaurus h2 + div + div > div + div { - background-color: #11171a; +.redocusaurus h2 + div + div { + border-bottom-color: var(--ifm-base-border-color); } -html[data-theme="dark"] .redocusaurus .menu-content, -html[data-theme="dark"] .redocusaurus .menu-content label { +.redocusaurus .menu-content, +.redocusaurus .menu-content label { background-color: var(--ifm-background-color) !important; } .redoc-json code { border: none !important; +} + +.redocusaurus p { + color: var(--ifm-color-content); +} + +.redocusaurus h2, .redocusaurus h3, .redocusaurus h4 { + color: var(--ifm-color-headers) !important; +} + +.redocusaurus [data-section-id] > div:nth-child(2) h2, .redocusaurus [data-section-id] > div:nth-child(2) h3, .redocusaurus [data-section-id] > div:nth-child(2) h4 { + --ifm-color-headers: var(--medusa-text-on-color); +} + +.redocusaurus [data-section-id]:after { + border-color: transparent !important; +} + +.redocusaurus .property-name + div { + color: var(--medusa-icon-error) !important; +} + +.redocusaurus .react-tabs__tab:not(.react-tabs__tab--selected) { + background-color: var(--ifm-secondary-btn-background-color) !important; + border-color: var(--ifm-secondary-btn-border-color) !important; + color: var(--ifm-secondary-btn-color) !important; +} + +.redocusaurus ul > li.react-tabs__tab--selected[aria-selected="true"]:not(.tab-error):not(.tab-success) { + background-color: var(--ifm-primary-btn-background-color) !important; + border-color: var(--ifm-primary-btn-border-color) !important; + color: var(--ifm-primary-btn-color) !important; +} + +.redocusaurus ul > li.react-tabs__tab--selected.tab-success { + background-color: var(--medusa-button-success) !important; + border-color: var(--medusa-button-success) !important; + color: var(--medusa-button-success-text) !important; +} + +.redocusaurus ul > li.react-tabs__tab--selected.tab-error { + background-color: var(--medusa-button-danger) !important; + border-color: var(--medusa-button-danger) !important; + color: var(--medusa-button-danger-text) !important; +} + +.redocusaurus ul > li.react-tabs__tab--selected.tab-error:hover { + background-color: var(--medusa-button-danger-hover) !important; + border-color: var(--medusa-button-danger-hover) !important; +} + +.redocusaurus .tab-error:not(.react-tabs__tab--selected) { + background-color: var(--ifm-secondary-btn-background-color) !important; + border-color: var(--ifm-secondary-btn-border-color) !important; + color: var(--medusa-support-error) !important; +} + +.redocusaurus .tab-success:not(.react-tabs__tab--selected) { + background-color: var(--ifm-secondary-btn-background-color) !important; + border-color: var(--ifm-secondary-btn-border-color) !important; + color: var(--medusa-support-success) !important; +} + +.redocusaurus [type=get] { + background-color: var(--medusa-support-success) !important; +} + +.redocusaurus [type=delete] { + background-color: var(--medusa-support-error) !important; +} + +.redocusaurus table th, +.redocusaurus table td { + border-color: var(--ifm-base-border-color) !important; } \ No newline at end of file diff --git a/www/docs/src/css/_sidebar.css b/www/docs/src/css/_sidebar.css index 180e865e13c38..0a2510ed3a7ca 100644 --- a/www/docs/src/css/_sidebar.css +++ b/www/docs/src/css/_sidebar.css @@ -1,243 +1,361 @@ -.main-wrapper aside { - z-index: var(--ifm-z-index-fixed); +/** General sidebar styles **/ +.theme-doc-sidebar-container { + z-index: calc(var(--ifm-z-index-overlay) - 2); + border-right: 1px solid var(--ifm-toc-border-color); } -.sidebar-bg { +.main-sidebar { + margin-top: 0 !important; + padding-top: 0 !important; + padding-left: var(--doc-sidebar-padding) !important; + padding-right: var(--doc-sidebar-padding) !important; + padding-bottom: calc(var(--ifm-base-margin-vertical) * 2) !important; +} + +.theme-doc-sidebar-item-category-level-1 > .menu__list { + margin-bottom: calc(var(--ifm-base-spacing) / 4); +} + +.menu__list:not(.theme-doc-sidebar-menu), +.theme-doc-sidebar-item-category-level-1 > .menu__list { + padding-left: 0 !important; +} + +.menu__list-item:not(:first-child):not(.sidebar-title) { + margin-top: 0 !important; +} + +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) [class*=theme-doc-sidebar-item-], +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) [class*=theme-doc-sidebar-item-] .menu__link--active { + position: relative; +} + +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) [class*=theme-doc-sidebar-item-]:not(.theme-doc-sidebar-item-link-category)::before, +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) .theme-doc-sidebar-item-category .menu__list-item-collapsible .menu__link--active::before, +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) > .theme-doc-sidebar-item-link > .menu__link--active::before, +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) .theme-doc-sidebar-item-category > .menu__list-item-collapsible::before { + content: ''; height: 100%; - font-size: 14px; - font-weight: 400; + width: 1px; + position: absolute; + left: 8px; + top: 0; + z-index: 1; } -.sidebar-bg img { - width: 100px; +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) [class*=theme-doc-sidebar-item-] .menu__link--active::before { + height: 20px !important; } -a.menu__link.menu__link--active.active { - padding-left: 16px; +.theme-doc-sidebar-item-category-level-1 > .menu__list > .menu__list-item:first-child::before, +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) .theme-doc-sidebar-item-category:first-child .menu__list-item-collapsible::before, +.theme-doc-sidebar-item-category-level-1 > .menu__list > .menu__list-item:last-child::before { + height: calc(var(--ifm-base-margin-vertical) - 4px) !important; } -a.menu__link--sublist::after, -.menu__caret:before { - background: var(--ifm-menu-link-sublist-icon) 50% / 1rem 2rem; +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) .theme-doc-sidebar-item-link:first-child::before, +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) .theme-doc-sidebar-item-category:first-child .menu__list-item-collapsible::before { + bottom: 0 !important; + top: unset !important; } -.menu__list-item > a { - font-weight: 450; +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) .theme-doc-sidebar-item-category:first-child .menu__list-item-collapsible { + padding-bottom: var(--ifm-menu-link-padding-vertical) !important; } -.react-toggle { - display: none; +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) .theme-doc-sidebar-item-category:first-child .menu__list-item-collapsible .menu__link { + padding-bottom: 0 !important; } -.menu__link, -.redocusaurus .menu-content label { - font-weight: 500 !important; - font-size: 12px; - line-height: 1.7em; - position: relative; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; + +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) [class*=theme-doc-sidebar-item-]::before, +.menu__list-item .menu__list:not(.theme-doc-sidebar-menu) .theme-doc-sidebar-item-category:first-child .menu__list-item-collapsible::before { + background-color: var(--medusa-border-base); } -.menu__link { - display: inline-block; - max-width: 100%; +.theme-doc-sidebar-item-category-level-2 > .menu__list-item-collapsible .menu__link--active::before, +.menu__list:not(.theme-doc-sidebar-menu) > .theme-doc-sidebar-item-link.theme-doc-sidebar-item-link-level-2 > .menu__link--active::before { + background-color: var(--medusa-icon-interactive); + z-index: 2 !important; + top: var(--ifm-menu-link-padding-vertical) !important; } -.theme-doc-sidebar-item-link-level-1 .menu__link, -.theme-doc-sidebar-item-category-level-1 .menu__link, -.redocusaurus .menu-content label.-depth1, -.navbar-sidebar__item .menu__link:not(.navbar-github-link), -[class*=theme-doc-sidebar-item-link-level-]:not(.theme-doc-sidebar-item-link-level-1) .menu__link { - padding-left: 24px; +.theme-doc-sidebar-item-category-level-2:only-child > .menu__list-item-collapsible .menu__link--active::before, +.menu__list:not(.theme-doc-sidebar-menu) > .theme-doc-sidebar-item-link.theme-doc-sidebar-item-link-level-2:only-child > .menu__link--active::before, +.menu__list:not(.theme-doc-sidebar-menu) > .theme-doc-sidebar-item-link.theme-doc-sidebar-item-link-level-2:first-child > .menu__link--active::before { + top: calc(var(--ifm-menu-link-padding-vertical) + 2px) !important; } -.redocusaurus .menu-content label { - color: var(--ifm-menu-color) +.menu__list:not(.theme-doc-sidebar-menu) > .theme-doc-sidebar-item-link:last-child > .menu__link--active::before { + top: calc(var(--ifm-menu-link-padding-vertical) - 2px) !important; } -.menu__link:hover, -.menu__link--active, -.menu__list-item-collapsible:hover, -.menu__list-item-collapsible--active, -.redocusaurus .menu-content label:hover, -.redocusaurus .menu-content label.active { - background-color: transparent !important; - color: var(--ifm-menu-active); +.menu__list-item-collapsible .menu__caret { + display: none; } -.menu__link--active, -.menu__list-item-collapsible--active, -.redocusaurus .menu-content label.active { - font-weight: 600 !important; +.menu__link--sublist-caret:after { + content: none; +} + +.sidebar-desktop nav { + --ifm-scrollbar-track-background-color: transparent !important; + --ifm-scrollbar-thumb-background-color: transparent !important; + --ifm-scrollbar-thumb-hover-background-color: transparent !important; +} + +.theme-doc-sidebar-item-link-level-1:not(.sidebar-title):not(.homepage-sidebar-item):not(.sidebar-back-link) { + margin-bottom: calc(var(--ifm-base-margin-vertical) / 2); +} + +.theme-doc-sidebar-item-link-level-1:not(.sidebar-title):not(.homepage-sidebar-item):not(.sidebar-back-link) .menu__link { + padding-left: 0 !important; +} + +.menu__list .menu__list { + margin-top: 0 !important; } -/* .menu__list, -.redocusaurus .menu-content ul { - padding-left: 1.7em; - padding-right: 1.7em; +/* .sidebar-desktop::before { + content: ''; + width: 100%; + height: calc(var(--ifm-base-spacing) * 1.5); + display: block; + background-color: var(--ifm-background-color); } */ -a.menu__link--sublist::after { - content: none; +/** Mobile Sidebar **/ +.navbar-sidebar__back { + background: transparent; + width: fit-content; + top: unset; + padding-left: 0; + margin-left: 0; + margin-bottom: calc(var(--ifm-base-margin-vertical) / 2); + font-size: var(--medusa-label-small-plus-size); + line-height: var(--medusa-label-small-plus-line-height); + font-weight: var(--medusa-label-small-plus-font-weight); } -a.menu__link--sublist + .menu__caret, -.redocusaurus .menu-content label svg { - display: none; +/** Homepage Sidebar Design **/ +.homepage-sidebar-item:is([class*="level-1"]):is([class*="theme-doc-sidebar-item"]) > .menu__link, +.homepage-sidebar-item:is([class*="level-1"]):is([class*="theme-doc-sidebar-item"]) > .menu__list-item-collapsible > .menu__link { + padding-left: calc(var(--ifm-base-spacing) / 2) !important; } -a.menu__link--sublist::before, -.redocusaurus .menu-content label[type=tag].-depth1::before { - content: ""; - height: 16px; - width: 16px; - background-repeat: no-repeat; - background-position: center; - background-size: 6.8px; - transition: transform var(--ifm-transition-fast) linear; - position: absolute; +/** General Sidebar items styles **/ +.menu__list-item-collapsible { + border-radius: var(--ifm-global-radius) !important; } -html:not([data-theme="dark"]) a.menu__link--sublist::before, -html:not([data-theme="dark"]) .redocusaurus .menu-content label[type=tag].-depth1::before { - background-image: url('/img/triangle-right.png'); +.menu__link { + cursor: pointer; + border-radius: var(--ifm-global-radius) !important; + font-size: var(--medusa-label-small-plus-size); + line-height: var(--medusa-label-small-plus-line-height); + font-weight: var(--medusa-label-small-plus-font-weight); } -[data-theme="dark"] a.menu__link--sublist::before, -[data-theme="dark"] .redocusaurus .menu-content label[type=tag].-depth1::before { - background-image: url('/img/triangle-right-dark.png'); +.theme-doc-sidebar-item-link { + display: flex; + align-items: center; } -html:not([data-theme="dark"]) a.menu__link--sublist:hover::before, -html:not([data-theme="dark"]) .redocusaurus .menu-content label[type=tag].-depth1:hover::before, -html:not([data-theme="dark"]) a.menu__link--sublist.menu__link--active::before, -html:not([data-theme="dark"]) .redocusaurus .menu-content label[type=tag].-depth1.active::before { - background-image: url('/img/triangle-right-hover.png'); +.menu__list-item-collapsible--active { + background-color: transparent !important; } -[data-theme="dark"] a.menu__link--sublist:hover::before, -[data-theme="dark"] .redocusaurus .menu-content label[type=tag].-depth1:hover::before, -[data-theme="dark"] a.menu__link--sublist.menu__link--active::before, -[data-theme="dark"] .redocusaurus .menu-content label[type=tag].-depth1.active::before { - background-image: url('/img/triangle-right-dark-hover.png'); +[class*="level-2"]:is([class*="theme-doc-sidebar-item"]) .menu__link, +[class*="level-2"]:is([class*="theme-doc-sidebar-item"]).sidebar-group-divider, +[class*="level-3"]:is([class*="theme-doc-sidebar-item"]) .menu__link, +[class*="level-3"]:is([class*="theme-doc-sidebar-item"]).sidebar-group-divider, +[class*="level-4"]:is([class*="theme-doc-sidebar-item"]) .menu__link, +[class*="level-4"]:is([class*="theme-doc-sidebar-item"]).sidebar-group-divider { + padding-top: var(--ifm-menu-link-padding-vertical); + padding-bottom: var(--ifm-menu-link-padding-vertical); } -.menu__list-item:not(.menu__list-item--collapsed) > .menu__list-item-collapsible > .menu__link--sublist:before { - transform: rotate(90deg); +[class*="level-2"]:is([class*="theme-doc-sidebar-item"]) .menu__link, +[class*="level-2"]:is([class*="theme-doc-sidebar-item"]).sidebar-group-divider { + padding-left: calc(var(--ifm-menu-link-padding-horizontal) * 2); } -.menu__link:not(.menu__link--sublist):not(.navbar-github-link)::before { - content: ""; - height: 16px; - width: 16px; - background-size: 6px; - background-image: url('/img/circle.png'); - background-repeat: no-repeat; - background-position: center; - position: absolute; +[class*="level-3"]:is([class*="theme-doc-sidebar-item"]) .menu__link, +[class*="level-3"]:is([class*="theme-doc-sidebar-item"]).sidebar-group-divider { + padding-left: calc(var(--ifm-menu-link-padding-horizontal) * 3); } -html:not([data-theme="dark"]) .menu__link:not(.menu__link--sublist):hover::before, -html:not([data-theme="dark"]) .menu__link:not(.menu__link--sublist).menu__link--active::before { - background-image: url('/img/circle-hover.png'); +[class*="level-4"]:is([class*="theme-doc-sidebar-item"]) .menu__link, +[class*="level-4"]:is([class*="theme-doc-sidebar-item"]).sidebar-group-divider { + padding-left: calc(var(--ifm-menu-link-padding-horizontal) * 4); } -[data-theme="dark"] .menu__link:not(.menu__link--sublist):hover::before, -[data-theme="dark"] .menu__link:not(.menu__link--sublist).menu__link--active::before { - background-image: url('/img/circle-dark-hover.png'); +/** Sidebar title **/ +.sidebar-title { + margin: 0 !important; + padding: calc(var(--ifm-base-margin-vertical) / 2) 0 !important; } -[class*=theme-doc-sidebar-item-link-level-]:not(.theme-doc-sidebar-item-link-level-1) .menu__link::before, -[class*=theme-doc-sidebar-item-link-level-]:not(.theme-doc-sidebar-item-link-level-1) a.menu__link--sublist::before, -[class*=theme-doc-sidebar-item-category-level-]:not(.theme-doc-sidebar-item-category-level-1) .menu__link::before, -[class*=theme-doc-sidebar-item-category-level-]:not(.theme-doc-sidebar-item-category-level-1) a.menu__link--sublist::before { - left: 5px; +.sidebar-title .menu__link, +.sidebar-title span { + --ifm-menu-link-padding-horizontal: 0; + font-size: var(--medusa-label-regular-plus-size) !important; + line-height: var(--medusa-label-regular-plus-line-height) !important; + font-weight: var(--medusa-label-regular-plus-font-weight) !important; + color: var(--medusa-text-base); } -.theme-doc-sidebar-item-link-level-1 .menu__link::before, -.theme-doc-sidebar-item-link-level-1 a.menu__link--sublist::before, -.theme-doc-sidebar-item-category-level-1 .menu__link::before, -.theme-doc-sidebar-item-category-level-1 a.menu__link--sublist::before, -.redocusaurus .menu-content label[type=tag].-depth1::before, -.navbar-sidebar__item .menu__link::before { - left: 0; +.sidebar-title .menu__link--active, +.sidebar-title .menu__link:hover { + background-color: transparent !important; } -.redocusaurus .menu-content label::before { - top: 35%; +/** Group Headline **/ +.sidebar-group-headline { + margin-top: calc(var(--ifm-base-margin-vertical) / 2); + padding: 6px 0; } -a.menu__link--sublist::before, -.theme-doc-sidebar-item-link-level-1 .menu__link::before, -.menu__link:not(.menu__link--sublist)::before { - top: 21%; +.theme-doc-sidebar-item-category-level-1.sidebar-group-headline { + margin-bottom: calc(var(--ifm-base-margin-vertical) / 2); } -.menu__list-item > .menu__list-item-collapsible + .menu__list { - transition-property: opacity, height !important; - transition-duration: 350ms !important; - transition-timing-function: ease-in-out !important; - will-change: opacity, height !important; - opacity: 0; - display: block !important; - height: 0; - transition-delay: 100ms, 0s !important; +.sidebar-group-headline:not(.theme-doc-sidebar-item-category-level-1) { + margin-bottom: 6px; } -.menu__list-item:not(.menu__list-item--collapsed) > .menu__list-item-collapsible + .menu__list { - opacity: 1; - height: auto; +.sidebar-group-headline > .menu__list-item-collapsible > .menu__link { + color: var(--medusa-text-base); + padding: 0 !important; } -.menu__list-item.alert-icon .menu__link::before { - background-image: url('/img/alert.svg'); - width: 20px; - height: 20px; - top: 19%; +.sidebar-group-headline > .menu__list-item-collapsible > .menu__link:not([href]) { + cursor: default; +} + +.sidebar-group-headline > .menu__list-item-collapsible > .menu__link:hover, +.sidebar-group-headline .menu__list-item-collapsible:hover { + background-color: transparent !important; } -html:not([data-theme="dark"]) .menu__list-item.alert-icon .menu__link:hover::before, -html:not([data-theme="dark"]) .menu__list-item.alert-icon .menu__link.menu__link--active::before { - background-image: url('/img/alert-hover.svg'); +.sidebar-group-headline > .menu__link, +.sidebar-group-headline > .menu__list-item-collapsible > .menu__link { + --medusa-label-small-plus-font-weight: 600; } -[data-theme="dark"] .menu__list-item.alert-icon .menu__link:hover::before, -[data-theme="dark"] .menu__list-item.alert-icon .menu__link.menu__link--active::before { - background-image: url('/img/alert-hover-dark.svg'); +/** Divider Line Item **/ +.sidebar-divider-line { + height: 1px; + width: 100%; + background-color: var(--medusa-border-base); + margin: calc(var(--ifm-base-margin-vertical) / 2) 0; } -.menu__list-item.topright-icon .menu__link::before { - background-image: url('/img/arrow-top-right.svg'); +/** Sidebar Group Divider **/ +.sidebar-group-divider { + padding-bottom: 6px; + text-transform: uppercase; + color: var(--medusa-text-placeholder); + font-size: var(--medusa-label-x-small-plus-size); + line-height: var(--medusa-label-x-small-plus-line-height); + font-weight: var(--medusa-label-x-small-plus-font-weight); +} + +.sidebar-group-divider:first-child { + padding-top: 6px !important; +} + +.sidebar-group-divider:not(:first-child) { + padding-top: calc(var(--ifm-base-margin-vertical) / 2) !important; +} + +/** Sidebar Item Icon **/ + +[class*="theme-doc-sidebar-item-"]:not(.sidebar-title) .sidebar-item-icon { width: 20px; height: 20px; - top: 19%; } -html:not([data-theme="dark"]) .menu__list-item.topright-icon .menu__link:hover::before, -html:not([data-theme="dark"]) .menu__list-item.topright-icon .menu__link.menu__link--active::before { - background-image: url('/img/arrow-top-right-hover.svg'); +[class*="theme-doc-sidebar-item-"]:not(.sidebar-title):not(.sidebar-back-link) .sidebar-item-icon { + margin-right: calc(var(--ifm-base-margin-vertical) / 2); } -[data-theme="dark"] .menu__list-item.topright-icon .menu__link:hover::before, -[data-theme="dark"] .menu__list-item.topright-icon .menu__link.menu__link--active::before { - background-image: url('/img/arrow-top-right-hover-dark.svg'); +/** Back Link **/ +.sidebar-back-link { + cursor: pointer; } -.menu__list-item.alert-icon [class*=iconExternalLink], -.menu__list-item.topright-icon [class*=iconExternalLink] { - display: none; +.sidebar-back-link .menu__link { + padding: 0 !important; } -.menu__list-item-collapsible { - padding-bottom: 6px; +.sidebar-back-link .menu__link, +.sidebar-back-link span { + font-size: var(--medusa-label-small-plus-size); + line-height: var(--medusa-label-small-plus-line-height); + font-weight: var(--medusa-label-small-plus-font-weight); +} + +.sidebar-back-link .menu__link:hover { + background-color: transparent !important; + color: var(--ifm-menu-color-active); } -.navbar-github-link { - overflow: visible; +.sidebar-back-link .sidebar-item-icon { + margin-right: calc(var(--ifm-base-margin-vertical) / 4); +} + +.menu__list-item-collapsible .menu__link--sublist:hover { + background-color: var(--ifm-menu-color-background-hover) !important; +} + +/** Sidebar Soon Link **/ +.sidebar-soon-link { + pointer-events: none; +} + +.sidebar-soon-link * { + --ifm-icon-color: var(--medusa-icon-disabled); + + color: var(--medusa-text-disabled); } -.sidebar-desktop:not(.scrolling) nav::-webkit-scrollbar { - --ifm-scrollbar-size: 0px; +/** Sidebar Badge **/ +.sidebar-badge-wrapper { + display: flex; + justify-content: space-between; + align-items: center; +} + +/** Redocly sidebar **/ + +.redocusaurus .menu-content > div > ul > li > ul label:not([type=tag]):not(.active) { + color: var(--ifm-menu-color); +} + +.redocusaurus .menu-content > div > ul > li > ul label:not([type=tag]).active, +.redocusaurus .menu-content > div > ul > li > ul label:not([type=tag]):not(.active):hover { + color: var(--ifm-menu-color-active); +} + +/** Media Query **/ +@media screen and (min-width: 992px) { + .sidebar-title, + .sidebar-back-link { + position: sticky; + background-color: var(--ifm-background-color); + z-index: 100; + } + + .sidebar-title:first-child { + top: 0; + } + + .sidebar-title:not(:first-child) { + top: var(--medusa-label-small-plus-line-height); + } + + .sidebar-back-link { + top: 0; + } } \ No newline at end of file diff --git a/www/docs/src/css/_toc.css b/www/docs/src/css/_toc.css index 21f6d466f1224..173a642f71335 100644 --- a/www/docs/src/css/_toc.css +++ b/www/docs/src/css/_toc.css @@ -1,3 +1,7 @@ +.theme-doc-toc-desktop { + padding-top: calc(var(--ifm-base-margin-vertical) * 1.5); +} + .theme-doc-toc-desktop .table-of-contents { border-left: none !important; padding: 0; @@ -7,21 +11,23 @@ } html:not([data-theme="dark"]) .theme-doc-toc-desktop .table-of-contents::before { - background-image: url('/img/side-menu.svg'); + background-image: url('/img/side-menu-light.svg'); } [data-theme="dark"] .theme-doc-toc-desktop .table-of-contents::before { - background-image: url('/img/side-menu-dark.svg'); + background-image: url('/img/side-menu.svg'); } .theme-doc-toc-desktop .table-of-contents::before { background-repeat: no-repeat; - background-size: 20px; - background-position-x: -1px; - padding-left: 28px; + background-size: 14px 10px; + background-position-y: center; + padding-left: 22px; content: 'On this page'; - font-size: 13px; padding-bottom: 0; + font-size: var(--medusa-label-small-plus-size); + line-height: var(--medusa-label-small-plus-line-height); + font-weight: var(--medusa-label-small-plus-font-weight); } .theme-doc-toc-desktop .table-of-contents .table-of-contents__link { @@ -29,7 +35,7 @@ html:not([data-theme="dark"]) .theme-doc-toc-desktop .table-of-contents::before } .theme-doc-toc-desktop .table-of-contents > li:first-child { - margin-top: 16px; + margin-top: calc(var(--ifm-base-margin-vertical) / 2); } .theme-doc-toc-desktop .table-of-contents::after { @@ -42,8 +48,15 @@ html:not([data-theme="dark"]) .theme-doc-toc-desktop .table-of-contents::before background-color: var(--ifm-toc-divider-color); } +.theme-doc-toc-desktop .table-of-contents li a + ul { + margin-top: 4px; +} + .theme-doc-toc-desktop .table-of-contents__link { position: relative; + font-size: var(--medusa-label-x-small-plus-size); + line-height: var(--medusa-label-x-small-plus-line-height); + font-weight: var(--medusa-label-x-small-plus-font-weight); } .theme-doc-toc-desktop .table-of-contents__link:hover, @@ -64,15 +77,6 @@ html:not([data-theme="dark"]) .theme-doc-toc-desktop .table-of-contents::before z-index: 1; } -.theme-doc-toc-desktop .toc-wrapper { - padding-left: 0; - padding-right: 0; -} - -.theme-doc-toc-desktop .markdown-row { - width: 100%; -} - .theme-doc-toc-desktop .table-of-contents li { margin-left: 0px; margin-right: 0px; @@ -99,14 +103,6 @@ html:not([data-theme="dark"]) .theme-doc-toc-desktop .table-of-contents::before padding-left: calc(var(--ifm-toc-padding-horizontal) + var(--ifm-toc-link-padding-left)) !important; } -@media screen and (min-width: 1441px) { - .col.toc-wrapper { - --ifm-col-width: calc(2 / 12 * 100%) - } -} - -@media screen and (max-width: 1440px) { - .col.toc-wrapper { - --ifm-col-width: calc(3 / 12 * 100%) - } +.col.toc-wrapper { + --ifm-col-width: var(--ifm-toc-width); } \ No newline at end of file diff --git a/www/docs/src/css/_tooltip.css b/www/docs/src/css/_tooltip.css index 5dd33d6f99b81..d55b4f1038353 100644 --- a/www/docs/src/css/_tooltip.css +++ b/www/docs/src/css/_tooltip.css @@ -1,11 +1,11 @@ .react-tooltip { border: 1px solid var(--ifm-tooltip-border-color) !important; - border-radius: 8px !important; - font-size: 12px !important; - font-weight: 500 !important; - line-height: 20px !important; - box-shadow: 0px 2px 16px var(--ifm-tooltip-box-shadow-color) !important; - padding: 8px 16px !important; + border-radius: var(--ifm-global-radius) !important; + font-size: var(--medusa-label-x-small-plus-size) !important; + line-height: var(--medusa-label-x-small-plus-line-height) !important; + font-weight: var(--medusa-label-x-small-plus-font-weight) !important; + box-shadow: var(--ifm-tooltip-box-shadow-color) !important; + padding: calc(var(--ifm-base-margin-vertical) / 4 - 1px) var(--ifm-base-spacing) !important; } .react-tooltip-arrow { diff --git a/www/docs/src/css/_typography.css b/www/docs/src/css/_typography.css index 729108da74387..2f2c4f60b9bb8 100644 --- a/www/docs/src/css/_typography.css +++ b/www/docs/src/css/_typography.css @@ -1,73 +1,85 @@ h1 { font-size: var(--ifm-h1-font-size); + font-weight: var(--ifm-h1-weight); line-height: var(--ifm-h1-line-height); } h2 { font-size: var(--ifm-h2-font-size); + font-weight: var(--ifm-h2-weight); line-height: var(--ifm-h2-line-height); } -h1, h2, h3, h4, h5, h6 { - color: var(--ifm-color-headers); +h3 { + font-size: var(--ifm-h3-font-size); + font-weight: var(--ifm-h3-weight); + line-height: var(--ifm-h3-line-height); } -p { - font-weight: 400; +h1, h2, h3, h4, h5, h6 { + color: var(--ifm-color-headers); } -.theme-doc-markdown a:hover { - text-decoration: none; +.markdown > h1, +.markdown > h1:first-child { + --ifm-h1-font-size: var(--medusa-h1-size); + --ifm-h1-line-height: var(--medusa-h1-line-height); + --ifm-h1-weight: var(--medusa-h1-weight); } -.markdown h1:first-child { - font-size: 30px !important; +.markdown > h1:first-child, +.markdown > h2, +.markdown > h3 { + margin-bottom: calc(var(--ifm-base-margin-vertical) / 4); } .markdown > h2 { - font-size: 24px !important; -} - -.markdown > p { - margin-bottom: calc(var(--ifm-base-margin-vertical) / 4); + --ifm-h2-font-size: var(--medusa-h2-size); + --ifm-h2-line-height: var(--medusa-h2-line-height); + --ifm-h2-weight: var(--medusa-h2-weight); } -.markdown a, -.markdown a:hover { - color: var(--ifm-link-color); +.markdown > h3 { + --ifm-h3-font-size: var(--medusa-h3-size); + --ifm-h3-line-height: var(--medusa-h3-line-height); + --ifm-h3-weight: var(--medusa-h3-weight); } -.markdown a:not(.hash-link) { - font-weight: var(--ifm-link-weight); +p { + font-weight: var(--ifm-font-weight-base); } -.markdown a:not(.hash-link):not(.card):not(.img-url):after { - display: inline-block; - width: 16px; - height: 16px; - content: ''; - vertical-align: middle; +.markdown > p { + margin-bottom: calc(var(--ifm-base-margin-vertical) / 4); } -html:not([data-theme="dark"]) .markdown a:not(.hash-link):not(.card):not(.img-url):after { - background-image: url('/img/link-icon.svg'); +.markdown a:not(.hash-link), +.DocSearch-Prefill { + font-weight: var(--ifm-link-weight); } -[data-theme="dark"] .markdown a:not(.hash-link):not(.card):not(.img-url):after { - background-image: url('/img/link-icon-dark.svg'); +.markdown p + img, +.markdown .alert, +.markdown .code-wrapper { + margin-bottom: var(--ifm-base-margin-vertical); } -.markdown p + h2, -.markdown .alert + h2 { - margin-top: calc(var(--ifm-base-margin-vertical) * 2); +.markdown h2, +.markdown h3, +.markdown p + .code-wrapper, +.markdown p + .tabs-wrapper, +.markdown p + .alert, +.markdown p + section, +video { + margin-top: var(--ifm-base-margin-vertical); } -.markdown p + .alert { - margin-top: var(--ifm-base-margin-vertical); +.markdown p + .card-wrapper { + margin-top: 24px; } .markdown { - margin-bottom: calc(var(--ifm-base-margin-vertical) * 2); + margin-bottom: 0; } .markdown p + p > img:not(.ui-icon) { @@ -76,4 +88,13 @@ html:not([data-theme="dark"]) .markdown a:not(.hash-link):not(.card):not(.img-ur p + img:not(.ui-icon) { margin-bottom: calc(var(--ifm-base-margin-vertical) * 2); +} + +h1 + .cards-grid, +h1 + .card-wrapper, +h2 + .cards-grid, +h2 + .card-wrapper, +h3 + .cards-grid, +h3 + .card-wrapper { + margin-top: calc(var(--ifm-hr-margin-vertical) - 8px); } \ No newline at end of file diff --git a/www/docs/src/css/_variables.css b/www/docs/src/css/_variables.css index 57a9045c701bf..0baabcc83830e 100644 --- a/www/docs/src/css/_variables.css +++ b/www/docs/src/css/_variables.css @@ -5,241 +5,285 @@ :root { /* Base Styles */ --ifm-global-radius: 8px; - --ifm-hr-background-color: #E5E7EB; + --ifm-hr-background-color: var(--medusa-border-base); + --ifm-base-spacing: 16px; + --ifm-global-spacing: var(--ifm-base-spacing); --ifm-base-margin-vertical: 32px; - --ifm-hr-margin-vertical: calc(var(--ifm-base-margin-vertical) * 2); + --ifm-hr-margin-vertical: var(--ifm-base-margin-vertical); + --ifm-leading: 24px; + --ifm-logo-width: 83px; + --ifm-logo-height: 20px; /* Colors */ - --ifm-color-primary: #111827; - --ifm-medusa-gray: #f0f0f0; - --ifm-color-content: #6B7280; + --ifm-color-primary: var(--medusa-text-base); + --ifm-background-color: var(--medusa-bg-base); + --ifm-background-surface-color: var(--medusa-bg-subtle); + --ifm-color-content: var(--medusa-text-subtle) !important; + --ifm-color-content-secondary: var(--ifm-color-content) !important; --ifm-primary-gradient: linear-gradient(90deg, rgba(146, 144, 254, 0) 0%, rgba(163, 219, 254, 0.4) 26.04%, #9290FE 53.65%, rgba(197, 145, 255, 0.4) 78.65%, rgba(201, 138, 255, 0) 100%); + --ifm-base-border-color: var(--medusa-border-base); + --ifm-strong-border-color: var(--medusa-border-strong); + --ifm-focus-border-color: var(--medusa-border-focus); + --ifm-icon-color: var(--medusa-icon-secondary); /* Fonts */ - --ifm-code-font-size: 14px; + --ifm-code-font-size: var(--medusa-body-regular-size); --ifm-font-family-base: "Inter",BlinkMacSystemFont,-apple-system,"Segoe UI","Roboto","Oxygen","Ubuntu","Cantarell","Fira Sans","Droid Sans","Helvetica Neue","Helvetica","Arial",sans-serif; --ifm-font-family-monospace: 'Roboto Mono',SFMono-Regular, Menlo, Monaco, Consolas,'Liberation Mono', 'Courier New', monospace; - --ifm-font-size-base: 14px; - --ifm-line-height-base: 24px; + --ifm-font-size-base: var(--medusa-body-regular-size); + --ifm-line-height-base: var(--medusa-body-regular-line-height); + --ifm-font-weight-base: var(--medusa-body-regular-font-weight); /* Headings */ - --ifm-color-headers: #111827; - --ifm-heading-font-weight: 600; - --ifm-heading-line-height: 24px; - --ifm-h1-font-size: 30px; - --ifm-h1-line-height: 48px; - --ifm-h2-font-size: 24px; - --ifm-h2-line-height: 36px; - --ifm-h4-font-size: 14px; + /** Due to how docusaurus styles headings, the variables are set again in _typography.css **/ + --ifm-color-headers: var(--ifm-color-primary); + --ifm-h1-font-size: var(--medusa-h1-size); + --ifm-h1-line-height: var(--medusa-h1-line-height); + --ifm-h1-weight: var(--medusa-h1-weight); + --ifm-h2-font-size: var(--medusa-h2-size); + --ifm-h2-line-height: var(--medusa-h2-line-height); + --ifm-h2-weight: var(--medusa-h2-weight); + --ifm-h3-font-size: var(--medusa-h3-size); + --ifm-h3-line-height: var(--medusa-h3-line-height); + --ifm-h3-weight: var(--medusa-h3-weight); + --ifm-h4-font-size: var(--ifm-font-size-base); /* Links */ - --ifm-link-color: #4B5563; - --ifm-link-weight: 600; + --ifm-link-color: var(--ifm-color-primary); + --ifm-link-weight: var(--medusa-body-regular-plus-font-weight); + --ifm-link-hover-color: var(--ifm-color-content); + --ifm-link-decoration: none; + --ifm-link-hover-decoration: none; /* Sidebar */ - --doc-sidebar-width: 250px !important; - --ifm-menu-active: #111827; + --doc-sidebar-width: 320px !important; + --doc-sidebar-padding: 24px; + --ifm-menu-link-padding-vertical: 6px; + --ifm-menu-link-padding-horizontal: 16px; + --ifm-menu-color: var(--medusa-text-subtle); + --ifm-menu-color-active: var(--medusa-text-base); + --ifm-menu-color-background-hover: var(--medusa-bg-base-hover); + --ifm-menu-color-background-active: var(--medusa-bg-base-pressed); /* Docs Page */ - --ifm-docs-page-max-width: 850px; + --ifm-docs-page-max-width: var(--ifm-container-width-xl); + --ifm-max-content-width: 1419px; /* Toc */ - --ifm-toc-border-color: #f0f0f0; - --ifm-toc-link-color: #6B7280; - --ifm-toc-padding-horizontal: 9px; - --ifm-toc-link-active: #111827; - --ifm-toc-divider-color: #E5E7EB; - --ifm-toc-link-padding-left: 16px; + --ifm-toc-border-color: var(--medusa-border-base); + --ifm-toc-link-color: var(--medusa-text-subtle); + --ifm-toc-padding-horizontal: 16px; + --ifm-toc-link-active: var(--medusa-text-base); + --ifm-toc-divider-color: var(--medusa-border-base); + --ifm-toc-link-padding-left: 11px; /* Navbar */ - --ifm-navbar-shadow: 0px 1px 0px 0px #E5E7EB; - --ifm-navbar-padding-top: 16px; - --ifm-navbar-padding-bottom: 17px; - --ifm-navbar-padding-vertical: 16px; + --ifm-navbar-background-color: var(--ifm-background-color); + --ifm-navbar-shadow: 0px 1px 0px 0px var(--medusa-border-base); + --ifm-navbar-padding-vertical: 12px; --ifm-navbar-padding-horizontal: 24px; + --ifm-navbar-item-padding-vertical: 6px; + --ifm-navbar-item-padding-horizontal: 16px; --ifm-navbar-height: 57px; - --ifm-navbar-link-hover-color: #111827; - --ifm-navbar-link-color: #6B7280; + --ifm-navbar-link-hover-color: var(--medusa-text-base); + --ifm-navbar-link-color: var(--medusa-text-subtle); + --ifm-navbar-divider-color: var(--medusa-border-strong); /* Color Mode toggler */ - --mode-tabs-bg: #F3F4F6; - --mode-button-text-color: #6B7280; - --mode-button-active-bg: #FFFFFF; - --mode-button-active-border-color: #E5E7EB; - --mode-button-active-text-color: #111827; + --ifm-color-mode-icon-color: var(--medusa-icon-secondary); /* Screen Width */ --ifm-container-width-xl: 960px; /* Notes */ - --ifm-note-background: #F9FAFB; - --ifm-note-border-color: #E5E7EB; - --ifm-note-text-color: #4B5563; - - /* Code */ + --ifm-note-background: var(--ifm-background-surface-color); + --ifm-note-border-color: var(--medusa-border-base); + --ifm-note-text-color: var(--medusa-text-subtle); + --ifm-note-info-color: var(--medusa-support-info); + --ifm-note-warning-color: var(--medusa-support-error); + --ifm-note-tip-color: var(--medusa-support-warning); + + /* Inline Code */ --ifm-code-border-radius: 8px; --ifm-code-padding-horizontal: 8px; - --ifm-code-border-color: #E5E7EB; - --ifm-code-background: #F9FAFB; - --ifm-code-color: #4B5563; - --ifm-code-tabs-color: #6F6F6F; - --ifm-code-tabs-active-bg: transparent; - --ifm-code-tabs-active-color: #F4F4F4; - --ifm-code-action-hover-bg: rgba(141, 141, 141, 0.16); + --ifm-code-border-color: var(--medusa-border-base); + --ifm-code-background: var(--medusa-bg-subtle) !important; + --ifm-code-background-hover: var(--medusa-bg-subtle-hover); + --ifm-code-background-pressed: var(--medusa-bg-subtle-pressed); + --ifm-code-color: var(--medusa-text-subtle); + + /* Code Blocks */ + --ifm-pre-background: var(--medusa-code-block); + --ifm-pre-background-transparent: var(--medusa-code-block-transparent); + --ifm-code-tabs-color: var(--medusa-code-tab-text); + --ifm-code-tabs-active-bg: var(--medusa-code-tab); + --ifm-code-tabs-active-color: var(--medusa-code-tab-active-text); + --ifm-code-action-hover-bg: var(--medusa-code-tab-hover); --ifm-pre-padding: 16px; - --docusaurus-highlighted-code-line-bg: #393939; - --ifm-code-title-color: #737373; + --ifm-code-title-color: var(--medusa-code-tab-title); + --ifm-code-line-number-color: var(--medusa-text-placeholder); + --ifm-code-block-border-color: var(--medusa-code-block-border); + + /* Tabs */ + --ifm-tabs-color-active: var(--ifm-color-primary); /* Tooltip */ - --ifm-tooltip-background-color: #fff; - --ifm-tooltip-border-color: #E5E7EB; - --ifm-tooltip-box-shadow-color: rgba(17, 24, 39, 0.08); + --ifm-tooltip-background-color: var(--medusa-tooltip); + --ifm-tooltip-border-color: var(--medusa-tooltip-border); + --ifm-tooltip-box-shadow-color: var(--medusa-tooltip-shadow); --rt-opacity: 1 !important; --rt-color-dark: var(--ifm-tooltip-background-color) !important; --rt-color-white: var(--ifm-color-content) !important; /* Buttons */ - --ifm-primary-btn-background-color: #fff; - --ifm-primary-btn-color: #111827; - --ifm-primary-btn-border-color: #E5E7EB; + --ifm-primary-btn-background-color: var(--medusa-button-primary); + --ifm-primary-btn-hover-background-color: var(--medusa-button-primary-hover); + --ifm-primary-btn-color: var(--medusa-text-on-color); + --ifm-primary-btn-border-color: var(--medusa-button-primary); + --ifm-primary-btn-focused-shadow: var(--medusa-shadow-button-focused); + --ifm-secondary-btn-background-color: var(--medusa-button-secondary); + --ifm-secondary-btn-color: var(--ifm-color-primary); + --ifm-secondary-btn-border-color: var(--ifm-base-border-color); + --ifm-secondary-btn-hover-background-color: var(--medusa-button-secondary-hover); + --ifm-secondary-btn-focused-shadow: var(--ifm-primary-btn-focused-shadow); /* Footer */ - --ifm-footer-border-color: #E5E7EB; - --ifm-footer-logo-max-width: 24px; - --ifm-footer-title-color: #111827; + --ifm-footer-color: var(--medusa-text-placeholder); + --ifm-footer-background-color: transparent; + --ifm-footer-padding-horizontal: 0; + --ifm-footer-social-icons-color: var(--medusa-icon-placeholder); + --ifm-footer-social-icons-color-hover: var(--medusa-icon-secondary); + --ifm-footer-border-color: var(--medusa-border-base); --ifm-footer-link-color: var(--ifm-color-content); + --ifm-doc-footer-border-color: var(--medusa-border-base); /* Search */ - --docsearch-searchbox-background: #F9FAFB !important; - --docsearch-modal-background: #fff !important; - --docsearch-modal-shadow: none !important; - --docsearch-modal-fade-bg: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #FFFFFF 100%); - --docsearch-container-background: rgba(17, 24, 39, 0.4) !important; - --docsearch-key-gradient: #E5E7EB !important; - --docsearch-muted-color: #6B7280 !important; - --docsearch-placeholder-color: #9CA3AF; - --docsearch-searchbox-shadow: 0px 0px 0px 4px rgba(124, 58, 237, 0.1) !important; - --docsearch-searchbox-border-color: #7C3AED; - --docsearch-primary-color: var(--docsearch-searchbox-border-color); - --docsearch-searchbox-height: 40px !important; - --docsearch-spacing: 16px !important; - --docsearch-highlight-color: #6B7280 !important; - --docsearch-text-color: #111827 !important; - --docsearch-hit-background: #FFFFFF !important; + --docsearch-searchbox-width: 280px; + --docsearch-searchbox-height: 32px !important; + --docsearch-searchbox-background: var(--medusa-bg-field) !important; + --docsearch-searchbox-focus-background: var(--medusa-bg-field-hover) !important; + --docsearch-searchbox-border-color: var(--medusa-border-base); + --docsearch-searchbox-shadow: none !important; + --docsearch-modal-height: 472px !important; + --docsearch-modal-background: var(--medusa-bg-base) !important; + --docsearch-modal-border-color: var(--medusa-border-base); + --docsearch-modal-shadow: var(--medusa-shadow-overlay) !important; + --docsearch-modal-fade-bg: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #FFFFFF 100%); /* TODO */ + --docsearch-modal-searchbox-height: 56px; + --docsearch-modal-searchbox-focus-background: none; + --docsearch-container-background: var(--medusa-bg-overlay) !important; + --docsearch-key-gradient: var(--medusa-bg-component) !important; + --docsearch-muted-color: var(--medusa-text-subtle) !important; + --docsearch-placeholder-color: var(--medusa-text-placeholder); + --docsearch-primary-color: var(--ifm-color-primary); + --docsearch-source-color: var(--medusa-text-placeholder); + --docsearch-spacing-y: 12px; + --docsearch-spacing-x: 24px; + --docsearch-spacing: var(--docsearch-spacing-y) var(--docsearch-spacing-x) !important; + --docsearch-source-spacing: 10px 24px; + --docsearch-highlight-color: var(--medusa-text-placeholder) !important; + --docsearch-text-color: var(--ifm-color-primary) !important; + --docsearch-hit-background: var(--docsearch-modal-background) !important; --docsearch-hit-height: auto !important; --docsearch-hit-active-color: var(--docsearch-text-color) !important; - --docsearch-hit-active-bg: #F9FAFB; - --docsearch-hit-icon-color: #9CA3AF; - --docsearch-hit-border-color: #E5E7EB; - --docsearch-hit-title-color: #000000; + --docsearch-hit-active-bg: var(--medusa-bg-base-hover); + --docsearch-hit-icon-color: var(--medusa-icon-placeholder); + --docsearch-icon-color: var(--medusa-icon-placeholder); + --docsearch-hit-border-color: var(--medusa-border-base); + --docsearch-hit-title-color: var(--docsearch-primary-color); + --docsearch-tree-color: var(--medusa-border-base); + --docsearch-tree-hover-color: var(--medusa-border-strong); + --docsearch-footer-height: 40px !important; /* Announcement Bar */ - --ifm-announcement-bar-bg: #FFFFFF; - --ifm-announcement-bar-border-color: #E5E7EB; - --ifm-announcement-bar-hover-bg: #F9FAFB; - --ifm-announcement-bar-icon-bg: #F3F4F6; - --ifm-announcement-bar-icon-border-color: var(--ifm-announcement-bar-border-color); - --ifm-announcement-bar-title-color: var(--ifm-color-headers); + --docusaurus-announcement-bar-height: auto !important; + --ifm-announcement-bar-bg: var(--ifm-background-surface-color); + --ifm-announcement-bar-border-color: var(--ifm-base-border-color); + --ifm-announcement-bar-hover-bg: var(--medusa-bg-subtle-hover); + --ifm-announcement-bar-icon-bg: url('/img/announcement-bg.svg'); + --ifm-announcement-bar-icon-color: var(--medusa-icon-on-color); + --ifm-announcement-bar-title-color: var(--ifm-color-primary); --ifm-announcement-bar-text-color: var(--ifm-color-content); - --ifm-announcement-bar-close-icon-color: #9CA3AF; + --ifm-announcement-bar-close-icon-color: var(--medusa-icon-placeholder); + + /* Cards */ + --ifm-card-bg: var(--ifm-background-surface-color); + --ifm-card-bg-hover: var(--medusa-bg-subtle-hover); + --ifm-card-border-color: var(--ifm-background-surface-color); + --ifm-card-icon-size: 20px; + --ifm-card-highlighted-bg-image: url('/img/small-squares-bg-light.svg'); + + /* Large Card */ + --large-card-bg: var(--ifm-background-surface-color); + --large-card-bg-hover: var(--medusa-bg-subtle-hover); + --large-card-border-color: var(--ifm-base-border-color); + --large-card-bg-image: url('/img/squares-bg-light.svg'); + --large-card-fade-effect: linear-gradient(transparent, var(--large-card-bg)); + --large-card-fade-effect-hover: linear-gradient(transparent, var(--large-card-bg-hover)); + --large-card-icon-size: 20px; + --large-card-icon-inside-padding: 6px; + --large-card-icon-wrapper-padding: var(--bordered-padding); + --large-card-icon-wrapper-border-color: var(--ifm-strong-border-color); + --large-card-title-color: var(--ifm-color-primary); + + /* Bordered Element */ + --bordered-border-color: var(--medusa-border-strong); + --bordered-padding: 3px; + --bordered-inside-padding: 2px; + --bordered-margin-right: calc(var(--ifm-base-margin-vertical) / 2); + + /** Tables **/ + --ifm-table-border-color: var(--medusa-border-base); + --ifm-table-head-background: var(--ifm-background-surface-color); + --ifm-table-head-color: var(--ifm-color-primary); + --ifm-table-head-font-weight: var(--medusa-body-regular-plus-font-weight); + --ifm-table-stripe-background: var(--ifm-background-surface-color) !important; } html[data-theme="dark"] { - /* Base Styles */ - --ifm-hr-background-color: #2D2D2D; - - /* Colors */ - --ifm-color-primary: #F3F3F3; - --ifm-background-color: #161616; - --ifm-background-surface-color: #161616; - --ifm-medusa-gray: #292929; - --ifm-color-content: #8A8A8A; - - /* Headings */ - --ifm-color-headers: #F3F3F3; - - /* Links */ - --ifm-link-color: #8A8A8A; /* Sidebar */ - --ifm-menu-color: rgba(255, 255, 255, 0.5); - --ifm-menu-active: #fff; - - /* Toc */ - --ifm-toc-border-color: #333; - --ifm-toc-link-active: #F3F3F3; - --ifm-toc-link-color: #737373; - --ifm-toc-divider-color: #393939; + --ifm-menu-color-background-hover: var(--medusa-bg-subtle-hover); + --ifm-menu-color-background-active: var(--medusa-bg-subtle-pressed); - /* Navbar */ - --ifm-navbar-background-color: #161616; - --ifm-navbar-shadow: 0px 1px 0px 0px #2D2D2D; - --ifm-navbar-link-hover-color: #F3F3F3; - --ifm-navbar-link-color: #8A8A8A; - - /* Color Mode toggler */ - --mode-tabs-bg: #222222; - --mode-button-text-color: #8A8A8A; - --mode-button-active-bg: #161616; - --mode-button-active-border-color: #393939; - --mode-button-active-text-color: #F3F3F3; + /* Colors */ + --ifm-background-color: var(--medusa-bg-subtle); + --ifm-background-surface-color: var(--medusa-bg-base); - /* Notes */ - --ifm-note-background: #222222; - --ifm-note-border-color: #393939; - --ifm-note-text-color: #8A8A8A; - - /* Code */ - --ifm-code-border-color: #393939; - --ifm-code-background: #222222; - --ifm-code-color: #8A8A8A; - --ifm-code-tabs-active-bg: #222222; - --ifm-code-tabs-active-color: #F3F3F3; - --ifm-code-action-hover-bg: rgba(255, 255, 255, 0.05); + /* Inline Code */ + --ifm-code-background: var(--medusa-bg-base) !important; + --ifm-code-background-hover: var(--medusa-bg-base-hover); + --ifm-code-background-pressed: var(--medusa-bg-base-pressed); - /* Tooltip */ - --ifm-tooltip-background-color: #222222; - --ifm-tooltip-border-color: #393939; + /* Cards */ + --ifm-card-bg-hover: var(--medusa-bg-base-hover); + --ifm-card-highlighted-bg-image: url('/img/small-squares-bg.svg'); - /* Buttons */ - --ifm-primary-btn-background-color: #222222; - --ifm-primary-btn-color: #F3F3F3; - --ifm-primary-btn-border-color: #393939; + /* Announcement Bar */ + --ifm-announcement-bar-hover-bg: var(--medusa-bg-base-hover); - /* Footer */ - --ifm-footer-border-color: #3E3F41; - --ifm-footer-title-color: #F3F3F3; - --ifm-footer-link-color: var(--ifm-color-content); + /* Large Card */ + --large-card-bg-hover: var(--medusa-bg-base-hover); + --large-card-bg-image: url('/img/squares-bg.svg'); +} - /* Search */ - --docsearch-searchbox-background: #222222 !important; - --docsearch-searchbox-focus-background: var(--docsearch-searchbox-background) !important; - --docsearch-modal-background: #222222 !important; - --docsearch-modal-fade-bg: linear-gradient(180deg, rgba(34, 34, 34, 0) 0%, #222222 100%); - --docsearch-container-background: rgba(22, 22, 22, 0.7) !important; - --docsearch-key-gradient: #393939 !important; - --docsearch-muted-color: #8A8A8A !important; - --docsearch-placeholder-color: #686868; - --docsearch-searchbox-shadow: 0px 0px 0px 4px rgba(139, 92, 246, 0.2) !important; - --docsearch-searchbox-border-color: #8B5CF6; - --docsearch-highlight-color: #8A8A8A !important; - --docsearch-text-color: #F3F3F3 !important; - --docsearch-hit-background: #222222 !important; - --docsearch-hit-active-color: var(--docsearch-text-color) !important; - --docsearch-hit-active-bg: #2D2D2D; - --docsearch-hit-icon-color: #737373; - --docsearch-hit-border-color: #393939; - --docsearch-hit-title-color: #F3F3F3; +@media screen and (min-width: 1441px) { + :root { + /** Table of Content **/ + --ifm-toc-width: calc(2 / 12 * 100%); + } +} - /* Announcement Bar */ - --ifm-announcement-bar-bg: #222222; - --ifm-announcement-bar-border-color: #2D2D2D; - --ifm-announcement-bar-hover-bg: #2D2D2D; - --ifm-announcement-bar-icon-bg: #393939; - --ifm-announcement-bar-icon-border-color: #393939; - --ifm-announcement-bar-text-color: #737373; +@media screen and (max-width: 1440px) { + :root { + /** Table of Content **/ + --ifm-toc-width: calc(3 / 12 * 100%); + } +} - /* Tabs */ - --ifm-tabs-color-active: #F3F3F3; +@media (min-width: 997px) { + :root { + --docusaurus-announcement-bar-height: 30px; + } } \ No newline at end of file diff --git a/www/docs/src/css/custom.css b/www/docs/src/css/custom.css index 9ae702329c083..2943798201ff8 100644 --- a/www/docs/src/css/custom.css +++ b/www/docs/src/css/custom.css @@ -1,16 +1,8 @@ -/* stylelint-disable docusaurus/copyright-header */ -/** - * Any CSS included here will be global. The classic template - * bundles Infima by default. Infima is a CSS framework designed to - * work well for content-centric websites. - */ - -/* You can override the default Infima variables here. */ +@import url('./_medusa.css'); @import url('./_variables.css'); @import url('./_card.css'); @import url('./_code.css'); -@import url('./_dark.css'); @import url('./_docsearch.css'); @import url('./_docspage.css'); @import url('./_footer.css'); diff --git a/www/docs/src/pages/index.module.css b/www/docs/src/pages/index.module.css deleted file mode 100644 index 0fa615b3755eb..0000000000000 --- a/www/docs/src/pages/index.module.css +++ /dev/null @@ -1,37 +0,0 @@ -/* stylelint-disable docusaurus/copyright-header */ - -/** - * CSS files with the .module.css suffix will be treated as CSS modules - * and scoped locally. - */ - -.heroBanner { - padding: 4rem 0; - text-align: center; - position: relative; - overflow: hidden; -} - -@media screen and (max-width: 966px) { - .heroBanner { - padding: 2rem; - } -} - -.buttons { - display: flex; - align-items: center; - justify-content: center; -} - -.container { - display: flex; - flex-direction: column; -} - -@media screen and (min-width: 966px) { - .container { - max-width: 850px; - margin: 0 auto; - } -} diff --git a/www/docs/src/theme/Admonition/index.js b/www/docs/src/theme/Admonition/index.js index 001b79b1537b9..f05ca5be7daf7 100644 --- a/www/docs/src/theme/Admonition/index.js +++ b/www/docs/src/theme/Admonition/index.js @@ -7,17 +7,32 @@ import useBaseUrl from '@docusaurus/useBaseUrl'; function NoteIcon() { return ( - + + + ); } function TipIcon() { return ( - + + + + ); } function DangerIcon() { return ( - + + + ); } function InfoIcon() { diff --git a/www/docs/src/theme/Admonition/styles.module.css b/www/docs/src/theme/Admonition/styles.module.css index cce64c4c27e7f..1087ef32b670f 100644 --- a/www/docs/src/theme/Admonition/styles.module.css +++ b/www/docs/src/theme/Admonition/styles.module.css @@ -1,5 +1,5 @@ .admonition { - margin-bottom: 32px; + margin-bottom: var(--ifm-base-margin-vertical); } .admonitionIcon { @@ -9,15 +9,13 @@ .admonitionIcon svg, .admonitionIcon img { display: inline-block; - vertical-align: middle; + margin-top: 2px; } .admonitionIcon { - height: 20px; - width: 20px; - margin-right: 16px; - flex: 1; - max-width: 20px; + height: 24px; + width: 24px; + margin-right: var(--ifm-base-spacing); } .admonitionIcon img { @@ -25,8 +23,10 @@ } .admonitionContent { - font-size: 14px; color: var(--ifm-note-text-color); + font-size: var(--medusa-body-regular-size) !important; + line-height: var(--medusa-body-regular-line-height) !important; + font-weight: var(--medusa-body-regular-font-weight) !important; flex: 1; width: calc(100% - 40px); } diff --git a/www/docs/src/theme/AnnouncementBar/CloseButton/index.js b/www/docs/src/theme/AnnouncementBar/CloseButton/index.js new file mode 100644 index 0000000000000..ebd479a06ca23 --- /dev/null +++ b/www/docs/src/theme/AnnouncementBar/CloseButton/index.js @@ -0,0 +1,20 @@ +import React from 'react'; +import clsx from 'clsx'; +import {translate} from '@docusaurus/Translate'; +import IconClose from '@theme/Icon/Close'; +import styles from './styles.module.css'; +export default function AnnouncementBarCloseButton(props) { + return ( + + ); +} diff --git a/www/docs/src/theme/AnnouncementBar/CloseButton/styles.module.css b/www/docs/src/theme/AnnouncementBar/CloseButton/styles.module.css new file mode 100644 index 0000000000000..6d4f6a875cd68 --- /dev/null +++ b/www/docs/src/theme/AnnouncementBar/CloseButton/styles.module.css @@ -0,0 +1,12 @@ +.closeButton { + --ifm-icon-color: var(--ifm-announcement-bar-close-icon-color); + + padding: 0; + line-height: 0; + align-self: flex-start; +} + +.closeButton, +.closeButton:hover { + opacity: 1 !important; +} \ No newline at end of file diff --git a/www/docs/src/theme/AnnouncementBar/Content/styles.module.css b/www/docs/src/theme/AnnouncementBar/Content/styles.module.css index 186bb94f26e4a..ed4f7258f6c3b 100644 --- a/www/docs/src/theme/AnnouncementBar/Content/styles.module.css +++ b/www/docs/src/theme/AnnouncementBar/Content/styles.module.css @@ -1,10 +1,10 @@ .contentWrapper { - font-size: 12px; - line-height: 16px; color: var(--ifm-announcement-bar-text-color); + font-size: var(--medusa-label-x-small-plus-size); + line-height: var(--medusa-label-x-small-plus-line-height); + font-weight: var(--medusa-label-x-small-plus-font-weight); } .contentTitle { - font-weight: 600; - color: var( --ifm-announcement-bar-title-color); + color: var(--ifm-announcement-bar-title-color); } \ No newline at end of file diff --git a/www/docs/src/theme/AnnouncementBar/index.js b/www/docs/src/theme/AnnouncementBar/index.js index 5e0cb45354367..0afa4cb65d140 100644 --- a/www/docs/src/theme/AnnouncementBar/index.js +++ b/www/docs/src/theme/AnnouncementBar/index.js @@ -3,9 +3,9 @@ import {useThemeConfig} from '@docusaurus/theme-common'; import {useAnnouncementBar} from '@docusaurus/theme-common/internal'; import AnnouncementBarCloseButton from '@theme/AnnouncementBar/CloseButton'; import AnnouncementBarContent from '@theme/AnnouncementBar/Content'; -import ThemedImage from '@theme/ThemedImage'; -import useBaseUrl from '@docusaurus/useBaseUrl'; import styles from './styles.module.css'; +import IconBell from '../Icon/Bell'; +import Bordered from '../../components/Bordered'; export default function AnnouncementBar() { const {announcementBar} = useThemeConfig(); @@ -18,13 +18,12 @@ export default function AnnouncementBar() {
-
- -
+ +
+ +
+
{isCloseable && ( 1 && styles.codeBlockLinesWithNumbering, tokens.length === 1 ? 'thin-code' : '' )}> {tokens.map((line, i) => ( @@ -84,7 +84,7 @@ export default function CodeBlockString({ getLineProps={getLineProps} getTokenProps={getTokenProps} classNames={lineClassNames[i]} - showLineNumbers={showLineNumbers} + showLineNumbers={showLineNumbers && tokens.length > 1} /> ))} @@ -95,19 +95,13 @@ export default function CodeBlockString({ {!noReport && ( - + )} {!noCopy && ( - + )}
diff --git a/www/docs/src/theme/CodeBlock/Content/styles.module.css b/www/docs/src/theme/CodeBlock/Content/styles.module.css index fb297d41613a0..3d25cb0888f05 100644 --- a/www/docs/src/theme/CodeBlock/Content/styles.module.css +++ b/www/docs/src/theme/CodeBlock/Content/styles.module.css @@ -1,37 +1,16 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - - .codeBlockContent { +.codeBlockContent { position: relative; /* rtl:ignore */ direction: ltr; border-radius: inherit; } -.codeBlockTitle { - border-bottom: 1px solid var(--ifm-color-emphasis-300); - font-size: var(--ifm-code-font-size); - font-weight: 500; - padding: 0.75rem var(--ifm-pre-padding); - border-top-left-radius: inherit; - border-top-right-radius: inherit; -} - .codeBlock { --ifm-pre-background: var(--prism-background-color); margin: 0; padding: 0; } -.codeBlockTitle + .codeBlockContent .codeBlock { - border-top-left-radius: 0; - border-top-right-radius: 0; -} - .codeBlockStandalone { padding: 0; } @@ -56,25 +35,12 @@ .buttonGroup { display: flex; - column-gap: 0.2rem; + column-gap: 2px; position: absolute; right: var(--ifm-pre-padding); top: var(--ifm-pre-padding); } -.buttonGroup .code-action { - display: flex; - align-items: center; - background: var(--prism-background-color); - color: var(--prism-color); - border: 1px solid var(--ifm-color-emphasis-300); - border-radius: var(--ifm-global-radius); - padding: 0.4rem; - line-height: 0; - transition: opacity 200ms ease-in-out; - opacity: 0; -} - .buttonGroup button:focus-visible, .buttonGroup button:hover { opacity: 1 !important; diff --git a/www/docs/src/theme/CodeBlock/index.js b/www/docs/src/theme/CodeBlock/index.js index d24c7493d612b..6eb79a9b94095 100644 --- a/www/docs/src/theme/CodeBlock/index.js +++ b/www/docs/src/theme/CodeBlock/index.js @@ -37,7 +37,12 @@ export default function CodeBlock({children: rawChildren, noReport = false, noCo {title}
)} - + {children}
diff --git a/www/docs/src/theme/ColorModeToggle/index.js b/www/docs/src/theme/ColorModeToggle/index.js deleted file mode 100644 index 85bb44dd3357c..0000000000000 --- a/www/docs/src/theme/ColorModeToggle/index.js +++ /dev/null @@ -1,104 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import clsx from 'clsx'; -import useIsBrowser from '@docusaurus/useIsBrowser'; -import {useThemeConfig} from '@docusaurus/theme-common'; - -const allowedModes = [ - 'light', - 'dark', - 'auto' -] - -function ColorModeToggle({className, onChange}) { - const isBrowser = useIsBrowser(); - const { colorMode } = useThemeConfig(); - const [storageColorMode, setStorageColorMode] = useState(''); - - useEffect(() => { - if (isBrowser) { - const previousSelected = window.localStorage.getItem('selected-color-mode') || window.localStorage.getItem('theme') - if (previousSelected && allowedModes.includes(previousSelected)) { - setStorageColorMode(previousSelected) - } else if (colorMode.respectPrefersColorScheme) { - setStorageColorMode('auto') - } else { - setStorageColorMode(colorMode.defaultMode || 'light') - } - } - }, [isBrowser]) - - useEffect(() => { - if (isBrowser && storageColorMode === 'auto') { - - function userPreferenceChangedHandler(event) { - onChange(event.matches ? "dark" : "light") - } - - window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', userPreferenceChangedHandler); - - return () => { - window.matchMedia('(prefers-color-scheme: dark)').removeEventListener('change', userPreferenceChangedHandler); - } - } - }, [storageColorMode, isBrowser]) - - function handleAutoOption () { - if (isBrowser) { - onChange(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') - } - } - - function handleColorModeChange(mode) { - if (isBrowser) { - window.localStorage.setItem('selected-color-mode', mode) - setStorageColorMode(mode) - } - - if (mode === 'auto') { - handleAutoOption(); - return; - } - - onChange(mode); - } - - return ( -
- - - - -
- ); -} -export default React.memo(ColorModeToggle); diff --git a/www/docs/src/theme/ColorModeToggle/styles.module.css b/www/docs/src/theme/ColorModeToggle/styles.module.css deleted file mode 100644 index cd82ec5279131..0000000000000 --- a/www/docs/src/theme/ColorModeToggle/styles.module.css +++ /dev/null @@ -1,28 +0,0 @@ -/* .toggle { - width: 2rem; - height: 2rem; -} - -.toggleButton { - -webkit-tap-highlight-color: transparent; - align-items: center; - display: flex; - justify-content: center; - width: 100%; - height: 100%; - border-radius: 50%; - transition: background var(--ifm-transition-fast); -} - -.toggleButton:hover { - background: var(--ifm-color-emphasis-200); -} - -[data-theme='light'] .darkToggleIcon, -[data-theme='dark'] .lightToggleIcon { - display: none; -} - -.toggleButtonDisabled { - cursor: not-allowed; -} */ \ No newline at end of file diff --git a/www/docs/src/theme/DocCard/index.js b/www/docs/src/theme/DocCard/index.js index 9a757fe42a879..bd6fe59d6099e 100644 --- a/www/docs/src/theme/DocCard/index.js +++ b/www/docs/src/theme/DocCard/index.js @@ -9,25 +9,34 @@ import clsx from 'clsx'; import isInternalUrl from '@docusaurus/isInternalUrl'; import styles from './styles.module.css'; import {translate} from '@docusaurus/Translate'; -import ThemedImage from '@theme/ThemedImage'; +import BorderedIcon from '../../components/BorderedIcon'; +import Badge from '../../components/Badge'; +import Icons from '../Icon'; function CardContainer({href, children, className}) { return ( - - {children} - +
+ + {children} + +
); } -function CardLayout({href, icon, title, description, containerClassName}) { + +function CardLayout({href, icon, title, description, html, containerClassName, isSoon = false, badge}) { return ( - - {icon} + +
+ {icon} + {isSoon && Guide coming soon} + {badge && } +
-

+ {title} -

+ {description && (

)} + {html && ( +

+ )}
); } + +function getCardIcon (item) { + if (item.customProps?.themedImage) { + return ( + + ) + } else if (item.customProps?.image) { + return ( + + ); + } else if (item.customProps?.icon) { + return ; + } else if (item.customProps?.iconName && Icons.hasOwnProperty(item.customProps?.iconName)) { + return ; + } else { + return ( +
+ {isInternalUrl(item.href) ? '📄️' : '🔗'} +
+ ); + } +} + function CardCategory({item}) { const href = findFirstCategoryLink(item); + const icon = getCardIcon(item); // Unexpected: categories that don't have a link have been filtered upfront if (!href) { return null; @@ -48,11 +98,11 @@ function CardCategory({item}) { return ( ); } + function CardLink({item}) { - let icon; - if (item.customProps && item.customProps.themedImage) { - icon = ( -
- -
- ) - } else if (item.customProps && item.customProps.image) { - icon = ( -
- {item.label} -
- ); - } else if (item.customProps && item.customProps.icon) { - icon = item.customProps.icon; - } else { - icon = ( -
- {isInternalUrl(item.href) ? '📄️' : '🔗'} -
- ); - } + const icon = getCardIcon(item); const doc = useDocById(item.docId ?? undefined); return ( @@ -97,10 +126,14 @@ function CardLink({item}) { icon={icon} title={item.label} description={item.customProps?.description || doc?.description} + html={item.customProps?.html} containerClassName={item.customProps?.className} + isSoon={item.customProps?.isSoon} + badge={item.customProps?.badge} /> ); } + export default function DocCard({item}) { switch (item.type) { case 'link': diff --git a/www/docs/src/theme/DocCard/styles.module.css b/www/docs/src/theme/DocCard/styles.module.css index fc71a0ec0e081..be7d9a4ae0457 100644 --- a/www/docs/src/theme/DocCard/styles.module.css +++ b/www/docs/src/theme/DocCard/styles.module.css @@ -1,60 +1,51 @@ .cardContainer { - --ifm-link-hover-decoration: none; - --ifm-background-color: #fff; - --ifm-background-color-hover: #F9FAFB; - --ifm-border-color: #E5E7EB; - - background-color: var(--ifm-background-color); - border: 1px solid var(--ifm-border-color) !important; - border-radius: 8px; box-shadow: none !important; transition: all var(--ifm-transition-fast) ease; - transition-property: border, box-shadow; - display: flex; - flex-direction: row; - padding: 16px 24px; + padding: var(--ifm-base-spacing); height: 100%; } -[data-theme="dark"] .cardContainer { - --ifm-background-color-hover: #2D2D2D; - --ifm-background-color: #222222; - --ifm-border-color: #393939; +.cardContainer *:last-child { + margin-bottom: 0; } -.cardContainer:hover { - background-color: var(--ifm-background-color-hover); +.cardContainer:not(.cardSoon):hover { + background-color: var(--ifm-card-bg-hover); } -.cardContainer *:last-child { - margin-bottom: 0; +.cardIconContainer { + margin-bottom: calc(var(--ifm-base-margin-vertical) / 2); + display: flex; + justify-content: space-between; + align-items: center; } .cardTitle { - font-size: 14px; - line-height: 24px; - margin-bottom: 4px; + font-size: var(--medusa-label-regular-plus-size); + line-height: var(--medusa-label-regular-plus-line-height); + font-weight: var(--medusa-label-regular-plus-font-weight); + color: var(--ifm-color-primary); + margin-bottom: calc(var(--ifm-base-margin-vertical) / 4); + display: block; } .cardDescription { - font-size: 14px; - line-height: 24px; + font-size: var(--medusa-label-regular-size); + line-height: var(--medusa-label-regular-line-height); + font-weight: var(--medusa-label-regular-font-weight); color: var(--ifm-color-content); } -.contentContainer { - width: calc(100% - 20px); +.cardTitle, +.cardDescription { + transition: all var(--ifm-transition-fast) ease; } -.cardTitle img { - vertical-align: bottom; - margin-right: 2px; +.contentContainer { + width: calc(100% - 20px); } -.imageContainer { - width: 20px; - height: 20px; - margin-right: 16px; - margin-top: 3px; +.cardSoon { + pointer-events: none; } \ No newline at end of file diff --git a/www/docs/src/theme/DocCardList/index.js b/www/docs/src/theme/DocCardList/index.js index 19a9d7a3d82db..968a419f79dd7 100644 --- a/www/docs/src/theme/DocCardList/index.js +++ b/www/docs/src/theme/DocCardList/index.js @@ -18,9 +18,7 @@ export default function DocCardList(props) { return (
{filteredItems.map((item, index) => ( -
- -
+ ))}
); diff --git a/www/docs/src/theme/DocItem/Layout/index.js b/www/docs/src/theme/DocItem/Layout/index.js index a2a394ce37330..a8b8048b76752 100644 --- a/www/docs/src/theme/DocItem/Layout/index.js +++ b/www/docs/src/theme/DocItem/Layout/index.js @@ -11,6 +11,7 @@ import DocItemTOCDesktop from '@theme/DocItem/TOC/Desktop'; import DocItemContent from '@theme/DocItem/Content'; import DocBreadcrumbs from '@theme/DocBreadcrumbs'; import styles from './styles.module.css'; +import Footer from '@theme/Footer'; /** * Decide if the toc should be rendered, on mobile or desktop viewports */ @@ -45,6 +46,7 @@ export default function DocItemLayout({children}) { +
{docTOC.desktop &&
{docTOC.desktop}
} diff --git a/www/docs/src/theme/DocItem/Layout/styles.module.css b/www/docs/src/theme/DocItem/Layout/styles.module.css index f86b16a3a7676..50a36090bc9a7 100644 --- a/www/docs/src/theme/DocItem/Layout/styles.module.css +++ b/www/docs/src/theme/DocItem/Layout/styles.module.css @@ -1,7 +1,3 @@ -.docItemContainer { - margin-bottom: calc(var(--ifm-base-margin-vertical) * 3); -} - .docItemContainer header + *, .docItemContainer article > *:first-child { margin-top: 0; diff --git a/www/docs/src/theme/DocPage/Layout/Main/index.js b/www/docs/src/theme/DocPage/Layout/Main/index.js new file mode 100644 index 0000000000000..d664f7e653c8d --- /dev/null +++ b/www/docs/src/theme/DocPage/Layout/Main/index.js @@ -0,0 +1,24 @@ +import React from 'react'; +import clsx from 'clsx'; +import {useDocsSidebar} from '@docusaurus/theme-common/internal'; +import styles from './styles.module.css'; + +export default function DocPageLayoutMain({hiddenSidebarContainer, children}) { + const sidebar = useDocsSidebar(); + return ( +
+
+ {children} +
+
+ ); +} diff --git a/www/docs/src/theme/DocPage/Layout/Main/styles.module.css b/www/docs/src/theme/DocPage/Layout/Main/styles.module.css new file mode 100644 index 0000000000000..8ba669e9ec06a --- /dev/null +++ b/www/docs/src/theme/DocPage/Layout/Main/styles.module.css @@ -0,0 +1,22 @@ +.docMainContainer { + display: flex; + flex-direction: column; + width: 100%; +} + +@media (min-width: 997px) { + .docMainContainer { + flex-grow: 1; + max-width: calc(100% - var(--doc-sidebar-width)); + } + + .docMainContainerEnhanced { + max-width: calc(100% - var(--doc-sidebar-hidden-width)); + } + + .docItemWrapperEnhanced { + max-width: calc( + var(--ifm-container-width) + var(--doc-sidebar-width) + ) !important; + } +} diff --git a/www/docs/src/theme/DocPage/Layout/Sidebar/index.js b/www/docs/src/theme/DocPage/Layout/Sidebar/index.js new file mode 100644 index 0000000000000..fc46a150b3463 --- /dev/null +++ b/www/docs/src/theme/DocPage/Layout/Sidebar/index.js @@ -0,0 +1,84 @@ +import React, {useState, useCallback, useRef} from 'react'; +import clsx from 'clsx'; +import {ThemeClassNames} from '@docusaurus/theme-common'; +import {useDocsSidebar} from '@docusaurus/theme-common/internal'; +import {useLocation} from '@docusaurus/router'; +import DocSidebar from '@theme/DocSidebar'; +import ExpandButton from '@theme/DocPage/Layout/Sidebar/ExpandButton'; +import styles from './styles.module.css'; +import { SwitchTransition, CSSTransition } from 'react-transition-group'; +// Reset sidebar state when sidebar changes +// Use React key to unmount/remount the children +// See https://github.com/facebook/docusaurus/issues/3414 +function ResetOnSidebarChange({children}) { + const sidebar = useDocsSidebar(); + return ( + + {children} + + ); +} +export default function DocPageLayoutSidebar({ + sidebar, + hiddenSidebarContainer, + setHiddenSidebarContainer, +}) { + const {pathname} = useLocation(); + const [hiddenSidebar, setHiddenSidebar] = useState(false); + const toggleSidebar = useCallback(() => { + if (hiddenSidebar) { + setHiddenSidebar(false); + } + setHiddenSidebarContainer((value) => !value); + }, [setHiddenSidebarContainer, hiddenSidebar]); + const {name} = useDocsSidebar() + const sidebarRef = useRef(null) + return ( + + ); +} diff --git a/www/docs/src/theme/DocPage/Layout/Sidebar/styles.module.css b/www/docs/src/theme/DocPage/Layout/Sidebar/styles.module.css new file mode 100644 index 0000000000000..004c4340603cc --- /dev/null +++ b/www/docs/src/theme/DocPage/Layout/Sidebar/styles.module.css @@ -0,0 +1,36 @@ +:root { + --doc-sidebar-width: 300px; + --doc-sidebar-hidden-width: 30px; +} + +.docSidebarContainer { + display: none; + + --animate-duration: 0.2s; +} + +@media (min-width: 997px) { + .docSidebarContainer { + display: block; + width: var(--doc-sidebar-width); + /* margin-top: calc(-1 * var(--ifm-navbar-height)); */ + will-change: width; + transition: width var(--ifm-transition-fast) ease; + clip-path: inset(0); + } + + .docSidebarContainerHidden { + width: var(--doc-sidebar-hidden-width); + cursor: pointer; + } + + .sidebarViewportWrapper { + top: var(--ifm-navbar-height); + position: sticky; + } + + .sidebarViewportWrapper, + .sidebarViewportWrapper > div { + max-height: 100vh; + } +} diff --git a/www/docs/src/theme/DocPage/index.js b/www/docs/src/theme/DocPage/index.js new file mode 100644 index 0000000000000..a6d28a9d7a9fe --- /dev/null +++ b/www/docs/src/theme/DocPage/index.js @@ -0,0 +1,63 @@ +import React from 'react'; +import clsx from 'clsx'; +import { + HtmlClassNameProvider, + ThemeClassNames, + PageMetadata, +} from '@docusaurus/theme-common'; +import { + docVersionSearchTag, + DocsSidebarProvider, + DocsVersionProvider, + useDocRouteMetadata, +} from '@docusaurus/theme-common/internal'; +import DocPageLayout from '@theme/DocPage/Layout'; +import NotFound from '@theme/NotFound'; +import SearchMetadata from '@theme/SearchMetadata'; +function DocPageMetadata(props) { + const {versionMetadata} = props; + return ( + <> + + + {versionMetadata.noIndex && ( + + )} + + + ); +} +export default function DocPage(props) { + const {versionMetadata} = props; + const currentDocRouteMetadata = useDocRouteMetadata(props); + if (!currentDocRouteMetadata) { + return ; + } + const {docElement, sidebarName, sidebarItems} = currentDocRouteMetadata; + + return ( + <> + + + + + {docElement} + + + + + ); +} diff --git a/www/docs/src/theme/DocSidebar/Desktop/index.js b/www/docs/src/theme/DocSidebar/Desktop/index.js index c44558bc37a31..7b2ae4a3f3cfb 100644 --- a/www/docs/src/theme/DocSidebar/Desktop/index.js +++ b/www/docs/src/theme/DocSidebar/Desktop/index.js @@ -1,15 +1,12 @@ import React, { useEffect, useRef } from 'react'; import clsx from 'clsx'; import {useThemeConfig} from '@docusaurus/theme-common'; -import Logo from '@theme/Logo'; import CollapseButton from '@theme/DocSidebar/Desktop/CollapseButton'; import Content from '@theme/DocSidebar/Desktop/Content'; import styles from './styles.module.css'; -import DocSidebarItem from '@theme/DocSidebarItem'; -import SearchBar from '../../SearchBar'; import useIsBrowser from '@docusaurus/useIsBrowser'; import AnnouncementBar from '@theme/AnnouncementBar'; -import {useWindowSize} from '@docusaurus/theme-common'; +import {useLocation} from '@docusaurus/router'; function DocSidebarDesktop({path, sidebar, onCollapse, isHidden}) { const { @@ -17,27 +14,26 @@ function DocSidebarDesktop({path, sidebar, onCollapse, isHidden}) { docs: { sidebar: {hideable}, }, - sidebarFooter = [], } = useThemeConfig(); const isBrowser = useIsBrowser() const sidebarRef = useRef(null) - const windowSize = useWindowSize(); + const location = useLocation(); useEffect(() => { if (isBrowser && sidebarRef.current) { function handleScroll () { - if (!sidebarRef.current.classList.contains('scrolling')) { - sidebarRef.current.classList.add('scrolling'); + if (!sidebarRef.current?.classList.contains('scrolling')) { + sidebarRef.current?.classList.add('scrolling'); const intervalId = setInterval(() => { - if (!sidebarRef.current.matches(':hover')) { - sidebarRef.current.classList.remove('scrolling'); + if (!sidebarRef.current?.matches(':hover')) { + sidebarRef.current?.classList.remove('scrolling'); clearInterval(intervalId); } }, 300) } } - const navElement = sidebarRef.current.querySelector('nav'); + const navElement = sidebarRef.current.querySelector('.main-sidebar'); navElement.addEventListener('scroll', handleScroll); return () => { @@ -46,6 +42,33 @@ function DocSidebarDesktop({path, sidebar, onCollapse, isHidden}) { } }, [isBrowser, sidebarRef.current]) + useEffect(() => { + const navElement = sidebarRef.current.querySelector('.main-sidebar'), + navElementBoundingRect = navElement.getBoundingClientRect(); + + //logic to scroll to current active item + const activeItem = document.querySelector('.sidebar-desktop [aria-current=page]') + + if (!activeItem) { + return + } + + const activeItemBoundingReact = activeItem.getBoundingClientRect(), + //the extra 160 is due to the sticky elements in the sidebar + isActiveItemVisible = activeItemBoundingReact.top >= 0 && activeItemBoundingReact.bottom + 160 <= navElementBoundingRect.height + + if (!isActiveItemVisible) { + const elementToScrollTo = activeItem, + elementBounding = elementToScrollTo.getBoundingClientRect() + //scroll to element + navElement.scroll({ + //the extra 160 is due to the sticky elements in the sidebar + top: elementBounding.top - navElementBoundingRect.top + navElement.scrollTop - 160, + behaviour: 'smooth' + }) + } + }, [location]) + return (
- {hideOnScroll && } -
- {windowSize !== 'mobile' && } -
- - {sidebarFooter.length > 0 && ( -
    - {sidebarFooter.map((item, index) => ( - - ))} -
- )} + {hideable && }
); diff --git a/www/docs/src/theme/DocSidebar/Desktop/styles.module.css b/www/docs/src/theme/DocSidebar/Desktop/styles.module.css index 000221175d4b8..f75b86c61f917 100644 --- a/www/docs/src/theme/DocSidebar/Desktop/styles.module.css +++ b/www/docs/src/theme/DocSidebar/Desktop/styles.module.css @@ -6,9 +6,8 @@ height: 100%; position: sticky; top: 0; - padding-top: var(--ifm-navbar-height); - width: var(--doc-sidebar-width); transition: opacity 50ms ease; + padding-top: calc(var(--ifm-base-spacing) * 1.5); } .sidebarWithHideableNavbar { @@ -25,34 +24,15 @@ .sidebarLogo { display: flex !important; align-items: center; - margin: 0 var(--ifm-navbar-padding-horizontal); - min-height: var(--ifm-navbar-height); - max-height: var(--ifm-navbar-height); + margin: 18px 0; color: inherit !important; text-decoration: none !important; + width: fit-content; + padding-left: var(--doc-sidebar-padding); + padding-right: var(--doc-sidebar-padding); } .sidebarLogo img { - margin-right: 0.5rem; - height: 2rem; + height: var(--ifm-logo-height); } -} - -.sidebarLogo { - display: none; -} - -.sidebarFooterList { - border-top: 1px solid var(--ifm-toc-border-color); - list-style: none; - padding-top: 1.7em; - padding-left: 0; -} - -.sidebarFooterList li a { - padding-left: 1.8em !important; -} - -.sidebarSearchContainer { - margin: 24px 16px 24px; } \ No newline at end of file diff --git a/www/docs/src/theme/DocSidebarItem/Category/index.js b/www/docs/src/theme/DocSidebarItem/Category/index.js new file mode 100644 index 0000000000000..75d5110d1c0d7 --- /dev/null +++ b/www/docs/src/theme/DocSidebarItem/Category/index.js @@ -0,0 +1,195 @@ +import React, {useEffect, useMemo} from 'react'; +import clsx from 'clsx'; +import { + ThemeClassNames, + useThemeConfig, + usePrevious, + useCollapsible, + Collapsible +} from '@docusaurus/theme-common'; +import { + isActiveSidebarItem, + findFirstCategoryLink, + useDocSidebarItemsExpandedState, + isSamePath, +} from '@docusaurus/theme-common/internal'; +import Link from '@docusaurus/Link'; +import {translate} from '@docusaurus/Translate'; +import useIsBrowser from '@docusaurus/useIsBrowser'; +import DocSidebarItems from '@theme/DocSidebarItems'; +import DocSidebarItemIcon from '../Icon'; + +// If we navigate to a category and it becomes active, it should automatically +// expand itself +function useAutoExpandActiveCategory({isActive, collapsed, updateCollapsed}) { + const wasActive = usePrevious(isActive); + useEffect(() => { + const justBecameActive = isActive && !wasActive; + if (justBecameActive && collapsed) { + updateCollapsed(false); + } + }, [isActive, wasActive, collapsed, updateCollapsed]); +} +/** + * When a collapsible category has no link, we still link it to its first child + * during SSR as a temporary fallback. This allows to be able to navigate inside + * the category even when JS fails to load, is delayed or simply disabled + * React hydration becomes an optional progressive enhancement + * see https://github.com/facebookincubator/infima/issues/36#issuecomment-772543188 + * see https://github.com/facebook/docusaurus/issues/3030 + */ +function useCategoryHrefWithSSRFallback(item) { + const isBrowser = useIsBrowser(); + return useMemo(() => { + if (item.href) { + return item.href; + } + // In these cases, it's not necessary to render a fallback + // We skip the "findFirstCategoryLink" computation + if (isBrowser || !item.collapsible) { + return undefined; + } + return findFirstCategoryLink(item); + }, [item, isBrowser]); +} +function CollapseButton({categoryLabel, onClick}) { + return ( +