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
2024-07-15 18:46:10 +03:00
committed by GitHub
parent 43eb38c8cb
commit a74c900ab1
19 changed files with 270 additions and 229 deletions

View File

@@ -60,6 +60,8 @@ jobs:
base: "develop"
title: "chore(docs): Updated API Reference (v2)"
labels: "type: chore"
add-paths: www/apps/api-reference/specs
add-paths: |
www/apps/api-reference/specs
www/utils/generated/oas-output
branch: "docs/generate-api-ref"
branch-suffix: "timestamp"

View File

@@ -33,10 +33,13 @@ To disable the authentication guard on custom routes under the `/admin` or `/sto
For example:
```ts title="src/api/store/customers/me/custom/route.ts" highlights={[["15"]]} apiTesting testApiUrl="http://localhost:9000/store/customers/me/custom" testApiMethod="GET"
```ts title="src/api/store/customers/me/custom/route.ts" highlights={[["12"]]} apiTesting testApiUrl="http://localhost:9000/store/customers/me/custom" testApiMethod="GET"
import type { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
export const GET = async (
req: MedusaRequest,
res: MedusaResponse
) => {
res.json({
message: "Hello",
})
@@ -55,7 +58,7 @@ You can access the logged-in customers ID in all API routes starting with `/s
For example:
```ts title="src/api/store/customers/me/custom/route.ts" highlights={[["16", "", "Access the logged-in customer's ID."]]} collapsibleLines="1-7" expandButtonLabel="Show Imports"
```ts title="src/api/store/customers/me/custom/route.ts" highlights={[["17", "req.auth_context.actor_id", "Access the logged-in customer's ID."]]} collapsibleLines="1-7" expandButtonLabel="Show Imports"
import type {
AuthenticatedMedusaRequest,
MedusaResponse,
@@ -89,7 +92,7 @@ You can access the logged-in admin users ID in all API Routes starting with `
For example:
```ts title="src/api/admin/custom/route.ts" highlights={[["16", "req.user.userId", "Access the logged-in admin user's ID."]]} collapsibleLines="1-7" expandButtonLabel="Show Imports"
```ts title="src/api/admin/custom/route.ts" highlights={[["17", "req.auth_context.actor_id", "Access the logged-in admin user's ID."]]} collapsibleLines="1-7" expandButtonLabel="Show Imports"
import type {
AuthenticatedMedusaRequest,
MedusaResponse,
@@ -125,12 +128,12 @@ For example:
export const highlights = [
[
"11",
"7",
"authenticate",
"Only authenticated admin users can access routes starting with `/custom/admin`",
],
[
"17",
"11",
"authenticate",
"Only authenticated customers can access routes starting with `/custom/customers`",
],

View File

@@ -27,14 +27,14 @@ export const belongsHighlights = [
// when creating an email
const email = await helloModuleService.createEmail({
// other properties...
user_id: "123"
user_id: "123",
})
// when updating an email
const email = await helloModuleService.updateEmail({
id: "321",
// other properties...
user_id: "123"
user_id: "123",
})
```
@@ -57,14 +57,14 @@ export const manyHighlights = [
// when creating a product
const product = await helloModuleService.createProduct({
// other properties...
order_ids: ["123", "321"]
order_ids: ["123", "321"],
})
// when updating an order
const order = await helloModuleService.updateOrder({
id: "321",
// other properties...
product_ids: ["123", "321"]
product_ids: ["123", "321"],
})
```

View File

@@ -0,0 +1,58 @@
export const metadata = {
title: `${pageNumber} Write Migration`,
}
# {metadata.title}
In this chapter, you'll learn how to create a migration and write it manually.
## What is a Migration?
A migration is a class created in a TypeScript or JavaScript file under a module's `migrations` directory. It has two methods:
- The `up` method reflects changes on the database.
- The `down` method reverts the changes made in the `up` method.
---
## How to Write a Migration?
The Medusa CLI tool provides a [migrations generate](!resources!/medusa-cli#migrations-generate) command to generate a migration for the specified modules' data models.
Alternatively, you can manually create a migration file under the `migrations` directory of your module.
For example:
```ts title="src/modules/hello/migrations/Migration20240429.ts"
import { Migration } from "@mikro-orm/migrations"
export class Migration20240702105919 extends Migration {
async up(): Promise<void> {
this.addSql("create table if not exists \"my_custom\" (\"id\" text not null, \"name\" text not null, \"created_at\" timestamptz not null default now(), \"updated_at\" timestamptz not null default now(), \"deleted_at\" timestamptz null, constraint \"my_custom_pkey\" primary key (\"id\"));")
}
async down(): Promise<void> {
this.addSql("drop table if exists \"my_custom\" cascade;")
}
}
```
The migration's file name should be of the format `Migration{YEAR}{MONTH}{DAY}.ts`. The migration class in the file extends the `Migration` class imported from `@mikro-orm/migrations`.
In the `up` and `down` method of the migration class, you use the `addSql` method provided by MikroORM's `Migration` class to run PostgreSQL syntax.
In the example above, the `up` method creates the table `my_custom`, and the `down` method drops the table if the migration is reverted.
---
## Run the Migration
To run your migration, run the following command:
```bash
npx medusa migrations run
```
This reflects the changes in the database as implemented in the migration's `up` method.

View File

@@ -111,7 +111,7 @@ import { defineLink } from "@medusajs/utils"
export default defineLink(
{
linkable: HelloModule.linkable.myCustom,
isList: true
isList: true,
},
ProductModule.linkable.product
)

View File

@@ -89,7 +89,7 @@ const query = remoteQueryObjectFromString({
fields: [
"id",
"name",
"product.*"
"product.*",
],
})
```
@@ -112,7 +112,7 @@ const query = remoteQueryObjectFromString({
fields: [
"id",
"name",
"products.*"
"products.*",
],
})
```

View File

@@ -40,10 +40,10 @@ The first step in the workflow receives the products ID and the data to updat
Create the file `src/workflows/update-product-erp/steps/update-product.ts` with the following content:
export const updateProductHighlights = [
["13", "resolve", "Resolve the `ProductService` from the Medusa container."],
["16", "previousProductData", "Retrieve the `previousProductData` to pass it to the compensation function."],
["19", "updateProducts", "Update the product."],
["39", "updateProducts", "Revert the products data using the `previousProductData` passed from the step to the compensation function."]
["10", "resolve", "Resolve the `ProductService` from the Medusa container."],
["13", "previousProductData", "Retrieve the `previousProductData` to pass it to the compensation function."],
["16", "updateProducts", "Update the product."],
["30", "updateProducts", "Revert the products data using the `previousProductData` passed from the step to the compensation function."]
]
```ts title="src/workflows/update-product-erp/steps/update-product.ts" highlights={updateProductHighlights} collapsibleLines="1-9" expandButtonLabel="Show Imports"
@@ -130,22 +130,22 @@ Create the file `src/workflows/update-product-erp/steps/update-erp.ts` with the
export const updateErpHighlights = [
[
"12",
"9",
"resolve",
"Resolve the `erpModuleService` from the Medusa container.",
],
[
"17",
"14",
"previousErpData",
"Retrieve the `previousErpData` to pass it to the compensation function.",
],
[
"21",
"16",
"updateProductErpData",
"Update the products ERP data and return the data from the ERP system.",
],
[
"37",
"31",
"updateProductErpData",
"Revert the product's data in the ERP system to its previous state using the `previousErpData`.",
],

View File

@@ -27,7 +27,7 @@ export const highlights = [
```ts highlights={highlights}
import {
createWorkflow,
when
when,
} from "@medusajs/workflows-sdk"
// step imports...

View File

@@ -127,7 +127,7 @@ const step1 = createStep(
// ...
return new StepResponse({
myMap
myMap,
})
}
)
@@ -146,7 +146,7 @@ const step1 = createStep(
// ...
return new StepResponse({
myObj
myObj,
})
}
)

View File

@@ -22,17 +22,21 @@ Similarly to your custom module, a commerce module's main service is registered
For example, you saw this code snippet in the [Medusa container chapter](../medusa-container/page.mdx):
```ts highlights={[["13"]]}
```ts highlights={[["10"]]}
import type { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
import { IProductModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/utils"
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
export const GET = async (
req: MedusaRequest,
res: MedusaResponse
) => {
const productModuleService: IProductModuleService = req.scope.resolve(
ModuleRegistrationName.PRODUCT
)
const [, count] = await productModuleService.listAndCount()
const [, count] = await productModuleService
.listAndCountProducts()
res.json({
count,

View File

@@ -17,7 +17,7 @@ A data model is a class that represents a table in the database. It's created in
<Note title="Steps Summary">
1. Create a data model in a module.
2. Create migration for the data model.
2. Generate migration for the data model.
4. Run migration to add the data model's table in the database.
</Note>
@@ -44,53 +44,21 @@ You define a data model using the `model`'s `define` method. It accepts two para
The example above defines the data model `MyCustom` with the properties `id` and `name`.
### Create a Migration
### Generate a Migration
A migration defines changes to be made in the database, such as create or update tables.
A migration is a class created in a TypeScript or JavaScript file under a module's `migrations` directory. It has two methods:
To generate a migration for the data models in your module, run the following command:
- The `up` method reflects changes on the database.
- The `down` method reverts the changes made in the `up` method.
```bash
npx medusa migrations generate helloModuleService
```
<Details summaryContent="Generate Migration">
To generate migrations:
The `migrations generate` command of the Medusa CLI accepts one or more module names (for example, `helloModuleService`) to generate the migration for.
1. Create the file `src/modules/hello/migrations-config.ts` with the following content:
The above command creates a migration file at the directory `src/modules/hello/migrations` similar to the following:
```ts
import { defineMikroOrmCliConfig } from "@medusajs/utils"
import path from "path"
import MyCustom from "./models/my-custom"
import { HELLO_MODULE } from "."
export default defineMikroOrmCliConfig(HELLO_MODULE, {
entities: [MyCustom] as any[],
migrations: {
path: path.join(__dirname, "migrations"),
},
})
```
2. Run the following command in the root directory of your Medusa application:
```bash
npx cross-env MIKRO_ORM_CLI=./src/modules/hello/migrations-config.ts mikro-orm migration:create
```
<Note title="Tip">
Add this command as a script in `package.json` for easy usage in the future. Use this command whenever you want to generate a new migration in your module.
</Note>
After running the command, a migration file is generated under the `src/modules/hello/migrations` directory.
</Details>
For example:
```ts title="src/modules/migrations/Migration20240429090012.ts"
```ts
import { Migration } from "@mikro-orm/migrations"
export class Migration20240702105919 extends Migration {
@@ -106,17 +74,11 @@ export class Migration20240702105919 extends Migration {
}
```
In the `up` method, you create the table `my_custom` and define its columns. In the `down` method, you drop the table.
<Note title="Tip">
The queries performed in each of the methods use PostgreSQL syntax.
</Note>
In the migration class, the `up` method creates the table `my_custom` and defines its columns. The `down` method drops the table.
### Run Migration
To reflect the changes in the migration, run the `migration` command:
To reflect the changes in the generated migration file, run the `migration` command:
```bash
npx medusa migrations run

View File

@@ -81,9 +81,9 @@ The subscriber function accepts an object parameter with the property `container
For example:
export const highlights = [
["10", "container", "Recieve the Medusa Container in the object parameter."],
["13", "resolve", "Resolve the Product Module's main service."],
["13", "ModuleRegistrationName.PRODUCT", "The module's registration name imported from `@medusajs/modules-sdk`."]
["7", "container", "Recieve the Medusa Container in the object parameter."],
["10", "resolve", "Resolve the Product Module's main service."],
["10", "ModuleRegistrationName.PRODUCT", "The module's registration name imported from `@medusajs/modules-sdk`."]
]
```ts title="src/subscribers/product-created.ts" highlights={highlights}

View File

@@ -15,9 +15,9 @@ You use the Medusa container to resolve resources, such as services.
For example, in a custom API route you can resolve any service registered in the Medusa application using the `scope.resolve` method of the `MedusaRequest` parameter:
export const highlights = [
["13", "resolve", "Resolve the Product Module's main service."],
["9", "resolve", "Resolve the Product Module's main service."],
[
"13",
"10",
"ModuleRegistrationName.PRODUCT",
"The resource registration name imported from `@medusajs/modules-sdk`.",
],
@@ -28,7 +28,10 @@ import type { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
import { IProductModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/utils"
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
export const GET = async (
req: MedusaRequest,
res: MedusaResponse
) => {
const productModuleService: IProductModuleService = req.scope.resolve(
ModuleRegistrationName.PRODUCT
)

View File

@@ -70,21 +70,18 @@ The last step is to add the module in Medusas configurations.
In `medusa-config.js`, add a `modules` property and pass to it your custom module:
```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"
// ...
```js title="medusa-config.js" highlights={[["4", "helloModuleService", "The key of the main service to be registered in the Medusa container."]]}
module.exports = defineConfig({
// ...
modules: {
[HELLO_MODULE]: {
"helloModuleService": {
resolve: "./modules/hello",
},
},
})
```
Its key (`helloModuleService` or `HELLO_MODULE`) is the name of the modules 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`) is the name of the modules 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` packages name.

View File

@@ -164,6 +164,10 @@ export const sidebar = sidebarAttachHrefCommonOptions(
path: "/advanced-development/data-models/searchable-property",
title: "Searchable Property",
},
{
path: "/advanced-development/data-models/write-migration",
title: "Write Migration",
},
],
},
{

View File

@@ -74,7 +74,7 @@ const orderReturn = await orderModuleService.createReturn({
items: [{
id: "orditem_123",
quantity: 1,
}]
}],
})
```

View File

@@ -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",
}
)
```

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>

View File

@@ -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 modules 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"]),
],
},
]
],
}
```