docs: create docs workspace (#5174)
* docs: migrate ui docs to docs universe * created yarn workspace * added eslint and tsconfig configurations * fix eslint configurations * fixed eslint configurations * shared tailwind configurations * added shared ui package * added more shared components * migrating more components * made details components shared * move InlineCode component * moved InputText * moved Loading component * Moved Modal component * moved Select components * Moved Tooltip component * moved Search components * moved ColorMode provider * Moved Notification components and providers * used icons package * use UI colors in api-reference * moved Navbar component * used Navbar and Search in UI docs * added Feedback to UI docs * general enhancements * fix color mode * added copy colors file from ui-preset * added features and enhancements to UI docs * move Sidebar component and provider * general fixes and preparations for deployment * update docusaurus version * adjusted versions * fix output directory * remove rootDirectory property * fix yarn.lock * moved code component * added vale for all docs MD and MDX * fix tests * fix vale error * fix deployment errors * change ignore commands * add output directory * fix docs test * general fixes * content fixes * fix announcement script * added changeset * fix vale checks * added nofilter option * fix vale error
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
---
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# Discount Generator
|
||||
|
||||
In this document, you’ll learn how to install the Discount Generator plugin on your Medusa backend.
|
||||
|
||||
## Overview
|
||||
|
||||
In Medusa, merchants can create dynamic discounts that act as a template for other discounts. With dynamic discounts, merchants don't have to repeat certain conditions every time they want to create a new discount.
|
||||
|
||||
The discount generator plugin allows merchants and developers to generate new discounts from a dynamic discount. This can be done either by envoking the `/discount-code` endpoint or using the `DiscountGeneratorService`.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you follow this guide, you must have a Medusa backend installed. If not, you can follow the [quickstart guide](../../create-medusa-app.mdx) to learn how to do it.
|
||||
|
||||
---
|
||||
|
||||
## Install Plugin
|
||||
|
||||
In the directory of your Medusa backend, run the following command to install the plugin:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install medusa-plugin-discount-generator
|
||||
```
|
||||
|
||||
Finally, add the plugin to the `plugins` array in `medusa-config.js`:
|
||||
|
||||
```js title=medusa-config.js
|
||||
const plugins = [
|
||||
// ...
|
||||
{
|
||||
resolve: `medusa-plugin-discount-generator`,
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Test the Plugin
|
||||
|
||||
### Using the Endpoint
|
||||
|
||||
The plugin registers a `POST` endpoint `/discount-code`. The endpoint accepts in the request body the parameter `discount_code` which is a string indicating the code of the dynamic discount to generate a new discount from. The endpoint then creates the new discount from the dynamic discount and returns it in the response.
|
||||
|
||||
So, to test out the endpoint, run the following command in the root of your project to start the Medusa backend:
|
||||
|
||||
```bash
|
||||
npx medusa develop
|
||||
```
|
||||
|
||||
Then, create a dynamic discount. You can do that either using the [Medusa admin](../../user-guide/discounts/create.mdx) which is available (if installed) at `http://localhost:7001` after starting the backend, or using the [Admin REST APIs](../../modules/discounts/admin/manage-discounts.mdx).
|
||||
|
||||
After that, send a `POST` request to the `/discount-code` endpoint, passing the `discount_code` parameter in the request body with the value being the code of the dynamic discount you just created. A new discount will be created with the same attributes as the dynamic discount code and returned in the response.
|
||||
|
||||
### Using the DiscountGeneratorService
|
||||
|
||||
After installing the plugin, the `DiscountGeneratorService` is registered in the [dependency container](../../development/fundamentals/dependency-injection.md). So, you can resolve and use it in custom services, endpoints, or other resources.
|
||||
|
||||
The `DiscountGeneratorService` has one method `generateDiscount`. This method requires passing the code of a dynamic discount as a parameter. It then creates a new discount having the same attributes as the dynamic discount, but with a different, random code.
|
||||
|
||||
Here's an example of using the service in an endpoint:
|
||||
|
||||
```ts title=src/api/index.ts
|
||||
import { Request, Response, Router } from "express"
|
||||
import bodyParser from "body-parser"
|
||||
|
||||
export default (rootDirectory: string): Router | Router[] => {
|
||||
const router = Router()
|
||||
|
||||
router.use(
|
||||
"/generate-discount-code",
|
||||
bodyParser.json(),
|
||||
async (req: Request, res: Response) => {
|
||||
// skipping validation for simplicity
|
||||
const { dynamicCode } = req.body
|
||||
const discountGenerator = req.scope.resolve(
|
||||
"discountGeneratorService"
|
||||
)
|
||||
const code = await discountGenerator.generateDiscount(
|
||||
dynamicCode
|
||||
)
|
||||
|
||||
res.json({
|
||||
code,
|
||||
})
|
||||
})
|
||||
|
||||
return router
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,7 @@
|
||||
import DocCardList from '@theme/DocCardList';
|
||||
|
||||
# Other Plugins
|
||||
|
||||
Check the [Community Plugins Library](https://medusajs.com/plugins/?filters=Other&categories=Other&categories=Source) for more plugins.
|
||||
|
||||
<DocCardList />
|
||||
@@ -0,0 +1,143 @@
|
||||
---
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# IP Lookup (ipstack) Plugin
|
||||
|
||||
In this document, you’ll learn how to install the IP Lookup plugin on your Medusa backend.
|
||||
|
||||
## Overview
|
||||
|
||||
Location detection in a commerce store is essential for multi-region support. Medusa provides an IP Lookup plugin that integrates the backend with [ipstack](https://ipstack.com/) to allow you to detect a customer’s location and, ultimately, their region.
|
||||
|
||||
This guide explains how you can install and use this plugin.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Medusa Backend
|
||||
|
||||
Before you follow this guide, you must have a Medusa backend installed. If not, you can follow the [quickstart guide](../../create-medusa-app.mdx) to learn how to do it.
|
||||
|
||||
### ipstack Account
|
||||
|
||||
You need an [ipstack account](https://ipstack.com/) before using this plugin. You can create a free account with ipstack on their website.
|
||||
|
||||
---
|
||||
|
||||
## Install Plugin
|
||||
|
||||
In the root directory of your Medusa backend, run the following command to install the IP Lookup plugin:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install medusa-plugin-ip-lookup
|
||||
```
|
||||
|
||||
Then, add the following environment variable in `.env`:
|
||||
|
||||
```bash
|
||||
IPSTACK_ACCESS_KEY=<YOUR_ACCESS_KEY>
|
||||
```
|
||||
|
||||
Where `<YOUR_ACCESS_KEY>` is your ipstack account’s access key. It’s available in your ipstack dashboard.
|
||||
|
||||
Finally, add the IP lookup plugin into the plugins array exported as part of the Medusa configuration in `medusa-config.js`:
|
||||
|
||||
```js title=medusa-config.js
|
||||
const plugins = [
|
||||
// other plugins...
|
||||
{
|
||||
resolve: `medusa-plugin-ip-lookup`,
|
||||
options: {
|
||||
access_token: process.env.IPSTACK_ACCESS_KEY,
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Test the Plugin
|
||||
|
||||
The plugin provides two resources: the `IpLookupService` and the `preCartCreation` middleware.
|
||||
|
||||
:::note
|
||||
|
||||
Due to how Express resolves the current IP when accessing your website from `localhost`, you won’t be able to test the plugin locally. You can either use tools like ngrok to expose the `9000` port to be accessed publicly, or you have to test it on a deployed backend.
|
||||
|
||||
:::
|
||||
|
||||
### IpLookupService
|
||||
|
||||
The `IpLookupService` can be used in other services, endpoints, or resources to get the user’s location by their IP address. It has only one method `lookupIp` that accepts the IP address as a parameter, sends a request to ipstack’s API, and returns the retrieved result.
|
||||
|
||||
For example, you can use the `IpLookupService` in a custom endpoint and return the user’s region:
|
||||
|
||||
:::tip
|
||||
|
||||
You can learn more about creating an endpoint [here](../../development/endpoints/create.mdx).
|
||||
|
||||
:::
|
||||
|
||||
```ts title=src/api/index.ts
|
||||
import { Request, Response, Router } from "express"
|
||||
|
||||
export default (rootDirectory: string): Router | Router[] => {
|
||||
const router = Router()
|
||||
// ...
|
||||
router.get(
|
||||
"/store/customer-region",
|
||||
async (req: Request, res: Response) => {
|
||||
const ipLookupService = req.scope.resolve(
|
||||
"ipLookupService"
|
||||
)
|
||||
const regionService = req.scope.resolve<RegionService>(
|
||||
"regionService"
|
||||
)
|
||||
|
||||
const ip = req.headers["x-forwarded-for"] ||
|
||||
req.socket.remoteAddress
|
||||
|
||||
const { data } = await ipLookupService.lookupIp(ip)
|
||||
|
||||
if (!data.country_code) {
|
||||
throw new Error ("Couldn't detect country code.")
|
||||
}
|
||||
|
||||
const region = await regionService
|
||||
.retrieveByCountryCode(data.country_code)
|
||||
|
||||
res.json({
|
||||
region,
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### preCartCreation
|
||||
|
||||
The `preCartCreation` middleware can be added as a middleware to any route to attach the region ID to that route based on the user’s location. For example, you can use it on the Create Cart endpoint to ensure that the user’s correct region is attached to the cart.
|
||||
|
||||
For example, you can attach it to all `/store` routes to ensure the customer’s region is always detected:
|
||||
|
||||
<!-- eslint-disable @typescript-eslint/no-var-requires -->
|
||||
|
||||
```ts title=src/api/index.ts
|
||||
import { Router } from "express"
|
||||
|
||||
const { preCartCreation } = require(
|
||||
"medusa-plugin-ip-lookup/api/medusa-middleware"
|
||||
).default
|
||||
|
||||
export default (
|
||||
rootDirectory: string
|
||||
): Router | Router[] => {
|
||||
const router = Router()
|
||||
// ...
|
||||
router.use("/store", preCartCreation)
|
||||
|
||||
return router
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,177 @@
|
||||
---
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# Restock Notifications Plugin
|
||||
|
||||
In this document, you’ll learn how to install the restock notification plugin on your Medusa backend.
|
||||
|
||||
:::note
|
||||
|
||||
This plugin doesn't actually implement the sending of the notification, only the required implementation to trigger restock events and allow customers to subscribe to product variants' stock status. To send the notification, you need to use a [notification plugin](../notifications/).
|
||||
|
||||
:::
|
||||
|
||||
## Overview
|
||||
|
||||
Customers browsing your products may find something that they need, but it's unfortunately out of stock. In this scenario, you can keep them interested in your product and, subsequently, in your store by notifying them when the product is back in stock.
|
||||
|
||||
The Restock Notifications plugin provides new endpoints that allow the customer to subscribe to restock notifications of a specific product variant. It also triggers the `restock-notification.restocked` event whenever a product variant's stock quantity is above a specified threshold. The event's payload includes the ID of the product variant and the customer emails subscribed to it. You can pair this with a subscriber that listens to that event and sends a notification to the customer using a [Notification plugin](../notifications/).
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Medusa Backend
|
||||
|
||||
Before you follow this guide, you must have a Medusa backend installed. If not, you can follow the [quickstart guide](../../create-medusa-app.mdx) to learn how to do it.
|
||||
|
||||
### Event-Bus Module
|
||||
|
||||
To trigger events to the subscribed handler methods, you must have an event-bus module installed. For development purposes, you can use the [Local module](../../development/events/modules/local.md) which should be enabled by default in your Medusa backend.
|
||||
|
||||
For production, it's recommended to use the [Redis module](../../development/events/modules/redis.md).
|
||||
|
||||
---
|
||||
|
||||
## Install Plugin
|
||||
|
||||
In the root directory of your Medusa backend, run the following command to install the Restock Notifications plugin:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install medusa-plugin-restock-notification
|
||||
```
|
||||
|
||||
Then, add the plugin into the plugins array exported as part of the Medusa configuration in `medusa-config.js`:
|
||||
|
||||
```js title=medusa-config.js
|
||||
const plugins = [
|
||||
// other plugins...
|
||||
{
|
||||
resolve: `medusa-plugin-restock-notification`,
|
||||
options: {
|
||||
// optional options
|
||||
trigger_delay, // delay time in milliseconds
|
||||
inventory_required, // minimum restock inventory quantity
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
The plugin accepts the following optional options:
|
||||
|
||||
1. `trigger_delay`: a number indicating the time in milliseconds to delay the triggering of the `restock-notification.restocked` event. Default value is `0`.
|
||||
2. `inventory_required`: a number indicating the minimum inventory quantity to consider a product variant as restocked. Default value is `0`.
|
||||
|
||||
Finally, run the migrations of this plugin before you start the Medusa backend:
|
||||
|
||||
```bash
|
||||
npx medusa migrations run
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Test Plugin
|
||||
|
||||
### 1. Run Medusa Backend
|
||||
|
||||
In the root of your Medusa backend project, run the following command to start the Medusa backend:
|
||||
|
||||
```bash npm2yarn
|
||||
npm run start
|
||||
```
|
||||
|
||||
### 2. Subscribe to Variant Restock Notifications
|
||||
|
||||
Then, send a `POST` request to the endpoint `<BACKEND_URL>/restock-notifications/variants/<VARIANT_ID>` to subscribe to restock notifications of a product variant ID. Note that `<BACKEND_URL>` refers to the URL fo your Medusa backend, which is `http://localhost:9000` during development, and `<VARIANT_ID>` refers to the ID of the product variant you're subscribing to.
|
||||
|
||||
:::note
|
||||
|
||||
You can only subscribe to product variants that are out-of-stock. Otherwise, you'll receive an error.
|
||||
|
||||
:::
|
||||
|
||||
The endpoint accepts the following request body parameters:
|
||||
|
||||
1. `email`: a string indicating the email that is subscribing to the product variant's restock notification.
|
||||
2. `sales_channel_id`: an optional string indicating the ID of the sales channel to check the stock quantity in when subscribing. This is useful if you're using multi-warehouse modules, as the product variant's quantity is checked correctly when checking if it's out of stock. Alternatively, you can pass the [publishable API key in the header of the request](../../development/publishable-api-keys/storefront/use-in-requests.md) and the sales channel will be derived from it.
|
||||
|
||||
### 3. Trigger Restock Notification
|
||||
|
||||
After subscribing to the out-of-stock variant, change its stock quantity to the minimum inventory required to test out the event trigger. The new stock quantity should be any value above `0` if you didn't set the `inventory_required` option.
|
||||
|
||||
You can use the [Medusa admin](../../user-guide/products/manage.mdx#manage-product-variants) or the [Admin REST API endpoints](https://docs.medusajs.com/api/admin#products_postproductsproductvariantsvariant) to update the quantity.
|
||||
|
||||
After you update the quantity, you can see the `restock-notification.restocked` triggered and logged in the Medusa backend logs. If you've implemented the notification sending, this is where it'll be triggered and a notification will be sent.
|
||||
|
||||
---
|
||||
|
||||
## Example: Implement Notification Sending with SendGrid
|
||||
|
||||
:::note
|
||||
|
||||
The SendGrid plugin already listens to and handles the `restock-notification.restocked` event. So, if you install it you don't need to manually create a subscriber that handles this event as explained here. This example is only provided for reference on how you can send a notification to the customer using a Notication plugin.
|
||||
|
||||
:::
|
||||
|
||||
Here's an example of a subscriber that listens to the `restock-notification.restocked` event and uses the [SendGrid plugin](../notifications/sendgrid.mdx) to send the subscribed customers an email:
|
||||
|
||||
```ts title=src/subscribers/restock-notification.ts
|
||||
import {
|
||||
EventBusService,
|
||||
ProductVariantService,
|
||||
} from "@medusajs/medusa"
|
||||
|
||||
type InjectedDependencies = {
|
||||
eventBusService: EventBusService,
|
||||
sendgridService: any
|
||||
productVariantService: ProductVariantService
|
||||
}
|
||||
|
||||
class RestockNotificationSubscriber {
|
||||
protected sendGridService_: any
|
||||
protected productVariantService_: ProductVariantService
|
||||
|
||||
constructor({
|
||||
eventBusService,
|
||||
sendgridService,
|
||||
productVariantService,
|
||||
}: InjectedDependencies) {
|
||||
this.sendGridService_ = sendgridService
|
||||
this.productVariantService_ = productVariantService
|
||||
eventBusService.subscribe(
|
||||
"restock-notification.restocked",
|
||||
this.handleRestockNotification
|
||||
)
|
||||
}
|
||||
|
||||
handleRestockNotification = async ({
|
||||
variant_id,
|
||||
emails,
|
||||
}) => {
|
||||
// retrieve variant
|
||||
const variant = await this.productVariantService_.retrieve(
|
||||
variant_id
|
||||
)
|
||||
|
||||
this.sendGridService_.sendEmail({
|
||||
templateId: "restock-notification",
|
||||
from: "hello@medusajs.com",
|
||||
to: emails,
|
||||
dynamic_template_data: {
|
||||
// any data necessary for your template...
|
||||
variant,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default RestockNotificationSubscriber
|
||||
```
|
||||
|
||||
Handler methods subscribed to the `restock-notification.restocked` event, which in this case is the `handleRestockNotification` method, receive the following object data payload as a parameter:
|
||||
|
||||
- `variant_id`: The ID of the variant that has been restocked.
|
||||
- `emails`: An array of strings indicating the email addresses subscribed to the restocked variant. Here, you pass it along to the SendGrid plugin directly to send the email to everyone subscribed. If necessary, you can also retrieve the customer of that email using the `CustomerService`'s [retrieveByEmail](../../references/services/classes/CustomerService.md#retrievebyemail) method.
|
||||
|
||||
In the method, you retrieve the variant by its ID using the `ProductVariantService`, then send the email using the SendGrid plugins' `SendGridService`.
|
||||
@@ -0,0 +1,96 @@
|
||||
---
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# Wishlist Plugin
|
||||
|
||||
In this document, you’ll learn how to install the Wishlist plugin on your Medusa backend.
|
||||
|
||||
## Overview
|
||||
|
||||
A wishlist allows customers to save items they like so they can browse and purchase them later. Medusa's wishlist plugin provides the following features:
|
||||
|
||||
- Allow a customer to manage their wishlist, including adding or deleting items.
|
||||
- Allow a customer to share their wishlist with others using a token.
|
||||
|
||||
:::tip
|
||||
|
||||
Items in the wishlist are added as line items. This allows you to implement functionalities like moving an item from the wishlist to the cart, although this is not implemented by the plugin.
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you follow this guide, you must have a Medusa backend installed. If not, you can follow the [quickstart guide](../../create-medusa-app.mdx) to learn how to do it.
|
||||
|
||||
---
|
||||
|
||||
## Install Plugin
|
||||
|
||||
In the directory of your Medusa backend, run the following command to install the plugin:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install medusa-plugin-wishlist
|
||||
```
|
||||
|
||||
Finally, add the plugin to the `plugins` array in `medusa-config.js`:
|
||||
|
||||
```js title=medusa-config.js
|
||||
const plugins = [
|
||||
// ...
|
||||
{
|
||||
resolve: `medusa-plugin-wishlist`,
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Test the Plugin
|
||||
|
||||
Before testing the plugin, run the following command in the directory of the Medusa backend to start the backend:
|
||||
|
||||
```bash
|
||||
npx medusa develop
|
||||
```
|
||||
|
||||
The plugin exposes four endpoints.
|
||||
|
||||
### Add Item to Wishlist Endpoint
|
||||
|
||||
The `POST` endpoint at `/store/customer/<CUSTOMER_ID>/wishlist` allows customers to add items to their existing or new wishlist, where `<CUSTOMER_ID>` is the ID of the customer. It accepts the following body parameters:
|
||||
|
||||
- `variant_id`: a string indicating the ID of the product variant to add to the wishlist.
|
||||
- `quantity`: (optional) a number indicating the quantity of the product variant.
|
||||
- `metadata`: (optional) any metadata to attach to the wishlist item.
|
||||
|
||||
The request returns the full customer object. The wishlist is available at `customer.metadata.wishlist`, where its value is an array of items.
|
||||
|
||||
### Delete Item from Wishlist Endpoint
|
||||
|
||||
The `DELETE` endpoint at `/store/customer/<CUSTOMER_ID>/wishlist` allows customers to delete items from their wishlist, where `<CUSTOMER_ID>` is the ID of the customer.
|
||||
|
||||
The endpoint accepts one request body parameter `index`, which indicates the index of the item in the `customer.metadata.wishlist` array.
|
||||
|
||||
The request returns the full customer object. The wishlist is available at `customer.metadata.wishlist`, where its value is an array of items.
|
||||
|
||||
#### Generate Share Token Endpoint
|
||||
|
||||
The `POST` endpoint at `/store/customer/<CUSTOMER_ID>/wishlist/share-token` allows customers to retrieve a token that can be used to access the wishlist, where `<CUSTOMER_ID>` is the ID of the customer.
|
||||
|
||||
The endpoint doesn't accept any request body parameters.
|
||||
|
||||
The request returns an object in the response having the property `share_token`, being the token that can be used to access the wishlist.
|
||||
|
||||
#### Access Wishlist with Token Endpoint
|
||||
|
||||
The `GET` endpoint at `/wishlists/<TOKEN>` allows anyone to access the wishlist using its token, where `<TOKEN>` is the token retrieved from the [Generate Share Token Endpoint](#generate-share-token-endpoint).
|
||||
|
||||
The endpoint doesn't accept any request body parameters.
|
||||
|
||||
The request returns an object in the response having the following properties:
|
||||
|
||||
- `items`: an array of objects, each being an item in the wishlist.
|
||||
- `first_name`: a string indicating the first name of the customer that this wishlist belongs to.
|
||||
Reference in New Issue
Block a user