From 41e125dadd77d28148c39cb06c2f0ed95fea0a2a Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Tue, 26 Nov 2024 18:53:28 +0200 Subject: [PATCH] docs: revise workflows docs (#10294) --- .../book/app/learn/basics/workflows/page.mdx | 148 +++++---- www/apps/book/generated/edit-dates.mjs | 280 ++++++++++++------ 2 files changed, 270 insertions(+), 158 deletions(-) diff --git a/www/apps/book/app/learn/basics/workflows/page.mdx b/www/apps/book/app/learn/basics/workflows/page.mdx index f988a50ac0..66912e11db 100644 --- a/www/apps/book/app/learn/basics/workflows/page.mdx +++ b/www/apps/book/app/learn/basics/workflows/page.mdx @@ -10,11 +10,17 @@ In this chapter, you’ll learn about workflows and how to define and execute th ## What is a Workflow? -A workflow is a series of queries and actions that complete a task. +In other commerce platforms, it's difficult to implement commerce features where a single task performs operations on core and custom data models, or connects to third-party systems. It's also almost impossible to maintain their execution, handle errors gracefully, and have more control over how these tasks are executed. -You construct a workflow similar to how you create a JavaScript function, but unlike regular functions, a workflow creates an internal representation of your steps. +Medusa solves this major pain point with workflows. A workflow is a series of queries and actions, called steps, that complete a task. You construct a workflow similar to how you create a JavaScript function. -By using a workflow, you can track its execution's progress, provide roll-back logic for each step to mitigate data inconsistency when errors occur, automatically retry failing steps, and do much more, as explained in later chapters. +However, unlike regular functions, workflows: + +- Create an internal representation of your steps, allowing you to track them and their progress. +- Support defining roll-back logic for each step, so that you can handle errors gracefully and your data remain consistent across systems. +- Perform long actions asynchronously, giving you control over when a step starts and finishes. + +You implement all custom flows within workflows, then execute them from [API routes](../api-routes/page.mdx), [subscribers](../events-and-subscribers/page.mdx), and [scheduled jobs](../scheduled-jobs/page.mdx). --- @@ -26,35 +32,58 @@ A workflow is made of a series of steps. A step is created using the `createStep Create the file `src/workflows/hello-world.ts` with the following content: -```ts title="src/workflows/hello-world.ts" +export const step1Highlights = [ + ["4", `"step-1"`, "The step's unique name."], + ["6", "`Hello from step one!`", "The step's returned data."] +] + +```ts title="src/workflows/hello-world.ts" highlights={step1Highlights} import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk" -const step1 = createStep("step-1", async () => { - return new StepResponse(`Hello from step one!`) -}) +const step1 = createStep( + "step-1", + async () => { + return new StepResponse(`Hello from step one!`) + } +) ``` -This creates one step that returns a hello message. +The `createStep` function accepts the step's unique name as a first parameter, and the step's function as a second parameter. -Steps can accept input parameters. +Steps must return an instance of `StepResponse`, whose parameter is the data to return to the workflow executing the step. -For example, add the following to `src/workflows/hello-world.ts`: +Steps can accept input parameters. For example, add the following to `src/workflows/hello-world.ts`: -```ts title="src/workflows/hello-world.ts" +export const step2Highlights = [ + ["7", "name", "Recieve step input as a parameter."] +] + +```ts title="src/workflows/hello-world.ts" highlights={step2Highlights} type WorkflowInput = { name: string } -const step2 = createStep("step-2", async ({ name }: WorkflowInput) => { - return new StepResponse(`Hello ${name} from step two!`) -}) +const step2 = createStep( + "step-2", + async ({ name }: WorkflowInput) => { + return new StepResponse(`Hello ${name} from step two!`) + } +) ``` +This adds another step whose function accepts as a parameter an object with a `name` property. + ### 2. Create a Workflow Next, add the following to the same file to create the workflow using the `createWorkflow` function: -```ts title="src/workflows/hello-world.ts" +export const workflowHighlights = [ + ["10", `"hello-world"`, "The workflow's unique name."], + ["11", "input", "The workflow's input is passed as a parameter."], + ["16", "WorkflowResponse", "The workflow returns an instance of WorkflowResponse."] +] + +```ts title="src/workflows/hello-world.ts" highlights={workflowHighlights} import { // other imports... createWorkflow, @@ -71,7 +100,7 @@ const myWorkflow = createWorkflow( const str2 = step2(input) return new WorkflowResponse({ - message: str1, + message: str2, }) } ) @@ -79,19 +108,19 @@ const myWorkflow = createWorkflow( export default myWorkflow ``` -This creates a `hello-world` workflow. When you create a workflow, it’s constructed but not executed yet. +The `createWorkflow` function accepts the workflow's unique name as a first parameter, and the workflow's function as a second parameter. The workflow can accept input which is passed as a parameter to the function. -The workflow must return an instance of `WorkflowResponse`, whose first parameter is returned to workflow executors. +The workflow must return an instance of `WorkflowResponse`, whose parameter is returned to workflow executors. ### 3. Execute the Workflow -You can execute a workflow from different resources within Medusa. +You can execute a workflow from different customizations: -- Use API routes to execute the workflow in response to an API request or a webhook. -- Use subscribers to execute a workflow when an event is triggered. -- Use scheduled jobs to execute a workflow on a regular schedule. +- Execute in an API route to expose the workflow's functionalities to clients. +- Execute in a subscriber to use the workflow's functionalities when a commerce operation is performed. +- Execute in a scheduled job to run the workflow's functionalities automatically at a specified repeated interval. -To execute the workflow, invoke it passing the Medusa container as a parameter. Then, use its `run` method: +To execute the workflow, invoke it passing the [Medusa container](../medusa-container/page.mdx) as a parameter. Then, use its `run` method: @@ -110,7 +139,7 @@ To execute the workflow, invoke it passing the Medusa container as a parameter. const { result } = await myWorkflow(req.scope) .run({ input: { - name: req.query.name as string, + name: "John", }, }) @@ -121,30 +150,21 @@ To execute the workflow, invoke it passing the Medusa container as a parameter. - ```ts title="src/subscribers/customer-created.ts" highlights={[["20"], ["21"], ["22"], ["23"], ["24"], ["25"]]} collapsibleLines="1-9" expandButtonLabel="Show Imports" + ```ts title="src/subscribers/customer-created.ts" highlights={[["11"], ["12"], ["13"], ["14"], ["15"], ["16"]]} collapsibleLines="1-6" expandButtonLabel="Show Imports" import { type SubscriberConfig, type SubscriberArgs, } from "@medusajs/framework" import myWorkflow from "../workflows/hello-world" - import { Modules } from "@medusajs/framework/utils" - import { IUserModuleService } from "@medusajs/framework/types" export default async function handleCustomerCreate({ event: { data }, container, }: SubscriberArgs<{ id: string }>) { - const userId = data.id - const userModuleService: IUserModuleService = container.resolve( - Modules.USER - ) - - const user = await userModuleService.retrieveUser(userId) - const { result } = await myWorkflow(container) .run({ input: { - name: user.first_name, + name: "John", }, }) @@ -152,7 +172,7 @@ To execute the workflow, invoke it passing the Medusa container as a parameter. } export const config: SubscriberConfig = { - event: "user.created", + event: "order.placed", } ``` @@ -193,39 +213,30 @@ To test out your workflow, start your Medusa application: npm run dev ``` -Then, send a `GET` request to `/workflow`: +Then, if you added the API route above, send a `GET` request to `/workflow`: ```bash -curl http://localhost:9000/workflow?name=john +curl http://localhost:9000/workflow ``` You’ll receive the following response: -```json +```json title="Example Response" { - "message": "Hello from step one!" + "message": "Hello John from step two!" } ``` --- -## When to Use Workflows +## Access Medusa Container in Workflow Steps - +A step receives an object as a second parameter with configurations and context-related properties. One of these properties is the `container` property, which is the [Medusa container](../medusa-container/page.mdx) to allow you to resolve framework and commerce tools in your application. -You're implementing a custom feature exposed by an API route, or used in subscribers or scheduled jobs. - - - ---- - -## Resolve Resources - -Each step in the workflow receives as a second parameter a `context` object. The object holds a `container` property which is the Medusa container. Use it to resolve other resources, such as services, of your Medusa application. - -For example: +For example, consider you want to implement a workflow that returns the total products in your application. Create the file `src/workflows/product-count.ts` with the following content: export const highlights = [ + ["11", "container", "Receive the Medusa container as a parameter"], ["12", "resolve", "Resolve the Product Module's main service."], [ "12", @@ -241,22 +252,23 @@ import { createWorkflow, WorkflowResponse, } from "@medusajs/framework/workflows-sdk" -import { IProductModuleService } from "@medusajs/framework/types" import { Modules } from "@medusajs/framework/utils" -const step1 = createStep("step-1", async (_, context) => { - const productModuleService: IProductModuleService = - context.container.resolve(Modules.PRODUCT) +const getProductCountStep = createStep( + "get-product-count", + async (_, { container }) => { + const productModuleService = container.resolve(Modules.PRODUCT) - const [, count] = await productModuleService.listAndCountProducts() + const [, count] = await productModuleService.listAndCountProducts() - return new StepResponse(count) -}) + return new StepResponse(count) + } +) -const myWorkflow = createWorkflow( +const productCountWorkflow = createWorkflow( "product-count", function () { - const count = step1() + const count = getProductCountStep() return new WorkflowResponse({ count, @@ -264,7 +276,15 @@ const myWorkflow = createWorkflow( } ) -export default myWorkflow +export default productCountWorkflow ``` -In `step1`, you resolve the Product Module's main service and use it to retrieve the product count. +In `getProductCountStep`, you use the `container` to resolve the Product Module's main service. Then, you use its `listAndCountProducts` method to retrieve the total count of products and return it in the step's response. You then execute this step in the `productCountWorkflow`. + +You can now execute this workflow in a custom API route, scheduled job, or subscriber to get the total count of products. + + + +Find a full list of the registered resources in the Medusa container and their registration key in [this reference](!resources!/resources/medusa-container-resources). You can use these resources in your custom workflows. + + \ No newline at end of file diff --git a/www/apps/book/generated/edit-dates.mjs b/www/apps/book/generated/edit-dates.mjs index 7f72f7f20c..607cdf065f 100644 --- a/www/apps/book/generated/edit-dates.mjs +++ b/www/apps/book/generated/edit-dates.mjs @@ -1,120 +1,212 @@ export const generatedEditDates = { "app/learn/basics/scheduled-jobs/page.mdx": "2024-11-26T11:50:10.302Z", - "app/learn/basics/workflows/page.mdx": "2024-09-30T08:43:53.132Z", + "app/learn/basics/workflows/page.mdx": "2024-11-26T14:12:10.031Z", "app/learn/deployment/page.mdx": "2024-11-25T14:32:44.949Z", "app/learn/page.mdx": "2024-09-03T07:09:09.034Z", "app/learn/basics/commerce-modules/page.mdx": "2024-11-21T16:24:19.136Z", - "app/learn/advanced-development/workflows/retry-failed-steps/page.mdx": "2024-09-30T08:43:53.130Z", - "app/learn/advanced-development/workflows/workflow-hooks/page.mdx": "2024-09-30T08:43:53.131Z", + "app/learn/advanced-development/workflows/retry-failed-steps/page.mdx": + "2024-09-30T08:43:53.130Z", + "app/learn/advanced-development/workflows/workflow-hooks/page.mdx": + "2024-09-30T08:43:53.131Z", "app/learn/cheatsheet/page.mdx": "2024-07-11T13:53:40+03:00", - "app/learn/debugging-and-testing/logging/page.mdx": "2024-09-30T08:43:53.135Z", + "app/learn/debugging-and-testing/logging/page.mdx": + "2024-09-30T08:43:53.135Z", "app/learn/more-resources/page.mdx": "2024-07-04T17:26:03+03:00", "app/learn/storefront-development/page.mdx": "2024-09-11T10:58:59.290Z", - "app/learn/storefront-development/nextjs-starter/page.mdx": "2024-07-04T17:26:03+03:00", + "app/learn/storefront-development/nextjs-starter/page.mdx": + "2024-07-04T17:26:03+03:00", "app/learn/basics/page.mdx": "2024-09-03T07:11:06.879Z", "app/learn/basics/admin-customizations/page.mdx": "2024-10-07T12:41:39.218Z", - "app/learn/advanced-development/workflows/workflow-timeout/page.mdx": "2024-09-30T08:43:53.131Z", - "app/learn/advanced-development/workflows/parallel-steps/page.mdx": "2024-09-30T08:43:53.130Z", + "app/learn/advanced-development/workflows/workflow-timeout/page.mdx": + "2024-09-30T08:43:53.131Z", + "app/learn/advanced-development/workflows/parallel-steps/page.mdx": + "2024-09-30T08:43:53.130Z", "app/learn/advanced-development/page.mdx": "2024-07-04T17:26:03+03:00", "app/learn/first-customizations/page.mdx": "2024-09-11T10:48:42.374Z", "app/learn/debugging-and-testing/page.mdx": "2024-05-03T17:36:38+03:00", "app/learn/basics/medusa-container/page.mdx": "2024-11-21T08:53:18.181Z", - "app/learn/basics/project-directories-files/page.mdx": "2024-10-03T12:46:52.762Z", + "app/learn/basics/project-directories-files/page.mdx": + "2024-10-03T12:46:52.762Z", "app/learn/basics/api-routes/page.mdx": "2024-09-11T10:48:31.777Z", - "app/learn/basics/modules-directory-structure/page.mdx": "2024-10-03T13:03:35.957Z", - "app/learn/advanced-development/workflows/access-workflow-errors/page.mdx": "2024-09-18T12:54:04.695Z", - "app/learn/basics/events-and-subscribers/page.mdx": "2024-11-22T12:19:32.916Z", - "app/learn/advanced-development/modules/container/page.mdx": "2024-11-21T08:59:18.707Z", - "app/learn/advanced-development/workflows/execute-another-workflow/page.mdx": "2024-09-30T08:43:53.129Z", + "app/learn/basics/modules-directory-structure/page.mdx": + "2024-10-03T13:03:35.957Z", + "app/learn/advanced-development/workflows/access-workflow-errors/page.mdx": + "2024-09-18T12:54:04.695Z", + "app/learn/basics/events-and-subscribers/page.mdx": + "2024-11-22T12:19:32.916Z", + "app/learn/advanced-development/modules/container/page.mdx": + "2024-11-21T08:59:18.707Z", + "app/learn/advanced-development/workflows/execute-another-workflow/page.mdx": + "2024-09-30T08:43:53.129Z", "app/learn/basics/loaders/page.mdx": "2024-11-22T10:51:32.931Z", - "app/learn/advanced-development/admin/widgets/page.mdx": "2024-10-07T12:51:09.969Z", - "app/learn/advanced-development/data-models/page.mdx": "2024-09-19T07:26:43.535Z", - "app/learn/advanced-development/modules/remote-link/page.mdx": "2024-09-30T08:43:53.127Z", - "app/learn/advanced-development/api-routes/protected-routes/page.mdx": "2024-09-30T08:43:53.121Z", - "app/learn/advanced-development/workflows/add-workflow-hook/page.mdx": "2024-09-30T08:43:53.128Z", - "app/learn/advanced-development/events-and-subscribers/data-payload/page.mdx": "2024-07-16T17:12:05+01:00", - "app/learn/advanced-development/data-models/default-properties/page.mdx": "2024-09-19T07:32:06.118Z", - "app/learn/advanced-development/workflows/advanced-example/page.mdx": "2024-09-11T10:46:59.975Z", - "app/learn/advanced-development/events-and-subscribers/emit-event/page.mdx": "2024-11-11T15:17:58.045Z", - "app/learn/advanced-development/workflows/conditions/page.mdx": "2024-09-30T08:43:53.128Z", - "app/learn/advanced-development/modules/module-link-directions/page.mdx": "2024-07-24T09:16:01+02:00", + "app/learn/advanced-development/admin/widgets/page.mdx": + "2024-10-07T12:51:09.969Z", + "app/learn/advanced-development/data-models/page.mdx": + "2024-09-19T07:26:43.535Z", + "app/learn/advanced-development/modules/remote-link/page.mdx": + "2024-09-30T08:43:53.127Z", + "app/learn/advanced-development/api-routes/protected-routes/page.mdx": + "2024-09-30T08:43:53.121Z", + "app/learn/advanced-development/workflows/add-workflow-hook/page.mdx": + "2024-09-30T08:43:53.128Z", + "app/learn/advanced-development/events-and-subscribers/data-payload/page.mdx": + "2024-07-16T17:12:05+01:00", + "app/learn/advanced-development/data-models/default-properties/page.mdx": + "2024-09-19T07:32:06.118Z", + "app/learn/advanced-development/workflows/advanced-example/page.mdx": + "2024-09-11T10:46:59.975Z", + "app/learn/advanced-development/events-and-subscribers/emit-event/page.mdx": + "2024-11-11T15:17:58.045Z", + "app/learn/advanced-development/workflows/conditions/page.mdx": + "2024-09-30T08:43:53.128Z", + "app/learn/advanced-development/modules/module-link-directions/page.mdx": + "2024-07-24T09:16:01+02:00", "app/learn/advanced-development/admin/page.mdx": "2024-10-07T12:39:13.178Z", - "app/learn/advanced-development/workflows/long-running-workflow/page.mdx": "2024-09-30T08:43:53.129Z", - "app/learn/advanced-development/workflows/constructor-constraints/page.mdx": "2024-11-14T16:13:19.234Z", - "app/learn/advanced-development/data-models/write-migration/page.mdx": "2024-07-15T17:46:10+02:00", - "app/learn/advanced-development/data-models/manage-relationships/page.mdx": "2024-09-10T11:39:51.167Z", - "app/learn/advanced-development/modules/remote-query/page.mdx": "2024-07-21T21:20:24+02:00", - "app/learn/advanced-development/modules/options/page.mdx": "2024-10-16T08:49:27.162Z", - "app/learn/advanced-development/data-models/relationships/page.mdx": "2024-09-30T08:43:53.125Z", - "app/learn/advanced-development/workflows/compensation-function/page.mdx": "2024-09-30T08:43:53.128Z", - "app/learn/advanced-development/modules/service-factory/page.mdx": "2024-09-30T08:43:53.127Z", - "app/learn/advanced-development/data-models/primary-key/page.mdx": "2024-09-30T08:43:53.123Z", - "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-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", - "app/learn/advanced-development/admin/ui-routes/page.mdx": "2024-11-14T15:29:22.901Z", - "app/learn/advanced-development/api-routes/middlewares/page.mdx": "2024-09-11T10:45:31.861Z", - "app/learn/advanced-development/modules/isolation/page.mdx": "2024-07-04T17:26:03+03:00", - "app/learn/advanced-development/data-models/configure-properties/page.mdx": "2024-09-30T08:43:53.122Z", - "app/learn/advanced-development/data-models/index/page.mdx": "2024-09-30T08:43:53.122Z", - "app/learn/advanced-development/custom-cli-scripts/page.mdx": "2024-09-30T08:43:53.122Z", - "app/learn/advanced-development/data-models/property-types/page.mdx": "2024-09-30T08:43:53.124Z", - "app/learn/debugging-and-testing/testing-tools/integration-tests/api-routes/page.mdx": "2024-09-30T08:43:53.136Z", - "app/learn/debugging-and-testing/testing-tools/integration-tests/page.mdx": "2024-09-10T11:39:51.170Z", - "app/learn/debugging-and-testing/testing-tools/integration-tests/workflows/page.mdx": "2024-09-30T08:43:53.139Z", - "app/learn/debugging-and-testing/testing-tools/page.mdx": "2024-09-30T08:43:53.139Z", - "app/learn/debugging-and-testing/testing-tools/unit-tests/module-example/page.mdx": "2024-09-02T11:04:27.232Z", - "app/learn/debugging-and-testing/testing-tools/unit-tests/page.mdx": "2024-09-02T11:03:26.997Z", - "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-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", - "app/learn/debugging-and-testing/testing-tools/modules-tests/page.mdx": "2024-10-16T08:50:23.232Z", - "app/learn/advanced-development/module-links/custom-columns/page.mdx": "2024-11-19T15:05:59.471Z", - "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-11-19T15:25:01.149Z", - "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", + "app/learn/advanced-development/workflows/long-running-workflow/page.mdx": + "2024-09-30T08:43:53.129Z", + "app/learn/advanced-development/workflows/constructor-constraints/page.mdx": + "2024-11-14T16:13:19.234Z", + "app/learn/advanced-development/data-models/write-migration/page.mdx": + "2024-07-15T17:46:10+02:00", + "app/learn/advanced-development/data-models/manage-relationships/page.mdx": + "2024-09-10T11:39:51.167Z", + "app/learn/advanced-development/modules/remote-query/page.mdx": + "2024-07-21T21:20:24+02:00", + "app/learn/advanced-development/modules/options/page.mdx": + "2024-10-16T08:49:27.162Z", + "app/learn/advanced-development/data-models/relationships/page.mdx": + "2024-09-30T08:43:53.125Z", + "app/learn/advanced-development/workflows/compensation-function/page.mdx": + "2024-09-30T08:43:53.128Z", + "app/learn/advanced-development/modules/service-factory/page.mdx": + "2024-09-30T08:43:53.127Z", + "app/learn/advanced-development/data-models/primary-key/page.mdx": + "2024-09-30T08:43:53.123Z", + "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-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", + "app/learn/advanced-development/admin/ui-routes/page.mdx": + "2024-11-14T15:29:22.901Z", + "app/learn/advanced-development/api-routes/middlewares/page.mdx": + "2024-09-11T10:45:31.861Z", + "app/learn/advanced-development/modules/isolation/page.mdx": + "2024-07-04T17:26:03+03:00", + "app/learn/advanced-development/data-models/configure-properties/page.mdx": + "2024-09-30T08:43:53.122Z", + "app/learn/advanced-development/data-models/index/page.mdx": + "2024-09-30T08:43:53.122Z", + "app/learn/advanced-development/custom-cli-scripts/page.mdx": + "2024-09-30T08:43:53.122Z", + "app/learn/advanced-development/data-models/property-types/page.mdx": + "2024-09-30T08:43:53.124Z", + "app/learn/debugging-and-testing/testing-tools/integration-tests/api-routes/page.mdx": + "2024-09-30T08:43:53.136Z", + "app/learn/debugging-and-testing/testing-tools/integration-tests/page.mdx": + "2024-09-10T11:39:51.170Z", + "app/learn/debugging-and-testing/testing-tools/integration-tests/workflows/page.mdx": + "2024-09-30T08:43:53.139Z", + "app/learn/debugging-and-testing/testing-tools/page.mdx": + "2024-09-30T08:43:53.139Z", + "app/learn/debugging-and-testing/testing-tools/unit-tests/module-example/page.mdx": + "2024-09-02T11:04:27.232Z", + "app/learn/debugging-and-testing/testing-tools/unit-tests/page.mdx": + "2024-09-02T11:03:26.997Z", + "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-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", + "app/learn/debugging-and-testing/testing-tools/modules-tests/page.mdx": + "2024-10-16T08:50:23.232Z", + "app/learn/advanced-development/module-links/custom-columns/page.mdx": + "2024-11-19T15:05:59.471Z", + "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-11-19T15:25:01.149Z", + "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", "app/learn/advanced-development/modules/page.mdx": "2024-09-16T14:33:48.217Z", - "app/learn/debugging-and-testing/instrumentation/page.mdx": "2024-09-17T08:53:15.910Z", - "app/learn/advanced-development/api-routes/additional-data/page.mdx": "2024-09-30T08:43:53.120Z", - "app/learn/advanced-development/workflows/page.mdx": "2024-09-18T08:00:57.364Z", - "app/learn/advanced-development/workflows/variable-manipulation/page.mdx": "2024-11-14T16:11:24.538Z", - "app/learn/customization/custom-features/api-route/page.mdx": "2024-09-12T12:42:34.201Z", - "app/learn/customization/custom-features/module/page.mdx": "2024-10-16T08:49:44.676Z", - "app/learn/customization/custom-features/workflow/page.mdx": "2024-09-30T08:43:53.133Z", - "app/learn/customization/extend-models/create-links/page.mdx": "2024-09-30T08:43:53.133Z", - "app/learn/customization/extend-models/extend-create-product/page.mdx": "2024-09-30T08:43:53.134Z", - "app/learn/customization/custom-features/page.mdx": "2024-09-12T11:18:13.271Z", - "app/learn/customization/customize-admin/page.mdx": "2024-09-12T12:25:29.853Z", - "app/learn/customization/customize-admin/route/page.mdx": "2024-10-07T12:43:11.335Z", - "app/learn/customization/customize-admin/widget/page.mdx": "2024-10-07T12:44:24.538Z", - "app/learn/customization/extend-models/define-link/page.mdx": "2024-09-30T08:43:53.134Z", + "app/learn/debugging-and-testing/instrumentation/page.mdx": + "2024-09-17T08:53:15.910Z", + "app/learn/advanced-development/api-routes/additional-data/page.mdx": + "2024-09-30T08:43:53.120Z", + "app/learn/advanced-development/workflows/page.mdx": + "2024-09-18T08:00:57.364Z", + "app/learn/advanced-development/workflows/variable-manipulation/page.mdx": + "2024-11-14T16:11:24.538Z", + "app/learn/customization/custom-features/api-route/page.mdx": + "2024-09-12T12:42:34.201Z", + "app/learn/customization/custom-features/module/page.mdx": + "2024-10-16T08:49:44.676Z", + "app/learn/customization/custom-features/workflow/page.mdx": + "2024-09-30T08:43:53.133Z", + "app/learn/customization/extend-models/create-links/page.mdx": + "2024-09-30T08:43:53.133Z", + "app/learn/customization/extend-models/extend-create-product/page.mdx": + "2024-09-30T08:43:53.134Z", + "app/learn/customization/custom-features/page.mdx": + "2024-09-12T11:18:13.271Z", + "app/learn/customization/customize-admin/page.mdx": + "2024-09-12T12:25:29.853Z", + "app/learn/customization/customize-admin/route/page.mdx": + "2024-10-07T12:43:11.335Z", + "app/learn/customization/customize-admin/widget/page.mdx": + "2024-10-07T12:44:24.538Z", + "app/learn/customization/extend-models/define-link/page.mdx": + "2024-09-30T08:43:53.134Z", "app/learn/customization/extend-models/page.mdx": "2024-09-12T12:38:57.394Z", - "app/learn/customization/extend-models/query-linked-records/page.mdx": "2024-09-30T08:43:53.134Z", - "app/learn/customization/integrate-systems/handle-event/page.mdx": "2024-09-30T08:43:53.135Z", - "app/learn/customization/integrate-systems/page.mdx": "2024-09-12T12:33:29.827Z", - "app/learn/customization/integrate-systems/schedule-task/page.mdx": "2024-09-30T08:43:53.135Z", - "app/learn/customization/integrate-systems/service/page.mdx": "2024-10-16T08:49:50.899Z", + "app/learn/customization/extend-models/query-linked-records/page.mdx": + "2024-09-30T08:43:53.134Z", + "app/learn/customization/integrate-systems/handle-event/page.mdx": + "2024-09-30T08:43:53.135Z", + "app/learn/customization/integrate-systems/page.mdx": + "2024-09-12T12:33:29.827Z", + "app/learn/customization/integrate-systems/schedule-task/page.mdx": + "2024-09-30T08:43:53.135Z", + "app/learn/customization/integrate-systems/service/page.mdx": + "2024-10-16T08:49:50.899Z", "app/learn/customization/next-steps/page.mdx": "2024-09-12T10:50:04.873Z", "app/learn/customization/page.mdx": "2024-09-12T11:16:18.504Z", "app/learn/more-resources/cheatsheet/page.mdx": "2024-07-11T16:11:26.480Z", - "app/learn/architecture/architectural-modules/page.mdx": "2024-09-23T12:51:04.520Z", + "app/learn/architecture/architectural-modules/page.mdx": + "2024-09-23T12:51:04.520Z", "app/learn/architecture/overview/page.mdx": "2024-09-23T12:55:01.339Z", - "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/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-11-21T14:09:42.197Z", - "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/build/page.mdx": "2024-11-11T11:08:41.832Z", "app/learn/deployment/general/page.mdx": "2024-11-25T14:33:50.439Z", - "app/learn/advanced-development/workflows/multiple-step-usage/page.mdx": "2024-11-12T11:11:49.191Z" -} \ No newline at end of file + "app/learn/advanced-development/workflows/multiple-step-usage/page.mdx": + "2024-11-12T11:11:49.191Z", +}