docs: add documentation for migration generate cli tool (#8128)

* docs: add documentation for migration generate cli tool

* changed migrations details in marketplace recipe

* added generated oas files to action

* vale + lint fixes

* don't import from src in medusa-config.js

* fix generate command in recipe

* fix module name
This commit is contained in:
Shahed Nasser authored and GitHub committed 2024-07-15 17:46:10 +02:00
1 parent 43eb38c8cb
commit a74c900ab1
19 files changed
+270 -229

No files matched your search

@@ -74,7 +74,7 @@ const orderReturn = await orderModuleService.createReturn({
items: [{
id: "orditem_123",
quantity: 1,
}]
}],
})
```
@@ -102,7 +102,7 @@ const actions = await promotionModuleService.computeActions(
items: lineItemAdjustments,
shipping_methods: shippingMethodAdjustments,
// TODO infer from cart or region
currency_code: "usd"
currency_code: "usd",
}
)
```
+44 -16
View File
@@ -8,12 +8,6 @@ export const metadata = {
The Medusa CLI tool provides commands that facilitate your development.
<Note type="soon">
Medusa's CLI tool doesn't fully support Medusa v2 yet.
</Note>
<Note type="check">
- [Node.js v16+](https://nodejs.org/en/download)
@@ -23,19 +17,14 @@ Medusa's CLI tool doesn't fully support Medusa v2 yet.
## Usage
In your Medusa application's directory, you can use the Medusa CLI tool using NPX. For example:
In your Medusa application's directory, you can use the Medusa CLI tool using NPX.
For example:
```bash
npx medusa --help
```
Alternatively, you can install the CLI tool globally:
```bash npm2yarn
npm install @medusajs/medusa-cli -g
medusa --help
```
---
## Commands
@@ -348,7 +337,7 @@ Run the latest migrations to reflect changes on the database.
npx medusa migrations run
```
### migration revert
### migrations revert
Revert the last migrations ran on one or more modules.
@@ -375,7 +364,46 @@ npx medusa migrations revert <module_names...>
</Table.Cell>
<Table.Cell>
The name of one or more module, separated by spaces. For example, `helloModuleService`.
The name of one or more module (separated by spaces) to rever their migrations. For example, `helloModuleService`.
</Table.Cell>
<Table.Cell>
Yes
</Table.Cell>
</Table.Row>
</Table.Body>
</Table>
### migrations generate
Generate a migration file for the latest changes in one or more modules.
```bash
npx medusa migrations generate <module_names...>
```
#### Arguments
<Table>
<Table.Header>
<Table.Row>
<Table.HeaderCell>Argument</Table.HeaderCell>
<Table.HeaderCell>Description</Table.HeaderCell>
<Table.HeaderCell>Required</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
<Table.Row>
<Table.Cell>
`module_names`
</Table.Cell>
<Table.Cell>
The name of one or more module (separated by spaces) to generate migrations for. For example, `helloModuleService`.
</Table.Cell>
<Table.Cell>
@@ -67,7 +67,7 @@ const Vendor = model.define("vendor", {
handle: model.text(),
name: model.text(),
logo: model.text().nullable(),
admins: model.hasMany(() => VendorAdmin)
admins: model.hasMany(() => VendorAdmin),
})
export default Vendor
@@ -89,8 +89,8 @@ const VendorAdmin = model.define("vendor_admin", {
last_name: model.text().nullable(),
email: model.text().unique(),
vendor: model.belongsTo(() => Vendor, {
mappedBy: "admins"
})
mappedBy: "admins",
}),
})
export default VendorAdmin
@@ -98,34 +98,6 @@ export default VendorAdmin
This creates a `VendorAdmin` data model, which represents an admin of a vendor.
### Generate Migrations
To create tables for the data models in the database, you need to generate migrations for them.
Create the file `src/modules/marketplace/migrations-config.ts` with the following content:
```ts
import { defineMikroOrmCliConfig } from "@medusajs/utils"
import path from "path"
import Vendor from "./models/vendor"
import VendorAdmin from "./models/vendor-admin"
export default defineMikroOrmCliConfig("marketplace", {
entities: [Vendor, VendorAdmin] as any[],
migrations: {
path: path.join(__dirname, "migrations"),
},
})
```
Then, run the following command to generate the migration:
```bash
npx cross-env MIKRO_ORM_CLI=./src/modules/marketplace/migrations-config.ts mikro-orm migration:create
```
This generates a migration in the `src/modules/marketeplace/migrations` directory.
### Create Main Module Service
Next, create the main service of the module at `src/modules/marketplace/service.ts` with the following content:
@@ -138,7 +110,7 @@ import { CreateVendorData, VendorData } from "./types"
class MarketplaceModuleService extends MedusaService({
Vendor,
VendorAdmin
VendorAdmin,
}) {
}
@@ -158,7 +130,7 @@ import MarketplaceModuleService from "./service"
export const MARKETPLACE_MODULE = "marketplaceModuleService"
export default Module(MARKETPLACE_MODULE, {
service: MarketplaceModuleService
service: MarketplaceModuleService,
})
```
@@ -167,7 +139,7 @@ export default Module(MARKETPLACE_MODULE, {
Finally, add the module to the list of modules in `medusa-config.js`:
```ts title="medusa-config.js"
import { MARKETPLACE_MODULE } from './src/modules/marketplace'
import { MARKETPLACE_MODULE } from "./src/modules/marketplace"
// ...
@@ -177,10 +149,10 @@ module.exports = defineConfig({
[MARKETPLACE_MODULE]: {
resolve: "./modules/marketplace",
definition: {
isQueryable: true
}
}
}
isQueryable: true,
},
},
},
})
```
@@ -212,7 +184,7 @@ export default defineLink(
MarketplaceModule.linkable.vendor,
{
linkable: ProductModule.linkable.product,
isList: true
isList: true,
}
)
```
@@ -230,7 +202,7 @@ export default defineLink(
MarketplaceModule.linkable.vendor,
{
linkable: OrderModule.linkable.order,
isList: true
isList: true,
}
)
```
@@ -243,9 +215,17 @@ This adds a list link between the `Vendor` and `Order` data models, indicating t
---
## Step 3: Run Migrations
## Step 3: Generate and Run Migrations
To reflect the module’s data models and the module links in the database, run the following command:
To create tables for the marketplace data models in the database, start by generating the migrations for the Marketplace Module with the following command:
```bash
npx medusa migrations generate marketplaceModuleService
```
This generates a migration in the `src/modules/marketeplace/migrations` directory.
Then, to reflect the migration and the module links in the database, run the following command:
```bash
npx medusa migrations run
@@ -372,12 +352,12 @@ export const vendorRouteSchemaHighlights = [
```ts title="src/api/vendors/route.ts" highlights={vendorRouteSchemaHighlights}
import {
AuthenticatedMedusaRequest,
MedusaResponse
MedusaResponse,
} from "@medusajs/medusa"
import { MedusaError } from "@medusajs/utils"
import { z } from "zod"
import MarketplaceModuleService from "../../modules/marketplace/service";
import createVendorAdminWorkflow from "../../workflows/marketplace/create-vendor-admin";
import MarketplaceModuleService from "../../modules/marketplace/service"
import createVendorAdminWorkflow from "../../workflows/marketplace/create-vendor-admin"
const schema = z.object({
name: z.string(),
@@ -386,8 +366,8 @@ const schema = z.object({
admin: z.object({
email: z.string(),
first_name: z.string().optional(),
last_name: z.string().optional()
}).strict()
last_name: z.string().optional(),
}).strict(),
}).strict()
type RequestBody = {
@@ -441,15 +421,15 @@ export const POST = async (
input: {
admin: {
...admin,
vendor_id: vendor[0].id
vendor_id: vendor[0].id,
},
authIdentityId: req.auth_context.auth_identity_id,
}
},
})
// retrieve vendor again with admins
vendor = await marketplaceModuleService.retrieveVendor(vendor[0].id, {
relations: ["admins"]
relations: ["admins"],
})
res.json({
@@ -482,7 +462,7 @@ export const config: MiddlewaresConfig = {
matcher: "/vendors/*",
middlewares: [
authenticate("vendor", ["session", "bearer"]),
]
],
},
],
}
@@ -571,12 +551,12 @@ export const retrieveProductHighlights = [
]
```ts title="src/api/vendors/products/route.ts" highlights={retrieveProductHighlights}
import { AuthenticatedMedusaRequest, MedusaResponse } from "@medusajs/medusa";
import { AuthenticatedMedusaRequest, MedusaResponse } from "@medusajs/medusa"
import {
remoteQueryObjectFromString,
} from "@medusajs/utils"
import MarketplaceModuleService from "../../../modules/marketplace/service";
import { MARKETPLACE_MODULE } from "../../../modules/marketplace";
import MarketplaceModuleService from "../../../modules/marketplace/service"
import { MARKETPLACE_MODULE } from "../../../modules/marketplace"
export const GET = async (
req: AuthenticatedMedusaRequest,
@@ -589,7 +569,7 @@ export const GET = async (
const vendorAdmin = await marketplaceModuleService.retrieveVendorAdmin(
req.auth_context.actor_id,
{
relations: ["vendor"]
relations: ["vendor"],
}
)
@@ -598,15 +578,15 @@ export const GET = async (
fields: ["products.*"],
variables: {
filters: {
id: [vendorAdmin.vendor.id]
}
}
id: [vendorAdmin.vendor.id],
},
},
})
const result = await remoteQuery(query)
res.json({
products: result[0].products
products: result[0].products,
})
}
```
@@ -626,11 +606,11 @@ import { createProductsWorkflow } from "@medusajs/core-flows"
import {
CreateProductWorkflowInputDTO,
IProductModuleService,
ISalesChannelModuleService
ISalesChannelModuleService,
} from "@medusajs/types"
import {
Modules,
ModuleRegistrationName
ModuleRegistrationName,
} from "@medusajs/utils"
// GET method...
@@ -655,7 +635,7 @@ export const POST = async (
const vendorAdmin = await marketplaceModuleService.retrieveVendorAdmin(
req.auth_context.actor_id,
{
relations: ["vendor"]
relations: ["vendor"],
}
)
@@ -678,19 +658,19 @@ const { result } = await createProductsWorkflow(req.scope)
input: {
products: [{
...req.body,
sales_channels: salesChannels
}]
}
sales_channels: salesChannels,
}],
},
})
// link product to vendor
await remoteLink.create({
[MARKETPLACE_MODULE]: {
vendor_id: vendorAdmin.vendor.id
vendor_id: vendorAdmin.vendor.id,
},
[Modules.PRODUCT]: {
product_id: result[0].id
}
product_id: result[0].id,
},
})
// retrieve product again
@@ -699,7 +679,7 @@ const product = await productModuleService.retrieveProduct(
)
res.json({
product
product,
})
```
@@ -727,8 +707,8 @@ export const config: MiddlewaresConfig = {
middlewares: [
authenticate("vendor", ["session", "bearer"]),
validateAndTransformBody(AdminCreateProduct),
]
}
],
},
],
}
```
@@ -823,11 +803,11 @@ const retrieveCartStep = createStep(
.resolve(ModuleRegistrationName.CART)
const cart = await cartModuleService.retrieveCart(cart_id, {
relations: ["items"]
relations: ["items"],
})
return new StepResponse({
cart
cart,
})
}
)
@@ -862,12 +842,12 @@ const createParentOrderStep = createStep(
const { result } = await completeCartWorkflow(container)
.run({
input: {
id: cart_id
}
id: cart_id,
},
})
return new StepResponse({
order: result
order: result,
})
}
)
@@ -906,9 +886,9 @@ const groupVendorItemsStep = createStep(
fields: ["vendor.*"],
variables: {
filters: {
id: [item.product_id]
}
}
id: [item.product_id],
},
},
})
const result = await remoteQuery(query)
@@ -920,12 +900,12 @@ const groupVendorItemsStep = createStep(
}
vendorsItems[vendorId] = [
...(vendorsItems[vendorId] || []),
item
item,
]
}))
return new StepResponse({
vendorsItems
vendorsItems,
})
}
)
@@ -973,7 +953,7 @@ const createVendorOrdersStep = createStep(
const vendorIds = Object.keys(vendorsItems)
if (vendorIds.length === 0) {
return new StepResponse({
orders: []
orders: [],
})
}
const remoteLink = container.resolve("remoteLink")
@@ -1005,20 +985,20 @@ if (isOnlyOneVendorOrder) {
// link the parent order to the vendor instead of creating child orders
await remoteLink.create({
[MARKETPLACE_MODULE]: {
vendor_id: vendorId
vendor_id: vendorId,
},
[Modules.ORDER]: {
order_id: parentOrder.id
}
order_id: parentOrder.id,
},
})
return new StepResponse({
orders: [
{
...parentOrder,
vendor
}
]
vendor,
},
],
})
}
@@ -1050,7 +1030,7 @@ await Promise.all(
input: {
items,
metadata: {
parent_order_id: parentOrder.id
parent_order_id: parentOrder.id,
},
// use info from parent
region_id: parentOrder.region_id,
@@ -1074,37 +1054,37 @@ await Promise.all(
rate: taxLine.rate,
provider_id: taxLine.provider_id,
tax_rate_id: taxLine.tax_rate_id,
description: taxLine.description
description: taxLine.description,
})),
adjustments: shippingMethod.adjustments.map((adjustment) => ({
code: adjustment.code,
amount: adjustment.amount,
description: adjustment.description,
promotion_id: adjustment.promotion_id,
provider_id: adjustment.provider_id
}))
provider_id: adjustment.provider_id,
})),
})),
}
},
})
await remoteLink.create({
[MARKETPLACE_MODULE]: {
vendor_id: vendorId
vendor_id: vendorId,
},
[Modules.ORDER]: {
order_id: childOrder.id
}
order_id: childOrder.id,
},
})
createdOrders.push({
...childOrder,
vendor
vendor,
})
})
)
return new StepResponse({
orders: createdOrders
orders: createdOrders,
})
```
@@ -1150,7 +1130,7 @@ const createVendorOrdersWorkflow = createWorkflow<
const { vendorsItems } = groupVendorItemsStep(
transform({
cart
cart,
},
(data) => data
)
@@ -1159,12 +1139,12 @@ const createVendorOrdersWorkflow = createWorkflow<
const { orders } = createVendorOrdersStep(
transform({
order,
vendorsItems
vendorsItems,
},
(data) => {
return {
parentOrder: data.order,
vendorsItems: data.vendorsItems
vendorsItems: data.vendorsItems,
}
}
)
@@ -1172,11 +1152,11 @@ const createVendorOrdersWorkflow = createWorkflow<
return transform({
order,
orders
orders,
},
(data) => ({
parent_order: data.order,
vendor_orders: data.orders
vendor_orders: data.orders,
})
)
}
@@ -1196,9 +1176,9 @@ Create the file `src/api/store/carts/[id]/complete/route.ts` with the following
```ts title="src/api/store/carts/[id]/complete/route.ts"
import {
AuthenticatedMedusaRequest,
MedusaResponse
} from "@medusajs/medusa";
import createVendorOrdersWorkflow from "../../../../../workflows/marketplace/create-vendor-orders";
MedusaResponse,
} from "@medusajs/medusa"
import createVendorOrdersWorkflow from "../../../../../workflows/marketplace/create-vendor-orders"
export const POST = async (
req: AuthenticatedMedusaRequest,
@@ -1209,13 +1189,13 @@ export const POST = async (
const { result } = await createVendorOrdersWorkflow(req.scope)
.run({
input: {
cart_id: cartId
}
cart_id: cartId,
},
})
res.json({
type: "order",
order: result.parent_order
order: result.parent_order,
})
}
```
@@ -1241,11 +1221,11 @@ export const getOrderHighlights = [
]
```ts title="src/api/vendors/orders/route.ts" highlights={getOrderHighlights} collapsibleLines="1-6" expandMoreLabel="Show Imports"
import { AuthenticatedMedusaRequest, MedusaResponse } from "@medusajs/medusa";
import { AuthenticatedMedusaRequest, MedusaResponse } from "@medusajs/medusa"
import { remoteQueryObjectFromString } from "@medusajs/utils"
import { getOrdersListWorkflow } from "@medusajs/core-flows"
import MarketplaceModuleService from "../../../modules/marketplace/service";
import { MARKETPLACE_MODULE } from "../../../modules/marketplace";
import MarketplaceModuleService from "../../../modules/marketplace/service"
import { MARKETPLACE_MODULE } from "../../../modules/marketplace"
export const GET = async (
req: AuthenticatedMedusaRequest,
@@ -1258,7 +1238,7 @@ export const GET = async (
const vendorAdmin = await marketplaceModuleService.retrieveVendorAdmin(
req.auth_context.actor_id,
{
relations: ["vendor"]
relations: ["vendor"],
}
)
@@ -1267,9 +1247,9 @@ export const GET = async (
fields: ["orders.*"],
variables: {
filters: {
id: [vendorAdmin.vendor.id]
}
}
id: [vendorAdmin.vendor.id],
},
},
})
const result = await remoteQuery(query)
@@ -1295,14 +1275,14 @@ export const GET = async (
],
variables: {
filters: {
id: result[0].orders.map((order) => order.id)
}
}
}
id: result[0].orders.map((order) => order.id),
},
},
},
})
res.json({
orders
orders,
})
}
```
@@ -1343,7 +1323,7 @@ export const config: MiddlewaresConfig = {
authenticate("vendor", ["session", "bearer"]),
],
},
]
],
}
```