docs: various improvements and fixes (#14257)
This commit is contained in:
1 parent
75eac9ebec
commit
0084460765
25 files changed
+141626
-131305
No files matched your search
@@ -1,3 +1,5 @@
|
||||
import { CodeTab, CodeTabs } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `${pageNumber} Add Columns to a Link Table`,
|
||||
}
|
||||
@@ -97,10 +99,13 @@ For example:
|
||||
|
||||
<Note>
|
||||
|
||||
Learn more about Link, how to resolve it, and its methods in [this chapter](../link/page.mdx).
|
||||
Refer to the [Link](../link/page.mdx) chapter to learn how to import and use the `link` instance.
|
||||
|
||||
</Note>
|
||||
|
||||
<CodeTabs group="link">
|
||||
<CodeTab label="Link" value="link">
|
||||
|
||||
```ts
|
||||
await link.create({
|
||||
[Modules.PRODUCT]: {
|
||||
@@ -117,6 +122,50 @@ await link.create({
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="createRemoteLinksStep" value="createRemoteLinksStep">
|
||||
|
||||
```ts
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
import { BLOG_MODULE } from "../modules/blog"
|
||||
import { createRemoteLinksStep } from "@medusajs/medusa/core-flows"
|
||||
import {
|
||||
createWorkflow,
|
||||
transform,
|
||||
} from "@medusajs/framework/workflows-sdk"
|
||||
|
||||
export const myWorkflow = createWorkflow(
|
||||
"my-workflow",
|
||||
() => {
|
||||
// ...
|
||||
const linkData = transform({
|
||||
// TODO pass input data
|
||||
}, () => {
|
||||
return [
|
||||
{
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "123",
|
||||
},
|
||||
[BLOG_MODULE]: {
|
||||
post_id: "321",
|
||||
},
|
||||
data: {
|
||||
metadata: {
|
||||
test: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
createRemoteLinksStep(linkData)
|
||||
// ...
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
|
||||
---
|
||||
|
||||
## Retrieve Custom Column with Link
|
||||
@@ -189,6 +238,9 @@ So, to update the value of a custom column in a created link, use the `create` m
|
||||
|
||||
For example:
|
||||
|
||||
<CodeTabs group="link">
|
||||
<CodeTab label="Link" value="link">
|
||||
|
||||
```ts
|
||||
await link.create({
|
||||
[Modules.PRODUCT]: {
|
||||
@@ -204,3 +256,47 @@ await link.create({
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="updateRemoteLinksStep" value="updateRemoteLinksStep">
|
||||
|
||||
```ts
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
import { BLOG_MODULE } from "../modules/blog"
|
||||
import { updateRemoteLinksStep } from "@medusajs/medusa/core-flows"
|
||||
import {
|
||||
createWorkflow,
|
||||
transform,
|
||||
} from "@medusajs/framework/workflows-sdk"
|
||||
|
||||
export const myWorkflow = createWorkflow(
|
||||
"my-workflow",
|
||||
() => {
|
||||
// ...
|
||||
const linkData = transform({
|
||||
// TODO pass input data
|
||||
}, () => {
|
||||
return [
|
||||
{
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "123",
|
||||
},
|
||||
[BLOG_MODULE]: {
|
||||
post_id: "321",
|
||||
},
|
||||
data: {
|
||||
metadata: {
|
||||
test: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
updateRemoteLinksStep(linkData)
|
||||
// ...
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
@@ -1,3 +1,5 @@
|
||||
import { CodeTab, CodeTabs } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `${pageNumber} Link`,
|
||||
}
|
||||
@@ -41,6 +43,17 @@ export async function POST(
|
||||
|
||||
You can use its methods to manage links, such as create or delete links.
|
||||
|
||||
### Link Usage in Workflows
|
||||
|
||||
To perform link operations in a [workflow](../../workflows/page.mdx), Medusa provides the following steps out-of-the-box:
|
||||
|
||||
- [createRemoteLinkStep](!resources!/references/helper-steps/createRemoteLinkStep): Creates a link between records of two data models.
|
||||
- [dismissRemoteLinkStep](!resources!/references/helper-steps/dismissRemoteLinkStep): Removes a link between records of two data models.
|
||||
- [removeRemoteLinkStep](!resources!/references/helper-steps/removeRemoteLinkStep): Deletes all linked records whose links are defined with cascade deletion.
|
||||
- [updateRemoteLinksStep](!resources!/references/helper-steps/updateRemoteLinksStep): Updates links between records of two data models.
|
||||
|
||||
The rest of this chapter provides examples using the Link class and the workflow steps.
|
||||
|
||||
---
|
||||
|
||||
## Create Link
|
||||
@@ -49,6 +62,9 @@ To create a link between records of two data models, use the `create` method of
|
||||
|
||||
For example:
|
||||
|
||||
<CodeTabs group="link">
|
||||
<CodeTab label="Link" value="link">
|
||||
|
||||
```ts
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
|
||||
@@ -58,12 +74,50 @@ await link.create({
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
"helloModuleService": {
|
||||
my_custom_id: "mc_123",
|
||||
blog: {
|
||||
post_id: "post_123",
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="createRemoteLinkStep" value="createRemoteLinkStep">
|
||||
|
||||
```ts
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
import { createRemoteLinkStep } from "@medusajs/medusa/core-flows"
|
||||
import {
|
||||
createWorkflow,
|
||||
transform,
|
||||
} from "@medusajs/framework/workflows-sdk"
|
||||
|
||||
export const myWorkflow = createWorkflow(
|
||||
"my-workflow",
|
||||
() => {
|
||||
// ...
|
||||
const linkData = transform({
|
||||
// TODO pass input data
|
||||
}, () => {
|
||||
return [
|
||||
{
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
blog: {
|
||||
post_id: "post_123",
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
createRemoteLinkStep(linkData)
|
||||
// ...
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
|
||||
The `create` method accepts as a parameter an object. The object’s keys are the names of the linked modules.
|
||||
|
||||
<Note title="Important">
|
||||
@@ -74,7 +128,7 @@ The keys (names of linked modules) must be in the same [direction](../directions
|
||||
|
||||
The value of each module’s property is an object, whose keys are of the format `{data_model_snake_name}_id`, and values are the IDs of the linked record.
|
||||
|
||||
So, in the example above, you link a record of the `MyCustom` data model in a `hello` module to a `Product` record in the Product Module.
|
||||
So, in the example above, you link a record of the `Post` data model in a `blog` module to a `Product` record in the Product Module.
|
||||
|
||||
### Enforced Integrity Constraints on Link Creation
|
||||
|
||||
@@ -88,23 +142,23 @@ await link.create({
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
"helloModuleService": {
|
||||
my_custom_id: "mc_123",
|
||||
blog: {
|
||||
post_id: "post_123",
|
||||
},
|
||||
})
|
||||
|
||||
// throws an error because `prod_123` already has a link to `mc_123`
|
||||
// throws an error because `prod_123` already has a link to `post_123`
|
||||
await link.create({
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
"helloModuleService": {
|
||||
my_custom_id: "mc_456",
|
||||
blog: {
|
||||
post_id: "mc_456",
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
- If the link is one-to-many and the "one" side already has a link to another record of the same data model. For example, if a product can have many `MyCustom` records, but a `MyCustom` record can only have one product:
|
||||
- If the link is one-to-many and the "one" side already has a link to another record of the same data model. For example, if a product can have many `Post` records, but a `Post` record can only have one product:
|
||||
|
||||
```ts
|
||||
// no error
|
||||
@@ -112,8 +166,8 @@ await link.create({
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
"helloModuleService": {
|
||||
my_custom_id: "mc_123",
|
||||
blog: {
|
||||
post_id: "post_123",
|
||||
},
|
||||
})
|
||||
|
||||
@@ -122,18 +176,18 @@ await link.create({
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
"helloModuleService": {
|
||||
my_custom_id: "mc_456",
|
||||
blog: {
|
||||
post_id: "mc_456",
|
||||
},
|
||||
})
|
||||
|
||||
// throws an error because `mc_123` already has a link to `prod_123`
|
||||
// throws an error because `post_123` already has a link to `prod_123`
|
||||
await link.create({
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_456",
|
||||
},
|
||||
"helloModuleService": {
|
||||
my_custom_id: "mc_123",
|
||||
blog: {
|
||||
post_id: "post_123",
|
||||
},
|
||||
})
|
||||
```
|
||||
@@ -148,6 +202,9 @@ To remove a link between records of two data models, use the `dismiss` method of
|
||||
|
||||
For example:
|
||||
|
||||
<CodeTabs group="link">
|
||||
<CodeTab label="Link" value="link">
|
||||
|
||||
```ts
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
|
||||
@@ -157,12 +214,50 @@ await link.dismiss({
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
"helloModuleService": {
|
||||
my_custom_id: "mc_123",
|
||||
blog: {
|
||||
post_id: "post_123",
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="dismissRemoteLinkStep" value="dismissRemoteLinkStep">
|
||||
|
||||
```ts
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
import { dismissRemoteLinkStep } from "@medusajs/medusa/core-flows"
|
||||
import {
|
||||
createWorkflow,
|
||||
transform,
|
||||
} from "@medusajs/framework/workflows-sdk"
|
||||
|
||||
export const myWorkflow = createWorkflow(
|
||||
"my-workflow",
|
||||
() => {
|
||||
// ...
|
||||
const linkData = transform({
|
||||
// TODO pass input data
|
||||
}, () => {
|
||||
return [
|
||||
{
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
blog: {
|
||||
post_id: "post_123",
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
dismissRemoteLinkStep(linkData)
|
||||
// ...
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
|
||||
The `dismiss` method accepts the same parameter type as the [create method](#create-link).
|
||||
|
||||
<Note title="Important">
|
||||
@@ -179,6 +274,9 @@ If you delete a record using a workflow or its module's service, use the `delete
|
||||
|
||||
For example:
|
||||
|
||||
<CodeTabs group="link">
|
||||
<CodeTab label="Link" value="link">
|
||||
|
||||
```ts
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
|
||||
@@ -193,6 +291,41 @@ await link.delete({
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="removeRemoteLinkStep" value="removeRemoteLinkStep">
|
||||
|
||||
```ts
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
import { removeRemoteLinkStep } from "@medusajs/medusa/core-flows"
|
||||
import {
|
||||
createWorkflow,
|
||||
transform,
|
||||
} from "@medusajs/framework/workflows-sdk"
|
||||
|
||||
export const myWorkflow = createWorkflow(
|
||||
"my-workflow",
|
||||
() => {
|
||||
// ...
|
||||
const linkData = transform({
|
||||
// TODO pass input data
|
||||
}, () => {
|
||||
return [
|
||||
{
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
removeRemoteLinkStep(linkData)
|
||||
// ...
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
|
||||
This deletes all records linked to the deleted product.
|
||||
|
||||
---
|
||||
@@ -216,3 +349,83 @@ await link.restore({
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Update Links
|
||||
|
||||
Links may have [custom columns](../custom-columns/page.mdx) to store additional information, such as a `metadata` column to store JSON data about the link.
|
||||
|
||||
You can update the custom columns of existing links by calling the `create` method again with the same linked records and the new values for the custom columns.
|
||||
|
||||
For example:
|
||||
|
||||
<CodeTabs group="link">
|
||||
<CodeTab label="Link" value="link">
|
||||
|
||||
```ts
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
|
||||
// ...
|
||||
|
||||
await link.create({
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
blog: {
|
||||
post_id: "post_123",
|
||||
},
|
||||
data: {
|
||||
metadata: {
|
||||
featured: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="updateRemoteLinksStep" value="updateRemoteLinksStep">
|
||||
|
||||
```ts
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
import { updateRemoteLinksStep } from "@medusajs/medusa/core-flows"
|
||||
import {
|
||||
createWorkflow,
|
||||
transform,
|
||||
} from "@medusajs/framework/workflows-sdk"
|
||||
|
||||
export const myWorkflow = createWorkflow(
|
||||
"my-workflow",
|
||||
() => {
|
||||
// ...
|
||||
const linkData = transform({
|
||||
// TODO pass input data
|
||||
}, () => {
|
||||
return [
|
||||
{
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
blog: {
|
||||
post_id: "post_123",
|
||||
},
|
||||
data: {
|
||||
metadata: {
|
||||
featured: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
updateRemoteLinksStep(linkData)
|
||||
// ...
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
|
||||
The object parameter you pass to the `create` method (or the `updateRemoteLinksStep` step) accepts an optional `data` property. The value of this property is an object whose keys are the names of the custom columns to update, and values are the new values for those columns.
|
||||
|
||||
Learn more in the [Custom Columns](../custom-columns/page.mdx) chapter.
|
||||
@@ -134,9 +134,15 @@ Refer to the [Locking Module reference](!resources!/references/locking-service)
|
||||
|
||||
## Locks in Nested Workflows
|
||||
|
||||
[Nested workflows](../execute-another-workflow/page.mdx) can't acquire locks. So, if you're using a workflow that acquires locks within another workflow, the parent workflow must handle the locking mechanism.
|
||||
When a [Nested workflows](../execute-another-workflow/page.mdx) acquires a lock with `acquireLockStep`, the lock is not acquired. So, if you're using a workflow that acquires locks with `acquireLockStep` within another workflow, the parent workflow must handle the locking mechanism.
|
||||
|
||||
For example, consider a custom workflow that executes Medusa's [completeCartWorkflow](!resources!/references/medusa-workflows/completeCartWorkflow). The `completeCartWorkflow` acquires locks on the cart to prevent race conditions.
|
||||
<Note>
|
||||
|
||||
If the nested workflow acquires a lock in a step using the Locking Module's service, the lock will be acquired as expected.
|
||||
|
||||
</Note>
|
||||
|
||||
For example, consider a custom workflow that executes Medusa's [completeCartWorkflow](!resources!/references/medusa-workflows/completeCartWorkflow). The `completeCartWorkflow` acquires locks on the cart with `acquireLockStep` to prevent race conditions.
|
||||
|
||||
Therefore, the custom workflow must acquire and release the locks around the `completeCartWorkflow` execution. For example:
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ export const generatedEditDates = {
|
||||
"app/learn/fundamentals/api-routes/errors/page.mdx": "2025-06-19T16:09:08.563Z",
|
||||
"app/learn/fundamentals/admin/constraints/page.mdx": "2025-07-21T08:20:43.223Z",
|
||||
"app/learn/debugging-and-testing/testing-tools/modules-tests/page.mdx": "2025-07-23T15:32:18.008Z",
|
||||
"app/learn/fundamentals/module-links/custom-columns/page.mdx": "2025-09-29T16:09:36.116Z",
|
||||
"app/learn/fundamentals/module-links/custom-columns/page.mdx": "2025-12-09T13:27:05.446Z",
|
||||
"app/learn/fundamentals/module-links/directions/page.mdx": "2025-03-17T12:52:06.161Z",
|
||||
"app/learn/fundamentals/module-links/page.mdx": "2025-11-28T13:45:06.742Z",
|
||||
"app/learn/fundamentals/module-links/query/page.mdx": "2025-10-27T09:30:26.957Z",
|
||||
@@ -98,7 +98,7 @@ export const generatedEditDates = {
|
||||
"app/learn/fundamentals/workflows/multiple-step-usage/page.mdx": "2025-08-01T14:59:59.501Z",
|
||||
"app/learn/installation/page.mdx": "2025-12-04T14:30:00.510Z",
|
||||
"app/learn/fundamentals/data-models/check-constraints/page.mdx": "2025-07-25T13:50:21.065Z",
|
||||
"app/learn/fundamentals/module-links/link/page.mdx": "2025-11-28T13:42:03.037Z",
|
||||
"app/learn/fundamentals/module-links/link/page.mdx": "2025-12-09T13:27:05.446Z",
|
||||
"app/learn/fundamentals/workflows/store-executions/page.mdx": "2025-04-17T08:29:10.166Z",
|
||||
"app/learn/fundamentals/plugins/create/page.mdx": "2025-04-17T08:29:09.910Z",
|
||||
"app/learn/fundamentals/plugins/page.mdx": "2025-01-22T10:14:10.433Z",
|
||||
@@ -132,7 +132,7 @@ export const generatedEditDates = {
|
||||
"app/learn/fundamentals/scheduled-jobs/interval/page.mdx": "2025-09-02T08:36:12.714Z",
|
||||
"app/learn/debugging-and-testing/feature-flags/create/page.mdx": "2025-09-02T08:36:12.714Z",
|
||||
"app/learn/debugging-and-testing/feature-flags/page.mdx": "2025-09-02T08:36:12.714Z",
|
||||
"app/learn/fundamentals/workflows/locks/page.mdx": "2025-11-26T11:40:04.279Z",
|
||||
"app/learn/fundamentals/workflows/locks/page.mdx": "2025-12-09T11:20:25.011Z",
|
||||
"app/learn/codemods/page.mdx": "2025-09-29T15:40:03.620Z",
|
||||
"app/learn/codemods/replace-imports/page.mdx": "2025-10-09T11:37:44.754Z",
|
||||
"app/learn/fundamentals/admin/translations/page.mdx": "2025-10-30T11:55:32.221Z",
|
||||
|
||||
@@ -15533,7 +15533,9 @@ The object you pass to Link's `create` method accepts a `data` property. Its val
|
||||
|
||||
For example:
|
||||
|
||||
Learn more about Link, how to resolve it, and its methods in [this chapter](https://docs.medusajs.com/learn/fundamentals/module-links/link/index.html.md).
|
||||
Refer to the [Link](https://docs.medusajs.com/learn/fundamentals/module-links/link/index.html.md) chapter to learn how to import and use the `link` instance.
|
||||
|
||||
### Link
|
||||
|
||||
```ts
|
||||
await link.create({
|
||||
@@ -15551,6 +15553,46 @@ await link.create({
|
||||
})
|
||||
```
|
||||
|
||||
### createRemoteLinksStep
|
||||
|
||||
```ts
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
import { BLOG_MODULE } from "../modules/blog"
|
||||
import { createRemoteLinksStep } from "@medusajs/medusa/core-flows"
|
||||
import {
|
||||
createWorkflow,
|
||||
transform,
|
||||
} from "@medusajs/framework/workflows-sdk"
|
||||
|
||||
export const myWorkflow = createWorkflow(
|
||||
"my-workflow",
|
||||
() => {
|
||||
// ...
|
||||
const linkData = transform({
|
||||
// TODO pass input data
|
||||
}, () => {
|
||||
return [
|
||||
{
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "123",
|
||||
},
|
||||
[BLOG_MODULE]: {
|
||||
post_id: "321",
|
||||
},
|
||||
data: {
|
||||
metadata: {
|
||||
test: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
createRemoteLinksStep(linkData)
|
||||
// ...
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Retrieve Custom Column with Link
|
||||
@@ -15611,6 +15653,8 @@ So, to update the value of a custom column in a created link, use the `create` m
|
||||
|
||||
For example:
|
||||
|
||||
### Link
|
||||
|
||||
```ts
|
||||
await link.create({
|
||||
[Modules.PRODUCT]: {
|
||||
@@ -15627,6 +15671,46 @@ await link.create({
|
||||
})
|
||||
```
|
||||
|
||||
### updateRemoteLinksStep
|
||||
|
||||
```ts
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
import { BLOG_MODULE } from "../modules/blog"
|
||||
import { updateRemoteLinksStep } from "@medusajs/medusa/core-flows"
|
||||
import {
|
||||
createWorkflow,
|
||||
transform,
|
||||
} from "@medusajs/framework/workflows-sdk"
|
||||
|
||||
export const myWorkflow = createWorkflow(
|
||||
"my-workflow",
|
||||
() => {
|
||||
// ...
|
||||
const linkData = transform({
|
||||
// TODO pass input data
|
||||
}, () => {
|
||||
return [
|
||||
{
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "123",
|
||||
},
|
||||
[BLOG_MODULE]: {
|
||||
post_id: "321",
|
||||
},
|
||||
data: {
|
||||
metadata: {
|
||||
test: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
updateRemoteLinksStep(linkData)
|
||||
// ...
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
# Module Link Direction
|
||||
|
||||
@@ -16488,6 +16572,17 @@ export async function POST(
|
||||
|
||||
You can use its methods to manage links, such as create or delete links.
|
||||
|
||||
### Link Usage in Workflows
|
||||
|
||||
To perform link operations in a [workflow](https://docs.medusajs.com/learn/fundamentals/workflows/index.html.md), Medusa provides the following steps out-of-the-box:
|
||||
|
||||
- [createRemoteLinkStep](https://docs.medusajs.com/resources/references/helper-steps/createRemoteLinkStep/index.html.md): Creates a link between records of two data models.
|
||||
- [dismissRemoteLinkStep](https://docs.medusajs.com/resources/references/helper-steps/dismissRemoteLinkStep/index.html.md): Removes a link between records of two data models.
|
||||
- [removeRemoteLinkStep](https://docs.medusajs.com/resources/references/helper-steps/removeRemoteLinkStep/index.html.md): Deletes all linked records whose links are defined with cascade deletion.
|
||||
- [updateRemoteLinksStep](https://docs.medusajs.com/resources/references/helper-steps/updateRemoteLinksStep/index.html.md): Updates links between records of two data models.
|
||||
|
||||
The rest of this chapter provides examples using the Link class and the workflow steps.
|
||||
|
||||
***
|
||||
|
||||
## Create Link
|
||||
@@ -16496,6 +16591,8 @@ To create a link between records of two data models, use the `create` method of
|
||||
|
||||
For example:
|
||||
|
||||
### Link
|
||||
|
||||
```ts
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
|
||||
@@ -16505,19 +16602,53 @@ await link.create({
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
"helloModuleService": {
|
||||
my_custom_id: "mc_123",
|
||||
blog: {
|
||||
post_id: "post_123",
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### createRemoteLinkStep
|
||||
|
||||
```ts
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
import { createRemoteLinkStep } from "@medusajs/medusa/core-flows"
|
||||
import {
|
||||
createWorkflow,
|
||||
transform,
|
||||
} from "@medusajs/framework/workflows-sdk"
|
||||
|
||||
export const myWorkflow = createWorkflow(
|
||||
"my-workflow",
|
||||
() => {
|
||||
// ...
|
||||
const linkData = transform({
|
||||
// TODO pass input data
|
||||
}, () => {
|
||||
return [
|
||||
{
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
blog: {
|
||||
post_id: "post_123",
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
createRemoteLinkStep(linkData)
|
||||
// ...
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
The `create` method accepts as a parameter an object. The object’s keys are the names of the linked modules.
|
||||
|
||||
The keys (names of linked modules) must be in the same [direction](https://docs.medusajs.com/learn/fundamentals/module-links/directions/index.html.md) of the link definition.
|
||||
|
||||
The value of each module’s property is an object, whose keys are of the format `{data_model_snake_name}_id`, and values are the IDs of the linked record.
|
||||
|
||||
So, in the example above, you link a record of the `MyCustom` data model in a `hello` module to a `Product` record in the Product Module.
|
||||
So, in the example above, you link a record of the `Post` data model in a `blog` module to a `Product` record in the Product Module.
|
||||
|
||||
### Enforced Integrity Constraints on Link Creation
|
||||
|
||||
@@ -16531,23 +16662,23 @@ await link.create({
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
"helloModuleService": {
|
||||
my_custom_id: "mc_123",
|
||||
blog: {
|
||||
post_id: "post_123",
|
||||
},
|
||||
})
|
||||
|
||||
// throws an error because `prod_123` already has a link to `mc_123`
|
||||
// throws an error because `prod_123` already has a link to `post_123`
|
||||
await link.create({
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
"helloModuleService": {
|
||||
my_custom_id: "mc_456",
|
||||
blog: {
|
||||
post_id: "mc_456",
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
- If the link is one-to-many and the "one" side already has a link to another record of the same data model. For example, if a product can have many `MyCustom` records, but a `MyCustom` record can only have one product:
|
||||
- If the link is one-to-many and the "one" side already has a link to another record of the same data model. For example, if a product can have many `Post` records, but a `Post` record can only have one product:
|
||||
|
||||
```ts
|
||||
// no error
|
||||
@@ -16555,8 +16686,8 @@ await link.create({
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
"helloModuleService": {
|
||||
my_custom_id: "mc_123",
|
||||
blog: {
|
||||
post_id: "post_123",
|
||||
},
|
||||
})
|
||||
|
||||
@@ -16565,18 +16696,18 @@ await link.create({
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
"helloModuleService": {
|
||||
my_custom_id: "mc_456",
|
||||
blog: {
|
||||
post_id: "mc_456",
|
||||
},
|
||||
})
|
||||
|
||||
// throws an error because `mc_123` already has a link to `prod_123`
|
||||
// throws an error because `post_123` already has a link to `prod_123`
|
||||
await link.create({
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_456",
|
||||
},
|
||||
"helloModuleService": {
|
||||
my_custom_id: "mc_123",
|
||||
blog: {
|
||||
post_id: "post_123",
|
||||
},
|
||||
})
|
||||
```
|
||||
@@ -16591,6 +16722,8 @@ To remove a link between records of two data models, use the `dismiss` method of
|
||||
|
||||
For example:
|
||||
|
||||
### Link
|
||||
|
||||
```ts
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
|
||||
@@ -16600,12 +16733,46 @@ await link.dismiss({
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
"helloModuleService": {
|
||||
my_custom_id: "mc_123",
|
||||
blog: {
|
||||
post_id: "post_123",
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### dismissRemoteLinkStep
|
||||
|
||||
```ts
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
import { dismissRemoteLinkStep } from "@medusajs/medusa/core-flows"
|
||||
import {
|
||||
createWorkflow,
|
||||
transform,
|
||||
} from "@medusajs/framework/workflows-sdk"
|
||||
|
||||
export const myWorkflow = createWorkflow(
|
||||
"my-workflow",
|
||||
() => {
|
||||
// ...
|
||||
const linkData = transform({
|
||||
// TODO pass input data
|
||||
}, () => {
|
||||
return [
|
||||
{
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
blog: {
|
||||
post_id: "post_123",
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
dismissRemoteLinkStep(linkData)
|
||||
// ...
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
The `dismiss` method accepts the same parameter type as the [create method](#create-link).
|
||||
|
||||
The keys (names of linked modules) must be in the same [direction](https://docs.medusajs.com/learn/fundamentals/module-links/directions/index.html.md) of the link definition.
|
||||
@@ -16618,6 +16785,8 @@ If you delete a record using a workflow or its module's service, use the `delete
|
||||
|
||||
For example:
|
||||
|
||||
### Link
|
||||
|
||||
```ts
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
|
||||
@@ -16632,6 +16801,37 @@ await link.delete({
|
||||
})
|
||||
```
|
||||
|
||||
### removeRemoteLinkStep
|
||||
|
||||
```ts
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
import { removeRemoteLinkStep } from "@medusajs/medusa/core-flows"
|
||||
import {
|
||||
createWorkflow,
|
||||
transform,
|
||||
} from "@medusajs/framework/workflows-sdk"
|
||||
|
||||
export const myWorkflow = createWorkflow(
|
||||
"my-workflow",
|
||||
() => {
|
||||
// ...
|
||||
const linkData = transform({
|
||||
// TODO pass input data
|
||||
}, () => {
|
||||
return [
|
||||
{
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
removeRemoteLinkStep(linkData)
|
||||
// ...
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
This deletes all records linked to the deleted product.
|
||||
|
||||
***
|
||||
@@ -16656,6 +16856,81 @@ await link.restore({
|
||||
})
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Update Links
|
||||
|
||||
Links may have [custom columns](https://docs.medusajs.com/learn/fundamentals/module-links/custom-columns/index.html.md) to store additional information, such as a `metadata` column to store JSON data about the link.
|
||||
|
||||
You can update the custom columns of existing links by calling the `create` method again with the same linked records and the new values for the custom columns.
|
||||
|
||||
For example:
|
||||
|
||||
### Link
|
||||
|
||||
```ts
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
|
||||
// ...
|
||||
|
||||
await link.create({
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
blog: {
|
||||
post_id: "post_123",
|
||||
},
|
||||
data: {
|
||||
metadata: {
|
||||
featured: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### updateRemoteLinksStep
|
||||
|
||||
```ts
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
import { updateRemoteLinksStep } from "@medusajs/medusa/core-flows"
|
||||
import {
|
||||
createWorkflow,
|
||||
transform,
|
||||
} from "@medusajs/framework/workflows-sdk"
|
||||
|
||||
export const myWorkflow = createWorkflow(
|
||||
"my-workflow",
|
||||
() => {
|
||||
// ...
|
||||
const linkData = transform({
|
||||
// TODO pass input data
|
||||
}, () => {
|
||||
return [
|
||||
{
|
||||
[Modules.PRODUCT]: {
|
||||
product_id: "prod_123",
|
||||
},
|
||||
blog: {
|
||||
post_id: "post_123",
|
||||
},
|
||||
data: {
|
||||
metadata: {
|
||||
featured: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
updateRemoteLinksStep(linkData)
|
||||
// ...
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
The object parameter you pass to the `create` method (or the `updateRemoteLinksStep` step) accepts an optional `data` property. The value of this property is an object whose keys are the names of the custom columns to update, and values are the new values for those columns.
|
||||
|
||||
Learn more in the [Custom Columns](https://docs.medusajs.com/learn/fundamentals/module-links/custom-columns/index.html.md) chapter.
|
||||
|
||||
|
||||
# Define Module Link
|
||||
|
||||
@@ -23420,9 +23695,11 @@ Refer to the [Locking Module reference](https://docs.medusajs.com/resources/refe
|
||||
|
||||
## Locks in Nested Workflows
|
||||
|
||||
[Nested workflows](https://docs.medusajs.com/learn/fundamentals/workflows/execute-another-workflow/index.html.md) can't acquire locks. So, if you're using a workflow that acquires locks within another workflow, the parent workflow must handle the locking mechanism.
|
||||
When a [Nested workflows](https://docs.medusajs.com/learn/fundamentals/workflows/execute-another-workflow/index.html.md) acquires a lock with `acquireLockStep`, the lock is not acquired. So, if you're using a workflow that acquires locks with `acquireLockStep` within another workflow, the parent workflow must handle the locking mechanism.
|
||||
|
||||
For example, consider a custom workflow that executes Medusa's [completeCartWorkflow](https://docs.medusajs.com/resources/references/medusa-workflows/completeCartWorkflow/index.html.md). The `completeCartWorkflow` acquires locks on the cart to prevent race conditions.
|
||||
If the nested workflow acquires a lock in a step using the Locking Module's service, the lock will be acquired as expected.
|
||||
|
||||
For example, consider a custom workflow that executes Medusa's [completeCartWorkflow](https://docs.medusajs.com/resources/references/medusa-workflows/completeCartWorkflow/index.html.md). The `completeCartWorkflow` acquires locks on the cart with `acquireLockStep` to prevent race conditions.
|
||||
|
||||
Therefore, the custom workflow must acquire and release the locks around the `completeCartWorkflow` execution. For example:
|
||||
|
||||
@@ -35434,7 +35711,7 @@ const totalRefunded = refundTransactions?.reduce((acc, t) => acc + Math.abs(t!.a
|
||||
|
||||
In this section of the documentation, you'll find guides and references related to Medusa's Commerce Modules.
|
||||
|
||||
A Commerce Module provides features for a commerce domain within its service. The Medusa application exposes these features in its API routes to clients.
|
||||
A Commerce Module provides features for a commerce domain within its service. When you install the Medusa application, all Commerce Modules are available out-of-the-box. The Medusa application exposes their features in its core API routes to clients.
|
||||
|
||||
A Commerce Module also defines data models, representing tables in the database. The Medusa Framework and tools allow you to extend these data models to add custom fields.
|
||||
|
||||
@@ -35465,7 +35742,7 @@ A Commerce Module also defines data models, representing tables in the database.
|
||||
|
||||
The Commerce Modules can be used in many use cases, including:
|
||||
|
||||
- Medusa Application: The Medusa application uses the Commerce Modules to expose commerce features through the REST APIs.
|
||||
- Medusa Application: The Medusa application comes with all Commerce Modules pre-installed and configured. Their commerce features are exposed through REST APIs.
|
||||
- Serverless Application: Use the Commerce Modules in a serverless application, such as a Next.js application, without having to manage a fully-fledged ecommerce system. You can use it by installing it in your Node.js project as an NPM package.
|
||||
- Node.js Application: Use the Commerce Modules in any Node.js application by installing it with NPM.
|
||||
|
||||
@@ -41850,7 +42127,7 @@ Learn more about why modules are isolated in [this documentation](https://docs.m
|
||||
## Store Features
|
||||
|
||||
- [Store Management](https://docs.medusajs.com/references/store/models/Store/index.html.md): Create and manage stores in your application.
|
||||
- [Multi-Tenancy Support](https://docs.medusajs.com/references/store/models/Store/index.html.md): Create multiple stores, each having its own configurations.
|
||||
- [Multi-Tenancy Support](https://docs.medusajs.com/references/store/models/Store/index.html.md): While Medusa doesn't natively support multi-tenancy, the Store Module allows you to create and manage multiple stores within a single Medusa instance. You can then build customizations to link products, customers, orders, and other resources to specific stores.
|
||||
|
||||
***
|
||||
|
||||
@@ -46201,8 +46478,8 @@ module.exports = defineConfig({
|
||||
// keep jobs for 1 hour or up to 1000 jobs
|
||||
age: 3600,
|
||||
count: 1000,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -95255,7 +95532,7 @@ const StripeSavedPaymentMethodsContainer = ({
|
||||
await initiatePaymentSession(cart, {
|
||||
provider_id: method.provider_id,
|
||||
data: {
|
||||
payment_method_id: method.id,
|
||||
payment_method: method.id,
|
||||
},
|
||||
}).catch((error) => {
|
||||
setError(error.message)
|
||||
|
||||
Reference in new issue
Block a user