From c1db40b564ecfb34ccd900316a967430962615eb Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Thu, 13 Jun 2024 12:21:54 +0300 Subject: [PATCH] docs: added customer storefront guides (#7685) * added customer guides * fixes to sidebar * remove old customer registration guide * fix build error * generate files * run linter --- .../admin/ui-routes/page.mdx | 4 +- .../admin/widgets/page.mdx | 2 +- .../api-routes/cors/page.mdx | 2 +- .../custom-cli-scripts/page.mdx | 10 +- .../modules/module-relationships/page.mdx | 8 +- .../modules/options/page.mdx | 4 +- .../app/basics/modules-and-services/page.mdx | 4 +- .../book/app/basics/scheduled-jobs/page.mdx | 4 +- .../cache/create/page.mdx | 2 +- .../cache/in-memory/page.mdx | 2 +- .../cache/redis/page.mdx | 2 +- .../event/create/page.mdx | 2 +- .../event/local/page.mdx | 2 +- .../event/redis/page.mdx | 2 +- .../notification/local/page.mdx | 4 +- .../notification/page.mdx | 2 +- .../notification/send-notification/page.mdx | 4 +- .../notification/sendgrid/page.mdx | 8 +- .../workflow-engine/in-memory/page.mdx | 2 +- .../workflow-engine/redis/page.mdx | 2 +- .../api-key/examples/page.mdx | 14 +- .../app/commerce-modules/api-key/page.mdx | 4 +- .../auth/auth-providers/_google/page.mdx | 6 +- .../auth/auth-providers/emailpass/page.mdx | 6 +- .../auth/auth-providers/page.mdx | 4 +- .../auth/authentication-route/page.mdx | 2 +- .../auth/create-actor-type/page.mdx | 24 +- .../auth/module-options/page.mdx | 4 +- .../app/commerce-modules/auth/page.mdx | 8 +- .../customer/register-customer-email/page.mdx | 74 --- .../fulfillment/module-options/page.mdx | 8 +- .../payment/module-options/page.mdx | 2 +- .../payment/payment-provider/stripe/page.mdx | 6 +- .../product/examples/page.mdx | 4 +- .../app/commerce-modules/promotion/page.mdx | 4 +- .../app/commerce-modules/region/page.mdx | 2 +- .../app/commerce-modules/store/page.mdx | 2 +- .../tax/module-options/page.mdx | 2 +- .../user/module-options/page.mdx | 2 +- www/apps/resources/app/recipes/b2b/page.mdx | 88 +-- .../app/recipes/commerce-automation/page.mdx | 154 ++--- .../app/recipes/digital-products/page.mdx | 162 ++--- .../integrate-ecommerce-stack/page.mdx | 18 +- .../app/recipes/marketplace/page.mdx | 136 ++--- .../cart/context/page.mdx | 12 +- .../cart/create/page.mdx | 16 +- .../cart/manage-items/page.mdx | 10 +- .../cart/retrieve/page.mdx | 6 +- .../cart/update/page.mdx | 12 +- .../checkout/address/page.mdx | 24 +- .../checkout/complete-cart/page.mdx | 6 +- .../checkout/email/page.mdx | 14 +- .../checkout/payment/page.mdx | 40 +- .../checkout/payment/stripe/page.mdx | 6 +- .../checkout/shipping/page.mdx | 20 +- .../customers/addresses/page.mdx | 570 ++++++++++++++++++ .../customers/context/page.mdx | 160 +++++ .../customers/log-out/page.mdx | 89 +++ .../customers/login/page.mdx | 347 +++++++++++ .../storefront-development/customers/page.mdx | 11 + .../customers/profile/page.mdx | 145 +++++ .../customers/register/page.mdx | 190 ++++++ .../customers/retrieve/page.mdx | 66 ++ .../products/categories/list/page.mdx | 12 +- .../categories/nested-categories/page.mdx | 4 +- .../products/categories/products/page.mdx | 18 +- .../products/collections/list/page.mdx | 12 +- .../products/collections/products/page.mdx | 18 +- .../products/list/page.mdx | 28 +- .../products/price/page.mdx | 16 +- .../products/retrieve/page.mdx | 16 +- .../products/variants/page.mdx | 6 +- .../regions/context/page.mdx | 14 +- .../regions/list/page.mdx | 8 +- .../regions/store-retrieve-region/page.mdx | 2 +- .../app/storefront-development/tips/page.mdx | 4 +- .../_sections/other/cors-errors.mdx | 4 +- www/apps/resources/generated/files-map.mjs | 36 +- www/apps/resources/generated/sidebar.mjs | 157 +++-- www/apps/resources/sidebar.mjs | 95 +-- 80 files changed, 2301 insertions(+), 701 deletions(-) delete mode 100644 www/apps/resources/app/commerce-modules/customer/register-customer-email/page.mdx create mode 100644 www/apps/resources/app/storefront-development/customers/addresses/page.mdx create mode 100644 www/apps/resources/app/storefront-development/customers/context/page.mdx create mode 100644 www/apps/resources/app/storefront-development/customers/log-out/page.mdx create mode 100644 www/apps/resources/app/storefront-development/customers/login/page.mdx create mode 100644 www/apps/resources/app/storefront-development/customers/page.mdx create mode 100644 www/apps/resources/app/storefront-development/customers/profile/page.mdx create mode 100644 www/apps/resources/app/storefront-development/customers/register/page.mdx create mode 100644 www/apps/resources/app/storefront-development/customers/retrieve/page.mdx diff --git a/www/apps/book/app/advanced-development/admin/ui-routes/page.mdx b/www/apps/book/app/advanced-development/admin/ui-routes/page.mdx index 8f83d26513..a9695c83af 100644 --- a/www/apps/book/app/advanced-development/admin/ui-routes/page.mdx +++ b/www/apps/book/app/advanced-development/admin/ui-routes/page.mdx @@ -54,7 +54,7 @@ export const highlights = [ ] ```tsx title="src/admin/routes/custom/page.tsx" highlights={[["21"], ["22"], ["23"], ["24"], ["25"], ["26"]]} -import { defineRouteConfig } from "@medusajs/admin-shared"; +import { defineRouteConfig } from "@medusajs/admin-shared" import { ChatBubbleLeftRight } from "@medusajs/icons" const CustomPage = () => { @@ -125,7 +125,7 @@ export const config = defineRouteConfig({ label: "Custom", }) -export default CustomSettingPage; +export default CustomSettingPage ``` This adds a page under the path `/app/settings/custom`. An item is also added to the settings sidebar with the label `Custom`. diff --git a/www/apps/book/app/advanced-development/admin/widgets/page.mdx b/www/apps/book/app/advanced-development/admin/widgets/page.mdx index 3c2e553fbf..784393be01 100644 --- a/www/apps/book/app/advanced-development/admin/widgets/page.mdx +++ b/www/apps/book/app/advanced-development/admin/widgets/page.mdx @@ -80,7 +80,7 @@ import { defineWidgetConfig } from "@medusajs/admin-shared" import { DetailWidgetProps, AdminProduct } from "@medusajs/types" const ProductWidget = ({ - data + data, }: DetailWidgetProps) => { return (
diff --git a/www/apps/book/app/advanced-development/api-routes/cors/page.mdx b/www/apps/book/app/advanced-development/api-routes/cors/page.mdx index 514f0c1a14..d4cb4c2076 100644 --- a/www/apps/book/app/advanced-development/api-routes/cors/page.mdx +++ b/www/apps/book/app/advanced-development/api-routes/cors/page.mdx @@ -24,7 +24,7 @@ module.exports = defineConfig({ adminCors: "http://localhost:7001", // ... }, - } + }, }) ``` diff --git a/www/apps/book/app/advanced-development/custom-cli-scripts/page.mdx b/www/apps/book/app/advanced-development/custom-cli-scripts/page.mdx index 7d4595e4bc..3e134c4595 100644 --- a/www/apps/book/app/advanced-development/custom-cli-scripts/page.mdx +++ b/www/apps/book/app/advanced-development/custom-cli-scripts/page.mdx @@ -21,12 +21,12 @@ For example, create the file `src/scripts/my-script.ts` with the following conte ```ts title="src/scripts/my-script.ts" import { ExecArgs, - IProductModuleService + IProductModuleService, } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -export default async function myScript ({ - container +export default async function myScript({ + container, }: ExecArgs) { const productModuleService: IProductModuleService = container.resolve(ModuleRegistrationName.PRODUCT) @@ -60,8 +60,8 @@ For example: ```ts import { ExecArgs } from "@medusajs/types" -export default async function myScript ({ - args +export default async function myScript({ + args, }: ExecArgs) { console.log(`The arguments you passed: ${args}`) } diff --git a/www/apps/book/app/advanced-development/modules/module-relationships/page.mdx b/www/apps/book/app/advanced-development/modules/module-relationships/page.mdx index 8fb40efdf6..773c4975e2 100644 --- a/www/apps/book/app/advanced-development/modules/module-relationships/page.mdx +++ b/www/apps/book/app/advanced-development/modules/module-relationships/page.mdx @@ -222,10 +222,10 @@ module.exports = defineConfig({ helloModuleService: { // ... definition: { - isQueryable: true - } - } - } + isQueryable: true, + }, + }, + }, }) ``` diff --git a/www/apps/book/app/advanced-development/modules/options/page.mdx b/www/apps/book/app/advanced-development/modules/options/page.mdx index 696c858732..5cfff51e2e 100644 --- a/www/apps/book/app/advanced-development/modules/options/page.mdx +++ b/www/apps/book/app/advanced-development/modules/options/page.mdx @@ -31,8 +31,8 @@ module.exports = defineConfig({ options: { capitalize: true, }, - } - } + }, + }, }) ``` diff --git a/www/apps/book/app/basics/modules-and-services/page.mdx b/www/apps/book/app/basics/modules-and-services/page.mdx index f6223723d3..4da2c3c4e6 100644 --- a/www/apps/book/app/basics/modules-and-services/page.mdx +++ b/www/apps/book/app/basics/modules-and-services/page.mdx @@ -68,8 +68,8 @@ module.exports = defineConfig({ modules: { helloModuleService: { resolve: "./modules/hello", - } - } + }, + }, }) ``` diff --git a/www/apps/book/app/basics/scheduled-jobs/page.mdx b/www/apps/book/app/basics/scheduled-jobs/page.mdx index da60baf1cf..387cad1311 100644 --- a/www/apps/book/app/basics/scheduled-jobs/page.mdx +++ b/www/apps/book/app/basics/scheduled-jobs/page.mdx @@ -66,9 +66,9 @@ To test out your scheduled job: ```js title="medusa-config.js" module.exports = defineConfig({ projectConfig: { - redisUrl: REDIS_URL + redisUrl: REDIS_URL, // ... - } + }, }) ``` diff --git a/www/apps/resources/app/architectural-modules/cache/create/page.mdx b/www/apps/resources/app/architectural-modules/cache/create/page.mdx index 7c8dd45941..e67ad9984c 100644 --- a/www/apps/resources/app/architectural-modules/cache/create/page.mdx +++ b/www/apps/resources/app/architectural-modules/cache/create/page.mdx @@ -166,6 +166,6 @@ module.exports = defineConfig({ ttl: 30, }, }, - } + }, }) ``` diff --git a/www/apps/resources/app/architectural-modules/cache/in-memory/page.mdx b/www/apps/resources/app/architectural-modules/cache/in-memory/page.mdx index db718e8670..98088da2e0 100644 --- a/www/apps/resources/app/architectural-modules/cache/in-memory/page.mdx +++ b/www/apps/resources/app/architectural-modules/cache/in-memory/page.mdx @@ -44,7 +44,7 @@ module.exports = defineConfig({ // optional options }, }, - } + }, }) ``` diff --git a/www/apps/resources/app/architectural-modules/cache/redis/page.mdx b/www/apps/resources/app/architectural-modules/cache/redis/page.mdx index ae4bf11480..2d13bb41d5 100644 --- a/www/apps/resources/app/architectural-modules/cache/redis/page.mdx +++ b/www/apps/resources/app/architectural-modules/cache/redis/page.mdx @@ -44,7 +44,7 @@ module.exports = defineConfig({ redisUrl: process.env.CACHE_REDIS_URL, }, }, - } + }, }) ``` 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 841b086ee2..35e3aafe0f 100644 --- a/www/apps/resources/app/architectural-modules/event/create/page.mdx +++ b/www/apps/resources/app/architectural-modules/event/create/page.mdx @@ -120,6 +120,6 @@ module.exports = defineConfig({ // any options }, }, - } + }, }) ``` diff --git a/www/apps/resources/app/architectural-modules/event/local/page.mdx b/www/apps/resources/app/architectural-modules/event/local/page.mdx index 292f0758dd..93a45f5ed5 100644 --- a/www/apps/resources/app/architectural-modules/event/local/page.mdx +++ b/www/apps/resources/app/architectural-modules/event/local/page.mdx @@ -37,7 +37,7 @@ module.exports = defineConfig({ // ... modules: { [Modules.EVENT_BUS]: true, - } + }, }) ``` diff --git a/www/apps/resources/app/architectural-modules/event/redis/page.mdx b/www/apps/resources/app/architectural-modules/event/redis/page.mdx index 934b0e710b..c7912cf935 100644 --- a/www/apps/resources/app/architectural-modules/event/redis/page.mdx +++ b/www/apps/resources/app/architectural-modules/event/redis/page.mdx @@ -48,7 +48,7 @@ module.exports = defineConfig({ redisUrl: process.env.EVENTS_REDIS_URL, }, }, - } + }, }) ``` diff --git a/www/apps/resources/app/architectural-modules/notification/local/page.mdx b/www/apps/resources/app/architectural-modules/notification/local/page.mdx index 7380ffe8e4..c67b904626 100644 --- a/www/apps/resources/app/architectural-modules/notification/local/page.mdx +++ b/www/apps/resources/app/architectural-modules/notification/local/page.mdx @@ -50,7 +50,7 @@ module.exports = defineConfig({ options: { config: { local: { - channels: ["email"] + channels: ["email"], }, }, }, @@ -58,7 +58,7 @@ module.exports = defineConfig({ ], }, }, - } + }, }) ``` diff --git a/www/apps/resources/app/architectural-modules/notification/page.mdx b/www/apps/resources/app/architectural-modules/notification/page.mdx index a560d935b0..a8bcd17f97 100644 --- a/www/apps/resources/app/architectural-modules/notification/page.mdx +++ b/www/apps/resources/app/architectural-modules/notification/page.mdx @@ -49,7 +49,7 @@ module.exports = { options: { config: { local: { - channels: ["email"] + channels: ["email"], }, }, }, diff --git a/www/apps/resources/app/architectural-modules/notification/send-notification/page.mdx b/www/apps/resources/app/architectural-modules/notification/send-notification/page.mdx index c8f7498c90..996d8e62ea 100644 --- a/www/apps/resources/app/architectural-modules/notification/send-notification/page.mdx +++ b/www/apps/resources/app/architectural-modules/notification/send-notification/page.mdx @@ -30,7 +30,7 @@ import { INotificationModuleService } from "@medusajs/types" export default async function productCreateHandler({ data, - container + container, }: SubscriberArgs<{ id: string }>) { const notificationModuleService: INotificationModuleService = container.resolve( @@ -41,7 +41,7 @@ export default async function productCreateHandler({ to: "shahednasser@gmail.com", channel: "email", template: "product-created", - data: "data" in data ? data.data : data + data: "data" in data ? data.data : data, }) } diff --git a/www/apps/resources/app/architectural-modules/notification/sendgrid/page.mdx b/www/apps/resources/app/architectural-modules/notification/sendgrid/page.mdx index 5d7e6dc7bc..c3f5b3c00a 100644 --- a/www/apps/resources/app/architectural-modules/notification/sendgrid/page.mdx +++ b/www/apps/resources/app/architectural-modules/notification/sendgrid/page.mdx @@ -54,7 +54,7 @@ module.exports = defineConfig({ sendgrid: { channels: ["email"], api_key: process.env.SENDGRID_API_KEY, - from: process.env.SENDGRID_FROM + from: process.env.SENDGRID_FROM, }, }, }, @@ -62,7 +62,7 @@ module.exports = defineConfig({ ], }, }, - } + }, }) ``` @@ -156,7 +156,7 @@ import { INotificationModuleService } from "@medusajs/types" export default async function productCreateHandler({ data, - container + container, }: SubscriberArgs<{ id: string }>) { const notificationModuleService: INotificationModuleService = container.resolve( @@ -167,7 +167,7 @@ export default async function productCreateHandler({ to: "test@gmail.com", channel: "email", template: "product-created", - data: "data" in data ? data.data : data + data: "data" in data ? data.data : data, }) } diff --git a/www/apps/resources/app/architectural-modules/workflow-engine/in-memory/page.mdx b/www/apps/resources/app/architectural-modules/workflow-engine/in-memory/page.mdx index f461d294ea..e997beabcd 100644 --- a/www/apps/resources/app/architectural-modules/workflow-engine/in-memory/page.mdx +++ b/www/apps/resources/app/architectural-modules/workflow-engine/in-memory/page.mdx @@ -39,6 +39,6 @@ module.exports = defineConfig({ // ... modules: { [Modules.WORKFLOW_ENGINE]: true, - } + }, }) ``` diff --git a/www/apps/resources/app/architectural-modules/workflow-engine/redis/page.mdx b/www/apps/resources/app/architectural-modules/workflow-engine/redis/page.mdx index f7d5e69ac2..134cf96ded 100644 --- a/www/apps/resources/app/architectural-modules/workflow-engine/redis/page.mdx +++ b/www/apps/resources/app/architectural-modules/workflow-engine/redis/page.mdx @@ -46,7 +46,7 @@ module.exports = defineConfig({ }, }, }, - } + }, }) ``` diff --git a/www/apps/resources/app/commerce-modules/api-key/examples/page.mdx b/www/apps/resources/app/commerce-modules/api-key/examples/page.mdx index 64b61fa712..c6a576fa44 100644 --- a/www/apps/resources/app/commerce-modules/api-key/examples/page.mdx +++ b/www/apps/resources/app/commerce-modules/api-key/examples/page.mdx @@ -122,11 +122,11 @@ In this guide, you’ll find common examples of how you can use the API Key Modu ```ts collapsibleLines="1-9" expandButtonLabel="Show Imports" import { AuthenticatedMedusaRequest, - MedusaResponse + MedusaResponse, } from "@medusajs/medusa" import { IApiKeyModuleService } from "@medusajs/types" import { - ModuleRegistrationName + ModuleRegistrationName, } from "@medusajs/modules-sdk" export async function POST( @@ -139,7 +139,7 @@ In this guide, you’ll find common examples of how you can use the API Key Modu const revokedKey = await apiKeyModuleService.revoke( request.params.id, { - revoked_by: request.auth_context.actor_id + revoked_by: request.auth_context.actor_id, } ) @@ -175,7 +175,7 @@ In this guide, you’ll find common examples of how you can use the API Key Modu const revokedKey = await apiKeyModuleService.revoke( params.id, { - revoked_by: params.user_id + revoked_by: params.user_id, } ) @@ -260,7 +260,7 @@ In this guide, you’ll find common examples of how you can use the API Key Modu ```ts collapsibleLines="1-8" expandButtonLabel="Show Imports" import { AuthenticatedMedusaRequest, - MedusaResponse + MedusaResponse, } from "@medusajs/medusa" import { IApiKeyModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" @@ -275,7 +275,7 @@ In this guide, you’ll find common examples of how you can use the API Key Modu const revokedKey = await apiKeyModuleService.revoke( request.params.id, { - revoked_by: request.auth_context.actor_id + revoked_by: request.auth_context.actor_id, } ) @@ -315,7 +315,7 @@ In this guide, you’ll find common examples of how you can use the API Key Modu const apiKeyModuleService = await initializeApiKeyModule() const revokedKey = await apiKeyModuleService.revoke(params.id, { - revoked_by: params.user_id + revoked_by: params.user_id, }) const newKey = await apiKeyModuleService.create({ diff --git a/www/apps/resources/app/commerce-modules/api-key/page.mdx b/www/apps/resources/app/commerce-modules/api-key/page.mdx index 5e2b065a7d..e2033a3101 100644 --- a/www/apps/resources/app/commerce-modules/api-key/page.mdx +++ b/www/apps/resources/app/commerce-modules/api-key/page.mdx @@ -53,7 +53,7 @@ Revoke keys to disable their use permenantly. ```ts const revokedKey = await apiKeyModuleService.revoke("apk_1", { - revoked_by: "user_123" + revoked_by: "user_123", }) ``` @@ -63,7 +63,7 @@ Roll API keys by revoking a key then re-creating it. ```ts const revokedKey = await apiKeyModuleService.revoke("apk_1", { - revoked_by: "user_123" + revoked_by: "user_123", }) const newKey = await apiKeyModuleService.create({ diff --git a/www/apps/resources/app/commerce-modules/auth/auth-providers/_google/page.mdx b/www/apps/resources/app/commerce-modules/auth/auth-providers/_google/page.mdx index defecac973..a1130a7873 100644 --- a/www/apps/resources/app/commerce-modules/auth/auth-providers/_google/page.mdx +++ b/www/apps/resources/app/commerce-modules/auth/auth-providers/_google/page.mdx @@ -57,9 +57,9 @@ const modules = { callbackURL: process.env.GOOGLE_CALLBACK_URL, successRedirectUrl: process.env.GOOGLE_SUCCESS_REDIRECT_URL, - } - } - } + }, + }, + }, }, ], }, diff --git a/www/apps/resources/app/commerce-modules/auth/auth-providers/emailpass/page.mdx b/www/apps/resources/app/commerce-modules/auth/auth-providers/emailpass/page.mdx index 51319e56b7..3da27b7502 100644 --- a/www/apps/resources/app/commerce-modules/auth/auth-providers/emailpass/page.mdx +++ b/www/apps/resources/app/commerce-modules/auth/auth-providers/emailpass/page.mdx @@ -36,8 +36,8 @@ const modules = { config: { emailpass: { // options... - } - } + }, + }, }, ], }, @@ -92,4 +92,4 @@ const modules = { ## Related Guides -- [How to register a customer using email and password](../../../customer/register-customer-email/page.mdx) +- [How to register a customer using email and password](../../../../storefront-development/customers/register/page.mdx) diff --git a/www/apps/resources/app/commerce-modules/auth/auth-providers/page.mdx b/www/apps/resources/app/commerce-modules/auth/auth-providers/page.mdx index a7a964a22e..d23d40f6b8 100644 --- a/www/apps/resources/app/commerce-modules/auth/auth-providers/page.mdx +++ b/www/apps/resources/app/commerce-modules/auth/auth-providers/page.mdx @@ -32,12 +32,12 @@ module.exports = defineConfig({ http: { authMethodsPerActor: { user: ["google"], - customer: ["emailpass"] + customer: ["emailpass"], }, // ... }, // ... - } + }, }) ``` diff --git a/www/apps/resources/app/commerce-modules/auth/authentication-route/page.mdx b/www/apps/resources/app/commerce-modules/auth/authentication-route/page.mdx index 694400d53d..09e5bdf214 100644 --- a/www/apps/resources/app/commerce-modules/auth/authentication-route/page.mdx +++ b/www/apps/resources/app/commerce-modules/auth/authentication-route/page.mdx @@ -32,6 +32,6 @@ There are two ways the returned authentication token is useful: -[How to register Customers using the authentication route](../../customer/register-customer-email/page.mdx). +[How to register Customers using the authentication route](../../../storefront-development/customers/register/page.mdx). 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 bee1234490..47ae4ef2c4 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 @@ -60,10 +60,10 @@ export const workflowHighlights = [ import { createWorkflow, createStep, - StepResponse + StepResponse, } from "@medusajs/workflows-sdk" import { - setAuthAppMetadataStep + setAuthAppMetadataStep, } from "@medusajs/core-flows" import ManagerModuleService from "../modules/manager/service" @@ -86,7 +86,7 @@ type CreateManagerWorkflowOutput = { const createManagerStep = createStep( "create-manager-step", async ({ - manager: managerData + manager: managerData, }: Pick, { container }) => { const managerModuleService: ManagerModuleService = @@ -106,13 +106,13 @@ const createManagerWorkflow = createWorkflow< "create-manager", function (input) { const manager = createManagerStep({ - manager: input.manager + manager: input.manager, }) setAuthAppMetadataStep({ authIdentityId: input.authIdentityId, actorType: "manager", - value: manager.id + value: manager.id, }) return manager @@ -146,7 +146,7 @@ export const createRouteHighlights = [ ```ts title="src/api/manager/route.ts" highlights={createRouteHighlights} import type { AuthenticatedMedusaRequest, - MedusaResponse + MedusaResponse, } from "@medusajs/medusa" import { MedusaError } from "@medusajs/utils" import createManagerWorkflow from "../../workflows/create-manager" @@ -174,8 +174,8 @@ export async function POST( .run({ input: { manager: req.body, - authIdentityId: req.auth_context.auth_identity_id - } + authIdentityId: req.auth_context.auth_identity_id, + }, }) res.status(200).json({ manager: result }) @@ -213,7 +213,7 @@ export const config: MiddlewaresConfig = { method: "POST", middlewares: [ authenticate("manager", ["session", "bearer"], { - allowUnregistered: true + allowUnregistered: true, }), ], }, @@ -239,9 +239,9 @@ For example, create the file `src/api/manager/me/route.ts` with the following co ```ts title="src/api/manager/me/route.ts" import { AuthenticatedMedusaRequest, - MedusaResponse -} from "@medusajs/medusa"; -import ManagerModuleService from "../../../modules/manager/service"; + MedusaResponse, +} from "@medusajs/medusa" +import ManagerModuleService from "../../../modules/manager/service" export async function GET( req: AuthenticatedMedusaRequest, diff --git a/www/apps/resources/app/commerce-modules/auth/module-options/page.mdx b/www/apps/resources/app/commerce-modules/auth/module-options/page.mdx index a04d8afc5e..7f6978101e 100644 --- a/www/apps/resources/app/commerce-modules/auth/module-options/page.mdx +++ b/www/apps/resources/app/commerce-modules/auth/module-options/page.mdx @@ -37,8 +37,8 @@ module.exports = defineConfig({ config: { google: { // provider options... - } - } + }, + }, }, }, ], diff --git a/www/apps/resources/app/commerce-modules/auth/page.mdx b/www/apps/resources/app/commerce-modules/auth/page.mdx index fa9b7175bf..4656e1976e 100644 --- a/www/apps/resources/app/commerce-modules/auth/page.mdx +++ b/www/apps/resources/app/commerce-modules/auth/page.mdx @@ -84,11 +84,11 @@ For example: ```ts title="src/api/store/custom/route.ts" import { MedusaRequest, - MedusaResponse + MedusaResponse, } from "@medusajs/medusa" import { IAuthModuleService } from "@medusajs/types" import { - ModuleRegistrationName + ModuleRegistrationName, } from "@medusajs/modules-sdk" export async function GET( @@ -111,7 +111,7 @@ For example: import { SubscriberArgs } from "@medusajs/medusa" import { IAuthModuleService } from "@medusajs/types" import { - ModuleRegistrationName + ModuleRegistrationName, } from "@medusajs/modules-sdk" export default async function subscriberHandler({ @@ -131,7 +131,7 @@ For example: import { createStep } from "@medusajs/workflows-sdk" import { IAuthModuleService } from "@medusajs/types" import { - ModuleRegistrationName + ModuleRegistrationName, } from "@medusajs/modules-sdk" const step1 = createStep( diff --git a/www/apps/resources/app/commerce-modules/customer/register-customer-email/page.mdx b/www/apps/resources/app/commerce-modules/customer/register-customer-email/page.mdx deleted file mode 100644 index 57786bf241..0000000000 --- a/www/apps/resources/app/commerce-modules/customer/register-customer-email/page.mdx +++ /dev/null @@ -1,74 +0,0 @@ -export const metadata = { - title: `How to Register a Customer with Email and Password`, -} - -# {metadata.title} - -In this guide, you'll learn the steps to register and authenticate a customer. - - - -1. Send a `POST` request to `/auth/customer/emailpass`. -2. Send a request to the [Create Customer API route](!api!/store#customers_postcustomers) passing the token obtained from the first step as a bearer token. -3. Send a `POST` request to `/auth/customer/emailpass` to log-in. - - - -## 1. Obtain Authentication Token - -Before registering and creating the customer, you must create an authentication identity that's associated with that customer. - -To do that, use the `/auth/customer/{provider}` API route, where `{provider}` is the auth provider to use to handle authentication. - - - -Learn more about the `/auth` route in [this document](../../auth/authentication-route/page.mdx) - - - -For example, send a `POST` request to `/auth/customer/emailpass`: - -```bash -curl -X POST 'http://localhost:9000/auth/customer/emailpass' \ ---header 'Content-Type: application/json' \ ---data-raw '{ - "email": "customer@gmail.com", - "password": "supersecret" -}' -``` - ---- - -## 2. Register Customer - -Then, use the returned token in the header of the [Create Customer API route](!api!/store#customers_postcustomers): - -```bash -curl -X POST 'http://localhost:9000/store/customers' \ --H 'Content-Type: application/json' \ --H 'Authorization: Bearer {token}' \ ---data-raw '{ - "email": "customer@gmail.com", - "first_name": "John", - "last_name": "Doe" -}' -``` - -This creates and returns the customer. - ---- - -## 3. Login Customer - -Finally, to log-in the customer, send a `POST` request again to `/auth/customer/emailpass`: - -```bash -curl -X POST 'http://localhost:9000/auth/customer/emailpass' \ ---header 'Content-Type: application/json' \ ---data-raw '{ - "email": "customer@gmail.com", - "password": "supersecret" -}' -``` - -You can now use the returned token to send authenticated requests as a customer. diff --git a/www/apps/resources/app/commerce-modules/fulfillment/module-options/page.mdx b/www/apps/resources/app/commerce-modules/fulfillment/module-options/page.mdx index e8fbdf0cfb..a3ff007bba 100644 --- a/www/apps/resources/app/commerce-modules/fulfillment/module-options/page.mdx +++ b/www/apps/resources/app/commerce-modules/fulfillment/module-options/page.mdx @@ -38,14 +38,14 @@ module.exports = defineConfig({ config: { manual: { // provider options... - } - } - } + }, + }, + }, }, ], }, }, - } + }, }) ``` diff --git a/www/apps/resources/app/commerce-modules/payment/module-options/page.mdx b/www/apps/resources/app/commerce-modules/payment/module-options/page.mdx index 447b551869..127474bc4a 100644 --- a/www/apps/resources/app/commerce-modules/payment/module-options/page.mdx +++ b/www/apps/resources/app/commerce-modules/payment/module-options/page.mdx @@ -124,7 +124,7 @@ module.exports = defineConfig({ ], }, }, - } + }, }) ``` diff --git a/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe/page.mdx b/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe/page.mdx index a4a01aaba9..1b47cd9a58 100644 --- a/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe/page.mdx +++ b/www/apps/resources/app/commerce-modules/payment/payment-provider/stripe/page.mdx @@ -60,14 +60,14 @@ module.exports = defineConfig({ apiKey: process.env.STRIPE_USD_API_KEY, }, }, - } - } + }, + }, }, }, ], }, }, - } + }, }) ``` diff --git a/www/apps/resources/app/commerce-modules/product/examples/page.mdx b/www/apps/resources/app/commerce-modules/product/examples/page.mdx index 5393545d7a..cf6b773455 100644 --- a/www/apps/resources/app/commerce-modules/product/examples/page.mdx +++ b/www/apps/resources/app/commerce-modules/product/examples/page.mdx @@ -213,7 +213,7 @@ In this guide, you’ll find common examples of how you can use the Product Modu request.scope.resolve(ModuleRegistrationName.PRODUCT) const data = await productModuleService.list({ - handle: "shirt" + handle: "shirt", }) res.json({ product: data[0] }) @@ -234,7 +234,7 @@ In this guide, you’ll find common examples of how you can use the Product Modu const productModuleService = await initializeProductModule() const data = await productModuleService.list({ - handle: "shirt" + handle: "shirt", }) return NextResponse.json({ product: data[0] }) diff --git a/www/apps/resources/app/commerce-modules/promotion/page.mdx b/www/apps/resources/app/commerce-modules/promotion/page.mdx index a8425c3d58..612ef558b6 100644 --- a/www/apps/resources/app/commerce-modules/promotion/page.mdx +++ b/www/apps/resources/app/commerce-modules/promotion/page.mdx @@ -24,7 +24,7 @@ const promotion = await promotionModuleService.create({ type: "percentage", target_type: "order", value: "10", - currency_code: "usd" + currency_code: "usd", }, }) ``` @@ -41,7 +41,7 @@ const promotion = await promotionModuleService.create({ type: "percentage", target_type: "order", value: "10", - currency_code: "usd" + currency_code: "usd", }, rules: [ { diff --git a/www/apps/resources/app/commerce-modules/region/page.mdx b/www/apps/resources/app/commerce-modules/region/page.mdx index ba40fa109c..9ea32d7d86 100644 --- a/www/apps/resources/app/commerce-modules/region/page.mdx +++ b/www/apps/resources/app/commerce-modules/region/page.mdx @@ -60,7 +60,7 @@ const regions = await regionModuleService.create([ name: "United States of America", currency_code: "usd", countries: ["us"], - payment_providers: ["stripe"] + payment_providers: ["stripe"], }, ]) ``` diff --git a/www/apps/resources/app/commerce-modules/store/page.mdx b/www/apps/resources/app/commerce-modules/store/page.mdx index ab34694342..a94edd09c4 100644 --- a/www/apps/resources/app/commerce-modules/store/page.mdx +++ b/www/apps/resources/app/commerce-modules/store/page.mdx @@ -34,7 +34,7 @@ const stores = await storeModuleService.create([ { name: "Europe Store", supported_currency_codes: ["eur"], - } + }, ]) ``` diff --git a/www/apps/resources/app/commerce-modules/tax/module-options/page.mdx b/www/apps/resources/app/commerce-modules/tax/module-options/page.mdx index 83ee05a1d1..26062afda5 100644 --- a/www/apps/resources/app/commerce-modules/tax/module-options/page.mdx +++ b/www/apps/resources/app/commerce-modules/tax/module-options/page.mdx @@ -39,7 +39,7 @@ module.exports = defineConfig({ ], }, }, - } + }, }) ``` diff --git a/www/apps/resources/app/commerce-modules/user/module-options/page.mdx b/www/apps/resources/app/commerce-modules/user/module-options/page.mdx index 815426ade0..80a77d99e6 100644 --- a/www/apps/resources/app/commerce-modules/user/module-options/page.mdx +++ b/www/apps/resources/app/commerce-modules/user/module-options/page.mdx @@ -28,7 +28,7 @@ module.exports = defineConfig({ jwt_secret: process.env.JWT_SECRET, }, }, - } + }, }) ``` diff --git a/www/apps/resources/app/recipes/b2b/page.mdx b/www/apps/resources/app/recipes/b2b/page.mdx index 63aeb42e51..315c469908 100644 --- a/www/apps/resources/app/recipes/b2b/page.mdx +++ b/www/apps/resources/app/recipes/b2b/page.mdx @@ -245,16 +245,16 @@ You can create a B2B module that adds necessary data models to represent a B2B c Next, create the migration in the file `src/modules/b2b/migrations/Migration20240516081502.ts` with the following content: ```ts title="src/modules/b2b/migrations/Migration20240516081502.ts" - import { Migration } from '@mikro-orm/migrations'; - + import { Migration } from "@mikro-orm/migrations" + export class Migration20240516081502 extends Migration { async up(): Promise { - this.addSql('create table if not exists "company" ("id" text not null, "name" text not null, "city" text not null, "country_code" text not null, "customer_group_id" text not null, constraint "company_pkey" primary key ("id"));'); + this.addSql("create table if not exists \"company\" (\"id\" text not null, \"name\" text not null, \"city\" text not null, \"country_code\" text not null, \"customer_group_id\" text not null, constraint \"company_pkey\" primary key (\"id\"));") } async down(): Promise { - this.addSql('drop table if exists "company" cascade;'); + this.addSql("drop table if exists \"company\" cascade;") } } ``` @@ -295,9 +295,9 @@ export const mainServiceHighlights = [ import { ModulesSdkUtils } from "@medusajs/utils" import { ModuleJoinerConfig, ModulesSdkTypes } from "@medusajs/types" import { Modules } from "@medusajs/modules-sdk" - import { Company } from "./models/company"; - import { CompanyDTO, CreateCompanyDTO } from "../../types/b2b"; - + import { Company } from "./models/company" + import { CompanyDTO, CreateCompanyDTO } from "../../types/b2b" + type InjectedDependencies = { companyService: ModulesSdkTypes.InternalModuleService } @@ -329,9 +329,9 @@ export const mainServiceHighlights = [ { name: ["company"], args: { - entity: Company.name - } - } + entity: Company.name, + }, + }, ], relationships: [ { @@ -340,14 +340,14 @@ export const mainServiceHighlights = [ primaryKey: "id", foreignKey: "customer_group_id", args: { - methodSuffix: "CustomerGroups" - } - } - ] + methodSuffix: "CustomerGroups", + }, + }, + ], } } - async create (data: CreateCompanyDTO): Promise { + async create(data: CreateCompanyDTO): Promise { const company = this.companyService_.create(data) return company @@ -365,8 +365,8 @@ export const mainServiceHighlights = [ Next, create the module definition at `src/modules/b2b/index.ts` with the following content: ```ts title="src/modules/b2b/index.ts" - import B2bModuleService from "./service"; - + import B2bModuleService from "./service" + export default { service: B2bModuleService, } @@ -381,10 +381,10 @@ export const mainServiceHighlights = [ b2bModuleService: { resolve: "./modules/b2b", definition: { - isQueryable: true - } + isQueryable: true, + }, }, - } + }, }) ``` @@ -411,15 +411,15 @@ export const workflowHighlights = [ import { StepResponse, createStep, - createWorkflow - } from "@medusajs/workflows-sdk"; + createWorkflow, + } from "@medusajs/workflows-sdk" import { - createCustomerGroupsWorkflow + createCustomerGroupsWorkflow, } from "@medusajs/core-flows" - import { CreateCustomerGroupDTO } from "@medusajs/types"; - import { CompanyDTO, CreateCompanyDTO } from "../types/b2b"; - import B2bModuleService from "../modules/b2b/service"; - + import { CreateCustomerGroupDTO } from "@medusajs/types" + import { CompanyDTO, CreateCompanyDTO } from "../types/b2b" + import B2bModuleService from "../modules/b2b/service" + export type CreateCompanyWorkflowInput = CreateCompanyDTO & { customer_group?: CreateCustomerGroupDTO } @@ -447,8 +447,8 @@ export const workflowHighlights = [ container ).run({ input: { - customersData: [customer_group] - } + customersData: [customer_group], + }, }) company.customer_group_id = result[0].id @@ -486,7 +486,7 @@ export const workflowHighlights = [ "create-company", function (input) { const { - company: companyData + company: companyData, } = tryToCreateCustomerGroupStep(input) const company = createCompanyStep({ companyData }) @@ -506,11 +506,11 @@ export const workflowHighlights = [ ```ts title="src/api/admin/b2b/company/route.ts" collapsibleLines="1-9" expandButtonLabel="Show Imports" import type { MedusaRequest, - MedusaResponse - } from "@medusajs/medusa"; + MedusaResponse, + } from "@medusajs/medusa" import { CreateCompanyWorkflowInput, - createCompanyWorkflow + createCompanyWorkflow, } from "../../../../workflows/create-company" type CreateCompanyReq = CreateCompanyWorkflowInput @@ -521,11 +521,11 @@ export const workflowHighlights = [ ) { const { result } = await createCompanyWorkflow(req.scope) .run({ - input: req.body + input: req.body, }) res.json({ - company: result.company + company: result.company, }) } ``` @@ -698,11 +698,11 @@ export const checkCustomerHighlights = [ ] ```ts title="src/api/store/b2b/check-customer/route.ts" highlights={checkCustomerHighlights} collapsibleLines="1-5" expandButtonLabel="Show Imports" - import type { AuthenticatedMedusaRequest, MedusaResponse } from "@medusajs/medusa"; - import { ModuleRegistrationName } from "@medusajs/modules-sdk"; - import { ICustomerModuleService } from "@medusajs/types"; - import B2bModuleService from "../../../../modules/b2b/service"; - + import type { AuthenticatedMedusaRequest, MedusaResponse } from "@medusajs/medusa" + import { ModuleRegistrationName } from "@medusajs/modules-sdk" + import { ICustomerModuleService } from "@medusajs/types" + import B2bModuleService from "../../../../modules/b2b/service" + export async function GET( req: AuthenticatedMedusaRequest, res: MedusaResponse @@ -714,15 +714,15 @@ export const checkCustomerHighlights = [ ) const customer = await customerModuleService.retrieve(req.auth.actor_id, { - relations: ["groups"] + relations: ["groups"], }) const companies = await b2bModuleService.list({ - customer_group_id: customer.groups.map((group) => group.id) + customer_group_id: customer.groups.map((group) => group.id), }) res.json({ - is_b2b: companies.length > 0 + is_b2b: companies.length > 0, }) } ``` @@ -743,7 +743,7 @@ export const checkCustomerHighlights = [ { matcher: "/store/b2b*", middlewares: [ - authenticate("store", ["bearer", "session"]) + authenticate("store", ["bearer", "session"]), ], }, ], diff --git a/www/apps/resources/app/recipes/commerce-automation/page.mdx b/www/apps/resources/app/recipes/commerce-automation/page.mdx index d670d91465..676793ac58 100644 --- a/www/apps/resources/app/recipes/commerce-automation/page.mdx +++ b/www/apps/resources/app/recipes/commerce-automation/page.mdx @@ -96,9 +96,9 @@ export const restockModelHighlights = [ import { Entity, PrimaryKey, - Property - } from "@mikro-orm/core"; - + Property, + } from "@mikro-orm/core" + @Entity() export class RestockNotification extends BaseEntity { @PrimaryKey({ columnType: "text" }) @@ -126,16 +126,16 @@ export const restockModelHighlights = [ Next, create the file `src/modules/restock-notification/migrations/Migration20240516140616.ts` with the following content: ```ts title="src/modules/restock-notification/migrations/Migration20240516140616.ts" - import { Migration } from '@mikro-orm/migrations'; - + import { Migration } from "@mikro-orm/migrations" + export class Migration20240516140616 extends Migration { async up(): Promise { - this.addSql('create table if not exists "restock_notification" ("id" text not null, "email" text not null, "variant_id" text not null, "sales_channel_id" text not null, constraint "restock_notification_pkey" primary key ("id"));'); + this.addSql("create table if not exists \"restock_notification\" (\"id\" text not null, \"email\" text not null, \"variant_id\" text not null, \"sales_channel_id\" text not null, constraint \"restock_notification_pkey\" primary key (\"id\"));") } async down(): Promise { - this.addSql('drop table if exists "restock_notification" cascade;'); + this.addSql("drop table if exists \"restock_notification\" cascade;") } } @@ -211,9 +211,9 @@ export const restockModuleService = [ { name: "restock_notification", args: { - entity: RestockNotification.name - } - } + entity: RestockNotification.name, + }, + }, ], relationships: [ { @@ -222,20 +222,20 @@ export const restockModuleService = [ primaryKey: "id", foreignKey: "variant_id", args: { - methodSuffix: "Variants" - } + methodSuffix: "Variants", + }, }, { serviceName: Modules.SALES_CHANNEL, alias: "sales_channel", primaryKey: "id", foreignKey: "sales_channel_id", - } - ] + }, + ], } } - async create (data: CreateRestockNotificationDTO): Promise { + async create(data: CreateRestockNotificationDTO): Promise { const restockNotification = await this.restockNotificationService_.create( data ) @@ -257,10 +257,10 @@ export const restockModuleService = [ Next, create the module's definition file `src/modules/restock-notification/index.ts` with the following content: ```ts title="src/modules/restock-notification/index.ts" - import RestockNotificationModuleService from "./service"; - + import RestockNotificationModuleService from "./service" + export default { - service: RestockNotificationModuleService + service: RestockNotificationModuleService, } ``` @@ -273,10 +273,10 @@ export const restockModuleService = [ "restockNotificationModuleService": { resolve: "./modules/restock-notification", definition: { - isQueryable: true - } + isQueryable: true, + }, }, - } + }, }) ``` @@ -293,14 +293,14 @@ export const restockModuleService = [ ```ts title="src/api/store/restock-notification/route.ts" collapsibleLines="1-10" expandButtonLabel="Show Imports" import type { MedusaRequest, - MedusaResponse - } from "@medusajs/medusa"; + MedusaResponse, + } from "@medusajs/medusa" import RestockNotificationModuleService - from "../../../modules/restock-notification/service"; + from "../../../modules/restock-notification/service" import { - CreateRestockNotificationDTO - } from "../../../types/restock-notification"; - + CreateRestockNotificationDTO, + } from "../../../types/restock-notification" + type RestockNotificationReq = CreateRestockNotificationDTO export async function POST( @@ -317,7 +317,7 @@ export const restockModuleService = [ ) res.json({ - success: true + success: true, }) } ``` @@ -357,18 +357,18 @@ export const subscriberHighlights = [ import { IInventoryServiceNext, INotificationModuleService, - RemoteQueryFunction + RemoteQueryFunction, } from "@medusajs/types" import { ContainerRegistrationKeys, Modules, - remoteQueryObjectFromString + remoteQueryObjectFromString, } from "@medusajs/utils" import { - RestockNotificationDTO + RestockNotificationDTO, } from "../types/restock-notification" import { - RemoteLink + RemoteLink, } from "@medusajs/modules-sdk" import RestockNotificationModuleService from "../modules/restock-notification/service" @@ -376,7 +376,7 @@ export const subscriberHighlights = [ // subscriber function export default async function inventoryItemUpdateHandler({ data, - container + container, }: SubscriberArgs<{ id: string }>) { const remoteQuery: RemoteQueryFunction = container.resolve( ContainerRegistrationKeys.REMOTE_QUERY @@ -406,7 +406,7 @@ export const subscriberHighlights = [ const inventoryVariantItems = await inventoryVariantLinkService.list({ - inventory_item_id: [inventoryItemId] + inventory_item_id: [inventoryItemId], }) as { variant_id: string, inventory_item_id: string @@ -421,13 +421,13 @@ export const subscriberHighlights = [ entryPoint: "restock_notification", fields: [ "email", - "variant.name" + "variant.name", ], variables: { filters: { - variant_id: inventoryVariantItems[0].variant_id - } - } + variant_id: inventoryVariantItems[0].variant_id, + }, + }, }) const restockNotifications: RestockNotificationDTO[] = @@ -444,8 +444,8 @@ export const subscriberHighlights = [ const salesChannelLocations = await salesChannelLocationService.list({ sales_channel_id: [ - restockNotification.sales_channel_id - ] + restockNotification.sales_channel_id, + ], }) as { stock_location_id: string sales_channel_id: string @@ -474,9 +474,9 @@ export const subscriberHighlights = [ template: "test_template", data: { variant_id: restockNotification.variant_id, - variant_name: restockNotification.variant.title + variant_name: restockNotification.variant.title, // other data... - } + }, }) // delete the restock notification @@ -582,17 +582,17 @@ export const syncProductsWorkflowHighlight = [ ] ```ts title="src/workflows/sync-products.ts" highlights={syncProductsWorkflowHighlight} - import { ModuleRegistrationName } from "@medusajs/modules-sdk"; - import { IProductModuleService, IStoreModuleService, ProductDTO, StoreDTO } from "@medusajs/types"; - import { StepResponse, createStep, createWorkflow } from "@medusajs/workflows-sdk"; - + import { ModuleRegistrationName } from "@medusajs/modules-sdk" + import { IProductModuleService, IStoreModuleService, ProductDTO, StoreDTO } from "@medusajs/types" + import { StepResponse, createStep, createWorkflow } from "@medusajs/workflows-sdk" + type RetrieveStoreStepInput = { id: string } const retrieveStoreStep = createStep( "retrieve-store-step", - async ({ id }: RetrieveStoreStepInput, {container}) => { + async ({ id }: RetrieveStoreStepInput, { container }) => { const storeModuleService: IStoreModuleService = container.resolve(ModuleRegistrationName.STORE) @@ -614,8 +614,8 @@ export const syncProductsWorkflowHighlight = [ const products = await productModuleService.list({ updated_at: { - $gt: last_sync_date - } + $gt: last_sync_date, + }, }) return new StepResponse({ products }) @@ -634,7 +634,7 @@ export const syncProductsWorkflowHighlight = [ ) const productsBeforeSync = await productSyncModuleService.list({ - id: products.map((product) => product.id) + id: products.map((product) => product.id), }) for (const product of products) { @@ -642,7 +642,7 @@ export const syncProductsWorkflowHighlight = [ } return new StepResponse({}, { - products: productsBeforeSync + products: productsBeforeSync, }) }, async ({ products }, { container }) => { @@ -670,13 +670,13 @@ export const syncProductsWorkflowHighlight = [ await storeModuleService.update(store.id, { metadata: { - last_sync_date: (new Date()).toString() - } + last_sync_date: (new Date()).toString(), + }, }) return new StepResponse({}, { id: store.id, - last_sync_date: prevLastSyncDate + last_sync_date: prevLastSyncDate, }) }, async ({ id, last_sync_date }, { container }) => { @@ -685,8 +685,8 @@ export const syncProductsWorkflowHighlight = [ await storeModuleService.update(id, { metadata: { - last_sync_date - } + last_sync_date, + }, }) } ) @@ -701,19 +701,19 @@ export const syncProductsWorkflowHighlight = [ "sync-products-workflow", function ({ store_id }: SyncProductsWorkflowInput) { const { store } = retrieveStoreStep({ - id: store_id + id: store_id, }) const { products } = retrieveProductsToUpdateStep({ - last_sync_date: store.metadata.last_sync_date + last_sync_date: store.metadata.last_sync_date, }) syncProductsStep({ - products + products, }) updateStoreLastSyncStep({ - store + store, }) } ) @@ -857,16 +857,16 @@ The `order.placed` event is currently not emitted. SubscriberConfig, } from "@medusajs/medusa" import { - ModuleRegistrationName + ModuleRegistrationName, } from "@medusajs/modules-sdk" import { ICustomerModuleService, - IOrderModuleService + IOrderModuleService, } from "@medusajs/types" export default async function orderCreatedHandler({ data, - container + container, }: SubscriberArgs<{ id: string }>) { const orderId = "data" in data ? data.data.id : data.id @@ -881,9 +881,9 @@ The `order.placed` event is currently not emitted. // check if VIP group exists const vipGroup = await customerModuleService .listCustomerGroups({ - name: "VIP" + name: "VIP", }, { - relations: ["customers"] + relations: ["customers"], }) if (!vipGroup.length) { @@ -902,7 +902,7 @@ The `order.placed` event is currently not emitted. } const [, count] = await orderModuleService.listAndCount({ - customer_id: order.customer_id + customer_id: order.customer_id, }) if (count < 20) { @@ -912,7 +912,7 @@ The `order.placed` event is currently not emitted. // add customer to VIP group await customerModuleService.addCustomerToGroup({ customer_group_id: vipGroup[0].id, - customer_id: order.customer_id + customer_id: order.customer_id, }) } @@ -986,20 +986,20 @@ export const newsletterHighlights = [ SubscriberConfig, } from "@medusajs/medusa" import { - ModuleRegistrationName + ModuleRegistrationName, } from "@medusajs/modules-sdk" import { - NotificationModuleService + NotificationModuleService, } from "@medusajs/notification" import { ICustomerModuleService, IProductModuleService, - IStoreModuleService + IStoreModuleService, } from "@medusajs/types" export default async function productCreateHandler({ data, - container + container, }: SubscriberArgs<{ id: string }>) { const productModuleService: IProductModuleService = container.resolve(ModuleRegistrationName.PRODUCT) @@ -1019,8 +1019,8 @@ export const newsletterHighlights = [ const products = await productModuleService.list({ created_at: { - $gt: store.metadata.last_newsletter_send_date - } + $gt: store.metadata.last_newsletter_send_date, + }, }) if (products.length < 10) { @@ -1035,15 +1035,15 @@ export const newsletterHighlights = [ channel: "email", template: "newsletter_template", data: { - products - } + products, + }, })) ) await storeModuleService.update(store.id, { metadata: { - last_newsletter_send_date: (new Date()).toString() - } + last_newsletter_send_date: (new Date()).toString(), + }, }) } diff --git a/www/apps/resources/app/recipes/digital-products/page.mdx b/www/apps/resources/app/recipes/digital-products/page.mdx index 61ca8c106d..916efe2a4c 100644 --- a/www/apps/resources/app/recipes/digital-products/page.mdx +++ b/www/apps/resources/app/recipes/digital-products/page.mdx @@ -130,9 +130,9 @@ The module will hold your custom data models and the service implementing digita // ... modules: { digitalProductModuleService: { - resolve: "./modules/digital-product" - } - } + resolve: "./modules/digital-product", + }, + }, }) ``` @@ -216,17 +216,17 @@ To represent a digital product, it's recommended to create a data model that has Create the file `src/modules/digital-product/migrations/Migration20240509093233.ts` with the following content: ```ts title="src/modules/digital-product/migrations/Migration20240509093233.ts" - import { Migration } from '@mikro-orm/migrations'; + import { Migration } from "@mikro-orm/migrations" export class Migration20240509093233 extends Migration { async up(): Promise { - this.addSql('create table if not exists "product_media" ("id" text not null, "name" text not null, "type" text check ("type" in (\'main\', \'preview\')) not null, "file_key" text not null, "mime_type" text not null, "variant_id" text not null, constraint "product_media_pkey" primary key ("id"));'); - this.addSql('CREATE INDEX IF NOT EXISTS "IDX_product_media_variant_id" ON "product_media" (variant_id);'); + this.addSql("create table if not exists \"product_media\" (\"id\" text not null, \"name\" text not null, \"type\" text check (\"type\" in ('main', 'preview')) not null, \"file_key\" text not null, \"mime_type\" text not null, \"variant_id\" text not null, constraint \"product_media_pkey\" primary key (\"id\"));") + this.addSql("CREATE INDEX IF NOT EXISTS \"IDX_product_media_variant_id\" ON \"product_media\" (variant_id);") } async down(): Promise { - this.addSql('drop table if exists "product_media" cascade;'); + this.addSql("drop table if exists \"product_media\" cascade;") } } @@ -316,7 +316,7 @@ Medusa facilitates implementing data-management features by providing a service import { CreateProductMediaDTO, ProductMediaDTO, - UpdateProductMediaDTO + UpdateProductMediaDTO, } from "../../types/digital-product/product-media" type InjectedDependencies = { @@ -340,8 +340,8 @@ Medusa facilitates implementing data-management features by providing a service constructor( { - productMediaService - }: InjectedDependencies, + productMediaService, + }: InjectedDependencies ) { // @ts-ignore super(...arguments) @@ -350,11 +350,11 @@ Medusa facilitates implementing data-management features by providing a service } async create( - data: CreateProductMediaDTO, + data: CreateProductMediaDTO ): Promise { const productMedia = await this.productMediaService_ .create( - data, + data ) return productMedia @@ -362,12 +362,12 @@ Medusa facilitates implementing data-management features by providing a service async update( id: string, - data: UpdateProductMediaDTO, + data: UpdateProductMediaDTO ): Promise { const productMedia = await this.productMediaService_ .update({ ...data, - id + id, }) return productMedia @@ -430,9 +430,9 @@ The Medusa application resolves module relationships without creating an actual { name: "product_media", args: { - entity: ProductMedia.name - } - } + entity: ProductMedia.name, + }, + }, ], relationships: [ { @@ -441,10 +441,10 @@ The Medusa application resolves module relationships without creating an actual primaryKey: "id", foreignKey: "variant_id", args: { - methodSuffix: "Variants" - } - } - ] + methodSuffix: "Variants", + }, + }, + ], } } } @@ -467,10 +467,10 @@ The Medusa application resolves module relationships without creating an actual digitalProductModuleService: { resolve: "./modules/digital-product", definition: { - isQueryable: true - } - } - } + isQueryable: true, + }, + }, + }, }) ``` @@ -518,7 +518,7 @@ To utilize the relationship to the Product Module, you use the remote query to f ```ts title="src/types/digital-product/product-media.ts" import { ProductVariantDTO, - CreateProductWorkflowInputDTO + CreateProductWorkflowInputDTO, } from "@medusajs/types" export enum MediaType { @@ -574,20 +574,20 @@ To utilize the relationship to the Product Module, you use the remote query to f createWorkflow, WorkflowData, createStep, - StepResponse + StepResponse, } from "@medusajs/workflows-sdk" import { createProductsWorkflow } from "@medusajs/core-flows" import { CreateProductMediaDTO, CreateProductMediaWorkflowInput, - ProductMediaDTO + ProductMediaDTO, } from "../../types/digital-product/product-media" import DigitalProductModuleService from "../../modules/digital-product/service" import { RemoteQueryFunction } from "@medusajs/modules-sdk" import { ContainerRegistrationKeys, - remoteQueryObjectFromString + remoteQueryObjectFromString, } from "@medusajs/utils" const tryToCreateProductVariantStep = createStep( @@ -597,9 +597,9 @@ To utilize the relationship to the Product Module, you use the remote query to f const { result, errors } = await createProductsWorkflow(container) .run({ input: { - products: [input.product] + products: [input.product], }, - throwOnError: false + throwOnError: false, }) if (errors.length) { @@ -646,13 +646,13 @@ To utilize the relationship to the Product Module, you use the remote query to f "type", "file_key", "mime_type", - "variant.*" + "variant.*", ], variables: { filters: { - id: input.id - } - } + id: input.id, + }, + }, }) const result = await remoteQuery(query) @@ -690,14 +690,14 @@ To utilize the relationship to the Product Module, you use the remote query to f ```ts title="src/api/admin/digital-products/route.ts" collapsibleLines="1-12" expandButtonLabel="Show Imports" import { MedusaRequest, - MedusaResponse + MedusaResponse, } from "@medusajs/medusa" import { MedusaError } from "@medusajs/utils" import { - CreateProductMediaWorkflowInput + CreateProductMediaWorkflowInput, } from "../../../types/digital-product/product-media" import { - createProductMediaWorkflow + createProductMediaWorkflow, } from "../../../workflows/digital-product/create" type CreateProductMediaReq = CreateProductMediaWorkflowInput @@ -709,15 +709,15 @@ To utilize the relationship to the Product Module, you use the remote query to f // validation omitted for simplicity const { result, - errors + errors, } = await createProductMediaWorkflow(req.scope) .run({ input: { data: { - ...req.body - } + ...req.body, + }, }, - throwOnError: false + throwOnError: false, }) if (errors.length) { @@ -728,7 +728,7 @@ To utilize the relationship to the Product Module, you use the remote query to f } res.json({ - product_media: result + product_media: result, }) } ``` @@ -808,7 +808,7 @@ To utilize the relationship to the Product Module, you use the remote query to f import { RemoteQueryFunction } from "@medusajs/modules-sdk" import { ContainerRegistrationKeys, - remoteQueryObjectFromString + remoteQueryObjectFromString, } from "@medusajs/utils" // ... @@ -830,14 +830,14 @@ To utilize the relationship to the Product Module, you use the remote query to f "file_key", "mime_type", "variant.*", - "variant.product.*" + "variant.product.*", ], }) const result = await remoteQuery(query) res.json({ - product_medias: result + product_medias: result, }) } ``` @@ -888,8 +888,8 @@ In your customizations, you send requests to the API routes you created to creat To create the UI route, create the file `src/admin/routes/product-media/page.tsx` with the following content: ```tsx title="src/admin/routes/product-media/page.tsx" badgeLabel="Medusa Application" collapsibleLines="1-13" expandButtonLabel="Show Imports" - import { defineRouteConfig } from "@medusajs/admin-shared"; - import { useEffect, useState } from "react"; + import { defineRouteConfig } from "@medusajs/admin-shared" + import { useEffect, useState } from "react" import { Container, Heading, @@ -993,7 +993,7 @@ In your customizations, you send requests to the API routes you created to creat Input, Label, Select, - Drawer + Drawer, } from "@medusajs/ui" type Props = { @@ -1017,13 +1017,13 @@ In your customizations, you send requests to the API routes you created to creat setLoading(true) const formData = new FormData() - formData.append("files", file); - + formData.append("files", file) + // upload file fetch(`/admin/uploads`, { method: "POST", credentials: "include", - body: formData + body: formData, }) .then((res) => res.json()) .then(({ files }) => { @@ -1032,7 +1032,7 @@ In your customizations, you send requests to the API routes you created to creat method: "POST", credentials: "include", headers: { - "Content-Type": "application/json" + "Content-Type": "application/json", }, body: JSON.stringify({ name, @@ -1043,11 +1043,11 @@ In your customizations, you send requests to the API routes you created to creat title: productName, variants: [ { - title: name - } - ] - } - }) + title: name, + }, + ], + }, + }), }) .then((res) => res.json()) .then(() => { @@ -1216,7 +1216,7 @@ In the subscriber, you can send a notification, such as an email, to the custome import { IOrderModuleService, IFileModuleService, - INotificationModuleService + INotificationModuleService, } from "@medusajs/types" import { ModuleRegistrationName, @@ -1245,7 +1245,7 @@ In the subscriber, you can send a notification, such as an email, to the custome const orderId = "data" in data ? data.data.id : data.id const order = await orderModuleService.retrieve(orderId, { - relations: ["items"] + relations: ["items"], }) // find product medias in the order @@ -1253,7 +1253,7 @@ In the subscriber, you can send a notification, such as an email, to the custome for (const item of order.items) { const productMedias = await digitalProductModuleService .list({ - variant_id: [item.variant_id] + variant_id: [item.variant_id], }) const downloadUrls = await Promise.all( @@ -1325,12 +1325,12 @@ To implement this, create a storefront API Route that allows you to fetch the di MedusaResponse, } from "@medusajs/medusa" import { - MediaType + MediaType, } from "../../../types/digital-product/product-media" import { RemoteQueryFunction } from "@medusajs/modules-sdk" import { ContainerRegistrationKeys, - remoteQueryObjectFromString + remoteQueryObjectFromString, } from "@medusajs/utils" export const GET = async ( @@ -1347,20 +1347,20 @@ To implement this, create a storefront API Route that allows you to fetch the di "name", "file_key", "mime_type", - "variant.*" + "variant.*", ], variables: { filters: { - type: MediaType.PREVIEW + type: MediaType.PREVIEW, }, // omitting pagination for simplicity - skip: 0 - } + skip: 0, + }, }) const { rows, - metadata: { count } + metadata: { count }, } = await remoteQuery(query) res.json({ @@ -2383,11 +2383,11 @@ After the customer purchases the digital product you can show a download button createWorkflow, transform, createStep, - StepResponse + StepResponse, } from "@medusajs/workflows-sdk" import { IOrderModuleService, - IFileModuleService + IFileModuleService, } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import DigitalProductModuleService from "../../modules/digital-product/service" @@ -2405,9 +2405,9 @@ After the customer purchases the digital product you can show a download button "check-variant-purchased-step", async ({ variant_id, - customer_id + customer_id, }: CheckVariantStepInput, { - container + container, }) => { const orderModuleService: IOrderModuleService = container.resolve(ModuleRegistrationName.ORDER) @@ -2489,22 +2489,22 @@ After the customer purchases the digital product you can show a download button checkVariantPurchasedStep(input) const { product_media } = getProductMediaStep({ - variant_id: input.variant_id + variant_id: input.variant_id, }) const url = getFileUrlStep({ - id: product_media.file_key + id: product_media.file_key, }) const result = transform( { url, - product_media + product_media, }, (transformInput) => ({ url: transformInput.url, name: transformInput.product_media.name, - mime_type: transformInput.product_media.mime_type + mime_type: transformInput.product_media.mime_type, }) ) @@ -2528,7 +2528,7 @@ After the customer purchases the digital product you can show a download button MedusaResponse, } from "@medusajs/medusa" import { - getPurchasedProductMediaUrlWorkflow + getPurchasedProductMediaUrlWorkflow, } from "../../../../../workflows/digital-product/get-url" export const GET = async ( @@ -2540,8 +2540,8 @@ After the customer purchases the digital product you can show a download button ).run({ input: { variant_id: req.params.variant_id, - customer_id: req.user.customer_id - } + customer_id: req.user.customer_id, + }, }) res.json(result) @@ -2553,7 +2553,7 @@ After the customer purchases the digital product you can show a download button ```ts title="src/api/middlewares.ts" import { type MiddlewaresConfig, - authenticate + authenticate, } from "@medusajs/medusa" export const config: MiddlewaresConfig = { @@ -2561,7 +2561,7 @@ After the customer purchases the digital product you can show a download button { matcher: "/store/product-media/download/*", middlewares: [ - authenticate("store", ["session", "bearer"]) + authenticate("store", ["session", "bearer"]), ], }, ], diff --git a/www/apps/resources/app/recipes/integrate-ecommerce-stack/page.mdx b/www/apps/resources/app/recipes/integrate-ecommerce-stack/page.mdx index 4db2c3ae74..0cc82561f3 100644 --- a/www/apps/resources/app/recipes/integrate-ecommerce-stack/page.mdx +++ b/www/apps/resources/app/recipes/integrate-ecommerce-stack/page.mdx @@ -67,12 +67,12 @@ export const serviceHighlights = [ this.client_ = axios.create({ baseURL: `https://api.erp-example.com`, headers: { - Authorization: `Bearer ${apiKey}` - } + Authorization: `Bearer ${apiKey}`, + }, }) } - async getProductData (id: string) { + async getProductData(id: string) { const { data: erpProduct } = await this.client_.get(`/product/${id}`) return erpProduct @@ -109,10 +109,10 @@ export const serviceHighlights = [ Then, create the module's definition file at `src/modules/erp/index.ts` with the following content: ```ts title="src/modules/erp/index.ts" - import ErpModuleService from "./service"; - + import ErpModuleService from "./service" + export default { - service: ErpModuleService + service: ErpModuleService, } ``` @@ -125,10 +125,10 @@ export const serviceHighlights = [ erpModuleService: { resolve: "./modules/erp", options: { - apiKey: process.env.ERP_API_KEY - } + apiKey: process.env.ERP_API_KEY, + }, }, - } + }, }) ``` diff --git a/www/apps/resources/app/recipes/marketplace/page.mdx b/www/apps/resources/app/recipes/marketplace/page.mdx index 4101168d7d..e463ab836e 100644 --- a/www/apps/resources/app/recipes/marketplace/page.mdx +++ b/www/apps/resources/app/recipes/marketplace/page.mdx @@ -60,7 +60,7 @@ Create a Marketplace Module that holds and manages these relationships. Then, create the file `src/modules/marketplace/models/store-user.ts` with the following content: ```ts title="src/modules/marketplace/models/store-user.ts" - import { BaseEntity } from "@medusajs/utils"; + import { BaseEntity } from "@medusajs/utils" import { Entity, PrimaryKey, Property } from "@mikro-orm/core" @Entity() @@ -83,7 +83,7 @@ Create a Marketplace Module that holds and manages these relationships. Next, create the file `src/modules/marketplace/models/store-product.ts` with the following content: ```ts title="src/modules/marketplace/models/store-product.ts" - import { BaseEntity } from "@medusajs/utils"; + import { BaseEntity } from "@medusajs/utils" import { Entity, PrimaryKey, Property } from "@mikro-orm/core" @Entity() @@ -106,7 +106,7 @@ Create a Marketplace Module that holds and manages these relationships. Finally, create the file `src/modules/marketplace/models/store-order.ts` with the following content: ```ts title="src/modules/marketplace/models/store-order.ts" - import { BaseEntity } from "@medusajs/utils"; + import { BaseEntity } from "@medusajs/utils" import { Entity, PrimaryKey, Property } from "@mikro-orm/core" @Entity() @@ -138,24 +138,24 @@ Create a Marketplace Module that holds and manages these relationships. To reflect these changes on the database, create the migration `src/modules/marketplace/migrations/Migration20240514143248.ts` with the following content: ```ts title="src/modules/marketplace/migrations/Migration20240514143248.ts" - import { Migration } from '@mikro-orm/migrations'; + import { Migration } from "@mikro-orm/migrations" export class Migration20240514143248 extends Migration { async up(): Promise { - this.addSql('create table if not exists "store_order" ("id" varchar(255) not null, "store_id" text not null, "order_id" text not null, "parent_order_id" text not null, constraint "store_order_pkey" primary key ("id"));'); + this.addSql("create table if not exists \"store_order\" (\"id\" varchar(255) not null, \"store_id\" text not null, \"order_id\" text not null, \"parent_order_id\" text not null, constraint \"store_order_pkey\" primary key (\"id\"));") - this.addSql('create table if not exists "store_product" ("id" varchar(255) not null, "store_id" text not null, "product_id" text not null, constraint "store_product_pkey" primary key ("id"));'); + this.addSql("create table if not exists \"store_product\" (\"id\" varchar(255) not null, \"store_id\" text not null, \"product_id\" text not null, constraint \"store_product_pkey\" primary key (\"id\"));") - this.addSql('create table if not exists "store_user" ("id" varchar(255) not null, "store_id" text not null, "user_id" text not null, constraint "store_user_pkey" primary key ("id"));'); + this.addSql("create table if not exists \"store_user\" (\"id\" varchar(255) not null, \"store_id\" text not null, \"user_id\" text not null, constraint \"store_user_pkey\" primary key (\"id\"));") } async down(): Promise { - this.addSql('drop table if exists "store_order" cascade;'); + this.addSql("drop table if exists \"store_order\" cascade;") - this.addSql('drop table if exists "store_product" cascade;'); + this.addSql("drop table if exists \"store_product\" cascade;") - this.addSql('drop table if exists "store_user" cascade;'); + this.addSql("drop table if exists \"store_user\" cascade;") } } @@ -173,7 +173,7 @@ Create a Marketplace Module that holds and manages these relationships. StoreDTO, UserDTO, ProductDTO, - OrderDTO + OrderDTO, } from "@medusajs/types" export type StoreUserDTO = { @@ -231,21 +231,21 @@ export const mainServiceHighlights = [ ```ts title="src/modules/marketplace/service.ts" highlights={mainServiceHighlights} collapsibleLines="1-17" expandButtonLabel="Show Imports" import { ModulesSdkUtils, Modules } from "@medusajs/utils" - import StoreUser from "./models/store-user"; - import StoreProduct from "./models/store-product"; - import StoreOrder from "./models/store-order"; + import StoreUser from "./models/store-user" + import StoreProduct from "./models/store-product" + import StoreOrder from "./models/store-order" import { CreateStoreOrderDTO, CreateStoreProductDTO, CreateStoreUserDTO, StoreOrderDTO, StoreProductDTO, - StoreUserDTO - } from "../../types/marketplace"; + StoreUserDTO, + } from "../../types/marketplace" import { ModuleJoinerConfig, - ModulesSdkTypes - } from "@medusajs/types"; + ModulesSdkTypes, + } from "@medusajs/types" type InjectedDependencies = { storeUserService: ModulesSdkTypes.InternalModuleService< @@ -273,7 +273,7 @@ export const mainServiceHighlights = [ const generateMethodsFor = [ StoreProduct, - StoreOrder + StoreOrder, ] class MarketplaceModuleService extends ModulesSdkUtils @@ -297,7 +297,7 @@ export const mainServiceHighlights = [ constructor({ storeUserService, storeProductService, - storeOrderService + storeOrderService, }: InjectedDependencies) { // @ts-ignore super(...arguments) @@ -313,50 +313,50 @@ export const mainServiceHighlights = [ { name: ["store_user"], args: { - entity: StoreUser.name - } + entity: StoreUser.name, + }, }, { name: ["store_product"], args: { entity: StoreProduct.name, - methodSuffix: "StoreProducts" - } + methodSuffix: "StoreProducts", + }, }, { name: ["store_order"], args: { entity: StoreOrder.name, - methodSuffix: "StoreOrders" - } - } + methodSuffix: "StoreOrders", + }, + }, ], relationships: [ { serviceName: Modules.STORE, alias: "store", primaryKey: "id", - foreignKey: "store_id" + foreignKey: "store_id", }, { serviceName: Modules.USER, alias: "user", primaryKey: "id", - foreignKey: "user_id" + foreignKey: "user_id", }, { serviceName: Modules.PRODUCT, alias: "product", primaryKey: "id", - foreignKey: "product_id" + foreignKey: "product_id", }, { serviceName: Modules.ORDER, alias: "order", primaryKey: "id", - foreignKey: "order_id" - } - ] + foreignKey: "order_id", + }, + ], } } @@ -401,7 +401,7 @@ export const mainServiceHighlights = [ Finally, create the module definition at `src/modules/marketplace/index.ts` with the following content: ```ts title="src/modules/marketplace/index.ts" - import MarketplaceModuleService from "./service"; + import MarketplaceModuleService from "./service" export default { service: MarketplaceModuleService, @@ -417,10 +417,10 @@ export const mainServiceHighlights = [ marketplaceModuleService: { resolve: "./modules/marketplace", definition: { - isQueryable: true - } + isQueryable: true, + }, }, - } + }, }) ``` @@ -463,13 +463,13 @@ export const userSubscriberHighlights = [ import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { IUserModuleService, - IStoreModuleService + IStoreModuleService, } from "@medusajs/types" import MarketplaceModuleService from "../modules/marketplace/service" export default async function userCreatedHandler({ data, - container + container, }: SubscriberArgs<{ id: string }>) { const { id } = data.data || { data } const userModuleService: IUserModuleService = container.resolve( @@ -485,12 +485,12 @@ export const userSubscriberHighlights = [ const user = await userModuleService.retrieve(id) const store = await storeModuleService.create({ - name: `${user.first_name}'s Store` + name: `${user.first_name}'s Store`, }) const storeUser = await marketplaceModuleService.create({ store_id: store.id, - user_id: user.id + user_id: user.id, }) console.log(`Created StoreUser ${storeUser.id}`) @@ -551,7 +551,7 @@ export const productSubscriberHighlights = [ export default async function productCreateHandler({ data, - container + container, }: SubscriberArgs<{ id: string }>) { const { id } = data.data || data const productModuleService: IProductModuleService = container.resolve( @@ -570,7 +570,7 @@ export const productSubscriberHighlights = [ await marketplaceModuleService.createStoreProduct({ store_id: product.metadata.store_id as string, - product_id: id + product_id: id, }) } @@ -646,13 +646,13 @@ export const productRoutesHighlights = [ ```ts title="src/api/admin/marketplace/products/route.ts" highlights={productRoutesHighlights} collapsibleLines="1-13" expandButtonLabel="Show Imports" import { AuthenticatedMedusaRequest, - MedusaResponse + MedusaResponse, } from "@medusajs/medusa" import { RemoteQueryFunction } from "@medusajs/modules-sdk" import { remoteQueryObjectFromString, ContainerRegistrationKeys, - MedusaError + MedusaError, } from "@medusajs/utils" import MarketplaceModuleService from "../../../../modules/marketplace/service" @@ -670,7 +670,7 @@ export const productRoutesHighlights = [ ) const storeUsers = await marketplaceModuleService.list({ - user_id: req.auth.actor_id + user_id: req.auth.actor_id, }) if (!storeUsers.length) { @@ -683,20 +683,20 @@ export const productRoutesHighlights = [ const query = remoteQueryObjectFromString({ entryPoint: "store_product", fields: [ - "product.*" + "product.*", ], variables: { filters: { - store_id: storeUsers[0].store_id - } - } + store_id: storeUsers[0].store_id, + }, + }, }) const result = await remoteQuery(query) res.json({ store_id: storeUsers[0].store_id, - products: result.map((data) => data.product) + products: result.map((data) => data.product), }) } ``` @@ -712,7 +712,7 @@ export const productRoutesHighlights = [ ```ts title="src/api/middlewares.ts" import { MiddlewaresConfig, - authenticate + authenticate, } from "@medusajs/medusa" export const config: MiddlewaresConfig = { @@ -779,12 +779,12 @@ export const orderSubscriberHighlights = [ ```ts title="src/subscribers/order-created.ts" highlights={orderSubscriberHighlights} collapsibleLines="1-13" expandButtonLabel="Show Imports" import type { SubscriberArgs, - SubscriberConfig + SubscriberConfig, } from "@medusajs/medusa" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { IOrderModuleService, - CreateOrderDTO + CreateOrderDTO, } from "@medusajs/types" import MarketplaceModuleService from "../modules/marketplace/service" @@ -792,7 +792,7 @@ export const orderSubscriberHighlights = [ export default async function orderCreatedHandler({ data, - container + container, }: SubscriberArgs<{ id: string }>) { const { id } = data.data || data const orderModuleService: IOrderModuleService = @@ -808,13 +808,13 @@ export const orderSubscriberHighlights = [ const storeToOrders: Record = {} const order = await orderModuleService.retrieve(id, { - relations: ["items"] + relations: ["items"], }) await Promise.all(order.items?.map(async (item) => { const storeProduct = await marketplaceModuleService .listStoreProducts({ - product_id: item.product_id + product_id: item.product_id, }) if (!storeProduct.length) { @@ -827,7 +827,7 @@ export const orderSubscriberHighlights = [ const { id, ...orderDetails } = order storeToOrders[storeId] = { ...orderDetails, - items: [] + items: [], } } @@ -850,7 +850,7 @@ export const orderSubscriberHighlights = [ // associate the order as-is with the store. await marketplaceModuleService.createStoreOrder({ store_id: storeToOrdersKeys[0], - order_id: order.id + order_id: order.id, }) return @@ -861,13 +861,13 @@ export const orderSubscriberHighlights = [ storeToOrdersKeys.map(async (storeId) => { const { result } = await createOrdersWorkflow(container) .run({ - input: storeToOrders[storeId] + input: storeToOrders[storeId], }) await marketplaceModuleService.createStoreOrder({ store_id: storeId, order_id: result.id, - parent_order_id: order.id + parent_order_id: order.id, }) }) ) @@ -928,7 +928,7 @@ export const orderRoutesHighlights = [ ```ts title="src/api/admin/marketplace/orders/route.ts" highlights={orderRoutesHighlights} collapsibleLines="1-12" expandButtonLabel="Show Imports" import { AuthenticatedMedusaRequest, - MedusaResponse + MedusaResponse, } from "@medusajs/medusa" import { RemoteQueryFunction } from "@medusajs/modules-sdk" import { @@ -951,25 +951,25 @@ export const orderRoutesHighlights = [ ) const storeUsers = await marketplaceModuleService.list({ - user_id: req.auth.actor_id + user_id: req.auth.actor_id, }) const query = remoteQueryObjectFromString({ entryPoint: "store_order", fields: [ - "order.*" + "order.*", ], variables: { filters: { - store_id: storeUsers[0].store_id - } - } + store_id: storeUsers[0].store_id, + }, + }, }) const result = await remoteQuery(query) res.json({ - orders: result.map((data) => data.order) + orders: result.map((data) => data.order), }) } diff --git a/www/apps/resources/app/storefront-development/cart/context/page.mdx b/www/apps/resources/app/storefront-development/cart/context/page.mdx index aa5e5e4432..53a11dd935 100644 --- a/www/apps/resources/app/storefront-development/cart/context/page.mdx +++ b/www/apps/resources/app/storefront-development/cart/context/page.mdx @@ -35,7 +35,7 @@ import { createContext, useContext, useEffect, - useState + useState, } from "react" import { HttpTypes } from "@medusajs/types" import { useRegion } from "./region" @@ -73,11 +73,11 @@ export const CartProvider = ({ children }: CartProviderProps) => { credentials: "include", headers: { "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp", - "Content-Type": "application/json" + "Content-Type": "application/json", }, body: JSON.stringify({ region_id: region.id, - }) + }), }) .then((res) => res.json()) .then(({ cart: dataCart }) => { @@ -87,7 +87,7 @@ export const CartProvider = ({ children }: CartProviderProps) => { } else { // retrieve cart fetch(`http://localhost:9000/store/carts/${cartId}`, { - credentials: "include" + credentials: "include", }) .then((res) => res.json()) .then(({ cart: dataCart }) => { @@ -105,7 +105,7 @@ export const CartProvider = ({ children }: CartProviderProps) => { {children} @@ -147,7 +147,7 @@ const inter = Inter({ subsets: ["latin"] }) export const metadata: Metadata = { title: "Create Next App", description: "Generated by create next app", -}; +} export default function RootLayout({ children, diff --git a/www/apps/resources/app/storefront-development/cart/create/page.mdx b/www/apps/resources/app/storefront-development/cart/create/page.mdx index 771902e121..1ac67ef409 100644 --- a/www/apps/resources/app/storefront-development/cart/create/page.mdx +++ b/www/apps/resources/app/storefront-development/cart/create/page.mdx @@ -31,11 +31,11 @@ export const fetchHighlights = [ credentials: "include", headers: { "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp", - "Content-Type": "application/json" + "Content-Type": "application/json", }, body: JSON.stringify({ region_id: region.id, - }) + }), }) .then((res) => res.json()) .then(({ cart }) => { @@ -58,9 +58,9 @@ export const highlights = [ ```tsx highlights={highlights} "use client" // include with Next.js 13+ - import { useEffect, useState } from "react"; + import { useEffect, useState } from "react" // other imports... - + export default function Home() { // TODO assuming you have the region retrieved const region = { @@ -82,11 +82,11 @@ export const highlights = [ credentials: "include", headers: { "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp", - "Content-Type": "application/json" + "Content-Type": "application/json", }, body: JSON.stringify({ region_id: region.id, - }) + }), }) .then((res) => res.json()) .then(({ cart }) => { @@ -130,8 +130,8 @@ fetch(`http://localhost:9000/store/carts`, { // ... body: JSON.stringify({ // ... - customer_id: customer.id - }) + customer_id: customer.id, + }), }) .then((res) => res.json()) .then(({ cart }) => { diff --git a/www/apps/resources/app/storefront-development/cart/manage-items/page.mdx b/www/apps/resources/app/storefront-development/cart/manage-items/page.mdx index b8d7bc5729..62245bbcc5 100644 --- a/www/apps/resources/app/storefront-development/cart/manage-items/page.mdx +++ b/www/apps/resources/app/storefront-development/cart/manage-items/page.mdx @@ -34,12 +34,12 @@ const addToCart = (variant_id: string) => { credentials: "include", method: "POST", headers: { - "Content-Type": "application/json" + "Content-Type": "application/json", }, body: JSON.stringify({ variant_id, quantity: 1, - }) + }), }) .then((res) => res.json()) .then(({ cart }) => { @@ -89,11 +89,11 @@ const updateQuantity = ( credentials: "include", method: "POST", headers: { - "Content-Type": "application/json" + "Content-Type": "application/json", }, body: JSON.stringify({ - quantity - }) + quantity, + }), }) .then((res) => res.json()) .then(({ cart }) => { diff --git a/www/apps/resources/app/storefront-development/cart/retrieve/page.mdx b/www/apps/resources/app/storefront-development/cart/retrieve/page.mdx index a990d2dd9c..80727ad64a 100644 --- a/www/apps/resources/app/storefront-development/cart/retrieve/page.mdx +++ b/www/apps/resources/app/storefront-development/cart/retrieve/page.mdx @@ -21,7 +21,7 @@ export const fetchHighlights = [ ```ts highlights={fetchHighlights} fetch(`http://localhost:9000/store/carts/${cartId}`, { - credentials: "include" + credentials: "include", }) .then((res) => res.json()) .then(({ cart }) => { @@ -47,7 +47,7 @@ export const highlights = [ import { useEffect, useState } from "react" import { HttpTypes } from "@medusajs/types" - export default function Cart () { + export default function Cart() { const [cart, setCart] = useState< HttpTypes.StoreCart >() @@ -64,7 +64,7 @@ export const highlights = [ } fetch(`http://localhost:9000/store/carts/${cartId}`, { - credentials: "include" + credentials: "include", }) .then((res) => res.json()) .then(({ cart: dataCart }) => { diff --git a/www/apps/resources/app/storefront-development/cart/update/page.mdx b/www/apps/resources/app/storefront-development/cart/update/page.mdx index e6c2586f0b..e1cc75018f 100644 --- a/www/apps/resources/app/storefront-development/cart/update/page.mdx +++ b/www/apps/resources/app/storefront-development/cart/update/page.mdx @@ -29,11 +29,11 @@ fetch(`http://localhost:9000/store/carts/${cartId}`, { credentials: "include", method: "POST", headers: { - "Content-Type": "application/json" + "Content-Type": "application/json", }, body: JSON.stringify({ - region_id: "new_id" - }) + region_id: "new_id", + }), }) .then((res) => res.json()) .then(({ cart }) => { @@ -61,11 +61,11 @@ fetch(`http://localhost:9000/store/carts/${cartId}`, { credentials: "include", method: "POST", headers: { - "Content-Type": "application/json" + "Content-Type": "application/json", }, body: JSON.stringify({ - customer_id: "logged_in_id" - }) + customer_id: "logged_in_id", + }), }) .then((res) => res.json()) .then(({ cart }) => { diff --git a/www/apps/resources/app/storefront-development/checkout/address/page.mdx b/www/apps/resources/app/storefront-development/checkout/address/page.mdx index 4174704859..989417d95a 100644 --- a/www/apps/resources/app/storefront-development/checkout/address/page.mdx +++ b/www/apps/resources/app/storefront-development/checkout/address/page.mdx @@ -29,19 +29,19 @@ For example: city, country_code, province, - phone + phone, } fetch(`http://localhost:9000/store/carts/${cartId}`, { credentials: "include", method: "POST", headers: { - "Content-Type": "application/json" + "Content-Type": "application/json", }, body: JSON.stringify({ shipping_address: address, - billing_address: address - }) + billing_address: address, + }), }) .then((res) => res.json()) .then(({ cart }) => { @@ -64,10 +64,10 @@ export const highlights = [ ```tsx highlights={highlights} "use client" // include with Next.js 13+ - import { useState } from "react"; - import { useCart } from "../../../providers/cart"; - - export default function CheckoutAddressStep () { + import { useState } from "react" + import { useCart } from "../../../providers/cart" + + export default function CheckoutAddressStep() { const { cart, setCart } = useCart() const [loading, setLoading] = useState(false) const [firstName, setFirstName] = useState("") @@ -99,19 +99,19 @@ export const highlights = [ city, country_code: countryCode, province, - phone: phoneNumber + phone: phoneNumber, } fetch(`http://localhost:9000/store/carts/${cart.id}`, { credentials: "include", method: "POST", headers: { - "Content-Type": "application/json" + "Content-Type": "application/json", }, body: JSON.stringify({ shipping_address: address, - billing_address: address - }) + billing_address: address, + }), }) .then((res) => res.json()) .then(({ cart: updatedCart }) => { diff --git a/www/apps/resources/app/storefront-development/checkout/complete-cart/page.mdx b/www/apps/resources/app/storefront-development/checkout/complete-cart/page.mdx index 90b25b8ef2..ea58531a66 100644 --- a/www/apps/resources/app/storefront-development/checkout/complete-cart/page.mdx +++ b/www/apps/resources/app/storefront-development/checkout/complete-cart/page.mdx @@ -17,7 +17,7 @@ fetch( `http://localhost:9000/store/carts/${cartId}/complete`, { credentials: "include", - method: "POST" + method: "POST", } ) .then((res) => res.json()) @@ -65,7 +65,7 @@ export const highlights = [ import { useState } from "react" import { useCart } from "../../providers/cart" -export default function SystemDefaultPayment () { +export default function SystemDefaultPayment() { const { cart, refreshCart } = useCart() const [loading, setLoading] = useState(false) @@ -87,7 +87,7 @@ export default function SystemDefaultPayment () { `http://localhost:9000/store/carts/${cart.id}/complete`, { credentials: "include", - method: "POST" + method: "POST", } ) .then((res) => res.json()) diff --git a/www/apps/resources/app/storefront-development/checkout/email/page.mdx b/www/apps/resources/app/storefront-development/checkout/email/page.mdx index 011a02c5f2..addc44b079 100644 --- a/www/apps/resources/app/storefront-development/checkout/email/page.mdx +++ b/www/apps/resources/app/storefront-development/checkout/email/page.mdx @@ -26,11 +26,11 @@ For example: credentials: "include", method: "POST", headers: { - "Content-Type": "application/json" + "Content-Type": "application/json", }, body: JSON.stringify({ - email - }) + email, + }), }) .then((res) => res.json()) .then(({ cart }) => { @@ -55,7 +55,7 @@ export const highlights = [ import { useState } from "react" import { useCart } from "../../../providers/cart" - export default function CheckoutEmailStep () { + export default function CheckoutEmailStep() { const { cart, setCart } = useCart() const [email, setEmail] = useState("") const [loading, setLoading] = useState(false) @@ -80,11 +80,11 @@ export const highlights = [ credentials: "include", method: "POST", headers: { - "Content-Type": "application/json" + "Content-Type": "application/json", }, body: JSON.stringify({ - email - }) + email, + }), }) .then((res) => res.json()) .then(({ cart: updatedCart }) => { diff --git a/www/apps/resources/app/storefront-development/checkout/payment/page.mdx b/www/apps/resources/app/storefront-development/checkout/payment/page.mdx index 9dd569101b..2b72bd505c 100644 --- a/www/apps/resources/app/storefront-development/checkout/payment/page.mdx +++ b/www/apps/resources/app/storefront-development/checkout/payment/page.mdx @@ -57,7 +57,7 @@ export const fetchHighlights = [ `http://localhost:9000/store/payment-providers?region_id=${ cart.region_id }`, { - credentials: "include" + credentials: "include", }) .then((res) => res.json()) @@ -77,14 +77,14 @@ export const fetchHighlights = [ credentials: "include", method: "POST", headers: { - "Content-Type": "application/json" + "Content-Type": "application/json", }, body: JSON.stringify({ cart_id: cart.id, region_id: cart.region_id, currency_code: cart.currency_code, - amount: cart.total - }) + amount: cart.total, + }), } ) .then((res) => res.json()) @@ -100,21 +100,21 @@ export const fetchHighlights = [ credentials: "include", method: "POST", headers: { - "Content-Type": "application/json" + "Content-Type": "application/json", }, body: JSON.stringify({ - provider_id: selectedPaymentProviderId - }) + provider_id: selectedPaymentProviderId, + }), }) .then((res) => res.json()) // re-fetch cart const { - cart: updatedCart + cart: updatedCart, } = await fetch( `http://localhost:9000/store/carts/${cart.id}`, { - credentials: "include" + credentials: "include", } ) .then((res) => res.json()) @@ -171,14 +171,14 @@ export const highlights = [ import { useCart } from "../../../providers/cart" import { HttpTypes } from "@medusajs/types" - export default function CheckoutPaymentStep () { + export default function CheckoutPaymentStep() { const { cart, setCart } = useCart() const [paymentProviders, setPaymentProviders] = useState< HttpTypes.StorePaymentProvider[] >([]) const [ selectedPaymentProvider, - setSelectedPaymentProvider + setSelectedPaymentProvider, ] = useState() const [loading, setLoading] = useState(false) @@ -190,7 +190,7 @@ export const highlights = [ fetch(`http://localhost:9000/store/payment-providers?region_id=${ cart.region_id }`, { - credentials: "include" + credentials: "include", }) .then((res) => res.json()) .then(({ payment_providers }) => { @@ -221,14 +221,14 @@ export const highlights = [ credentials: "include", method: "POST", headers: { - "Content-Type": "application/json" + "Content-Type": "application/json", }, body: JSON.stringify({ cart_id: cart.id, region_id: cart.region_id, currency_code: cart.currency_code, - amount: cart.total - }) + amount: cart.total, + }), } ) .then((res) => res.json()) @@ -244,21 +244,21 @@ export const highlights = [ credentials: "include", method: "POST", headers: { - "Content-Type": "application/json" + "Content-Type": "application/json", }, body: JSON.stringify({ - provider_id: selectedPaymentProvider - }) + provider_id: selectedPaymentProvider, + }), }) .then((res) => res.json()) // re-fetch cart const { - cart: updatedCart + cart: updatedCart, } = await fetch( `http://localhost:9000/store/carts/${cart.id}`, { - credentials: "include" + credentials: "include", } ) .then((res) => res.json()) diff --git a/www/apps/resources/app/storefront-development/checkout/payment/stripe/page.mdx b/www/apps/resources/app/storefront-development/checkout/payment/stripe/page.mdx index 88ad116820..d10812bdd5 100644 --- a/www/apps/resources/app/storefront-development/checkout/payment/stripe/page.mdx +++ b/www/apps/resources/app/storefront-development/checkout/payment/stripe/page.mdx @@ -75,7 +75,7 @@ import { CardElement, Elements, useElements, - useStripe + useStripe, } from "@stripe/react-stripe-js" import { loadStripe } from "@stripe/stripe-js" import { useCart } from "../../providers/cart" @@ -102,7 +102,7 @@ export default function StripePayment() { } const StripeForm = ({ - clientSecret + clientSecret, }: { clientSecret: string | undefined }) => { @@ -157,7 +157,7 @@ const StripeForm = ({ `http://localhost:9000/store/carts/${cart.id}/complete`, { credentials: "include", - method: "POST" + method: "POST", } ) .then((res) => res.json()) diff --git a/www/apps/resources/app/storefront-development/checkout/shipping/page.mdx b/www/apps/resources/app/storefront-development/checkout/shipping/page.mdx index dd88637f25..2d4d51d27e 100644 --- a/www/apps/resources/app/storefront-development/checkout/shipping/page.mdx +++ b/www/apps/resources/app/storefront-development/checkout/shipping/page.mdx @@ -32,7 +32,7 @@ export const fetchHighlights = [ `http://localhost:9000/store/shipping-options?cart_id=${ cart.id }`, { - credentials: "include" + credentials: "include", } ) .then((res) => res.json()) @@ -49,15 +49,15 @@ export const fetchHighlights = [ credentials: "include", method: "POST", headers: { - "Content-Type": "application/json" + "Content-Type": "application/json", }, body: JSON.stringify({ option_id: selectedShippingOptionId, data: { // TODO add any data necessary for // fulfillment provider - } - }) + }, + }), }) .then((res) => res.json()) .then(({ cart }) => { @@ -84,7 +84,7 @@ export const highlights = [ import { useCart } from "../../../providers/cart" import { HttpTypes } from "@medusajs/types" - export default function CheckoutShippingStep () { + export default function CheckoutShippingStep() { const { cart, setCart } = useCart() const [loading, setLoading] = useState(false) const [shippingOptions, setShippingOptions] = useState< @@ -92,7 +92,7 @@ export const highlights = [ >([]) const [ selectedShippingOption, - setSelectedShippingOption + setSelectedShippingOption, ] = useState() useEffect(() => { @@ -102,7 +102,7 @@ export const highlights = [ fetch(`http://localhost:9000/store/shipping-options?cart_id=${ cart.id }`, { - credentials: "include" + credentials: "include", }) .then((res) => res.json()) .then(({ shipping_options }) => { @@ -126,15 +126,15 @@ export const highlights = [ credentials: "include", method: "POST", headers: { - "Content-Type": "application/json" + "Content-Type": "application/json", }, body: JSON.stringify({ option_id: selectedShippingOption, data: { // TODO add any data necessary for // fulfillment provider - } - }) + }, + }), }) .then((res) => res.json()) .then(({ cart: updatedCart }) => { diff --git a/www/apps/resources/app/storefront-development/customers/addresses/page.mdx b/www/apps/resources/app/storefront-development/customers/addresses/page.mdx new file mode 100644 index 0000000000..bde76f6fdc --- /dev/null +++ b/www/apps/resources/app/storefront-development/customers/addresses/page.mdx @@ -0,0 +1,570 @@ +import { CodeTabs, CodeTab } from "docs-ui" + +export const metadata = { + title: `Manage Customer Addresses in Storefront`, +} + +# {metadata.title} + +In this document, you'll learn how to manage a customer's addresses in a storefront. + +## List Customer Addresses + +To retrieve the list of customer addresses, send a request to the [List Customer Addresses API route](!api!/store#customers_getcustomersmeaddressesaddress_id): + + + + +export const fetchHighlights = [ + ["2", "limit", "The number of addresses to retrieve"], + ["3", "offset", "The number of addresses to skip before those retrieved."], +] + + ```ts highlights={fetchHighlights} + const searchParams = new URLSearchParams({ + limit: `${limit}`, + offset: `${offset}`, + }) + + fetch(`http://localhost:9000/store/customers/me/addresses?${ + searchParams.toString() + }`, { + credentials: "include", + }) + .then((res) => res.json()) + .then(({ addresses, count }) => { + // use addresses... + console.log(addresses, count) + }) + ``` + + + + +export const highlights = [ + ["20", "offset", "Calculate the number of addresses to skip based on the current page and limit."], + ["27", "fetch", "Send a request to retrieve the addresses."], + ["28", "searchParams.toString()", "Pass the pagination parameters in the query."], + ["33", "count", "The total number of addresses in the Medusa application."], + ["45", "setHasMorePages", "Set whether there are more pages based on the total count."], + ["59", "", "Using only two address fields for simplicity."], + ["65", "button", "Show a button to load more addresses if there are more pages."] +] + + ```tsx highlights={highlights} collapsibleLines="50-77" expandButtonLabel="Show render" + "use client" // include with Next.js 13+ + + import { HttpTypes } from "@medusajs/types" + import { useEffect, useState } from "react" + + export default function Addresses() { + const [addresses, setAddresses] = useState< + HttpTypes.StoreCustomerAddress[] + >([]) + const [loading, setLoading] = useState(true) + const limit = 20 + const [currentPage, setCurrentPage] = useState(1) + const [hasMorePages, setHasMorePages] = useState(false) + + useEffect(() => { + if (!loading) { + return + } + + const offset = (currentPage - 1) * limit + + const searchParams = new URLSearchParams({ + limit: `${limit}`, + offset: `${offset}`, + }) + + fetch(`http://localhost:9000/store/customers/me/addresses?${ + searchParams.toString() + }`, { + credentials: "include", + }) + .then((res) => res.json()) + .then(({ addresses: addressesData, count }) => { + setAddresses((prev) => { + if (prev.length > offset) { + // addresses already added because + // the same request has already been sent + return prev + } + return [ + ...prev, + ...addressesData, + ] + }) + setHasMorePages(count > limit * currentPage) + }) + .finally(() => setLoading(false)) + }, [loading]) + + return ( +
+ {loading && Loading...} + {!loading && !addresses.length && ( + You have no addresses + )} +
    + {addresses.map((address) => ( +
  • + City: {address.city} - + Country: {address.country_code} +
  • + ))} +
+ {!loading && hasMorePages && ( + + )} +
+ ) + } + ``` + +
+
+ +The List Customer Addresses API route accepts pagination parameters to paginate the address. + +{/* TODO add a link to the address object */} + +It returns in the response the `addresses` field, which is an array of addresses. + +--- + +## Add Customer Address + +To add a new address for the customer, send a request to the [Add Customer Address API route](!api!/store#customers_postcustomersmeaddresses): + + + + + ```ts + fetch(`http://localhost:9000/store/customers/me/addresses`, { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + first_name: firstName, + last_name: lastName, + address_1: address1, + company, + postal_code: postalCode, + city, + country_code: countryCode, + province, + phone: phoneNumber, + }), + }) + .then((res) => res.json()) + .then(({ customer }) => { + // use customer + console.log(customer) + }) + ``` + + + + +export const addHighlights = [ + ["4", "useRegion", "Use the hook defined in the Region Context guide."], + ["5", "useCustomer", "Use the hook defined in the Customer Context guide."], + ["28"], ["29"], ["30"], ["31"], ["32"], ["33"], ["34"], ["35"], ["36"], ["37"], + ["38"], ["39"], ["40"], ["41"], ["42"], ["43"], ["44"], ["45"], ["46"], ["47"], + ["48"], ["49"] +] + + ```tsx highlights={addHighlights} collapsibleLines="53-124" expandButtonLabel="Show form" + "use client" // include with Next.js 13+ + + import { useState } from "react" + import { useRegion } from "../../../../providers/region" + import { useCustomer } from "../../../../providers/customer" + + export default function AddAddress() { + const { region } = useRegion() + const { setCustomer } = useCustomer() + + const [loading, setLoading] = useState(false) + const [firstName, setFirstName] = useState("") + const [lastName, setLastName] = useState("") + const [address1, setAddress1] = useState("") + const [company, setCompany] = useState("") + const [postalCode, setPostalCode] = useState("") + const [city, setCity] = useState("") + const [countryCode, setCountryCode] = useState("") + const [province, setProvince] = useState("") + const [phoneNumber, setPhoneNumber] = useState("") + + const handleAdd = ( + e: React.MouseEvent + ) => { + e.preventDefault() + setLoading(false) + + fetch(`http://localhost:9000/store/customers/me/addresses`, { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + first_name: firstName, + last_name: lastName, + address_1: address1, + company, + postal_code: postalCode, + city, + country_code: countryCode, + province, + phone: phoneNumber, + }), + }) + .then((res) => res.json()) + .then(({ customer }) => { + setCustomer(customer) + }) + .finally(() => setLoading(false)) + } + + return ( +
+ setFirstName(e.target.value)} + /> + setLastName(e.target.value)} + /> + setAddress1(e.target.value)} + /> + setCompany(e.target.value)} + /> + setPostalCode(e.target.value)} + /> + setCity(e.target.value)} + /> + + setProvince(e.target.value)} + /> + setPhoneNumber(e.target.value)} + /> + +
+ ) + } + ``` + +
+
+ +The Add Address API route returns in the response a `customer` field, which is a [customer object](!api!/store#customers_customer_schema). + +--- + +## Edit an Address + +To edit an address, send a request to the [Update Customer Address API route](!api!/store#customers_postcustomersmeaddressesaddress_id): + + + + + ```ts + fetch( + `http://localhost:9000/store/customers/me/addresses/${ + address.id + }`, + { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + first_name: firstName, + last_name: lastName, + address_1: address1, + company, + postal_code: postalCode, + city, + country_code: countryCode, + province, + phone: phoneNumber, + }), + } + ) + .then((res) => res.json()) + .then(({ customer }) => { + // use customer... + console.log(customer) + }) + ``` + + + + +export const editHighlights = [ + ["4", "useRegion", "Use the hook defined in the Region Context guide."], + ["5", "useCustomer", "Use the hook defined in the Customer Context guide."], + ["14", "{ params: { id }}", "This is based on Next.js which passes the path parameters as a prop."], + ["19", "address", "Retrieve the address from the customer's `addresses` property."], + ["60"], ["61"], ["62"], ["63"], ["64"], ["65"], ["66"], ["67"], ["68"], ["69"], + ["70"], ["71"], ["72"], ["73"], ["74"], ["75"], ["76"], ["77"], ["78"], ["79"], + ["80"], ["81"] +] + + ```tsx highlights={editHighlights} collapsibleLines="90-161" expandButtonLabel="Show form" + "use client" // include with Next.js 13+ + + import { useState } from "react" + import { useRegion } from "../../../../../providers/region" + import { useCustomer } from "../../../../../providers/customer" + + type Params = { + params: { + id: string + } + } + + export default function EditAddress( + { params: { id } }: Params + ) { + const { customer, setCustomer } = useCustomer() + const { region } = useRegion() + + const address = customer?.addresses.find( + (address) => address.id === id + ) + const [loading, setLoading] = useState(false) + const [firstName, setFirstName] = useState( + address?.first_name || "" + ) + const [lastName, setLastName] = useState( + address?.last_name || "" + ) + const [address1, setAddress1] = useState( + address?.address_1 || "" + ) + const [company, setCompany] = useState( + address?.company || "" + ) + const [postalCode, setPostalCode] = useState( + address?.postal_code || "" + ) + const [city, setCity] = useState( + address?.city || "" + ) + const [countryCode, setCountryCode] = useState( + address?.country_code || "" + ) + const [province, setProvince] = useState( + address?.province || "" + ) + const [phoneNumber, setPhoneNumber] = useState( + address?.phone || "" + ) + + const handleEdit = ( + e: React.MouseEvent + ) => { + e.preventDefault() + if (!customer || !address) { + return + } + setLoading(true) + + fetch( + `http://localhost:9000/store/customers/me/addresses/${ + address.id + }`, + { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + first_name: firstName, + last_name: lastName, + address_1: address1, + company, + postal_code: postalCode, + city, + country_code: countryCode, + province, + phone: phoneNumber, + }), + } + ) + .then((res) => res.json()) + .then(({ customer }) => { + setCustomer(customer) + }) + .finally(() => setLoading(false)) + } + + return ( +
+ setFirstName(e.target.value)} + /> + setLastName(e.target.value)} + /> + setAddress1(e.target.value)} + /> + setCompany(e.target.value)} + /> + setPostalCode(e.target.value)} + /> + setCity(e.target.value)} + /> + + setProvince(e.target.value)} + /> + setPhoneNumber(e.target.value)} + /> + +
+ ) + } + ``` + +
+
+ +The Update Address API route returns in the response a `customer` field, which is a [customer object](!api!/store#customers_customer_schema). + +--- + +## Delete Customer Address + +To delete a customer's address, send a request to the [Delete Customer Address API route](!api!/store#customers_deletecustomersmeaddressesaddress_id): + +export const deleteHighlights = [ + ["3", "addrId", "The ID of the address to delete."] +] + +```ts highlights={deleteHighlights} +fetch( + `http://localhost:9000/store/customers/me/addresses/${ + addrId + }`, + { + credentials: "include", + method: "DELETE", + } +) +.then((res) => res.json()) +.then(({ parent: customer }) => { + // use customer... + console.log(customer) +}) +``` + +The Delete Customer Address API route returns a `parent` field in the response, which is a [customer object](!api!/store#customers_customer_schema). diff --git a/www/apps/resources/app/storefront-development/customers/context/page.mdx b/www/apps/resources/app/storefront-development/customers/context/page.mdx new file mode 100644 index 0000000000..afea21246a --- /dev/null +++ b/www/apps/resources/app/storefront-development/customers/context/page.mdx @@ -0,0 +1,160 @@ +export const metadata = { + title: `Customer Context in Storefront`, +} + +# {metadata.title} + +Throughout your storefront, you'll need to access the logged-in customer to perform different actions, such as associate it with a cart. + +So, if your storefront is React-based, create a customer context and add it at the top of your components tree. Then, you can access the logged-in customer anywhere in your storefront. + +## Create Customer Context Provider + +For example, create the following file that exports a `CustomerProvider` component and a `useCustomer` hook: + +export const highlights = [ + ["12", "customer", "Expose customer to children of the context provider."], + ["13", "setCustomer", "Allow the context provider's\nchildren to change the logged-in customer."], + ["24", "CustomerProvider", "The provider component to use in your component tree."], + ["36", "fetch", "Try to retrieve the customer's details,\nif the customer is authentiated."], + ["37", `credentials: "include"`, "Important to include this option for cookie session authentication.\nFor token authentication, pass the authorization header instead."], + ["58", "useCustomer", "The hook that child components of the provider use to access the customer."] +] + +```tsx highlights={highlights} +"use client" // include with Next.js 13+ + +import { + createContext, + useContext, + useEffect, + useState, +} from "react" +import { HttpTypes } from "@medusajs/types" + +type CustomerContextType = { + customer: HttpTypes.StoreCustomer | undefined + setCustomer: React.Dispatch< + React.SetStateAction + > +} + +const CustomerContext = createContext(null) + +type CustomerProviderProps = { + children: React.ReactNode +} + +export const CustomerProvider = ({ + children, +}: CustomerProviderProps) => { + const [customer, setCustomer] = useState< + HttpTypes.StoreCustomer + >() + + useEffect(() => { + if (customer) { + return + } + + fetch(`http://localhost:9000/store/customers/me`, { + credentials: "include", + }) + .then((res) => res.json()) + .then(({ customer }) => { + setCustomer(customer) + }) + .catch((err) => { + // customer isn't logged in + }) + }, []) + + return ( + + {children} + + ) +} + +export const useCustomer = () => { + const context = useContext(CustomerContext) + + if (!context) { + throw new Error("useCustomer must be used within a CustomerProvider") + } + + return context +} +``` + +The `CustomerProvider` handles retrieving the authenticated customer from the Medusa application. + +The `useCustomer` hook returns the value of the `CustomerContext`. Child components of `CustomerProvider` use this hook to access `customer` or `setCustomer`. + +--- + +## Use CustomerProvider in Component Tree + +To use the customer context's value, add the `CustomerProvider` high in your component tree. + +For example, if you're using Next.js, add it to the `app/layout.tsx` or `src/app/layout.tsx` file: + +```tsx title="app/layout.tsx" collapsibleLines="1-14" highlights={[["24"]]} +import type { Metadata } from "next" +import { Inter } from "next/font/google" +import "./globals.css" +import { CartProvider } from "../providers/cart" +import { RegionProvider } from "../providers/region" +import { CustomerProvider } from "../providers/customer" + +const inter = Inter({ subsets: ["latin"] }) + +export const metadata: Metadata = { + title: "Create Next App", + description: "Generated by create next app", +} + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + + + + {/* Other providers... */} + + {children} + + + + + + ) +} + +``` + +--- + +## Use useCustomer Hook + +Now, you can use the `useCustomer` hook in child components of `CustomerProvider`. + +For example: + +```tsx +"use client" // include with Next.js 13+ +// ... +import { useCustomer } from "../providers/customer" + +export default function Profile() { + const { customer } = useCustomer() + // ... +} +``` diff --git a/www/apps/resources/app/storefront-development/customers/log-out/page.mdx b/www/apps/resources/app/storefront-development/customers/log-out/page.mdx new file mode 100644 index 0000000000..9a7aa615ce --- /dev/null +++ b/www/apps/resources/app/storefront-development/customers/log-out/page.mdx @@ -0,0 +1,89 @@ +import { CodeTabs, CodeTab } from "docs-ui" + +export const metadata = { + title: `Log-out Customer in Storefront`, +} + +# {metadata.title} + +In this document, you'll learn how to log-out a customer in the storefront based on the authentication method. + +## Log-Out for JWT Token + +If you're authenticating the customer with their JWT token, remove the stored token from the browser. + +For example, if you've stored the JWT token in the `localStorage`, remove the item from it: + +```ts +localStorage.removeItem(`token`) +``` + +--- + +## Log-Out for Cookie Session + +If you're authenticating the customer with their cookie session ID, send a `DELETE` request to the `/auth/session`. + +For example: + + + + + ```ts + fetch(`http://localhost:9000/auth/session`, { + credentials: "include", + method: "DELETE", + }) + .then((res) => res.json()) + .then(() => { + // TODO redirect customer to login page + }) + ``` + + + + +export const highlights = [ + ["3", "useCustomer", "Use the hook defined in the Customer Context guide."], + ["9"], ["10"], ["11"], ["12"], ["13"], ["14"], ["15"], ["16"], ["17"], ["18"], + ["19"], +] + + ```tsx highlights={highlights} + "use client" // include with Next.js 13+ + + import { useCustomer } from "../../../providers/customer" + + export default function Profile() { + const { setCustomer } = useCustomer() + + const handleLogOut = () => { + fetch(`http://localhost:9000/auth/session`, { + credentials: "include", + method: "DELETE", + }) + .then((res) => res.json()) + .then(() => { + setCustomer(undefined) + // TODO redirect to login page + alert("Logged out") + }) + } + + return ( +
+ {/* Profile details... */} + +
+ ) + } + ``` + +
+
+ +The API route returns nothing in the response. If the request was successful, you can perform any necessary work to unset the customer and redirect them to the login page. diff --git a/www/apps/resources/app/storefront-development/customers/login/page.mdx b/www/apps/resources/app/storefront-development/customers/login/page.mdx new file mode 100644 index 0000000000..c30907a924 --- /dev/null +++ b/www/apps/resources/app/storefront-development/customers/login/page.mdx @@ -0,0 +1,347 @@ +import { CodeTabs, CodeTab } from "docs-ui" + +export const metadata = { + title: `Login Customer in Storefront`, +} + +# {metadata.title} + +In this document, you'll learn about the two ways to login a customer in a storefront. + +## 1. Using a JWT Token + +Using the `/auth/customer/emailpass` API route, you obtain a JSON Web Token (JWT) for the customer. Then, use that token as a bearer token in the authorization header of subsequent requests, and the customer is considered authenticated. + +For example: + + + + +export const fetchHighlights = [ + ["3", "fetch", "Send a request to obtain a JWT token."], + ["21", "fetch", "Send a request as an authenticated customer."], + ["27", "token", "Pass as a Bearer token in the authorization header."], +] + + ```ts highlights={fetchHighlights} + const handleLogin = async () => { + // obtain JWT token + const { token } = await fetch( + `http://localhost:9000/auth/customer/emailpass`, + { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + email, + password, + }), + } + ) + .then((res) => res.json()) + + // use token in the authorization header of + // all follow up requests. For example: + const { customer } = await fetch( + `http://localhost:9000/store/customers/me`, + { + credentials: "include", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${token}`, + }, + } + ) + .then((res) => res.json()) + + console.log(customer) + } + ``` + + + + +export const highlights = [ + ["21", "fetch", "Send a request to obtain a JWT token."], + ["39", "fetch", "Send a request as an authenticated customer."], + ["45", "token", "Pass as a Bearer token in the authorization header."], +] + + ```tsx highlights={highlights} collapsibleLines="55-79" expandButtonLabel="Show form" + "use client" // include with Next.js 13+ + + import { useState } from "react" + + export default function Login() { + const [loading, setLoading] = useState(false) + const [email, setEmail] = useState("") + const [password, setPassword] = useState("") + + const handleLogin = async ( + e: React.MouseEvent + ) => { + e.preventDefault() + if (!email || !password) { + return + } + + setLoading(true) + + // obtain JWT token + const { token } = await fetch( + `http://localhost:9000/auth/customer/emailpass`, + { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + email, + password, + }), + } + ) + .then((res) => res.json()) + + // use token in the authorization header of + // all follow up requests. For example: + const { customer } = await fetch( + `http://localhost:9000/store/customers/me`, + { + credentials: "include", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${token}`, + }, + } + ) + .then((res) => res.json()) + + console.log(customer) + setLoading(false) + } + + return ( +
+ setEmail(e.target.value)} + /> + setPassword(e.target.value)} + /> + +
+ ) + } + ``` + +
+
+ +In the example above, you: + +1. Create a `handleLogin` function that logs in a customer. +2. In the function, you obtain a JWT token by sending a request to the `/auth/customer/emailpass`. +3. You can then use that token in the authorization header of subsequent requests, and the customer is considered authenticated. As an example, you send a request to obtain the customer's details. + +--- + +## 2. Using a Cookie Session + +Authenticating the customer with a cookie session means the customer is authenticated in subsequent requests that use that cookie. + +If you're using the Fetch API, using the `credentials: include` option ensures that your cookie session is passed in every request. + +For example: + + + + +export const fetchSessionHighlights = [ + ["3", "fetch", "Send a request to obtain a JWT token."], + ["20", "fetch", "Send a request to set the authenticated session ID in the cookies."], + ["27", "token", "Pass as a Bearer token in the authorization header."], + ["35", "fetch", "Retrieve the customer's details as an example of testing authentication."], +] + + ```ts highlights={fetchSessionHighlights} + const handleLogin = async () => { + // obtain JWT token + const { token } = await fetch( + `http://localhost:9000/auth/customer/emailpass`, + { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + email, + password, + }), + } + ) + .then((res) => res.json()) + + // set session + await fetch( + `http://localhost:9000/auth/session`, + { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${token}`, + }, + } + ) + .then((res) => res.json()) + + // customer is now authenticated using the + // cookie session. For example + const { customer } = await fetch( + `http://localhost:9000/store/customers/me`, + { + credentials: "include", + headers: { + "Content-Type": "application/json", + }, + } + ) + .then((res) => res.json()) + + console.log(customer) + setLoading(false) + } + ``` + + + + +export const sessionHighlights = [ + ["21", "fetch", "Send a request to obtain a JWT token."], + ["38", "fetch", "Send a request to set the authenticated session ID in the cookies."], + ["45", "token", "Pass as a Bearer token in the authorization header."], + ["53", "fetch", "Retrieve the customer's details as an example of testing authentication."], +] + + ```tsx highlights={sessionHighlights} collapsibleLines="68-92" expandButtonLabel="Show form" + "use client" // include with Next.js 13+ + + import { useState } from "react" + + export default function Login() { + const [loading, setLoading] = useState(false) + const [email, setEmail] = useState("") + const [password, setPassword] = useState("") + + const handleLogin = async ( + e: React.MouseEvent + ) => { + e.preventDefault() + if (!email || !password) { + return + } + + setLoading(true) + + // obtain JWT token + const { token } = await fetch( + `http://localhost:9000/auth/customer/emailpass`, + { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + email, + password, + }), + } + ) + .then((res) => res.json()) + + // set session + await fetch( + `http://localhost:9000/auth/session`, + { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${token}`, + }, + } + ) + .then((res) => res.json()) + + // customer is now authenticated using the + // cookie session. For example + const { customer } = await fetch( + `http://localhost:9000/store/customers/me`, + { + credentials: "include", + headers: { + "Content-Type": "application/json", + }, + } + ) + .then((res) => res.json()) + + console.log(customer) + setLoading(false) + } + + return ( +
+ setEmail(e.target.value)} + /> + setPassword(e.target.value)} + /> + +
+ ) + } + ``` + +
+
+ +In the example above, you: + +1. Create a `handleLogin` function that logs in a customer. +2. In the function, you obtain a JWT token by sending a request to the `/auth/customer/emailpass`. +3. You send a request to the `/auth/session` API route passing in the authorization header the token as a Bearer token. This sets the authenticated session ID in the cookies. +4. You can now send authenticated requests, as long as you include the `credentials: include` option in your fetch requests. For example, you send a request to retrieve the customer's details. diff --git a/www/apps/resources/app/storefront-development/customers/page.mdx b/www/apps/resources/app/storefront-development/customers/page.mdx new file mode 100644 index 0000000000..87d248065a --- /dev/null +++ b/www/apps/resources/app/storefront-development/customers/page.mdx @@ -0,0 +1,11 @@ +import { ChildDocs } from "docs-ui" + +export const metadata = { + title: `Customers in Storefront`, +} + +# {metadata.title} + +A customer can register, manage their account, keep track of their orders, and more. + + \ No newline at end of file diff --git a/www/apps/resources/app/storefront-development/customers/profile/page.mdx b/www/apps/resources/app/storefront-development/customers/profile/page.mdx new file mode 100644 index 0000000000..a2cc749e62 --- /dev/null +++ b/www/apps/resources/app/storefront-development/customers/profile/page.mdx @@ -0,0 +1,145 @@ +import { CodeTabs, CodeTab } from "docs-ui" + +export const metadata = { + title: `Edit Customer Profile in Storefront`, +} + +# {metadata.title} + +To edit the customer's profile in the storefront, send a request to the [Update Customer API route](!api!/store#customers_postcustomersme). + +For example: + + + + + ```ts + fetch(`http://localhost:9000/store/customers/me`, { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + first_name, + last_name, + company_name, + phone, + }), + }) + .then((res) => res.json()) + .then(({ customer }) => { + // use customer... + console.log(customer) + }) + ``` + + + + +export const highlights = [ + ["4", "useCustomer", "Use the hook defined in the Customer Context guide."], + ["33"], ["34"], ["35"], ["36"], ["37"], ["38"], ["39"], ["40"], ["41"], ["42"], + ["43"], ["44"], ["45"], ["46"], ["47"], ["48"], ["49"] +] + + ```tsx highlights={highlights} collapsibleLines="53-91" expandButtonLabel="Show form" + "use client" // include with Next.js 13+ + + import { useState } from "react" + import { useCustomer } from "../../../providers/customer" + + export default function EditProfile() { + const { customer, setCustomer } = useCustomer() + const [firstName, setFirstName] = useState( + customer?.first_name || "" + ) + const [lastName, setLastName] = useState( + customer?.last_name || "" + ) + const [company, setCompany] = useState( + customer?.company_name || "" + ) + const [phone, setPhone] = useState( + customer?.phone || "" + ) + const [loading, setLoading] = useState(false) + + const handleEdit = ( + e: React.MouseEvent + ) => { + e.preventDefault() + + if (!customer) { + return + } + + setLoading(true) + + fetch(`http://localhost:9000/store/customers/me`, { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + first_name: firstName, + last_name: lastName, + company_name: company, + phone, + }), + }) + .then((res) => res.json()) + .then(({ customer: updatedCustomer }) => { + setCustomer(updatedCustomer) + }) + .finally(() => setLoading(false)) + } + + return ( +
+ setFirstName(e.target.value)} + /> + setLastName(e.target.value)} + /> + setCompany(e.target.value)} + /> + setPhone(e.target.value)} + /> + +
+ ) + } + ``` + +
+
+ +In the example above, you send a request to the Update Customer API route to update the customer's details. + +The response of the request has a `customer` field which is a [customer object](!api!/store#customers_customer_schema). diff --git a/www/apps/resources/app/storefront-development/customers/register/page.mdx b/www/apps/resources/app/storefront-development/customers/register/page.mdx new file mode 100644 index 0000000000..290eda8101 --- /dev/null +++ b/www/apps/resources/app/storefront-development/customers/register/page.mdx @@ -0,0 +1,190 @@ +import { CodeTabs, CodeTab } from "docs-ui" + +export const metadata = { + title: `Register Customer in Storefront`, +} + +# {metadata.title} + +To register a customer, you implement the following steps: + +1. Show the customer a form to enter their details. +2. Send a `POST` request to the `/auth/customer/emailpass` API route to obtain a JWT token. +3. Send a request to the [Create Customer API route](!api!/store#customers_postcustomers) pass the JWT token in the header. + +For example: + + + + +export const fetchHighlights = [ + ["3", "fetch", "Send a request to obtain a JWT token."], + ["20", "fetch", "Send a request to create the customer."], + ["27", "token", "Pass as a Bearer token in the authorization header."], + ["39", "TODO", "Redirect the customer to the log in page."] +] + + ```ts highlights={fetchHighlights} + const handleRegistration = async () => { + // obtain JWT token + const { token } = await fetch( + `http://localhost:9000/auth/customer/emailpass`, + { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + email, + password, + }), + } + ) + .then((res) => res.json()) + + // create customer + const { customer } = await fetch( + `http://localhost:9000/store/customers`, + { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${token}`, + }, + body: JSON.stringify({ + first_name: firstName, + last_name: lastName, + email, + }), + } + ) + .then((res) => res.json()) + + console.log(customer) + // TODO redirect to login page + } + ``` + + + + +export const highlights = [ + ["22", "fetch", "Send a request to obtain a JWT token."], + ["39", "fetch", "Send a request to create the customer."], + ["46", "token", "Pass as a Bearer token in the authorization header."], + ["59", "TODO", "Redirect the customer to the log in page."] +] + + ```tsx highlights={highlights} collapsibleLines="61-100" expandButtonLabel="Show form" + "use client" // include with Next.js 13+ + + import { useState } from "react" + + export default function Register() { + const [loading, setLoading] = useState(false) + const [firstName, setFirstName] = useState("") + const [lastName, setLastName] = useState("") + const [email, setEmail] = useState("") + const [password, setPassword] = useState("") + + const handleRegistration = async ( + e: React.MouseEvent + ) => { + e.preventDefault() + if (!firstName || !lastName || !email || !password) { + return + } + setLoading(true) + + // obtain JWT token + const { token } = await fetch( + `http://localhost:9000/auth/customer/emailpass`, + { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + email, + password, + }), + } + ) + .then((res) => res.json()) + + // create customer + const { customer } = await fetch( + `http://localhost:9000/store/customers`, + { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${token}`, + }, + body: JSON.stringify({ + first_name: firstName, + last_name: lastName, + email, + }), + } + ) + .then((res) => res.json()) + + console.log(customer) + setLoading(false) + // TODO redirect to login page + } + + return ( +
+ setFirstName(e.target.value)} + /> + setLastName(e.target.value)} + /> + setEmail(e.target.value)} + /> + setPassword(e.target.value)} + /> + +
+ ) + } + ``` + +
+
+ +In the above example, you create a `handleRegistration` function that: + +- Obtains a JWT token from the `/auth/customer/emailpass` API route. +- Send a request to the Create Customer API route, and pass the JWT token as a Bearer token in the authorization header. +- Once the customer is registered successfully, you can either redirect the customer to the login page or log them in automatically as explained in this guide. diff --git a/www/apps/resources/app/storefront-development/customers/retrieve/page.mdx b/www/apps/resources/app/storefront-development/customers/retrieve/page.mdx new file mode 100644 index 0000000000..56ad3689c7 --- /dev/null +++ b/www/apps/resources/app/storefront-development/customers/retrieve/page.mdx @@ -0,0 +1,66 @@ +import { CodeTabs, CodeTab } from "docs-ui" + +export const metadata = { + title: `Retrieve Customer in Storefront`, +} + +# {metadata.title} + +To retrieve a customer after it's been authenticated in your storefront, send a request to the [Get Customer API route](!api!/store#customers_getcustomersme): + + + + +export const bearerHighlights = [ + ["7", "", "Pass JWT token as bearer token in authorization header."], +] + + ```ts highlights={bearerHighlights} + fetch( + `http://localhost:9000/store/customers/me`, + { + credentials: "include", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${token}`, + }, + } + ) + .then((res) => res.json()) + .then(({ customer }) => { + // use customer... + console.log(customer) + }) + ``` + + + + +export const sessionHighlights = [ + ["4", "", "Pass this option to ensure the cookie session is passed in the request."], +] + + ```ts highlights={sessionHighlights} + fetch( + `http://localhost:9000/store/customers/me`, + { + credentials: "include", + headers: { + "Content-Type": "application/json", + }, + } + ) + .then((res) => res.json()) + .then(({ customer }) => { + // use customer... + console.log(customer) + }) + ``` + + + + +- If you authenticate the customer with bearer authorization, pass the token in the authorization header of the request. +- If you authenticate the customer with cookie session, pass the `credentials: include` option to the `fetch` function. + +The Get Customer API route returns a `customer` field, which is a [customer object](!api!/store#customers_customer_schema). diff --git a/www/apps/resources/app/storefront-development/products/categories/list/page.mdx b/www/apps/resources/app/storefront-development/products/categories/list/page.mdx index a0c2e1aa16..f231050e24 100644 --- a/www/apps/resources/app/storefront-development/products/categories/list/page.mdx +++ b/www/apps/resources/app/storefront-development/products/categories/list/page.mdx @@ -37,7 +37,7 @@ export const highlights = [ ```tsx highlights={highlights} "use client" // include with Next.js 13+ - import { useEffect, useState } from "react"; + import { useEffect, useState } from "react" import { HttpTypes } from "@medusajs/types" export default function Categories() { @@ -75,7 +75,7 @@ export const highlights = [ )}
- ); + ) } ``` @@ -108,7 +108,7 @@ export const paginateHighlights = [ ```tsx highlights={paginateHighlights} "use client" // include with Next.js 13+ -import { useEffect, useState } from "react"; +import { useEffect, useState } from "react" import { HttpTypes } from "@medusajs/types" export default function Categories() { @@ -147,7 +147,7 @@ export default function Categories() { } return [ ...prev, - ...product_categories + ...product_categories, ] }) setHasMorePages(count > limit * currentPage) @@ -180,7 +180,7 @@ export default function Categories() { )} - ); + ) } ``` @@ -196,7 +196,7 @@ For example, to run a query on the product categories: ```ts const searchParams = new URLSearchParams({ - q: "Shirt" + q: "Shirt", }) fetch(`http://localhost:9000/store/product-categories?${ diff --git a/www/apps/resources/app/storefront-development/products/categories/nested-categories/page.mdx b/www/apps/resources/app/storefront-development/products/categories/nested-categories/page.mdx index 5c2dcd6473..d04c57f13b 100644 --- a/www/apps/resources/app/storefront-development/products/categories/nested-categories/page.mdx +++ b/www/apps/resources/app/storefront-development/products/categories/nested-categories/page.mdx @@ -21,7 +21,7 @@ export const fetchHighlights = [ ```ts highlights={fetchHighlights} const searchParams = new URLSearchParams({ - fields: "*category_children" + fields: "*category_children", }) fetch(`http://localhost:9000/store/product-categories/${id}?${ @@ -71,7 +71,7 @@ export const highlights = [ } const searchParams = new URLSearchParams({ - fields: "*category_children" + fields: "*category_children", }) fetch(`http://localhost:9000/store/product-categories/${id}?${ diff --git a/www/apps/resources/app/storefront-development/products/categories/products/page.mdx b/www/apps/resources/app/storefront-development/products/categories/products/page.mdx index 095d3de8e6..58897e5d6b 100644 --- a/www/apps/resources/app/storefront-development/products/categories/products/page.mdx +++ b/www/apps/resources/app/storefront-development/products/categories/products/page.mdx @@ -19,14 +19,14 @@ export const fetchHighlights = [ ```ts highlights={fetchHighlights} const searchParams = new URLSearchParams({ // other query params... - "category_id[]": categoryId + "category_id[]": categoryId, }) fetch(`http://localhost:9000/store/products?${searchParams.toString()}`, { credentials: "include", headers: { - "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp" - } + "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp", + }, }) .then((res) => res.json()) .then(({ products, count }) => { @@ -60,7 +60,7 @@ export const highlights = [ } export default function CategoryProducts({ - params: { categoryId } + params: { categoryId }, }: Params) { const [loading, setLoading] = useState(true) const [products, setProducts] = useState< @@ -80,14 +80,14 @@ export const highlights = [ const searchParams = new URLSearchParams({ limit: `${limit}`, offset: `${offset}`, - "category_id[]": categoryId + "category_id[]": categoryId, }) fetch(`http://localhost:9000/store/products?${searchParams.toString()}`, { credentials: "include", headers: { - "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp" - } + "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp", + }, }) .then((res) => res.json()) .then(({ products: dataProducts, count }) => { @@ -98,7 +98,7 @@ export const highlights = [ } return [ ...prev, - ...dataProducts + ...dataProducts, ] }) setHasMorePages(count > limit * currentPage) @@ -131,7 +131,7 @@ export const highlights = [ )} - ); + ) } ``` diff --git a/www/apps/resources/app/storefront-development/products/collections/list/page.mdx b/www/apps/resources/app/storefront-development/products/collections/list/page.mdx index 745446d48a..636d2f6bbd 100644 --- a/www/apps/resources/app/storefront-development/products/collections/list/page.mdx +++ b/www/apps/resources/app/storefront-development/products/collections/list/page.mdx @@ -37,7 +37,7 @@ export const highlights = [ ```tsx highlights={highlights} "use client" // include with Next.js 13+ - import { useEffect, useState } from "react"; + import { useEffect, useState } from "react" import { HttpTypes } from "@medusajs/types" export default function Collections() { @@ -75,7 +75,7 @@ export const highlights = [ )} - ); + ) } ``` @@ -110,7 +110,7 @@ export const paginateHighlights = [ ```tsx highlights={paginateHighlights} "use client" // include with Next.js 13+ -import { useEffect, useState } from "react"; +import { useEffect, useState } from "react" import { HttpTypes } from "@medusajs/types" export default function Collections() { @@ -149,7 +149,7 @@ export default function Collections() { } return [ ...prev, - ...dataCollections + ...dataCollections, ] }) setHasMorePages(count > limit * currentPage) @@ -182,7 +182,7 @@ export default function Collections() { )} - ); + ) } ``` @@ -198,7 +198,7 @@ For example: ```ts const searchParams = new URLSearchParams({ - title: "test" + title: "test", }) fetch(`http://localhost:9000/store/collections?${ diff --git a/www/apps/resources/app/storefront-development/products/collections/products/page.mdx b/www/apps/resources/app/storefront-development/products/collections/products/page.mdx index 7463662ac8..b512ec1b9c 100644 --- a/www/apps/resources/app/storefront-development/products/collections/products/page.mdx +++ b/www/apps/resources/app/storefront-development/products/collections/products/page.mdx @@ -19,14 +19,14 @@ export const fetchHighlights = [ ```ts highlights={fetchHighlights} const searchParams = new URLSearchParams({ // other query params... - "collection_id[]": collectionId + "collection_id[]": collectionId, }) fetch(`http://localhost:9000/store/products?${searchParams.toString()}`, { credentials: "include", headers: { - "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp" - } + "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp", + }, }) .then((res) => res.json()) .then(({ products, count }) => { @@ -60,7 +60,7 @@ export const highlights = [ } export default function CollectionProducts({ - params: { collectionId } + params: { collectionId }, }: Params) { const [loading, setLoading] = useState(true) const [products, setProducts] = useState< @@ -80,7 +80,7 @@ export const highlights = [ const searchParams = new URLSearchParams({ limit: `${limit}`, offset: `${offset}`, - "collection_id[]": collectionId + "collection_id[]": collectionId, }) fetch(`http://localhost:9000/store/products?${ @@ -88,8 +88,8 @@ export const highlights = [ }`, { credentials: "include", headers: { - "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp" - } + "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp", + }, }) .then((res) => res.json()) .then(({ products: dataProducts, count }) => { @@ -100,7 +100,7 @@ export const highlights = [ } return [ ...prev, - ...dataProducts + ...dataProducts, ] }) setHasMorePages(count > limit * currentPage) @@ -133,7 +133,7 @@ export const highlights = [ )} - ); + ) } ``` diff --git a/www/apps/resources/app/storefront-development/products/list/page.mdx b/www/apps/resources/app/storefront-development/products/list/page.mdx index 6d08844d51..2a0cb007c8 100644 --- a/www/apps/resources/app/storefront-development/products/list/page.mdx +++ b/www/apps/resources/app/storefront-development/products/list/page.mdx @@ -23,8 +23,8 @@ export const fetchHighlights = [ fetch(`http://localhost:9000/store/products`, { credentials: "include", headers: { - "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp" - } + "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp", + }, }) .then((res) => res.json()) .then((data) => { @@ -45,7 +45,7 @@ export const highlights = [ ```tsx highlights={highlights} "use client" // include with Next.js 13+ - import { useEffect, useState } from "react"; + import { useEffect, useState } from "react" import { HttpTypes } from "@medusajs/types" export default function Products() { @@ -62,8 +62,8 @@ export const highlights = [ fetch(`http://localhost:9000/store/products`, { credentials: "include", headers: { - "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp" - } + "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp", + }, }) .then((res) => res.json()) .then((data) => { @@ -84,7 +84,7 @@ export const highlights = [ )} - ); + ) } ``` @@ -119,7 +119,7 @@ export const paginateHighlights = [ ```tsx highlights={paginateHighlights} "use client" // include with Next.js 13+ -import { useEffect, useState } from "react"; +import { useEffect, useState } from "react" import { HttpTypes } from "@medusajs/types" export default function Products() { @@ -146,8 +146,8 @@ export default function Products() { fetch(`http://localhost:9000/store/products?${searchParams.toString()}`, { credentials: "include", headers: { - "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp" - } + "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp", + }, }) .then((res) => res.json()) .then(({ products: dataProducts, count }) => { @@ -158,7 +158,7 @@ export default function Products() { } return [ ...prev, - ...dataProducts + ...dataProducts, ] }) setHasMorePages(count > limit * currentPage) @@ -189,7 +189,7 @@ export default function Products() { )} - ); + ) } ``` @@ -206,14 +206,14 @@ For example, to run a query on the products: ```ts const searchParams = new URLSearchParams({ // other params... - q: "Shirt" + q: "Shirt", }) fetch(`http://localhost:9000/store/products?${searchParams.toString()}`, { credentials: "include", headers: { - "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp" - } + "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp", + }, }) .then((res) => res.json()) .then(({ products: dataProducts, count }) => { diff --git a/www/apps/resources/app/storefront-development/products/price/page.mdx b/www/apps/resources/app/storefront-development/products/price/page.mdx index 9d96974391..3ad4e9eb34 100644 --- a/www/apps/resources/app/storefront-development/products/price/page.mdx +++ b/www/apps/resources/app/storefront-development/products/price/page.mdx @@ -74,14 +74,14 @@ export default function Product({ params: { id } }: Params) { const queryParams = new URLSearchParams({ fields: `*variants.calculated_price`, - region_id: region.id + region_id: region.id, }) fetch(`http://localhost:9000/store/products/${id}?${queryParams.toString()}`, { credentials: "include", headers: { - "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp" - } + "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp", + }, }) .then((res) => res.json()) .then(({ product: dataProduct }) => { @@ -152,7 +152,7 @@ export default function Product({ params: { id } }: Params) { setSelectedOptions((prev) => { return { ...prev, - [option.id!]: optionValue.value! + [option.id!]: optionValue.value!, } }) }} @@ -254,14 +254,14 @@ export default function Product({ params: { id } }: Params) { const queryParams = new URLSearchParams({ fields: `*variants.calculated_price`, - region_id: region.id + region_id: region.id, }) fetch(`http://localhost:9000/store/products/${id}?${queryParams.toString()}`, { credentials: "include", headers: { - "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp" - } + "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp", + }, }) .then((res) => res.json()) .then(({ product: dataProduct }) => { @@ -350,7 +350,7 @@ export default function Product({ params: { id } }: Params) { setSelectedOptions((prev) => { return { ...prev, - [option.id!]: optionValue.value! + [option.id!]: optionValue.value!, } }) }} diff --git a/www/apps/resources/app/storefront-development/products/retrieve/page.mdx b/www/apps/resources/app/storefront-development/products/retrieve/page.mdx index 78237aa82e..480f2e6b7d 100644 --- a/www/apps/resources/app/storefront-development/products/retrieve/page.mdx +++ b/www/apps/resources/app/storefront-development/products/retrieve/page.mdx @@ -29,8 +29,8 @@ export const fetchHighlights = [ fetch(`http://localhost:9000/store/products/${id}`, { credentials: "include", headers: { - "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp" - } + "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp", + }, }) .then((res) => res.json()) .then(({ product }) => { @@ -75,8 +75,8 @@ export const highlights = [ fetch(`http://localhost:9000/store/products/${id}`, { credentials: "include", headers: { - "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp" - } + "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp", + }, }) .then((res) => res.json()) .then(({ product: dataProduct }) => { @@ -140,8 +140,8 @@ export const handleFetchHighlights = [ fetch(`http://localhost:9000/store/products?handle=${handle}`, { credentials: "include", headers: { - "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp" - } + "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp", + }, }) .then((res) => res.json()) .then(({ products }) => { @@ -190,8 +190,8 @@ export const handleHighlights = [ fetch(`http://localhost:9000/store/products?handle=${handle}`, { credentials: "include", headers: { - "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp" - } + "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp", + }, }) .then((res) => res.json()) .then(({ products }) => { diff --git a/www/apps/resources/app/storefront-development/products/variants/page.mdx b/www/apps/resources/app/storefront-development/products/variants/page.mdx index faaa03c20a..7829caf954 100644 --- a/www/apps/resources/app/storefront-development/products/variants/page.mdx +++ b/www/apps/resources/app/storefront-development/products/variants/page.mdx @@ -57,8 +57,8 @@ export default function Product({ params: { id } }: Params) { fetch(`http://localhost:9000/store/products/${id}`, { credentials: "include", headers: { - "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp" - } + "x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp", + }, }) .then((res) => res.json()) .then(({ product: dataProduct }) => { @@ -99,7 +99,7 @@ export default function Product({ params: { id } }: Params) { setSelectedOptions((prev) => { return { ...prev, - [option.id!]: optionValue.value! + [option.id!]: optionValue.value!, } }) }} diff --git a/www/apps/resources/app/storefront-development/regions/context/page.mdx b/www/apps/resources/app/storefront-development/regions/context/page.mdx index 289edd71d2..313682ff9d 100644 --- a/www/apps/resources/app/storefront-development/regions/context/page.mdx +++ b/www/apps/resources/app/storefront-development/regions/context/page.mdx @@ -32,7 +32,7 @@ import { createContext, useContext, useEffect, - useState + useState, } from "react" import { HttpTypes } from "@medusajs/types" @@ -68,7 +68,7 @@ export const RegionProvider = ( if (!regionId) { // retrieve regions and select the first one fetch(`http://localhost:9000/store/regions`, { - credentials: "include" + credentials: "include", }) .then((res) => res.json()) .then(({ regions }) => { @@ -77,7 +77,7 @@ export const RegionProvider = ( } else { // retrieve selected region fetch(`http://localhost:9000/store/regions/${regionId}`, { - credentials: "include" + credentials: "include", }) .then((res) => res.json()) .then(({ region: dataRegion }) => { @@ -89,7 +89,7 @@ export const RegionProvider = ( return ( {children} @@ -126,12 +126,12 @@ import "./globals.css" import { CartProvider } from "../providers/cart" import { RegionProvider } from "../providers/region" -const inter = Inter({ subsets: ["latin"] }); +const inter = Inter({ subsets: ["latin"] }) export const metadata: Metadata = { title: "Create Next App", description: "Generated by create next app", -}; +} export default function RootLayout({ children, @@ -147,7 +147,7 @@ export default function RootLayout({ - ); + ) } ``` diff --git a/www/apps/resources/app/storefront-development/regions/list/page.mdx b/www/apps/resources/app/storefront-development/regions/list/page.mdx index a637b5071d..9608c6fb0d 100644 --- a/www/apps/resources/app/storefront-development/regions/list/page.mdx +++ b/www/apps/resources/app/storefront-development/regions/list/page.mdx @@ -13,7 +13,7 @@ To list regions in your storefront, send a request to the [List Regions API rout ```ts fetch(`http://localhost:9000/store/regions`, { - credentials: "include" + credentials: "include", }) .then((res) => res.json()) .then(({ regions }) => { @@ -32,7 +32,7 @@ export const highlights = [ ```tsx highlights={highlights} "use client" // include with Next.js 13+ - import { useEffect, useState } from "react"; + import { useEffect, useState } from "react" import { HttpTypes } from "@medusajs/types" export default function Regions() { @@ -47,7 +47,7 @@ export const highlights = [ } fetch(`http://localhost:9000/store/regions`, { - credentials: "include" + credentials: "include", }) .then((res) => res.json()) .then(({ regions: dataRegions }) => { @@ -68,7 +68,7 @@ export const highlights = [ )} - ); + ) } ``` diff --git a/www/apps/resources/app/storefront-development/regions/store-retrieve-region/page.mdx b/www/apps/resources/app/storefront-development/regions/store-retrieve-region/page.mdx index 124eaa4cbd..6679a88762 100644 --- a/www/apps/resources/app/storefront-development/regions/store-retrieve-region/page.mdx +++ b/www/apps/resources/app/storefront-development/regions/store-retrieve-region/page.mdx @@ -32,7 +32,7 @@ To retrieve the selected region, use the [Retrieve Region API route](!api!/store const regionId = localStorage.getItem("region_id") fetch(`http://localhost:9000/store/regions/${regionId}`, { - credentials: "include" + credentials: "include", }) .then((res) => res.json()) .then(({ region }) => { diff --git a/www/apps/resources/app/storefront-development/tips/page.mdx b/www/apps/resources/app/storefront-development/tips/page.mdx index 13f8409089..79d23a1d3e 100644 --- a/www/apps/resources/app/storefront-development/tips/page.mdx +++ b/www/apps/resources/app/storefront-development/tips/page.mdx @@ -46,8 +46,8 @@ module.exports = defineConfig({ http: { storeCors: "http://localhost:3000", // ... - } - } + }, + }, // ... }) ``` diff --git a/www/apps/resources/app/troubleshooting/_sections/other/cors-errors.mdx b/www/apps/resources/app/troubleshooting/_sections/other/cors-errors.mdx index 5b3d5d0075..4954846b90 100644 --- a/www/apps/resources/app/troubleshooting/_sections/other/cors-errors.mdx +++ b/www/apps/resources/app/troubleshooting/_sections/other/cors-errors.mdx @@ -12,8 +12,8 @@ module.exports = defineConfig({ http: { storeCors: process.env.STORE_CORS, adminCors: process.env.ADMIN_CORS, - } + }, // ... - } + }, }) ``` diff --git a/www/apps/resources/generated/files-map.mjs b/www/apps/resources/generated/files-map.mjs index 768ba612a8..1466b22e6a 100644 --- a/www/apps/resources/generated/files-map.mjs +++ b/www/apps/resources/generated/files-map.mjs @@ -323,10 +323,6 @@ export const filesMap = [ "filePath": "/www/apps/resources/app/commerce-modules/customer/page.mdx", "pathname": "/commerce-modules/customer" }, - { - "filePath": "/www/apps/resources/app/commerce-modules/customer/register-customer-email/page.mdx", - "pathname": "/commerce-modules/customer/register-customer-email" - }, { "filePath": "/www/apps/resources/app/commerce-modules/customer/relations-to-other-modules/page.mdx", "pathname": "/commerce-modules/customer/relations-to-other-modules" @@ -923,6 +919,38 @@ export const filesMap = [ "filePath": "/www/apps/resources/app/storefront-development/checkout/shipping/page.mdx", "pathname": "/storefront-development/checkout/shipping" }, + { + "filePath": "/www/apps/resources/app/storefront-development/customers/addresses/page.mdx", + "pathname": "/storefront-development/customers/addresses" + }, + { + "filePath": "/www/apps/resources/app/storefront-development/customers/context/page.mdx", + "pathname": "/storefront-development/customers/context" + }, + { + "filePath": "/www/apps/resources/app/storefront-development/customers/log-out/page.mdx", + "pathname": "/storefront-development/customers/log-out" + }, + { + "filePath": "/www/apps/resources/app/storefront-development/customers/login/page.mdx", + "pathname": "/storefront-development/customers/login" + }, + { + "filePath": "/www/apps/resources/app/storefront-development/customers/page.mdx", + "pathname": "/storefront-development/customers" + }, + { + "filePath": "/www/apps/resources/app/storefront-development/customers/profile/page.mdx", + "pathname": "/storefront-development/customers/profile" + }, + { + "filePath": "/www/apps/resources/app/storefront-development/customers/register/page.mdx", + "pathname": "/storefront-development/customers/register" + }, + { + "filePath": "/www/apps/resources/app/storefront-development/customers/retrieve/page.mdx", + "pathname": "/storefront-development/customers/retrieve" + }, { "filePath": "/www/apps/resources/app/storefront-development/page.mdx", "pathname": "/storefront-development" diff --git a/www/apps/resources/generated/sidebar.mjs b/www/apps/resources/generated/sidebar.mjs index dfc0e624cf..e142d33c3b 100644 --- a/www/apps/resources/generated/sidebar.mjs +++ b/www/apps/resources/generated/sidebar.mjs @@ -1030,20 +1030,6 @@ export const generatedSidebar = [ } ] }, - { - "loaded": true, - "isPathHref": true, - "title": "Guides", - "children": [ - { - "loaded": true, - "isPathHref": true, - "path": "/commerce-modules/customer/register-customer-email", - "title": "Register a Customer with Email", - "children": [] - } - ] - }, { "loaded": true, "isPathHref": true, @@ -7140,49 +7126,6 @@ export const generatedSidebar = [ } ] }, - { - "loaded": true, - "isPathHref": true, - "path": "/storefront-development/cart", - "title": "Carts", - "children": [ - { - "loaded": true, - "isPathHref": true, - "path": "/storefront-development/cart/create", - "title": "Create Cart", - "children": [] - }, - { - "loaded": true, - "isPathHref": true, - "path": "/storefront-development/cart/retrieve", - "title": "Retrieve Cart", - "children": [] - }, - { - "loaded": true, - "isPathHref": true, - "path": "/storefront-development/cart/context", - "title": "Cart React Context", - "children": [] - }, - { - "loaded": true, - "isPathHref": true, - "path": "/storefront-development/cart/update", - "title": "Update Cart", - "children": [] - }, - { - "loaded": true, - "isPathHref": true, - "path": "/storefront-development/cart/manage-items", - "title": "Manage Line Items", - "children": [] - } - ] - }, { "loaded": true, "isPathHref": true, @@ -7284,6 +7227,49 @@ export const generatedSidebar = [ } ] }, + { + "loaded": true, + "isPathHref": true, + "path": "/storefront-development/cart", + "title": "Carts", + "children": [ + { + "loaded": true, + "isPathHref": true, + "path": "/storefront-development/cart/create", + "title": "Create Cart", + "children": [] + }, + { + "loaded": true, + "isPathHref": true, + "path": "/storefront-development/cart/retrieve", + "title": "Retrieve Cart", + "children": [] + }, + { + "loaded": true, + "isPathHref": true, + "path": "/storefront-development/cart/context", + "title": "Cart React Context", + "children": [] + }, + { + "loaded": true, + "isPathHref": true, + "path": "/storefront-development/cart/update", + "title": "Update Cart", + "children": [] + }, + { + "loaded": true, + "isPathHref": true, + "path": "/storefront-development/cart/manage-items", + "title": "Manage Line Items", + "children": [] + } + ] + }, { "loaded": true, "isPathHref": true, @@ -7334,6 +7320,63 @@ export const generatedSidebar = [ "children": [] } ] + }, + { + "loaded": true, + "isPathHref": true, + "path": "/storefront-development/customers", + "title": "Customers", + "children": [ + { + "loaded": true, + "isPathHref": true, + "path": "/storefront-development/customers/register", + "title": "Register Customer", + "children": [] + }, + { + "loaded": true, + "isPathHref": true, + "path": "/storefront-development/customers/login", + "title": "Login Customer", + "children": [] + }, + { + "loaded": true, + "isPathHref": true, + "path": "/storefront-development/customers/retrieve", + "title": "Retrieve Customer", + "children": [] + }, + { + "loaded": true, + "isPathHref": true, + "path": "/storefront-development/customers/context", + "title": "Customer React Context", + "children": [] + }, + { + "loaded": true, + "isPathHref": true, + "path": "/storefront-development/customers/profile", + "title": "Edit Customer Profile", + "children": [] + }, + { + "loaded": true, + "isPathHref": true, + "path": "/storefront-development/customers/addresses", + "title": "Manage Customer Addresses", + "children": [] + }, + { + "loaded": true, + "isPathHref": true, + "path": "/storefront-development/customers/log-out", + "title": "Log-out Customer", + "children": [] + } + ] } ] }, diff --git a/www/apps/resources/sidebar.mjs b/www/apps/resources/sidebar.mjs index 8b864c0fbb..934b7ad537 100644 --- a/www/apps/resources/sidebar.mjs +++ b/www/apps/resources/sidebar.mjs @@ -310,15 +310,6 @@ export const sidebar = sidebarAttachHrefCommonOptions([ }, ], }, - { - title: "Guides", - children: [ - { - path: "/commerce-modules/customer/register-customer-email", - title: "Register a Customer with Email", - }, - ], - }, { title: "References", children: [ @@ -1809,32 +1800,6 @@ export const sidebar = sidebarAttachHrefCommonOptions([ }, ], }, - { - path: "/storefront-development/cart", - title: "Carts", - children: [ - { - path: "/storefront-development/cart/create", - title: "Create Cart", - }, - { - path: "/storefront-development/cart/retrieve", - title: "Retrieve Cart", - }, - { - path: "/storefront-development/cart/context", - title: "Cart React Context", - }, - { - path: "/storefront-development/cart/update", - title: "Update Cart", - }, - { - path: "/storefront-development/cart/manage-items", - title: "Manage Line Items", - }, - ], - }, { path: "/storefront-development/products", title: "Products", @@ -1897,6 +1862,32 @@ export const sidebar = sidebarAttachHrefCommonOptions([ }, ], }, + { + path: "/storefront-development/cart", + title: "Carts", + children: [ + { + path: "/storefront-development/cart/create", + title: "Create Cart", + }, + { + path: "/storefront-development/cart/retrieve", + title: "Retrieve Cart", + }, + { + path: "/storefront-development/cart/context", + title: "Cart React Context", + }, + { + path: "/storefront-development/cart/update", + title: "Update Cart", + }, + { + path: "/storefront-development/cart/manage-items", + title: "Manage Line Items", + }, + ], + }, { path: "/storefront-development/checkout", title: "Checkout", @@ -1929,6 +1920,40 @@ export const sidebar = sidebarAttachHrefCommonOptions([ }, ], }, + { + path: "/storefront-development/customers", + title: "Customers", + children: [ + { + path: "/storefront-development/customers/register", + title: "Register Customer", + }, + { + path: "/storefront-development/customers/login", + title: "Login Customer", + }, + { + path: "/storefront-development/customers/retrieve", + title: "Retrieve Customer", + }, + { + path: "/storefront-development/customers/context", + title: "Customer React Context", + }, + { + path: "/storefront-development/customers/profile", + title: "Edit Customer Profile", + }, + { + path: "/storefront-development/customers/addresses", + title: "Manage Customer Addresses", + }, + { + path: "/storefront-development/customers/log-out", + title: "Log-out Customer", + }, + ], + }, ], }, {