docs: add Query documentation (#9079)

- Replace remote query documentation with new Query documentation
- Add redirect from old remote query to new query documentation
- Update remote query usages across docs to use new query usage.
This commit is contained in:
Shahed Nasser
2024-09-10 12:31:47 +00:00
committed by GitHub
parent 1d8dd54014
commit e9b5f76f9a
31 changed files with 437 additions and 635 deletions
@@ -14,17 +14,18 @@ In this document, you'll learn how to calculate a product variant's price with t
You'll need the following resources for the taxes calculation:
1. Remote query to retrieve the product's variants' prices for a context. Learn more about that in [this guide](../price/page.mdx).
1. Query to retrieve the product's variants' prices for a context. Learn more about that in [this guide](../price/page.mdx).
2. The Tax Module's main service to get the tax lines for each product.
```ts
// other imports...
import {
ModuleRegistrationName,
ContainerRegistrationKeys,
} from "@medusajs/utils"
// In an API route, workflow step, etc...
const remoteQuery = container.resolve("remoteQuery")
const query = container.resolve(ContainerRegistrationKeys.QUERY)
const taxModuleService = container.resolve(
ModuleRegistrationName.TAX
)
@@ -34,16 +35,10 @@ const taxModuleService = container.resolve(
## Step 1: Retrieve Prices for a Context
After resolving the resources, use the remote query to retrieve the products with the variants' prices for a context:
After resolving the resources, use Query to retrieve the products with the variants' prices for a context:
```ts
// other imports...
import {
remoteQueryObjectFromString,
} from "@medusajs/utils"
// ...
const query = remoteQueryObjectFromString({
const { data: products } = await query.graph({
entryPoint: "product",
fields: [
"*",
@@ -52,18 +47,16 @@ const query = remoteQueryObjectFromString({
],
variables: {
filters: {
id,
id: "prod_123",
},
"variants.calculated_price": {
context: {
region_id,
currency_code,
region_id: "region_123",
currency_code: "usd",
},
},
},
})
const products = await remoteQuery(query)
```
<Note>
@@ -3,29 +3,29 @@ sidebar_label: "Get Product Variant Prices"
---
export const metadata = {
title: `Get Product Variant Prices using Remote Query`,
title: `Get Product Variant Prices using Query`,
}
# {metadata.title}
In this document, you'll learn how to retrieve product variant prices in the Medusa application using the [remote query](!docs!/advanced-development/modules/remote-query).
In this document, you'll learn how to retrieve product variant prices in the Medusa application using the [Query](!docs!/advanced-development/modules/query).
<Note title="Why use the Remote Query?">
<Note title="Why use Query?">
The Product Module doesn't provide pricing functionalities. The Medusa application links the Product Module's `ProductVariant` data model to the Pricing Module's `PriceSet` data model.
So, to retrieve data across the linked records of the two modules, you use the remote query.
So, to retrieve data across the linked records of the two modules, you use Query.
</Note>
## Retrieve All Product Variant Prices
To retrieve all product variant prices, retrieve the product using the remote query and include among its fields `variants.prices.*`.
To retrieve all product variant prices, retrieve the product using Query and include among its fields `variants.prices.*`.
For example:
```ts highlights={[["6"]]}
const query = remoteQueryObjectFromString({
const { data: products } = await query.graph({
entryPoint: "product",
fields: [
"*",
@@ -40,9 +40,6 @@ const query = remoteQueryObjectFromString({
},
},
})
// `result` is array of products
const result = await remoteQuery(query)
```
Each variant in the retrieved products has a `prices` array property with all the product variant prices. Each price object has the properties of the [Pricing Module's Price data model](/references/pricing/models/Price).
@@ -59,7 +56,7 @@ Learn more about prices calculation in [this Pricing Module documentation](../..
</Note>
To retrieve calculated prices of variants based on a context, retrieve the products using remote query and:
To retrieve calculated prices of variants based on a context, retrieve the products using Query and:
- Pass `variants.calculated_price.*` in the `fields` property.
- Pass in the `variables` property a `variants.calculated_price` property whose value is the [calculation context object](../../../pricing/price-calculation/page.mdx#calculation-context).
@@ -67,7 +64,7 @@ To retrieve calculated prices of variants based on a context, retrieve the produ
For example:
```ts highlights={[["6"], ["12"], ["13"], ["14"], ["15"], ["16"], ["17"]]}
const query = remoteQueryObjectFromString({
const { data: products } = await query.graph({
entryPoint: "product",
fields: [
"*",
@@ -76,7 +73,7 @@ const query = remoteQueryObjectFromString({
],
variables: {
filters: {
id,
id: "prod_123",
},
"variants.calculated_price": {
context: {
@@ -86,9 +83,6 @@ const query = remoteQueryObjectFromString({
},
},
})
// `result` is array of products
const result = await remoteQuery(query)
```
The `variants.calculated_price` property of `variables` is an object that has a `context` property. `context`'s value is an object whose keys are price rules, such as `region_id`, and value is the rule's value in this context, such as the customer's region's ID.
@@ -8,6 +8,12 @@ export const metadata = {
This documentation page includes the list of resources registered in the Medusa container of your Medusa application.
<Note>
Use the `ContainerRegistrationKeys` enum imported from `@medusajs/utils` to resolve these resources' names.
</Note>
<Table>
<Table.Header>
<Table.Row>
@@ -43,7 +49,7 @@ This documentation page includes the list of resources registered in the Medusa
</Table.Cell>
<Table.Cell>
`configModule`
`configModule` or `ContainerRegistrationKeys.CONFIG_MODULE`
</Table.Cell>
</Table.Row>
@@ -61,7 +67,7 @@ This documentation page includes the list of resources registered in the Medusa
</Table.Cell>
<Table.Cell>
`logger`
`logger` or `ContainerRegistrationKeys.LOGGER`
</Table.Cell>
</Table.Row>
@@ -69,17 +75,17 @@ This documentation page includes the list of resources registered in the Medusa
<Table.Row>
<Table.Cell>
Remote Query
Query
</Table.Cell>
<Table.Cell>
The remote query function.
The Query utility methods.
</Table.Cell>
<Table.Cell>
`remoteQuery`
`query` or `ContainerRegistrationKeys.QUERY`
</Table.Cell>
</Table.Row>
@@ -97,7 +103,7 @@ This documentation page includes the list of resources registered in the Medusa
</Table.Cell>
<Table.Cell>
`remoteLink`
`remoteLink` or `ContainerRegistrationKeys.REMOTE_LINK`
</Table.Cell>
</Table.Row>
@@ -288,7 +288,7 @@ import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "@medusajs/medusa"
import { remoteQueryObjectFromString } from "@medusajs/utils"
import { ContainerRegistrationKeys } from "@medusajs/utils"
export const GET = async (
req: AuthenticatedMedusaRequest,
@@ -299,9 +299,12 @@ export const GET = async (
limit = 20,
offset = 0,
} = req.validatedQuery || {}
const remoteQuery = req.scope.resolve("remoteQuery")
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const query = remoteQueryObjectFromString({
const {
data: digitalProducts,
metadata: { count, take, skip },
} = await query.graph({
entryPoint: "digital_product",
fields: [
"*",
@@ -315,13 +318,8 @@ export const GET = async (
},
})
const {
rows,
metadata: { count, take, skip },
} = await remoteQuery(query)
res.json({
digital_products: rows,
digital_products: digitalProducts,
count,
limit: take,
offset: skip,
@@ -331,7 +329,7 @@ export const GET = async (
This adds a `GET` API route at `/admin/digital-products`.
In the route handler, you use the remote query to retrieve the list of digital products and their relations. The route handler also supports pagination.
In the route handler, you use Query to retrieve the list of digital products and their relations. The route handler also supports pagination.
### Test API Route
@@ -364,7 +362,7 @@ Make sure to replace `{token}` with the JWT token you retrieved.
### Further Reads
- [How to Create an API Route](!docs!/basics/api-routes)
- [Learn more about the remote query](!docs!/advanced-development/modules/remote-query)
- [Learn more about Query](!docs!/advanced-development/modules/query)
---
@@ -1830,7 +1828,7 @@ Create the file `digital-product/src/subscribers/handle-digital-order.ts` with t
export const subscriberHighlight = [
["20", "notificationModuleService", "Resolve the Notification Module's service to use it later to send a notification."],
["22", "fileModuleService", "Resolve the File Module's service to use it later to retrieve a media's URL."],
["26", "query", "Assemble the query to retrieve the digital product order."]
["26", "query", "Run the query to retrieve the digital product order."]
]
```ts title="digital-product/src/subscribers/handle-digital-order.ts" highlights={subscriberHighlight} collapsibleLines="1-14" expandMoreLabel="Show Imports"
@@ -1844,7 +1842,7 @@ import {
} from "@medusajs/types"
import {
ModuleRegistrationName,
remoteQueryObjectFromString,
ContainerRegistrationKeys,
} from "@medusajs/utils"
import { MediaType } from "../modules/digital-product/types"
@@ -1852,14 +1850,14 @@ async function digitalProductOrderCreatedHandler({
event: { data },
container,
}: SubscriberArgs<{ id: string }>) {
const remoteQuery = container.resolve("remoteQuery")
const query = container.resolve(ContainerRegistrationKeys.QUERY)
const notificationModuleService: INotificationModuleService = container
.resolve(ModuleRegistrationName.NOTIFICATION)
const fileModuleService: IFileModuleService = container.resolve(
ModuleRegistrationName.FILE
)
const query = remoteQueryObjectFromString({
const { data: [digitalProductOrder] } = await query.graph({
entryPoint: "digital_product_order",
fields: [
"*",
@@ -1874,8 +1872,6 @@ async function digitalProductOrderCreatedHandler({
},
})
const digitalProductOrder = (await remoteQuery(query))[0]
// TODO format and send notification
}
@@ -2031,7 +2027,7 @@ You return in the response the preview files.
Create the file `src/api/store/customers/me/digital-products/route.ts` with the following content:
export const purchasedDpHighlights = [
["15", "remoteQueryObjectFromString", "Retrieve the customer's purchased digital products."]
["15", "graph", "Retrieve the customer's purchased digital products."]
]
```ts title="src/api/store/customers/me/digital-products/route.ts" highlights={purchasedDpHighlights} collapsibleLines="1-8" expandMoreLabel="Show Imports"
@@ -2040,16 +2036,16 @@ import {
MedusaResponse,
} from "@medusajs/medusa"
import {
remoteQueryObjectFromString,
ContainerRegistrationKeys,
} from "@medusajs/utils"
export const GET = async (
req: AuthenticatedMedusaRequest,
res: MedusaResponse
) => {
const remoteQuery = req.scope.resolve("remoteQuery")
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const query = remoteQueryObjectFromString({
const { data: [customer] } = await query.graph({
entryPoint: "customer",
fields: [
"orders.digital_product_order.products.*",
@@ -2062,11 +2058,9 @@ export const GET = async (
},
})
const result = await remoteQuery(query)
const digitalProducts = {}
result[0].orders.forEach((order) => {
customer.orders.forEach((order) => {
order.digital_product_order.products.forEach((product) => {
digitalProducts[product.id] = product
})
@@ -2076,23 +2070,22 @@ export const GET = async (
digital_products: Object.values(digitalProducts),
})
}
```
This adds a `GET` API route at `/store/customers/me/digital-products`. All API routes under `/store/customers/me` require customer authentication.
In the route handler, you use remote query to retrieve the customers orders and linked digital product orders, and return the purchased digital products in the response.
In the route handler, you use Query to retrieve the customers orders and linked digital product orders, and return the purchased digital products in the response.
### Get Digital Product Media Download URL API Route
Create the file `src/api/store/customers/me/digital-products/[mediaId]/download/route.ts` with the following content:
export const downloadUrlHighlights = [
["20", "remoteQueryObjectFromString", "Get the customer's orders and linked digital orders."],
["37", "remoteQueryObjectFromString", "Get the digital product orders of the customer and associated products and media."],
["62", "foundMedia", "Set `foundMedia` if the media's ID is equal to the ID passed as a route parameter."],
["68", "!foundMedia", "If `foundMedia` isn't set, throw an error."],
["75", "retrieveFile", "Retrieve the details of the media's file."]
["20", "query.graph", "Get the customer's orders and linked digital orders."],
["36", "query.graph", "Get the digital product orders of the customer and associated products and media."],
["56", "foundMedia", "Set `foundMedia` if the media's ID is equal to the ID passed as a route parameter."],
["65", "!foundMedia", "If `foundMedia` isn't set, throw an error."],
["72", "retrieveFile", "Retrieve the details of the media's file."]
]
```ts title="src/api/store/customers/me/digital-products/[mediaId]/download/route.ts" highlights={downloadUrlHighlights} collapsibleLines="1-10" expandMoreLabel="Show Imports"
@@ -2102,7 +2095,7 @@ import {
} from "@medusajs/medusa"
import {
ModuleRegistrationName,
remoteQueryObjectFromString,
ContainerRegistrationKeys,
MedusaError,
} from "@medusajs/utils"
@@ -2113,9 +2106,9 @@ export const POST = async (
const fileModuleService = req.scope.resolve(
ModuleRegistrationName.FILE
)
const remoteQuery = req.scope.resolve("remoteQuery")
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const customerQuery = remoteQueryObjectFromString({
const { data: [customer] } = await query.graph({
entryPoint: "customer",
fields: [
"orders.digital_product_order.*",
@@ -2127,12 +2120,11 @@ export const POST = async (
},
})
const customerResult = await remoteQuery(customerQuery)
const customerDigitalOrderIds = customerResult[0].orders
const customerDigitalOrderIds = customer.orders
.filter((order) => order.digital_product_order !== undefined)
.map((order) => order.digital_product_order.id)
const dpoQuery = remoteQueryObjectFromString({
const { data: dpoResult } = await query.graph({
entryPoint: "digital_product_order",
fields: [
"products.medias.*",
@@ -2144,8 +2136,6 @@ export const POST = async (
},
})
const dpoResult = await remoteQuery(dpoQuery)
if (!dpoResult.length) {
throw new MedusaError(
MedusaError.Types.NOT_ALLOWED,
@@ -123,9 +123,9 @@ Create workflows to implement these flows, then utilize these workflows in other
## Manage Linked Records
If you've defined links between data models of two modules, you can manage them through two functions: remote link and remote query.
If you've defined links between data models of two modules, you can manage them through two functions: remote link and Query.
Use the remote link to create a link between two records, and use the remote query to fetch data across linked data models.
Use the remote link to create a link between two records, and use Query to fetch data across linked data models.
<CardList itemsPerRow={2} items={[
{
@@ -135,9 +135,9 @@ Use the remote link to create a link between two records, and use the remote que
icon: AcademicCapSolid,
},
{
href: "!docs!/advanced-development/modules/remote-query",
title: "How to Use the Remote Query",
text: "Learn how to fetch data across modules with remote query.",
href: "!docs!/advanced-development/modules/query",
title: "How to Use Query",
text: "Learn how to fetch data across modules with Medusa's Query.",
icon: AcademicCapSolid,
},
]} />
@@ -627,16 +627,16 @@ In the file `src/api/restaurants/route.ts` add the following API route:
```ts title="src/api/restaurants/route.ts"
// other imports...
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
import { remoteQueryObjectFromString } from "@medusajs/utils"
import { ContainerRegistrationKeys } from "@medusajs/utils"
// ...
export async function GET(req: MedusaRequest, res: MedusaResponse) {
const { currency_code = "eur", ...queryFilters } = req.query
const remoteQuery = req.scope.resolve("remoteQuery")
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const restaurantsQuery = remoteQueryObjectFromString({
const { data: restaurants } = await query.graph({
entryPoint: "restaurants",
fields: [
"id",
@@ -662,13 +662,11 @@ export async function GET(req: MedusaRequest, res: MedusaResponse) {
},
})
const restaurants = await remoteQuery(restaurantsQuery)
return res.status(200).json({ restaurants })
}
```
This creates a `GET` API route at `/restaurants`. It uses remote query to retrieve a restaurant, its products, and the product variants prices for a specified currency.
This creates a `GET` API route at `/restaurants`. It uses Query to retrieve a restaurant, its products, and the product variants prices for a specified currency.
### Test it Out
@@ -682,7 +680,7 @@ This returns the list of restaurants in the response.
### Further Reads
- [What is Remote Query and how to use it](!docs!/advanced-development/modules/remote-query)
- [What is and how to use it](!docs!/advanced-development/modules/query)
- [How to Retrieve Prices for Product Variants](../../../../commerce-modules/product/guides/price/page.mdx)
---
@@ -1502,14 +1500,14 @@ Create the file `src/workflows/delivery/steps/notify-restaurant.ts` with the fol
export const notifyRestaurantStepHighlights = [
["11", "async", "Set the step as async."],
["18", "deliveryQuery", "Retrieve the delivery and its restaurant."],
["32", "emit", "Emit a custom event that can be used to notify the restaurant that a new delivery is created."]
["18", "graph", "Retrieve the delivery and its restaurant."],
["30", "emit", "Emit a custom event that can be used to notify the restaurant that a new delivery is created."]
]
```ts title="src/workflows/delivery/steps/notify-restaurant.ts" highlights={notifyRestaurantStepHighlights} collapsibleLines="1-6" expandButtonLabel="Show Imports"
import {
ModuleRegistrationName,
remoteQueryObjectFromString,
ContainerRegistrationKeys,
} from "@medusajs/utils"
import { createStep } from "@medusajs/workflows-sdk"
@@ -1522,9 +1520,9 @@ export const notifyRestaurantStep = createStep(
maxRetries: 2,
},
async function (deliveryId: string, { container }) {
const remoteQuery = container.resolve("remoteQuery")
const query = container.resolve(ContainerRegistrationKeys.QUERY)
const deliveryQuery = remoteQueryObjectFromString({
const { data: [delivery] } = await query.graph({
entryPoint: "deliveries",
variables: {
filters: {
@@ -1534,8 +1532,6 @@ export const notifyRestaurantStep = createStep(
fields: ["id", "restaurant.id"],
})
const delivery = await remoteQuery(deliveryQuery).then((res) => res[0])
const eventBus = container.resolve(ModuleRegistrationName.EVENT_BUS)
await eventBus.emit({
@@ -1547,7 +1543,6 @@ export const notifyRestaurantStep = createStep(
})
}
)
```
In this step, you:
@@ -1600,7 +1595,7 @@ import { CreateOrderShippingMethodDTO } from "@medusajs/types"
import {
ModuleRegistrationName,
Modules,
remoteQueryObjectFromString,
ContainerRegistrationKeys,
} from "@medusajs/utils"
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
import { DELIVERY_MODULE } from "../../../modules/delivery"
@@ -1608,9 +1603,9 @@ import { DELIVERY_MODULE } from "../../../modules/delivery"
export const createOrderStep = createStep(
"create-order-step",
async function (deliveryId: string, { container }) {
const remoteQuery = container.resolve("remoteQuery")
const query = container.resolve(ContainerRegistrationKeys.QUERY)
const deliveryQuery = remoteQueryObjectFromString({
const { data: [delivery] } = await query.graph({
entryPoint: "deliveries",
variables: {
filters: {
@@ -1627,8 +1622,6 @@ export const createOrderStep = createStep(
],
})
const delivery = await remoteQuery(deliveryQuery).then((res) => res[0])
// TODO create order
},
async ({ orderId }, { container }) => {
@@ -2409,8 +2402,8 @@ Start by creating the file `src/api/utils/is-delivery-restaurant.ts` with the fo
export const isDeliveryRestaurantHighlights = [
["21", "restaurantAdmin", "Retrieve the logged-in restaurant admin."],
["28", "query", "Retrieve the delivery based on the ID in the path parameter."],
["42", "", "If the restaurant admin doesn't belong to the delivery's restaurant, return an unauthorized response."]
["28", "graph", "Retrieve the delivery based on the ID in the path parameter."],
["40", "", "If the restaurant admin doesn't belong to the delivery's restaurant, return an unauthorized response."]
]
```ts title="src/api/utils/is-delivery-restaurant.ts" highlights={isDeliveryRestaurantHighlights} collapsibleLines="1-10" expandButtonLabel="Show Imports"
@@ -2420,7 +2413,7 @@ import {
MedusaResponse,
} from "@medusajs/medusa"
import {
remoteQueryObjectFromString,
ContainerRegistrationKeys,
} from "@medusajs/utils"
import { RESTAURANT_MODULE } from "../../modules/restaurant"
@@ -2429,7 +2422,7 @@ export const isDeliveryRestaurant = async (
res: MedusaResponse,
next: MedusaNextFunction
) => {
const remoteQuery = req.scope.resolve("remoteQuery")
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const restaurantModuleService = req.scope.resolve(
RESTAURANT_MODULE
)
@@ -2441,7 +2434,7 @@ export const isDeliveryRestaurant = async (
}
)
const query = remoteQueryObjectFromString({
const { data: [delivery] } = await query.graph({
entryPoint: "delivery",
fields: [
"restaurant.*",
@@ -2453,9 +2446,7 @@ export const isDeliveryRestaurant = async (
},
})
const result = await remoteQuery(query)
if (result[0].restaurant.id !== restaurantAdmin.restaurant.id) {
if (delivery.restaurant.id !== restaurantAdmin.restaurant.id) {
return res.status(403).json({
message: "unauthorized",
})
@@ -563,13 +563,13 @@ To create the API route that retrieves the vendors products, create the file
export const retrieveProductHighlights = [
["16", "retrieveVendorAdmin", "Retrive the vendor admin to retrieve its vendor's ID."],
["33", "remoteQuery", "Retrieve the vendor's products using remote query."]
["23", "graph", "Retrieve the vendor's products using Query."]
]
```ts title="src/api/vendors/products/route.ts" highlights={retrieveProductHighlights}
import { AuthenticatedMedusaRequest, MedusaResponse } from "@medusajs/medusa"
import {
remoteQueryObjectFromString,
ContainerRegistrationKeys,
} from "@medusajs/utils"
import MarketplaceModuleService from "../../../modules/marketplace/service"
import { MARKETPLACE_MODULE } from "../../../modules/marketplace"
@@ -578,7 +578,7 @@ export const GET = async (
req: AuthenticatedMedusaRequest,
res: MedusaResponse
) => {
const remoteQuery = req.scope.resolve("remoteQuery")
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const marketplaceModuleService: MarketplaceModuleService =
req.scope.resolve(MARKETPLACE_MODULE)
@@ -589,7 +589,7 @@ export const GET = async (
}
)
const query = remoteQueryObjectFromString({
const { data: [vendor] } = await query.graph({
entryPoint: "vendor",
fields: ["products.*"],
variables: {
@@ -599,15 +599,13 @@ export const GET = async (
},
})
const result = await remoteQuery(query)
res.json({
products: result[0].products,
products: vendor.products,
})
}
```
This adds a `GET` API route at `/vendors/products` that, using the remote query, retrieves the list of products of the vendor and returns them in the response.
This adds a `GET` API route at `/vendors/products` that, using Query, retrieves the list of products of the vendor and returns them in the response.
To add the create product API route, add to the same file the following:
@@ -782,7 +780,7 @@ curl 'http://localhost:9000/vendors/products' \
### Further Reads
- [How to use the Remote Query](!docs!/advanced-development/modules/remote-query)
- [How to use Query](!docs!/advanced-development/modules/query)
- [How to use the Remote Link](!docs!/advanced-development/modules/remote-link)
---
@@ -817,7 +815,7 @@ import {
StepResponse,
} from "@medusajs/workflows-sdk"
import { CartDTO, CartLineItemDTO } from "@medusajs/types"
import { remoteQueryObjectFromString } from "@medusajs/utils"
import { ContainerRegistrationKeys } from "@medusajs/utils"
type StepInput = {
cart: CartDTO
@@ -826,12 +824,12 @@ type StepInput = {
const groupVendorItemsStep = createStep(
"group-vendor-items",
async ({ cart }: StepInput, { container }) => {
const remoteQuery = container.resolve("remoteQuery")
const query = container.resolve(ContainerRegistrationKeys.QUERY)
const vendorsItems: Record<string, CartLineItemDTO[]> = {}
await Promise.all(cart.items?.map(async (item) => {
const query = remoteQueryObjectFromString({
const { data: [product] } = await query.graph({
entryPoint: "product",
fields: ["vendor.*"],
variables: {
@@ -841,9 +839,7 @@ const groupVendorItemsStep = createStep(
},
})
const result = await remoteQuery(query)
const vendorId = result[0].vendor?.id
const vendorId = product.vendor?.id
if (!vendorId) {
return
@@ -1251,13 +1247,13 @@ Create the file `src/api/vendors/orders/route.ts` with the following content:
export const getOrderHighlights = [
["15", "retrieveVendorAdmin", "Retrive the vendor admin to retrieve its vendor's ID."],
["32", "remoteQuery", "Retrieve the orders of the vendor."],
["34", "getOrdersListWorkflow", "Use Medusa's workflow to retrieve the list of orders."],
["22", "graph", "Retrieve the orders of the vendor."],
["32", "getOrdersListWorkflow", "Use Medusa's workflow to retrieve the list of orders."],
]
```ts title="src/api/vendors/orders/route.ts" highlights={getOrderHighlights} collapsibleLines="1-6" expandMoreLabel="Show Imports"
import { AuthenticatedMedusaRequest, MedusaResponse } from "@medusajs/medusa"
import { remoteQueryObjectFromString } from "@medusajs/utils"
import { ContainerRegistrationKeys } from "@medusajs/utils"
import { getOrdersListWorkflow } from "@medusajs/core-flows"
import MarketplaceModuleService from "../../../modules/marketplace/service"
import { MARKETPLACE_MODULE } from "../../../modules/marketplace"
@@ -1266,7 +1262,7 @@ export const GET = async (
req: AuthenticatedMedusaRequest,
res: MedusaResponse
) => {
const remoteQuery = req.scope.resolve("remoteQuery")
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const marketplaceModuleService: MarketplaceModuleService =
req.scope.resolve(MARKETPLACE_MODULE)
@@ -1277,7 +1273,7 @@ export const GET = async (
}
)
const query = remoteQueryObjectFromString({
const { data: [vendor] } = await query.graph({
entryPoint: "vendor",
fields: ["orders.*"],
variables: {
@@ -1287,8 +1283,6 @@ export const GET = async (
},
})
const result = await remoteQuery(query)
const { result: orders } = await getOrdersListWorkflow(req.scope)
.run({
input: {
@@ -1310,7 +1304,7 @@ export const GET = async (
],
variables: {
filters: {
id: result[0].orders.map((order) => order.id),
id: vendor.orders.map((order) => order.id),
},
},
},
@@ -654,7 +654,7 @@ In this step, youll change what happens when the [Complete Cart API route](!a
Create the file `src/api/store/carts/[id]/complete/route.ts` with the following content:
export const completeCartHighlights = [
["17", "remoteQueryObjectFromString", "Retrieve the cart to retrieve the subscription details from the `metadata`."],
["17", "graph", "Retrieve the cart to retrieve the subscription details from the `metadata`."],
["31", "", "If the subscription data isn't set in the cart's `metadata`, throw an error"],
["38", "createSubscriptionWorkflow", "Execute the workflow created in the previous step."]
]
@@ -665,7 +665,7 @@ import {
MedusaResponse,
} from "@medusajs/medusa"
import {
remoteQueryObjectFromString,
ContainerRegistrationKeys,
MedusaError,
} from "@medusajs/utils"
import createSubscriptionWorkflow from "../../../../../workflows/create-subscription"
@@ -674,9 +674,9 @@ export const POST = async (
req: MedusaRequest,
res: MedusaResponse
) => {
const remoteQuery = req.scope.resolve("remoteQuery")
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const query = remoteQueryObjectFromString({
const { data: [cart] } = await query.graph({
entryPoint: "cart",
fields: [
"metadata",
@@ -688,7 +688,7 @@ export const POST = async (
},
})
const { metadata } = (await remoteQuery(query))[0]
const { metadata } = cart
if (!metadata?.subscription_interval || !metadata.subscription_period) {
throw new MedusaError(
@@ -973,7 +973,7 @@ In this step, youll add two API routes for admin users:
Create the file `src/api/admin/subscriptions/route.ts` with the following content:
export const listSubscriptionsAdminHighlight = [
["18", "remoteQueryObjectFromString", "Retrieve the subscriptions with their orders and customer."]
["21", "graph", "Retrieve the subscriptions with their orders and customer."]
]
```ts title="src/api/admin/subscriptions/route.ts" highlights={listSubscriptionsAdminHighlight}
@@ -981,20 +981,23 @@ import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "@medusajs/medusa"
import { remoteQueryObjectFromString } from "@medusajs/utils"
import { ContainerRegistrationKeys } from "@medusajs/utils"
export const GET = async (
req: AuthenticatedMedusaRequest,
res: MedusaResponse
) => {
const remoteQuery = req.scope.resolve("remoteQuery")
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const {
limit = 20,
offset = 0,
} = req.validatedQuery || {}
const query = remoteQueryObjectFromString({
const {
data: subscriptions,
metadata: { count, take, skip },
} = await query.graph({
entryPoint: "subscription",
fields: [
"*",
@@ -1011,13 +1014,8 @@ export const GET = async (
},
})
const {
rows,
metadata: { count, take, skip },
} = await remoteQuery(query)
res.json({
subscriptions: rows,
subscriptions,
count,
limit: take,
offset: skip,
@@ -1027,7 +1025,7 @@ export const GET = async (
This adds a `GET` API route at `/admin/subscriptions`.
In the route handler, you use the remote query to retrieve a subscription with its orders and customer.
In the route handler, you use Query to retrieve a subscription with its orders and customer.
The API route accepts pagination parameters to paginate the subscription list. It returns the subscriptions with pagination parameters in the response.
@@ -1036,7 +1034,7 @@ The API route accepts pagination parameters to paginate the subscription list. I
Create the file `src/api/admin/subscriptions/[id]/route.ts` with the following content:
export const getSubscriptionsAdminHighlight = [
["13", "remoteQueryObjectFromString", "Retrieve the subscription with its orders and customer."]
["13", "graph", "Retrieve the subscription with its orders and customer."]
]
```ts title="src/api/admin/subscriptions/[id]/route.ts" highlights={getSubscriptionsAdminHighlight}
@@ -1044,15 +1042,15 @@ import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "@medusajs/medusa"
import { remoteQueryObjectFromString } from "@medusajs/utils"
import { ContainerRegistrationKeys } from "@medusajs/utils"
export const GET = async (
req: AuthenticatedMedusaRequest,
res: MedusaResponse
) => {
const remoteQuery = req.scope.resolve("remoteQuery")
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const query = remoteQueryObjectFromString({
const { data: [subscription] } = await query.graph({
entryPoint: "subscription",
fields: [
"*",
@@ -1067,17 +1065,15 @@ export const GET = async (
},
})
const result = await remoteQuery(query)
res.json({
subscription: result[0],
subscription,
})
}
```
This adds a `GET` API route at `/admin/subscriptions/[id]`, where `[id]` is the ID of the subscription to retrieve.
In the route handler, you retrieve a subscription by its ID using the remote query and return it in the response.
In the route handler, you retrieve a subscription by its ID using Query and return it in the response.
In the next section, youll extend the Medusa admin and use these API routes to show the subscriptions.
@@ -2130,15 +2126,15 @@ import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "@medusajs/medusa"
import { remoteQueryObjectFromString } from "@medusajs/utils"
import { ContainerRegistrationKeys } from "@medusajs/utils"
export const GET = async (
req: AuthenticatedMedusaRequest,
res: MedusaResponse
) => {
const remoteQuery = req.scope.resolve("remoteQuery")
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const query = remoteQueryObjectFromString({
const { data: [customer] } = await query.graph({
entryPoint: "customer",
fields: [
"subscriptions.*",
@@ -2150,17 +2146,15 @@ export const GET = async (
},
})
const result = await remoteQuery(query)
res.json({
subscriptions: result[0].subscriptions,
subscriptions: customer.subscriptions,
})
}
```
This adds an API route at `/store/customers/me/subscriptions`.
In the route handler, you retrieve the authenticated customers subscriptions using the remote query and return them in the response.
In the route handler, you retrieve the authenticated customers subscriptions using Query and return them in the response.
### Cancel Subscription API Route
@@ -48,7 +48,7 @@ The method returns an array of the first `15` records matching the filters.
<Note>
This applies to relations between data models of the same module. To retrieve linked records of different modules, use [remote query](!docs!/advanced-development/modules/remote-query).
This applies to relations between data models of the same module. To retrieve linked records of different modules, use [Query](!docs!/advanced-development/modules/query).
</Note>
@@ -54,7 +54,7 @@ The method returns an array with two items:
<Note>
This applies to relations between data models of the same module. To retrieve linked records of different modules, use [remote query](!docs!/advanced-development/modules/remote-query).
This applies to relations between data models of the same module. To retrieve linked records of different modules, use [Query](!docs!/advanced-development/modules/query).
</Note>
@@ -30,7 +30,7 @@ The method returns the record as an object.
<Note>
This applies to relations between data models of the same module. To retrieve linked records of different modules, use [remote query](!docs!/advanced-development/modules/remote-query).
This applies to relations between data models of the same module. To retrieve linked records of different modules, use [Query](!docs!/advanced-development/modules/query).
</Note>