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:
@@ -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 customer’s 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 customer’s 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 variant’s 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 variant’s 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 vendor’s 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, you’ll 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, you’ll 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, you’ll 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 customer’s subscriptions using the remote query and return them in the response.
|
||||
In the route handler, you retrieve the authenticated customer’s 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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user