diff --git a/www/apps/book/app/_not-found.mdx b/www/apps/book/app/_not-found.mdx index 914b2b8541129..fa69e0b22d4d4 100644 --- a/www/apps/book/app/_not-found.mdx +++ b/www/apps/book/app/_not-found.mdx @@ -23,7 +23,7 @@ If you think this is a mistake, please [report this issue on GitHub](https://git items={[ { title: "Get Started Docs", - href: "/", + href: "/learn", icon: BookOpen }, { diff --git a/www/apps/book/app/learn/advanced-development/admin/tips/page.mdx b/www/apps/book/app/learn/advanced-development/admin/tips/page.mdx index 1975cc38aa1ca..e1bf3f817cef4 100644 --- a/www/apps/book/app/learn/advanced-development/admin/tips/page.mdx +++ b/www/apps/book/app/learn/advanced-development/admin/tips/page.mdx @@ -55,7 +55,7 @@ import { DetailWidgetProps, HttpTypes } from "@medusajs/framework/types" const ProductWidget = () => { const { data, isLoading } = useQuery({ queryFn: () => sdk.admin.product.list(), - queryKey: ["products"] + queryKey: ["products"], }) return ( @@ -95,17 +95,17 @@ import { sdk } from "../lib/config" import { DetailWidgetProps, HttpTypes } from "@medusajs/framework/types" const ProductWidget = ({ - data: productData + data: productData, }: DetailWidgetProps) => { const { mutateAsync } = useMutation({ mutationFn: (payload: HttpTypes.AdminUpdateProduct) => sdk.admin.product.update(productData.id, payload), - onSuccess: () => alert("updated product") + onSuccess: () => alert("updated product"), }) const handleUpdate = () => { mutateAsync({ - title: "New Product Title" + title: "New Product Title", }) } diff --git a/www/apps/book/app/learn/advanced-development/api-routes/parameters/page.mdx b/www/apps/book/app/learn/advanced-development/api-routes/parameters/page.mdx index 4523156ab60b2..5587d6f00a6b9 100644 --- a/www/apps/book/app/learn/advanced-development/api-routes/parameters/page.mdx +++ b/www/apps/book/app/learn/advanced-development/api-routes/parameters/page.mdx @@ -95,6 +95,12 @@ export const GET = async ( The value of `req.query.name` is the value passed in `?name=John`, for example. +### Validate Query Parameters + +You can apply validation rules on received query parameters to ensure they match specified rules and types. + +Learn more in [this documentation](../validation/page.mdx#how-to-validate-request-query-paramters). + --- ## Request Body Parameters @@ -153,3 +159,9 @@ This returns the following JSON object: "message": "[POST] Hello John!" } ``` + +### Validate Body Parameters + +You can apply validation rules on received body parameters to ensure they match specified rules and types. + +Learn more in [this documentation](../validation/page.mdx#how-to-validate-request-body). diff --git a/www/apps/book/app/learn/advanced-development/api-routes/validation/page.mdx b/www/apps/book/app/learn/advanced-development/api-routes/validation/page.mdx index 8c5669ddd756a..ad6177ef33404 100644 --- a/www/apps/book/app/learn/advanced-development/api-routes/validation/page.mdx +++ b/www/apps/book/app/learn/advanced-development/api-routes/validation/page.mdx @@ -1,24 +1,33 @@ export const metadata = { - title: `${pageNumber} Request Body Parameter Validation`, + title: `${pageNumber} Request Body and Query Parameter Validation`, } # {metadata.title} -In this chapter, you'll learn how to validate request body parameters in your custom API route. +In this chapter, you'll learn how to validate request body and query parameters in your custom API route. -## Example Scenario +## Request Validation Consider you're creating a `POST` API route at `/custom`. It accepts two parameters `a` and `b` that are required numbers, and returns their sum. -The next steps explain how to add validation to this API route, as an example. +Medusa provides two middlewares to validate the request body and query paramters of incoming requests to your custom API routes: + +- `validateAndTransformBody` to validate the request's body parameters against a schema. +- `validateAndTransformQuery` to validate the request's query parameters against a schema. + +Both middlewares accept a [Zod](https://zod.dev/) schema as a parameter, which gives you flexibility in how you define your validation schema with complex rules. + +The next steps explain how to add request body and query parameter validation to the API route mentioned earlier. --- -## Step 1: Create Zod Schema +## How to Validate Request Body -Medusa uses [Zod](https://zod.dev/) to validate the body parameters of an incoming request. +### Step 1: Create Validation Schema -To use Zod to validate your custom schemas, create a `validators.ts` file in any `src/api` subfolder. This file holds Zod schemas for each of your API routes. +Medusa uses [Zod](https://zod.dev/) to create validation schemas. These schemas are then used to validate incoming request bodies or query parameters. + +To create a validation schema with Zod, create a `validators.ts` file in any `src/api` subfolder. This file holds Zod schemas for each of your API routes. For example, create the file `src/api/custom/validators.ts` with the following content: @@ -37,11 +46,9 @@ The `PostStoreCustomSchema` variable is a Zod schema that indicates the request 2. It has a property `a` that is a required number. 3. It has a property `b` that is a required number. ---- - -## Step 2: Add Validation Middleware +### Step 2: Add Request Body Validation Middleware -To use this schema for validating the body parameters of requests to `/custom`, use the `validateAndTransformBody` middleware provided by `@medusajs/framework/utils`. It accepts the Zod schema as a parameter. +To use this schema for validating the body parameters of requests to `/custom`, use the `validateAndTransformBody` middleware provided by `@medusajs/framework/http`. It accepts the Zod schema as a parameter. For example, create the file `src/api/middlewares.ts` with the following content: @@ -49,7 +56,7 @@ For example, create the file `src/api/middlewares.ts` with the following content import { defineMiddlewares } from "@medusajs/medusa" import { validateAndTransformBody, -} from "@medusajs/framework/utils" +} from "@medusajs/framework/http" import { PostStoreCustomSchema } from "./custom/validators" export default defineMiddlewares({ @@ -67,15 +74,13 @@ export default defineMiddlewares({ This applies the `validateAndTransformBody` middleware on `POST` requests to `/custom`. It uses the `PostStoreCustomSchema` as the validation schema. -### How the Validation Works +#### How the Validation Works If a request's body parameters don't pass the validation, the `validateAndTransformBody` middleware throws an error indicating the validation errors. If a request's body parameters are validated successfully, the middleware sets the validated body parameters in the `validatedBody` property of `MedusaRequest`. ---- - -## Step 3: Use Validated Body in API Route +### Step 3: Use Validated Body in API Route In your API route, consume the validated body using the `validatedBody` property of `MedusaRequest`. @@ -113,11 +118,131 @@ To pass the request body's type as a type parameter to `MedusaRequest`, use Zod' +### Test it Out + +To test out the validation, send a `POST` request to `/custom` passing `a` and `b` body parameters. You can try sending incorrect request body parameters to test out the validation. + +For example, if you omit the `a` parameter, you'll receive a `400` response code with the following response data: + +```json +{ + "type": "invalid_data", + "message": "Invalid request: Field 'a' is required" +} +``` + --- -## Test it Out +## How to Validate Request Query Paramters + +The steps to validate the request query parameters are the similar to that of [validating the body](#how-to-validate-request-body). + +### Step 1: Create Validation Schema + +The first step is to create a schema with Zod with the rules of the accepted query parameters. + +Consider that the API route accepts two query parameters `a` and `b` that are numbers, similar to the previous section. + +Create the file `src/api/custom/validators.ts` with the following content: + +```ts title="src/api/custom/validators.ts" +import { z } from "zod" + +export const PostStoreCustomSchema = z.object({ + a: z.preprocess( + (val) => { + if (val && typeof val === "string") { + return parseInt(val) + } + return val + }, + z + .number() + ), + b: z.preprocess( + (val) => { + if (val && typeof val === "string") { + return parseInt(val) + } + return val + }, + z + .number() + ), +}) +``` + +Since a query parameter's type is originally a string or array of strings, you have to use Zod's `preprocess` method to validate other query types, such as numbers. + +For both `a` and `b`, you transform the query parameter's value to an integer first if it's a string, then, you check that the resulting value is a number. + +### Step 2: Add Request Query Validation Middleware + +Next, you'll use the schema to validate incoming requests' query parameters to the `/custom` API route. + +Add the `validateAndTransformQuery` middleware to the API route in the file `src/api/middlewares.ts`: + +```ts title="src/api/middlewares.ts" +import { defineMiddlewares } from "@medusajs/medusa" +import { + validateAndTransformQuery, +} from "@medusajs/framework/http" +import { PostStoreCustomSchema } from "./custom/validators" + +export default defineMiddlewares({ + routes: [ + { + matcher: "/custom", + method: "POST", + middlewares: [ + validateAndTransformQuery( + PostStoreCustomSchema, + {} + ), + ], + }, + ], +}) +``` + +The `validateAndTransformQuery` accepts two parameters: + +- The first one is the Zod schema to validate the query parameters against. +- The second one is an object of options for retrieving data using Query, which you can learn more about in [this chapter](../../module-links/query/page.mdx). + +#### How the Validation Works + +If a request's query parameters don't pass the validation, the `validateAndTransformQuery` middleware throws an error indicating the validation errors. + +If a request's query parameters are validated successfully, the middleware sets the validated query parameters in the `validatedQuery` property of `MedusaRequest`. + +### Step 3: Use Validated Query in API Route + +Finally, use the validated query in the API route. The `MedusaRequest` parameter has a `validatedQuery` parameter that you can use to access the validated parameters. + +For example, create the file `src/api/custom/route.ts` with the following content: + +```ts title="src/api/custom/route.ts" +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" + +export const GET = async ( + req: MedusaRequest, + res: MedusaResponse +) => { + const a = req.validatedQuery.a as number + const b = req.validatedQuery.b as number + + res.json({ + sum: a + b + }) +} +``` + +In the API route, you use the `validatedQuery` property of `MedusaRequest` to access the values of the `a` and `b` properties as numbers, then return in the response their sum. + +### Test it Out -To test out the validation, send a `POST` request to `/custom`. You can try sending incorrect request body parameters. +To test out the validation, send a `POST` request to `/custom` with `a` and `b` query parameters. You can try sending incorrect query parameters to see how the validation works. For example, if you omit the `a` parameter, you'll receive a `400` response code with the following response data: diff --git a/www/apps/book/app/learn/advanced-development/module-links/query/page.mdx b/www/apps/book/app/learn/advanced-development/module-links/query/page.mdx index cb3a50b3198e4..d1b0b542bac03 100644 --- a/www/apps/book/app/learn/advanced-development/module-links/query/page.mdx +++ b/www/apps/book/app/learn/advanced-development/module-links/query/page.mdx @@ -8,12 +8,6 @@ export const metadata = { In this chapter, you’ll learn about the Query utility and how to use it to fetch data from modules. - - -Query is in development and is subject to change in future releases. - - - ## What is Query? Query fetches data across modules. It’s a set of methods registered in the Medusa container under the `query` key. @@ -227,3 +221,126 @@ When you provide the pagination fields, the `query.graph` method's returned obje description: "The total number of records." } ]} sectionTitle="Apply Pagination" /> + +--- + +## Request Query Configurations + +For API routes that retrieve a single or list of resources, Medusa provides a `validateAndTransformQuery` middleware that: + +- Validates accepted query parameters, as explained in [this documentation](../../api-routes/validation/page.mdx). +- Parses configurations that are received as query parameters to be passed to Query. + +Using this middleware allows you to have default configurations for retrieved fields and relations or pagination, while allowing clients to customize them per request. + +### Step 1: Add Middleware + +The first step is to use the `validateAndTransformQuery` middleware on the `GET` route. You add the middleware in `src/api/middlewares.ts`: + +```ts title="src/api/middlewares.ts" +import { defineMiddlewares } from "@medusajs/medusa" +import { + validateAndTransformQuery, +} from "@medusajs/framework/http" +import { createFindParams } from "@medusajs/medusa/api/utils/validators" + +export const GetCustomSchema = createFindParams() + +export default defineMiddlewares({ + routes: [ + { + matcher: "/customs", + method: "GET", + middlewares: [ + validateAndTransformQuery( + GetCustomSchema, + { + defaults: [ + "id", + "name", + "products.*" + ], + isList: true + } + ), + ], + }, + ], +}) +``` + +The `validateAndTransformQuery` accepts two parameters: + +1. A Zod validation schema for the query parameters, which you can learn more about in the [API Route Validation documentation](../../api-routes/validation/page.mdx). Medusa has a `createFindParams` utility that generates a Zod schema that accepts four query parameters: + 1. `fields`: The fields and relations to retrieve in the returned resources. + 2. `offset`: The number of items to skip before retrieving the returned items. + 3. `limit`: The maximum number of items to return. + 4. `order`: The fields to order the returned items by in ascending or descending order. +2. A Query configuration object. It accepts the following properties: + 1. `defaults`: An array of default fields and relations to retrieve in each resource. + 2. `isList`: A boolean indicating whether a list of items are returned in the response. + 3. `allowed`: An array of fields and relations allowed to be passed in the `fields` query parameter. + 4. `defaultLimit`: A number indicating the default limit to use if no limit is provided. By default, it's `50`. + +### Step 2: Use Configurations in API Route + +After applying this middleware, your API route now accepts the `fields`, `offset`, `limit`, and `order` query parameters mentioned above. + +The middleware transforms these parameters to configurations that you can pass to Query in your API route handler. These configurations are stored in the `remoteQueryConfig` parameter of the `MedusaRequest` object. + +For example, Create the file `src/api/customs/route.ts` with the following content: + +export const queryConfigHighlights = [ + ["17", "req.remoteQueryConfig", "Pass the parsed request Query configurations to the Query graph execution."] +] + +```ts title="src/api/customs/route.ts" +import { + MedusaRequest, + MedusaResponse, +} from "@medusajs/framework/http" +import { + ContainerRegistrationKeys, +} from "@medusajs/framework/utils" + +export const GET = async ( + req: MedusaRequest, + res: MedusaResponse +) => { + const query = req.scope.resolve(ContainerRegistrationKeys.QUERY) + + const { data: myCustoms } = await query.graph({ + entity: "my_custom", + ...req.remoteQueryConfig + }) + + res.json({ my_customs: myCustoms }) +} +``` + +This adds a `GET` API route at `/customs`, which is the API route you added the middleware for. + +In the API route, you pass `req.remoteQueryConfig` to `query.graph`. `remoteQueryConfig` has properties like `fields` and `pagination` to configure the query based on the default values you specified in the middleware, and the query parameters passed in the request. + +### Test it Out + +To test it out, start your Medusa application and send a `GET` request to the `/customs` API route. A list of records are retrieved with the specified fields in the middleware. + +```json title="Returned Data" +{ + "my_customs": [ + { + "id": "123", + "name": "test" + } + ] +} +``` + +Try passing one of the Query configuration parameters, like `fields` or `limit`, and you'll see its impact on the returned result. + + + +Learn more about [specifing fields and relations](!api!/store#select-fields-and-relations) and [pagination](!api!/store#pagination) in the API reference. + + diff --git a/www/apps/book/app/learn/advanced-development/modules/container/page.mdx b/www/apps/book/app/learn/advanced-development/modules/container/page.mdx index 18cd48805bcab..b0d6cd6628b4c 100644 --- a/www/apps/book/app/learn/advanced-development/modules/container/page.mdx +++ b/www/apps/book/app/learn/advanced-development/modules/container/page.mdx @@ -57,7 +57,7 @@ import { LoaderOptions, } from "@medusajs/framework/types" import { - ContainerRegistrationKeys + ContainerRegistrationKeys, } from "@medusajs/framework/utils" export default async function helloWorldLoader({ diff --git a/www/apps/book/app/learn/advanced-development/modules/options/page.mdx b/www/apps/book/app/learn/advanced-development/modules/options/page.mdx index d6bd8cae47efb..7635e9095b336 100644 --- a/www/apps/book/app/learn/advanced-development/modules/options/page.mdx +++ b/www/apps/book/app/learn/advanced-development/modules/options/page.mdx @@ -30,7 +30,7 @@ module.exports = defineConfig({ capitalize: true, }, }, - ] + ], }) ``` diff --git a/www/apps/book/app/learn/advanced-development/modules/service-constraints/page.mdx b/www/apps/book/app/learn/advanced-development/modules/service-constraints/page.mdx index 30e6ad83eeb48..6420aa7098e0b 100644 --- a/www/apps/book/app/learn/advanced-development/modules/service-constraints/page.mdx +++ b/www/apps/book/app/learn/advanced-development/modules/service-constraints/page.mdx @@ -10,7 +10,7 @@ This chapter lists constraints to keep in mind when creating a service. Medusa wraps service method executions to inject useful context or transactions. However, since Medusa can't detect whether the method is asynchronous, it always executes methods in the wrapper with the `await` keyword. -For example, if you have a synchronous `getMessage` method, and you use it other resources like workflows, Medusa executes it as an async method: +For example, if you have a synchronous `getMessage` method, and you use it in other resources like workflows, Medusa executes it as an async method: ```ts await helloModuleService.getMessage() diff --git a/www/apps/book/app/learn/advanced-development/workflows/constructor-constraints/page.mdx b/www/apps/book/app/learn/advanced-development/workflows/constructor-constraints/page.mdx index d1136dceaa4b1..6223860ebacb9 100644 --- a/www/apps/book/app/learn/advanced-development/workflows/constructor-constraints/page.mdx +++ b/www/apps/book/app/learn/advanced-development/workflows/constructor-constraints/page.mdx @@ -145,7 +145,7 @@ const myWorkflow = createWorkflow( function (input: WorkflowInput) { const message = transform( { - input + input, }, (data) => data.input.message || "hello" ) diff --git a/www/apps/book/app/learn/advanced-development/workflows/multiple-step-usage/page.mdx b/www/apps/book/app/learn/advanced-development/workflows/multiple-step-usage/page.mdx new file mode 100644 index 0000000000000..91db3d58c3de5 --- /dev/null +++ b/www/apps/book/app/learn/advanced-development/workflows/multiple-step-usage/page.mdx @@ -0,0 +1,80 @@ +export const metadata = { + title: `${pageNumber} Multiple Step Usage in Workflow`, +} + +# {metadata.title} + +In this chapter, you'll learn how to use a step multiple times in a workflow. + +## Problem Reusing a Step in a Workflow + +In some cases, you may need to use a step multiple times in the same workflow. + +The most common example is using the `useQueryGraphStep` multiple times in a workflow to retrieve multiple unrelated data, such as customers and products. + +Each workflow step must have a unique ID, which is the ID passed as a first parameter when creating the step: + +```ts +const useQueryGraphStep = createStep( + "use-query-graph", + // ... +) +``` + +This causes an error when you use the same step multiple times in a workflow, as it's registered in the workflow as two steps having the same ID: + +```ts +const helloWorkflow = createWorkflow( + "hello", + () => { + const { data: products } = useQueryGraphStep({ + entity: "product", + fields: ["id"] + }) + + // ERROR OCCURS HERE: A STEP HAS THE SAME ID AS ANOTHER IN THE WORKFLOW + const { data: customers } = useQueryGraphStep({ + entity: "customer", + fields: ["id"] + }) + } +) +``` + +The next section explains how to fix this issue to use the same step multiple times in a workflow. + +--- + +## How to Use a Step Multiple Times in a Workflow? + +When you execute a step in a workflow, you can chain a `config` method to it to change the step's config. + +Use the `config` method to change a step's ID for a single execution. + +So, this is the correct way to write the example above: + +export const highlights = [ + ["13", "name", "Change the step's ID for this execution."] +] + +```ts highlights={highlights} +const helloWorkflow = createWorkflow( + "hello", + () => { + const { data: products } = useQueryGraphStep({ + entity: "product", + fields: ["id"] + }) + + // ✓ No error occurs, the step has a different ID. + const { data: customers } = useQueryGraphStep({ + entity: "customer", + fields: ["id"] + }).config({ name: "fetch-customers" }) + } +) +``` + +The `config` method accepts an object with a `name` property. Its value is a new ID of the step to use for this execution only. + +The first `useQueryGraphStep` usage has the ID `use-query-graph`, and the second `useQueryGraphStep` usage has the ID `fetch-customers`. diff --git a/www/apps/book/app/learn/advanced-development/workflows/variable-manipulation/page.mdx b/www/apps/book/app/learn/advanced-development/workflows/variable-manipulation/page.mdx index e3f84a2a5c780..42a41ce84cafc 100644 --- a/www/apps/book/app/learn/advanced-development/workflows/variable-manipulation/page.mdx +++ b/www/apps/book/app/learn/advanced-development/workflows/variable-manipulation/page.mdx @@ -179,7 +179,7 @@ const myWorkflow = createWorkflow( "hello-world", function (input) { validateHasStr1({ - input + input, }) // workflow continues its execution only if diff --git a/www/apps/book/app/learn/basics/modules/page.mdx b/www/apps/book/app/learn/basics/modules/page.mdx index ccefdce4436be..aca04b00bbad5 100644 --- a/www/apps/book/app/learn/basics/modules/page.mdx +++ b/www/apps/book/app/learn/basics/modules/page.mdx @@ -135,8 +135,8 @@ module.exports = defineConfig({ modules: [ { resolve: "./src/modules/hello", - } - ] + }, + ], }) ``` @@ -212,11 +212,11 @@ export async function GET( ) const my_custom = await helloModuleService.createMyCustoms({ - name: "test" + name: "test", }) res.json({ - my_custom + my_custom, }) } ``` diff --git a/www/apps/book/app/learn/customization/custom-features/api-route/page.mdx b/www/apps/book/app/learn/customization/custom-features/api-route/page.mdx index 34c1d5869ec7d..462629566288d 100644 --- a/www/apps/book/app/learn/customization/custom-features/api-route/page.mdx +++ b/www/apps/book/app/learn/customization/custom-features/api-route/page.mdx @@ -16,7 +16,7 @@ This chapter covers how to define an API route that creates a brand as the last items={[ { text: "createBrandWorkflow", - link: "/customization/custom-features/workflow" + link: "/learn/customization/custom-features/workflow" } ]} /> diff --git a/www/apps/book/app/learn/customization/custom-features/module/page.mdx b/www/apps/book/app/learn/customization/custom-features/module/page.mdx index 9dc8ac4f2d3f4..eacdc739fd4d0 100644 --- a/www/apps/book/app/learn/customization/custom-features/module/page.mdx +++ b/www/apps/book/app/learn/customization/custom-features/module/page.mdx @@ -105,8 +105,8 @@ module.exports = defineConfig({ modules: [ { resolve: "./src/modules/brand", - } - ] + }, + ], }) ``` diff --git a/www/apps/book/app/learn/customization/custom-features/workflow/page.mdx b/www/apps/book/app/learn/customization/custom-features/workflow/page.mdx index cd283ecdfdb25..ab66d555f30e4 100644 --- a/www/apps/book/app/learn/customization/custom-features/workflow/page.mdx +++ b/www/apps/book/app/learn/customization/custom-features/workflow/page.mdx @@ -34,7 +34,7 @@ This is even more useful when you create workflows with many steps, or integrate items={[ { text: "Brand Module", - link: "/customization/custom-features/module" + link: "/learn/customization/custom-features/module" } ]} /> diff --git a/www/apps/book/app/learn/customization/customize-admin/route/page.mdx b/www/apps/book/app/learn/customization/customize-admin/route/page.mdx index 01ddb07221212..049cb0b6edb96 100644 --- a/www/apps/book/app/learn/customization/customize-admin/route/page.mdx +++ b/www/apps/book/app/learn/customization/customize-admin/route/page.mdx @@ -26,7 +26,7 @@ The UI Route can be shown in the sidebar or added as a nested page. items={[ { text: "Brand Module", - link: "/customization/custom-features/module" + link: "/learn/customization/custom-features/module" }, ]} /> diff --git a/www/apps/book/app/learn/customization/customize-admin/widget/page.mdx b/www/apps/book/app/learn/customization/customize-admin/widget/page.mdx index e4b4cea99d4b2..df354ac619488 100644 --- a/www/apps/book/app/learn/customization/customize-admin/widget/page.mdx +++ b/www/apps/book/app/learn/customization/customize-admin/widget/page.mdx @@ -18,7 +18,7 @@ This chapter covers how to show the brand of a product in the Medusa Admin using items={[ { text: "Retrieve Brand of Product API Route", - link: "/customization/extend-models/query-linked-records" + link: "/learn/customization/extend-models/query-linked-records" } ]} /> diff --git a/www/apps/book/app/learn/customization/extend-models/define-link/page.mdx b/www/apps/book/app/learn/customization/extend-models/define-link/page.mdx index 0891dbfc979df..ebc1c22600a28 100644 --- a/www/apps/book/app/learn/customization/extend-models/define-link/page.mdx +++ b/www/apps/book/app/learn/customization/extend-models/define-link/page.mdx @@ -18,7 +18,7 @@ This chapter covers how to define a link between the `Brand` and `Product`data m items={[ { text: "Brand Module having a Brand data model", - link: "/customization/custom-features/module" + link: "/learn/customization/custom-features/module" } ]} /> diff --git a/www/apps/book/app/learn/customization/extend-models/extend-create-product/page.mdx b/www/apps/book/app/learn/customization/extend-models/extend-create-product/page.mdx index 962e8fdbc243c..17c0f3e165ef9 100644 --- a/www/apps/book/app/learn/customization/extend-models/extend-create-product/page.mdx +++ b/www/apps/book/app/learn/customization/extend-models/extend-create-product/page.mdx @@ -26,11 +26,11 @@ It's useful when you want to pass custom data, such as the brand ID, then perfor items={[ { text: "Brand Module", - link: "/customization/custom-features/module" + link: "/learn/customization/custom-features/module" }, { text: "Defined link between the Brand and Product data models.", - link: "/customization/extend-models/define-link" + link: "/learn/customization/extend-models/define-link" } ]} /> diff --git a/www/apps/book/app/learn/customization/extend-models/query-linked-records/page.mdx b/www/apps/book/app/learn/customization/extend-models/query-linked-records/page.mdx index 6a56da474f318..3a4ba06e02440 100644 --- a/www/apps/book/app/learn/customization/extend-models/query-linked-records/page.mdx +++ b/www/apps/book/app/learn/customization/extend-models/query-linked-records/page.mdx @@ -24,11 +24,11 @@ Query is a utility that retrieves data across modules and their links. It’s re items={[ { text: "Brand Module", - link: "/customization/custom-features/module" + link: "/learn/customization/custom-features/module" }, { text: "Defined link between the Brand and Product data models.", - link: "/customization/extend-models/define-link" + link: "/learn/customization/extend-models/define-link" } ]} /> diff --git a/www/apps/book/app/learn/customization/integrate-systems/handle-event/page.mdx b/www/apps/book/app/learn/customization/integrate-systems/handle-event/page.mdx index 3d72c3e258565..d0cad26da6354 100644 --- a/www/apps/book/app/learn/customization/integrate-systems/handle-event/page.mdx +++ b/www/apps/book/app/learn/customization/integrate-systems/handle-event/page.mdx @@ -18,7 +18,7 @@ This chapter covers how to emit an event when a brand is created, listen to that items={[ { text: "Brand Module with createBrandWorkflow", - link: "/customization/custom-features/workflow" + link: "/learn/customization/custom-features/workflow" } ]} /> diff --git a/www/apps/book/app/learn/customization/integrate-systems/schedule-task/page.mdx b/www/apps/book/app/learn/customization/integrate-systems/schedule-task/page.mdx index 375c1b3a00484..58f70e5251bd4 100644 --- a/www/apps/book/app/learn/customization/integrate-systems/schedule-task/page.mdx +++ b/www/apps/book/app/learn/customization/integrate-systems/schedule-task/page.mdx @@ -18,7 +18,7 @@ This chapter covers how to use workflows and scheduled jobs to sync brands from items={[ { text: "Brand Module", - link: "/customization/custom-features/module" + link: "/learn/customization/custom-features/module" }, ]} /> diff --git a/www/apps/book/app/learn/customization/integrate-systems/service/page.mdx b/www/apps/book/app/learn/customization/integrate-systems/service/page.mdx index cd79fa6c9d83f..82b96e44a10d7 100644 --- a/www/apps/book/app/learn/customization/integrate-systems/service/page.mdx +++ b/www/apps/book/app/learn/customization/integrate-systems/service/page.mdx @@ -18,7 +18,7 @@ This chapter covers how to integrate a dummy third-party system in a service as items={[ { text: "Brand Module", - link: "/customization/custom-features/module" + link: "/learn/customization/custom-features/module" } ]} /> @@ -192,7 +192,7 @@ module.exports = defineConfig({ apiKey: process.env.BRAND_API_KEY || "temp", }, }, - ] + ], }) ``` diff --git a/www/apps/book/app/learn/debugging-and-testing/testing-tools/integration-tests/api-routes/page.mdx b/www/apps/book/app/learn/debugging-and-testing/testing-tools/integration-tests/api-routes/page.mdx index 80fc794f04ca7..57f728efda905 100644 --- a/www/apps/book/app/learn/debugging-and-testing/testing-tools/integration-tests/api-routes/page.mdx +++ b/www/apps/book/app/learn/debugging-and-testing/testing-tools/integration-tests/api-routes/page.mdx @@ -12,7 +12,7 @@ In this chapter, you'll learn how to write integration tests for API routes usin items={[ { text: "Testing Tools Setup", - link: "/debugging-and-testing/testing-tools" + link: "/learn/debugging-and-testing/testing-tools" } ]} /> @@ -60,6 +60,8 @@ medusaIntegrationTestRunner({ }) }, }) + +jest.setTimeout(60 * 1000) ``` You use the `medusaIntegrationTestRunner` to write your tests. @@ -86,6 +88,15 @@ If you don't have a `test:integration` script in `package.json`, refer to the [M This runs your Medusa application and runs the tests available under the `src/integrations/http` directory. +### Jest Timeout + +Since your tests connect to the database and perform actions that require more time than the typical tests, make sure to increase the timeout in your test: + +```ts title="integration-tests/http/custom-routes.spec.ts" +// in your test's file +jest.setTimeout(60 * 1000) +``` + --- ## Test a POST API Route diff --git a/www/apps/book/app/learn/debugging-and-testing/testing-tools/integration-tests/page.mdx b/www/apps/book/app/learn/debugging-and-testing/testing-tools/integration-tests/page.mdx index 4a4d5330f6785..c8b0dfe5cd633 100644 --- a/www/apps/book/app/learn/debugging-and-testing/testing-tools/integration-tests/page.mdx +++ b/www/apps/book/app/learn/debugging-and-testing/testing-tools/integration-tests/page.mdx @@ -36,6 +36,8 @@ medusaIntegrationTestRunner({ // TODO write tests... }, }) + +jest.setTimeout(60 * 1000) ``` The `medusaIntegrationTestRunner` function accepts an object as a parameter. The object has a required property `testSuite`. @@ -50,6 +52,15 @@ The `medusaIntegrationTestRunner` function accepts an object as a parameter. The The tests in the `testSuite` function are written using [Jest](https://jestjs.io/). +### Jest Timeout + +Since your tests connect to the database and perform actions that require more time than the typical tests, make sure to increase the timeout in your test: + +```ts title="integration-tests/http/test.spec.ts" +// in your test's file +jest.setTimeout(60 * 1000) +``` + --- ### Run Tests diff --git a/www/apps/book/app/learn/debugging-and-testing/testing-tools/integration-tests/workflows/page.mdx b/www/apps/book/app/learn/debugging-and-testing/testing-tools/integration-tests/workflows/page.mdx index 0aec5b27c1565..d5cf5bb91b6e6 100644 --- a/www/apps/book/app/learn/debugging-and-testing/testing-tools/integration-tests/workflows/page.mdx +++ b/www/apps/book/app/learn/debugging-and-testing/testing-tools/integration-tests/workflows/page.mdx @@ -12,7 +12,7 @@ In this chapter, you'll learn how to write integration tests for workflows using items={[ { text: "Testing Tools Setup", - link: "/debugging-and-testing/testing-tools" + link: "/learn/debugging-and-testing/testing-tools" } ]} /> @@ -61,10 +61,21 @@ medusaIntegrationTestRunner({ }) }, }) + +jest.setTimeout(60 * 1000) ``` You use the `medusaIntegrationTestRunner` to write an integration test for the workflow. The test pases if the workflow returns the string `"Hello, World!"`. +### Jest Timeout + +Since your tests connect to the database and perform actions that require more time than the typical tests, make sure to increase the timeout in your test: + +```ts title="integration-tests/http/custom-routes.spec.ts" +// in your test's file +jest.setTimeout(60 * 1000) +``` + --- ## Run Test diff --git a/www/apps/book/app/learn/debugging-and-testing/testing-tools/modules-tests/module-example/page.mdx b/www/apps/book/app/learn/debugging-and-testing/testing-tools/modules-tests/module-example/page.mdx index e88c4811c07a0..c104862d8f516 100644 --- a/www/apps/book/app/learn/debugging-and-testing/testing-tools/modules-tests/module-example/page.mdx +++ b/www/apps/book/app/learn/debugging-and-testing/testing-tools/modules-tests/module-example/page.mdx @@ -12,7 +12,7 @@ In this chapter, find an example of writing an integration test for a module usi items={[ { text: "Testing Tools Setup", - link: "/debugging-and-testing/testing-tools" + link: "/learn/debugging-and-testing/testing-tools" } ]} /> diff --git a/www/apps/book/app/learn/debugging-and-testing/testing-tools/modules-tests/page.mdx b/www/apps/book/app/learn/debugging-and-testing/testing-tools/modules-tests/page.mdx index c0229a41b39a0..b265527cca561 100644 --- a/www/apps/book/app/learn/debugging-and-testing/testing-tools/modules-tests/page.mdx +++ b/www/apps/book/app/learn/debugging-and-testing/testing-tools/modules-tests/page.mdx @@ -12,7 +12,7 @@ In this chapter, you'll learn about the `moduleIntegrationTestRunner` utility fu items={[ { text: "Testing Tools Setup", - link: "/debugging-and-testing/testing-tools" + link: "/learn/debugging-and-testing/testing-tools" } ]} /> diff --git a/www/apps/book/app/learn/installation/page.mdx b/www/apps/book/app/learn/installation/page.mdx index afde8da56d4a1..e64287b8627a2 100644 --- a/www/apps/book/app/learn/installation/page.mdx +++ b/www/apps/book/app/learn/installation/page.mdx @@ -109,7 +109,7 @@ You can then use the user's credentials to log into the Medusa Admin application By default, your Medusa application is equipped with the basic configuration to start your development. -If you run into issues with configurations, such as CORS configurations, or need to make changes to the default configuration, refer to [this guide on all available configurations](!resources!/medusa-config). +If you run into issues with configurations, such as CORS configurations, or need to make changes to the default configuration, refer to [this guide on all available configurations](!resources!/references/medusa-config). --- diff --git a/www/apps/book/generated/edit-dates.mjs b/www/apps/book/generated/edit-dates.mjs index 1fb70dd2e8b3c..27eef72c0741e 100644 --- a/www/apps/book/generated/edit-dates.mjs +++ b/www/apps/book/generated/edit-dates.mjs @@ -52,7 +52,7 @@ export const generatedEditDates = { "app/learn/advanced-development/modules/module-links/page.mdx": "2024-09-30T08:43:53.126Z", "app/learn/advanced-development/data-models/searchable-property/page.mdx": "2024-09-30T08:43:53.125Z", "app/learn/advanced-development/scheduled-jobs/execution-number/page.mdx": "2024-07-02T09:41:15+00:00", - "app/learn/advanced-development/api-routes/parameters/page.mdx": "2024-09-11T10:44:13.491Z", + "app/learn/advanced-development/api-routes/parameters/page.mdx": "2024-11-12T13:35:09.393Z", "app/learn/advanced-development/api-routes/http-methods/page.mdx": "2024-09-11T10:43:33.169Z", "app/learn/advanced-development/admin/tips/page.mdx": "2024-10-07T12:50:36.335Z", "app/learn/advanced-development/api-routes/cors/page.mdx": "2024-09-30T08:43:53.121Z", @@ -72,7 +72,7 @@ export const generatedEditDates = { "app/learn/advanced-development/modules/service-constraints/page.mdx": "2024-09-30T08:43:53.127Z", "app/learn/advanced-development/api-routes/page.mdx": "2024-09-04T09:36:33.961Z", "app/learn/advanced-development/api-routes/responses/page.mdx": "2024-09-11T10:44:37.016Z", - "app/learn/advanced-development/api-routes/validation/page.mdx": "2024-09-11T10:46:31.476Z", + "app/learn/advanced-development/api-routes/validation/page.mdx": "2024-11-12T13:32:32.484Z", "app/learn/advanced-development/api-routes/errors/page.mdx": "2024-09-30T08:43:53.121Z", "app/learn/advanced-development/admin/constraints/page.mdx": "2024-09-10T11:39:51.165Z", "app/learn/debugging-and-testing/testing-tools/modules-tests/module-example/page.mdx": "2024-10-16T08:50:03.061Z", @@ -80,7 +80,7 @@ export const generatedEditDates = { "app/learn/advanced-development/module-links/custom-columns/page.mdx": "2024-09-16T15:51:33.570Z", "app/learn/advanced-development/module-links/directions/page.mdx": "2024-09-16T15:37:51.441Z", "app/learn/advanced-development/module-links/page.mdx": "2024-09-16T15:36:48.190Z", - "app/learn/advanced-development/module-links/query/page.mdx": "2024-09-16T12:42:27.579Z", + "app/learn/advanced-development/module-links/query/page.mdx": "2024-11-12T15:40:24.411Z", "app/learn/advanced-development/module-links/remote-link/page.mdx": "2024-09-16T12:42:27.581Z", "app/learn/advanced-development/modules/db-operations/page.mdx": "2024-09-16T14:38:29.150Z", "app/learn/advanced-development/modules/multiple-services/page.mdx": "2024-09-16T14:41:32.975Z", @@ -113,5 +113,6 @@ export const generatedEditDates = { "app/learn/advanced-development/data-models/infer-type/page.mdx": "2024-09-30T08:43:53.123Z", "app/learn/advanced-development/custom-cli-scripts/seed-data/page.mdx": "2024-10-03T11:11:07.181Z", "app/learn/basics/modules/page.mdx": "2024-10-16T08:49:39.997Z", - "app/learn/advanced-development/environment-variables/page.mdx": "2024-10-25T14:59:07.831Z" + "app/learn/advanced-development/environment-variables/page.mdx": "2024-10-25T14:59:07.831Z", + "app/learn/advanced-development/workflows/multiple-step-usage/page.mdx": "2024-11-12T11:11:49.191Z" } \ No newline at end of file diff --git a/www/apps/book/sidebar.mjs b/www/apps/book/sidebar.mjs index 757ff0328313f..c779323590a1c 100644 --- a/www/apps/book/sidebar.mjs +++ b/www/apps/book/sidebar.mjs @@ -473,6 +473,11 @@ export const sidebar = numberSidebarItems( path: "/learn/advanced-development/workflows/execute-another-workflow", title: "Execute Another Workflow", }, + { + type: "link", + path: "/learn/advanced-development/workflows/multiple-step-usage", + title: "Multiple Step Usage", + }, ], }, { diff --git a/www/apps/resources/app/architectural-modules/event/create/page.mdx b/www/apps/resources/app/architectural-modules/event/create/page.mdx index 9344ee3f490fd..0f47f55d33757 100644 --- a/www/apps/resources/app/architectural-modules/event/create/page.mdx +++ b/www/apps/resources/app/architectural-modules/event/create/page.mdx @@ -1,3 +1,5 @@ +import { TypeList } from "docs-ui" + export const metadata = { title: `How to Create an Event Module`, } @@ -19,15 +21,18 @@ Create the file `src/modules/my-event/service.ts` that holds the implementation The Event Module's main service must extend the `AbstractEventBusModuleService` class imported from `@medusajs/framework/utils`: ```ts title="src/modules/my-event/service.ts" -import { EmitData, Message } from "@medusajs/framework/types" -import { AbstractEventBusModuleService } from "@medusajs/framework/utils" +import { AbstractEventBusModuleService } from "@medusajs/framework/utils"; +import { Message } from "@medusajs/types"; class MyEventService extends AbstractEventBusModuleService { - emit(eventName: string, data: T, options: Record): Promise; - emit(data: EmitData[]): Promise; - emit(data: Message[]): Promise; - emit(eventName: unknown, data?: unknown, options?: unknown): Promise { - throw new Error("Method not implemented.") + async emit(data: Message | Message[], options: Record): Promise { + throw new Error("Method not implemented."); + } + async releaseGroupedEvents(eventGroupId: string): Promise { + throw new Error("Method not implemented."); + } + async clearGroupedEvents(eventGroupId: string): Promise { + throw new Error("Method not implemented."); } } @@ -36,52 +41,175 @@ export default MyEventService The service implements the required methods based on the desired publish/subscribe logic. -### Note About the eventToSubscribersMap Property +### eventToSubscribersMap_ Property -The `AbstractEventBusModuleService` has a field `eventToSubscribersMap`, which is a JavaScript Map. The map's keys are the event names, whereas the value of each key is an array of subscribed handler functions. +The `AbstractEventBusModuleService` has a field `eventToSubscribersMap_`, which is a JavaScript Map. The map's keys are the event names, whereas the value of each key is an array of subscribed handler functions. In your custom implementation, you can use this property to manage the subscribed handler functions: ```ts const eventSubscribers = - this.eventToSubscribersMap.get(eventName) || [] + this.eventToSubscribersMap_.get(eventName) || [] ``` -### Implement emit Method +### emit Method The `emit` method is used to push an event from the Medusa application into your messaging system. The subscribers to that event would then pick up the message and execute their asynchronous tasks. -The `emit` method has three different signatures: +An example implementation: + +```ts title="src/modules/my-event/service.ts" +class MyEventService extends AbstractEventBusModuleService { + async emit(data: Message | Message[], options: Record): Promise { + const events = Array.isArray(data) ? data : [data] + + for (const event of events) { + console.log(`Received the event ${event.name} with data ${event.data}`) + + // TODO push the event somewhere + } + } + // ... +} +``` + +The `emit` method receives the following parameters: + + + +### releaseGroupedEvents Method + +Grouped events are useful when you have distributed transactions where you need to explicitly group, release, and clear events upon lifecycle transaction events. + +If your Event Module supports grouped events, this method is used to emit all events in a group, then clear that group. + +For example: + +```ts title="src/modules/my-event/service.ts" +class MyEventService extends AbstractEventBusModuleService { + protected groupedEventsMap_: Map + + constructor() { + // @ts-ignore + super(...arguments) + + this.groupedEventsMap_ = new Map() + } + + async releaseGroupedEvents(eventGroupId: string): Promise { + const groupedEvents = this.groupedEventsMap_.get(eventGroupId) || [] + + for (const event of groupedEvents) { + const { options, ...eventBody } = event + + // TODO emit event + } -1. The first signature accepts three parameters: - - The first parameter is a string indicating the name of the event to trigger. - - The second parameter is data to send to subscribers of that event. - - The third optional parameter can be used to pass options specific to the event service. -2. The second signature accepts one parameter, which is an array of objects having the following properties: - - `eventName`: A string indicating the name of the event to trigger. - - `data`: The data to send to subsribers of that event. - - `options`: (optional) options specific to the event service. -3. The third signature accepts one parameter, which is an array of objects having the following properties: - - `eventName`: A string indicating the name of the event to trigger. - - `body`: An object of event-related data. It has two properties: `data` holding the data of the event, and `metadata` which is an object with more details on how the event was emitted, such as the action that occurred or the service that emitted it. - - `options`: (optional) options specific to the event service. + await this.clearGroupedEvents(eventGroupId) + } + + // ... +} +``` + +The `releaseGroupedEvents` receives the group ID as a parameter. + +In the example above, you add a `groupedEventsMap_` property to store grouped events. Then, in the method, you emit the events in the group, then clear the grouped events using the `clearGroupedEvents` which you'll learn about next. -You can implement your method in a way that supports both signatures by checking the type of the first input. For example: +To add events to the grouped events map, you can do it in the `emit` method: ```ts title="src/modules/my-event/service.ts" class MyEventService extends AbstractEventBusModuleService { // ... - emit(eventName: string, data: T, options: Record): Promise; - emit(data: EmitData[]): Promise; - emit(data: Message[]): Promise; - emit(eventOrData: unknown, data?: unknown, options?: unknown): Promise { - const isBulkEmit = Array.isArray(eventOrData) + async emit(data: Message | Message[], options: Record): Promise { + const events = Array.isArray(data) ? data : [data] + + for (const event of events) { + console.log(`Received the event ${event.name} with data ${event.data}`) + + if (event.metadata.eventGroupId) { + const groupedEvents = this.groupedEventsMap_.get( + event.metadata.eventGroupId + ) || [] + + groupedEvents.push(event) + + this.groupedEventsMap_.set(event.metadata.eventGroupId, groupedEvents) + continue + } + + // TODO push the event somewhere + } + } +} +``` + +### clearGroupedEvents Method + +If your Event Module supports grouped events, this method is used to remove the events of a group. - // ... +For example: + +```ts title="src/modules/my-event/service.ts" +class MyEventService extends AbstractEventBusModuleService { + // from previous section + protected groupedEventsMap_: Map + + async clearGroupedEvents(eventGroupId: string): Promise { + this.groupedEventsMap_.delete(eventGroupId) } + + // ... } ``` +The method accepts the group's name as a parameter. + +In the method, you delete the group from the `groupedEventsMap_` property (added in the previous section), deleting the stored events of it as well. + --- ## 3. Create Module Definition File diff --git a/www/apps/resources/app/architectural-modules/page.mdx b/www/apps/resources/app/architectural-modules/page.mdx index 86a3546e46838..ae19437da66dc 100644 --- a/www/apps/resources/app/architectural-modules/page.mdx +++ b/www/apps/resources/app/architectural-modules/page.mdx @@ -8,4 +8,4 @@ export const metadata = { This section includes documentation for official Medusa architectural modules. - \ No newline at end of file + \ No newline at end of file diff --git a/www/apps/resources/app/commerce-modules/auth/create-actor-type/page.mdx b/www/apps/resources/app/commerce-modules/auth/create-actor-type/page.mdx index b37100870fb29..63fe239709fac 100644 --- a/www/apps/resources/app/commerce-modules/auth/create-actor-type/page.mdx +++ b/www/apps/resources/app/commerce-modules/auth/create-actor-type/page.mdx @@ -349,7 +349,7 @@ You add a step that deletes the manager using the `deleteManagers` method of the Next, in the same file, add the workflow that deletes a manager: export const deleteHighlights = [ - ["30", "manager_id", "If your actor type has a different name, such as vendor, change it to be `{actor_type}_id`."] + ["29", "manager_id", "If your actor type has a different name, such as vendor, change it to be `{actor_type}_id`."] ] ```ts title="src/workflows/delete-manager.ts" collapsibleLines="1-15" expandButtonLabel="Show Imports" highlights={deleteHighlights} @@ -363,7 +363,7 @@ import { } from "@medusajs/framework/workflows-sdk" import { setAuthAppMetadataStep, - useRemoteQueryStep, + useQueryGraphStep, } from "@medusajs/medusa/core-flows" // ... @@ -375,17 +375,15 @@ export const deleteManagerWorkflow = createWorkflow( ): WorkflowResponse => { deleteManagerStep(input) - const authIdentities = useRemoteQueryStep({ - entry_point: "auth_identity", + const { data: authIdentities } = useQueryGraphStep({ + entity: "auth_identity", fields: ["id"], - variables: { - filters: { - app_metadata: { - // the ID is of the format `{actor_type}_id`. - manager_id: input.id, - }, - }, - }, + filters: { + app_metadata: { + // the ID is of the format `{actor_type}_id`. + manager_id: input.id, + } + } }) const authIdentity = transform( diff --git a/www/apps/resources/app/commerce-modules/cart/extend/page.mdx b/www/apps/resources/app/commerce-modules/cart/extend/page.mdx index 61875693c96ff..9fd7028e23e08 100644 --- a/www/apps/resources/app/commerce-modules/cart/extend/page.mdx +++ b/www/apps/resources/app/commerce-modules/cart/extend/page.mdx @@ -492,7 +492,7 @@ Finally, you'll create the workflow. Create the file `src/workflows/update-custo ```ts title="src/workflows/update-custom-from-cart/index.ts" collapsibleLines="1-9" expandButtonLabel="Show Imports" import { CartDTO } from "@medusajs/framework/types" import { createWorkflow, when, WorkflowResponse } from "@medusajs/framework/workflows-sdk" -import { createRemoteLinkStep, dismissRemoteLinkStep, useRemoteQueryStep } from "@medusajs/medusa/core-flows" +import { createRemoteLinkStep, dismissRemoteLinkStep, useQueryGraphStep } from "@medusajs/medusa/core-flows" import { createCustomStep } from "../create-custom-from-cart/steps/create-custom" import { Modules } from "@medusajs/framework/utils" import { HELLO_MODULE } from "../../modules/hello" @@ -509,15 +509,12 @@ export type UpdateCustomFromCartStepInput = { export const updateCustomFromCartWorkflow = createWorkflow( "update-custom-from-cart", (input: UpdateCustomFromCartStepInput) => { - const cartData = useRemoteQueryStep({ - entry_point: "cart", + const { data: carts } = useQueryGraphStep({ + entity: "cart", fields: ["custom.*"], - variables: { - filters: { - id: input.cart.id, - }, - }, - list: false, + filters: { + id: input.cart.id + } }) // TODO create, update, or delete Custom record @@ -534,9 +531,9 @@ Next, replace the `TODO` with the following: ```ts title="src/workflows/update-custom-from-cart/index.ts" const created = when({ input, - cartData, + carts, }, (data) => - !data.cartData.custom && + !data.carts[0].custom && data.input.additional_data?.custom_name?.length > 0 ) .then(() => { @@ -568,25 +565,25 @@ Next, replace the new `TODO` with the following: ```ts title="src/workflows/update-custom-from-cart/index.ts" const deleted = when({ input, - cartData, + carts, }, (data) => - data.cartData.custom && ( + data.carts[0].custom && ( data.input.additional_data?.custom_name === null || data.input.additional_data?.custom_name.length === 0 ) ) .then(() => { deleteCustomStep({ - custom: cartData.custom, + custom: carts[0].custom, }) dismissRemoteLinkStep({ [HELLO_MODULE]: { - custom_id: cartData.custom.id, + custom_id: carts[0].custom.id, }, }) - return cartData.custom.id + return carts[0].custom.id }) // TODO delete Custom record @@ -599,11 +596,11 @@ Finally, replace the new `TODO` with the following: ```ts title="src/workflows/update-custom-from-cart/index.ts" const updated = when({ input, - cartData, -}, (data) => data.cartData.custom && data.input.additional_data?.custom_name?.length > 0) + carts, +}, (data) => data.carts[0].custom && data.input.additional_data?.custom_name?.length > 0) .then(() => { const custom = updateCustomStep({ - id: cartData.custom.id, + id: carts[0].custom.id, custom_name: input.additional_data.custom_name, }) diff --git a/www/apps/resources/app/commerce-modules/customer/extend/page.mdx b/www/apps/resources/app/commerce-modules/customer/extend/page.mdx index a89437efa78a2..dbcc3b5c09c1c 100644 --- a/www/apps/resources/app/commerce-modules/customer/extend/page.mdx +++ b/www/apps/resources/app/commerce-modules/customer/extend/page.mdx @@ -504,7 +504,7 @@ Finally, you'll create the workflow. Create the file `src/workflows/update-custo ```ts title="src/workflows/update-custom-from-customer/index.ts" collapsibleLines="1-9" expandButtonLabel="Show Imports" import { CustomerDTO } from "@medusajs/framework/types" import { createWorkflow, when, WorkflowResponse } from "@medusajs/framework/workflows-sdk" -import { createRemoteLinkStep, dismissRemoteLinkStep, useRemoteQueryStep } from "@medusajs/medusa/core-flows" +import { createRemoteLinkStep, dismissRemoteLinkStep, useQueryGraphStep } from "@medusajs/medusa/core-flows" import { createCustomStep } from "../create-custom-from-customer/steps/create-custom" import { Modules } from "@medusajs/framework/utils" import { HELLO_MODULE } from "../../modules/hello" @@ -521,15 +521,12 @@ export type UpdateCustomFromCustomerStepInput = { export const updateCustomFromCustomerWorkflow = createWorkflow( "update-custom-from-customer", (input: UpdateCustomFromCustomerStepInput) => { - const customerData = useRemoteQueryStep({ - entry_point: "customer", + const { data: customers } = useQueryGraphStep({ + entity: "customer", fields: ["custom.*"], - variables: { - filters: { - id: input.customer.id, - }, - }, - list: false, + filters: { + id: input.customer.id, + } }) // TODO create, update, or delete Custom record @@ -546,9 +543,9 @@ Next, replace the `TODO` with the following: ```ts title="src/workflows/update-custom-from-customer/index.ts" const created = when({ input, - customerData, + customers, }, (data) => - !data.customerData.custom && + !data.customers[0].custom && data.input.additional_data?.custom_name?.length > 0 ) .then(() => { @@ -580,25 +577,25 @@ Next, replace the new `TODO` with the following: ```ts title="src/workflows/update-custom-from-customer/index.ts" const deleted = when({ input, - customerData, + customers, }, (data) => - data.customerData.custom && ( + data.customers[0].custom && ( data.input.additional_data?.custom_name === null || data.input.additional_data?.custom_name.length === 0 ) ) .then(() => { deleteCustomStep({ - custom: customerData.custom, + custom: customers[0].custom, }) dismissRemoteLinkStep({ [HELLO_MODULE]: { - custom_id: customerData.custom.id, + custom_id: customers[0].custom.id, }, }) - return customerData.custom.id + return customers[0].custom.id }) // TODO delete Custom record @@ -611,11 +608,11 @@ Finally, replace the new `TODO` with the following: ```ts title="src/workflows/update-custom-from-customer/index.ts" const updated = when({ input, - customerData, -}, (data) => data.customerData.custom && data.input.additional_data?.custom_name?.length > 0) + customers, +}, (data) => data.customers[0].custom && data.input.additional_data?.custom_name?.length > 0) .then(() => { const custom = updateCustomStep({ - id: customerData.custom.id, + id: customers[0].custom.id, custom_name: input.additional_data.custom_name, }) diff --git a/www/apps/resources/app/commerce-modules/product/extend/page.mdx b/www/apps/resources/app/commerce-modules/product/extend/page.mdx index 53da450d2fd66..8980bda480ca1 100644 --- a/www/apps/resources/app/commerce-modules/product/extend/page.mdx +++ b/www/apps/resources/app/commerce-modules/product/extend/page.mdx @@ -510,7 +510,7 @@ Finally, you'll create the workflow. Create the file `src/workflows/update-custo ```ts title="src/workflows/update-custom-from-product/index.ts" collapsibleLines="1-9" expandButtonLabel="Show Imports" import { ProductDTO } from "@medusajs/framework/types" import { createWorkflow, when, WorkflowResponse } from "@medusajs/framework/workflows-sdk" -import { createRemoteLinkStep, dismissRemoteLinkStep, useRemoteQueryStep } from "@medusajs/medusa/core-flows" +import { createRemoteLinkStep, dismissRemoteLinkStep, useQueryGraphStep } from "@medusajs/medusa/core-flows" import { createCustomStep } from "../create-custom-from-cart/steps/create-custom" import { Modules } from "@medusajs/framework/utils" import { HELLO_MODULE } from "../../modules/hello" @@ -527,15 +527,12 @@ export type UpdateCustomFromProductStepInput = { export const updateCustomFromProductWorkflow = createWorkflow( "update-custom-from-product", (input: UpdateCustomFromProductStepInput) => { - const productData = useRemoteQueryStep({ - entry_point: "product", + const { data: products } = useQueryGraphStep({ + entity: "product", fields: ["custom.*"], - variables: { - filters: { - id: input.product.id - } - }, - list: false + filters: { + id: input.product.id, + } }) // TODO create, update, or delete Custom record @@ -552,9 +549,9 @@ Next, replace the `TODO` with the following: ```ts title="src/workflows/update-custom-from-product/index.ts" const created = when({ input, - productData + products }, (data) => - !data.productData.custom && + !data.products[0].custom && data.input.additional_data?.custom_name?.length > 0 ) .then(() => { @@ -586,25 +583,25 @@ Next, replace the new `TODO` with the following: ```ts title="src/workflows/update-custom-from-product/index.ts" const deleted = when({ input, - productData + products }, (data) => - data.productData.custom && ( + data.products[0].custom && ( data.input.additional_data?.custom_name === null || data.input.additional_data?.custom_name.length === 0 ) ) .then(() => { deleteCustomStep({ - custom: productData.custom + custom: products[0].custom }) dismissRemoteLinkStep({ [HELLO_MODULE]: { - custom_id: productData.custom.id + custom_id: products[0].custom.id } }) - return productData.custom.id + return products[0].custom.id }) // TODO delete Custom record @@ -617,11 +614,11 @@ Finally, replace the new `TODO` with the following: ```ts title="src/workflows/update-custom-from-product/index.ts" const updated = when({ input, - productData -}, (data) => data.productData.custom && data.input.additional_data?.custom_name?.length > 0) + products +}, (data) => data.products[0].custom && data.input.additional_data?.custom_name?.length > 0) .then(() => { const custom = updateCustomStep({ - id: productData.custom.id, + id: products[0].custom.id, custom_name: input.additional_data.custom_name }) diff --git a/www/apps/resources/app/commerce-modules/promotion/extend/page.mdx b/www/apps/resources/app/commerce-modules/promotion/extend/page.mdx index 85a81136e3839..488c9b66913fe 100644 --- a/www/apps/resources/app/commerce-modules/promotion/extend/page.mdx +++ b/www/apps/resources/app/commerce-modules/promotion/extend/page.mdx @@ -516,7 +516,7 @@ Finally, you'll create the workflow. Create the file `src/workflows/update-custo ```ts title="src/workflows/update-custom-from-promotion/index.ts" collapsibleLines="1-9" expandButtonLabel="Show Imports" import { PromotionDTO } from "@medusajs/framework/types" import { createWorkflow, when, WorkflowResponse } from "@medusajs/framework/workflows-sdk" -import { createRemoteLinkStep, dismissRemoteLinkStep, useRemoteQueryStep } from "@medusajs/medusa/core-flows" +import { createRemoteLinkStep, dismissRemoteLinkStep, useQueryGraphStep } from "@medusajs/medusa/core-flows" import { createCustomStep } from "../create-custom-from-cart/steps/create-custom" import { Modules } from "@medusajs/framework/utils" import { HELLO_MODULE } from "../../modules/hello" @@ -533,15 +533,12 @@ export type UpdateCustomFromPromotionStepInput = { export const updateCustomFromPromotionWorkflow = createWorkflow( "update-custom-from-promotion", (input: UpdateCustomFromPromotionStepInput) => { - const promotionData = useRemoteQueryStep({ - entry_point: "promotion", + const { data: promotions } = useQueryGraphStep({ + entity: "promotion", fields: ["custom.*"], - variables: { - filters: { - id: input.promotion.id - } - }, - list: false + filters: { + id: input.promotion.id, + } }) // TODO create, update, or delete Custom record @@ -558,9 +555,9 @@ Next, replace the `TODO` with the following: ```ts title="src/workflows/update-custom-from-promotion/index.ts" const created = when({ input, - promotionData + promotions }, (data) => - !data.promotionData.custom && + !data.promotions[0].custom && data.input.additional_data?.custom_name?.length > 0 ) .then(() => { @@ -592,25 +589,25 @@ Next, replace the new `TODO` with the following: ```ts title="src/workflows/update-custom-from-promotion/index.ts" const deleted = when({ input, - promotionData + promotions }, (data) => - data.promotionData.custom && ( + data.promotions[0].custom && ( data.input.additional_data?.custom_name === null || data.input.additional_data?.custom_name.length === 0 ) ) .then(() => { deleteCustomStep({ - custom: promotionData.custom + custom: promotions[0].custom }) dismissRemoteLinkStep({ [HELLO_MODULE]: { - custom_id: promotionData.custom.id + custom_id: promotions[0].custom.id } }) - return promotionData.custom.id + return promotions[0].custom.id }) // TODO delete Custom record @@ -623,11 +620,11 @@ Finally, replace the new `TODO` with the following: ```ts title="src/workflows/update-custom-from-promotion/index.ts" const updated = when({ input, - promotionData -}, (data) => data.promotionData.custom && data.input.additional_data?.custom_name?.length > 0) + promotions +}, (data) => data.promotions[0].custom && data.input.additional_data?.custom_name?.length > 0) .then(() => { const custom = updateCustomStep({ - id: promotionData.custom.id, + id: promotions[0].custom.id, custom_name: input.additional_data.custom_name }) diff --git a/www/apps/resources/app/deployment/storefront/vercel/page.mdx b/www/apps/resources/app/deployment/storefront/vercel/page.mdx index 790310b438532..43304af4f31b0 100644 --- a/www/apps/resources/app/deployment/storefront/vercel/page.mdx +++ b/www/apps/resources/app/deployment/storefront/vercel/page.mdx @@ -5,7 +5,7 @@ sidebar_label: "Vercel" import { Prerequisites } from "docs-ui" export const metadata = { - title: `Deploy Medusa Admin to Vercel`, + title: `Deploy Medusa Next.js to Vercel`, } # {metadata.title} diff --git a/www/apps/resources/app/recipes/digital-products/examples/standard/page.mdx b/www/apps/resources/app/recipes/digital-products/examples/standard/page.mdx index 9daf3d52c349a..920809d7587f9 100644 --- a/www/apps/resources/app/recipes/digital-products/examples/standard/page.mdx +++ b/www/apps/resources/app/recipes/digital-products/examples/standard/page.mdx @@ -1567,8 +1567,8 @@ To customize the cart completion flow, you’ll create a workflow and then use t ```mermaid graph TD - completeCartWorkflow["completeCartWorkflow (Medusa)"] --> useRemoteQueryStep["useRemoteQueryStep (Medusa)"] - useRemoteQueryStep --> when{order has digital products?} + completeCartWorkflow["completeCartWorkflow (Medusa)"] --> useQueryGraphStep["useQueryGraphStep (Medusa)"] + useQueryGraphStep --> when{order has digital products?} when -->|Yes| createDigitalProductOrderStep createDigitalProductOrderStep --> createRemoteLinkStep["createRemoteLinkStep (Medusa)"] createRemoteLinkStep --> createOrderFulfillmentWorkflow["createOrderFulfillmentWorkflow (Medusa)"] @@ -1580,7 +1580,7 @@ graph TD The workflow has the following steps: 1. `completeCartWorkflow` to create a Medusa order from the cart. Medusa provides this workflow through the `@medusajs/medusa/core-flows` package and you can use it as a step. -2. `useRemoteQueryStep` to retrieve the order’s items with the digital products associated with the purchased product variants. Medusa provides this step through the `@medusajs/medusa/core-flows` package. +2. `useQueryGraphStep` to retrieve the order’s items with the digital products associated with the purchased product variants. Medusa provides this step through the `@medusajs/medusa/core-flows` package. 3. If the order has digital products, you: 1. create the digital product order. 2. link the digital product order with the Medusa order. Medusa provides a `createRemoteLinkStep` in the `@medusajs/medusa/core-flows` package that can be used here. @@ -1665,14 +1665,14 @@ In the compensation function, you delete the digital product order. Create the file `src/workflows/create-digital-product-order/index.ts` with the following content: export const createDpoWorkflowHighlights = [ - ["25", "completeCartWorkflow", "Create an order for the cart."], - ["31", "useRemoteQueryStep", "Retrieve the order's items and their associated variants and linked digital products."], - ["56", "when", "Check whether the order has any digital products."], - ["61", "then", "Perform the callback function if an order has digital products."], - ["64", "createDigitalProductOrderStep", "Create the digital product order."], - ["66", "createRemoteLinkStep", "Link the digital product order to the Medusa order."], - ["75", "createOrderFulfillmentWorkflow", "Create a fulfillment for the digital products in the order."], - ["89", "emitEventStep", "Emit the `digital_product_order.created` event."] + ["27", "completeCartWorkflow", "Create an order for the cart."], + ["33", "useQueryGraphStep", "Retrieve the order's items and their associated variants and linked digital products."], + ["57", "when", "Check whether the order has any digital products."], + ["60", "then", "Perform the callback function if an order has digital products."], + ["63", "createDigitalProductOrderStep", "Create the digital product order."], + ["67", "createRemoteLinkStep", "Link the digital product order to the Medusa order."], + ["76", "createOrderFulfillmentWorkflow", "Create a fulfillment for the digital products in the order."], + ["90", "emitEventStep", "Emit the `digital_product_order.created` event."] ] ```ts title="src/workflows/create-digital-product-order/index.ts" highlights={createDpoWorkflowHighlights} collapsibleLines="1-17" expandMoreLabel="Show Imports" @@ -1680,16 +1680,18 @@ import { createWorkflow, transform, when, - WorkflowResponse, + WorkflowResponse } from "@medusajs/framework/workflows-sdk" import { completeCartWorkflow, - useRemoteQueryStep, + useQueryGraphStep, createRemoteLinkStep, createOrderFulfillmentWorkflow, - emitEventStep, + emitEventStep } from "@medusajs/medusa/core-flows" -import { Modules } from "@medusajs/framework/utils" +import { + Modules +} from "@medusajs/framework/utils" import createDigitalProductOrderStep from "./steps/create-digital-product-order" import { DIGITAL_PRODUCT_MODULE } from "../../modules/digital-product" @@ -1700,35 +1702,34 @@ type WorkflowInput = { const createDigitalProductOrderWorkflow = createWorkflow( "create-digital-product-order", (input: WorkflowInput) => { - const order = completeCartWorkflow.runAsStep({ + const { id } = completeCartWorkflow.runAsStep({ input: { - id: input.cart_id, - }, + id: input.cart_id + } }) - const { items } = useRemoteQueryStep({ - entry_point: "order", + const { data: orders } = useQueryGraphStep({ + entity: "order", fields: [ "*", "items.*", "items.variant.*", - "items.variant.digital_product.*", + "items.variant.digital_product.*" ], - variables: { - filters: { - id: order.id, - }, + filters: { + id }, - throw_if_key_not_found: true, - list: false, + options: { + throwIfKeyNotFound: true + } }) const itemsWithDigitalProducts = transform({ - items, + orders }, (data) => { - return data.items.filter((item) => item.variant.digital_product !== undefined) - } + return data.orders[0].items.filter((item) => item.variant.digital_product !== undefined) + } ) const digital_product_order = when(itemsWithDigitalProducts, (itemsWithDigitalProducts) => { @@ -1737,44 +1738,46 @@ const createDigitalProductOrderWorkflow = createWorkflow( .then(() => { const { digital_product_order, - } = createDigitalProductOrderStep({ items }) + } = createDigitalProductOrderStep({ + items: orders[0].items + }) createRemoteLinkStep([{ [DIGITAL_PRODUCT_MODULE]: { - digital_product_order_id: digital_product_order.id, + digital_product_order_id: digital_product_order.id }, [Modules.ORDER]: { - order_id: order.id, - }, + order_id: id + } }]) createOrderFulfillmentWorkflow.runAsStep({ input: { - order_id: order.id, + order_id: id, items: transform({ - itemsWithDigitalProducts, + itemsWithDigitalProducts }, (data) => { return data.itemsWithDigitalProducts.map((item) => ({ id: item.id, - quantity: item.quantity, + quantity: item.quantity })) - }), - }, + }) + } }) emitEventStep({ eventName: "digital_product_order.created", data: { - id: digital_product_order.id, - }, + id: digital_product_order.id + } }) return digital_product_order }) return new WorkflowResponse({ - order, - digital_product_order, + order: orders[0], + digital_product_order }) } ) @@ -1785,7 +1788,7 @@ export default createDigitalProductOrderWorkflow This creates the workflow `createDigitalProductOrderWorkflow`. It runs the following steps: 1. `completeCartWorkflow` as a step to create the Medusa order. -2. `useRemoteQueryStep` to retrieve the order’s items with their associated variants and linked digital products. +2. `useQueryGraphStep` to retrieve the order’s items with their associated variants and linked digital products. 3. Use `when` to check whether the order has digital products. If so: 1. Use the `createDigitalProductOrderStep` to create the digital product order. 2. Use the `createRemoteLinkStep` to link the digital product order to the Medusa order. @@ -1842,7 +1845,7 @@ In this step, you'll create a workflow that fulfills a digital order by sending The workflow has the following steps: -1. Retrieve the digital product order's details. For this, you'll use the `useRemoteQueryStep` imported from `@medusajs/medusa/core-flows`. +1. Retrieve the digital product order's details. For this, you'll use the `useQueryGraphStep` imported from `@medusajs/medusa/core-flows`. 2. Send a notification to the customer with the digital products to download. So, you only need to implement the second step. @@ -1959,17 +1962,17 @@ You use the `createNotifications` method of the Notification Module's main servi Create the workflow in the file `src/workflows/fulfill-digital-order/index.ts`: export const fulfillWorkflowHighlights = [ - ["17", "useRemoteQueryStep", "Retrieve the digital product order's details."], + ["17", "useQueryGraphStep", "Retrieve the digital product order's details."], ["33", "sendDigitalOrderNotificationStep", "Send a notification to the customer."] ] ```ts title="src/workflows/fulfill-digital-order/index.ts" highlights={fulfillWorkflowHighlights} collapsibleLines="1-10" expandMoreLabel="Show Imports" import { createWorkflow, - WorkflowResponse, + WorkflowResponse } from "@medusajs/framework/workflows-sdk" import { - useRemoteQueryStep, + useQueryGraphStep, } from "@medusajs/medusa/core-flows" import { sendDigitalOrderNotificationStep } from "./steps/send-digital-order-notification" @@ -1980,29 +1983,28 @@ type FulfillDigitalOrderWorkflowInput = { export const fulfillDigitalOrderWorkflow = createWorkflow( "fulfill-digital-order", ({ id }: FulfillDigitalOrderWorkflowInput) => { - const digitalProductOrder = useRemoteQueryStep({ - entry_point: "digital_product_order", + const { data: digitalProductOrders } = useQueryGraphStep({ + entity: "digital_product_order", fields: [ "*", "products.*", "products.medias.*", - "order.*", + "order.*" ], - variables: { - filters: { - id, - }, + filters: { + id, }, - list: false, - throw_if_key_not_found: true, + options: { + throwIfKeyNotFound: true + } }) sendDigitalOrderNotificationStep({ - digital_product_order: digitalProductOrder, + digital_product_order: digitalProductOrders[0] }) return new WorkflowResponse( - digitalProductOrder + digitalProductOrders[0] ) } ) @@ -2010,7 +2012,7 @@ export const fulfillDigitalOrderWorkflow = createWorkflow( In the workflow, you: -1. Retrieve the digital product order's details using the `useRemoteQueryStep` imported from `@medusajs/medusa/core-flows`. +1. Retrieve the digital product order's details using the `useQueryGraphStep` imported from `@medusajs/medusa/core-flows`. 2. Send a notification to the customer with the digital product download links using the `sendDigitalOrderNotificationStep`. ### Configure Notification Module Provider diff --git a/www/apps/resources/app/recipes/marketplace/examples/restaurant-delivery/page.mdx b/www/apps/resources/app/recipes/marketplace/examples/restaurant-delivery/page.mdx index 4964ce3332477..b9c952c4145d3 100644 --- a/www/apps/resources/app/recipes/marketplace/examples/restaurant-delivery/page.mdx +++ b/www/apps/resources/app/recipes/marketplace/examples/restaurant-delivery/page.mdx @@ -1119,7 +1119,7 @@ import { } from "@medusajs/framework/workflows-sdk" import { setAuthAppMetadataStep, - useRemoteQueryStep, + useQueryGraphStep, } from "@medusajs/medusa/core-flows" import { deleteRestaurantAdminStep } from "../steps/delete-restaurant-admin" @@ -1144,14 +1144,12 @@ So far, you only use the `deleteRestaurantAdminStep` in the workflow, which dele Replace the `TODO` with the following: ```ts title="restaurant-marketplace/src/workflows/restaurant/workflows/delete-restaurant-admin.ts" -const authIdentities = useRemoteQueryStep({ - entry_point: "auth_identity", +const { data: authIdentities } = useQueryGraphStep({ + entity: "auth_identity", fields: ["id"], - variables: { - filters: { - app_metadata: { - restaurant_id: input.id, - }, + filters: { + app_metadata: { + restaurant_id: input.id, }, }, }) diff --git a/www/apps/resources/app/recipes/marketplace/examples/vendors/page.mdx b/www/apps/resources/app/recipes/marketplace/examples/vendors/page.mdx index 748bfc935afa8..26d6b0e158764 100644 --- a/www/apps/resources/app/recipes/marketplace/examples/vendors/page.mdx +++ b/www/apps/resources/app/recipes/marketplace/examples/vendors/page.mdx @@ -803,14 +803,14 @@ In this step, you’ll create a workflow that’s executed when the customer pla ```mermaid graph TD - retrieveCartStep["Retrieve Cart (useRemoteQueryStep from Medusa)"] --> completeCartWorkflow["completeCartWorkflow (Medusa)"] + retrieveCartStep["Retrieve Cart (useQueryGraphStep from Medusa)"] --> completeCartWorkflow["completeCartWorkflow (Medusa)"] completeCartWorkflow["completeCartWorkflow (Medusa)"] --> groupVendorItemsStep groupVendorItemsStep --> getOrderDetailWorkflow getOrderDetailWorkflow --> createVendorOrdersStep createVendorOrdersStep --> createRemoteLinkStep["Create Links (createRemoteLinkStep from Medusa)"] ``` -1. Retrieve the cart using its ID. Medusa provides a `useRemoteQueryStep` in the `@medusajs/medusa/core-flows` package that you can use. +1. Retrieve the cart using its ID. Medusa provides a `useQueryGraphStep` in the `@medusajs/medusa/core-flows` package that you can use. 2. Create a parent order for the cart and its items. Medusa also has a `completeCartWorkflow` in the `@medusajs/medusa/core-flows` package that you can use as a step. 3. Group the cart items by their product’s associated vendor. 4. Retrieve the order's details using Medusa's `getOrderDetailWorkflow` exported by the `@medusajs/medusa/core-flows` package. @@ -1135,25 +1135,24 @@ The compensation function cancels all child orders received from the step. It us Finally, create the workflow at the file `src/workflows/marketplace/create-vendor-orders/index.ts`: export const createVendorOrdersWorkflowHighlights = [ - ["21", "useRemoteQueryStep", "Retrieve the cart's details."], - ["29", "completeCartWorkflow", "Create the parent order from the cart."], - ["35", "groupVendorItemsStep", "Group the items by their vendor."], - ["42", "createVendorOrdersStep", "Create child orders for each vendor"], - ["47", "createRemoteLinkStep", "Create the links returned by the previous step."] + ["21", "useQueryGraphStep", "Retrieve the cart's details."], + ["30", "completeCartWorkflow", "Create the parent order from the cart."], + ["36", "groupVendorItemsStep", "Group the items by their vendor."], + ["59", "createVendorOrdersStep", "Create child orders for each vendor"], + ["64", "createRemoteLinkStep", "Create the links returned by the previous step."] ] ```ts title="src/workflows/marketplace/create-vendor-orders/index.ts" collapsibleLines="1-13" expandMoreLabel="Show Imports" import { createWorkflow, - WorkflowResponse, + WorkflowResponse } from "@medusajs/framework/workflows-sdk" import { - useRemoteQueryStep, + useQueryGraphStep, createRemoteLinkStep, completeCartWorkflow, getOrderDetailWorkflow } from "@medusajs/medusa/core-flows" -import { CartDTO } from "@medusajs/framework/types" import groupVendorItemsStep from "./steps/group-vendor-items" import createVendorOrdersStep from "./steps/create-vendor-orders" @@ -1164,24 +1163,25 @@ type WorkflowInput = { const createVendorOrdersWorkflow = createWorkflow( "create-vendor-order", (input: WorkflowInput) => { - const cart = useRemoteQueryStep({ - entry_point: "cart", - fields: ["items.*"], - variables: { id: input.cart_id }, - list: false, - throw_if_key_not_found: true, - }) as CartDTO + const { data: carts } = useQueryGraphStep({ + entity: "cart", + fields: ['items.*'], + filters: { id: input.cart_id }, + options: { + throwIfKeyNotFound: true + } + }) const { id: orderId } = completeCartWorkflow.runAsStep({ input: { - id: cart.id + id: carts[0].id } }) const { vendorsItems } = groupVendorItemsStep({ - cart, + cart: carts[0].id }) - + const order = getOrderDetailWorkflow.runAsStep({ input: { order_id: orderId, @@ -1200,17 +1200,17 @@ const createVendorOrdersWorkflow = createWorkflow( const { orders: vendorOrders, - linkDefs, + linkDefs } = createVendorOrdersStep({ parentOrder: order, - vendorsItems, + vendorsItems }) createRemoteLinkStep(linkDefs) return new WorkflowResponse({ parent_order: order, - vendor_orders: vendorOrders, + vendor_orders: vendorOrders }) } ) @@ -1220,11 +1220,12 @@ export default createVendorOrdersWorkflow In the workflow, you run the following steps: -1. `useRemoteQueryStep` to retrieve the cart's details. +1. `useQueryGraphStep` to retrieve the cart's details. 2. `completeCartWorkflow` to complete the cart and create a parent order. 3. `groupVendorItemsStep` to group the order's items by their vendor. -4. `createVendorOrdersStep` to create child orders for each vendor's items. -5. `createRemoteLinkStep` to create the links returned by the previous step. +4. `getOrderDetailWorkflow` to retrieve an order's details. +5. `createVendorOrdersStep` to create child orders for each vendor's items. +6. `createRemoteLinkStep` to create the links returned by the previous step. You return the parent and vendor orders. diff --git a/www/apps/resources/app/recipes/subscriptions/examples/standard/page.mdx b/www/apps/resources/app/recipes/subscriptions/examples/standard/page.mdx index 84f42e854346b..f3a35c6a9b066 100644 --- a/www/apps/resources/app/recipes/subscriptions/examples/standard/page.mdx +++ b/www/apps/resources/app/recipes/subscriptions/examples/standard/page.mdx @@ -592,23 +592,23 @@ Create the file `src/workflows/create-subscription/index.ts` with the following export const createSubscriptionWorkflowHighlights = [ ["26", "completeCartWorkflow", "Complete the cart and create the order."], - ["32", "useRemoteQueryStep", "Retrieve the order's details."], - ["44", "createSubscriptionStep", "Create the subscription."], - ["51", "createRemoteLinkStep", "Create the links returned by the previous step."] + ["32", "useQueryGraphStep", "Retrieve the order's details."], + ["43", "createSubscriptionStep", "Create the subscription."], + ["50", "createRemoteLinkStep", "Create the links returned by the previous step."] ] ```ts title="src/workflows/create-subscription/index.ts" highlights={createSubscriptionWorkflowHighlights} collapsibleLines="1-13" expandMoreLabel="Show Imports" import { createWorkflow, - WorkflowResponse, + WorkflowResponse } from "@medusajs/framework/workflows-sdk" import { createRemoteLinkStep, completeCartWorkflow, - useRemoteQueryStep + useQueryGraphStep } from "@medusajs/medusa/core-flows" import { - SubscriptionInterval, + SubscriptionInterval } from "../../modules/subscription/types" import createSubscriptionStep from "./steps/create-subscription" @@ -629,30 +629,29 @@ const createSubscriptionWorkflow = createWorkflow( } }) - const order = useRemoteQueryStep({ - entry_point: "order", + const { data: orders } = useQueryGraphStep({ + entity: "order", fields: ["*", "id", "customer_id"], - variables: { - filters: { - id - } + filters: { + id }, - list: false, - throw_if_key_not_found: true + options: { + throwIfKeyNotFound: true + } }) const { subscription, linkDefs } = createSubscriptionStep({ cart_id: input.cart_id, - order_id: order.id, - customer_id: order.customer_id, - subscription_data: input.subscription_data, + order_id: orders[0].id, + customer_id: orders[0].customer_id, + subscription_data: input.subscription_data }) createRemoteLinkStep(linkDefs) return new WorkflowResponse({ subscription: subscription, - order: order, + order: orders[0] }) } ) @@ -663,7 +662,7 @@ export default createSubscriptionWorkflow This workflow accepts the cart’s ID, along with the subscription details. It executes the following steps: 1. `completeCartWorkflow` from `@medusajs/medusa/core-flows` that completes a cart and creates an order. -2. `useRemoteQueryStep` from `@medusajs/medusa/core-flows` to retrieve the order's details. +2. `useQueryGraphStep` from `@medusajs/medusa/core-flows` to retrieve the order's details. 3. `createSubscriptionStep`, which is the step you created previously. 4. `createRemoteLinkStep` from `@medusajs/medusa/core-flows`, which accepts links to create. These links are in the `linkDefs` array returned by the previous step. @@ -1478,7 +1477,7 @@ The workflow has eight steps: ```mermaid graph TD - useRemoteQueryStep["Retrieve Cart (useRemoteQueryStep by Medusa)"] --> createPaymentCollectionStep["createPaymentCollectionStep (Medusa)"] + useQueryGraphStep["Retrieve Cart (useQueryGraphStep by Medusa)"] --> createPaymentCollectionStep["createPaymentCollectionStep (Medusa)"] createPaymentCollectionStep["createPaymentCollectionStep (Medusa)"] --> createPaymentSessionsWorkflow["createPaymentSessionsWorkflow (Medusa)"] createPaymentSessionsWorkflow["createPaymentSessionsWorkflow (Medusa)"] --> authorizePaymentSessionStep["authorizePaymentSessionStep (Medusa)"] authorizePaymentSessionStep["authorizePaymentSessionStep (Medusa)"] --> createSubscriptionOrderStep @@ -1487,7 +1486,7 @@ graph TD capturePaymentStep["capturePaymentStep (Medusa)"] --> updateSubscriptionStep ``` -1. Retrieve the subscription’s linked cart. Medusa provides a `useRemoteQueryStep` in the `@medusajs/medusa/core-flows` package that can be used as a step. +1. Retrieve the subscription’s linked cart. Medusa provides a `useQueryGraphStep` in the `@medusajs/medusa/core-flows` package that can be used as a step. 2. Create a payment collection for the new order. Medusa provides a `createPaymentCollectionsStep` in the `@medusajs/medusa/core-flows` package that you can use. 3. Create payment sessions in the payment collection. Medusa provides a `createPaymentSessionsWorkflow` in the `@medusajs/medusa/core-flows` package that can be used as a step. 4. Authorize the payment session. Medusa also provides the `authorizePaymentSessionStep` in the `@medusajs/medusa/core-flows` package, which can be used. @@ -1771,38 +1770,30 @@ This updates the subscription’s `last_order_date` and `next_order_date` proper Finally, create the file `src/workflows/create-subscription-order/index.ts` with the following content: export const createSubscriptionOrderWorkflowHighlights = [ - ["33", "useRemoteQueryStep", "Retrieve the cart linked to the subscription."], - ["60", "createPaymentCollectionsStep", "Create a payment collection using the same information in the cart."], - ["67", "createPaymentSessionsWorkflow", "Create a payment session in the payment collection from the previous step."], - ["76", "authorizePaymentSessionStep", "Authorize the payment session created from the first step."], - ["81", "createSubscriptionOrderStep", "Create the new order for the subscription."], - ["87", "createRemoteLinkStep", "Create links returned by the previous step."], - ["89", "capturePaymentStep", "Capture the order’s payment."], - ["94", "updateSubscriptionStep", "Update the subscription’s `last_order_date` and `next_order_date`."] + ["25", "useQueryGraphStep", "Retrieve the cart linked to the subscription."], + ["49", "createPaymentCollectionsStep", "Create a payment collection using the same information in the cart."], + ["56", "createPaymentSessionsWorkflow", "Create a payment session in the payment collection from the previous step."], + ["65", "authorizePaymentSessionStep", "Authorize the payment session created from the first step."], + ["70", "createSubscriptionOrderStep", "Create the new order for the subscription."], + ["76", "createRemoteLinkStep", "Create links returned by the previous step."], + ["78", "capturePaymentStep", "Capture the order’s payment."], + ["83", "updateSubscriptionStep", "Update the subscription’s `last_order_date` and `next_order_date`."] ] ```ts title="src/workflows/create-subscription-order/index.ts" highlights={createSubscriptionOrderWorkflowHighlights} collapsibleLines="1-25" expandMoreLabel="Show Imports" +import { createWorkflow, WorkflowResponse } from "@medusajs/framework/workflows-sdk" import { - createWorkflow, - WorkflowResponse, -} from "@medusajs/framework/workflows-sdk" -import { - useRemoteQueryStep, + useQueryGraphStep, createPaymentSessionsWorkflow, createRemoteLinkStep, - capturePaymentStep, + capturePaymentStep } from "@medusajs/medusa/core-flows" import { - CartWorkflowDTO, -} from "@medusajs/framework/types" -import { - SubscriptionData, + SubscriptionData } from "../../modules/subscription/types" import { authorizePaymentSessionStep, -} from "@medusajs/medusa/core-flows" -import { - createPaymentCollectionsStep, + createPaymentCollectionsStep } from "@medusajs/medusa/core-flows" import createSubscriptionOrderStep from "./steps/create-subscription-order" import updateSubscriptionStep from "./steps/update-subscription" @@ -1814,8 +1805,8 @@ type WorkflowInput = { const createSubscriptionOrderWorkflow = createWorkflow( "create-subscription-order", (input: WorkflowInput) => { - const { cart } = useRemoteQueryStep({ - entry_point: "subscription", + const { data: carts } = useQueryGraphStep({ + entity: "subscription", fields: [ "*", "cart.*", @@ -1828,59 +1819,56 @@ const createSubscriptionOrderWorkflow = createWorkflow( "cart.shipping_methods.tax_lines.*", "cart.shipping_methods.adjustments.*", "cart.payment_collection.*", - "cart.payment_collection.payment_sessions.*", + "cart.payment_collection.payment_sessions.*" ], - variables: { - filters: { - id: [input.subscription.id], - }, + filters: { + id: [input.subscription.id] }, - list: false, - throw_if_key_not_found: true, - }) as { - cart: CartWorkflowDTO - } + options: { + throwIfKeyNotFound: true + } + }) const payment_collection = createPaymentCollectionsStep([{ - region_id: cart.region_id, - currency_code: cart.currency_code, - amount: cart.payment_collection.amount, - metadata: cart.payment_collection.metadata, + region_id: carts[0].region_id, + currency_code: carts[0].currency_code, + amount: carts[0].payment_collection.amount, + metadata: carts[0].payment_collection.metadata }])[0] const paymentSession = createPaymentSessionsWorkflow.runAsStep({ input: { payment_collection_id: payment_collection.id, - provider_id: cart.payment_collection.payment_sessions[0].provider_id, - data: cart.payment_collection.payment_sessions[0].data, - context: cart.payment_collection.payment_sessions[0].context, - }, + provider_id: carts[0].payment_collection.payment_sessions[0].provider_id, + data: carts[0].payment_collection.payment_sessions[0].data, + context: carts[0].payment_collection.payment_sessions[0].context + } }) const payment = authorizePaymentSessionStep({ id: paymentSession.id, - context: paymentSession.context, + context: paymentSession.context }) const { order, linkDefs } = createSubscriptionOrderStep({ subscription: input.subscription, - cart, - payment_collection, + cart: carts[0], + payment_collection }) createRemoteLinkStep(linkDefs) capturePaymentStep({ payment_id: payment.id, - amount: payment.amount, + amount: payment.amount }) updateSubscriptionStep({ - subscription_id: input.subscription.id, + subscription_id: input.subscription.id }) return new WorkflowResponse({ - order, + order }) } ) @@ -1890,7 +1878,7 @@ export default createSubscriptionOrderWorkflow The workflow runs the following steps: -1. `useRemoteQueryStep` to retrieve the details of the cart linked to the subscription. +1. `useQueryGraphStep` to retrieve the details of the cart linked to the subscription. 2. `createPaymentCollectionsStep` to create a payment collection using the same information in the cart. 3. `createPaymentSessionsWorkflow` to create a payment session in the payment collection from the previous step. 4. `authorizePaymentSessionStep` to authorize the payment session created from the first step. diff --git a/www/apps/resources/generated/edit-dates.mjs b/www/apps/resources/generated/edit-dates.mjs index 1b90ee3bf3e8e..f5d862012f082 100644 --- a/www/apps/resources/generated/edit-dates.mjs +++ b/www/apps/resources/generated/edit-dates.mjs @@ -236,7 +236,7 @@ export const generatedEditDates = { "app/architectural-modules/cache/create/page.mdx": "2024-10-16T08:51:35.074Z", "app/admin-widget-injection-zones/page.mdx": "2024-09-30T08:43:53.147Z", "app/architectural-modules/notification/page.mdx": "2024-10-15T12:51:28.735Z", - "app/architectural-modules/event/create/page.mdx": "2024-10-16T08:51:41.334Z", + "app/architectural-modules/event/create/page.mdx": "2024-11-12T11:54:51.583Z", "references/core_flows/Order/functions/core_flows.Order.orderEditUpdateItemQuantityValidationStep/page.mdx": "2024-08-20T00:10:58.913Z", "references/core_flows/Order/functions/core_flows.Order.orderEditUpdateItemQuantityWorkflow/page.mdx": "2024-08-20T00:10:58.949Z", "references/core_flows/Order/functions/core_flows.Order.updateOrderEditItemQuantityValidationStep/page.mdx": "2024-08-20T00:10:59.121Z", @@ -447,9 +447,9 @@ export const generatedEditDates = { "references/fulfillment_models/classes/fulfillment_models.ShippingOptionRule/page.mdx": "2024-10-03T00:12:15.551Z", "references/fulfillment_models/classes/fulfillment_models.ShippingOptionType/page.mdx": "2024-10-03T00:12:15.557Z", "references/fulfillment_models/classes/fulfillment_models.ShippingProfile/page.mdx": "2024-10-03T00:12:15.581Z", - "references/helper_steps/functions/helper_steps.createRemoteLinkStep/page.mdx": "2024-10-03T00:12:16.458Z", - "references/helper_steps/functions/helper_steps.dismissRemoteLinkStep/page.mdx": "2024-10-03T00:12:16.461Z", - "references/helper_steps/functions/helper_steps.emitEventStep/page.mdx": "2024-10-03T00:12:16.464Z", + "references/helper_steps/functions/helper_steps.createRemoteLinkStep/page.mdx": "2024-11-12T16:19:00.137Z", + "references/helper_steps/functions/helper_steps.dismissRemoteLinkStep/page.mdx": "2024-11-12T16:19:00.139Z", + "references/helper_steps/functions/helper_steps.emitEventStep/page.mdx": "2024-11-12T16:19:00.140Z", "references/helper_steps/functions/helper_steps.updateRemoteLinksStep/page.mdx": "2024-10-02T00:12:16.726Z", "references/helper_steps/types/helper_steps.DismissRemoteLinksStepInput/page.mdx": "2024-08-28T00:11:31.042Z", "references/medusa_config/interfaces/medusa_config.AdminOptions/page.mdx": "2024-11-06T21:09:09.666Z", @@ -737,7 +737,7 @@ export const generatedEditDates = { "references/core_flows/types/core_flows.OrderEditRequestWorkflowInput/page.mdx": "2024-10-23T07:15:51.428Z", "references/core_flows/types/core_flows.UpdateOrderTaxLinesWorkflowInput/page.mdx": "2024-10-23T07:15:51.436Z", "references/core_flows/types/core_flows.UpdateTaxLinesWorkflowInput/page.mdx": "2024-11-06T21:09:04.554Z", - "references/helper_steps/functions/helper_steps.useRemoteQueryStep/page.mdx": "2024-10-03T00:12:16.474Z", + "references/helper_steps/functions/helper_steps.useRemoteQueryStep/page.mdx": "2024-11-12T16:19:00.148Z", "references/modules/types/page.mdx": "2024-11-12T09:36:21.248Z", "references/order/IOrderModuleService/methods/order.IOrderModuleService.cancelReturn/page.mdx": "2024-11-06T21:09:11.354Z", "references/order/interfaces/order.CancelOrderClaimDTO/page.mdx": "2024-10-03T00:12:17.706Z", @@ -1776,7 +1776,7 @@ export const generatedEditDates = { "references/dml/Property_Types/methods/dml.Property_Types.json/page.mdx": "2024-10-03T00:12:15.464Z", "references/dml/Property_Types/methods/dml.Property_Types.number/page.mdx": "2024-10-03T00:12:15.459Z", "references/dml/Property_Types/methods/dml.Property_Types.text/page.mdx": "2024-10-03T00:12:15.457Z", - "references/helper_steps/functions/helper_steps.removeRemoteLinkStep/page.mdx": "2024-10-03T00:12:16.466Z", + "references/helper_steps/functions/helper_steps.removeRemoteLinkStep/page.mdx": "2024-11-12T16:19:00.142Z", "references/modules/workflows/page.mdx": "2024-09-30T08:43:53.315Z", "references/search/classes/search.AbstractSearchService/page.mdx": "2024-10-14T09:11:45.913Z", "references/workflows/StepResponse/methods/workflows.StepResponse.permanentFailure/page.mdx": "2024-10-02T00:12:20.683Z", @@ -2716,17 +2716,17 @@ export const generatedEditDates = { "references/js_sdk/auth/Auth/methods/js_sdk.auth.Auth.updateProvider/page.mdx": "2024-10-24T13:48:31.024Z", "references/js_sdk/auth/classes/js_sdk.auth.Auth/page.mdx": "2024-10-22T15:09:53.780Z", "references/js_sdk/modules/js_sdk.admin/page.mdx": "2024-10-22T15:09:52.264Z", - "references/js_sdk/store/Store/properties/js_sdk.store.Store.category/page.mdx": "2024-11-11T10:32:09.787Z", + "references/js_sdk/store/Store/properties/js_sdk.store.Store.category/page.mdx": "2024-11-12T16:19:01.705Z", "references/js_sdk/modules/js_sdk.store/page.mdx": "2024-10-22T15:09:53.787Z", "references/js_sdk/modules/js_sdk.auth/page.mdx": "2024-10-22T15:09:53.779Z", - "references/js_sdk/store/Store/properties/js_sdk.store.Store.collection/page.mdx": "2024-10-25T15:35:30.345Z", - "references/js_sdk/store/Store/properties/js_sdk.store.Store.cart/page.mdx": "2024-11-11T10:32:09.851Z", - "references/js_sdk/store/Store/properties/js_sdk.store.Store.customer/page.mdx": "2024-11-11T10:32:09.935Z", - "references/js_sdk/store/Store/properties/js_sdk.store.Store.fulfillment/page.mdx": "2024-10-25T15:35:30.425Z", - "references/js_sdk/store/Store/properties/js_sdk.store.Store.order/page.mdx": "2024-11-11T10:32:09.891Z", - "references/js_sdk/store/Store/properties/js_sdk.store.Store.payment/page.mdx": "2024-11-11T10:32:09.875Z", - "references/js_sdk/store/Store/properties/js_sdk.store.Store.product/page.mdx": "2024-11-11T10:32:09.803Z", - "references/js_sdk/store/Store/properties/js_sdk.store.Store.region/page.mdx": "2024-11-11T10:32:09.763Z", + "references/js_sdk/store/Store/properties/js_sdk.store.Store.collection/page.mdx": "2024-11-12T16:19:01.699Z", + "references/js_sdk/store/Store/properties/js_sdk.store.Store.cart/page.mdx": "2024-11-12T16:19:01.735Z", + "references/js_sdk/store/Store/properties/js_sdk.store.Store.customer/page.mdx": "2024-11-12T16:19:01.773Z", + "references/js_sdk/store/Store/properties/js_sdk.store.Store.fulfillment/page.mdx": "2024-11-12T16:19:01.739Z", + "references/js_sdk/store/Store/properties/js_sdk.store.Store.order/page.mdx": "2024-11-12T16:19:01.753Z", + "references/js_sdk/store/Store/properties/js_sdk.store.Store.payment/page.mdx": "2024-11-12T16:19:01.748Z", + "references/js_sdk/store/Store/properties/js_sdk.store.Store.product/page.mdx": "2024-11-12T16:19:01.712Z", + "references/js_sdk/store/Store/properties/js_sdk.store.Store.region/page.mdx": "2024-11-12T16:19:01.693Z", "references/js_sdk/store/classes/js_sdk.store.Store/page.mdx": "2024-10-22T15:09:53.788Z", "references/modules/js_sdk/page.mdx": "2024-10-22T15:09:52.263Z", "references/core_flows/Inventory/Steps_Inventory/functions/core_flows.Inventory.Steps_Inventory.validateInventoryDeleteStep/page.mdx": "2024-10-23T07:15:37.028Z", diff --git a/www/apps/resources/generated/sidebar.mjs b/www/apps/resources/generated/sidebar.mjs index 14b1f29357705..b57829992878f 100644 --- a/www/apps/resources/generated/sidebar.mjs +++ b/www/apps/resources/generated/sidebar.mjs @@ -8616,7 +8616,7 @@ export const generatedSidebar = [ "loaded": true, "isPathHref": true, "type": "link", - "path": "/references/js-sdk/admin/cart", + "path": "/references/js-sdk/store/cart", "title": "cart", "children": [] }, @@ -8624,7 +8624,7 @@ export const generatedSidebar = [ "loaded": true, "isPathHref": true, "type": "link", - "path": "/references/js-sdk/admin/category", + "path": "/references/js-sdk/store/category", "title": "category", "children": [] }, @@ -8632,7 +8632,7 @@ export const generatedSidebar = [ "loaded": true, "isPathHref": true, "type": "link", - "path": "/references/js-sdk/admin/collection", + "path": "/references/js-sdk/store/collection", "title": "collection", "children": [] }, @@ -8640,7 +8640,7 @@ export const generatedSidebar = [ "loaded": true, "isPathHref": true, "type": "link", - "path": "/references/js-sdk/admin/customer", + "path": "/references/js-sdk/store/customer", "title": "customer", "children": [] }, @@ -8648,7 +8648,7 @@ export const generatedSidebar = [ "loaded": true, "isPathHref": true, "type": "link", - "path": "/references/js-sdk/admin/fulfillment", + "path": "/references/js-sdk/store/fulfillment", "title": "fulfillment", "children": [] }, @@ -8656,7 +8656,7 @@ export const generatedSidebar = [ "loaded": true, "isPathHref": true, "type": "link", - "path": "/references/js-sdk/admin/order", + "path": "/references/js-sdk/store/order", "title": "order", "children": [] }, @@ -8664,7 +8664,7 @@ export const generatedSidebar = [ "loaded": true, "isPathHref": true, "type": "link", - "path": "/references/js-sdk/admin/payment", + "path": "/references/js-sdk/store/payment", "title": "payment", "children": [] }, @@ -8672,7 +8672,7 @@ export const generatedSidebar = [ "loaded": true, "isPathHref": true, "type": "link", - "path": "/references/js-sdk/admin/product", + "path": "/references/js-sdk/store/product", "title": "product", "children": [] }, @@ -8680,7 +8680,7 @@ export const generatedSidebar = [ "loaded": true, "isPathHref": true, "type": "link", - "path": "/references/js-sdk/admin/region", + "path": "/references/js-sdk/store/region", "title": "region", "children": [] } diff --git a/www/apps/resources/generated/slug-changes.mjs b/www/apps/resources/generated/slug-changes.mjs index 8bd3e8cd1e77f..8aa276b041602 100644 --- a/www/apps/resources/generated/slug-changes.mjs +++ b/www/apps/resources/generated/slug-changes.mjs @@ -4336,47 +4336,47 @@ export const slugChanges = [ }, { "origSlug": "/references/js_sdk/store/Store/properties/js_sdk.store.Store.cart", - "newSlug": "/references/js-sdk/admin/cart", + "newSlug": "/references/js-sdk/store/cart", "filePath": "/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.cart/page.mdx" }, { "origSlug": "/references/js_sdk/store/Store/properties/js_sdk.store.Store.category", - "newSlug": "/references/js-sdk/admin/category", + "newSlug": "/references/js-sdk/store/category", "filePath": "/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.category/page.mdx" }, { "origSlug": "/references/js_sdk/store/Store/properties/js_sdk.store.Store.collection", - "newSlug": "/references/js-sdk/admin/collection", + "newSlug": "/references/js-sdk/store/collection", "filePath": "/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.collection/page.mdx" }, { "origSlug": "/references/js_sdk/store/Store/properties/js_sdk.store.Store.customer", - "newSlug": "/references/js-sdk/admin/customer", + "newSlug": "/references/js-sdk/store/customer", "filePath": "/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.customer/page.mdx" }, { "origSlug": "/references/js_sdk/store/Store/properties/js_sdk.store.Store.fulfillment", - "newSlug": "/references/js-sdk/admin/fulfillment", + "newSlug": "/references/js-sdk/store/fulfillment", "filePath": "/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.fulfillment/page.mdx" }, { "origSlug": "/references/js_sdk/store/Store/properties/js_sdk.store.Store.order", - "newSlug": "/references/js-sdk/admin/order", + "newSlug": "/references/js-sdk/store/order", "filePath": "/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.order/page.mdx" }, { "origSlug": "/references/js_sdk/store/Store/properties/js_sdk.store.Store.payment", - "newSlug": "/references/js-sdk/admin/payment", + "newSlug": "/references/js-sdk/store/payment", "filePath": "/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.payment/page.mdx" }, { "origSlug": "/references/js_sdk/store/Store/properties/js_sdk.store.Store.product", - "newSlug": "/references/js-sdk/admin/product", + "newSlug": "/references/js-sdk/store/product", "filePath": "/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.product/page.mdx" }, { "origSlug": "/references/js_sdk/store/Store/properties/js_sdk.store.Store.region", - "newSlug": "/references/js-sdk/admin/region", + "newSlug": "/references/js-sdk/store/region", "filePath": "/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.region/page.mdx" }, { diff --git a/www/apps/resources/references/helper_steps/functions/helper_steps.createRemoteLinkStep/page.mdx b/www/apps/resources/references/helper_steps/functions/helper_steps.createRemoteLinkStep/page.mdx index 465f9c0334f05..5560f0ca1237c 100644 --- a/www/apps/resources/references/helper_steps/functions/helper_steps.createRemoteLinkStep/page.mdx +++ b/www/apps/resources/references/helper_steps/functions/helper_steps.createRemoteLinkStep/page.mdx @@ -9,6 +9,10 @@ import { TypeList } from "docs-ui" This documentation provides a reference to the `createRemoteLinkStep` step. It belongs to the `@medusajs/medusa/core-flows` package. +This step creates remote links between two records of linked data models. + +Learn more in the [Remote Link documentation.](https://docs.medusajs.com/advanced-development/modules/remote-link#create-link). + ## Example ```ts diff --git a/www/apps/resources/references/helper_steps/functions/helper_steps.dismissRemoteLinkStep/page.mdx b/www/apps/resources/references/helper_steps/functions/helper_steps.dismissRemoteLinkStep/page.mdx index 6203d92aa1dfa..15cd626a6bc15 100644 --- a/www/apps/resources/references/helper_steps/functions/helper_steps.dismissRemoteLinkStep/page.mdx +++ b/www/apps/resources/references/helper_steps/functions/helper_steps.dismissRemoteLinkStep/page.mdx @@ -9,6 +9,10 @@ import { TypeList } from "docs-ui" This documentation provides a reference to the `dismissRemoteLinkStep` step. It belongs to the `@medusajs/medusa/core-flows` package. +This step removes remote links between two records of linked data models. + +Learn more in the [Remote Link documentation.](https://docs.medusajs.com/advanced-development/modules/remote-link#dismiss-link). + ## Example ```ts diff --git a/www/apps/resources/references/helper_steps/functions/helper_steps.emitEventStep/page.mdx b/www/apps/resources/references/helper_steps/functions/helper_steps.emitEventStep/page.mdx index 9c0b0b6f41387..b775b8710acab 100644 --- a/www/apps/resources/references/helper_steps/functions/helper_steps.emitEventStep/page.mdx +++ b/www/apps/resources/references/helper_steps/functions/helper_steps.emitEventStep/page.mdx @@ -9,6 +9,8 @@ import { TypeList } from "docs-ui" This documentation provides a reference to the `emitEventStep` step. It belongs to the `@medusajs/medusa/core-flows` package. +Emit an event. + ## Example ```ts diff --git a/www/apps/resources/references/helper_steps/functions/helper_steps.removeRemoteLinkStep/page.mdx b/www/apps/resources/references/helper_steps/functions/helper_steps.removeRemoteLinkStep/page.mdx index 4d1322ccb6d49..b385a7a745598 100644 --- a/www/apps/resources/references/helper_steps/functions/helper_steps.removeRemoteLinkStep/page.mdx +++ b/www/apps/resources/references/helper_steps/functions/helper_steps.removeRemoteLinkStep/page.mdx @@ -9,6 +9,10 @@ import { TypeList } from "docs-ui" This documentation provides a reference to the `removeRemoteLinkStep` step. It belongs to the `@medusajs/medusa/core-flows` package. +This step deletes linked records of a record. + +Learn more in the [Remote Link documentation](https://docs.medusajs.com/advanced-development/modules/remote-link#cascade-delete-linked-records) + ## Example ```ts diff --git a/www/apps/resources/references/helper_steps/functions/helper_steps.useRemoteQueryStep/page.mdx b/www/apps/resources/references/helper_steps/functions/helper_steps.useRemoteQueryStep/page.mdx index af4277af7aae0..e540a8fbd0abb 100644 --- a/www/apps/resources/references/helper_steps/functions/helper_steps.useRemoteQueryStep/page.mdx +++ b/www/apps/resources/references/helper_steps/functions/helper_steps.useRemoteQueryStep/page.mdx @@ -9,6 +9,10 @@ import { TypeList } from "docs-ui" This documentation provides a reference to the `useRemoteQueryStep` step. It belongs to the `@medusajs/medusa/core-flows` package. +This step fetches data across modules using the remote query. + +Learn more in the [Remote Query documentation](https://docs.medusajs.com/advanced-development/modules/remote-query). + ## Example To retrieve a list of records of a data model: diff --git a/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.cart/page.mdx b/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.cart/page.mdx index 6b29b7b90a750..1880edf2df14f 100644 --- a/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.cart/page.mdx +++ b/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.cart/page.mdx @@ -1,5 +1,5 @@ --- -slug: /references/js-sdk/admin/cart +slug: /references/js-sdk/store/cart sidebar_label: cart --- diff --git a/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.category/page.mdx b/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.category/page.mdx index 6dc2b9c991783..d9352bb8227c4 100644 --- a/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.category/page.mdx +++ b/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.category/page.mdx @@ -1,5 +1,5 @@ --- -slug: /references/js-sdk/admin/category +slug: /references/js-sdk/store/category sidebar_label: category --- diff --git a/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.collection/page.mdx b/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.collection/page.mdx index 0019fcc3a8af4..330404669f22c 100644 --- a/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.collection/page.mdx +++ b/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.collection/page.mdx @@ -1,5 +1,5 @@ --- -slug: /references/js-sdk/admin/collection +slug: /references/js-sdk/store/collection sidebar_label: collection --- diff --git a/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.customer/page.mdx b/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.customer/page.mdx index 1940cc0a0d02f..3f0cceac12413 100644 --- a/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.customer/page.mdx +++ b/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.customer/page.mdx @@ -1,5 +1,5 @@ --- -slug: /references/js-sdk/admin/customer +slug: /references/js-sdk/store/customer sidebar_label: customer --- diff --git a/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.fulfillment/page.mdx b/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.fulfillment/page.mdx index 8942eed630d18..a88a99d0cab5c 100644 --- a/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.fulfillment/page.mdx +++ b/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.fulfillment/page.mdx @@ -1,5 +1,5 @@ --- -slug: /references/js-sdk/admin/fulfillment +slug: /references/js-sdk/store/fulfillment sidebar_label: fulfillment --- diff --git a/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.order/page.mdx b/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.order/page.mdx index ab006d5407b45..da592e42e4a40 100644 --- a/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.order/page.mdx +++ b/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.order/page.mdx @@ -1,5 +1,5 @@ --- -slug: /references/js-sdk/admin/order +slug: /references/js-sdk/store/order sidebar_label: order --- diff --git a/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.payment/page.mdx b/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.payment/page.mdx index d8afe90fc23a4..1ec13b86a9cd0 100644 --- a/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.payment/page.mdx +++ b/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.payment/page.mdx @@ -1,5 +1,5 @@ --- -slug: /references/js-sdk/admin/payment +slug: /references/js-sdk/store/payment sidebar_label: payment --- diff --git a/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.product/page.mdx b/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.product/page.mdx index d5ab9232eeb0e..7e40f55b59e1f 100644 --- a/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.product/page.mdx +++ b/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.product/page.mdx @@ -1,5 +1,5 @@ --- -slug: /references/js-sdk/admin/product +slug: /references/js-sdk/store/product sidebar_label: product --- diff --git a/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.region/page.mdx b/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.region/page.mdx index 3d3e1c0ac7f5d..843ff83b57c09 100644 --- a/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.region/page.mdx +++ b/www/apps/resources/references/js_sdk/store/Store/properties/js_sdk.store.Store.region/page.mdx @@ -1,5 +1,5 @@ --- -slug: /references/js-sdk/admin/region +slug: /references/js-sdk/store/region sidebar_label: region --- diff --git a/www/packages/docs-ui/src/components/CodeBlock/Header/index.tsx b/www/packages/docs-ui/src/components/CodeBlock/Header/index.tsx index b6be62c9d8511..1121c46c1e8a7 100644 --- a/www/packages/docs-ui/src/components/CodeBlock/Header/index.tsx +++ b/www/packages/docs-ui/src/components/CodeBlock/Header/index.tsx @@ -17,6 +17,7 @@ type CodeBlockHeaderProps = { title?: string blockStyle?: CodeBlockStyle actionsProps: CodeBlockActionsProps + hideActions?: boolean } & CodeBlockHeaderMeta export const CodeBlockHeader = ({ @@ -25,6 +26,7 @@ export const CodeBlockHeader = ({ badgeLabel, actionsProps, badgeColor, + hideActions = false }: CodeBlockHeaderProps) => { const { colorMode } = useColorMode() @@ -54,7 +56,7 @@ export const CodeBlockHeader = ({ )} - + {!hideActions && } ) } diff --git a/www/packages/docs-ui/src/components/CodeBlock/index.tsx b/www/packages/docs-ui/src/components/CodeBlock/index.tsx index 8d8befeab7698..eefce95c1d914 100644 --- a/www/packages/docs-ui/src/components/CodeBlock/index.tsx +++ b/www/packages/docs-ui/src/components/CodeBlock/index.tsx @@ -363,6 +363,7 @@ export const CodeBlock = ({ ...actionsProps, inHeader: true, }} + hideActions={hasTabs} /> )}
comment}} +{{{signatureComment}}} {{/if}} diff --git a/www/utils/packages/utils/src/step-utils.ts b/www/utils/packages/utils/src/step-utils.ts index 38a0ac31b77cc..eda89c6159465 100644 --- a/www/utils/packages/utils/src/step-utils.ts +++ b/www/utils/packages/utils/src/step-utils.ts @@ -3,9 +3,16 @@ import { ArrayType, SignatureReflection, SomeType, UnionType } from "typedoc" const disallowedIntrinsicTypeNames = ["unknown", "void", "any", "never"] export function isWorkflowStep(reflection: SignatureReflection): boolean { - return ( - reflection.parent?.children?.some((child) => child.name === "__step__") || - false + if (reflection.parent?.children?.some((child) => child.name === "__step__")) { + return true + } + if (reflection.type?.type !== "intersection") { + return false + } + return reflection.type.types.some( + (refType) => + refType.type === "reference" && + refType.name === "StepFunctionReturnConfig" ) }