docs: integrate Vale for documentation linting (#2242)
* added value rules * resolved errors raised by vale * added github action * fixes to github action * added details in contribution guidelines * added rule for numbers * limited checks to errors
This commit is contained in:
1 parent
d0d789b6d4
commit
6adaf56c73
103 files changed
+2408
-832
No files matched your search
@@ -1,4 +1,4 @@
|
||||
name: Docusaurus Documentation Test
|
||||
name: Documentation Tests
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
@@ -34,3 +34,29 @@ jobs:
|
||||
cd www/docs
|
||||
yarn install
|
||||
yarn build
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.9.1
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2.3.5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get Directories to Scan
|
||||
working-directory: docs
|
||||
run: ./get-files.sh
|
||||
id: directories
|
||||
|
||||
- name: Vale Linter
|
||||
uses: errata-ai/vale-action@reviewdog
|
||||
with:
|
||||
files: ${{ steps.directories.outputs.LIST }}
|
||||
fail_on_error: true
|
||||
vale_flags: '--minAlertLevel=error'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
@@ -0,0 +1,17 @@
|
||||
StylesPath = docs/styles
|
||||
|
||||
MinAlertLevel = suggestion
|
||||
Vocab = Base
|
||||
|
||||
Packages = write-good
|
||||
|
||||
[*.{md,mdx}]
|
||||
BasedOnStyles = Vale, write-good, docs
|
||||
Vale.Spelling=warning
|
||||
write-good.E-Prime=No
|
||||
write-good.So=No
|
||||
write-good.ThereIs=No
|
||||
Vale.Terms=No
|
||||
|
||||
[formats]
|
||||
mdx = md
|
||||
@@ -14,7 +14,7 @@ Through Medusa's flexible plugin system, it is possible to add a search engine t
|
||||
|
||||
### Medusa Components
|
||||
|
||||
It is required to have a Medusa server installed before starting with this documentation. If not, please follow along with our [quickstart guide](../quickstart/quick-start.md) to get started in minutes.
|
||||
It is required to have a Medusa server installed before starting with this documentation. If not, please follow along with the [quickstart guide](../quickstart/quick-start.md) to get started in minutes.
|
||||
|
||||
Furthermore, it’s highly recommended to ensure your Medusa server is configured to work with Redis. As Medusa uses Redis for the event queue internally, configuring Redis ensures that the search indices in Algolia are updated whenever products on the Medusa server are updated. You can follow [this documentation to install Redis](../tutorial/0-set-up-your-development-environment.mdx#redis) and then [configure it on your Medusa server](../usage/configurations.md#redis).
|
||||
|
||||
|
||||
@@ -227,13 +227,13 @@ export const query = graphql`
|
||||
To test this out, run your Medusa server by running this command in its directory:
|
||||
|
||||
```bash
|
||||
npm start
|
||||
npm run start
|
||||
```
|
||||
|
||||
Then run the Gatsby storefront by running this command in its directory:
|
||||
|
||||
```bash
|
||||
npm start
|
||||
npm run start
|
||||
```
|
||||
|
||||
This runs the Gatsby storefront on `localhost:8000`. Go to the storefront in your browser and open the About page. You should see the Rich Text content you added.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Contentful
|
||||
|
||||
In this document, you’ll learn how to integrate a Medusa server with Contentful to add rich CMS functionalities
|
||||
In this document, you’ll learn how to integrate a Medusa server with Contentful to add rich Content Management System (CMS) functionalities
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -36,7 +36,7 @@ This installs a new Medusa server in the directory `medusa-contentful`.
|
||||
|
||||
### Add Contentful Environment Variables
|
||||
|
||||
Change to the `medusa-contentful` directory. In `.env` you’ll find 3 variables:
|
||||
Change to the `medusa-contentful` directory. In `.env` you’ll find three variables:
|
||||
|
||||
```bash
|
||||
CONTENTFUL_SPACE_ID=
|
||||
@@ -172,7 +172,7 @@ npm run seed
|
||||
To start the server run the following command:
|
||||
|
||||
```bash
|
||||
npm start
|
||||
npm run start
|
||||
```
|
||||
|
||||
If you seeded the database with demo data, you should see that events related to the products are triggered.
|
||||
@@ -257,7 +257,7 @@ You should find the field "Content Delivery API - access token”. Copy its valu
|
||||
Make sure the Medusa server is still running. Then, start the storefront:
|
||||
|
||||
```bash
|
||||
npm start
|
||||
npm run start
|
||||
```
|
||||
|
||||
This starts the storefront at `localhost:8000`. Open it in your browser and you should see on the homepage the Featured Product section with the products you chose on Contentful.
|
||||
|
||||
@@ -10,19 +10,19 @@ By integrating Mailchimp with Medusa, customers will be able to subscribe from M
|
||||
|
||||
:::note
|
||||
|
||||
This plugin is only used to allow your customers to subscribe but does not actually do any email sending. If you want to send emails to customers based on specific events, for example, when an order is placed, you should check out our [SendGrid plugin](./sendgrid.mdx) instead.
|
||||
This plugin is only used to allow your customers to subscribe but does not actually do any email sending. If you want to send emails to customers based on specific events, for example, when an order is placed, you should check out the [SendGrid plugin](./sendgrid.mdx) instead.
|
||||
|
||||
:::
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before going further with this guide make sure you have a Medusa server set up. You can follow our [Quickstart guide](https://docs.medusajs.com/quickstart/quick-start).
|
||||
Before going further with this guide make sure you have a Medusa server set up. You can follow the [Quickstart guide](https://docs.medusajs.com/quickstart/quick-start).
|
||||
|
||||
You also need a Mailchimp account, so please [create one](https://mailchimp.com/signup) before you start.
|
||||
|
||||
## Obtain Mailchimp Keys
|
||||
|
||||
To integrate the plugin into Medusa you need 2 keys: The API Key and the Newsletter list or Audience ID. The API Key acts as a credential for your account, whereas the Newsletter list ID determines which audience should the subscribed customers be added to.
|
||||
To integrate the plugin into Medusa you need two keys: The API Key and the Newsletter list or Audience ID. The API Key acts as a credential for your account, whereas the Newsletter list ID determines which audience should the subscribed customers be added to.
|
||||
|
||||
You can follow [this guide](https://mailchimp.com/help/about-api-keys/#Find_or_generate_your_API_key) from Mailchimp’s documentation to obtain an API Key.
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ Through Medusa's flexible plugin system, it is possible to add a search engine t
|
||||
|
||||
### Medusa Components
|
||||
|
||||
It is required to have a Medusa server installed before starting with this documentation. If not, please follow along with our [quickstart guide](../quickstart/quick-start.md) to get started in minutes.
|
||||
It is required to have a Medusa server installed before starting with this documentation. If not, please follow along with the [quickstart guide](../quickstart/quick-start.md) to get started in minutes.
|
||||
|
||||
Furthermore, it’s highly recommended to ensure your Medusa server is configured to work with Redis. As Medusa uses Redis for the event queue internally, configuring Redis ensures that the search indices in MeiliSearch are updated whenever products on the Medusa server are updated. You can follow [this documentation to install Redis](../tutorial/0-set-up-your-development-environment.mdx#redis) and then [configure it on your Medusa server](../usage/configurations.md#redis).
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@ In addition, you need to configure a webhook listener on your PayPal Developer D
|
||||
|
||||
Webhooks are used in scenarios where the customer might leave the page during the authorization and before the checkout flow is fully complete. It will then create the order or swap after the payment is authorized if they weren’t created
|
||||
|
||||
Additionally, you need a Medusa server installed and set up. If not, you can follow our [quickstart guide](https://docs.medusajs.com/quickstart/quick-start) to get started.
|
||||
Additionally, you need a Medusa server installed and set up. If not, you can follow the [quickstart guide](https://docs.medusajs.com/quickstart/quick-start) to get started.
|
||||
|
||||
You also need [Medusa Admin](../admin/quickstart.md) installed to enable PayPal as a payment provider. You can alternatively use our [REST APIs](https://docs.medusajs.com/api/admin).
|
||||
You also need [Medusa Admin](../admin/quickstart.md) installed to enable PayPal as a payment provider. You can alternatively use the [REST APIs](https://docs.medusajs.com/api/admin).
|
||||
|
||||
## Medusa Server
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ The Create Bucket form will open. In the General Configuration section enter a n
|
||||
|
||||

|
||||
|
||||
Next, in the Object Ownership section, choose ACLs enabled. Then, 2 radio buttons will show below it. Choose Bucket owner preferred.
|
||||
Next, in the Object Ownership section, choose ACLs enabled. Then, two radio buttons will show below it. Choose Bucket owner preferred.
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ const plugins = [
|
||||
Run your server with the following command:
|
||||
|
||||
```bash npm2yarn
|
||||
npm start
|
||||
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.md) or [Gatsby](../starters/gatsby-medusa-starter.md) storefronts.
|
||||
|
||||
@@ -22,7 +22,7 @@ By integrating SendGrid with Medusa, you’ll be sending email notifications to
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before going further with this guide make sure you have a Medusa server set up. You can follow our [Quickstart guide](../quickstart/quick-start.md).
|
||||
Before going further with this guide make sure you have a Medusa server set up. You can follow the [Quickstart guide](../quickstart/quick-start.md).
|
||||
|
||||
You also must have [Redis configured on your Medusa server](/tutorial/set-up-your-development-environment#redis). Sending emails is done through Subscribers, which uses Redis as the event queue. If you don’t set up Redis, the plugin will not send emails.
|
||||
|
||||
@@ -42,7 +42,7 @@ If you choose to give the API Key restricted access, make sure to at least give
|
||||
|
||||
:::
|
||||
|
||||
Once you create the API key, the key will be shown for one time only. So, make sure to copy and save it somewhere for later usage.
|
||||
Once you create the API key, the key will be shown for one time only. Make sure to copy and save it somewhere for later usage.
|
||||
|
||||
### Email Templates
|
||||
|
||||
@@ -3953,7 +3953,7 @@ To test it out, perform an action that would trigger one of the emails being sen
|
||||
|
||||
:::tip
|
||||
|
||||
If you don’t have a storefront installed, check out our [Gatsby](../starters/gatsby-medusa-starter.md) or [Next.js](../starters/nextjs-medusa-starter.md) starters to create a storefront in minutes.
|
||||
If you don’t have a storefront installed, check out the [Gatsby](../starters/gatsby-medusa-starter.md) or [Next.js](../starters/nextjs-medusa-starter.md) starters to create a storefront in minutes.
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Strapi
|
||||
|
||||
In this document, you’ll learn how to integrate Strapi with Medusa to add rich CMS functionalities.
|
||||
In this document, you’ll learn how to integrate Strapi with Medusa to add rich Content Management System (CMS) functionalities.
|
||||
|
||||
:::info
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ This document guides you through setting up Stripe payments in your Medusa serve
|
||||
|
||||
## Video Guide
|
||||
|
||||
You can also follow our video guide to learn how the setup works:
|
||||
You can also follow this video guide to learn how the setup works:
|
||||
|
||||
<div>
|
||||
<video width="100%" height="100%" playsinline autoplay muted controls>
|
||||
@@ -26,7 +26,7 @@ Before you proceed with this guide, make sure you create a [Stripe account](http
|
||||
|
||||
This section guides you over the steps necessary to add Stripe as a payment provider to your Medusa server.
|
||||
|
||||
If you don’t have a Medusa server installed yet, you must follow our [quickstart guide](../quickstart/quick-start) first.
|
||||
If you don’t have a Medusa server installed yet, you must follow the [quickstart guide](../quickstart/quick-start) first.
|
||||
|
||||
### Install the Stripe Plugin
|
||||
|
||||
@@ -61,7 +61,7 @@ You might find that this code is already available but commented out. You can pr
|
||||
|
||||
:::
|
||||
|
||||
The Stripe plugin uses 2 configuration options. The `api_key` is essential to both your development and production environments. As for the `webhook_secret`, it’s essential for your production environment. So, if you’re only using Stripe for development you can skip adding the value for this option at the moment.
|
||||
The Stripe plugin uses two configuration options. The `api_key` is essential to both your development and production environments. As for the `webhook_secret`, it’s essential for your production environment. So, if you’re only using Stripe for development you can skip adding the value for this option at the moment.
|
||||
|
||||
### Retrieve Stripe's Keys
|
||||
|
||||
|
||||
@@ -16,13 +16,13 @@ This plugin only gives you access to the Twilio SMS API but does not implement s
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before going further with this guide make sure you have a Medusa server set up. You can follow our [Quickstart guide](../quickstart/quick-start.md) if you don’t.
|
||||
Before going further with this guide make sure you have a Medusa server set up. You can follow the [Quickstart guide](../quickstart/quick-start.md) if you don’t.
|
||||
|
||||
You also must have a [Twilio account created](https://www.twilio.com/sms) so if you don’t already please go ahead and create one.
|
||||
|
||||
## Retrieve Credentials
|
||||
|
||||
For the [Twilio SMS plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-plugin-twilio-sms), you need three credentials from your Twilio account: Account SID, Auth Token, and a Twilio phone number to send from. You can find these 3 from your [Twilio Console’s homepage](https://console.twilio.com).
|
||||
For the [Twilio SMS plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-plugin-twilio-sms), you need three credentials from your Twilio account: Account SID, Auth Token, and a Twilio phone number to send from. You can find these three from your [Twilio Console’s homepage](https://console.twilio.com).
|
||||
|
||||
## Install Plugin
|
||||
|
||||
@@ -110,7 +110,7 @@ If you create an order now on your storefront, you should receive a message from
|
||||
|
||||
:::tip
|
||||
|
||||
If you don’t have a storefront set up yet, you can install one of our [Next.js](../starters/nextjs-medusa-starter.md) or [Gatsby](../starters/gatsby-medusa-starter.md) storefronts.
|
||||
If you don’t have a storefront set up yet, you can install one of the [Next.js](../starters/nextjs-medusa-starter.md) or [Gatsby](../starters/gatsby-medusa-starter.md) storefronts.
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ The default port is set in `package.json` in the `develop` 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 CORS issues.
|
||||
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.
|
||||
|
||||
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:
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
In this document, you’ll learn what Batch Jobs are and how they work in Medusa.
|
||||
|
||||
## What are Batch Jobs?
|
||||
## 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.
|
||||
|
||||
@@ -56,6 +56,6 @@ If the batch job fails at any point in this flow, its status is changed to `fail
|
||||
|
||||

|
||||
|
||||
## What’s Next?
|
||||
## What’s Next
|
||||
|
||||
- Learn about the [Batch Job’s events](../subscribers/events-list.md#batch-jobs-events).
|
||||
@@ -4,7 +4,7 @@ In this document, you’ll learn how to create a cron job in Medusa.
|
||||
|
||||
## Overview
|
||||
|
||||
Medusa allows you to create cron jobs that run at specific times during your server’s lifetime. For example, you can synchronize your inventory with an ERP system once a day.
|
||||
Medusa allows you to create cron 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.
|
||||
|
||||
This guide explains how to create a cron job on your Medusa server. The cron job in this example will simply change the status of draft products to `published`.
|
||||
|
||||
@@ -12,7 +12,7 @@ This guide explains how to create a cron job on your Medusa server. The cron job
|
||||
|
||||
### 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.md) to get started.
|
||||
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.md) to get started.
|
||||
|
||||
### Redis
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ import cors from "cors"
|
||||
import { projectConfig } from "../../medusa-config"
|
||||
```
|
||||
|
||||
Then, create an object that will hold the CORS configurations:
|
||||
Then, create an object that will hold the Cross-Origin Resource Sharing (CORS) configurations:
|
||||
|
||||
```js
|
||||
const corsOptions = {
|
||||
@@ -204,7 +204,7 @@ const user = await userService.retrieve(id)
|
||||
|
||||
### Route Parameters
|
||||
|
||||
The routes you create receive 2 parameters. The first one is the absolute path to the root directory that your server is running from. The second one 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.
|
||||
The routes you create receive two parameters. The first one is the absolute path to the root directory that your server is running from. The second one 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.
|
||||
|
||||
```js
|
||||
export default (rootDirectory, pluginOptions) => {
|
||||
|
||||
@@ -53,7 +53,7 @@ import cors from "cors"
|
||||
import { projectConfig } from "../../medusa-config"
|
||||
```
|
||||
|
||||
Then, create an object that will hold the CORS configurations:
|
||||
Then, create an object that will hold the Cross-Origin Resource Sharing (CORS) configurations:
|
||||
|
||||
```js
|
||||
const corsOptions = {
|
||||
@@ -203,7 +203,7 @@ const customer = await customerService.retrieve(id)
|
||||
|
||||
### Route Parameters
|
||||
|
||||
The routes you create receive 2 parameters. The first one is the absolute path to the root directory that your server is running from. The second one 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.
|
||||
The routes you create receive two parameters. The first one is the absolute path to the root directory that your server is running from. The second one 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.
|
||||
|
||||
```js
|
||||
export default (rootDirectory, pluginOptions) => {
|
||||
|
||||
@@ -121,7 +121,7 @@ In the constructor, you can use dependency injection to get access to instances
|
||||
|
||||
Then, in the method `list`, you can obtain an instance of the `PostRepository` using `this.manager_.getCustomRepository` passing it `this.postRepository` as a parameter. This lets you use [Custom Repositories with Typeorm](https://typeorm.io/custom-repository) to create custom methods in your repository that work with the data in your database.
|
||||
|
||||
After getting an instance of the repository, you can then use [Typeorm’s Repository methods](https://typeorm.io/repository-api) to perform CRUD (Create, Read, Update, Delete) operations on your entity.
|
||||
After getting an instance of the repository, you can then use [Typeorm’s Repository methods](https://typeorm.io/repository-api) to perform Create, Read, Update, and Delete (CRUD) operations on your entity.
|
||||
|
||||
If you need access to your entity in endpoints, you can then use the methods you define in the service.
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
In this document, you'll learn what Entities are in Medusa.
|
||||
|
||||
## What are Entities?
|
||||
## What are Entities
|
||||
|
||||
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.
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ Medusa’s Migrations do not work with SQLite databases. They are intended to be
|
||||
|
||||
:::
|
||||
|
||||
## What are Migrations?
|
||||
## 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.
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ When an event is triggered that your Notification Provider is registered as a ha
|
||||
|
||||
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.
|
||||
|
||||
This method receives 3 parameters:
|
||||
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.
|
||||
@@ -156,7 +156,7 @@ The `to` and `data` properties are used in the `NotificationService` in Medusa
|
||||
|
||||
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.
|
||||
|
||||
This method receives 3 parameters:
|
||||
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`.
|
||||
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.
|
||||
@@ -240,7 +240,7 @@ Then, place an order either using the [REST APIs](https://docs.medusajs.com/api/
|
||||
|
||||
:::tip
|
||||
|
||||
If you don’t have a storefront installed you can get started with either our [Next.js](../../../starters/nextjs-medusa-starter.md) or [Gatsby](../../../starters/gatsby-medusa-starter.md) starter storefronts in minutes.
|
||||
If you don’t have a storefront installed you can get started with either the [Next.js](../../../starters/nextjs-medusa-starter.md) or [Gatsby](../../../starters/gatsby-medusa-starter.md) starter storefronts in minutes.
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This document gives an overview of the notification architecture and how it work
|
||||
|
||||
Medusa provides a Notification API to mainly handle sending and resending notifications when an event occurs. For example, sending an email to the customer when they place an order.
|
||||
|
||||
The Notification architecture is made up of 2 main components: the Notification Provider and the Notification. Simply put, the Notification Provider handles the sending and resending of a Notification.
|
||||
The Notification architecture is made up of two main components: the Notification Provider and the Notification. Simply put, the Notification Provider handles the sending and resending of a Notification.
|
||||
|
||||
## Notification Provider
|
||||
|
||||
@@ -48,7 +48,7 @@ A Notification also represents a resent notification. So, when a notification is
|
||||
|
||||
### Notification Entity Overview
|
||||
|
||||
The 2 most important properties in the `Notification` entity are the `to` and `data` properties.
|
||||
The two most important properties in the `Notification` 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.
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ A Payment Provider in Medusa is a method to handle payments in selected regions.
|
||||
|
||||
Payment Providers can be integrated with third-party services that handle payment operations such as capturing a payment. An example of a Payment Provider is Stripe.
|
||||
|
||||
Payment Providers can also be related to a custom way of handling payment operations. An example of that is cash on delivery (COD) payment methods or Medusa’s [manual payment provider plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-payment-manual) which provides a minimal implementation of a payment provider and allows store operators to manually handle order payments.
|
||||
Payment Providers can also be related to a custom way of handling payment operations. An example of that is Cash on Delivery (COD) payment methods or Medusa’s [manual payment provider plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-payment-manual) which provides a minimal implementation of a payment provider and allows store operators to manually handle order payments.
|
||||
|
||||
### How Payment Provider is Created
|
||||
|
||||
|
||||
@@ -301,9 +301,9 @@ rm -rf node_modules
|
||||
cd <SERVER_PATH>/node_modules/<PLUGIN_NAME>
|
||||
npm install
|
||||
cd <PLUGIN_PATH>
|
||||
npm build
|
||||
npm run build
|
||||
cd <SERVER_PATH>
|
||||
npm start
|
||||
npm run start
|
||||
```
|
||||
|
||||
Where `<SERVER_PATH>` is the path to your Medusa server, `<PLUGIN_PATH>` is the path to your plugin and `<PLUGIN_NAME>` is the name of your plugin as it is in your plugin `package.json` file.
|
||||
|
||||
@@ -18,7 +18,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, 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 [packages directory in the Medusa repository on GitHub](https://github.com/medusajs/medusa/tree/master/packages).
|
||||
|
||||
:::tip
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
In this document, you'll learn about what Services are in Medusa.
|
||||
|
||||
## What are Services?
|
||||
## 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.
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ constructor({}, options) {
|
||||
|
||||
When the admin is creating shipping options available for customers during checkout, they choose one of the fulfillment options provided by underlying fulfillment providers.
|
||||
|
||||
For example, if you’re integrating UPS as a fulfillment provider, you might support 2 fulfillment options: UPS Express Shipping and UPS Access Point.
|
||||
For example, if you’re integrating UPS as a fulfillment provider, you might support two fulfillment options: UPS Express Shipping and UPS Access Point.
|
||||
|
||||
These fulfillment options are defined in the `getFulfillmentOptions` method. This method should return an array of options.
|
||||
|
||||
@@ -124,7 +124,7 @@ When the customer chooses a shipping option on checkout, the shipping option and
|
||||
|
||||
`validateFulfillmentOption` is called when a `POST` request is sent to [`/carts/:id/shipping-methods`](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCartsCartShippingMethod).
|
||||
|
||||
This method accepts 3 parameters:
|
||||
This method accepts three parameters:
|
||||
|
||||
1. The shipping option data.
|
||||
2. The `data` object passed in the body of the request.
|
||||
@@ -156,7 +156,7 @@ After an order is placed, it can be fulfilled either manually by the admin or us
|
||||
|
||||
This method gives you access to the fulfillment being created as well as other details in case you need to perform any additional actions with the third-party provider.
|
||||
|
||||
This method accepts 4 parameters:
|
||||
This method accepts four parameters:
|
||||
|
||||
1. The data of the shipping method associated with the order.
|
||||
2. An array of items in the order to be fulfilled. The admin can choose all or some of the items to fulfill.
|
||||
@@ -210,7 +210,7 @@ canCalculate(data) {
|
||||
|
||||
This method is called on checkout when the shipping method is being created if the `price_type` of the selected shipping option is `calculated`.
|
||||
|
||||
This method receives 3 parameters:
|
||||
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).
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Shipping Architecture Overview
|
||||
|
||||
This document gives an overview of the shipping architecture and its 4 most important components.
|
||||
This document gives an overview of the shipping architecture and its four most important components.
|
||||
|
||||
## Introduction
|
||||
|
||||
In Medusa, the Shipping architecture relies on 4 components: **Fulfillment Provider**, **Shipping Profiles**, **Shipping Options**, and **Shipping Methods**.
|
||||
|
||||
The distinction between the 4 is important. It has been carefully planned and put together to support all the different ecommerce use cases and shipping providers that can be integrated.
|
||||
The distinction between the four is important. It has been carefully planned and put together to support all the different ecommerce use cases and shipping providers that can be integrated.
|
||||
|
||||
It’s also constructed to support multiple regions, provide different shipment configurations and options for different product types, provide promotional shipments for your customers, and much more.
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ It is assumed you’re already familiar with [Subscribers in Medusa and how to l
|
||||
|
||||
## Legend
|
||||
|
||||
Events in this document are listed under the entity they’re associated with. They’re listed in a table of 3 columns:
|
||||
Events in this document are listed under the entity they’re associated with. They’re listed in a table of three columns:
|
||||
|
||||
1. **Event Name:** The name you use to subscribe a handler for the event.
|
||||
2. **Description:** When this event is triggered.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
In this document, you'll learn what Subscribers are in Medusa.
|
||||
|
||||
## What are Events?
|
||||
## What are Events
|
||||
|
||||
In Medusa, there are events that are emitted when a certain action occurs. For example, if a customer places an order, the `order.placed` event is emitted with the order data.
|
||||
|
||||
@@ -10,7 +10,7 @@ The purpose of these events is to allow other parts of the platform, or third-pa
|
||||
|
||||
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.
|
||||
|
||||
## What are Subscribers?
|
||||
## What are Subscribers
|
||||
|
||||
Subscribers register handlers for an events and allows you to perform an action when that event occurs. For example, if you want to send your customer an email when they place an order, then you can listen to the `order.placed` event and send the email when the event is emitted.
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ This can be useful when some countries have the same currency but have different
|
||||
|
||||
Then, Medusa handles calculating the tax amount using the tax rate and the tax-inclusive price. This is managed in the backend and relayed to accounting and analytics tools.
|
||||
|
||||
## How is Tax Inclusivity Defined?
|
||||
## How is Tax Inclusivity Defined
|
||||
|
||||
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`.
|
||||
|
||||
@@ -29,7 +29,7 @@ If you want to enable or disable this attribute for any of these entities, you c
|
||||
|
||||
The value set for these entities can affect whether line items and shipping methods are tax inclusive or not.
|
||||
|
||||
### How is Tax Inclusivity Defined for Line Items?
|
||||
### How is Tax Inclusivity Defined for Line Items
|
||||
|
||||
:::info
|
||||
|
||||
@@ -44,7 +44,7 @@ The `LineItem` entity also has the `includes_tax` attribute. The value of this f
|
||||
- Or a price list that includes the product variant associated with the line item has the `includes_tax` attribute set to `true`, and the tax-inclusive amount of one of the variant’s prices in the price list is less than the original price of the variant;
|
||||
- Or one of the variant’s prices in the price list uses a currency or region that has the `includes_tax` attribute set to `true`, and the tax-inclusive amount of the price is less than the original price of the variant.
|
||||
|
||||
### How is Tax Inclusivity Defined for Shipping Methods?
|
||||
### How is Tax Inclusivity Defined for Shipping Methods
|
||||
|
||||
:::info
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ By default, taxes are automatically calculated by Medusa during checkout. This b
|
||||
|
||||
If you disable this behavior, you must manually trigger taxes calculation. When taxes are calculated, this means that requests will be sent to the tax provider to retrieve the tax rates.
|
||||
|
||||
## How to Manually Calculate Taxes in Checkout?
|
||||
## How to Manually Calculate Taxes in Checkout
|
||||
|
||||
This section explores different ways you can calculate taxes based on your purpose.
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ Updating your medusa server to version `1.3.8` may cause issues when using NPM.
|
||||
|
||||
## Update Using Yarn
|
||||
|
||||
We highly recommend using [yarn](https://yarnpkg.com/) when working with Medusa. Updating with yarn should resolve any issues you might run into during the update.
|
||||
It's highly recommended to use [yarn](https://yarnpkg.com/) when working with Medusa. Updating with yarn should resolve any issues you might run into during the update.
|
||||
|
||||
## Resolving Update Issues with NPM
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ This document will guide you through the steps needed to implement the checkout
|
||||
|
||||
## Overview
|
||||
|
||||
A checkout flow is composed of the necessary steps to allow a customer to perform a successful checkout. It’s generally made up of 2 primary steps: the shipping and payment steps.
|
||||
A checkout flow is composed of the necessary steps to allow a customer to perform a successful checkout. It’s generally made up of two primary steps: the shipping and payment steps.
|
||||
|
||||
This document will take you through the general process of a checkout flow. You should follow along with this document if you’re creating a custom storefront, if you’re adding a custom payment provider, or if you’re just interested in learning more about how checkout works in Medusa.
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ If you’re fixing errors in an existing documentation page, you can scroll down
|
||||
|
||||
If you’re adding a new page or contributing to the codebase, fork the repository, create a new branch, and make all changes necessary in your repository. Then, once you’re done creating a PR in the Medusa repository.
|
||||
|
||||
For more details on how to contribute, check out [the contribution guidelines on our repository](https://github.com/medusajs/medusa/blob/master/CONTRIBUTING.md).
|
||||
For more details on how to contribute, check out [the contribution guidelines in the Medusa repository](https://github.com/medusajs/medusa/blob/master/CONTRIBUTING.md).
|
||||
|
||||
### Branch Name
|
||||
|
||||
@@ -53,8 +53,12 @@ Make sure that the branch name starts with `docs/`. For example, `docs/fix-servi
|
||||
|
||||
When you create a pull request, prefix the title with “docs:”. Make sure to keep “docs” in small letters.
|
||||
|
||||
<!-- vale off -->
|
||||
|
||||
In the body of the PR, explain clearly what the PR does. If the PR solves an issue, use [closing keywords](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword) with the issue number. For example, “Closes #1333”.
|
||||
|
||||
<!-- vale on -->
|
||||
|
||||
## 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).
|
||||
@@ -101,14 +105,22 @@ The code snippet must be written using NPM, and the `npm2yarn` plugin will autom
|
||||
|
||||
### Expand Commands
|
||||
|
||||
<!-- vale off -->
|
||||
|
||||
Don't use commands in their abbrivated terms. For example, instead of `npm i` use `npm install`.
|
||||
|
||||
<!-- vale on -->
|
||||
|
||||
### Run Command
|
||||
|
||||
Make sure to always use the `run` command when the command runs a script.
|
||||
|
||||
<!-- vale off -->
|
||||
|
||||
For example, even though you can run the `start` script using NPM with `npm start`, however, to make sure it’s transformed properly to a Yarn command, you must add the `run` keyword before `start`.
|
||||
|
||||
<!-- vale on -->
|
||||
|
||||
### Global Option
|
||||
|
||||
When a command uses the global option `-g`, add it at the end of the NPM command to ensure that it’s transformed to a Yarn command properly. For example:
|
||||
@@ -117,6 +129,59 @@ When a command uses the global option `-g`, add it at the end of the NPM command
|
||||
npm install @medusajs/medusa-cli -g
|
||||
```
|
||||
|
||||
## Need Additional Help?
|
||||
## Linting with Vale
|
||||
|
||||
If you need any additional help while contributing, you can join our [Discord server](https://discord.gg/medusajs) and ask Medusa’s core team as well as the community any questions.
|
||||
Medusa uses Vale to lint documentation pages and perform checks on incoming PRs into the repository.
|
||||
|
||||
### Result of PR Checks
|
||||
|
||||
You can check the result of running the "lint" action on your PR by clicking the Details link next to it. You can find there all errors that you need to fix.
|
||||
|
||||
### Run Vale Locally
|
||||
|
||||
If you want to check your work locally, you can do that by:
|
||||
|
||||
1. [Installing Vale](https://vale.sh/docs/vale-cli/installation/) on your machine.
|
||||
2. Change to the `docs` directory:
|
||||
|
||||
```bash
|
||||
cd docs
|
||||
```
|
||||
|
||||
3\. Run the `run-vale` script:
|
||||
|
||||
```bash
|
||||
./run-vale.sh error
|
||||
```
|
||||
|
||||
### VS Code Extension
|
||||
|
||||
To facilitate writing documentation, you can optionally use the [Vale VS Code extension](https://github.com/errata-ai/vale-vscode). This will show you any errors in your documentation while writing it.
|
||||
|
||||
### Linter Exceptions
|
||||
|
||||
If it's needed to break some style guide rules in a document, you can wrap the parts that the linter shouldn't scan with the following comments in the `md` or `mdx` files:
|
||||
|
||||
```md
|
||||
<!-- vale off -->
|
||||
|
||||
content that shouldn't be scanned for errors here...
|
||||
|
||||
<!-- vale on -->
|
||||
```
|
||||
|
||||
You can also disable specific rules. For example:
|
||||
|
||||
```md
|
||||
<!-- vale docs.Numbers = NO -->
|
||||
|
||||
Medusa supports Node versions 14 and 16.
|
||||
|
||||
<!-- vale docs.Numbers = YES -->
|
||||
```
|
||||
|
||||
If you use this in your PR, you must justify its usage.
|
||||
|
||||
## Need Additional Help
|
||||
|
||||
If you need any additional help while contributing, you can join Medusa's [Discord server](https://discord.gg/medusajs) and ask Medusa’s core team as well as the community any questions.
|
||||
@@ -98,7 +98,7 @@ 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 2 inputs for the key and value of the environment variable.
|
||||
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.
|
||||
|
||||
@@ -128,7 +128,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 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 server. Follow along in the [Configure Cross-Origin Resource Sharing (CORS) on the Medusa Server](#configure-cors-variable-on-the-medusa-server) section.
|
||||
|
||||
:::
|
||||
|
||||
@@ -168,7 +168,7 @@ In your terminal, run the following command:
|
||||
netlify init
|
||||
```
|
||||
|
||||
You’ll have to follow 5 steps for the initialization:
|
||||
You’ll have to follow five steps for the initialization:
|
||||
|
||||
##### **Step 1: Create Netlify Website**
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ DigitalOcean is a reliable hosting provider that provides different ways to host
|
||||
|
||||
### Medusa Server
|
||||
|
||||
It is assumed that you already have a Medusa server installed locally. If you don’t, please follow our [quickstart guide](../../quickstart/quick-start.md).
|
||||
It is assumed that you already have a Medusa server installed locally. If you don’t, please follow the [quickstart guide](../../quickstart/quick-start.md).
|
||||
|
||||
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.
|
||||
|
||||
@@ -163,7 +163,7 @@ Once you’re done, click Next to move on to the next step.
|
||||
|
||||
In this section, you’ll add environment variables that are essential to your Medusa server.
|
||||
|
||||
You should see 2 ways to add environment variables: Global or specific to the Web Service.
|
||||
You should see two ways to add environment variables: Global or specific to the Web Service.
|
||||
|
||||

|
||||
|
||||
@@ -263,7 +263,7 @@ Make sure to replace `<EMAIL>` and `<PASSWORD>` with the credentials you want to
|
||||
|
||||
## Add Environment Variables
|
||||
|
||||
You’ll likely need to add environment variables later such as Admin CORS and Store CORS variables.
|
||||
You’ll likely need to add environment variables later such as Admin Cross-Origin Resource Sharing (CORS) and Store CORS variables.
|
||||
|
||||
To add environment variables, on the App’s page click on Settings and choose the Web Service component.
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ Alternatively, you can use this button to deploy the Medusa server to Heroku dir
|
||||
|
||||
### Medusa Server
|
||||
|
||||
It is assumed that you already have a Medusa server installed locally. If you don’t, please follow our [quickstart guide](../../quickstart/quick-start.md).
|
||||
It is assumed that you already have a Medusa server installed locally. If you don’t, please follow the [quickstart guide](../../quickstart/quick-start.md).
|
||||
|
||||
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.
|
||||
|
||||
@@ -135,7 +135,7 @@ heroku buildpacks:set heroku/nodejs
|
||||
|
||||
Upstash adds the Redis URL under the environment variable `UPSTASH_REDIS_URL`. However, Medusa looks for the `REDIS_URL` environment variable when initializing the connection with Redis.
|
||||
|
||||
So, retrieve the value of `UPSTASH_REDIS_URL` with the following command:
|
||||
Retrieve the value of `UPSTASH_REDIS_URL` with the following command:
|
||||
|
||||
```bash
|
||||
heroku config:get UPSTASH_REDIS_URL
|
||||
@@ -153,7 +153,7 @@ Where `<YOUR_REDIS_URL>` is the value you received from the previous command.
|
||||
|
||||
#### Configure the PostgreSQL Database URL
|
||||
|
||||
If you're using the Heroku PostgreSQL Add-on, it should configure the environment variable `DATABASE_URL`. So, you don't need to perform any additional actions.
|
||||
If you're using the Heroku PostgreSQL Add-on, it should configure the environment variable `DATABASE_URL`. In that case, you don't need to perform any additional actions.
|
||||
|
||||
However, if you use another add-on, make sure to set the environment variable `DATABASE_URL` to the PostgreSQL Database URL.
|
||||
|
||||
@@ -270,7 +270,7 @@ Where `<APP_NAME>` is the name of your Heroku app, and `<EMAIL>` and `<PASSWORD>
|
||||
|
||||
## Add Environment Variables
|
||||
|
||||
You’ll likely need to add environment variables later such as Admin CORS and Store CORS variables.
|
||||
You’ll likely need to add environment variables later such as Admin Cross-Origin Resource Sharing (CORS) and Store CORS variables.
|
||||
|
||||
To set or change an environment variable's value, you can use the following command:
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
In this document, you'll learn how to deploy your Medusa server 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 (e.g. AWS, DigitalOcean).
|
||||
[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).
|
||||
|
||||
[Terraform](https://www.terraform.io/) is an open source infrastructure as code software (IaC) tool that allows you to easily deploy apps like Medusa and the resources it needs to Qovery using a single script.
|
||||
|
||||
@@ -16,7 +16,7 @@ This tutorial explains how to deploy Medusa to a Qovery organization with an AWS
|
||||
|
||||
### Medusa Server
|
||||
|
||||
It is assumed that you already have a Medusa server installed locally. If you don’t, please follow our [quickstart guide](../../quickstart/quick-start.md).
|
||||
It is assumed that you already have a Medusa server installed locally. If you don’t, please follow the [quickstart guide](../../quickstart/quick-start.md).
|
||||
|
||||
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.
|
||||
|
||||
@@ -240,7 +240,7 @@ Here’s an explanation of each of the variables and how to retrieve their varia
|
||||
- `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 JWT 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 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.
|
||||
- `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`.
|
||||
@@ -461,7 +461,7 @@ terraform apply
|
||||
|
||||
You’ll be asked to confirm creating all the necessary resources in Qovery. Enter `yes` and the deployment will start.
|
||||
|
||||
The deployment can take up to 30 minutes to finish. You’ll be able to track its status both in your terminal and in the [Qovery Console](https://console.qovery.com/).
|
||||
The deployment can take up to thirty minutes to finish. You’ll be able to track its status both in your terminal and in the [Qovery Console](https://console.qovery.com/).
|
||||
|
||||
:::tip
|
||||
|
||||
@@ -496,7 +496,7 @@ medusa user --email <EMAIL> --password <PASSWORD>
|
||||
|
||||
## Add Environment Variables
|
||||
|
||||
You’ll likely need to add environment variables later such as Admin CORS and Store CORS variables.
|
||||
You’ll likely need to add environment variables later such as Admin Cross-Origin Resource Sharing (CORS) and Store CORS variables.
|
||||
|
||||
To add environment variables, in your [Qovery Console](https://console.qovery.com/) go to the Medusa app and choose Environment Variables from the sidebar. You can add environment variables here at any point later on.
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ 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 2 inputs for the key and value of the environment variable.
|
||||
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.
|
||||
|
||||
@@ -146,7 +146,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 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 Server section](#configure-cors-variable-on-the-medusa-server).
|
||||
|
||||
:::
|
||||
|
||||
@@ -186,7 +186,7 @@ In your terminal, run the following command:
|
||||
netlify init
|
||||
```
|
||||
|
||||
You’ll have to follow 5 steps for the initialization:
|
||||
You’ll have to follow five steps for the initialization:
|
||||
|
||||
##### Step 1: Create Netlify Website
|
||||
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
---
|
||||
title: Create a file plugin
|
||||
---
|
||||
|
||||
# File Plugin
|
||||
|
||||
This guide will give an introduction about the File Service and steps required to create a custom file uploader plugin for Medusa. It build on article about [creating custom plugins](../advanced/backend/payment/overview.md).
|
||||
|
||||
As an example, we will create a File plugin that uploads the product images to Cloudinary.
|
||||
|
||||
## The File API
|
||||
|
||||
The file api is used to upload and manage product images used in Medusa.
|
||||
|
||||
## Implementing the File Service
|
||||
|
||||
The File Service is an built in interface in Medusa Core. It has two methods which must be overidden by our custom implementation of the service: `upload` and `delete`.
|
||||
|
||||
As the names suggest, upload allows us to specify the logic for uploading the file/image to our service while delete is used for deleting the image.
|
||||
|
||||
Both of the methods must return an promise.
|
||||
The upload method should return the url of uploaded image.
|
||||
In case of any error uploading, both methods should reject the promise and return an appropriate error message.
|
||||
|
||||
Here is the implementation of the base file service that we will extend.
|
||||
```javascript
|
||||
/**
|
||||
* Interface for file connectors
|
||||
* @interface
|
||||
*/
|
||||
class BaseFileService extends BaseService {
|
||||
constructor() {
|
||||
super()
|
||||
}
|
||||
|
||||
upload() {
|
||||
throw Error("upload must be overridden by the child class")
|
||||
}
|
||||
|
||||
delete() {
|
||||
throw Error("delete must be overridden by the child class")
|
||||
}
|
||||
}
|
||||
|
||||
export default BaseFileService
|
||||
```
|
||||
|
||||
See the example below for detailed usage.
|
||||
|
||||
## Example
|
||||
|
||||
We will create an plugin for uploading product images to [Cloudinary](https://cloudinary.com/)
|
||||
|
||||
The first step is to create an account on Cloudinary and copy the credentials like given below.
|
||||
|
||||
```
|
||||
cloud_name: "xx"
|
||||
api_key: "xx"
|
||||
api_secret: "xx"
|
||||
|
||||
```
|
||||
|
||||
The first step in creating a plugin is to initialize the Node.js project:
|
||||
|
||||
```bash npm2yarn
|
||||
npm init
|
||||
```
|
||||
|
||||
This command will ask you to fill out your project's metadata, which will eventually be used when publishing the package to NPM. After this command completes, you are ready to start implementing the functionality.
|
||||
|
||||
Next up, we need to install cloudinary's Node.js SDK.
|
||||
|
||||
```bash npm2yarn
|
||||
npm install cloudinary
|
||||
```
|
||||
|
||||
### Implementation
|
||||
|
||||
To quickly get started with the implementation, we advise you to copy `/services/`, `/api/`, `/subscribers/` and the config files from the tutorial and add them in `/src`. As a result, you should have the following folder structure:
|
||||
|
||||
```js
|
||||
.
|
||||
├── src
|
||||
│ ├── api
|
||||
│ └── services
|
||||
│ └── subscribers
|
||||
├── .babelrc
|
||||
├── .gitignore
|
||||
├── medusa-config.js
|
||||
├── README.md
|
||||
└── package.json
|
||||
```
|
||||
|
||||
We will create a new file `cloudinary.js` in the `services` directory.
|
||||
|
||||
```javascript
|
||||
import fs from "fs";
|
||||
|
||||
import { v2 as cloudinary } from "cloudinary";
|
||||
import { FileService } from "medusa-interfaces";
|
||||
|
||||
class CloudinaryService extends FileService {
|
||||
constructor({}, options) {
|
||||
super();
|
||||
|
||||
// Initialize the Cloudinary sdk
|
||||
cloudinary.config({
|
||||
cloud_name: options.cloud_name,
|
||||
api_key: options.api_key,
|
||||
api_secret: options.api_secret,
|
||||
secure: options.secure,
|
||||
});
|
||||
}
|
||||
|
||||
// File upload
|
||||
upload(file) {
|
||||
console.log("Starting image upload");
|
||||
return new Promise((resolve, reject) => {
|
||||
// upload_stream allows to upload a file stream
|
||||
var upload_stream = cloudinary.uploader.upload_stream(
|
||||
{},
|
||||
function (err, image) {
|
||||
if (err) {
|
||||
// Reject and return an error if the file upload failed
|
||||
console.error(err);
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
// Return the url of image uploaded
|
||||
resolve({ url: image.url });
|
||||
}
|
||||
);
|
||||
// Create a file stream from path and forward it to our uploader
|
||||
fs.createReadStream(file.path).pipe(upload_stream);
|
||||
});
|
||||
}
|
||||
|
||||
delete(file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Pass the name of file to be deleted
|
||||
cloudinary.uploader.destroy(file, function (result) {
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default CloudinaryService;
|
||||
```
|
||||
|
||||
### Publishing
|
||||
|
||||
In order for your plugin to become a part of the Medusa plugin ecosystem, you need to publish it to NPM. Make sure that you've included the `package.json` file. NPM uses the details of this file to configure the publishing. Please include `medusa` and `medusa-plugin` and possibly more in the `keywords` field of the `package.json`.
|
||||
|
||||
```bash
|
||||
{
|
||||
"name": "medusa-file-cloudinary",
|
||||
...
|
||||
"keywords": [
|
||||
"medusa",
|
||||
"medusa-file",
|
||||
"medusa-plugin"
|
||||
],
|
||||
"description": "Cloudinary File Plugin for Medusa Commerce",
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Finally, you should add a README for the plugin, such that the community understands the purpose of the plugin and how to install it.
|
||||
|
||||
|
||||
## Summary
|
||||
|
||||
As a result of following this guide, you should now be able to both implement a custom file plugin for your Medusa project.
|
||||
@@ -1,71 +0,0 @@
|
||||
---
|
||||
title: Fulfillment API
|
||||
---
|
||||
|
||||
## **Introduction**
|
||||
|
||||
This guide will give an overview of Medusa's Fulfillment API and how it can be implemented to work with different fulfillment providers. Before digging deeper into the API it should be clarified what is meant by a fulfillment provider; in Medusa a fulfillment provider is typically a 3rd party service that can handle order data for the purpose of shipping the items in the order to a customer. Examples of fulfillment providers are: a carrier like UPS, a logistics platform like ShipBob or a 3PL solution.
|
||||
|
||||
Implementations of the Fulfillment API can be distributed as npm packages for easy installation through the plugin system, there are already a couple of examples of fulfillment plugins in the Medusa monorepo, you can identify these by looking for `medusa-fulfillment-*`. For further details on building and publishing plugins [please check this guide](../advanced/backend/payment/overview.md).
|
||||
|
||||
## Fulfillment Service Interface
|
||||
|
||||
The fulfillment service interface can be found in the [`medusa-interfaces` package](https://github.com/medusajs/medusa/blob/master/packages/medusa-interfaces/src/fulfillment-service.js) where you can see the full list of methods that can be implemented. The methods in the interface allow you to implement plugins that can calculate shipping rates, create fulfillments in other systems, create return labels, retrieve customs documents and more.
|
||||
|
||||
In this guide we will focus on the methods involved in a typical fulfillment flow i.e. creating a shipping option, adding a shipping method to a cart, creating a fulfillment of items in a cart and finally marking the fulfillment as shipped. The methods involved in this flow are:
|
||||
|
||||
```jsx
|
||||
getFulfillmentOptions()
|
||||
validateOption(optionData)
|
||||
validateFulfillmentData(fulfillmentData, cart)
|
||||
createFulfillment(fulfillmentData, fulfillmentItems, order, fulfillment)
|
||||
```
|
||||
|
||||
The figure below shows at what points in the flow the Fulfillment API is called.
|
||||
|
||||

|
||||
|
||||
- **Get fulfillment options for Region**
|
||||
|
||||
In Medusa Shipping Options are defined and configured for each region - this allows store operators to granularly control how orders can be fulfilled in different countries. When creating a shipping option on a Region the Fulfillment API calls `getFulfillmentOptions` which will return the ways in which a fulfillment provider can process an order. Let's imagine that you have built a UPS plugin that can be used to fulfill orders with UPS; in this case `getFulfillmentOptions` might respond with UPS Express Shipping and UPS Access Point.
|
||||
|
||||
- **Create Shipping Option**
|
||||
|
||||
When creating the Shipping Option in Medusa, a store operator selects which underlying fulfillment option will be used when customers create Orders with the Shipping Option. To build from the UPS example a store operator may select the UPS Access Point option from the list of fulfillment options, she will then add an appropriate name for the Shipping Option, set the Shipping Option's price and if needed adjust the requirements that must be met for the Shipping Option to be active (e.g. minimum cart subtotal). Before the Shipping Option is created, `validateOption` will be called to ensure that the selected fulfillment option is in fact valid and correctly formatted. `validateOption` should respond with the validated fulfillment option; this also provides a point at which you may add additional details to the fulfillment data before the Shipping Option is created.
|
||||
|
||||
- **Get Shipping Options for Cart**
|
||||
|
||||
Moving to the customer perspective it is assumed that a cart has been created, items have been added to the cart and the customer is now looking towards selecting the Shipping Option they wish to have their Order fulfilled with. The first step from the storefront perspective is to retrieve the list of Shipping Options that are available for the Cart; these will be filtered based on the Region the Cart belongs to and the items that are in the cart. There are no calls to the Fulfillment API associated with the retrieval.
|
||||
|
||||
- **Add Shipping Method to Cart**
|
||||
|
||||
At this point the customer has selected a Shipping Option and may have configured additional details about the fulfillment. For example, building on the UPS example, the customer may have selected a Shipping Option that uses the UPS Access Point fulfillment option; in this case the customer sends an `access_point_id` in the `data` object of the `POST /store/carts/:id/shipping-methods` payload. At this point the Shipping Option becomes a Shipping Method, the distinction between the two is that a Shipping Option is a template for how a cart may be shipped whereas a Shipping Method is the instantiated way that the cart will be shipped (which may include specific details like the `access_point_id`). In order to ensure that the details that the customer selects are valid the Fulfillment API's `validateFulfillmentData` is called, this is where a fulfillment implementation may check that the `access_point_id` is in fact a valid value, etc.
|
||||
|
||||
- **Create Fulfillment**
|
||||
|
||||
It is now assumed that the customer has completed their purchase with a given Shipping Method and the order has been confirmed. At this point we are ready to create the fulfillment in the 3rd party system. When a store operator (or an automation) attempts to fulfill an order the `createFulfillment` method will be called in the Fulfillment API, in our UPS example this method should then book a shipment via UPS's API.
|
||||
Note: in Medusa you can make partial fulfillments of an order it is therefore important that the id sent to the 3rd party is unique by fulfillment and not only order.
|
||||
|
||||
- **Mark as shipped**
|
||||
|
||||
The final step of the fulfillment process is to mark the fulfillment as shipped. It is also at this stage that you would record a tracking number that can be shared with the customer. This step typically happens asynchronously through a webhook.
|
||||
|
||||
## Other useful methods
|
||||
|
||||
The flow above describes the Fulfillment API in high level terms; check out the `[medusa-fulfillment-webshipper](https://github.com/medusajs/medusa/blob/master/packages/medusa-fulfillment-webshipper/src/services/webshipper-fulfillment.js)` plugin for a full implementation of the Fulfillment API. In the implementation you will find examples of all the method described above.
|
||||
|
||||
### `createReturn`
|
||||
|
||||
You will find that the Webshipper plugin has an implementation for `createReturn` which allows fulfillment providers to implement a way for generating return labels. When implemented this can be used to allow customers to create self managed returns or to integrate automatic return label generation in the admin dashboard.
|
||||
|
||||
### `canCalculate(fulfillmentOption)`
|
||||
|
||||
If implemented this method can be used to dynamically calculate prices based on a cart's contents or details. The method returns a boolean value indicating if a given fulfillment option can have a dynamically calculated price or not.
|
||||
|
||||
### `calculatePrice(fulfillmentOption, fulfillmentData, cart)`
|
||||
|
||||
If the shipping option is configured to dynamically calculate the price of the this method will be called when Shipping Options are fetched for the Cart and when Shipping Methods are created on a Cart.
|
||||
|
||||
## What's next?
|
||||
|
||||
Now that you have an overview of the Fulfillment API you can start developing your own fulfillment plugin. For a guide on how to create plugins [check this guide](../advanced/backend/payment/overview.md). If you have questions or issues please feel free to [join our Discord server](https://discord.gg/medusajs) for direct access to the engineering team.
|
||||
@@ -12,7 +12,7 @@ Medusa is an open-source headless commerce engine that enables developers to cre
|
||||
|
||||
:::tip
|
||||
|
||||
Get started with Medusa in a few minutes with our [Quickstart guide](./quickstart/quick-start.md)!
|
||||
Get started with Medusa in a few minutes with the [Quickstart guide](./quickstart/quick-start.md)!
|
||||
|
||||
:::
|
||||
|
||||
@@ -25,11 +25,11 @@ Medusa comes with a set of building blocks that allow you to create unique digit
|
||||
- **Orders** come with all the functionality necessary to perform powerful customer service operations with ease.
|
||||
- **Carts** allow customers to collect products for purchase, add shipping details, and complete payments.
|
||||
- **Products** come with relevant fields for customs, stock keeping, and sales. Medusa supports multiple options and unlimited variants.
|
||||
- **Swaps** allow customers to exchange products after purchase (e.g. for incorrect sizes). Accounting, payment, and fulfillment plugins handle all the tedious work for you for automated customer service.
|
||||
- **Swaps** allow customers to exchange products after purchase (for example, for incorrect sizes). Accounting, payment, and fulfillment plugins handle all the tedious work for you for automated customer service.
|
||||
- **Claims** can be created if customers experience problems with one of their products. Plugins make sure to automate sending out replacements, handling refunds, and collecting valuable data for analysis.
|
||||
- **Returns** allow customers to send back products and can be configured to function in 100% automated flow-through accounting and payment plugins.
|
||||
- **Fulfillment API** makes it easy to integrate with any fulfillment provider by creating fulfillment plugins.
|
||||
- **Payments API** makes it easy to integrate with any payment provider by creating payment plugins, we already support Stripe, Paypal, and Klarna.
|
||||
- **Payments API** makes it easy to integrate with any payment provider by creating payment plugins, Medusa already supports Stripe, Paypal, and Klarna.
|
||||
- **Notification API** allows integrations with email providers, chatbots, Slack channels, etc.
|
||||
- **Customer Login** gives customers a way of managing their data, viewing their orders, and saving payment details.
|
||||
- **Shipping Options & Profiles** enable powerful rules for free shipping limits, multiple fulfillment methods, and more.
|
||||
@@ -40,7 +40,7 @@ Medusa comes with a set of building blocks that allow you to create unique digit
|
||||
|
||||
### The Medusa Server
|
||||
|
||||
You can follow our [quickstart guide](quickstart/quick-start.md) to install and run a Medusa server.
|
||||
You can follow the [quickstart guide](quickstart/quick-start.md) to install and run a Medusa server.
|
||||
|
||||
It's also recommended to learn how to [set up your development environment](tutorial/set-up-your-development-environment) with the required tools and services to run a Medusa server, then [configure your Medusa server](usage/configurations.md).
|
||||
|
||||
@@ -48,13 +48,13 @@ It's also recommended to learn how to [set up your development environment](tuto
|
||||
|
||||
The Medusa Admin provides you with a lot of functionalities and configurations such as Product Management, Order Management, Discounts and Promotions, and more.
|
||||
|
||||
You can install the Medusa admin in 2 steps by following our [Medusa Admin quickstart guide](admin/quickstart.md).
|
||||
You can install the Medusa admin in two steps by following the [Medusa Admin quickstart guide](admin/quickstart.md).
|
||||
|
||||
### The Storefront
|
||||
|
||||
The final step is to set up a storefront to sell your products.
|
||||
|
||||
Medusa provides 2 starter storefronts, one built with [Next.js](./starters/nextjs-medusa-starter.md) and one with [Gatsby](./starters/gatsby-medusa-starter.md), that you can use to quickly set up your store and start selling.
|
||||
Medusa provides two starter storefronts, one built with [Next.js](./starters/nextjs-medusa-starter.md) and one with [Gatsby](./starters/gatsby-medusa-starter.md), that you can use to quickly set up your store and start selling.
|
||||
|
||||
Alternatively, you can build your own storefront with any frontend framework of your choice just by connecting to your server with the [Storefront REST APIs](https://docs.medusajs.com/api/store).
|
||||
|
||||
@@ -76,6 +76,6 @@ You can find more details about contributing in [CONTRIBUTING.md](https://github
|
||||
|
||||
## Community & Support
|
||||
|
||||
If you need any support during your development with Medusa, you can join our [Discord Server](https://discord.gg/medusajs). You will get help directly from our core team as well as our community.
|
||||
If you need any support during your development with Medusa, you can join Medusa's [Discord Server](https://discord.gg/medusajs). You will get help directly from Medusa's core team as well as the community.
|
||||
|
||||
By joining our Discord Server, you’ll also have the chance to participate in many events such as Bug Hunts and showcase your work with Medusa.
|
||||
By joining the Discord Server, you’ll also have the chance to participate in many events such as Bug Hunts and showcase your work with Medusa.
|
||||
@@ -1,57 +0,0 @@
|
||||
# Uploading images to MinIO
|
||||
|
||||
In order to work with images in Medusa, you need a file service plugin responsible for hosting. Following this guide will allow you to upload images to MinIO bucket.
|
||||
|
||||
### Before you start
|
||||
|
||||
At this point, you should have an instance of our store engine running. If not, we have a [full guide](https://docs.medusajs.com/tutorial/set-up-your-development-environment) for setting up your local environment.
|
||||
|
||||
### Set up MinIO
|
||||
|
||||
#### Create an MinIO bucket
|
||||
|
||||
In the MinIO console create a new bucket, then click into that bucket and change the `Access Policy` to `public`.
|
||||
|
||||
Be aware, that this will allow for anyone to acces your bucket. Avoid storing sensitive data.
|
||||
|
||||
#### Generate access keys
|
||||
|
||||
Navigate to users and perform the following steps:
|
||||
|
||||
- Enter new `Access Key` and `Secret Key`
|
||||
- Select readwrite policy
|
||||
- Submit the details
|
||||
|
||||
### Installation
|
||||
|
||||
First, install the plugin using your preferred package manager:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install medusa-file-minio
|
||||
```
|
||||
|
||||
Then configure your `medusa-config.js` to include the plugin alongside the required options:
|
||||
|
||||
```=javascript
|
||||
{
|
||||
resolve: `medusa-file-minio`,
|
||||
options: {
|
||||
endpoint: "minio.server.com",
|
||||
bucket: "test",
|
||||
access_key_id: "YOUR-ACCESS-KEY",
|
||||
secret_access_key: "YOUR-SECRET-KEY",
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
The two access keys in the options are the ones created in the previous section.
|
||||
|
||||
:::tip
|
||||
|
||||
Make sure to use an environment variable for the secret key in a live environment.
|
||||
|
||||
:::
|
||||
|
||||
### Try it out
|
||||
|
||||
Finally, run your Medusa server alongside our admin system to try out your new file service. Upon editing or creating products, you can now upload thumbnails and images, that are stored in an MinIO server.
|
||||
@@ -1,89 +0,0 @@
|
||||
# Uploading images to S3
|
||||
|
||||
In order to work with images in Medusa, you need a file service plugin responsible for hosting. Following this guide will allow you to upload images to AWS S3.
|
||||
|
||||
### Before you start
|
||||
|
||||
At this point, you should have an instance of our store engine running. If not, we have a [full guide](https://docs.medusajs.com/tutorial/set-up-your-development-environment) for setting up your local environment.
|
||||
|
||||
### Set up AWS
|
||||
|
||||
#### Create an S3 bucket
|
||||
|
||||
In the AWS console navigate to S3 and create a bucket for your images. Make sure to uncheck "Block _all_ public access".
|
||||
|
||||
Additionally, you need to add a policy to your bucket, that will allow public access to objects that are uploaded. Navigate to the permissions tab of your bucket and add the following policy:
|
||||
|
||||
```shell=
|
||||
{
|
||||
"Id": "Policy1397632521960",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "Stmt1397633323327",
|
||||
"Action": [
|
||||
"s3:GetObject"
|
||||
],
|
||||
"Effect": "Allow",
|
||||
"Resource": "arn:aws:s3:::YOUR-BUCKET-NAME/*",
|
||||
"Principal": {
|
||||
"AWS": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Be aware, that this will allow for anyone to acces your bucket. Avoid storing sensitive data.
|
||||
|
||||
#### Generate access keys
|
||||
|
||||
Navigate to the IAM section of your AWS console and perform the following steps:
|
||||
|
||||
- Add a new user with programmatic access
|
||||
- Add the existing **AmazonS3FullAccess** policy to the user
|
||||
- Submit the details
|
||||
|
||||
Upon successful creation of the user, you are presented with an **Access key ID** and a **Secret access key**. Note both of them down for later use.
|
||||
|
||||
### Installation
|
||||
|
||||
First, install the plugin using your preferred package manager:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install medusa-file-s3
|
||||
```
|
||||
|
||||
Then configure your `medusa-config.js` to include the plugin alongside the required options:
|
||||
|
||||
```=javascript
|
||||
{
|
||||
resolve: `medusa-file-s3`,
|
||||
options: {
|
||||
s3_url: "https://s3-guide-test.s3.eu-west-1.amazonaws.com",
|
||||
bucket: "test",
|
||||
region: "eu-west-1"
|
||||
access_key_id: "YOUR-ACCESS-KEY",
|
||||
secret_access_key: "YOUR-SECRET-KEY",
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
In the above options, an `s3_url` is included. The url has the following format:
|
||||
|
||||
```shell=
|
||||
https://[bucket].s3.[region].amazonaws.com
|
||||
```
|
||||
|
||||
The two access keys in the options are the ones created in the previous section.
|
||||
|
||||
:::tip
|
||||
|
||||
Make sure to use an environment variable for the secret key in a live environment.
|
||||
|
||||
:::
|
||||
|
||||
### Try it out
|
||||
|
||||
Finally, run your Medusa server alongside our admin system to try out your new file service. Upon editing or creating products, you can now upload thumbnails and images, that are stored in an AWS S3 bucket.
|
||||
@@ -1,52 +0,0 @@
|
||||
# Uploading images to Spaces
|
||||
|
||||
In order to work with images in Medusa, you need a file service plugin responsible for hosting. Following this guide will allow you to upload images to DigitalOcean Spaces.
|
||||
|
||||
### Before you start
|
||||
|
||||
At this point, you should have an instance of our store engine running. If not, we have a [full guide](https://docs.medusajs.com/tutorial/set-up-your-development-environment) for setting up your local environment.
|
||||
|
||||
### Set up DigitalOcean
|
||||
|
||||
#### Create a Space
|
||||
|
||||
Create an account on DigitalOcean and navigate to Spaces. Create a new Space with the default settings.
|
||||
|
||||
#### Generate access keys
|
||||
|
||||
Navigate to API in the left sidebar. Generate a new Spaces access key. This should provide you with an access key id and a secret key. Note them both down.
|
||||
|
||||
### Installation
|
||||
|
||||
First, install the plugin using your preferred package manager:
|
||||
|
||||
```bash npm2yarn
|
||||
npm install medusa-file-spaces
|
||||
```
|
||||
|
||||
Then configure your `medusa-config.js` to include the plugin alongside the required options:
|
||||
|
||||
```=javascript
|
||||
{
|
||||
resolve: `medusa-file-spaces`,
|
||||
options: {
|
||||
spaces_url: "https://test.fra1.digitaloceanspaces.com",
|
||||
bucket: "test",
|
||||
endpoint: "fra1.digitaloceanspaces.com",
|
||||
access_key_id: "YOUR-ACCESS-KEY",
|
||||
secret_access_key: "YOUR-SECRET-KEY",
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
In the above options, a `spaces_url` is included. This can be found in your Space overview. The `bucket` should point to the name you gave your Space. The `endpoint` identifies the region in which you created the Space. And finally the two keys are the ones created in the previous section.
|
||||
|
||||
:::tip
|
||||
|
||||
Make sure to use an environment variable for the secret key in a live environment.
|
||||
|
||||
:::
|
||||
|
||||
### Try it out!
|
||||
|
||||
Finally, run your Medusa server alongside our admin system to try out your new file service. Upon editing or creating products, you can now upload thumbnails and images, that are stored in DigitalOcean Spaces.
|
||||
@@ -4,7 +4,7 @@ title: Introduction
|
||||
|
||||
## Architecture overview
|
||||
|
||||
Medusa is composed of 3 components: The headless backend, the admin dashboard, and the storefront.
|
||||
Medusa is composed of three components: The headless backend, the admin dashboard, and the storefront.
|
||||
|
||||

|
||||
|
||||
@@ -18,10 +18,10 @@ Your Medusa server will include all functionalities related to your store’s ch
|
||||
|
||||
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. Our admin dashboard provides a lot of functionalities to manage your store including Order management, Product management, User management, and more.
|
||||
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 2 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/).
|
||||
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/).
|
||||
@@ -1,3 +1,4 @@
|
||||
<!-- vale off -->
|
||||
# Quickstart w. Docker
|
||||
|
||||
This quick start is intended for developers, that have already configured their local development environment and familiarised them selves with all the technologies and frameworks used throughout the Medusa eco-system.
|
||||
@@ -84,3 +85,5 @@ Add custom endpoint to your Medusa project
|
||||
Install and configure additional plugins
|
||||
|
||||
Build a storefront using our [Gatsby Starter](https://github.com/medusajs/gatsby-starter-medusa)
|
||||
|
||||
<!-- vale on -->
|
||||
@@ -45,7 +45,7 @@ You can install Node from the [official website](https://nodejs.org/en/).
|
||||
|
||||
### Test Your Server
|
||||
|
||||
After these 3 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:
|
||||
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
|
||||
curl localhost:9000/store/products | python -m json.tool
|
||||
@@ -79,7 +79,7 @@ You can learn more about configuring your server and loading environment variabl
|
||||
|
||||
## What's next :rocket:
|
||||
|
||||
- Install our [Next.js](../starters/nextjs-medusa-starter.md) or [Gatsby](../starters/gatsby-medusa-starter.md) storefronts to set up your ecommerce storefront quickly.
|
||||
- Install the [Next.js](../starters/nextjs-medusa-starter.md) or [Gatsby](../starters/gatsby-medusa-starter.md) storefronts to set up your ecommerce storefront quickly.
|
||||
- Install the [Medusa Admin](../admin/quickstart.md) to supercharge your ecommerce experience with easy access to configurations and features.
|
||||
- Check out the [API reference](https://docs.medusajs.com/api/store) to learn more about available endpoints available on your Medusa server.
|
||||
- Install [plugins](https://github.com/medusajs/medusa/tree/master/packages) for features like Payment, CMS, Notifications, among other features.
|
||||
@@ -52,7 +52,7 @@ To customize the components, pages, and UI of your Gatsby storefront, just edit
|
||||
|
||||
The Gatsby storefront uses the [gatsby-source-medusa](https://github.com/medusajs/medusa/tree/master/packages/gatsby-source-medusa) plugin to source data from your Medusa server. This data includes products, collections, and regions, and as a result, you can query this data in the storefront starter using GraphQL queries. You can also explore the data in your store on `localhost:8000/___graphql`.
|
||||
|
||||
Because of this, you must rebuild the site every time you update any of this data for it to be reflected in your storefront. We will soon be releasing a new version of the plugin which adds incremental builds, which will improve build times.
|
||||
Because of this, you must rebuild the site every time you update any of this data for it to be reflected in your storefront. The Medusa team will soon be releasing a new version of the plugin which adds incremental builds, which will improve build times.
|
||||
|
||||
### Change Port
|
||||
|
||||
@@ -77,7 +77,7 @@ STORE_CORS=http://localhost:<PORT>
|
||||
|
||||
:::info
|
||||
|
||||
For more details about the Store CORS configuration, check out the [Configure your Server documentation](../usage/configurations.md#storefront-cors).
|
||||
For more details about the Store Cross-Origin Resource Sharing (CORS) configuration, check out the [Configure your Server documentation](../usage/configurations.md#storefront-cors).
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# CORS issues
|
||||
|
||||
If you are experiencing connection issues when trying to access your Medusa server from a storefront, it is most likely due to CORS issues.
|
||||
If you are experiencing connection issues when trying to access your Medusa server from a storefront, it is most likely due to Cross-Origin Resource Sharing (CORS) issues.
|
||||
|
||||
You might see a log in your browser console, that looks like this:
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Documentation Error
|
||||
|
||||
If you have installed the dependencies in the root of the Medusa repository (i.e., if you have a `node_modules` directory at the root of the Medusa repository), this will cause an error when running the documentation website.
|
||||
If you have installed the dependencies in the root of the Medusa repository (that is, if you have a `node_modules` directory at the root of the Medusa repository), this will cause an error when running the documentation website.
|
||||
|
||||
This is because the content resides in `docs/content`. When that content is being imported from there, a mix up can happen between the dependencies in the root of the Medusa repository and the dependencies in `www/docs` which causes an `invalid hook call` error.
|
||||
|
||||
|
||||
@@ -15,4 +15,4 @@ medusa user -e some@email.com -p somepassword
|
||||
|
||||
## Additional Resources
|
||||
|
||||
Learn more about our CLI tool in the [CLI reference](../cli/reference.md).
|
||||
Learn more about Medusa's CLI tool in the [CLI reference](../cli/reference.md).
|
||||
@@ -138,13 +138,13 @@ npm install @medusajs/medusa-cli -g
|
||||
|
||||
## Optional Tools
|
||||
|
||||
These tools are not required to have to run a Medusa server, but we highly recommend that you have them installed.
|
||||
These tools are not required to have to run a Medusa server, but it's highly recommended that you have them installed.
|
||||
|
||||
### PostgreSQL
|
||||
|
||||
:::info
|
||||
|
||||
PostgreSQL is an open-source relational database system with more than 30 years of active development. It is robust, reliable, and ensures data integrity so there's no need to worry about those when you scale your project.
|
||||
PostgreSQL is an open-source relational database system with more than thirty years of active development. It is robust, reliable, and ensures data integrity so there's no need to worry about those when you scale your project.
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@@ -1,268 +0,0 @@
|
||||
---
|
||||
title: Adding custom functionality
|
||||
---
|
||||
|
||||
# Adding custom functionality
|
||||
|
||||
## Introduction
|
||||
|
||||
In the previous part of the tutorial we set up your Medusa project using the `medusa new` and started your Medusa server locally. In this part we will start adding some custom functionality that extends the core. In particular this tutorial will take you through adding custom services, custom endpoints and subscribers. The custom functionality that we will be adding will create an endpoint called `/welcome/:cart_id` which customers of your store can use to opt-in to receiving a welcome in their email inbox after completing their order.
|
||||
|
||||
The custom functionality will do a number of things:
|
||||
|
||||
- Create a custom service that handles the logic around opting in. The service will ensure that only first time buyers will receive a welcome.
|
||||
- Create a custom endpoint at `/welcome/:cart_id` which will take a `optin` parameter as part of its request body, and call our custom service.
|
||||
- Create a subscriber that listens for the `order.placed` event and tells the custom service to send a welcome.
|
||||
|
||||
## Services
|
||||
|
||||
We will begin our custom implementation by adding a custom service. In your project create a new file at `/src/services/welcome.js`. Open the newly created file and add a class:
|
||||
|
||||
```javascript
|
||||
import { BaseService } from "medusa-interfaces"
|
||||
|
||||
class WelcomeService extends BaseService {
|
||||
constructor({}) {
|
||||
super()
|
||||
}
|
||||
|
||||
async registerOptin(cartId, optin) {}
|
||||
|
||||
async sendWelcome(orderId) {}
|
||||
}
|
||||
|
||||
export default WelcomeService
|
||||
```
|
||||
|
||||
We will be filling out each of the methods in turn, but before we get to that it should be noted that placing files in `/src/services` has a special meaning in Medusa projects. When Medusa starts up it will look for files in this folder and register exports from these files to the global container. The global container holds all services and repositories in your Medusa project allowing for dependency injection. Dependency injection is a software development technique in which objects only receive other objects that it depends upon.
|
||||
|
||||
### `constructor`
|
||||
|
||||
We will see dependency injection in action now when implementing the constructor:
|
||||
|
||||
```javascript
|
||||
constructor({ cartService, orderService }) {
|
||||
super()
|
||||
|
||||
this.cartService_ = cartService
|
||||
|
||||
this.orderService_ = orderService
|
||||
}
|
||||
```
|
||||
|
||||
In the constructor we specify that our `WelcomeService` will depend upon the `cartService` and `orderService` and Medusa will make sure to provide those as the first argument to the constructor when starting up Medusa. We then keep a reference to these services within the `WelcomeService` so that we can use them later on.
|
||||
|
||||
:::note
|
||||
|
||||
Just like we can depend on the `cartService` and `orderService` other services will be able to depend on our newly created `WelcomeService`. The registration name of our service is the camelCased version of our file name with the registration type appended. I.e. `/src/services/welcome.js` -> `welcomeService`.
|
||||
|
||||
:::
|
||||
|
||||
### `registerOptin`
|
||||
|
||||
The `registerOption` function will take two arguments: `cartId` and `optin`, where `cartId` holds the id of the cart that we wish to register optin for and `optin` is a boolean to indicate if the customer has accepted or optin or not. We will save the `optin` preferences in the cart's `metadata` field, so that it can be persisted for the future when we need to evaluate if we should send the welcome or not.
|
||||
|
||||
```javascript
|
||||
async registerOptin(cartId, optin) {
|
||||
if (typeof optin !== "boolean") {
|
||||
throw new Error("optin must be a boolean value.")
|
||||
}
|
||||
|
||||
return await this.cartService_.update(cartId, {
|
||||
metadata: { welcome_optin: optin }
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
The `registerOptin` implementation simply validates that the provided argument is of the correct type and calls the CartService function `update`. `update` takes two arguments: the first is the id of the cart to update and the second is an object that with the key/value pairs that we want to update. In this case we are updating the metadata on the cart. The `metadata` field on the cart is itself an object so we need to pass an object when updating this field.
|
||||
|
||||
:::note
|
||||
|
||||
Most entities in Medusa have a `metadata` field that can be used for customizations or integrations when it is necessary to persist some data relating to the entity. Metadata cannot be overridden by other
|
||||
plugins.
|
||||
|
||||
:::
|
||||
|
||||
### `sendWelcome`
|
||||
|
||||
The final function to implement in our class is the `sendWelcome` function that takes one argument `orderId` which holds the id of an order that we will evaluate whether to send a welcome for. In the implementation we leverage that when an order is created from a cart all the cart's metadata is copied to the order. We can therefore check `metadata.welcome_optin` to evaluate if the customer has allowed us to send a welcome to their email.
|
||||
|
||||
```javascript
|
||||
async sendWelcome(orderId) {
|
||||
const order = await this.orderService_.retrieve(orderId, {
|
||||
select: ["email", "customer_id", "metadata"]
|
||||
})
|
||||
|
||||
const prevOrders = await this.orderService_.list({
|
||||
customer_id: order.customer_id
|
||||
}, {
|
||||
select: ["id"]
|
||||
})
|
||||
|
||||
if (prevOrders.length > 1) {
|
||||
// We only send welcomes to new customers. This customer
|
||||
// has already completed an order before so we can stop.
|
||||
return
|
||||
}
|
||||
|
||||
if (order.metadata && order.metadata.welcome_optin) {
|
||||
// Customer opted in so we should send an email
|
||||
return await someEmailSender.send({
|
||||
to: order.email,
|
||||
subject: "Welcome to our Medusa Store!",
|
||||
body: `We are so happy to have you!`
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In the above implementation we are first retrieving the order that we need to check if we should send a welcome for. We are selecting only the fields that we need. In this case the `email` on the order, we will use this if we need to send out the welcome email, the `customer_id` which is used to determine if the customer has completed prior orders and `metadata` to check if the customer opted in to receiving the welcome email.
|
||||
|
||||
After retrieving the order we list all orders that have the same `customer_id` as the order we just retrieved. We are only interested in the count of these orders so it is sufficient for us to just select the ids of these orders.
|
||||
|
||||
We then check if the number of previous orders is greater than 1, indicating that the customer has previously purchased anything from our store. If the number of previous orders is greater than 1 we can exit our function prematurely as we only send welcomes to new customers.
|
||||
|
||||
The final part of the implementation checks if the `welcome_optin` metadata has been set to true. If the customer has opted in we use `someEmailService.send` to trigger and email dispatch to the email stored on the order. In this case `someEmailSender` could be any email service for example Sendgrid, SES, Mailgun, etc.
|
||||
|
||||
:::note
|
||||
|
||||
If you have `medusa-plugin-sendgrid` installed you can use `sendgridService` in your constructor to use it later in `sendWelcome`. You will then be able to do `sendgridService.send({ ... })`.
|
||||
|
||||
:::
|
||||
|
||||
We have completed the implementation of our custom service and we will now be able to call it from elsewhere in our project.
|
||||
|
||||
## Endpoints
|
||||
|
||||
Similarly to the `/src/services` directory, the `/src/api` directory has a special meaning in Medusa. Exports from this directory are assumed to be functions that return an express router instance that will be registered on the internal express app that Medusa creates when starting your server. This allows you to create custom endpoints for custom functionality. We will use this to create the custom endpoint that customers can use to give there welcome opt-in.
|
||||
|
||||
Create a new file at `/src/api/index.js` and add the following controller:
|
||||
|
||||
```javascript
|
||||
import { Router } from "express"
|
||||
import bodyParser from "body-parser"
|
||||
|
||||
export default () => {
|
||||
const app = Router()
|
||||
|
||||
app.post("/welcome/:cart_id", bodyParser.json(), async (req, res) => {
|
||||
// TODO
|
||||
})
|
||||
|
||||
return app
|
||||
}
|
||||
```
|
||||
|
||||
### Controller implementation
|
||||
|
||||
Our endpoint controller's implementation will be very simple. It will extract the `id` from the path paramater and the `optin` flag from the request body. We will then use these values to call our the `WelcomeService`, which will take care of updating the cart metadata for later.
|
||||
|
||||
```javascript
|
||||
app.post("/welcome/:cart_id", bodyParser.json(), async (req, res) => {
|
||||
const { cart_id } = req.params
|
||||
const { optin } = req.body
|
||||
|
||||
// Validate that the optin value was provided.
|
||||
// If not respond with a Bad Request status
|
||||
if (typeof optin !== "boolean") {
|
||||
res.status(400).json({
|
||||
message: "You must provide an boolean optin value in the request body",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const welcomeService = req.scope.resolve("welcomeService")
|
||||
|
||||
try {
|
||||
await welcomeService.registerOptin(cart_id, optin)
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
})
|
||||
} catch (err) {
|
||||
// This is not supposed to happen.
|
||||
res.status(500).json({
|
||||
message: "Something unexpected happened.",
|
||||
})
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
In the implementation above we are first validating that the request body is structured correctly so that we can proceed with our opt-in registration. If the validation fails we respond with 400 Bad Request which is an HTTP code that indicates that the client that sent the request has not provided the correct values.
|
||||
|
||||
After validation is passed we leverage Medusa's container system again to fetch our custom service. When Medusa starts up it places an object on the express `req` object called `scope` which contains the function `resolve` that can be used to get any of the services registered in Medusa by simply providing the registration name as a string. In this case we are resolving our custom `welcomeService`, but you can resolve any service such as the `cartService` or `orderService` using this function.
|
||||
|
||||
We put our `registerOptin` function call in a try-catch block to ensure that we can handle unexpected errors. If the call to `registerOptin` succeeds we respond with 200 OK and if for some reason we encounter an error we respond with 500 Internal Server Error.
|
||||
|
||||
We have now completed the implementation necessary to complete opt-in registration on a cart. To test that your implementation is working correctly start up your Medusa server using: `medusa develop`. You can now send requests to the server, first create a new cart using:
|
||||
|
||||
```shell
|
||||
curl -X POST localhost:9000/store/carts | python -m json.tool
|
||||
```
|
||||
|
||||
The copy the cart id (the one that starts with `cart_`) and use it to opt-in to the welcome pack using:
|
||||
|
||||
```shell
|
||||
curl -X POST \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{ "optin": true }' \
|
||||
localhost:9000/welcome/[copied cart id]
|
||||
```
|
||||
|
||||
The endpoint should respond with `{"success":true}`. If you wish to check that the `metadata` field has been updated you can fetch the created cart by doing:
|
||||
|
||||
```shell
|
||||
curl -X GET localhost:9000/store/carts/[copied cart id] | python -m json.tool
|
||||
```
|
||||
|
||||
The response should contain the cart with the metadata field set like this:
|
||||
|
||||
```
|
||||
{
|
||||
"cart": {
|
||||
...,
|
||||
"metadata": {
|
||||
"welcome_optin": true
|
||||
},
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Subscribers
|
||||
|
||||
The final thing that we will add in this part of the tutorial is the subscriber that listens for the `order.placed` event and sends out emails if the user has opted in for welcomes. Again we will leverage one of the special directories in Medusa that makes dependency injection easy and automatic. The directory to place a file in this time is the `/src/subscribers` directory, which treats exports as subscribers and makes sure the inject dependencies in a similar fashion to what we saw with services. To get started with our implementation create a file at `/src/subscribers/welcome.js` and add the following:
|
||||
|
||||
```javascript
|
||||
class WelcomeSubscriber {
|
||||
constructor({ welcomeService, eventBusService }) {
|
||||
this.welcomeService_ = welcomeService
|
||||
|
||||
eventBusService.subscribe("order.placed", this.handleWelcome)
|
||||
}
|
||||
|
||||
handleWelcome = async (data) => {
|
||||
return await this.welcomeService_.sendWelcome(data.id)
|
||||
}
|
||||
}
|
||||
|
||||
export default WelcomeSubscriber
|
||||
```
|
||||
|
||||
The implementation above is all that is needed to automate the `sendWelcome` function to be called every time a new order is created. The subscriber class here delegates all of the business logic to the `sendWelcome` function, where we are checking for opt-in and first time buyers.
|
||||
|
||||
If we take a closer look at the constructor it will seem pretty familiar. Just like with our custom service, we are indicating which dependencies we would like to receive and Medusa will make sure to pass these on as the first argument to our constructor. In this case we are depending on the `welcomeService` which is used to take care of sending welcomes, and the `eventBusService` which is a core service in Medusa that handles events across your server allowing you to subscribe to events of interest. In this case we are using the `eventBusService` to subscribe to the `order.placed` event which is emitted every time a new order is created. The subscription is registered by the `eventBusService.subscribe` function which takes the event name to subscribe to as its first argument and a callback function to call when the event occurs, as its second argument.
|
||||
|
||||
In this case we are using the `handleWelcome` function as our callback. The callback function receives the data that is passed for the event. The `order.placed` event contains the order id in the data object which is what the `welcomeService` needs to handle the sending logic so we simply call `sendWelcome` with `data.id`.
|
||||
|
||||
You can now start up your server and test out the subscriber. Given that you have opted in to receiving welcome emails you can complete an order and you should receive an email with the welcome message.
|
||||
|
||||
## Summary
|
||||
|
||||
You have now learned how to add custom functionality to your Medusa server, which is one of the most powerful features of the Medusa core. The example above is quite simple, yet we have covered many of the customization capabilities available. We first looked at how to include custom business logic in Medusa by using services and dependency injection. Afterwards we put that logic to use when implementing our custom endpoint and in the final part of the tutorial we added some simple automation that handles sending the welcome message on every new order.
|
||||
|
||||
### What's next?
|
||||
|
||||
You have now been introduced to many of the key parts of Medusa and with your knowledge of customization you can now begin creating some really powerful commerce experiences. If you have an idea for a cool customization go ahead and make it right now! If you are not completely ready yet you can browse the reference docs further.
|
||||
|
||||
<!-- In the next part of this tutorial we will look into linking your local project with Medusa Cloud to make development smoother while leveraging the powerful management tools that merchants use to manage their Medusa store. -->
|
||||
@@ -2,6 +2,8 @@
|
||||
title: Linking your local project with Medusa Cloud
|
||||
---
|
||||
|
||||
<!-- vale off -->
|
||||
|
||||
# Linking your local project with Medusa Cloud
|
||||
|
||||
## Introduction
|
||||
@@ -64,3 +66,5 @@ You are all set to start developing on your Medusa project. If you haven't alrea
|
||||
- [Gatsby Starter](https://github.com/medusajs/gatsby-starter-medusa)
|
||||
|
||||
The final step to take from here is to deploy your Medusa project. We will cover how this is done in the next part of the tutorial (Coming soon!).
|
||||
|
||||
<!-- vale on -->
|
||||
@@ -1,5 +1,7 @@
|
||||
# Collected Usage Information
|
||||
|
||||
<!-- vale docs.We = NO -->
|
||||
|
||||
This document gives an overview of Medusa’s optional collected usage information, how it helps Medusa become a better platform, and how developers can opt out of this feature.
|
||||
|
||||
## Overview
|
||||
@@ -48,3 +50,5 @@ Or, you can run the following command in the root of your Medusa server project
|
||||
```bash
|
||||
medusa telemetry --disable
|
||||
```
|
||||
|
||||
<!-- vale docs.We = YES -->
|
||||
@@ -71,7 +71,7 @@ npm install dotenv --save
|
||||
|
||||
## Database Configuration
|
||||
|
||||
Medusa supports 2 database types: SQLite and PostgreSQL.
|
||||
Medusa supports two database types: SQLite and PostgreSQL.
|
||||
|
||||
:::tip
|
||||
|
||||
@@ -81,7 +81,7 @@ You can use SQLite for development purposes, however, it’s recommended to use
|
||||
|
||||
### SQLite Configurations
|
||||
|
||||
For SQLite you mainly need 2 configurations:
|
||||
For SQLite you mainly need two configurations:
|
||||
|
||||
```jsx
|
||||
module.exports = {
|
||||
@@ -103,7 +103,7 @@ Before getting started with configuring PostgreSQL, you should have created a Po
|
||||
|
||||
:::
|
||||
|
||||
For PostgreSQL you mainly need 2 configurations:
|
||||
For PostgreSQL you mainly need two configurations:
|
||||
|
||||
```jsx
|
||||
module.exports = {
|
||||
@@ -181,9 +181,9 @@ You can learn more about Subscribers and events in the [Subscriber documentation
|
||||
|
||||
:::
|
||||
|
||||
## JSON Web Token (JWT) Secret
|
||||
## JWT Secret
|
||||
|
||||
Medusa uses JWT to handle user authentication. To set the JWT secret:
|
||||
Medusa uses JSON Web Token (JWT) to handle user authentication. To set the JWT secret:
|
||||
|
||||
```jsx
|
||||
module.exports = {
|
||||
@@ -353,6 +353,6 @@ It is recommended to use environment variables to store values of options instea
|
||||
|
||||
## What’s Next 🚀
|
||||
|
||||
- Check out our [Next.js](../starters/nextjs-medusa-starter.md) and [Gatsby](../starters/gatsby-medusa-starter.md) starter storefronts.
|
||||
- Check out the [Next.js](../starters/nextjs-medusa-starter.md) and [Gatsby](../starters/gatsby-medusa-starter.md) starter storefronts.
|
||||
- Install the [Medusa admin](../admin/quickstart.md).
|
||||
- Learn about [deploying the Medusa server](../deployments/server/index.mdx).
|
||||
@@ -3,15 +3,15 @@ import TabItem from '@theme/TabItem';
|
||||
|
||||
# Use create-medusa-app
|
||||
|
||||
In this document, you’ll learn how to use `create-medusa-app` to create a Medusa project with the 3 main components of Medusa.
|
||||
In this document, you’ll learn how to use `create-medusa-app` to create a Medusa project with the three main components of Medusa.
|
||||
|
||||
## Overview
|
||||
|
||||
As explained in the [Introduction guide](../introduction.md), Medusa is composed of 3 different components: the headless server, the storefront, and the admin dashboard.
|
||||
As explained in the [Introduction guide](../introduction.md), Medusa is composed of three different components: the headless server, the storefront, and the admin dashboard.
|
||||
|
||||
Medusa provides the necessary tools and resources to set up the 3 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.
|
||||
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 3 components, you can easily make use of the `create-medusa-app` command instead of creating each separately.
|
||||
However, if you’re interested in using Medusa’s starters for the three components, you can easily 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.
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ To delete a denomination:
|
||||
|
||||
:::info
|
||||
|
||||
You can add up to 10 images for a Gift Card.
|
||||
You can add up to ten images for a Gift Card.
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ This user guide is intended to help users learn how they can use the Medusa admi
|
||||
|
||||
:::tip
|
||||
|
||||
If you don’t have a Medusa admin yet, you can check [our live demo](https://demo.medusajs.com/)!
|
||||
If you don’t have a Medusa admin yet, you can check [the live demo](https://demo.medusajs.com/)!
|
||||
|
||||
:::
|
||||
|
||||
@@ -69,8 +69,8 @@ At the top right, you’ll find an avatar icon. By clicking this icon, you’ll
|
||||
|
||||

|
||||
|
||||
### Need Help?
|
||||
### Need Help
|
||||
|
||||
At the top right, you’ll find a <UiIcon lightIcon="https://i.imgur.com/CrABja9.png" darkIcon="https://i.imgur.com/cgeX2hP.png" alt="question mark" /> icon. When you click on this icon, a form will pop up. You can use this form to send the Medusa team a message asking for help. Our team usually responds in a few hours on business days.
|
||||
At the top right, you’ll find a <UiIcon lightIcon="https://i.imgur.com/CrABja9.png" darkIcon="https://i.imgur.com/cgeX2hP.png" alt="question mark" /> icon. When you click on this icon, a form will pop up. You can use this form to send the Medusa team a message asking for help. The Medusa team usually responds in a few hours on business days.
|
||||
|
||||

|
||||
@@ -136,7 +136,7 @@ To cancel a claim’s fulfillment:
|
||||
|
||||
1. Open the order details page.
|
||||
2. Scroll down to the Fulfillment section.
|
||||
3. Find the fulfillment you want to cancel. A claim’s fulfillment’s title should be prefixed with “Claim fulfillment”.
|
||||
3. Find the fulfillment you want to cancel. A claim’s fulfillment’s title should be prefixed with “Claim fulfillment”.
|
||||
4. Click on the <UiIcon lightIcon="https://i.imgur.com/1ordBC6.png" darkIcon="https://i.imgur.com/dSwWYBH.png" alt="three dots" /> icon next to it.
|
||||
5. Click on Cancel Fulfillment in the dropdown.
|
||||
6. Confirm canceling the fulfillment by clicking the “Yes, confirm” button in the pop-up.
|
||||
|
||||
@@ -14,7 +14,7 @@ Taxes are calculated for products and shipping methods on checkout. Medusa provi
|
||||
|
||||
---
|
||||
|
||||
## How are Taxes Created?
|
||||
## How are Taxes Created
|
||||
|
||||
Once a region is created, a default tax rate is created for that region. You can specify the rate and code of the tax rate during the creation of the region.
|
||||
|
||||
|
||||
@@ -58,6 +58,6 @@ To delete a tax rate:
|
||||
|
||||
:::info
|
||||
|
||||
Default tax rates can’t be deleted. If you don’t want to apply any taxes in a region, you can instead set the default tax rate to 0.
|
||||
Default tax rates can’t be deleted. If you don’t want to apply any taxes in a region, you can instead set the default tax rate to zero.
|
||||
|
||||
:::
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
list=""
|
||||
# get directories in content other than reference
|
||||
for i in `find content -type d -maxdepth 1 -not -path 'content/references' -not -path 'content'`
|
||||
do
|
||||
if [ ${#list} -gt 0 ]; then
|
||||
list+=','
|
||||
fi
|
||||
list+="\"docs/$i\""
|
||||
done
|
||||
#get files in content (not nested)
|
||||
for i in `find content -type f -maxdepth 1 -not -path 'content/references'`
|
||||
do
|
||||
if [ ${#list} -gt 0 ]; then
|
||||
list+=','
|
||||
fi
|
||||
list+="\"docs/$i\""
|
||||
done
|
||||
echo "::set-output name=LIST::[$list]"
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
|
||||
list=""
|
||||
alertLevel=$1
|
||||
|
||||
if [ ${#alertLevel} -eq 0 ]; then
|
||||
alertLevel="suggestion"
|
||||
fi
|
||||
|
||||
# get directories in content other than reference
|
||||
for i in `find content -type d -maxdepth 1 -not -path 'content/references' -not -path 'content'`
|
||||
do
|
||||
if [ ${#list} -gt 0 ]; then
|
||||
list+=' '
|
||||
fi
|
||||
list+="docs/$i"
|
||||
done
|
||||
#get files in content (not nested)
|
||||
for i in `find content -type f -maxdepth 1 -not -path 'content/references'`
|
||||
do
|
||||
if [ ${#list} -gt 0 ]; then
|
||||
list+=' '
|
||||
fi
|
||||
list+="docs/$i"
|
||||
done
|
||||
|
||||
cd ..
|
||||
exec vale $list --minAlertLevel $alertLevel
|
||||
@@ -0,0 +1,4 @@
|
||||
(?i)Medusa
|
||||
(?i)Qovery
|
||||
(?i)Netlify
|
||||
(?i)s3
|
||||
Whitespace-only changes.
@@ -0,0 +1,73 @@
|
||||
extends: conditional
|
||||
message: "'%s' has no definition."
|
||||
link: https://medusajs.notion.site/Style-Guide-Docs-fad86dd1c5f84b48b145e959f36628e0#4a59adcd20a949008302f27502921933
|
||||
level: error
|
||||
ignorecase: false
|
||||
scope: paragraph
|
||||
# Ensures that the existence of 'first' implies the existence of 'second'.
|
||||
first: '\b([A-Z]{3,5})\b'
|
||||
second: '(?:\b[A-Z][a-z]+ )+\(([A-Z]{3,5})\)'
|
||||
# ... with the exception of these:
|
||||
exceptions:
|
||||
- API
|
||||
- ASP
|
||||
- CLI
|
||||
- CPU
|
||||
- CSS
|
||||
- CSV
|
||||
- DEBUG
|
||||
- DOM
|
||||
- DPI
|
||||
- FAQ
|
||||
- GCC
|
||||
- GDB
|
||||
- GET
|
||||
- GPU
|
||||
- GTK
|
||||
- GUI
|
||||
- HTML
|
||||
- HTTP
|
||||
- HTTPS
|
||||
- IDE
|
||||
- JAR
|
||||
- JSON
|
||||
- JSX
|
||||
- LESS
|
||||
- LLDB
|
||||
- NET
|
||||
- NOTE
|
||||
- NVDA
|
||||
- OSS
|
||||
- PATH
|
||||
- PDF
|
||||
- PHP
|
||||
- POST
|
||||
- RAM
|
||||
- REPL
|
||||
- RSA
|
||||
- SCM
|
||||
- SCSS
|
||||
- SDK
|
||||
- SQL
|
||||
- SSH
|
||||
- SSL
|
||||
- SVG
|
||||
- TBD
|
||||
- TCP
|
||||
- TODO
|
||||
- URI
|
||||
- URL
|
||||
- USB
|
||||
- UTF
|
||||
- XML
|
||||
- XSS
|
||||
- YAML
|
||||
- ZIP
|
||||
- AWS
|
||||
- REST
|
||||
- MDX
|
||||
- NPM
|
||||
- SMS
|
||||
- SID
|
||||
- VIP
|
||||
- UPS
|
||||
@@ -0,0 +1,120 @@
|
||||
extends: substitution
|
||||
message: "Consider using '%s' instead of '%s'."
|
||||
link: https://medusajs.notion.site/Style-Guide-Docs-fad86dd1c5f84b48b145e959f36628e0#426bd116f42d42859d3572c2de9f73f7
|
||||
ignorecase: true
|
||||
level: suggestion
|
||||
action:
|
||||
name: replace
|
||||
swap:
|
||||
"approximate(?:ly)?": about
|
||||
abundance: plenty
|
||||
accelerate: speed up
|
||||
accentuate: stress
|
||||
accompany: go with
|
||||
accomplish: carry out|do
|
||||
accorded: given
|
||||
accordingly: so
|
||||
accrue: add
|
||||
accurate: right|exact
|
||||
acquiesce: agree
|
||||
acquire: get|buy
|
||||
additional: more|extra
|
||||
address: discuss
|
||||
addressees: you
|
||||
adjacent to: next to
|
||||
adjustment: change
|
||||
admissible: allowed
|
||||
advantageous: helpful
|
||||
advise: tell
|
||||
aggregate: total
|
||||
aircraft: plane
|
||||
alleviate: ease
|
||||
allocate: assign|divide
|
||||
alternatively: or
|
||||
alternatives: choices|options
|
||||
ameliorate: improve
|
||||
amend: change
|
||||
anticipate: expect
|
||||
apparent: clear|plain
|
||||
ascertain: discover|find out
|
||||
assistance: help
|
||||
attain: meet
|
||||
attempt: try
|
||||
authorize: allow
|
||||
belated: late
|
||||
bestow: give
|
||||
cease: stop|end
|
||||
collaborate: work together
|
||||
commence: begin
|
||||
compensate: pay
|
||||
component: part
|
||||
comprise: form|include
|
||||
concept: idea
|
||||
concerning: about
|
||||
confer: give|award
|
||||
consequently: so
|
||||
consolidate: merge
|
||||
constitutes: forms
|
||||
contains: has
|
||||
convene: meet
|
||||
demonstrate: show|prove
|
||||
depart: leave
|
||||
designate: choose
|
||||
desire: want|wish
|
||||
determine: decide|find
|
||||
detrimental: bad|harmful
|
||||
disclose: share|tell
|
||||
discontinue: stop
|
||||
disseminate: send|give
|
||||
eliminate: end
|
||||
elucidate: explain
|
||||
employ: use
|
||||
enclosed: inside|included
|
||||
encounter: meet
|
||||
endeavor: try
|
||||
enumerate: count
|
||||
equitable: fair
|
||||
equivalent: equal
|
||||
exclusively: only
|
||||
expedite: hurry
|
||||
facilitate: ease
|
||||
females: women
|
||||
finalize: complete|finish
|
||||
frequently: often
|
||||
identical: same
|
||||
incorrect: wrong
|
||||
indication: sign
|
||||
initiate: start|begin
|
||||
itemized: listed
|
||||
jeopardize: risk
|
||||
liaise: work with|partner with
|
||||
maintain: keep|support
|
||||
methodology: method
|
||||
modify: change
|
||||
monitor: check|watch
|
||||
multiple: many
|
||||
necessitate: cause
|
||||
notify: tell
|
||||
numerous: many
|
||||
objective: aim|goal
|
||||
obligate: bind|compel
|
||||
optimum: best|most
|
||||
permit: let
|
||||
portion: part
|
||||
possess: own
|
||||
previous: earlier
|
||||
previously: before
|
||||
prioritize: rank
|
||||
procure: buy
|
||||
provide: give|offer
|
||||
purchase: buy
|
||||
relocate: move
|
||||
solicit: request
|
||||
state-of-the-art: latest
|
||||
subsequent: later|next
|
||||
substantial: large
|
||||
sufficient: enough
|
||||
terminate: end
|
||||
transmit: send
|
||||
utilization: use
|
||||
utilize: use
|
||||
@@ -0,0 +1,49 @@
|
||||
extends: substitution
|
||||
message: "Use '%s' instead of '%s'."
|
||||
level: suggestion
|
||||
ignorecase: true
|
||||
action:
|
||||
name: replace
|
||||
swap:
|
||||
are not: aren't
|
||||
cannot: can't
|
||||
could not: couldn't
|
||||
did not: didn't
|
||||
do not: don't
|
||||
does not: doesn't
|
||||
has not: hasn't
|
||||
have not: haven't
|
||||
how is: how's
|
||||
is not: isn't
|
||||
|
||||
'it is(?!\.)': it's
|
||||
'it''s(?=\.)': it is
|
||||
|
||||
should not: shouldn't
|
||||
|
||||
'that is(?!\.)': that's
|
||||
'that''s(?=\.)': that is
|
||||
|
||||
'they are(?!\.)': they're
|
||||
'they''re(?=\.)': they are
|
||||
|
||||
was not: wasn't
|
||||
|
||||
'we are(?!\.)': we're
|
||||
'we''re(?=\.)': we are
|
||||
|
||||
'we have(?!\.)': we've
|
||||
'we''ve(?=\.)': we have
|
||||
|
||||
were not: weren't
|
||||
|
||||
'what is(?!\.)': what's
|
||||
'what''s(?=\.)': what is
|
||||
|
||||
'when is(?!\.)': when's
|
||||
'when''s(?=\.)': when is
|
||||
|
||||
'where is(?!\.)': where's
|
||||
'where''s(?=\.)': where is
|
||||
|
||||
will not: won't
|
||||
@@ -0,0 +1,16 @@
|
||||
extends: existence
|
||||
message: "Avoid using first person (such as '%s')"
|
||||
link: https://medusajs.notion.site/Style-Guide-Docs-fad86dd1c5f84b48b145e959f36628e0#9f0dc7c440b841d3bfcb006df12c2652
|
||||
ignorecase: true
|
||||
level: error
|
||||
nonword: true
|
||||
tokens:
|
||||
- (?:^|\s)I\s
|
||||
- (?:^|\s)I,\s
|
||||
- \bI'd\b
|
||||
- \bI'll\b
|
||||
- \bI'm\b
|
||||
- \bI've\b
|
||||
- \bme\b
|
||||
- \bmy\b
|
||||
- \bmine\b
|
||||
@@ -0,0 +1,11 @@
|
||||
extends: substitution
|
||||
message: "Use '%s' instead of '%s'."
|
||||
ignorecase: true
|
||||
level: error
|
||||
nonword: true
|
||||
action:
|
||||
name: replace
|
||||
swap:
|
||||
'\b(?:eg|e\.g\.)[\s,]': for example
|
||||
'\b(?:ie|i\.e\.)[\s,]': that is
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
extends: existence
|
||||
message: "Don't use '%s'."
|
||||
level: error
|
||||
ignorecase: true
|
||||
tokens:
|
||||
- he/she
|
||||
- s/he
|
||||
@@ -0,0 +1,8 @@
|
||||
extends: existence
|
||||
message: "Capitalize '%s'."
|
||||
link: https://medusajs.notion.site/Style-Guide-Docs-fad86dd1c5f84b48b145e959f36628e0#a5043fc5f8bc4b0b84f3ba494f817e42
|
||||
nonword: true
|
||||
level: error
|
||||
scope: heading
|
||||
tokens:
|
||||
- ':\s[a-z]'
|
||||
@@ -0,0 +1,13 @@
|
||||
extends: existence
|
||||
message: "Don't use end punctuation in headings."
|
||||
link: https://medusajs.notion.site/Style-Guide-Docs-fad86dd1c5f84b48b145e959f36628e0#a5043fc5f8bc4b0b84f3ba494f817e42
|
||||
nonword: true
|
||||
level: error
|
||||
scope: heading
|
||||
action:
|
||||
name: edit
|
||||
params:
|
||||
- remove
|
||||
- '.?!'
|
||||
tokens:
|
||||
- '[a-z][.?!](?:\s|$)'
|
||||
@@ -0,0 +1,8 @@
|
||||
extends: existence
|
||||
message: "Consider adding npm2yarn to ```bash"
|
||||
link: https://docs.medusajs.com/contribution-guidelines#npm-and-yarn-code-blocks
|
||||
level: warning
|
||||
scope: code
|
||||
ignorecase: true
|
||||
raw:
|
||||
- '```bash[\n]+npm'
|
||||
@@ -0,0 +1,11 @@
|
||||
extends: substitution
|
||||
message: Use '%s' instead of '%s'
|
||||
link: https://docs.medusajs.com/contribution-guidelines#expand-commands
|
||||
level: error
|
||||
scope: code
|
||||
ignorecase: false
|
||||
# swap maps tokens in form of bad: good
|
||||
swap:
|
||||
npm i: npm install
|
||||
npm start: npm run start
|
||||
npm build: npm run build
|
||||
@@ -0,0 +1,8 @@
|
||||
extends: existence
|
||||
message: "The -g option should be added at the end of the command"
|
||||
link: https://docs.medusajs.com/contribution-guidelines#global-option
|
||||
level: error
|
||||
scope: code
|
||||
ignorecase: true
|
||||
raw:
|
||||
- '(npm (i|install) (-g|--global)|npm (-g|--global) (i|install))'
|
||||
@@ -0,0 +1,14 @@
|
||||
extends: existence
|
||||
message: "Numbers must be spelled out"
|
||||
link: https://medusajs.notion.site/Style-Guide-Docs-fad86dd1c5f84b48b145e959f36628e0#24a7270d3eee4d8e97657b0e12cd979a
|
||||
level: error
|
||||
ignorecase: true
|
||||
scope: paragraph
|
||||
tokens:
|
||||
- '.*[0-9]+\s(?!(AM|PM))+' #need to match words before to add exceptions
|
||||
- '.*[0-9][.]'
|
||||
exceptions:
|
||||
- '[pP]ort [0-9]+'
|
||||
- 'WSL2'
|
||||
- '[vV]ersions? [0-9]'
|
||||
- '[v.]+[0-9]+'
|
||||
@@ -0,0 +1,12 @@
|
||||
extends: existence
|
||||
message: "Don't add -ly to an ordinal number."
|
||||
level: suggestion
|
||||
action:
|
||||
name: edit
|
||||
params:
|
||||
- trim
|
||||
- ly
|
||||
tokens:
|
||||
- firstly
|
||||
- secondly
|
||||
- thirdly
|
||||
@@ -0,0 +1,7 @@
|
||||
extends: existence
|
||||
message: "Avoid using our"
|
||||
link: https://medusajs.notion.site/Style-Guide-Docs-fad86dd1c5f84b48b145e959f36628e0#9f0dc7c440b841d3bfcb006df12c2652
|
||||
level: warning
|
||||
ignorecase: true
|
||||
tokens:
|
||||
- ours?
|
||||
@@ -0,0 +1,8 @@
|
||||
extends: existence
|
||||
message: "Use the Oxford comma in '%s'."
|
||||
link: https://docs.microsoft.com/en-us/style-guide/punctuation/commas
|
||||
scope: sentence
|
||||
level: suggestion
|
||||
nonword: true
|
||||
tokens:
|
||||
- '(?:[^\s,]+,){1,} \w+ (?:and|or) \w+[.?!]'
|
||||
@@ -0,0 +1,183 @@
|
||||
extends: existence
|
||||
message: "'%s' looks like passive voice."
|
||||
ignorecase: true
|
||||
level: warning
|
||||
raw:
|
||||
- \b(am|are|were|being|is|been|was|be)\b\s*
|
||||
tokens:
|
||||
- '[\w]+ed'
|
||||
- awoken
|
||||
- beat
|
||||
- become
|
||||
- been
|
||||
- begun
|
||||
- bent
|
||||
- beset
|
||||
- bet
|
||||
- bid
|
||||
- bidden
|
||||
- bitten
|
||||
- bled
|
||||
- blown
|
||||
- born
|
||||
- bought
|
||||
- bound
|
||||
- bred
|
||||
- broadcast
|
||||
- broken
|
||||
- brought
|
||||
- built
|
||||
- burnt
|
||||
- burst
|
||||
- cast
|
||||
- caught
|
||||
- chosen
|
||||
- clung
|
||||
- come
|
||||
- cost
|
||||
- crept
|
||||
- cut
|
||||
- dealt
|
||||
- dived
|
||||
- done
|
||||
- drawn
|
||||
- dreamt
|
||||
- driven
|
||||
- drunk
|
||||
- dug
|
||||
- eaten
|
||||
- fallen
|
||||
- fed
|
||||
- felt
|
||||
- fit
|
||||
- fled
|
||||
- flown
|
||||
- flung
|
||||
- forbidden
|
||||
- foregone
|
||||
- forgiven
|
||||
- forgotten
|
||||
- forsaken
|
||||
- fought
|
||||
- found
|
||||
- frozen
|
||||
- given
|
||||
- gone
|
||||
- gotten
|
||||
- ground
|
||||
- grown
|
||||
- heard
|
||||
- held
|
||||
- hidden
|
||||
- hit
|
||||
- hung
|
||||
- hurt
|
||||
- kept
|
||||
- knelt
|
||||
- knit
|
||||
- known
|
||||
- laid
|
||||
- lain
|
||||
- leapt
|
||||
- learnt
|
||||
- led
|
||||
- left
|
||||
- lent
|
||||
- let
|
||||
- lighted
|
||||
- lost
|
||||
- made
|
||||
- meant
|
||||
- met
|
||||
- misspelt
|
||||
- mistaken
|
||||
- mown
|
||||
- overcome
|
||||
- overdone
|
||||
- overtaken
|
||||
- overthrown
|
||||
- paid
|
||||
- pled
|
||||
- proven
|
||||
- put
|
||||
- quit
|
||||
- read
|
||||
- rid
|
||||
- ridden
|
||||
- risen
|
||||
- run
|
||||
- rung
|
||||
- said
|
||||
- sat
|
||||
- sawn
|
||||
- seen
|
||||
- sent
|
||||
- set
|
||||
- sewn
|
||||
- shaken
|
||||
- shaven
|
||||
- shed
|
||||
- shod
|
||||
- shone
|
||||
- shorn
|
||||
- shot
|
||||
- shown
|
||||
- shrunk
|
||||
- shut
|
||||
- slain
|
||||
- slept
|
||||
- slid
|
||||
- slit
|
||||
- slung
|
||||
- smitten
|
||||
- sold
|
||||
- sought
|
||||
- sown
|
||||
- sped
|
||||
- spent
|
||||
- spilt
|
||||
- spit
|
||||
- split
|
||||
- spoken
|
||||
- spread
|
||||
- sprung
|
||||
- spun
|
||||
- stolen
|
||||
- stood
|
||||
- stridden
|
||||
- striven
|
||||
- struck
|
||||
- strung
|
||||
- stuck
|
||||
- stung
|
||||
- stunk
|
||||
- sung
|
||||
- sunk
|
||||
- swept
|
||||
- swollen
|
||||
- sworn
|
||||
- swum
|
||||
- swung
|
||||
- taken
|
||||
- taught
|
||||
- thought
|
||||
- thrived
|
||||
- thrown
|
||||
- thrust
|
||||
- told
|
||||
- torn
|
||||
- trodden
|
||||
- understood
|
||||
- upheld
|
||||
- upset
|
||||
- wed
|
||||
- wept
|
||||
- withheld
|
||||
- withstood
|
||||
- woken
|
||||
- won
|
||||
- worn
|
||||
- wound
|
||||
- woven
|
||||
- written
|
||||
- wrung
|
||||
@@ -0,0 +1,7 @@
|
||||
extends: existence
|
||||
message: "Use a numeral plus the units."
|
||||
link: https://medusajs.notion.site/Style-Guide-Docs-fad86dd1c5f84b48b145e959f36628e0#24a7270d3eee4d8e97657b0e12cd979a
|
||||
nonword: true
|
||||
level: error
|
||||
tokens:
|
||||
- '\b[a-zA-z]+\spercent\b'
|
||||
@@ -0,0 +1,7 @@
|
||||
extends: occurrence
|
||||
message: "Try to keep sentences short (< 30 words)."
|
||||
scope: sentence
|
||||
level: suggestion
|
||||
max: 30
|
||||
token: \b(\w+)\b
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
extends: existence
|
||||
message: "'%s' should have one space."
|
||||
level: error
|
||||
nonword: true
|
||||
tokens:
|
||||
- '[a-z][.?!] {2,}[A-Z]'
|
||||
- '[a-z][.?!][A-Z]'
|
||||
@@ -0,0 +1,8 @@
|
||||
extends: substitution
|
||||
message: Consider using '%s' instead of '%s'
|
||||
level: warning
|
||||
scope: code
|
||||
ignorecase: false
|
||||
# swap maps tokens in form of bad: good
|
||||
swap:
|
||||
e-commerce: ecommerce
|
||||
@@ -0,0 +1,10 @@
|
||||
extends: existence
|
||||
message: "Avoid using first-person plural like '%s'."
|
||||
link: https://medusajs.notion.site/Style-Guide-Docs-fad86dd1c5f84b48b145e959f36628e0#9f0dc7c440b841d3bfcb006df12c2652
|
||||
level: error
|
||||
ignorecase: true
|
||||
tokens:
|
||||
- we
|
||||
- we'(?:ve|re)
|
||||
- us
|
||||
- let's
|
||||
@@ -0,0 +1,122 @@
|
||||
extends: substitution
|
||||
message: "Consider using '%s' instead of '%s'."
|
||||
link: https://medusajs.notion.site/Style-Guide-Docs-fad86dd1c5f84b48b145e959f36628e0#426bd116f42d42859d3572c2de9f73f7
|
||||
ignorecase: true
|
||||
level: suggestion
|
||||
action:
|
||||
name: replace
|
||||
swap:
|
||||
(?:give|gave) rise to: lead to
|
||||
(?:previous|prior) to: before
|
||||
a (?:large)? majority of: most
|
||||
a (?:large)? number of: many
|
||||
a myriad of: myriad
|
||||
adversely impact: hurt
|
||||
all across: across
|
||||
all of a sudden: suddenly
|
||||
all of these: these
|
||||
all of: all
|
||||
all-time record: record
|
||||
almost all: most
|
||||
almost never: seldom
|
||||
along the lines of: similar to
|
||||
an adequate number of: enough
|
||||
an appreciable number of: many
|
||||
an estimated: about
|
||||
any and all: all
|
||||
are in agreement: agree
|
||||
as a matter of fact: in fact
|
||||
as a means of: to
|
||||
as a result of: because of
|
||||
as of yet: yet
|
||||
as per: per
|
||||
at a later date: later
|
||||
at all times: always
|
||||
at the present time: now
|
||||
at this point in time: at this point
|
||||
based in large part on: based on
|
||||
based on the fact that: because
|
||||
basic necessity: necessity
|
||||
because of the fact that: because
|
||||
came to a realization: realized
|
||||
came to an abrupt end: ended abruptly
|
||||
carry out an evaluation of: evaluate
|
||||
close down: close
|
||||
closed down: closed
|
||||
complete stranger: stranger
|
||||
completely separate: separate
|
||||
concerning the matter of: regarding
|
||||
conduct a review of: review
|
||||
conduct an investigation: investigate
|
||||
conduct experiments: experiment
|
||||
continue on: continue
|
||||
despite the fact that: although
|
||||
disappear from sight: disappear
|
||||
drag and drop: drag
|
||||
drag-and-drop: drag
|
||||
doomed to fail: doomed
|
||||
due to the fact that: because
|
||||
during the period of: during
|
||||
during the time that: while
|
||||
emergency situation: emergency
|
||||
except when: unless
|
||||
excessive number: too many
|
||||
extend an invitation: invite
|
||||
fall down: fall
|
||||
fell down: fell
|
||||
for the duration of: during
|
||||
gather together: gather
|
||||
has the ability to: can
|
||||
has the capacity to: can
|
||||
has the opportunity to: could
|
||||
hold a meeting: meet
|
||||
if this is not the case: if not
|
||||
in a careful manner: carefully
|
||||
in a thoughtful manner: thoughtfully
|
||||
in a timely manner: timely
|
||||
in an effort to: to
|
||||
in between: between
|
||||
in lieu of: instead of
|
||||
in many cases: often
|
||||
in most cases: usually
|
||||
in order to: to
|
||||
in some cases: sometimes
|
||||
in spite of the fact that: although
|
||||
in spite of: despite
|
||||
in the (?:very)? near future: soon
|
||||
in the event that: if
|
||||
in the neighborhood of: roughly
|
||||
in the vicinity of: close to
|
||||
it would appear that: apparently
|
||||
lift up: lift
|
||||
made reference to: referred to
|
||||
make reference to: refer to
|
||||
mix together: mix
|
||||
none at all: none
|
||||
not in a position to: unable
|
||||
not possible: impossible
|
||||
of major importance: important
|
||||
perform an assessment of: assess
|
||||
pertaining to: about
|
||||
place an order: order
|
||||
plays a key role in: is essential to
|
||||
present time: now
|
||||
readily apparent: apparent
|
||||
some of the: some
|
||||
span across: span
|
||||
subsequent to: after
|
||||
successfully complete: complete
|
||||
sufficient number (?:of)?: enough
|
||||
take action: act
|
||||
take into account: consider
|
||||
the question as to whether: whether
|
||||
there is no doubt but that: doubtless
|
||||
this day and age: this age
|
||||
this is a subject that: this subject
|
||||
time (?:frame|period): time
|
||||
under the provisions of: under
|
||||
until such time as: until
|
||||
used for fuel purposes: used for fuel
|
||||
whether or not: whether
|
||||
with regard to: regarding
|
||||
with the exception of: except for
|
||||
@@ -0,0 +1,9 @@
|
||||
extends: metric
|
||||
message: "Try to keep the Flesch-Kincaid grade level (%s) below 8."
|
||||
link: https://en.wikipedia.org/wiki/Flesch%E2%80%93Kincaid_readability_tests
|
||||
|
||||
formula: |
|
||||
(0.39 * (words / sentences)) + (11.8 * (syllables / words)) - 15.59
|
||||
|
||||
condition: "> 8"
|
||||
level: suggestion
|
||||
@@ -0,0 +1,702 @@
|
||||
extends: existence
|
||||
message: "Try to avoid using clichés like '%s'."
|
||||
ignorecase: true
|
||||
level: warning
|
||||
tokens:
|
||||
- a chip off the old block
|
||||
- a clean slate
|
||||
- a dark and stormy night
|
||||
- a far cry
|
||||
- a fine kettle of fish
|
||||
- a loose cannon
|
||||
- a penny saved is a penny earned
|
||||
- a tough row to hoe
|
||||
- a word to the wise
|
||||
- ace in the hole
|
||||
- acid test
|
||||
- add insult to injury
|
||||
- against all odds
|
||||
- air your dirty laundry
|
||||
- all fun and games
|
||||
- all in a day's work
|
||||
- all talk, no action
|
||||
- all thumbs
|
||||
- all your eggs in one basket
|
||||
- all's fair in love and war
|
||||
- all's well that ends well
|
||||
- almighty dollar
|
||||
- American as apple pie
|
||||
- an axe to grind
|
||||
- another day, another dollar
|
||||
- armed to the teeth
|
||||
- as luck would have it
|
||||
- as old as time
|
||||
- as the crow flies
|
||||
- at loose ends
|
||||
- at my wits end
|
||||
- avoid like the plague
|
||||
- babe in the woods
|
||||
- back against the wall
|
||||
- back in the saddle
|
||||
- back to square one
|
||||
- back to the drawing board
|
||||
- bad to the bone
|
||||
- badge of honor
|
||||
- bald faced liar
|
||||
- ballpark figure
|
||||
- banging your head against a brick wall
|
||||
- baptism by fire
|
||||
- barking up the wrong tree
|
||||
- bat out of hell
|
||||
- be all and end all
|
||||
- beat a dead horse
|
||||
- beat around the bush
|
||||
- been there, done that
|
||||
- beggars can't be choosers
|
||||
- behind the eight ball
|
||||
- bend over backwards
|
||||
- benefit of the doubt
|
||||
- bent out of shape
|
||||
- best thing since sliced bread
|
||||
- bet your bottom dollar
|
||||
- better half
|
||||
- better late than never
|
||||
- better mousetrap
|
||||
- better safe than sorry
|
||||
- between a rock and a hard place
|
||||
- beyond the pale
|
||||
- bide your time
|
||||
- big as life
|
||||
- big cheese
|
||||
- big fish in a small pond
|
||||
- big man on campus
|
||||
- bigger they are the harder they fall
|
||||
- bird in the hand
|
||||
- bird's eye view
|
||||
- birds and the bees
|
||||
- birds of a feather flock together
|
||||
- bit the hand that feeds you
|
||||
- bite the bullet
|
||||
- bite the dust
|
||||
- bitten off more than he can chew
|
||||
- black as coal
|
||||
- black as pitch
|
||||
- black as the ace of spades
|
||||
- blast from the past
|
||||
- bleeding heart
|
||||
- blessing in disguise
|
||||
- blind ambition
|
||||
- blind as a bat
|
||||
- blind leading the blind
|
||||
- blood is thicker than water
|
||||
- blood sweat and tears
|
||||
- blow off steam
|
||||
- blow your own horn
|
||||
- blushing bride
|
||||
- boils down to
|
||||
- bolt from the blue
|
||||
- bone to pick
|
||||
- bored stiff
|
||||
- bored to tears
|
||||
- bottomless pit
|
||||
- boys will be boys
|
||||
- bright and early
|
||||
- brings home the bacon
|
||||
- broad across the beam
|
||||
- broken record
|
||||
- brought back to reality
|
||||
- bull by the horns
|
||||
- bull in a china shop
|
||||
- burn the midnight oil
|
||||
- burning question
|
||||
- burning the candle at both ends
|
||||
- burst your bubble
|
||||
- bury the hatchet
|
||||
- busy as a bee
|
||||
- by hook or by crook
|
||||
- call a spade a spade
|
||||
- called onto the carpet
|
||||
- calm before the storm
|
||||
- can of worms
|
||||
- can't cut the mustard
|
||||
- can't hold a candle to
|
||||
- case of mistaken identity
|
||||
- cat got your tongue
|
||||
- cat's meow
|
||||
- caught in the crossfire
|
||||
- caught red-handed
|
||||
- checkered past
|
||||
- chomping at the bit
|
||||
- cleanliness is next to godliness
|
||||
- clear as a bell
|
||||
- clear as mud
|
||||
- close to the vest
|
||||
- cock and bull story
|
||||
- cold shoulder
|
||||
- come hell or high water
|
||||
- cool as a cucumber
|
||||
- cool, calm, and collected
|
||||
- cost a king's ransom
|
||||
- count your blessings
|
||||
- crack of dawn
|
||||
- crash course
|
||||
- creature comforts
|
||||
- cross that bridge when you come to it
|
||||
- crushing blow
|
||||
- cry like a baby
|
||||
- cry me a river
|
||||
- cry over spilt milk
|
||||
- crystal clear
|
||||
- curiosity killed the cat
|
||||
- cut and dried
|
||||
- cut through the red tape
|
||||
- cut to the chase
|
||||
- cute as a bugs ear
|
||||
- cute as a button
|
||||
- cute as a puppy
|
||||
- cuts to the quick
|
||||
- dark before the dawn
|
||||
- day in, day out
|
||||
- dead as a doornail
|
||||
- devil is in the details
|
||||
- dime a dozen
|
||||
- divide and conquer
|
||||
- dog and pony show
|
||||
- dog days
|
||||
- dog eat dog
|
||||
- dog tired
|
||||
- don't burn your bridges
|
||||
- don't count your chickens
|
||||
- don't look a gift horse in the mouth
|
||||
- don't rock the boat
|
||||
- don't step on anyone's toes
|
||||
- don't take any wooden nickels
|
||||
- down and out
|
||||
- down at the heels
|
||||
- down in the dumps
|
||||
- down the hatch
|
||||
- down to earth
|
||||
- draw the line
|
||||
- dressed to kill
|
||||
- dressed to the nines
|
||||
- drives me up the wall
|
||||
- dull as dishwater
|
||||
- dyed in the wool
|
||||
- eagle eye
|
||||
- ear to the ground
|
||||
- early bird catches the worm
|
||||
- easier said than done
|
||||
- easy as pie
|
||||
- eat your heart out
|
||||
- eat your words
|
||||
- eleventh hour
|
||||
- even the playing field
|
||||
- every dog has its day
|
||||
- every fiber of my being
|
||||
- everything but the kitchen sink
|
||||
- eye for an eye
|
||||
- face the music
|
||||
- facts of life
|
||||
- fair weather friend
|
||||
- fall by the wayside
|
||||
- fan the flames
|
||||
- feast or famine
|
||||
- feather your nest
|
||||
- feathered friends
|
||||
- few and far between
|
||||
- fifteen minutes of fame
|
||||
- filthy vermin
|
||||
- fine kettle of fish
|
||||
- fish out of water
|
||||
- fishing for a compliment
|
||||
- fit as a fiddle
|
||||
- fit the bill
|
||||
- fit to be tied
|
||||
- flash in the pan
|
||||
- flat as a pancake
|
||||
- flip your lid
|
||||
- flog a dead horse
|
||||
- fly by night
|
||||
- fly the coop
|
||||
- follow your heart
|
||||
- for all intents and purposes
|
||||
- for the birds
|
||||
- for what it's worth
|
||||
- force of nature
|
||||
- force to be reckoned with
|
||||
- forgive and forget
|
||||
- fox in the henhouse
|
||||
- free and easy
|
||||
- free as a bird
|
||||
- fresh as a daisy
|
||||
- full steam ahead
|
||||
- fun in the sun
|
||||
- garbage in, garbage out
|
||||
- gentle as a lamb
|
||||
- get a kick out of
|
||||
- get a leg up
|
||||
- get down and dirty
|
||||
- get the lead out
|
||||
- get to the bottom of
|
||||
- get your feet wet
|
||||
- gets my goat
|
||||
- gilding the lily
|
||||
- give and take
|
||||
- go against the grain
|
||||
- go at it tooth and nail
|
||||
- go for broke
|
||||
- go him one better
|
||||
- go the extra mile
|
||||
- go with the flow
|
||||
- goes without saying
|
||||
- good as gold
|
||||
- good deed for the day
|
||||
- good things come to those who wait
|
||||
- good time was had by all
|
||||
- good times were had by all
|
||||
- greased lightning
|
||||
- greek to me
|
||||
- green thumb
|
||||
- green-eyed monster
|
||||
- grist for the mill
|
||||
- growing like a weed
|
||||
- hair of the dog
|
||||
- hand to mouth
|
||||
- happy as a clam
|
||||
- happy as a lark
|
||||
- hasn't a clue
|
||||
- have a nice day
|
||||
- have high hopes
|
||||
- have the last laugh
|
||||
- haven't got a row to hoe
|
||||
- head honcho
|
||||
- head over heels
|
||||
- hear a pin drop
|
||||
- heard it through the grapevine
|
||||
- heart's content
|
||||
- heavy as lead
|
||||
- hem and haw
|
||||
- high and dry
|
||||
- high and mighty
|
||||
- high as a kite
|
||||
- hit paydirt
|
||||
- hold your head up high
|
||||
- hold your horses
|
||||
- hold your own
|
||||
- hold your tongue
|
||||
- honest as the day is long
|
||||
- horns of a dilemma
|
||||
- horse of a different color
|
||||
- hot under the collar
|
||||
- hour of need
|
||||
- I beg to differ
|
||||
- icing on the cake
|
||||
- if the shoe fits
|
||||
- if the shoe were on the other foot
|
||||
- in a jam
|
||||
- in a jiffy
|
||||
- in a nutshell
|
||||
- in a pig's eye
|
||||
- in a pinch
|
||||
- in a word
|
||||
- in hot water
|
||||
- in the gutter
|
||||
- in the nick of time
|
||||
- in the thick of it
|
||||
- in your dreams
|
||||
- it ain't over till the fat lady sings
|
||||
- it goes without saying
|
||||
- it takes all kinds
|
||||
- it takes one to know one
|
||||
- it's a small world
|
||||
- it's only a matter of time
|
||||
- ivory tower
|
||||
- Jack of all trades
|
||||
- jockey for position
|
||||
- jog your memory
|
||||
- joined at the hip
|
||||
- judge a book by its cover
|
||||
- jump down your throat
|
||||
- jump in with both feet
|
||||
- jump on the bandwagon
|
||||
- jump the gun
|
||||
- jump to conclusions
|
||||
- just a hop, skip, and a jump
|
||||
- just the ticket
|
||||
- justice is blind
|
||||
- keep a stiff upper lip
|
||||
- keep an eye on
|
||||
- keep it simple, stupid
|
||||
- keep the home fires burning
|
||||
- keep up with the Joneses
|
||||
- keep your chin up
|
||||
- keep your fingers crossed
|
||||
- kick the bucket
|
||||
- kick up your heels
|
||||
- kick your feet up
|
||||
- kid in a candy store
|
||||
- kill two birds with one stone
|
||||
- kiss of death
|
||||
- knock it out of the park
|
||||
- knock on wood
|
||||
- knock your socks off
|
||||
- know him from Adam
|
||||
- know the ropes
|
||||
- know the score
|
||||
- knuckle down
|
||||
- knuckle sandwich
|
||||
- knuckle under
|
||||
- labor of love
|
||||
- ladder of success
|
||||
- land on your feet
|
||||
- lap of luxury
|
||||
- last but not least
|
||||
- last hurrah
|
||||
- last-ditch effort
|
||||
- law of the jungle
|
||||
- law of the land
|
||||
- lay down the law
|
||||
- leaps and bounds
|
||||
- let sleeping dogs lie
|
||||
- let the cat out of the bag
|
||||
- let the good times roll
|
||||
- let your hair down
|
||||
- let's talk turkey
|
||||
- letter perfect
|
||||
- lick your wounds
|
||||
- lies like a rug
|
||||
- life's a bitch
|
||||
- life's a grind
|
||||
- light at the end of the tunnel
|
||||
- lighter than a feather
|
||||
- lighter than air
|
||||
- like clockwork
|
||||
- like father like son
|
||||
- like taking candy from a baby
|
||||
- like there's no tomorrow
|
||||
- lion's share
|
||||
- live and learn
|
||||
- live and let live
|
||||
- long and short of it
|
||||
- long lost love
|
||||
- look before you leap
|
||||
- look down your nose
|
||||
- look what the cat dragged in
|
||||
- looking a gift horse in the mouth
|
||||
- looks like death warmed over
|
||||
- loose cannon
|
||||
- lose your head
|
||||
- lose your temper
|
||||
- loud as a horn
|
||||
- lounge lizard
|
||||
- loved and lost
|
||||
- low man on the totem pole
|
||||
- luck of the draw
|
||||
- luck of the Irish
|
||||
- make hay while the sun shines
|
||||
- make money hand over fist
|
||||
- make my day
|
||||
- make the best of a bad situation
|
||||
- make the best of it
|
||||
- make your blood boil
|
||||
- man of few words
|
||||
- man's best friend
|
||||
- mark my words
|
||||
- meaningful dialogue
|
||||
- missed the boat on that one
|
||||
- moment in the sun
|
||||
- moment of glory
|
||||
- moment of truth
|
||||
- money to burn
|
||||
- more power to you
|
||||
- more than one way to skin a cat
|
||||
- movers and shakers
|
||||
- moving experience
|
||||
- naked as a jaybird
|
||||
- naked truth
|
||||
- neat as a pin
|
||||
- needle in a haystack
|
||||
- needless to say
|
||||
- neither here nor there
|
||||
- never look back
|
||||
- never say never
|
||||
- nip and tuck
|
||||
- nip it in the bud
|
||||
- no guts, no glory
|
||||
- no love lost
|
||||
- no pain, no gain
|
||||
- no skin off my back
|
||||
- no stone unturned
|
||||
- no time like the present
|
||||
- no use crying over spilled milk
|
||||
- nose to the grindstone
|
||||
- not a hope in hell
|
||||
- not a minute's peace
|
||||
- not in my backyard
|
||||
- not playing with a full deck
|
||||
- not the end of the world
|
||||
- not written in stone
|
||||
- nothing to sneeze at
|
||||
- nothing ventured nothing gained
|
||||
- now we're cooking
|
||||
- off the top of my head
|
||||
- off the wagon
|
||||
- off the wall
|
||||
- old hat
|
||||
- older and wiser
|
||||
- older than dirt
|
||||
- older than Methuselah
|
||||
- on a roll
|
||||
- on cloud nine
|
||||
- on pins and needles
|
||||
- on the bandwagon
|
||||
- on the money
|
||||
- on the nose
|
||||
- on the rocks
|
||||
- on the spot
|
||||
- on the tip of my tongue
|
||||
- on the wagon
|
||||
- on thin ice
|
||||
- once bitten, twice shy
|
||||
- one bad apple doesn't spoil the bushel
|
||||
- one born every minute
|
||||
- one brick short
|
||||
- one foot in the grave
|
||||
- one in a million
|
||||
- one red cent
|
||||
- only game in town
|
||||
- open a can of worms
|
||||
- open and shut case
|
||||
- open the flood gates
|
||||
- opportunity doesn't knock twice
|
||||
- out of pocket
|
||||
- out of sight, out of mind
|
||||
- out of the frying pan into the fire
|
||||
- out of the woods
|
||||
- out on a limb
|
||||
- over a barrel
|
||||
- over the hump
|
||||
- pain and suffering
|
||||
- pain in the
|
||||
- panic button
|
||||
- par for the course
|
||||
- part and parcel
|
||||
- party pooper
|
||||
- pass the buck
|
||||
- patience is a virtue
|
||||
- pay through the nose
|
||||
- penny pincher
|
||||
- perfect storm
|
||||
- pig in a poke
|
||||
- pile it on
|
||||
- pillar of the community
|
||||
- pin your hopes on
|
||||
- pitter patter of little feet
|
||||
- plain as day
|
||||
- plain as the nose on your face
|
||||
- play by the rules
|
||||
- play your cards right
|
||||
- playing the field
|
||||
- playing with fire
|
||||
- pleased as punch
|
||||
- plenty of fish in the sea
|
||||
- point with pride
|
||||
- poor as a church mouse
|
||||
- pot calling the kettle black
|
||||
- pretty as a picture
|
||||
- pull a fast one
|
||||
- pull your punches
|
||||
- pulling your leg
|
||||
- pure as the driven snow
|
||||
- put it in a nutshell
|
||||
- put one over on you
|
||||
- put the cart before the horse
|
||||
- put the pedal to the metal
|
||||
- put your best foot forward
|
||||
- put your foot down
|
||||
- quick as a bunny
|
||||
- quick as a lick
|
||||
- quick as a wink
|
||||
- quick as lightning
|
||||
- quiet as a dormouse
|
||||
- rags to riches
|
||||
- raining buckets
|
||||
- raining cats and dogs
|
||||
- rank and file
|
||||
- rat race
|
||||
- reap what you sow
|
||||
- red as a beet
|
||||
- red herring
|
||||
- reinvent the wheel
|
||||
- rich and famous
|
||||
- rings a bell
|
||||
- ripe old age
|
||||
- ripped me off
|
||||
- rise and shine
|
||||
- road to hell is paved with good intentions
|
||||
- rob Peter to pay Paul
|
||||
- roll over in the grave
|
||||
- rub the wrong way
|
||||
- ruled the roost
|
||||
- running in circles
|
||||
- sad but true
|
||||
- sadder but wiser
|
||||
- salt of the earth
|
||||
- scared stiff
|
||||
- scared to death
|
||||
- sealed with a kiss
|
||||
- second to none
|
||||
- see eye to eye
|
||||
- seen the light
|
||||
- seize the day
|
||||
- set the record straight
|
||||
- set the world on fire
|
||||
- set your teeth on edge
|
||||
- sharp as a tack
|
||||
- shoot for the moon
|
||||
- shoot the breeze
|
||||
- shot in the dark
|
||||
- shoulder to the wheel
|
||||
- sick as a dog
|
||||
- sigh of relief
|
||||
- signed, sealed, and delivered
|
||||
- sink or swim
|
||||
- six of one, half a dozen of another
|
||||
- skating on thin ice
|
||||
- slept like a log
|
||||
- slinging mud
|
||||
- slippery as an eel
|
||||
- slow as molasses
|
||||
- smart as a whip
|
||||
- smooth as a baby's bottom
|
||||
- sneaking suspicion
|
||||
- snug as a bug in a rug
|
||||
- sow wild oats
|
||||
- spare the rod, spoil the child
|
||||
- speak of the devil
|
||||
- spilled the beans
|
||||
- spinning your wheels
|
||||
- spitting image of
|
||||
- spoke with relish
|
||||
- spread like wildfire
|
||||
- spring to life
|
||||
- squeaky wheel gets the grease
|
||||
- stands out like a sore thumb
|
||||
- start from scratch
|
||||
- stick in the mud
|
||||
- still waters run deep
|
||||
- stitch in time
|
||||
- stop and smell the roses
|
||||
- straight as an arrow
|
||||
- straw that broke the camel's back
|
||||
- strong as an ox
|
||||
- stubborn as a mule
|
||||
- stuff that dreams are made of
|
||||
- stuffed shirt
|
||||
- sweating blood
|
||||
- sweating bullets
|
||||
- take a load off
|
||||
- take one for the team
|
||||
- take the bait
|
||||
- take the bull by the horns
|
||||
- take the plunge
|
||||
- takes one to know one
|
||||
- takes two to tango
|
||||
- the more the merrier
|
||||
- the real deal
|
||||
- the real McCoy
|
||||
- the red carpet treatment
|
||||
- the same old story
|
||||
- there is no accounting for taste
|
||||
- thick as a brick
|
||||
- thick as thieves
|
||||
- thin as a rail
|
||||
- think outside of the box
|
||||
- third time's the charm
|
||||
- this day and age
|
||||
- this hurts me worse than it hurts you
|
||||
- this point in time
|
||||
- three sheets to the wind
|
||||
- through thick and thin
|
||||
- throw in the towel
|
||||
- tie one on
|
||||
- tighter than a drum
|
||||
- time and time again
|
||||
- time is of the essence
|
||||
- tip of the iceberg
|
||||
- tired but happy
|
||||
- to coin a phrase
|
||||
- to each his own
|
||||
- to make a long story short
|
||||
- to the best of my knowledge
|
||||
- toe the line
|
||||
- tongue in cheek
|
||||
- too good to be true
|
||||
- too hot to handle
|
||||
- too numerous to mention
|
||||
- touch with a ten foot pole
|
||||
- tough as nails
|
||||
- trial and error
|
||||
- trials and tribulations
|
||||
- tried and true
|
||||
- trip down memory lane
|
||||
- twist of fate
|
||||
- two cents worth
|
||||
- two peas in a pod
|
||||
- ugly as sin
|
||||
- under the counter
|
||||
- under the gun
|
||||
- under the same roof
|
||||
- under the weather
|
||||
- until the cows come home
|
||||
- unvarnished truth
|
||||
- up the creek
|
||||
- uphill battle
|
||||
- upper crust
|
||||
- upset the applecart
|
||||
- vain attempt
|
||||
- vain effort
|
||||
- vanquish the enemy
|
||||
- vested interest
|
||||
- waiting for the other shoe to drop
|
||||
- wakeup call
|
||||
- warm welcome
|
||||
- watch your p's and q's
|
||||
- watch your tongue
|
||||
- watching the clock
|
||||
- water under the bridge
|
||||
- weather the storm
|
||||
- weed them out
|
||||
- week of Sundays
|
||||
- went belly up
|
||||
- wet behind the ears
|
||||
- what goes around comes around
|
||||
- what you see is what you get
|
||||
- when it rains, it pours
|
||||
- when push comes to shove
|
||||
- when the cat's away
|
||||
- when the going gets tough, the tough get going
|
||||
- white as a sheet
|
||||
- whole ball of wax
|
||||
- whole hog
|
||||
- whole nine yards
|
||||
- wild goose chase
|
||||
- will wonders never cease?
|
||||
- wisdom of the ages
|
||||
- wise as an owl
|
||||
- wolf at the door
|
||||
- words fail me
|
||||
- work like a dog
|
||||
- world weary
|
||||
- worst nightmare
|
||||
- worth its weight in gold
|
||||
- wrong side of the bed
|
||||
- yanking your chain
|
||||
- yappy as a dog
|
||||
- years young
|
||||
- you are what you eat
|
||||
- you can run but you can't hide
|
||||
- you only live once
|
||||
- you're the boss
|
||||
- young and foolish
|
||||
- young and vibrant
|
||||
@@ -0,0 +1,32 @@
|
||||
extends: existence
|
||||
message: "Try to avoid using '%s'."
|
||||
ignorecase: true
|
||||
level: suggestion
|
||||
tokens:
|
||||
- am
|
||||
- are
|
||||
- aren't
|
||||
- be
|
||||
- been
|
||||
- being
|
||||
- he's
|
||||
- here's
|
||||
- here's
|
||||
- how's
|
||||
- i'm
|
||||
- is
|
||||
- isn't
|
||||
- it's
|
||||
- she's
|
||||
- that's
|
||||
- there's
|
||||
- they're
|
||||
- was
|
||||
- wasn't
|
||||
- we're
|
||||
- were
|
||||
- weren't
|
||||
- what's
|
||||
- where's
|
||||
- who's
|
||||
- you're
|
||||
@@ -0,0 +1,11 @@
|
||||
extends: repetition
|
||||
message: "'%s' is repeated!"
|
||||
level: warning
|
||||
alpha: true
|
||||
action:
|
||||
name: edit
|
||||
params:
|
||||
- truncate
|
||||
- " "
|
||||
tokens:
|
||||
- '[^\s]+'
|
||||
@@ -0,0 +1,183 @@
|
||||
extends: existence
|
||||
message: "'%s' may be passive voice. Use active voice if you can."
|
||||
ignorecase: true
|
||||
level: warning
|
||||
raw:
|
||||
- \b(am|are|were|being|is|been|was|be)\b\s*
|
||||
tokens:
|
||||
- '[\w]+ed'
|
||||
- awoken
|
||||
- beat
|
||||
- become
|
||||
- been
|
||||
- begun
|
||||
- bent
|
||||
- beset
|
||||
- bet
|
||||
- bid
|
||||
- bidden
|
||||
- bitten
|
||||
- bled
|
||||
- blown
|
||||
- born
|
||||
- bought
|
||||
- bound
|
||||
- bred
|
||||
- broadcast
|
||||
- broken
|
||||
- brought
|
||||
- built
|
||||
- burnt
|
||||
- burst
|
||||
- cast
|
||||
- caught
|
||||
- chosen
|
||||
- clung
|
||||
- come
|
||||
- cost
|
||||
- crept
|
||||
- cut
|
||||
- dealt
|
||||
- dived
|
||||
- done
|
||||
- drawn
|
||||
- dreamt
|
||||
- driven
|
||||
- drunk
|
||||
- dug
|
||||
- eaten
|
||||
- fallen
|
||||
- fed
|
||||
- felt
|
||||
- fit
|
||||
- fled
|
||||
- flown
|
||||
- flung
|
||||
- forbidden
|
||||
- foregone
|
||||
- forgiven
|
||||
- forgotten
|
||||
- forsaken
|
||||
- fought
|
||||
- found
|
||||
- frozen
|
||||
- given
|
||||
- gone
|
||||
- gotten
|
||||
- ground
|
||||
- grown
|
||||
- heard
|
||||
- held
|
||||
- hidden
|
||||
- hit
|
||||
- hung
|
||||
- hurt
|
||||
- kept
|
||||
- knelt
|
||||
- knit
|
||||
- known
|
||||
- laid
|
||||
- lain
|
||||
- leapt
|
||||
- learnt
|
||||
- led
|
||||
- left
|
||||
- lent
|
||||
- let
|
||||
- lighted
|
||||
- lost
|
||||
- made
|
||||
- meant
|
||||
- met
|
||||
- misspelt
|
||||
- mistaken
|
||||
- mown
|
||||
- overcome
|
||||
- overdone
|
||||
- overtaken
|
||||
- overthrown
|
||||
- paid
|
||||
- pled
|
||||
- proven
|
||||
- put
|
||||
- quit
|
||||
- read
|
||||
- rid
|
||||
- ridden
|
||||
- risen
|
||||
- run
|
||||
- rung
|
||||
- said
|
||||
- sat
|
||||
- sawn
|
||||
- seen
|
||||
- sent
|
||||
- set
|
||||
- sewn
|
||||
- shaken
|
||||
- shaven
|
||||
- shed
|
||||
- shod
|
||||
- shone
|
||||
- shorn
|
||||
- shot
|
||||
- shown
|
||||
- shrunk
|
||||
- shut
|
||||
- slain
|
||||
- slept
|
||||
- slid
|
||||
- slit
|
||||
- slung
|
||||
- smitten
|
||||
- sold
|
||||
- sought
|
||||
- sown
|
||||
- sped
|
||||
- spent
|
||||
- spilt
|
||||
- spit
|
||||
- split
|
||||
- spoken
|
||||
- spread
|
||||
- sprung
|
||||
- spun
|
||||
- stolen
|
||||
- stood
|
||||
- stridden
|
||||
- striven
|
||||
- struck
|
||||
- strung
|
||||
- stuck
|
||||
- stung
|
||||
- stunk
|
||||
- sung
|
||||
- sunk
|
||||
- swept
|
||||
- swollen
|
||||
- sworn
|
||||
- swum
|
||||
- swung
|
||||
- taken
|
||||
- taught
|
||||
- thought
|
||||
- thrived
|
||||
- thrown
|
||||
- thrust
|
||||
- told
|
||||
- torn
|
||||
- trodden
|
||||
- understood
|
||||
- upheld
|
||||
- upset
|
||||
- wed
|
||||
- wept
|
||||
- withheld
|
||||
- withstood
|
||||
- woken
|
||||
- won
|
||||
- worn
|
||||
- wound
|
||||
- woven
|
||||
- written
|
||||
- wrung
|
||||
@@ -0,0 +1,27 @@
|
||||
Based on [write-good](https://github.com/btford/write-good).
|
||||
|
||||
> Naive linter for English prose for developers who can't write good and wanna learn to do other stuff good too.
|
||||
|
||||
```
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Brian Ford
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
@@ -0,0 +1,5 @@
|
||||
extends: existence
|
||||
message: "Don't start a sentence with '%s'."
|
||||
level: error
|
||||
raw:
|
||||
- '(?:[;-]\s)so[\s,]|\bSo[\s,]'
|
||||
@@ -0,0 +1,6 @@
|
||||
extends: existence
|
||||
message: "Don't start a sentence with '%s'."
|
||||
ignorecase: false
|
||||
level: error
|
||||
raw:
|
||||
- '(?:[;-]\s)There\s(is|are)|\bThere\s(is|are)\b'
|
||||
Loaded 100 of 103 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user