docs: improvements to module and data model documentation (#8062)
* docs: improvements to module and data model documentation * add note about data model name casing
No files matched your search
@@ -12,6 +12,18 @@ Data model relationships are in active development and may change.
|
|||||||
|
|
||||||
</Note>
|
</Note>
|
||||||
|
|
||||||
|
<Note title="Use data model relationships when" type="success">
|
||||||
|
|
||||||
|
- You want to create a relation between data models in the same module.
|
||||||
|
|
||||||
|
</Note>
|
||||||
|
|
||||||
|
<Note title="Don't use data model relationships if" type="error">
|
||||||
|
|
||||||
|
- You want to create a relationship between data models in different modules. Use module links instead.
|
||||||
|
|
||||||
|
</Note>
|
||||||
|
|
||||||
## What is a Relationship Property?
|
## What is a Relationship Property?
|
||||||
|
|
||||||
A relationship property is defined using relation methods, such as `hasOne` or `belongsTo`. It represents a relationship between two data models in a module.
|
A relationship property is defined using relation methods, such as `hasOne` or `belongsTo`. It represents a relationship between two data models in a module.
|
||||||
|
|||||||
@@ -18,6 +18,18 @@ A module link forms an association between two data models of different modules,
|
|||||||
|
|
||||||
You can then retrieve data across the linked modules, and manage their linked records.
|
You can then retrieve data across the linked modules, and manage their linked records.
|
||||||
|
|
||||||
|
<Note title="Use module links when" type="success">
|
||||||
|
|
||||||
|
- You want to create a relation between data models from different modules.
|
||||||
|
|
||||||
|
</Note>
|
||||||
|
|
||||||
|
<Note title="Don't use module links if" type="error">
|
||||||
|
|
||||||
|
- You want to create a relationship between data models in the same module. Use data model relationships instead.
|
||||||
|
|
||||||
|
</Note>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Prerequisite: isQueryable Configuration
|
## Prerequisite: isQueryable Configuration
|
||||||
@@ -27,10 +39,13 @@ Before you define a module link, you must enable the `isQueryable` configuration
|
|||||||
For example:
|
For example:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
import { HELLO_MODULE } from "./src/modules/hello"
|
||||||
|
// ...
|
||||||
|
|
||||||
module.exports = defineConfig({
|
module.exports = defineConfig({
|
||||||
// ...
|
// ...
|
||||||
modules: {
|
modules: {
|
||||||
helloModuleService: {
|
[HELLO_MODULE]: {
|
||||||
resolve: "./modules/hello",
|
resolve: "./modules/hello",
|
||||||
definition: {
|
definition: {
|
||||||
isQueryable: true,
|
isQueryable: true,
|
||||||
|
|||||||
@@ -23,10 +23,13 @@ To pass options to a module, add an `options` property to the module’s configu
|
|||||||
For example:
|
For example:
|
||||||
|
|
||||||
```js title="medusa-config.js"
|
```js title="medusa-config.js"
|
||||||
|
import { HELLO_MODULE } from "./src/modules/hello"
|
||||||
|
// ...
|
||||||
|
|
||||||
module.exports = defineConfig({
|
module.exports = defineConfig({
|
||||||
// ...
|
// ...
|
||||||
modules: {
|
modules: {
|
||||||
helloModuleService: {
|
[HELLO_MODULE]: {
|
||||||
resolve: "./modules/hello",
|
resolve: "./modules/hello",
|
||||||
options: {
|
options: {
|
||||||
capitalize: true,
|
capitalize: true,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Table } from "docs-ui"
|
import { Tabs, TabsContent, TabsContentWrapper, TabsList, TabsTrigger } from "docs-ui"
|
||||||
|
|
||||||
export const metadata = {
|
export const metadata = {
|
||||||
title: `${pageNumber} Service Factory`,
|
title: `${pageNumber} Service Factory`,
|
||||||
@@ -60,118 +60,216 @@ The method's names are the operation's name, suffixed by the data model's name.
|
|||||||
|
|
||||||
For example, the following methods are generated for the code snippet above:
|
For example, the following methods are generated for the code snippet above:
|
||||||
|
|
||||||
<Table>
|
<Tabs defaultValue="listMyCustoms" layoutType="vertical" className="mt-2">
|
||||||
<Table.Header>
|
<TabsList>
|
||||||
<Table.Row>
|
<TabsTrigger value="listMyCustoms">listMyCustoms</TabsTrigger>
|
||||||
<Table.HeaderCell>Method</Table.HeaderCell>
|
<TabsTrigger value="listAndCountMyCustoms">listAndCountMyCustoms</TabsTrigger>
|
||||||
<Table.HeaderCell>Description</Table.HeaderCell>
|
<TabsTrigger value="retrieveMyCustom">retrieveMyCustom</TabsTrigger>
|
||||||
</Table.Row>
|
<TabsTrigger value="createMyCustoms">createMyCustoms</TabsTrigger>
|
||||||
</Table.Header>
|
<TabsTrigger value="updateMyCustoms">updateMyCustoms</TabsTrigger>
|
||||||
<Table.Body>
|
<TabsTrigger value="deleteMyCustoms">deleteMyCustoms</TabsTrigger>
|
||||||
<Table.Row>
|
<TabsTrigger value="softDeleteMyCustoms">softDeleteMyCustoms</TabsTrigger>
|
||||||
<Table.Cell>
|
<TabsTrigger value="restoreMyCustoms">restoreMyCustoms</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
<TabsContentWrapper className="[&_h3]:!mt-0">
|
||||||
|
<TabsContent value="listMyCustoms">
|
||||||
|
|
||||||
`listMyCustoms`
|
### listMyCustoms
|
||||||
|
|
||||||
</Table.Cell>
|
This method retrieves an array of records based on filters and pagination configurations.
|
||||||
<Table.Cell>
|
|
||||||
|
|
||||||
Retrieves an array of records based on filters and pagination configurations.
|
For example:
|
||||||
|
|
||||||
</Table.Cell>
|
```ts
|
||||||
</Table.Row>
|
const myCustoms = await helloModuleService
|
||||||
<Table.Row>
|
.listMyCustoms()
|
||||||
<Table.Cell>
|
|
||||||
|
|
||||||
`listAndCountMyCustoms`
|
// with filters
|
||||||
|
const myCustoms = await helloModuleService
|
||||||
|
.listMyCustoms({
|
||||||
|
id: ["123"]
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
</Table.Cell>
|
</TabsContent>
|
||||||
<Table.Cell>
|
<TabsContent value="listAndCountMyCustoms">
|
||||||
|
|
||||||
Retrieves a tuple of an array of records and the total count of available records based on the filters and pagination configurations provided.
|
### listAndCountMyCustoms
|
||||||
|
|
||||||
</Table.Cell>
|
This method retrieves a tuple of an array of records and the total count of available records based on the filters and pagination configurations provided.
|
||||||
</Table.Row>
|
|
||||||
<Table.Row>
|
|
||||||
<Table.Cell>
|
|
||||||
|
|
||||||
`retrieveMyCustom`
|
For example:
|
||||||
|
|
||||||
</Table.Cell>
|
```ts
|
||||||
<Table.Cell>
|
const [
|
||||||
|
myCustoms,
|
||||||
|
count
|
||||||
|
] = await helloModuleService.listAndCountMyCustoms()
|
||||||
|
|
||||||
Retrieves a record by its ID.
|
// with filters
|
||||||
|
const [
|
||||||
|
myCustoms,
|
||||||
|
count
|
||||||
|
] = await helloModuleService.listAndCountMyCustoms({
|
||||||
|
id: ["123"]
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
</Table.Cell>
|
</TabsContent>
|
||||||
</Table.Row>
|
<TabsContent value="retrieveMyCustom">
|
||||||
<Table.Row>
|
|
||||||
<Table.Cell>
|
|
||||||
|
|
||||||
`createMyCustoms`
|
### retrieveMyCustom
|
||||||
|
|
||||||
</Table.Cell>
|
This method retrieves a record by its ID.
|
||||||
<Table.Cell>
|
|
||||||
|
|
||||||
Create and retrieve records of the data model.
|
For example:
|
||||||
|
|
||||||
</Table.Cell>
|
```ts
|
||||||
</Table.Row>
|
const myCustom = await helloModuleService
|
||||||
<Table.Row>
|
.retrieveMyCustom("123")
|
||||||
<Table.Cell>
|
```
|
||||||
|
|
||||||
`updateMyCustoms`
|
</TabsContent>
|
||||||
|
<TabsContent value="createMyCustoms">
|
||||||
|
|
||||||
</Table.Cell>
|
### createMyCustoms
|
||||||
<Table.Cell>
|
|
||||||
|
|
||||||
Update and retrieve records of the data model.
|
This method creates and retrieves records of the data model.
|
||||||
|
|
||||||
</Table.Cell>
|
For example:
|
||||||
</Table.Row>
|
|
||||||
<Table.Row>
|
|
||||||
<Table.Cell>
|
|
||||||
|
|
||||||
`deleteMyCustoms`
|
```ts
|
||||||
|
const myCustom = await helloModuleService
|
||||||
|
.createMyCustoms({
|
||||||
|
name: "test"
|
||||||
|
})
|
||||||
|
|
||||||
</Table.Cell>
|
// create multiple
|
||||||
<Table.Cell>
|
const myCustoms = await helloModuleService
|
||||||
|
.createMyCustoms([
|
||||||
|
{
|
||||||
|
name: "test"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "test 2"
|
||||||
|
},
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
Deletes records by an ID or filter.
|
</TabsContent>
|
||||||
|
<TabsContent value="updateMyCustoms">
|
||||||
|
|
||||||
</Table.Cell>
|
### updateMyCustoms
|
||||||
</Table.Row>
|
|
||||||
<Table.Row>
|
|
||||||
<Table.Cell>
|
|
||||||
|
|
||||||
`softDeleteMyCustoms`
|
This method updates and retrieves records of the data model.
|
||||||
|
|
||||||
</Table.Cell>
|
For example:
|
||||||
<Table.Cell>
|
|
||||||
|
|
||||||
Soft-deletes records using an array of IDs or an object of filters.
|
```ts
|
||||||
|
const myCustom = await helloModuleService
|
||||||
|
.updateMyCustoms({
|
||||||
|
id: "123",
|
||||||
|
name: "test"
|
||||||
|
})
|
||||||
|
|
||||||
</Table.Cell>
|
// update multiple
|
||||||
</Table.Row>
|
const myCustoms = await helloModuleService
|
||||||
<Table.Row>
|
.updateMyCustoms([
|
||||||
<Table.Cell>
|
{
|
||||||
|
id: "123",
|
||||||
|
name: "test"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "321",
|
||||||
|
name: "test 2"
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
`restoreMyCustoms`
|
// use filters
|
||||||
|
const myCustoms = await helloModuleService
|
||||||
|
.updateMyCustoms([
|
||||||
|
{
|
||||||
|
selector: {
|
||||||
|
id: ["123", "321"]
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
name: "test"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
</Table.Cell>
|
</TabsContent>
|
||||||
<Table.Cell>
|
<TabsContent value="deleteMyCustoms">
|
||||||
|
|
||||||
Restores soft-deleted records using an array of IDs or an object of filters.
|
### deleteMyCustoms
|
||||||
|
|
||||||
</Table.Cell>
|
This method deletes records by an ID or filter.
|
||||||
</Table.Row>
|
|
||||||
</Table.Body>
|
|
||||||
</Table>
|
|
||||||
|
|
||||||
<Note>
|
For example:
|
||||||
|
|
||||||
Except for the `retrieve` method, the suffixed data model's name is plural.
|
```ts
|
||||||
|
await helloModuleService.deleteMyCustoms("123")
|
||||||
|
|
||||||
</Note>
|
// delete multiple
|
||||||
|
await helloModuleService.deleteMyCustoms([
|
||||||
|
"123", "321"
|
||||||
|
])
|
||||||
|
|
||||||
|
// use filters
|
||||||
|
await helloModuleService.deleteMyCustoms({
|
||||||
|
selector: {
|
||||||
|
id: ["123", "321"]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabsContent>
|
||||||
|
<TabsContent value="softDeleteMyCustoms">
|
||||||
|
|
||||||
|
### softDeleteMyCustoms
|
||||||
|
|
||||||
|
This method soft-deletes records using an array of IDs or an object of filters.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
await helloModuleService.softDeleteMyCustoms("123")
|
||||||
|
|
||||||
|
// soft-delete multiple
|
||||||
|
await helloModuleService.softDeleteMyCustoms([
|
||||||
|
"123", "321"
|
||||||
|
])
|
||||||
|
|
||||||
|
// use filters
|
||||||
|
await helloModuleService.softDeleteMyCustoms({
|
||||||
|
id: ["123", "321"]
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabsContent>
|
||||||
|
<TabsContent value="restoreMyCustoms">
|
||||||
|
|
||||||
|
### restoreMyCustoms
|
||||||
|
|
||||||
|
This method restores soft-deleted records using an array of IDs or an object of filters.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
await helloModuleService.restoreMyCustoms([
|
||||||
|
"123", "321"
|
||||||
|
])
|
||||||
|
|
||||||
|
// use filters
|
||||||
|
await helloModuleService.restoreMyCustoms({
|
||||||
|
id: ["123", "321"]
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabsContent>
|
||||||
|
</TabsContentWrapper>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
### Using a Constructor
|
### Using a Constructor
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export default MyCustom
|
|||||||
|
|
||||||
You define a data model using the `model`'s `define` method. It accepts two parameters:
|
You define a data model using the `model`'s `define` method. It accepts two parameters:
|
||||||
|
|
||||||
1. The first one is the name of the data model's table in the database.
|
1. The first one is the name of the data model's table in the database. It should be in snake-case form.
|
||||||
2. The second is an object, which is the data model's schema. The schema's properties are defined using the `model`'s methods.
|
2. The second is an object, which is the data model's schema. The schema's properties are defined using the `model`'s methods.
|
||||||
|
|
||||||
The example above defines the data model `MyCustom` with the properties `id` and `name`.
|
The example above defines the data model `MyCustom` with the properties `id` and `name`.
|
||||||
|
|||||||
@@ -52,7 +52,9 @@ For example, create the file `src/modules/hello/index.ts` with the following con
|
|||||||
import HelloModuleService from "./service"
|
import HelloModuleService from "./service"
|
||||||
import { Module } from "@medusajs/utils"
|
import { Module } from "@medusajs/utils"
|
||||||
|
|
||||||
export default Module("helloModuleService", {
|
export const HELLO_MODULE = "helloModuleService"
|
||||||
|
|
||||||
|
export default Module(HELLO_MODULE, {
|
||||||
service: HelloModuleService,
|
service: HelloModuleService,
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
@@ -68,18 +70,21 @@ The last step is to add the module in Medusa’s configurations.
|
|||||||
|
|
||||||
In `medusa-config.js`, add a `modules` property and pass to it your custom module:
|
In `medusa-config.js`, add a `modules` property and pass to it your custom module:
|
||||||
|
|
||||||
```js title="medusa-config.js" highlights={[["4", "helloModuleService", "The key of the main service to be registered in the Medusa container."]]}
|
```js title="medusa-config.js" highlights={[["7", "HELLO_MODULE", "The key of the main service to be registered in the Medusa container."]]}
|
||||||
|
import { HELLO_MODULE } from "./src/modules/hello"
|
||||||
|
// ...
|
||||||
|
|
||||||
module.exports = defineConfig({
|
module.exports = defineConfig({
|
||||||
// ...
|
// ...
|
||||||
modules: {
|
modules: {
|
||||||
helloModuleService: {
|
[HELLO_MODULE]: {
|
||||||
resolve: "./modules/hello",
|
resolve: "./modules/hello",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
Its key (`helloModuleService`) is the name of the module’s main service. It will be registered in the Medusa container with that name. It should also be the same name passed as the first parameter to the `Module` function in the module's definition.
|
Its key (`helloModuleService` or `HELLO_MODULE`) is the name of the module’s main service. It will be registered in the Medusa container with that name. It should also be the same name passed as the first parameter to the `Module` function in the module's definition.
|
||||||
|
|
||||||
Its value is an object having the `resolve` property, whose value is either a path to module's directory relative to `src`(it shouldn't include `src` in the path), or an `npm` package’s name.
|
Its value is an object having the `resolve` property, whose value is either a path to module's directory relative to `src`(it shouldn't include `src` in the path), or an `npm` package’s name.
|
||||||
|
|
||||||
@@ -94,13 +99,14 @@ For example, create the API route `src/api/store/custom/route.ts` with the follo
|
|||||||
```ts title="src/api/store/custom/route.ts"
|
```ts title="src/api/store/custom/route.ts"
|
||||||
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
|
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
|
||||||
import HelloModuleService from "../../../modules/hello/service"
|
import HelloModuleService from "../../../modules/hello/service"
|
||||||
|
import { HELLO_MODULE } from "../../../modules/hello"
|
||||||
|
|
||||||
export async function GET(
|
export async function GET(
|
||||||
req: MedusaRequest,
|
req: MedusaRequest,
|
||||||
res: MedusaResponse
|
res: MedusaResponse
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const helloModuleService: HelloModuleService = req.scope.resolve(
|
const helloModuleService: HelloModuleService = req.scope.resolve(
|
||||||
"helloModuleService"
|
HELLO_MODULE
|
||||||
)
|
)
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
|
|||||||
@@ -45,6 +45,19 @@ This chapter provides a cheat sheet for Medusa's resources on when to use or not
|
|||||||
|
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
|
<Table.Row>
|
||||||
|
<Table.Cell>Module Links</Table.Cell>
|
||||||
|
<Table.Cell>
|
||||||
|
|
||||||
|
- You want to create a relation between data models from different modules.
|
||||||
|
|
||||||
|
</Table.Cell>
|
||||||
|
<Table.Cell>
|
||||||
|
|
||||||
|
- You want to create a relationship between data models in the same module. Use data model relationships instead.
|
||||||
|
|
||||||
|
</Table.Cell>
|
||||||
|
</Table.Row>
|
||||||
<Table.Row>
|
<Table.Row>
|
||||||
<Table.Cell>Data Models</Table.Cell>
|
<Table.Cell>Data Models</Table.Cell>
|
||||||
<Table.Cell>
|
<Table.Cell>
|
||||||
@@ -58,6 +71,19 @@ This chapter provides a cheat sheet for Medusa's resources on when to use or not
|
|||||||
|
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
|
<Table.Row>
|
||||||
|
<Table.Cell>Data Model Relationships</Table.Cell>
|
||||||
|
<Table.Cell>
|
||||||
|
|
||||||
|
- You want to create a relation between data models in the same module.
|
||||||
|
|
||||||
|
</Table.Cell>
|
||||||
|
<Table.Cell>
|
||||||
|
|
||||||
|
- You want to create a relationship between data models in different modules. Use module links instead.
|
||||||
|
|
||||||
|
</Table.Cell>
|
||||||
|
</Table.Row>
|
||||||
<Table.Row>
|
<Table.Row>
|
||||||
<Table.Cell>Loaders</Table.Cell>
|
<Table.Cell>Loaders</Table.Cell>
|
||||||
<Table.Cell>
|
<Table.Cell>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 101 KiB |
|
After Width: | Height: | Size: 101 KiB |
|
After Width: | Height: | Size: 230 KiB |
|
After Width: | Height: | Size: 230 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 101 KiB |
|
After Width: | Height: | Size: 101 KiB |
|
After Width: | Height: | Size: 232 KiB |
|
After Width: | Height: | Size: 232 KiB |