docs: improvements to module and data model documentation (#8062)
* docs: improvements to module and data model documentation * add note about data model name casing
@@ -12,6 +12,18 @@ Data model relationships are in active development and may change.
|
||||
|
||||
</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?
|
||||
|
||||
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.
|
||||
|
||||
<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
|
||||
@@ -27,10 +39,13 @@ Before you define a module link, you must enable the `isQueryable` configuration
|
||||
For example:
|
||||
|
||||
```js
|
||||
import { HELLO_MODULE } from "./src/modules/hello"
|
||||
// ...
|
||||
|
||||
module.exports = defineConfig({
|
||||
// ...
|
||||
modules: {
|
||||
helloModuleService: {
|
||||
[HELLO_MODULE]: {
|
||||
resolve: "./modules/hello",
|
||||
definition: {
|
||||
isQueryable: true,
|
||||
|
||||
@@ -23,10 +23,13 @@ To pass options to a module, add an `options` property to the module’s configu
|
||||
For example:
|
||||
|
||||
```js title="medusa-config.js"
|
||||
import { HELLO_MODULE } from "./src/modules/hello"
|
||||
// ...
|
||||
|
||||
module.exports = defineConfig({
|
||||
// ...
|
||||
modules: {
|
||||
helloModuleService: {
|
||||
[HELLO_MODULE]: {
|
||||
resolve: "./modules/hello",
|
||||
options: {
|
||||
capitalize: true,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Table } from "docs-ui"
|
||||
import { Tabs, TabsContent, TabsContentWrapper, TabsList, TabsTrigger } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
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:
|
||||
|
||||
<Table>
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell>Method</Table.HeaderCell>
|
||||
<Table.HeaderCell>Description</Table.HeaderCell>
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
<Table.Body>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
|
||||
`listMyCustoms`
|
||||
<Tabs defaultValue="listMyCustoms" layoutType="vertical" className="mt-2">
|
||||
<TabsList>
|
||||
<TabsTrigger value="listMyCustoms">listMyCustoms</TabsTrigger>
|
||||
<TabsTrigger value="listAndCountMyCustoms">listAndCountMyCustoms</TabsTrigger>
|
||||
<TabsTrigger value="retrieveMyCustom">retrieveMyCustom</TabsTrigger>
|
||||
<TabsTrigger value="createMyCustoms">createMyCustoms</TabsTrigger>
|
||||
<TabsTrigger value="updateMyCustoms">updateMyCustoms</TabsTrigger>
|
||||
<TabsTrigger value="deleteMyCustoms">deleteMyCustoms</TabsTrigger>
|
||||
<TabsTrigger value="softDeleteMyCustoms">softDeleteMyCustoms</TabsTrigger>
|
||||
<TabsTrigger value="restoreMyCustoms">restoreMyCustoms</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContentWrapper className="[&_h3]:!mt-0">
|
||||
<TabsContent value="listMyCustoms">
|
||||
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
|
||||
Retrieves an array of records based on filters and pagination configurations.
|
||||
### listMyCustoms
|
||||
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
|
||||
`listAndCountMyCustoms`
|
||||
This method retrieves an array of records based on filters and pagination configurations.
|
||||
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
|
||||
Retrieves a tuple of an array of records and the total count of available records based on the filters and pagination configurations provided.
|
||||
For example:
|
||||
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
|
||||
`retrieveMyCustom`
|
||||
```ts
|
||||
const myCustoms = await helloModuleService
|
||||
.listMyCustoms()
|
||||
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
|
||||
Retrieves a record by its ID.
|
||||
// with filters
|
||||
const myCustoms = await helloModuleService
|
||||
.listMyCustoms({
|
||||
id: ["123"]
|
||||
})
|
||||
```
|
||||
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
|
||||
`createMyCustoms`
|
||||
</TabsContent>
|
||||
<TabsContent value="listAndCountMyCustoms">
|
||||
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
|
||||
Create and retrieve records of the data model.
|
||||
### listAndCountMyCustoms
|
||||
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
|
||||
`updateMyCustoms`
|
||||
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.Cell>
|
||||
<Table.Cell>
|
||||
|
||||
Update and retrieve records of the data model.
|
||||
For example:
|
||||
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
|
||||
`deleteMyCustoms`
|
||||
```ts
|
||||
const [
|
||||
myCustoms,
|
||||
count
|
||||
] = await helloModuleService.listAndCountMyCustoms()
|
||||
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
|
||||
Deletes records by an ID or filter.
|
||||
// with filters
|
||||
const [
|
||||
myCustoms,
|
||||
count
|
||||
] = await helloModuleService.listAndCountMyCustoms({
|
||||
id: ["123"]
|
||||
})
|
||||
```
|
||||
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
|
||||
`softDeleteMyCustoms`
|
||||
</TabsContent>
|
||||
<TabsContent value="retrieveMyCustom">
|
||||
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
|
||||
Soft-deletes records using an array of IDs or an object of filters.
|
||||
### retrieveMyCustom
|
||||
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
|
||||
`restoreMyCustoms`
|
||||
This method retrieves a record by its ID.
|
||||
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
|
||||
Restores soft-deleted records using an array of IDs or an object of filters.
|
||||
For example:
|
||||
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Body>
|
||||
</Table>
|
||||
```ts
|
||||
const myCustom = await helloModuleService
|
||||
.retrieveMyCustom("123")
|
||||
```
|
||||
|
||||
<Note>
|
||||
</TabsContent>
|
||||
<TabsContent value="createMyCustoms">
|
||||
|
||||
Except for the `retrieve` method, the suffixed data model's name is plural.
|
||||
### createMyCustoms
|
||||
|
||||
</Note>
|
||||
This method creates and retrieves records of the data model.
|
||||
|
||||
For example:
|
||||
|
||||
```ts
|
||||
const myCustom = await helloModuleService
|
||||
.createMyCustoms({
|
||||
name: "test"
|
||||
})
|
||||
|
||||
// create multiple
|
||||
const myCustoms = await helloModuleService
|
||||
.createMyCustoms([
|
||||
{
|
||||
name: "test"
|
||||
},
|
||||
{
|
||||
name: "test 2"
|
||||
},
|
||||
])
|
||||
```
|
||||
|
||||
</TabsContent>
|
||||
<TabsContent value="updateMyCustoms">
|
||||
|
||||
### updateMyCustoms
|
||||
|
||||
This method updates and retrieves records of the data model.
|
||||
|
||||
For example:
|
||||
|
||||
```ts
|
||||
const myCustom = await helloModuleService
|
||||
.updateMyCustoms({
|
||||
id: "123",
|
||||
name: "test"
|
||||
})
|
||||
|
||||
// update multiple
|
||||
const myCustoms = await helloModuleService
|
||||
.updateMyCustoms([
|
||||
{
|
||||
id: "123",
|
||||
name: "test"
|
||||
},
|
||||
{
|
||||
id: "321",
|
||||
name: "test 2"
|
||||
},
|
||||
])
|
||||
|
||||
// use filters
|
||||
const myCustoms = await helloModuleService
|
||||
.updateMyCustoms([
|
||||
{
|
||||
selector: {
|
||||
id: ["123", "321"]
|
||||
},
|
||||
data: {
|
||||
name: "test"
|
||||
}
|
||||
},
|
||||
])
|
||||
```
|
||||
|
||||
</TabsContent>
|
||||
<TabsContent value="deleteMyCustoms">
|
||||
|
||||
### deleteMyCustoms
|
||||
|
||||
This method deletes records by an ID or filter.
|
||||
|
||||
For example:
|
||||
|
||||
```ts
|
||||
await helloModuleService.deleteMyCustoms("123")
|
||||
|
||||
// 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
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ export default MyCustom
|
||||
|
||||
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.
|
||||
|
||||
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 { Module } from "@medusajs/utils"
|
||||
|
||||
export default Module("helloModuleService", {
|
||||
export const HELLO_MODULE = "helloModuleService"
|
||||
|
||||
export default Module(HELLO_MODULE, {
|
||||
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:
|
||||
|
||||
```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({
|
||||
// ...
|
||||
modules: {
|
||||
helloModuleService: {
|
||||
[HELLO_MODULE]: {
|
||||
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.
|
||||
|
||||
@@ -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"
|
||||
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
|
||||
import HelloModuleService from "../../../modules/hello/service"
|
||||
import { HELLO_MODULE } from "../../../modules/hello"
|
||||
|
||||
export async function GET(
|
||||
req: MedusaRequest,
|
||||
res: MedusaResponse
|
||||
): Promise<void> {
|
||||
const helloModuleService: HelloModuleService = req.scope.resolve(
|
||||
"helloModuleService"
|
||||
HELLO_MODULE
|
||||
)
|
||||
|
||||
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.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.Cell>Data Models</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.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.Cell>Loaders</Table.Cell>
|
||||
<Table.Cell>
|
||||
|
||||
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 101 KiB |
BIN
www/apps/book/app/icon.ico
Normal file
|
After Width: | Height: | Size: 101 KiB |
BIN
www/apps/book/app/opengraph-image.jpg
Normal file
|
After Width: | Height: | Size: 230 KiB |
BIN
www/apps/book/app/twitter-image.jpg
Normal file
|
After Width: | Height: | Size: 230 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 101 KiB |
BIN
www/apps/resources/app/icon.ico
Normal file
|
After Width: | Height: | Size: 101 KiB |
BIN
www/apps/resources/app/opengraph-image.jpg
Normal file
|
After Width: | Height: | Size: 232 KiB |
BIN
www/apps/resources/app/twitter-image.jpg
Normal file
|
After Width: | Height: | Size: 232 KiB |