docs: changes for next release (#11708)

* docs: changes for next release

* small fixes

* fix lint error

* small fix
This commit is contained in:
Shahed Nasser
2025-03-04 15:23:50 +02:00
committed by GitHub
parent 9e410be04a
commit c29a709dd1
6 changed files with 13032 additions and 12728 deletions

View File

@@ -18,11 +18,20 @@ As Medusa's server is based on Express, you can use any [Express middleware](htt
</Note>
### Middleware Types
There are two types of middlewares:
1. Global Middleware: A middleware that applies to all routes matching a specified pattern.
2. Route Middleware: A middleware that applies to routes matching a specified pattern and HTTP method(s).
These middlewares generally have the same definition and usage, but they differ in the routes they apply to. You'll learn how to create both types in the following sections.
---
## How to Create a Middleware?
## How to Create a Global Middleware?
Middlewares are defined in the special file `src/api/middlewares.ts`. Use the `defineMiddlewares` function from the Medusa Framework to define the middlewares, and export its value.
Middlewares of all types are defined in the special file `src/api/middlewares.ts`. Use the `defineMiddlewares` function from the Medusa Framework to define the middlewares, and export its value.
For example:
@@ -57,13 +66,11 @@ export default defineMiddlewares({
The `defineMiddlewares` function accepts a middleware configurations object that has the property `routes`. `routes`'s value is an array of middleware route objects, each having the following properties:
- `matcher`: a string or regular expression indicating the API route path to apply the middleware on. The regular expression must be compatible with [path-to-regexp](https://github.com/pillarjs/path-to-regexp).
- `middlewares`: An array of middleware functions.
- `middlewares`: An array of global and route middleware functions.
In the example above, you define a middleware that logs the message `Received a request!` whenever a request is sent to an API route path starting with `/custom`.
In the example above, you define a global middleware that logs the message `Received a request!` whenever a request is sent to an API route path starting with `/custom`.
---
## Test the Middleware
### Test the Global Middleware
To test the middleware:
@@ -82,6 +89,64 @@ Received a request!
---
## How to Create a Route Middleware?
In the previous section, you learned how to create a global middleware. You define the route middleware in the same way in `src/api/middlewares.ts`, but you specify an additional property `method` in the middleware route object. Its value is one or more HTTP methods to apply the middleware to.
For example:
export const highlights = [["12", "method", "Apply the middleware only on `POST` requests"]]
```ts title="src/api/middlewares.ts" highlights={highlights} collapsibleLines="1-7" expandButtonLabel="Show Imports"
import {
MedusaNextFunction,
MedusaRequest,
MedusaResponse,
defineMiddlewares,
} from "@medusajs/framework/http"
export default defineMiddlewares({
routes: [
{
matcher: "/custom*",
method: ["POST", "PUT"],
middlewares: [
(
req: MedusaRequest,
res: MedusaResponse,
next: MedusaNextFunction
) => {
console.log("Received a request!")
next()
},
],
},
],
})
```
This example applies the middleware only when a `POST` or `PUT` request is sent to an API route path starting with `/custom`, changing the middleware from a global middleware to a route middleware.
### Test the Route Middleware
To test the middleware:
1. Start the application:
```bash npm2yarn
npm run dev
```
2. Send a `POST` request to any API route starting with `/custom`.
3. See the following message in the terminal:
```bash
Received a request!
```
---
## When to Use Middlewares
<Note type="success" title="Use middlewares when">
@@ -141,48 +206,13 @@ This applies a middleware to the routes defined in the file `src/api/custom/[id]
---
## Restrict HTTP Methods
Restrict which HTTP methods the middleware is applied to using the `method` property of the middleware route object.
For example:
export const highlights = [["12", "method", "Apply the middleware only on `POST` requests"]]
```ts title="src/api/middlewares.ts" highlights={highlights} collapsibleLines="1-7" expandButtonLabel="Show Imports"
import {
MedusaNextFunction,
MedusaRequest,
MedusaResponse,
defineMiddlewares,
} from "@medusajs/framework/http"
export default defineMiddlewares({
routes: [
{
matcher: "/custom*",
method: ["POST", "PUT"],
middlewares: [
// ...
],
},
],
})
```
`method`'s value is one or more HTTP methods to apply the middleware to.
This example applies the middleware only when a `POST` or `PUT` request is sent to an API route path starting with `/custom`.
---
## Request URLs with Trailing Backslashes
A middleware whose `matcher` pattern doesn't end with a backslash won't be applied for requests to URLs with a trailing backslash.
For example, consider you have the following middleware:
```ts collapsibleLines="1-7" expandMoreLabel="Show Imports"
```ts title="src/api/middlewares.ts" collapsibleLines="1-7" expandMoreLabel="Show Imports"
import {
MedusaNextFunction,
MedusaRequest,
@@ -218,8 +248,123 @@ In general, avoid adding trailing backslashes when sending requests to API route
---
## Middlewares Precedence in Registration
## Middlewares and Route Ordering
The Medusa application registers your middlewares first, then registers middlewares defined in Medusa's core.
<Note>
So, if you add a middleware for a route defined in the core, it might get overridden by the core middleware. For example, if you add a middleware to change authentication of admin routes, the authentication middleware defined in the core will still run, leading to your middleware not being effective.
The ordering explained in this section was added in [Medusa v2.6](https://github.com/medusajs/medusa/releases/tag/v2.6)
</Note>
The Medusa application registers middlewares and API route handlers in the following order:
1. Global middlewares in the following order:
1. Global middleware defined in the Medusa's core.
2. Global middleware defined in the plugins (in the order the plugins are registered in).
3. Global middleware you define in the application.
2. Route middlewares in the following order:
1. Route middleware defined in the Medusa's core.
2. Route middleware defined in the plugins (in the order the plugins are registered in).
3. Route middleware you define in the application.
3. API routes in the following order:
1. API routes defined in the Medusa's core.
2. API routes defined in the plugins (in the order the plugins are registered in).
3. API routes you define in the application.
### Middlewares Sorting
On top of the previous ordering, Medusa sorts global and route middlewares based on their matcher pattern in the following order:
1. Wildcard matchers. For example, `/custom*`.
2. Regex matchers. For example, `/custom/(products|collections)`.
3. Static matchers without parameters. For example, `/custom`.
4. Static matchers with parameters. For example, `/custom/:id`.
For example, if you have the following middlewares:
```ts title="src/api/middlewares.ts"
export default defineMiddlewares({
routes: [
{
matcher: "/custom/:id",
middlewares: [/* ... */],
},
{
matcher: "/custom",
middlewares: [/* ... */],
},
{
matcher: "/custom*",
method: ["GET"],
middlewares: [/* ... */],
},
{
matcher: "/custom/:id",
method: ["GET"],
middlewares: [/* ... */],
},
],
})
```
The global middlewares are sorted into the following order before they're registered:
1. Global middleware `/custom`.
2. Global middleware `/custom/:id`.
And the route middlewares are sorted into the following order before they're registered:
1. Route middleware `/custom*`.
2. Route middleware `/custom/:id`.
Then, the middlwares are registered in the order mentioned earlier, with global middlewares first, then the route middlewares.
### Middlewares and Route Execution Order
When a request is sent to an API route, the global middlewares are executed first, then the route middlewares, and finally the route handler.
For example, consider you have the following middlewares:
```ts title="src/api/middlewares.ts"
export default defineMiddlewares({
routes: [
{
matcher: "/custom",
middlewares: [
(req, res, next) => {
console.log("Global middleware")
next()
},
],
},
{
matcher: "/custom",
method: ["GET"],
middlewares: [
(req, res, next) => {
console.log("Route middleware")
next()
},
],
},
],
})
```
When you send a request to `/custom` route, the following messages are logged in the terminal:
```bash
Global middleware
Route middleware
Hello from custom! # message logged from API route handler
```
The global middleware runs first, then the route middleware, and finally the route handler, assuming that it logs the message `Hello from custom!`.
---
## Overriding Middlewares
A middleware can not override an existing middleware. Instead, middlewares are added to the end of the middleware stack.
For example, if you define a custom validation middleware, such as `validateAndTransformBody`, on an existing route, then both the original and the custom validation middleware will run.

View File

@@ -53,7 +53,7 @@ export const generatedEditDates = {
"app/learn/fundamentals/admin/tips/page.mdx": "2025-02-24T09:52:06.901Z",
"app/learn/fundamentals/api-routes/cors/page.mdx": "2024-12-09T13:04:04.357Z",
"app/learn/fundamentals/admin/ui-routes/page.mdx": "2025-02-24T09:35:11.752Z",
"app/learn/fundamentals/api-routes/middlewares/page.mdx": "2025-02-12T17:05:20.708Z",
"app/learn/fundamentals/api-routes/middlewares/page.mdx": "2025-03-04T10:16:15.029Z",
"app/learn/fundamentals/modules/isolation/page.mdx": "2024-12-09T11:02:38.087Z",
"app/learn/fundamentals/data-models/configure-properties/page.mdx": "2024-10-21T13:30:21.368Z",
"app/learn/fundamentals/data-models/index/page.mdx": "2024-10-21T13:30:21.368Z",

File diff suppressed because it is too large Load Diff

View File

@@ -339,8 +339,9 @@ If the authentication is successful, the request returns a `201` response code.
The Medusa application defines an API route at `/auth/{actor_type}/{auth_provider}/update` that accepts a token and, if valid, updates the user's password.
```bash
curl -X POST http://localhost:9000/auth/{actor_type}/{providers}/update?token=123
curl -X POST http://localhost:9000/auth/{actor_type}/{providers}/update
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {token}' \
--data-raw '{
"email": "Whitney_Schultz@gmail.com",
"password": "supersecret"
@@ -360,9 +361,15 @@ Its path parameters are:
- `{actor_type}`: the actor type of the user you're authenticating. For example, `customer`.
- `{provider}`: the auth provider to handle the authentication. For example, `emailpass`.
#### Query Parameters
#### Pass Token in Authorization Header
The route accepts a `token` query parameter, which is the token generated using the [Generate Reset Password Token route](#generate-reset-password-token-route).
<Note>
Before [Medusa v2.6](https://github.com/medusajs/medusa/releases/tag/v2.6), you passed the token as a query parameter. Now, you must pass it in the `Authorization` header.
</Note>
In the request's authorization header, you must pass the token generated using the [Generate Reset Password Token route](#generate-reset-password-token-route). You pass it as a bearer token.
### Request Body Parameters

View File

@@ -167,8 +167,8 @@ export const resetPasswordFetchHighlights = [
["3", "email", "Receive the email from a query parameter."],
["9", "password", "Assuming the password is retrieved from an input field."],
["14", "fetch", "Send a request to update the customer's password."],
["14", "token", "Pass the token as a query parameter."],
["20", "body", "Pass the email and password in the request body."]
["19", "token", "Pass the token in the Authorization header."],
["21", "body", "Pass the email and password in the request body."]
]
```ts highlights={resetPasswordFetchHighlights}
@@ -185,11 +185,12 @@ export const resetPasswordFetchHighlights = [
return
}
fetch(`http://localhost:9000/auth/customer/emailpass/update?token=${token}`, {
fetch(`http://localhost:9000/auth/customer/emailpass/update`, {
credentials: "include",
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`,
},
body: JSON.stringify({
email,
@@ -210,8 +211,8 @@ export const resetPasswordHighlights = [
["18", "token", "Receive the token from a query parameter."],
["21", "email", "Receive the email from a query parameter."],
["35", "fetch", "Send a request to update the customer's password."],
["35", "token", "Pass the token as a query parameter."],
["41", "body", "Pass the email and password in the request body."]
["40", "token", "Pass the token in the Authorization header."],
["42", "body", "Pass the email and password in the request body."]
]
```tsx highlights={resetPasswordHighlights}
@@ -249,11 +250,12 @@ export const resetPasswordHighlights = [
}
setLoading(true)
fetch(`http://localhost:9000/auth/customer/emailpass/update?token=${token}`, {
fetch(`http://localhost:9000/auth/customer/emailpass/update`, {
credentials: "include",
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`,
},
body: JSON.stringify({
email,
@@ -289,4 +291,10 @@ export const resetPasswordHighlights = [
In this example, you receive the `token` and `email` from the page's query parameters.
Then, when the form that has the password field is submitted, you send a request to the `http://localhost:9000/auth/customer/emailpass/update` API route. You pass it the token as a query parameter, and the email and password in the request body.
Then, when the form that has the password field is submitted, you send a request to the `http://localhost:9000/auth/customer/emailpass/update` API route. You pass it the token as in the Authorization header as a bearer token, and the email and password in the request body.
<Note>
Before [Medusa v2.6](https://github.com/medusajs/medusa/releases/tag/v2.6), you passed the token as a query parameter. Now, you must pass it in the `Authorization` header.
</Note>

View File

@@ -1,7 +1,7 @@
export const generatedEditDates = {
"app/commerce-modules/auth/auth-providers/emailpass/page.mdx": "2025-01-13T11:31:35.361Z",
"app/commerce-modules/auth/auth-providers/page.mdx": "2024-10-08T07:27:21.859Z",
"app/commerce-modules/auth/authentication-route/page.mdx": "2025-01-13T11:31:17.572Z",
"app/commerce-modules/auth/authentication-route/page.mdx": "2025-03-04T09:13:45.919Z",
"app/commerce-modules/auth/examples/page.mdx": "2024-10-15T15:02:13.794Z",
"app/commerce-modules/auth/module-options/page.mdx": "2025-01-07T12:47:35.073Z",
"app/commerce-modules/auth/page.mdx": "2025-01-09T13:41:05.476Z",
@@ -2108,7 +2108,7 @@ export const generatedEditDates = {
"app/admin-components/layouts/two-column/page.mdx": "2024-10-07T11:16:10.092Z",
"app/admin-components/components/forms/page.mdx": "2024-10-09T12:48:04.229Z",
"app/commerce-modules/auth/reset-password/page.mdx": "2025-02-26T11:18:00.391Z",
"app/storefront-development/customers/reset-password/page.mdx": "2024-12-19T16:32:00.724Z",
"app/storefront-development/customers/reset-password/page.mdx": "2025-03-04T09:15:25.662Z",
"app/commerce-modules/api-key/links-to-other-modules/page.mdx": "2025-01-06T11:19:22.450Z",
"app/commerce-modules/cart/extend/page.mdx": "2024-12-25T12:48:59.149Z",
"app/commerce-modules/cart/links-to-other-modules/page.mdx": "2025-01-06T11:19:35.593Z",