docs: update docs across projects following publishable API key change in store routes (#9098)

* docs: update docs across projects following publishable API key change in store routes

* rename env variable

* move subscribe route out of store
This commit is contained in:
Shahed Nasser authored and GitHub committed 2024-09-16 16:42:08 +03:00
1 parent ef8dc4087e
commit 58f06be44d
66 files changed
+577 -298

No files matched your search

+12 -15
View File
@@ -140,34 +140,31 @@ fetch(`<BACKEND_URL>/store/products`, {
## Publishable API Key
Publishable API Keys allow you to send a request with a pre-defined scope. You can associate the
publishable API key with one or more resources, such as sales channels, then include the publishable
API key in the header of your requests.
You must pass a publishable API key in the header of your requests to the store API routes.
The Medusa application will infer the scope of the current
request based on the publishable API key. At the moment, publishable API keys only work with sales channels.
It's highly recommended to create a publishable API key and pass it in the header of all your requests to the
store APIs.
{/* TODO add link to the v2 guide */}
{/* You can learn more about publishable API keys and how to use them in [this documentation](https://docs.medusajs.com/development/publishable-api-keys/). */}
Publishable API Keys sets the scope of your request to one or more sales channels. This ensures you only
retrieve products available in the publishable API key's sales channels, retrieve correct inventory details,
and associate placed orders with the specified sales channel.
### How to Create a Publishable API Key
{/* TODO add v2 links */}
Create a publishable API key either using the admin REST APIs, or using the Medusa Admin.
Create a publishable API key either using the [admin REST APIs](https://docs.medusajs.com/v2/api/admin#api-keys_postapikeys), or using the Medusa Admin.
### How to Use a Publishable API Key
You can pass the publishable API key in the header `x-publishable-api-key` in all your requests to the store APIs:
You pass the publishable API key in the header `x-publishable-api-key` in all your requests to the store APIs.
For example:
```bash
x-publishable-api-key: {your_publishable_api_key}
curl 'http://localhost:9000/store/products' \
-H 'x-publishable-api-key: {your_publishable_api_key}'
```
Where `{your_publishable_api_key}` is the token of the publishable API key.
<Feedback
event="survey_api-ref"
extraData={{
@@ -12,9 +12,9 @@ An API route is created for every HTTP method you export a handler function for
Allowed HTTP methods are: `GET`, `POST`, `DELETE`, `PUT`, `PATCH`, `OPTIONS`, and `HEAD`.
For example, create the file `src/api/store/hello-world/route.ts` with the following content:
For example, create the file `src/api/hello-world/route.ts` with the following content:
```ts title="src/api/store/hello-world/route.ts"
```ts title="src/api/hello-world/route.ts"
import type {
MedusaRequest,
MedusaResponse,
@@ -41,5 +41,5 @@ export const POST = async (
This adds two API Routes:
- A `GET` route at `http://localhost:9000/store/hello-world`.
- A `POST` route at `http://localhost:9000/store/hello-world`.
- A `GET` route at `http://localhost:9000/hello-world`.
- A `POST` route at `http://localhost:9000/hello-world`.
@@ -37,7 +37,7 @@ import type {
export default defineMiddlewares({
routes: [
{
matcher: "/store*",
matcher: "/custom*",
middlewares: [
(
req: MedusaRequest,
@@ -59,7 +59,7 @@ The `defineMiddlewares` function accepts a middleware configurations object that
- `matcher`: a string or regular expression indicating the API route path to apply the middleware on. The regular expression must be compatible with [path-to-regexp](https://github.com/pillarjs/path-to-regexp).
- `middlewares`: An array of middleware functions.
In the example above, you define a middleware that logs the message `Received a request!` whenever a request is sent to an API route path starting with `/store`.
In the example above, you define a middleware that logs the message `Received a request!` whenever a request is sent to an API route path starting with `/custom`.
---
@@ -73,7 +73,7 @@ To test the middleware:
npm run dev
```
2. Send a request to any API route starting with `/store`.
2. Send a request to any API route starting with `/custom`.
3. See the following message in the terminal:
```bash
@@ -128,7 +128,7 @@ import type {
export default defineMiddlewares({
routes: [
{
matcher: "/store/custom/:id",
matcher: "/custom/:id",
middlewares: [
// ...
],
@@ -137,7 +137,7 @@ export default defineMiddlewares({
})
```
This applies a middleware to the routes defined in the file `src/api/store/custom/[id]/route.ts`.
This applies a middleware to the routes defined in the file `src/api/custom/[id]/route.ts`.
---
@@ -160,7 +160,7 @@ import type {
export default defineMiddlewares({
routes: [
{
matcher: "/store*",
matcher: "/custom*",
method: ["POST", "PUT"],
middlewares: [
// ...
@@ -172,7 +172,7 @@ export default defineMiddlewares({
`method`'s value is one or more HTTP methods to apply the middleware to.
This example applies the middleware only when a `POST` or `PUT` request is sent to an API route path starting with `/store`.
This example applies the middleware only when a `POST` or `PUT` request is sent to an API route path starting with `/custom`.
---
@@ -10,13 +10,13 @@ In this chapter, you’ll learn about path, query, and request body parameters.
To create an API route that accepts a path parameter, create a directory within the route file's path whose name is of the format `[param]`.
For example, to create an API Route at the path `/hello-world/:id`, where `:id` is a path parameter, create the file `src/api/store/hello-world/[id]/route.ts` with the following content:
For example, to create an API Route at the path `/hello-world/:id`, where `:id` is a path parameter, create the file `src/api/hello-world/[id]/route.ts` with the following content:
export const singlePathHighlights = [
["11", "req.params.id", "Access the path parameter `id`"]
]
```ts title="src/api/store/hello-world/[id]/route.ts" highlights={singlePathHighlights} apiTesting testApiUrl="http://localhost:9000/store/hello-world/{id}" testApiMethod="GET" testPathParams={{ "id": "" }}
```ts title="src/api/hello-world/[id]/route.ts" highlights={singlePathHighlights}
import type {
MedusaRequest,
MedusaResponse,
@@ -38,14 +38,14 @@ The `MedusaRequest` object has a `params` property. `params` holds the path para
To create an API route that accepts multiple path parameters, create within the file's path multiple directories whose names are of the format `[param]`.
For example, to create an API route at `/store/hello-world/:id/name/:name`, create the file `src/api/store/hello-world/[id]/name/[name]/route.ts` with the following content:
For example, to create an API route at `/hello-world/:id/name/:name`, create the file `src/api/hello-world/[id]/name/[name]/route.ts` with the following content:
export const multiplePathHighlights = [
["12", "req.params.id", "Access the path parameter `id`"],
["13", "req.params.name", "Access the path parameter `name`"]
]
```ts title="src/api/store/hello-world/[id]/name/[name]/route.ts" highlights={multiplePathHighlights} apiTesting testApiUrl="http://localhost:9000/store/hello-world/{id}/name/{name}" testApiMethod="GET" testPathParams={{ "id": "", "name": "" }}
```ts title="src/api/hello-world/[id]/name/[name]/route.ts" highlights={multiplePathHighlights}
import type {
MedusaRequest,
MedusaResponse,
@@ -77,7 +77,7 @@ export const queryHighlights = [
["11", "req.query.name", "Access the query parameter `name`"],
]
```ts title="src/api/store/hello-world/route.ts" highlights={queryHighlights} apiTesting testApiUrl="http://localhost:9000/store/hello-world" testApiMethod="GET" testQueryParams={{ "name": "" }}
```ts title="src/api/hello-world/route.ts" highlights={queryHighlights}
import type {
MedusaRequest,
MedusaResponse,
@@ -108,7 +108,7 @@ export const bodyHighlights = [
["15", "req.body.name", "Access the request body parameter `name`"],
]
```ts title="src/api/store/hello-world/route.ts" highlights={bodyHighlights}
```ts title="src/api/hello-world/route.ts" highlights={bodyHighlights}
import type {
MedusaRequest,
MedusaResponse,
@@ -138,8 +138,8 @@ The `MedusaRequest` type accepts a type argument that indicates the type of the
To test it out, send the following request to your Medusa application:
```bash apiTesting testApiUrl="http://localhost:9000/store/hello-world" testApiMethod="POST" testBodyParams={{ "name": "" }}
curl -X POST 'http://localhost:9000/store/hello-world' \
```bash
curl -X POST 'http://localhost:9000/hello-world' \
-H 'Content-Type: application/json' \
--data-raw '{
"name": "John"
@@ -20,7 +20,7 @@ Requests to `/admin` must be user-authenticated to access the route.
<Note title="Tip">
Refer to the API Reference for [Admin](https://docs.medusajs.com/api/admin#authentication) and [Store](https://docs.medusajs.com/api/store#authentication) authentication methods.
Refer to the API Reference for [Admin](!api!/admin#authentication) and [Store](!api!/store#authentication) authentication methods.
</Note>
@@ -16,7 +16,7 @@ export const jsonHighlights = [
["7", "json", "Return a JSON object."]
]
```ts title="src/api/store/custom/route.ts" highlights={jsonHighlights} apiTesting testApiUrl="http://localhost:9000/store/custom" testApiMethod="GET"
```ts title="src/api/custom/route.ts" highlights={jsonHighlights}
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
export const GET = async (
@@ -51,7 +51,7 @@ export const statusHighlight = [
["7", "status", "Set the response code to `201`."]
]
```ts title="src/api/store/custom/route.ts" highlights={statusHighlight} apiTesting testApiUrl="http://localhost:9000/store/custom" testApiMethod="GET"
```ts title="src/api/custom/route.ts" highlights={statusHighlight}
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
export const GET = async (
@@ -8,7 +8,7 @@ In this chapter, you'll learn how to validate request body parameters in your cu
## Example Scenario
Consider you're creating a `POST` API route at `/store/custom`. It accepts two paramters `a` and `b` that are required numbers, and returns their sum.
Consider you're creating a `POST` API route at `/custom`. It accepts two paramters `a` and `b` that are required numbers, and returns their sum.
The next steps explain how to add validation to this API route, as an example.
@@ -20,9 +20,9 @@ Medusa uses [Zod](https://zod.dev/) to validate the body parameters of an incomi
To use Zod to validate your custom schemas, create a `validators.ts` file in any `src/api` subfolder. This file holds Zod schemas for each of your API routes.
For example, create the file `src/api/store/custom/validators.ts` with the following content:
For example, create the file `src/api/custom/validators.ts` with the following content:
```ts title="src/api/store/custom/validators.ts"
```ts title="src/api/custom/validators.ts"
import { z } from "zod"
export const PostStoreCustomSchema = z.object({
@@ -41,7 +41,7 @@ The `PostStoreCustomSchema` variable is a Zod schema that indicates the request
## Step 2: Add Validation Middleware
To use this schema for validating the body parameters of requests to `/store/custom`, use the `validateAndTransformBody` middleware provided by `@medusajs/medusa`. It accepts the Zod schema as a parameter.
To use this schema for validating the body parameters of requests to `/custom`, use the `validateAndTransformBody` middleware provided by `@medusajs/medusa`. It accepts the Zod schema as a parameter.
For example, create the file `src/api/middlewares.ts` with the following content:
@@ -50,12 +50,12 @@ import { defineMiddlewares } from "@medusajs/medusa"
import {
validateAndTransformBody,
} from "@medusajs/medusa/dist/api/utils/validate-body"
import { PostStoreCustomSchema } from "./store/custom/validators"
import { PostStoreCustomSchema } from "./custom/validators"
export default defineMiddlewares({
routes: [
{
matcher: "/store/custom",
matcher: "/custom",
method: "POST",
middlewares: [
validateAndTransformBody(PostStoreCustomSchema),
@@ -65,7 +65,7 @@ export default defineMiddlewares({
})
```
This applies the `validateAndTransformBody` middleware on `POST` requests to `/store/custom`. It uses the `PostStoreCustomSchema` as the validation schema.
This applies the `validateAndTransformBody` middleware on `POST` requests to `/custom`. It uses the `PostStoreCustomSchema` as the validation schema.
### How the Validation Works
@@ -79,14 +79,14 @@ If a request's body parameters are validated successfully, the middleware sets t
In your API route, consume the validated body using the `validatedBody` property of `MedusaRequest`.
For example, create the file `src/api/store/custom/route.ts` with the following content:
For example, create the file `src/api/custom/route.ts` with the following content:
export const routeHighlights = [
["5", "PostStoreCustomSchemaType", "Infer the request body type from the schema to pass it as a type parameter to `MedusaRequest`."],
["14", "", "Access the body parameters using `validatedBody`."]
]
```ts title="src/api/store/custom/route.ts" highlights={routeHighlights}
```ts title="src/api/custom/route.ts" highlights={routeHighlights}
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
import { z } from "zod"
import { PostStoreCustomSchema } from "./validators"
@@ -117,7 +117,7 @@ To pass the request body's type as a type parameter to `MedusaRequest`, use Zod'
## Test it Out
To test out the validation, send a `POST` request to `/store/custom`. You can try sending incorrect request body parameters.
To test out the validation, send a `POST` request to `/custom`. You can try sending incorrect request body parameters.
For example, if you omit the `a` parameter, you'll receive a `400` response code with the following response data:
@@ -24,7 +24,7 @@ In your resources, such as API routes or workflows, you can resolve Query to fet
## Query Example
For example, create the route `src/api/store/query/route.ts` with the following content:
For example, create the route `src/api/query/route.ts` with the following content:
export const exampleHighlights = [
["13", "", "Resolve Query from the Medusa container."],
@@ -33,7 +33,7 @@ export const exampleHighlights = [
["17", "fields", "An array of the data model’s properties to retrieve in the result."],
]
```ts title="src/api/store/query/route.ts" highlights={exampleHighlights} apiTesting testApiMethod="GET" testApiUrl="http://localhost:9000/store/query" collapsibleLines="1-8" expandButtonLabel="Show Imports"
```ts title="src/api/query/route.ts" highlights={exampleHighlights} collapsibleLines="1-8" expandButtonLabel="Show Imports"
import {
MedusaRequest,
MedusaResponse,
@@ -19,7 +19,7 @@ export const highlights = [
["14", "throwOnError", "Specify that errors occuring during the workflow's execution should be returned, not thrown."],
]
```ts title="src/api/store/workflows/route.ts" highlights={highlights} collapsibleLines="1-6" expandButtonLabel="Show Imports"
```ts title="src/api/workflows/route.ts" highlights={highlights} collapsibleLines="1-6" expandButtonLabel="Show Imports"
import type {
MedusaRequest,
MedusaResponse,
@@ -239,9 +239,9 @@ In the workflow construction function, you first run the `updateProduct` step, t
You can now use and execute your workflow in your Medusa application.
To execute the workflow in an API route, create the file `src/api/store/products/[id]/erp/route.ts` with the following content:
To execute the workflow in an API route, create the file `src/api/products/[id]/erp/route.ts` with the following content:
```ts title="src/api/store/products/[id]/erp/route.ts"
```ts title="src/api/products/[id]/erp/route.ts"
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
import updateProductAndErpWorkflow, {
UpdateProductAndErpWorkflowInput,
@@ -79,7 +79,7 @@ export default myWorkflow
3. Execute the workflow from a resource, such as an API route:
```ts title="src/api/store/workflow/route.ts" collapsibleLines="1-6" expandButtonLabel="Show Imports"
```ts title="src/api/workflow/route.ts" collapsibleLines="1-6" expandButtonLabel="Show Imports"
import type {
MedusaRequest,
MedusaResponse,
@@ -103,10 +103,10 @@ export async function GET(
npm run dev
```
5. Send a `GET` request to `/store/workflow`:
5. Send a `GET` request to `/workflow`:
```bash apiTesting testApiMethod="GET" testApiUrl="http://localhost:9000/store/workflow"
curl http://localhost:9000/store/workflow
```bash
curl http://localhost:9000/workflow
```
In the console, you'll see:
@@ -276,7 +276,7 @@ export const highlights = [
["30", "subscribe", "Subscribe to status changes of the workflow execution."],
]
```ts title="src/api/store/workflows/route.ts" highlights={highlights} collapsibleLines="1-11" expandButtonLabel="Show Imports"
```ts title="src/api/workflows/route.ts" highlights={highlights} collapsibleLines="1-11" expandButtonLabel="Show Imports"
import type { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
import myWorkflow from "../../../workflows/hello-world"
import {
+5 -5
View File
@@ -20,9 +20,9 @@ An API Route is created in a TypeScript or JavaScript file under the `src/api` d
Each file exports API Route handler functions for at least one HTTP method (`GET`, `POST`, `DELETE`, etc…).
For example, to create a `GET` API Route at `/store/hello-world`, create the file `src/api/store/hello-world/route.ts` with the following content:
For example, to create a `GET` API Route at `/hello-world`, create the file `src/api/hello-world/route.ts` with the following content:
```ts title="src/api/store/hello-world/route.ts"
```ts title="src/api/hello-world/route.ts"
import type {
MedusaRequest,
MedusaResponse,
@@ -46,10 +46,10 @@ To test the API route above, start the Medusa application:
npm run dev
```
Then, send a `GET` request to the `/store/hello-world` API Route:
Then, send a `GET` request to the `/hello-world` API Route:
```bash apiTesting testApiUrl="http://localhost:9000/store/hello-world" testApiMethod="GET"
curl http://localhost:9000/store/hello-world
```bash
curl http://localhost:9000/hello-world
```
---
@@ -105,9 +105,9 @@ Resolving a module's service is essential to use its methods that perform action
</Note>
For example, create the API route `src/api/store/custom/route.ts` with the following content:
For example, create the API route `src/api/custom/route.ts` with the following content:
```ts title="src/api/store/custom/route.ts"
```ts title="src/api/custom/route.ts"
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
import HelloModuleService from "../../../modules/hello/service"
import { HELLO_MODULE } from "../../../modules/hello"
@@ -132,10 +132,10 @@ Then, start the Medusa application:
npm run dev
```
Finally, send a `GET` request to `/store/custom`:
Finally, send a `GET` request to `/custom`:
```bash apiTesting testApiUrl="http://localhost:9000/store/custom" testApiMethod="GET"
curl http://localhost:9000/store/custom
```bash
curl http://localhost:9000/custom
```
You’ll receive the following response:
+4 -4
View File
@@ -96,7 +96,7 @@ To execute the workflow, invoke it passing the Medusa container as a parameter.
<CodeTabs group="resource-types">
<CodeTab label="API Route" value="api-route">
```ts title="src/api/store/workflow/route.ts" highlights={[["11"], ["12"], ["13"], ["14"], ["15"], ["16"]]} collapsibleLines="1-6" expandButtonLabel="Show Imports"
```ts title="src/api/workflow/route.ts" highlights={[["11"], ["12"], ["13"], ["14"], ["15"], ["16"]]} collapsibleLines="1-6" expandButtonLabel="Show Imports"
import type {
MedusaRequest,
MedusaResponse,
@@ -193,10 +193,10 @@ To test out your workflow, start your Medusa application:
npm run dev
```
Then, send a `GET` request to `/store/workflow`:
Then, send a `GET` request to `/workflow`:
```bash apiTesting testApiMethod="GET" testApiUrl="http://localhost:9000/store/workflow"
curl http://localhost:9000/store/workflow
```bash
curl http://localhost:9000/workflow
```
You’ll receive the following response:
@@ -19,9 +19,9 @@ In this chapter, you'll learn how to write integration tests for API routes usin
## Test a GET API Route
Consider the following API route created at `src/api/store/custom/route.ts`:
Consider the following API route created at `src/api/custom/route.ts`:
```ts title="src/api/store/custom/route.ts"
```ts title="src/api/custom/route.ts"
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
export async function GET(
@@ -37,7 +37,7 @@ export async function GET(
To write an integration test that tests this API route, create the file `integration-tests/http/custom-routes.spec.ts` with the following content:
export const getHighlights = [
["8", "api.get", "Send a GET request to the `/store/custom` API route."]
["8", "api.get", "Send a GET request to the `/custom` API route."]
]
```ts title="integration-tests/http/custom-routes.spec.ts" highlights={getHighlights}
@@ -46,10 +46,10 @@ import { medusaIntegrationTestRunner } from "medusa-test-utils"
medusaIntegrationTestRunner({
testSuite: ({ api, getContainer }) => {
describe("Custom endpoints", () => {
describe("GET /store/custom", () => {
describe("GET /custom", () => {
it("returns correct message", async () => {
const response = await api.get(
`/store/custom`
`/custom`
)
expect(response.status).toEqual(200)
@@ -64,7 +64,7 @@ medusaIntegrationTestRunner({
You use the `medusaIntegrationTestRunner` to write your tests.
You add a single test that sends a `GET` request to `/store/custom` using the `api.get` method. For the test to pass, the response is expected to:
You add a single test that sends a `GET` request to `/custom` using the `api.get` method. For the test to pass, the response is expected to:
- Have a code status `200`,
- Have a `message` property in the returned data.
@@ -103,9 +103,9 @@ const MyCustom = model.define("my_custom", {
export default MyCustom
```
And consider that the file `src/api/store/custom/route.ts` defines another route handler for `POST` requests:
And consider that the file `src/api/custom/route.ts` defines another route handler for `POST` requests:
```ts title="src/api/store/custom/route.ts"
```ts title="src/api/custom/route.ts"
// other imports...
import HelloModuleService from "../../../modules/hello/service"
@@ -134,7 +134,7 @@ This API route creates a new record of `MyCustom`.
To write tests for this API route, add the following at the end of the `testSuite` function in `integration-tests/http/custom-routes.spec.ts`:
export const postHighlights = [
["14", "api.post", "Send a POST request to the `/store/custom` API route."]
["14", "api.post", "Send a POST request to the `/custom` API route."]
]
```ts title="integration-tests/http/custom-routes.spec.ts" highlights={postHighlights}
@@ -146,13 +146,13 @@ medusaIntegrationTestRunner({
describe("Custom endpoints", () => {
// other tests...
describe("POST /store/custom", () => {
describe("POST /custom", () => {
const id = "1"
it("Creates my custom", async () => {
const response = await api.post(
`/store/custom`,
`/custom`,
{
id,
name: "Test",
@@ -174,7 +174,7 @@ medusaIntegrationTestRunner({
})
```
This adds a test for the `POST /store/custom` API route. It uses `api.post` to send the POST request. The `api.post` method accepts as a second parameter the data to pass in the request body.
This adds a test for the `POST /custom` API route. It uses `api.post` to send the POST request. The `api.post` method accepts as a second parameter the data to pass in the request body.
The test passes if the response has:
@@ -188,7 +188,7 @@ To ensure consistency in the database for the rest of the tests after the above
Use the `getContainer` function passed as a parameter to the `testSuite` function to resolve a service and use it for setup or teardown purposes
So, add an `afterAll` hook in the `describe` block for `POST /store/custom`:
So, add an `afterAll` hook in the `describe` block for `POST /custom`:
```ts title="integration-tests/http/custom-routes.spec.ts"
// other imports...
@@ -199,7 +199,7 @@ medusaIntegrationTestRunner({
describe("Custom endpoints", () => {
// other tests...
describe("POST /store/custom", () => {
describe("POST /custom", () => {
// ...
afterAll(() => async () => {
const helloModuleService: HelloModuleService = getContainer().resolve(
@@ -220,9 +220,9 @@ The `afterAll` hook resolves the `HelloModuleService` and use its `deleteMyCusto
## Test a DELETE API Route
Consider a `/store/custom/:id` API route created at `src/api/store/custom/[id]/route.ts`:
Consider a `/custom/:id` API route created at `src/api/custom/[id]/route.ts`:
```ts title="src/api/store/custom/[id]/route.ts"
```ts title="src/api/custom/[id]/route.ts"
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
import HelloModuleService from "../../../modules/hello/service"
@@ -247,7 +247,7 @@ This API route accepts an ID path parameter, and uses the `HelloModuleService` t
To add tests for this API route, add the following to `integration-tests/http/custom-routes.spec.ts`:
export const deleteHighlights = [
["21", "api.delete", "Send a DELETE request to the `/store/custom/:id` API route."]
["21", "api.delete", "Send a DELETE request to the `/custom/:id` API route."]
]
```ts title="integration-tests/http/custom-routes.spec.ts" highlights={deleteHighlights}
@@ -256,7 +256,7 @@ medusaIntegrationTestRunner({
describe("Custom endpoints", () => {
// ...
describe("DELETE /store/custom/:id", () => {
describe("DELETE /custom/:id", () => {
const id = "1"
beforeAll(() => async () => {
@@ -272,7 +272,7 @@ medusaIntegrationTestRunner({
it("Deletes my custom", async () => {
const response = await api.delete(
`/store/custom/${id}`
`/custom/${id}`
)
expect(response.status).toEqual(200)
@@ -285,9 +285,9 @@ medusaIntegrationTestRunner({
})
```
This adds a new test for the `DELETE /store/custom/:id` API route. You use the `beforeAll` hook to create a `MyCustom` record using the `HelloModuleService`.
This adds a new test for the `DELETE /custom/:id` API route. You use the `beforeAll` hook to create a `MyCustom` record using the `HelloModuleService`.
In the test, you use the `api.delete` method to send a `DELETE` request to `/store/custom/:id`. The test passes if the response:
In the test, you use the `api.delete` method to send a `DELETE` request to `/custom/:id`. The test passes if the response:
- Has a `200` status code.
- Has a `success` property in its data.
@@ -10,9 +10,9 @@ In this chapter, you’ll build your first customizations with Medusa.
API Routes expose business logic through REST APIs. You can create custom API routes to expose custom business logic.
To create an API route, create the file `src/api/store/hello-world/route.ts` with the following content:
To create an API route, create the file `src/api/hello-world/route.ts` with the following content:
```ts title="src/api/store/hello-world/route.ts"
```ts title="src/api/hello-world/route.ts"
import type {
MedusaRequest,
MedusaResponse,
@@ -40,10 +40,10 @@ To test out your customizations:
npm run dev
```
2. Send a `GET` request to `/store/hello-world`:
2. Send a `GET` request to `/hello-world`:
```bash apiTesting testApiMethod="GET" testApiUrl="http://localhost:9000/store/hello-world"
curl http://localhost:9000/store/hello-world
```bash
curl http://localhost:9000/hello-world
```
In the response, you’ll receive the following object:
@@ -13,3 +13,15 @@ You're free to choose how to build your storefront. You can start with our Next.
To learn how to build a storefront from scratch, check out the [Storefront Development guides](!resources!/storefront-development) in the Learning Resources documentation.
</Note>
---
## Passing a Publishable API Key in Storefront Requests
When sending a request to an API route starting with `/store`, you must include a publishable API key in the header of your request.
A publishable API key sets the scope of your request to one or more sales channels.
Then, when you retrieve products, only products of those sales channels are retrieved. This also ensures you retrieve correct inventory data, and associate created orders with the scoped sales channel.
Learn more about passing the publishable API key in [this storefront development guide](!resources!/storefront-development/publishable-api-keys).
+15 -15
View File
@@ -1,30 +1,30 @@
export const generatedEditDates = {
"app/basics/scheduled-jobs/page.mdx": "2024-08-05T07:24:27+00:00",
"app/basics/workflows/page.mdx": "2024-09-03T08:07:16.276Z",
"app/basics/workflows/page.mdx": "2024-09-11T10:48:38.853Z",
"app/deployment/page.mdx": "2024-08-05T07:24:05+00:00",
"app/page.mdx": "2024-09-03T07:09:09.034Z",
"app/basics/modules-and-services/page.mdx": "2024-09-04T15:37:27.695Z",
"app/basics/modules-and-services/page.mdx": "2024-09-11T10:48:35.195Z",
"app/basics/commerce-modules/page.mdx": "2024-09-03T07:48:48.148Z",
"app/advanced-development/workflows/retry-failed-steps/page.mdx": "2024-07-31T17:01:33+03:00",
"app/advanced-development/workflows/workflow-hooks/page.mdx": "2024-09-10T11:39:51.168Z",
"app/cheatsheet/page.mdx": "2024-07-11T13:53:40+03:00",
"app/debugging-and-testing/logging/page.mdx": "2024-07-04T17:26:03+03:00",
"app/more-resources/page.mdx": "2024-07-04T17:26:03+03:00",
"app/storefront-development/page.mdx": "2024-07-04T17:26:03+03:00",
"app/storefront-development/page.mdx": "2024-09-11T10:58:59.290Z",
"app/storefront-development/nextjs-starter/page.mdx": "2024-07-04T17:26:03+03:00",
"app/basics/page.mdx": "2024-09-03T07:11:06.879Z",
"app/basics/admin-customizations/page.mdx": "2024-09-03T08:07:35.584Z",
"app/advanced-development/workflows/workflow-timeout/page.mdx": "2024-07-31T17:01:33+03:00",
"app/advanced-development/workflows/parallel-steps/page.mdx": "2024-07-31T17:01:33+03:00",
"app/advanced-development/page.mdx": "2024-07-04T17:26:03+03:00",
"app/first-customizations/page.mdx": "2024-05-07T18:00:28+02:00",
"app/first-customizations/page.mdx": "2024-09-11T10:48:42.374Z",
"app/debugging-and-testing/page.mdx": "2024-05-03T17:36:38+03:00",
"app/basics/medusa-container/page.mdx": "2024-09-03T07:31:40.214Z",
"app/architectural-modules/page.mdx": "2024-07-04T17:26:03+03:00",
"app/basics/project-directories-files/page.mdx": "2024-07-04T17:26:03+03:00",
"app/basics/api-routes/page.mdx": "2024-07-04T17:26:03+03:00",
"app/basics/api-routes/page.mdx": "2024-09-11T10:48:31.777Z",
"app/basics/modules-directory-structure/page.mdx": "2024-05-07T18:00:28+02:00",
"app/advanced-development/workflows/access-workflow-errors/page.mdx": "2024-07-04T17:26:03+03:00",
"app/advanced-development/workflows/access-workflow-errors/page.mdx": "2024-09-11T10:46:54.913Z",
"app/basics/events-and-subscribers/page.mdx": "2024-09-03T08:01:30.986Z",
"app/advanced-development/modules/container/page.mdx": "2024-08-05T07:23:49+00:00",
"app/basics/data-models/page.mdx": "2024-09-03T07:58:42.761Z",
@@ -33,11 +33,11 @@ export const generatedEditDates = {
"app/advanced-development/admin/widgets/page.mdx": "2024-08-06T09:44:22+02:00",
"app/advanced-development/data-models/page.mdx": "2024-07-04T17:26:03+03:00",
"app/advanced-development/modules/remote-link/page.mdx": "2024-07-24T09:16:01+02:00",
"app/advanced-development/api-routes/protected-routes/page.mdx": "2024-09-10T11:39:51.166Z",
"app/advanced-development/api-routes/protected-routes/page.mdx": "2024-09-11T10:45:44.293Z",
"app/advanced-development/workflows/add-workflow-hook/page.mdx": "2024-08-13T09:55:37+03:00",
"app/advanced-development/events-and-subscribers/data-payload/page.mdx": "2024-07-16T17:12:05+01:00",
"app/advanced-development/data-models/default-properties/page.mdx": "2024-07-02T12:34:44+03:00",
"app/advanced-development/workflows/advanced-example/page.mdx": "2024-07-31T17:01:33+03:00",
"app/advanced-development/workflows/advanced-example/page.mdx": "2024-09-11T10:46:59.975Z",
"app/advanced-development/events-and-subscribers/emit-event/page.mdx": "2024-09-10T11:39:51.168Z",
"app/advanced-development/workflows/conditions/page.mdx": "2024-07-31T17:01:33+03:00",
"app/advanced-development/modules/module-link-directions/page.mdx": "2024-07-24T09:16:01+02:00",
@@ -55,18 +55,18 @@ export const generatedEditDates = {
"app/advanced-development/modules/module-links/page.mdx": "2024-07-24T09:16:01+02:00",
"app/advanced-development/data-models/searchable-property/page.mdx": "2024-07-04T17:26:03+03:00",
"app/advanced-development/scheduled-jobs/execution-number/page.mdx": "2024-07-02T09:41:15+00:00",
"app/advanced-development/api-routes/parameters/page.mdx": "2024-09-04T08:17:50.071Z",
"app/advanced-development/api-routes/http-methods/page.mdx": "2024-09-04T08:15:11.609Z",
"app/advanced-development/api-routes/parameters/page.mdx": "2024-09-11T10:44:13.491Z",
"app/advanced-development/api-routes/http-methods/page.mdx": "2024-09-11T10:43:33.169Z",
"app/advanced-development/admin/tips/page.mdx": "2024-09-10T11:39:51.165Z",
"app/advanced-development/api-routes/cors/page.mdx": "2024-09-04T08:24:47.068Z",
"app/advanced-development/admin/ui-routes/page.mdx": "2024-08-06T09:44:22+02:00",
"app/advanced-development/api-routes/middlewares/page.mdx": "2024-09-04T09:45:12.441Z",
"app/advanced-development/api-routes/middlewares/page.mdx": "2024-09-11T10:45:31.861Z",
"app/advanced-development/modules/isolation/page.mdx": "2024-07-04T17:26:03+03:00",
"app/advanced-development/data-models/configure-properties/page.mdx": "2024-07-04T17:26:03+03:00",
"app/advanced-development/data-models/index/page.mdx": "2024-07-04T17:26:03+03:00",
"app/advanced-development/custom-cli-scripts/page.mdx": "2024-07-04T17:26:03+03:00",
"app/advanced-development/data-models/property-types/page.mdx": "2024-07-04T17:26:03+03:00",
"app/debugging-and-testing/testing-tools/integration-tests/api-routes/page.mdx": "2024-09-10T11:39:51.170Z",
"app/debugging-and-testing/testing-tools/integration-tests/api-routes/page.mdx": "2024-09-11T10:48:09.593Z",
"app/debugging-and-testing/testing-tools/integration-tests/page.mdx": "2024-09-10T11:39:51.170Z",
"app/debugging-and-testing/testing-tools/integration-tests/workflows/page.mdx": "2024-09-10T11:39:51.171Z",
"app/debugging-and-testing/testing-tools/page.mdx": "2024-09-10T11:39:51.172Z",
@@ -74,11 +74,11 @@ export const generatedEditDates = {
"app/debugging-and-testing/testing-tools/unit-tests/page.mdx": "2024-09-02T11:03:26.997Z",
"app/advanced-development/modules/service-constraints/page.mdx": "2024-09-04T15:37:04.166Z",
"app/advanced-development/api-routes/page.mdx": "2024-09-04T09:36:33.961Z",
"app/advanced-development/api-routes/responses/page.mdx": "2024-09-10T11:39:51.167Z",
"app/advanced-development/api-routes/validation/page.mdx": "2024-09-10T11:39:51.167Z",
"app/advanced-development/api-routes/responses/page.mdx": "2024-09-11T10:44:37.016Z",
"app/advanced-development/api-routes/validation/page.mdx": "2024-09-11T10:46:31.476Z",
"app/advanced-development/api-routes/errors/page.mdx": "2024-09-10T11:39:51.166Z",
"app/advanced-development/admin/constraints/page.mdx": "2024-09-10T11:39:51.165Z",
"app/advanced-development/modules/query/page.mdx": "2024-09-10T11:39:51.168Z",
"app/advanced-development/modules/query/page.mdx": "2024-09-11T10:46:49.512Z",
"app/debugging-and-testing/testing-tools/modules-tests/module-example/page.mdx": "2024-09-10T11:39:51.171Z",
"app/debugging-and-testing/testing-tools/modules-tests/page.mdx": "2024-09-10T11:39:51.171Z"
}
@@ -2268,6 +2268,9 @@ export const getDigitalProductPreview = cache(async function ({
const { previews } = await fetch(
`${process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL}/store/digital-products/${id}/preview`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
}).then((res) => res.json())
// for simplicity, return only the first preview url
@@ -2378,6 +2381,7 @@ export const getCustomerDigitalProducts = async () => {
credentials: "include",
headers: {
...getAuthHeaders(),
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
}).then((res) => res.json())
@@ -2536,6 +2540,7 @@ export const getDigitalMediaDownloadLink = async (mediaId: string) => {
method: "POST",
headers: {
...getAuthHeaders(),
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
}).then((res) => res.json())
@@ -57,6 +57,10 @@ This recipe is adapted from [Medusa Eats](https://github.com/medusajs/medusa-eat
text: "A new Medusa application installed.",
link: "!docs!#get-started"
},
{
text: "Publishable API key to send store requests. You can create it in the Medusa Admin or using the Admin API routes",
link: "/storefront-development/publishable-api-keys"
},
{
text: "Recommended: Use the Redis Workflow Engine Module for improved tracking and storage of workflow executions."
}
@@ -2134,6 +2138,7 @@ Before using the API route, you must have a cart with at least one product from
```bash
curl -X POST 'http://localhost:9000/store/carts' \
-H 'Content-Type: application/json' \
-H 'x-publishable-api-key: {your_publishable_api_key}' \
--data-raw '{
"region_id": "reg_01J66SWSSWFZPQV0GWR2W7P1SB",
"sales_channel_id": "sc_01J66SWSRK95F2P2KTFHMYR7VC",
@@ -2164,6 +2169,7 @@ curl -X POST 'http://localhost:9000/store/carts' \
```bash
curl -X POST 'http://localhost:9000/store/carts/cart_01J67MS5WPH2CE5R84BENJCGSW/line-items' \
-H 'Content-Type: application/json' \
-H 'x-publishable-api-key: {your_publishable_api_key}' \
--data-raw '{
"variant_id": "variant_01J66T0VC2S0NB4BNDBCZN8P9F",
"quantity": 1
@@ -2176,6 +2182,7 @@ curl -X POST 'http://localhost:9000/store/carts/cart_01J67MS5WPH2CE5R84BENJCGSW/
```bash
curl 'http://localhost:9000/store/shipping-options?cart_id=cart_01J67JT10B3RCWKT9NFEFYA2XG' \
-H 'x-publishable-api-key: {your_publishable_api_key}'
```
Make sure to replace the value of the `cart_id` query parameter with the cart’s ID.
@@ -2185,6 +2192,7 @@ curl 'http://localhost:9000/store/shipping-options?cart_id=cart_01J67JT10B3RCWKT
```bash
curl -X POST 'http://localhost:9000/store/carts/cart_01J67MS5WPH2CE5R84BENJCGSW/shipping-methods' \
-H 'Content-Type: application/json' \
-H 'x-publishable-api-key: {your_publishable_api_key}' \
--data-raw '{
"option_id": "so_01J66SWSVQG7S1BSJKR7PYWH6C",
"data": {}
@@ -2198,6 +2206,7 @@ curl -X POST 'http://localhost:9000/store/carts/cart_01J67MS5WPH2CE5R84BENJCGSW/
```bash
curl -X POST 'http://localhost:9000/store/payment-collections' \
-H 'Content-Type: application/json' \
-H 'x-publishable-api-key: {your_publishable_api_key}' \
--data-raw '{
"cart_id": "cart_01J67MS5WPH2CE5R84BENJCGSW"
}'
@@ -2210,6 +2219,7 @@ curl -X POST 'http://localhost:9000/store/payment-collections' \
```bash
curl -X POST 'http://localhost:9000/store/payment-collections/pay_col_01J67MSK397M3BKD3RDVDMJSRE/payment-sessions' \
-H 'Content-Type: application/json' \
-H 'x-publishable-api-key: {your_publishable_api_key}' \
--data-raw '{
"provider_id": "pp_system_default"
}'
@@ -2227,6 +2237,7 @@ Then, send a `POST` request to `/store/deliveries` to create the order delivery:
```bash
curl -X POST 'http://localhost:9000/store/deliveries' \
-H 'Content-Type: application/json' \
-H 'x-publishable-api-key: {your_publishable_api_key}' \
--data '{
"cart_id": "cart_01J67MS5WPH2CE5R84BENJCGSW",
"restaurant_id": "res_01J66SYN5DSRR0R6QM3A4SYRFZ"
@@ -3256,9 +3267,9 @@ In this step, you’ll learn how to implement real-time tracking of a delivery i
Before adding the storefront UI, you need an API route that allows a client to stream delivery changes.
So, create the file `src/api/store/deliveries/subscribe/route.ts` with the following content:
So, create the file `src/api/deliveries/subscribe/route.ts` with the following content:
```ts title="src/api/store/deliveries/subscribe/route.ts" collapsibleLines="1-12" expandButtonLabel="Show Imports"
```ts title="src/api/deliveries/subscribe/route.ts" collapsibleLines="1-12" expandButtonLabel="Show Imports"
import {
MedusaRequest,
MedusaResponse,
@@ -3287,11 +3298,11 @@ export const GET = async (
}
```
This creates a `GET` API route at `/store/deliveries/[id]/subscribe`. Currently, you only retrieve the delivery by its ID.
This creates a `GET` API route at `/deliveries/[id]/subscribe`. Currently, you only retrieve the delivery by its ID.
Next, you’ll stream the changes in the delivery. To do that, replace the `TODO` with the following:
```ts title="src/api/store/deliveries/subscribe/route.ts"
```ts title="src/api/deliveries/subscribe/route.ts"
const headers = {
"Content-Type": "text/event-stream",
Connection: "keep-alive",
@@ -3316,7 +3327,7 @@ In the above snippet, you set the response to a stream and write an initial mess
To listen to the workflow changes, replace the new `TODO` with the following:
```ts title="src/api/store/deliveries/subscribe/route.ts"
```ts title="src/api/deliveries/subscribe/route.ts"
const workflowEngine = req.scope.resolve(
Modules.WORKFLOW_ENGINE
)
@@ -3338,9 +3349,9 @@ In this snippet, you resolve the Workflow Engine Module’s main service. Then,
The storefront UI will also need to retrieve the delivery. So, you’ll create an API route that retrieves the delivery’s details.
Create the file `src/api/store/deliveries/[id]/route.ts` with the following content:
Create the file `src/api/deliveries/[id]/route.ts` with the following content:
```ts title="src/api/store/deliveries/[id]/route.ts"
```ts title="src/api/deliveries/[id]/route.ts"
import { MedusaRequest, MedusaResponse } from "@medusajs/medusa"
import { DELIVERY_MODULE } from "../../../../modules/delivery"
@@ -3405,6 +3416,9 @@ To retrieve the delivery from the Medusa application, replace the first `TODO` w
// retrieve the delivery
fetch(`http://localhost:9000/store/deliveries/${id}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_PAK,
},
})
.then((res) => res.json())
.then((data) => {
@@ -3420,7 +3434,7 @@ Next, to subscribe to the delivery’s changes in real-time, replace the remaini
```tsx title="Storefront Page"
// subscribe to the delivery updates
const source = new EventSource(
`http://localhost:9000/store/deliveries/${id}/subscribe`
`http://localhost:9000/deliveries/${id}/subscribe`
)
source.onmessage = (message) => {
@@ -3442,7 +3456,7 @@ return () => {
}
```
You use the [EventSource API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) to receive the stream from the `/store/deliveries/[id]/subscribe` API route.
You use the [EventSource API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) to receive the stream from the `/deliveries/[id]/subscribe` API route.
When a new message is set, the new delivery update is extracted from `message.data.response`, if `response` is available and has a `delivery_status` property.
@@ -28,6 +28,7 @@ For example, if you’re asking customers to enter a message to put in a letter
```bash
curl -X POST '{backend_url}/store/carts/{id}/line-items' \
-H 'Content-Type: application/json' \
-H 'x-publishable-api-key: {your_publishable_api_key}' \
--data-raw '{
"variant_id": "variant_123",
"quantity": 1,
@@ -2234,7 +2234,8 @@ Then, send a `GET` request to `/store/customers/me/subscriptions` to retrieve th
```bash
curl 'http://localhost:9000/store/customers/me/subscriptions' \
-H 'Authorization: Bearer {token}'
-H 'Authorization: Bearer {token}' \
-H 'x-publishable-api-key: {your_publishable_api_key}'
```
Where `{token}` is the token retrieved from the previous request.
@@ -2243,7 +2244,8 @@ To cancel a subscription, send a `POST` request to `/store/customers/me/subscrip
```bash
curl -X POST 'http://localhost:9000/store/customers/me/subscriptions/01J2VB8TVC14K29FREQ2DRS6NA' \
-H 'Authorization: Bearer {token}'
-H 'Authorization: Bearer {token}' \
-H 'x-publishable-api-key: {your_publishable_api_key}'
```
---
@@ -22,10 +22,10 @@ export const highlights = [
["32", "useRegion", "Use the `useRegion` hook defined in the Region Context guide."],
["37", "setItem", "Set the cart's ID in `localStorage` in case it changed."],
["45", "fetch", "If the customer doesn't have a cart, create a new one."],
["49", "process.env.NEXT_PUBLIC_PAK", "Pass the Publishable API key to associate the correct sales channel(s)."],
["49", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to associate the correct sales channel(s)."],
["63", "fetch", "Retrieve the customer's cart."],
["73", "refreshCart", "This function unsets the cart, which triggers the `useEffect` callback to create a cart."],
["89", "useCart", "The hook that child components of the provider use to access the cart."]
["76", "refreshCart", "This function unsets the cart, which triggers the `useEffect` callback to create a cart."],
["92", "useCart", "The hook that child components of the provider use to access the cart."]
]
```tsx highlights={highlights}
@@ -72,7 +72,7 @@ export const CartProvider = ({ children }: CartProviderProps) => {
method: "POST",
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
@@ -88,6 +88,9 @@ export const CartProvider = ({ children }: CartProviderProps) => {
// retrieve cart
fetch(`http://localhost:9000/store/carts/${cartId}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ cart: dataCart }) => {
@@ -20,7 +20,7 @@ For example:
<CodeTab label="Fetch API" value="fetch">
export const fetchHighlights = [
["5", "process.env.NEXT_PUBLIC_PAK", "Pass the Publishable API key to associate the correct sales channel(s)."],
["5", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to associate the correct sales channel(s)."],
["9", "region_id", "Associate the cart with the chosen region for accurate pricing."],
["14", "setItem", "Set the cart's ID in the `localStorage`."]
]
@@ -30,7 +30,7 @@ export const fetchHighlights = [
method: "POST",
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
@@ -50,7 +50,7 @@ export const highlights = [
["8", "region", "Assuming you previously retrieved the chosen region."],
["15", "cartId", "Retrieve the cart ID from `localStorage`, if exists."],
["21", "", "Send a request to create the cart."],
["26", "process.env.NEXT_PUBLIC_PAK", "Pass the Publishable API key to associate the correct sales channel(s)."],
["26", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to associate the correct sales channel(s)."],
["30", "region_id", "Associate the cart with the chosen region for accurate pricing."],
["35", "setItem", "Set the cart's ID in the `localStorage`."]
]
@@ -81,7 +81,7 @@ export const highlights = [
method: "POST",
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
@@ -19,7 +19,8 @@ For example:
export const addHighlights = [
["1", "variant_id", "The ID of the selected variant."],
["2", "cartId", "Retrieve the cart ID from the `localStorage`."],
["16", "quantity", "You can also allow customers to specify the quantity."]
["13", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "You must pass the publishable API key of all storefront requests."],
["17", "quantity", "You can also allow customers to specify the quantity."]
]
```ts highlights={addHighlights}
@@ -35,6 +36,7 @@ const addToCart = (variant_id: string) => {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
variant_id,
@@ -70,6 +72,7 @@ export const updateHighlights = [
["3", "quantity", "The new quantity of the item."],
["5", "cartId", "Retrieve the cart ID from the `localStorage`."],
["12", "itemId", "Pass the item's ID as a path parameter."],
["18", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "You must pass the publishable API key of all storefront requests."],
]
```ts highlights={updateHighlights}
@@ -90,6 +93,7 @@ const updateQuantity = (
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
quantity,
@@ -122,7 +126,8 @@ export const deleteHighlights = [
["1", "itemId", "The ID of the line item to remove."],
["2", "cartId", "Retrieve the cart ID from the `localStorage`."],
["9", "itemId", "Pass the item's ID as a path parameter."],
["15", "parent", "The updated cart is returned as the `parent` field."]
["13", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "You must pass the publishable API key of all storefront requests."],
["18", "parent", "The updated cart is returned as the `parent` field."]
]
```ts highlights={deleteHighlights}
@@ -137,6 +142,9 @@ const removeItem = (itemId: string) => {
itemId
}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
method: "DELETE",
})
.then((res) => res.json())
@@ -22,6 +22,9 @@ export const fetchHighlights = [
```ts highlights={fetchHighlights}
fetch(`http://localhost:9000/store/carts/${cartId}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ cart }) => {
@@ -37,8 +40,8 @@ export const highlights = [
["16", "cartId", "Retrieve the cart ID from `localStorage`."],
["18", "TODO", "You can create the cart and set it here as explained in the Create Cart guide."],
["22"], ["23"], ["24"], ["25"], ["26"], ["27"], ["28"],
["31", "formatPrice", "This function was previously created to format product prices. You can re-use the same function."],
["34", "currency_code", "If you reuse the `formatPrice` function, pass the currency code as a parameter."],
["34", "formatPrice", "This function was previously created to format product prices. You can re-use the same function."],
["37", "currency_code", "If you reuse the `formatPrice` function, pass the currency code as a parameter."],
]
```tsx highlights={highlights}
@@ -65,6 +68,9 @@ export const highlights = [
fetch(`http://localhost:9000/store/carts/${cartId}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ cart: dataCart }) => {
@@ -21,7 +21,7 @@ If a customer changes their region, you must update their cart to be associated
For example:
export const updateRegionHighlights = [
["8", `"new_id"`, "Pass the new chosen region's ID."]
["11", `"new_id"`, "Pass the new chosen region's ID."]
]
```ts highlights={updateRegionHighlights}
@@ -30,6 +30,9 @@ fetch(`http://localhost:9000/store/carts/${cartId}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
},
body: JSON.stringify({
region_id: "new_id",
@@ -53,7 +56,7 @@ If a guest customer logs in, you must update the cart to be associated with the
For example:
export const updateCustomerHighlights = [
["8", `"logged_in_id"`, "Pass the logged-in customer's ID."]
["11", `"logged_in_id"`, "Pass the logged-in customer's ID."]
]
```ts highlights={updateCustomerHighlights}
@@ -62,6 +65,9 @@ fetch(`http://localhost:9000/store/carts/${cartId}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
},
body: JSON.stringify({
customer_id: "logged_in_id",
@@ -37,6 +37,7 @@ For example:
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
shipping_address: address,
@@ -57,8 +58,8 @@ export const highlights = [
["4", "useCart", "The `useCart` hook was defined in the Cart React Context documentation."],
["29", "address", "Assemble the address object to be used for both shipping and billing addresses."],
["41"], ["42"], ["43"], ["44"], ["45"], ["46"], ["47"], ["48"],
["49"], ["50"], ["51"], ["52"], ["53"], ["54"], ["55"],
["102", "", "The address's country can only be within the cart's region."]
["49"], ["50"], ["51"], ["52"], ["53"], ["54"], ["55"], ["56"]
["103", "", "The address's country can only be within the cart's region."]
]
```tsx highlights={highlights}
@@ -107,6 +108,7 @@ export const highlights = [
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
shipping_address: address,
@@ -17,6 +17,9 @@ fetch(
`http://localhost:9000/store/carts/${cartId}/complete`,
{
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
method: "POST",
}
)
@@ -53,10 +56,10 @@ export const highlights = [
["10", "handlePayment", "This function sends the request\nto the Medusa application to complete the cart."],
["21", "TODO", "If you're integrating a third-party payment provider,\nyou perform the custom logic before completing the cart."],
["24", "fetch", "Send a request to the Medusa application\nto complete the cart and place the order."],
["33", `type === "cart"`, "If the `type` returned is `cart`,\nit means an error occurred and the cart wasn't completed."],
["36", `type === "order"`, "If the `type` returned is `order`,\nit means the cart was completed and the order was placed successfully."],
["40", "refreshCart", "Unset and reset the cart."],
["47", "button", "This button triggers the `handlePayment` function when clicked."]
["36", `type === "cart"`, "If the `type` returned is `cart`,\nit means an error occurred and the cart wasn't completed."],
["39", `type === "order"`, "If the `type` returned is `order`,\nit means the cart was completed and the order was placed successfully."],
["43", "refreshCart", "Unset and reset the cart."],
["50", "button", "This button triggers the `handlePayment` function when clicked."]
]
```tsx highlights={highlights}
@@ -87,6 +90,9 @@ export default function SystemDefaultPayment() {
`http://localhost:9000/store/carts/${cart.id}/complete`,
{
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
method: "POST",
}
)
@@ -27,6 +27,7 @@ For example:
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
email,
@@ -46,7 +47,7 @@ export const highlights = [
["4", "useCart", "The `useCart` hook was defined in the Cart React Context documentation."],
["13", "TODO", "Cart must have at least one item. If not, redirect to another page."],
["27"], ["28"], ["29"], ["30"], ["31"], ["32"], ["33"], ["34"],
["35"], ["36"], ["37"], ["38"], ["39"], ["40"]
["35"], ["36"], ["37"], ["38"], ["39"], ["40"], ["41"]
]
```tsx highlights={highlights}
@@ -81,6 +82,7 @@ export const highlights = [
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
email,
@@ -34,17 +34,17 @@ For example, to implement the payment step flow:
export const fetchHighlights = [
["6", "retrievePaymentProviders", "This function retrieves the payment provider that the customer can choose from."],
["7", "fetch", "Retrieve available payment providers."],
["18", "selectPaymentProvider", "This function is executed when the customer submits their chosen payment provider."],
["25", "fetch", "Create a payment collection for the cart when it doesn't have one."],
["44", "fetch", "Initialize the payment session in the payment collection for the chosen provider."],
["62", "fetch", "Retrieve the cart again to update its data."],
["73", "getPaymentUi", "This function shows the necessary UI based on the selected payment provider."],
["74", "activePaymentSession", "The active session is the first in the payment collection's sessions."],
["80", "", "Test which payment provider is chosen based on the prefix of the provider ID."],
["81", `"pp_stripe_"`, "Check if the chosen provider is Stripe."],
["85", `"pp_system_default"`, "Check if the chosen provider is the default systen provider."],
["87", "default", "Handle unrecognized providers."],
["94", "handlePayment", "The function that handles the payment process using the above functions."]
["21", "selectPaymentProvider", "This function is executed when the customer submits their chosen payment provider."],
["28", "fetch", "Create a payment collection for the cart when it doesn't have one."],
["48", "fetch", "Initialize the payment session in the payment collection for the chosen provider."],
["67", "fetch", "Retrieve the cart again to update its data."],
["81", "getPaymentUi", "This function shows the necessary UI based on the selected payment provider."],
["82", "activePaymentSession", "The active session is the first in the payment collection's sessions."],
["88", "", "Test which payment provider is chosen based on the prefix of the provider ID."],
["89", `"pp_stripe_"`, "Check if the chosen provider is Stripe."],
["93", `"pp_system_default"`, "Check if the chosen provider is the default systen provider."],
["95", "default", "Handle unrecognized providers."],
["102", "handlePayment", "The function that handles the payment process using the above functions."]
]
```ts highlights={fetchHighlights}
@@ -59,6 +59,9 @@ const retrievePaymentProviders = async () => {
cart.region_id
}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -79,6 +82,7 @@ const selectPaymentProvider = async (
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
cart_id: cart.id,
@@ -99,6 +103,7 @@ const selectPaymentProvider = async (
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
provider_id: selectedPaymentProviderId,
@@ -113,6 +118,9 @@ const selectPaymentProvider = async (
`http://localhost:9000/store/carts/${cart.id}`,
{
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
}
)
.then((res) => res.json())
@@ -159,18 +167,18 @@ const handlePayment = () => {
export const highlights = [
["4", "useCart", "The `useCart` hook was defined in the Cart React Context documentation."],
["23", "fetch", "Retrieve available payment providers."],
["31", "setSelectedPaymentProvider", "If a payment provider was selected before, pre-fill it."],
["37", "handleSelectProvider", "This function is executed when the customer submits their chosen payment provider."],
["50", "fetch", "Create a payment collection for the cart when it doesn't have one."],
["72", "fetch", "Initialize the payment session in the payment collection for the chosen provider."],
["90", "fetch", "Retrieve the cart again to update its data."],
["103", "getPaymentUi", "This function shows the necessary UI based on the selected payment provider."],
["104", "activePaymentSession", "The active session is the first in the payment collection's sessions."],
["110", "", "Test which payment provider is chosen based on the prefix of the provider ID."],
["111", `"pp_stripe_"`, "Check if the chosen provider is Stripe."],
["119", `"pp_system_default"`, "Check if the chosen provider is the default systen provider."],
["125", "default", "Handle unrecognized providers."],
["160", "getPaymentUi", "If a provider is chosen, render its UI."]
["34", "setSelectedPaymentProvider", "If a payment provider was selected before, pre-fill it."],
["40", "handleSelectProvider", "This function is executed when the customer submits their chosen payment provider."],
["53", "fetch", "Create a payment collection for the cart when it doesn't have one."],
["76", "fetch", "Initialize the payment session in the payment collection for the chosen provider."],
["95", "fetch", "Retrieve the cart again to update its data."],
["111", "getPaymentUi", "This function shows the necessary UI based on the selected payment provider."],
["112", "activePaymentSession", "The active session is the first in the payment collection's sessions."],
["118", "", "Test which payment provider is chosen based on the prefix of the provider ID."],
["119", `"pp_stripe_"`, "Check if the chosen provider is Stripe."],
["127", `"pp_system_default"`, "Check if the chosen provider is the default systen provider."],
["133", "default", "Handle unrecognized providers."],
["168", "getPaymentUi", "If a provider is chosen, render its UI."]
]
```tsx highlights={highlights}
@@ -200,6 +208,9 @@ export default function CheckoutPaymentStep() {
cart.region_id
}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ payment_providers }) => {
@@ -231,6 +242,7 @@ export default function CheckoutPaymentStep() {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
cart_id: cart.id,
@@ -251,6 +263,7 @@ export default function CheckoutPaymentStep() {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
provider_id: selectedPaymentProvider,
@@ -265,6 +278,9 @@ export default function CheckoutPaymentStep() {
`http://localhost:9000/store/carts/${cart.id}`,
{
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
}
)
.then((res) => res.json())
@@ -66,10 +66,10 @@ export const highlights = [
["61", "confirmCardPayment", "This function shows the UI to the customer to accept the card payment."],
["78", "", "Once the customer enters their card details and submits the form,\nthe Promise resolves and executes this function."],
["85", "fetch", "Send a request to the Medusa application\nto complete the cart and place the order."],
["94", `type === "cart"`, "If the `type` returned is `cart`,\nit means an error occurred and the cart wasn't completed."],
["97", `type === "order"`, "If the `type` returned is `order`,\nit means the cart was completed and the order was placed successfully."],
["101", "refreshCart", "Unset and reset the cart."],
["111", "button", "This button triggers the `handlePayment` function when clicked."]
["97", `type === "cart"`, "If the `type` returned is `cart`,\nit means an error occurred and the cart wasn't completed."],
["100", `type === "order"`, "If the `type` returned is `order`,\nit means the cart was completed and the order was placed successfully."],
["104", "refreshCart", "Unset and reset the cart."],
["114", "button", "This button triggers the `handlePayment` function when clicked."]
]
```tsx highlights={highlights}
@@ -161,6 +161,9 @@ const StripeForm = ({
`http://localhost:9000/store/carts/${cart.id}/complete`,
{
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
method: "POST",
}
)
@@ -20,8 +20,8 @@ For example:
export const fetchHighlights = [
["3", "retrieveShippingOptions", "This function retrieves the shipping options of the customer's cart."],
["16", "setShippingMethod", "This function sets the shipping method of the cart using the selected shipping option."],
["29", "data", "Pass in this property any data relevant to the fulfillment provider."],
["19", "setShippingMethod", "This function sets the shipping method of the cart using the selected shipping option."],
["33", "data", "Pass in this property any data relevant to the fulfillment provider."],
]
```ts highlights={fetchHighlights}
@@ -33,6 +33,9 @@ export const fetchHighlights = [
cart.id
}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
}
)
.then((res) => res.json())
@@ -50,6 +53,7 @@ export const fetchHighlights = [
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
option_id: selectedShippingOptionId,
@@ -73,8 +77,8 @@ export const fetchHighlights = [
export const highlights = [
["4", "useCart", "The `useCart` hook was defined in the Cart React Context documentation."],
["22", "fetch", "Retrieve available shipping method of the customer's cart."],
["43", "fetch", "Set the cart's shipping method using the selected shipping option."],
["53", "data", "Pass in this property any data relevant to the fulfillment provider."]
["46", "fetch", "Set the cart's shipping method using the selected shipping option."],
["57", "data", "Pass in this property any data relevant to the fulfillment provider."]
]
```tsx highlights={highlights}
@@ -103,6 +107,9 @@ export const highlights = [
cart.id
}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ shipping_options }) => {
@@ -127,6 +134,7 @@ export const highlights = [
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
option_id: selectedShippingOption,
@@ -30,6 +30,9 @@ export const fetchHighlights = [
searchParams.toString()
}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ addresses, count }) => {
@@ -44,11 +47,11 @@ export const fetchHighlights = [
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."]
["31", "searchParams.toString()", "Pass the pagination parameters in the query."],
["34", "count", "The total number of addresses in the Medusa application."],
["48", "setHasMorePages", "Set whether there are more pages based on the total count."],
["62", "", "Using only two address fields for simplicity."],
["68", "button", "Show a button to load more addresses if there are more pages."]
]
```tsx highlights={highlights} collapsibleLines="50-77" expandButtonLabel="Show render"
@@ -82,6 +85,9 @@ export const highlights = [
searchParams.toString()
}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ addresses: addressesData, count }) => {
@@ -155,6 +161,7 @@ To add a new address for the customer, send a request to the [Add Customer Addre
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
first_name: firstName,
@@ -183,7 +190,7 @@ export const addHighlights = [
["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"]
["48"], ["49"], ["50"]
]
```tsx highlights={addHighlights} collapsibleLines="53-124" expandButtonLabel="Show form"
@@ -219,6 +226,7 @@ export const addHighlights = [
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
first_name: firstName,
@@ -337,6 +345,7 @@ To edit an address, send a request to the [Update Customer Address API route](!a
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
first_name: firstName,
@@ -368,7 +377,7 @@ export const editHighlights = [
["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"]
["80"], ["81"], ["82"]
]
```tsx highlights={editHighlights} collapsibleLines="90-161" expandButtonLabel="Show form"
@@ -440,6 +449,7 @@ export const editHighlights = [
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
first_name: firstName,
@@ -557,6 +567,9 @@ fetch(
}`,
{
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
method: "DELETE",
}
)
@@ -18,7 +18,7 @@ export const highlights = [
["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."]
["61", "useCustomer", "The hook that child components of the provider use to access the customer."]
]
```tsx highlights={highlights}
@@ -59,6 +59,9 @@ export const CustomerProvider = ({
fetch(`http://localhost:9000/store/customers/me`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ customer }) => {
@@ -45,12 +45,11 @@ For example:
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"],
["9"], ["10"], ["11"], ["12"], ["13"], ["14"], ["15"], ["16"], ["17"], ["18"]
]
```tsx highlights={highlights}
"use client" // include with Next.js 13+
"use client" // include with Next.js 13+
import { useCustomer } from "../../../providers/customer"
@@ -51,6 +51,7 @@ export const fetchHighlights = [
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`,
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
}
)
@@ -115,6 +116,7 @@ export const highlights = [
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`,
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
}
)
@@ -221,6 +223,7 @@ export const fetchSessionHighlights = [
credentials: "include",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
}
)
@@ -300,6 +303,7 @@ export const sessionHighlights = [
credentials: "include",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
}
)
@@ -19,6 +19,7 @@ For example:
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
first_name,
@@ -40,7 +41,7 @@ For example:
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"]
["43"], ["44"], ["45"], ["46"], ["47"], ["48"], ["49"], ["50"]
]
```tsx highlights={highlights} collapsibleLines="53-91" expandButtonLabel="Show form"
@@ -81,6 +82,7 @@ export const highlights = [
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
first_name: firstName,
@@ -21,7 +21,7 @@ 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."]
["40", "TODO", "Redirect the customer to the log in page."]
]
```ts highlights={fetchHighlights}
@@ -52,6 +52,7 @@ export const fetchHighlights = [
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`,
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
first_name: firstName,
@@ -74,7 +75,7 @@ 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."]
["60", "TODO", "Redirect the customer to the log in page."]
]
```tsx highlights={highlights} collapsibleLines="61-100" expandButtonLabel="Show form"
@@ -124,6 +125,7 @@ export const highlights = [
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`,
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
first_name: firstName,
@@ -23,6 +23,7 @@ export const bearerHighlights = [
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`,
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
}
)
@@ -47,6 +48,7 @@ export const sessionHighlights = [
credentials: "include",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
}
)
@@ -85,6 +85,7 @@ const loginWithGoogle = async () => {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${result.token}`,
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
}
)
@@ -138,6 +139,7 @@ export default function Login() {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${result.token}`,
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
}
)
@@ -292,6 +294,7 @@ const createCustomer = async (token: string) => {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`,
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
// TODO show form to retrieve email from customer
@@ -364,6 +367,7 @@ const validateCallback = async () => {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`,
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
// TODO show form to retrieve email from customer
@@ -406,6 +410,7 @@ const validateCallback = async () => {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`,
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
// TODO show form to retrieve email from customer
@@ -481,6 +486,7 @@ const createCustomer = async (token: string) => {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`,
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
// TODO show form to retrieve email from customer
@@ -521,6 +527,7 @@ const validateCallback = async () => {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`,
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
// TODO show form to retrieve email from customer
@@ -575,6 +582,7 @@ export default function GoogleCallback() {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`,
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
// TODO show form to retrieve email from customer
@@ -615,6 +623,7 @@ export default function GoogleCallback() {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`,
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
body: JSON.stringify({
// TODO show form to retrieve email from customer
@@ -18,6 +18,9 @@ To retrieve the list of product categories, send a request to the [List Product
```ts
fetch(`http://localhost:9000/store/product-categories`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ product_categories }) => {
@@ -31,7 +34,8 @@ To retrieve the list of product categories, send a request to the [List Product
export const highlights = [
["17"], ["18"], ["19"], ["20"],
["21"], ["22"], ["23"], ["24"]
["21"], ["22"], ["23"], ["24"],
["25"], ["26"], ["27"]
]
```tsx highlights={highlights}
@@ -53,6 +57,9 @@ export const highlights = [
fetch(`http://localhost:9000/store/product-categories`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ product_categories }) => {
@@ -100,9 +107,9 @@ For example:
export const paginateHighlights = [
["20", "offset", "Calculate the number of product categories to skip based on the current page and limit."],
["28", "searchParams.toString()", "Pass the pagination parameters in the query."],
["33", "count", "The total number of product categories in the Medusa application."],
["45", "setHasMorePages", "Set whether there are more pages based on the total count."],
["64", "button", "Show a button to load more product categories if there are more pages."]
["36", "count", "The total number of product categories in the Medusa application."],
["48", "setHasMorePages", "Set whether there are more pages based on the total count."],
["67", "button", "Show a button to load more product categories if there are more pages."]
]
```tsx highlights={paginateHighlights}
@@ -136,6 +143,9 @@ export default function Categories() {
searchParams.toString()
}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ product_categories, count }) => {
@@ -203,6 +213,9 @@ fetch(`http://localhost:9000/store/product-categories?${
searchParams.toString()
}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ product_categories, count }) => {
@@ -28,6 +28,9 @@ export const fetchHighlights = [
searchParams.toString()
}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ product_category }) => {
@@ -43,8 +46,8 @@ export const highlights = [
["12", "{ params: { id } }: Params", "This is based on Next.js which passes the path parameters as a prop."],
["24", `"*category_children"`, "Select the `category_children` relation."],
["27"], ["28"], ["29"],
["30"], ["31"], ["32"], ["33"], ["34"], ["35"], ["36"],
["50", "", "Show the nested categories."],
["30"], ["31"], ["32"], ["33"], ["34"], ["35"], ["36"], ["37"], ["38"], ["39"],
["53", "", "Show the nested categories."],
]
```tsx highlights={highlights}
@@ -78,6 +81,9 @@ export const highlights = [
searchParams.toString()
}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ product_category }) => {
@@ -13,7 +13,7 @@ To retrieve a category's products in the storefront, send a request to the [List
export const fetchHighlights = [
["3", "", "Pass the category ID as a query parameter."],
["9", "process.env.NEXT_PUBLIC_PAK", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
["9", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
]
```ts highlights={fetchHighlights}
@@ -25,7 +25,7 @@ export const fetchHighlights = [
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_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -42,7 +42,7 @@ export const highlights = [
["13", "params: { categoryId }", "This is based on Next.js which passes the path parameters as a prop."],
["33", "", "Pass the category ID as a query parameter."],
["36"], ["37"], ["38"],
["39", "process.env.NEXT_PUBLIC_PAK", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
["39", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
["40"], ["41"], ["42"], ["43"], ["44"], ["45"], ["46"], ["47"], ["48"], ["49"], ["50"], ["51"], ["52"], ["53"], ["54"],
["55"], ["56"]
]
@@ -86,7 +86,7 @@ export const highlights = [
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_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -27,6 +27,9 @@ export const fetchHighlights = [
```ts highlights={fetchHighlights}
fetch(`http://localhost:9000/store/product-categories/${id}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ product_category }) => {
@@ -41,7 +44,7 @@ export const fetchHighlights = [
export const highlights = [
["12", "{ params: { id } }: Params", "This is based on Next.js which passes the path parameters as a prop."],
["23"], ["24"], ["25"], ["26"],
["27"], ["28"], ["29"], ["30"]
["27"], ["28"], ["29"], ["30"], ["31"], ["32"], ["33"]
]
```tsx highlights={highlights}
@@ -69,6 +72,9 @@ export const highlights = [
fetch(`http://localhost:9000/store/product-categories/${id}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ product_category }) => {
@@ -114,6 +120,9 @@ export const handleFetchHighlights = [
handle
}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ product_categories }) => {
@@ -133,7 +142,7 @@ export const handleHighlights = [
["12", "{ params: { handle } }: Params", "This is based on Next.js which passes the path parameters as a prop."],
["23"], ["24"], ["25"], ["26"],
["27"], ["28"], ["29"], ["30"],
["31"], ["32"], ["33"], ["34"]
["31"], ["32"], ["33"], ["34"], ["35"], ["36"], ["37"]
]
```tsx highlights={handleHighlights}
@@ -163,6 +172,9 @@ export const handleHighlights = [
handle
}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ product_categories }) => {
@@ -18,6 +18,9 @@ To retrieve the list of product collections, send a request to the [List Product
```ts
fetch(`http://localhost:9000/store/collections`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ collections }) => {
@@ -31,7 +34,8 @@ To retrieve the list of product collections, send a request to the [List Product
export const highlights = [
["17"], ["18"], ["19"], ["20"],
["21"], ["22"], ["23"], ["24"]
["21"], ["22"], ["23"], ["24"],
["25"], ["26"], ["27"]
]
```tsx highlights={highlights}
@@ -53,6 +57,9 @@ export const highlights = [
fetch(`http://localhost:9000/store/collections`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ collections: dataCollections }) => {
@@ -102,9 +109,9 @@ For example:
export const paginateHighlights = [
["20", "offset", "Calculate the number of product collections to skip based on the current page and limit."],
["28", "searchParams.toString()", "Pass the pagination parameters in the query."],
["33", "count", "The total number of product collections in the Medusa application."],
["45", "setHasMorePages", "Set whether there are more pages based on the total count."],
["64", "button", "Show a button to load more product collections if there are more pages."]
["36", "count", "The total number of product collections in the Medusa application."],
["48", "setHasMorePages", "Set whether there are more pages based on the total count."],
["67", "button", "Show a button to load more product collections if there are more pages."]
]
```tsx highlights={paginateHighlights}
@@ -138,6 +145,9 @@ export default function Collections() {
searchParams.toString()
}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ collections: dataCollections, count }) => {
@@ -205,6 +215,9 @@ fetch(`http://localhost:9000/store/collections?${
searchParams.toString()
}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ collections, count }) => {
@@ -13,7 +13,7 @@ To retrieve a collection's products in the storefront, send a request to the [Li
export const fetchHighlights = [
["3", "", "Pass the collection ID as a query parameter."],
["9", "process.env.NEXT_PUBLIC_PAK", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
["9", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
]
```ts highlights={fetchHighlights}
@@ -25,7 +25,7 @@ export const fetchHighlights = [
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_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -42,7 +42,7 @@ export const highlights = [
["13", "params: { collectionId }", "This is based on Next.js which passes the path parameters as a prop."],
["33", "", "Pass the collection ID as a query parameter."],
["36"], ["37"], ["38"],
["39", "process.env.NEXT_PUBLIC_PAK", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
["39", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
["40"], ["41"], ["42"], ["43"], ["44"], ["45"], ["46"], ["47"], ["48"], ["49"], ["50"], ["51"], ["52"], ["53"], ["54"],
["55"], ["56"], ["57"], ["58"]
]
@@ -88,7 +88,7 @@ export const highlights = [
}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_PAK || "temp",
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -27,6 +27,9 @@ export const fetchHighlights = [
```ts highlights={fetchHighlights}
fetch(`http://localhost:9000/store/collections/${id}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ collection }) => {
@@ -41,7 +44,8 @@ fetch(`http://localhost:9000/store/collections/${id}`, {
export const highlights = [
["12", "{ params: { id } }: Params", "This is based on Next.js which passes the path parameters as a prop."],
["23"], ["24"], ["25"], ["26"],
["27"], ["28"], ["29"], ["30"]
["27"], ["28"], ["29"], ["30"],
["31"], ["32"], ["33"]
]
```tsx highlights={highlights}
@@ -69,6 +73,9 @@ export const highlights = [
fetch(`http://localhost:9000/store/collections/${id}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ collection: dataCollection }) => {
@@ -115,6 +122,9 @@ export const handleFetchHighlights = [
handle
}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ collections }) => {
@@ -133,7 +143,8 @@ export const handleFetchHighlights = [
export const handleHighlights = [
["13", "{ params: { handle } }: Params", "This is based on Next.js which passes the path parameters as a prop."],
["25"], ["26"], ["27"], ["28"],
["29"], ["30"], ["31"], ["32"], ["33"], ["34"], ["35"], ["36"]
["29"], ["30"], ["31"], ["32"], ["33"], ["34"], ["35"], ["36"],
["37"], ["38"], ["39"]
]
```tsx highlights={handleHighlights}
@@ -165,6 +176,9 @@ export const handleHighlights = [
handle
}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ collections }) => {
@@ -15,7 +15,7 @@ For example:
export const fetchHighlights = [
["2", "fields", "Pass `+variants.inventory_quantity` in the fields to retrieve."],
["8", "process.env.NEXT_PUBLIC_PAK", "Pass the Publishable API key to retrieve the inventory quantity based on the associated sales channels' stock locations."],
["8", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve the inventory quantity based on the associated sales channels' stock locations."],
["14", "isInStock", "Consider the variant in stock either if its `manage_inventory` property is disabled, or the `inventory_quantity` is greater than `0`."]
]
@@ -27,7 +27,7 @@ const queryParams = new URLSearchParams({
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_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -61,7 +61,7 @@ A variant is in stock if:
export const reactHighlights = [
["12", "{ params: { id } }: Params", "This is based on Next.js which passes the path parameters as a prop."],
["25", "fields", "Pass `+variants.inventory_quantity` in the fields to retrieve."],
["31", "process.env.NEXT_PUBLIC_PAK", "Pass the Publishable API key to retrieve the inventory quantity based on the associated sales channels' stock locations."],
["31", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve the inventory quantity based on the associated sales channels' stock locations."],
["55", "isInStock", "Consider the selected variant in stock either if its `manage_inventory` property is disabled, or the `inventory_quantity` is greater than `0`."],
["96", "isInStock", "Show whether the selected variant is in stock."]
]
@@ -97,7 +97,7 @@ export default function Product({ params: { id } }: Params) {
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_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -16,14 +16,14 @@ To list products, send a request to the [List Products API route](!api!/store#pr
<CodeTab label="Fetch API" value="fetch">
export const fetchHighlights = [
["4", "process.env.NEXT_PUBLIC_PAK", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
["4", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
]
```ts highlights={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_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -38,7 +38,7 @@ export const fetchHighlights = [
export const highlights = [
["17"], ["18"], ["19"],
["20", "process.env.NEXT_PUBLIC_PAK", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
["20", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
["21"], ["22"], ["23"], ["24"], ["25"], ["26"], ["27"]
]
@@ -62,7 +62,7 @@ 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_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -146,7 +146,7 @@ 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_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -212,7 +212,7 @@ const searchParams = new URLSearchParams({
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_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -99,7 +99,7 @@ export default function Product({ params: { id } }: Params) {
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_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -100,7 +100,7 @@ export default function Product({ params: { id } }: Params) {
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_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -31,7 +31,7 @@ const queryParams = new URLSearchParams({
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_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -141,7 +141,7 @@ export default function Product({ params: { id } }: Params) {
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_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -30,7 +30,7 @@ const queryParams = new URLSearchParams({
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_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -22,14 +22,14 @@ To retrieve a product by its ID, send a request to the [Retrieve Product API rou
export const fetchHighlights = [
["1", "id", "The product's ID."],
["4", "process.env.NEXT_PUBLIC_PAK", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
["4", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
]
```ts highlights={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_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -45,7 +45,7 @@ export const fetchHighlights = [
export const highlights = [
["12", "{ params: { id } }: Params", "This is based on Next.js which passes the path parameters as a prop."]
["23"], ["24"], ["25"],
["26", "process.env.NEXT_PUBLIC_PAK", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
["26", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
["27"], ["28"], ["29"], ["30"], ["31"], ["32"], ["33"]
]
@@ -75,7 +75,7 @@ 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_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -133,14 +133,14 @@ To retrieve a product by its handle, send a request to the [List Products API ro
export const handleFetchHighlights = [
["1", "id", "The product's ID."],
["4", "process.env.NEXT_PUBLIC_PAK", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
["4", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
]
```ts highlights={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_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -160,7 +160,7 @@ export const handleFetchHighlights = [
export const handleHighlights = [
["12", "{ params: { handle } }: Params", "This is based on Next.js which passes the path parameters as a prop."]
["23"], ["24"], ["25"],
["26", "process.env.NEXT_PUBLIC_PAK", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
["26", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
["27"], ["28"], ["29"], ["30"], ["31"], ["32"], ["33"], ["34"], ["35"]
]
@@ -190,7 +190,7 @@ 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_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -55,7 +55,7 @@ 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_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
@@ -0,0 +1,80 @@
export const metadata = {
title: `Use a Publishable API Key in the Storefront`,
}
# {metadata.title}
When sending requests to the `/store` API routes, you must pass the publishable API key in the header of your request.
## What is a Publishable API Key?
Publishable API keys specify the scope of a request. Admin users create them, and they can only be used on the client-side, such as in a storefront.
Publishable API keys are associated with sales channels. Then, when the publishable API key is passed in the header of a request, the Medusa application automatically infers what sales channel is being used.
---
## How to Create a Publishable API Key?
{/* TODO replace link with admin how-to guide once available. */}
You create a publishable API key either using the Medusa Admin or the [Admin API routes](!api!/admin#api-keys_postapikeys).
For example, using the [Create API Key API Route](!api!/admin#api-keys_postapikeys):
```bash
curl -X POST 'http://localhost:9000/admin/api-keys' \
-H 'Authorization: Bearer {token}' \
-H 'Content-Type: application/json' \
--data-raw '{
"title": "Storefront Key",
"type": "publishable"
}'
```
<Note title="Tip">
Learn how to send authenticated admin requests in the [Admin API reference](!api!/admin#authentication)
</Note>
To add sales channels to the publishable API key's scope, use the [Manage Sales Channels API route](!api!/admin#api-keys_postapikeysidsaleschannels):
```bash
curl -X POST 'http://localhost:9000/admin/api-keys/apk_123/sales-channels' \
-H 'Authorization: Bearer {token}' \
-H 'Content-Type: application/json' \
--data-raw '{
"add": ["sc_123"]
}'
```
Make sure to replace `apk_123` with the ID of the publishable API key, and `sc_123` with the ID of the sales channel.
---
## How to Use Publishable API Key in Storefront Requests
In your storefront, pass the `x-publishable-api-key` in the header of all your requests to the Medusa application.
For example:
export const highlights = [
["4", "NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "An environment variable that holds the publishable API key's token."]
]
```ts
fetch(`http://localhost:9000/store/products`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then((data) => {
// use products...
console.log(data.products)
})
```
Where `NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY` is an environment variable that holds your publishable API key's token.
@@ -21,8 +21,8 @@ export const highlights = [
["32", "", "If a region is set, set its ID in the local storage again in case it changed."],
["39", "regionId", "Retrieve the selected region from the `localStorage`."],
["42", "fetch", "If no region is selected, retrieve the list of regions from the Medusa application and select the first one."],
["51", "fetch", "If a region is selected, retrieve it from the Medusa application."],
["71", "useRegion", "The hook that child components of the provider use to access the region."]
["54", "fetch", "If a region is selected, retrieve it from the Medusa application."],
["77", "useRegion", "The hook that child components of the provider use to access the region."]
]
```tsx highlights={highlights}
@@ -69,6 +69,9 @@ export const RegionProvider = (
// retrieve regions and select the first one
fetch(`http://localhost:9000/store/regions`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ regions }) => {
@@ -78,6 +81,9 @@ export const RegionProvider = (
// retrieve selected region
fetch(`http://localhost:9000/store/regions/${regionId}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ region: dataRegion }) => {
@@ -14,6 +14,9 @@ To list regions in your storefront, send a request to the [List Regions API rout
```ts
fetch(`http://localhost:9000/store/regions`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ regions }) => {
@@ -26,7 +29,8 @@ To list regions in your storefront, send a request to the [List Regions API rout
<CodeTab label="React" value="react">
export const highlights = [
["17"], ["18"], ["19"], ["20"], ["21"], ["22"], ["23"], ["24"]
["17"], ["18"], ["19"], ["20"], ["21"], ["22"], ["23"], ["24"],
["25"], ["26"], ["27"]
]
```tsx highlights={highlights}
@@ -48,6 +52,9 @@ export const highlights = [
fetch(`http://localhost:9000/store/regions`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ regions: dataRegions }) => {
@@ -33,6 +33,9 @@ const regionId = localStorage.getItem("region_id")
fetch(`http://localhost:9000/store/regions/${regionId}`, {
credentials: "include",
headers: {
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
},
})
.then((res) => res.json())
.then(({ region }) => {
@@ -51,21 +51,3 @@ module.exports = defineConfig({
// ...
})
```
---
## Use Publishable API Keys
Publishable API keys specify the scope of a request. Admin users create them, and they can only be used on the client-side, such as in a storefront.
Publishable API keys are associated with sales channels. Then, when the publishable API key is passed in the header of a request, the Medusa application automatically infers what sales channel is being used.
<Note>
Products, carts, and orders are associated with a sales channel. If you don’t specify a sales channel or a publishable API key, the products, carts, and orders are associated with the default sales channel.
</Note>
{/* TODO replace link with admin how-to guide once available. */}
Create a publishable API key either using the Medusa Admin or the [Admin API routes](!api!/admin#api-keys_postapikeys).
+43 -42
View File
@@ -141,7 +141,7 @@ export const generatedEditDates = {
"app/nextjs-starter/page.mdx": "2024-07-01T10:21:19+03:00",
"app/recipes/b2b/page.mdx": "2024-08-29T09:23:12.736Z",
"app/recipes/commerce-automation/page.mdx": "2024-08-05T07:24:27+00:00",
"app/recipes/digital-products/examples/standard/page.mdx": "2024-08-16T09:28:31+03:00",
"app/recipes/digital-products/examples/standard/page.mdx": "2024-09-11T10:50:14.310Z",
"app/recipes/digital-products/page.mdx": "2024-08-02T13:02:06+00:00",
"app/recipes/ecommerce/page.mdx": "2024-06-09T15:18:43+02:00",
"app/recipes/integrate-ecommerce-stack/page.mdx": "2024-08-05T07:24:27+00:00",
@@ -150,9 +150,9 @@ export const generatedEditDates = {
"app/recipes/multi-region-store/page.mdx": "2024-07-01T10:21:19+03:00",
"app/recipes/omnichannel/page.mdx": "2024-06-09T15:18:43+02:00",
"app/recipes/oms/page.mdx": "2024-07-01T10:21:19+03:00",
"app/recipes/personalized-products/page.mdx": "2024-07-01T10:21:19+03:00",
"app/recipes/personalized-products/page.mdx": "2024-09-11T10:53:03.936Z",
"app/recipes/pos/page.mdx": "2024-07-04T17:26:03+03:00",
"app/recipes/subscriptions/examples/standard/page.mdx": "2024-08-02T12:40:26+03:00",
"app/recipes/subscriptions/examples/standard/page.mdx": "2024-09-11T10:16:35.673Z",
"app/recipes/subscriptions/page.mdx": "2024-08-02T12:40:26+03:00",
"app/recipes/page.mdx": "2024-07-11T15:56:41+00:00",
"app/service-factory-reference/methods/create/page.mdx": "2024-07-31T17:01:33+03:00",
@@ -165,49 +165,49 @@ export const generatedEditDates = {
"app/service-factory-reference/methods/update/page.mdx": "2024-07-31T17:01:33+03:00",
"app/service-factory-reference/tips/filtering/page.mdx": "2024-07-31T17:01:33+03:00",
"app/service-factory-reference/page.mdx": "2024-07-26T14:40:56+00:00",
"app/storefront-development/cart/context/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/cart/create/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/cart/manage-items/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/cart/retrieve/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/cart/update/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/cart/context/page.mdx": "2024-09-11T10:08:05.194Z",
"app/storefront-development/cart/create/page.mdx": "2024-09-11T10:08:05.195Z",
"app/storefront-development/cart/manage-items/page.mdx": "2024-09-11T10:10:54.932Z",
"app/storefront-development/cart/retrieve/page.mdx": "2024-09-11T10:12:55.828Z",
"app/storefront-development/cart/update/page.mdx": "2024-09-11T10:12:47.704Z",
"app/storefront-development/cart/page.mdx": "2024-06-11T11:56:37+03:00",
"app/storefront-development/checkout/address/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/checkout/complete-cart/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/checkout/email/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/checkout/payment/stripe/page.mdx": "2024-07-01T10:21:19+03:00",
"app/storefront-development/checkout/payment/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/checkout/shipping/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/checkout/address/page.mdx": "2024-09-11T09:40:02.899Z",
"app/storefront-development/checkout/complete-cart/page.mdx": "2024-09-11T09:40:48.531Z",
"app/storefront-development/checkout/email/page.mdx": "2024-09-11T09:41:22.358Z",
"app/storefront-development/checkout/payment/stripe/page.mdx": "2024-09-11T09:41:52.777Z",
"app/storefront-development/checkout/payment/page.mdx": "2024-09-11T09:46:55.373Z",
"app/storefront-development/checkout/shipping/page.mdx": "2024-09-11T09:47:54.828Z",
"app/storefront-development/checkout/page.mdx": "2024-06-12T19:46:06+02:00",
"app/storefront-development/customers/addresses/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/customers/context/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/customers/log-out/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/customers/login/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/customers/profile/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/customers/register/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/customers/retrieve/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/customers/addresses/page.mdx": "2024-09-11T09:50:20.736Z",
"app/storefront-development/customers/context/page.mdx": "2024-09-11T09:50:36.936Z",
"app/storefront-development/customers/log-out/page.mdx": "2024-09-11T10:00:38.904Z",
"app/storefront-development/customers/login/page.mdx": "2024-09-11T10:00:28.555Z",
"app/storefront-development/customers/profile/page.mdx": "2024-09-11T09:54:38.574Z",
"app/storefront-development/customers/register/page.mdx": "2024-09-11T09:59:29.085Z",
"app/storefront-development/customers/retrieve/page.mdx": "2024-09-11T09:55:40.516Z",
"app/storefront-development/customers/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/products/categories/list/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/products/categories/nested-categories/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/products/categories/products/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/products/categories/retrieve/page.mdx": "2024-06-11T19:55:56+02:00",
"app/storefront-development/products/categories/list/page.mdx": "2024-09-11T10:01:50.873Z",
"app/storefront-development/products/categories/nested-categories/page.mdx": "2024-09-11T10:02:28.405Z",
"app/storefront-development/products/categories/products/page.mdx": "2024-09-11T10:08:05.194Z",
"app/storefront-development/products/categories/retrieve/page.mdx": "2024-09-11T10:04:38.752Z",
"app/storefront-development/products/categories/page.mdx": "2024-06-11T19:55:56+02:00",
"app/storefront-development/products/collections/list/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/products/collections/products/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/products/collections/retrieve/page.mdx": "2024-06-11T19:55:56+02:00",
"app/storefront-development/products/collections/list/page.mdx": "2024-09-11T10:05:31.249Z",
"app/storefront-development/products/collections/products/page.mdx": "2024-09-11T10:08:05.205Z",
"app/storefront-development/products/collections/retrieve/page.mdx": "2024-09-11T10:06:12.064Z",
"app/storefront-development/products/collections/page.mdx": "2024-06-11T19:55:56+02:00",
"app/storefront-development/products/list/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/products/price/examples/sale-price/page.mdx": "2024-07-30T12:52:21+03:00",
"app/storefront-development/products/price/examples/show-price/page.mdx": "2024-07-30T12:52:21+03:00",
"app/storefront-development/products/price/examples/tax-price/page.mdx": "2024-07-31T17:01:33+03:00",
"app/storefront-development/products/price/page.mdx": "2024-09-05T14:58:05.735Z",
"app/storefront-development/products/retrieve/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/products/variants/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/products/list/page.mdx": "2024-09-11T10:08:05.195Z",
"app/storefront-development/products/price/examples/sale-price/page.mdx": "2024-09-11T10:08:05.204Z",
"app/storefront-development/products/price/examples/show-price/page.mdx": "2024-09-11T10:08:05.202Z",
"app/storefront-development/products/price/examples/tax-price/page.mdx": "2024-09-11T10:08:05.204Z",
"app/storefront-development/products/price/page.mdx": "2024-09-11T10:08:05.202Z",
"app/storefront-development/products/retrieve/page.mdx": "2024-09-11T10:08:05.195Z",
"app/storefront-development/products/variants/page.mdx": "2024-09-11T10:08:05.207Z",
"app/storefront-development/products/page.mdx": "2024-06-11T19:55:56+02:00",
"app/storefront-development/regions/context/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/regions/list/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/regions/store-retrieve-region/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/regions/context/page.mdx": "2024-09-11T10:07:10.566Z",
"app/storefront-development/regions/list/page.mdx": "2024-09-11T10:07:34.742Z",
"app/storefront-development/regions/store-retrieve-region/page.mdx": "2024-09-11T10:07:42.887Z",
"app/storefront-development/regions/page.mdx": "2024-06-09T15:19:09+02:00",
"app/storefront-development/tips/page.mdx": "2024-06-13T12:21:54+03:00",
"app/storefront-development/tips/page.mdx": "2024-09-11T09:25:17.014Z",
"app/storefront-development/page.mdx": "2024-06-09T15:19:09+02:00",
"app/troubleshooting/cors-errors/page.mdx": "2024-05-03T17:36:38+03:00",
"app/troubleshooting/create-medusa-app-errors/page.mdx": "2024-07-11T10:29:13+03:00",
@@ -915,7 +915,7 @@ export const generatedEditDates = {
"references/types/interfaces/types.BaseClaim/page.mdx": "2024-09-04T00:11:02.485Z",
"app/commerce-modules/auth/auth-providers/github/page.mdx": "2024-09-05T12:13:04.991Z",
"app/commerce-modules/auth/auth-providers/google/page.mdx": "2024-09-05T12:12:59.196Z",
"app/storefront-development/customers/third-party-login/page.mdx": "2024-09-05T11:35:24.269Z",
"app/storefront-development/customers/third-party-login/page.mdx": "2024-09-11T09:58:51.801Z",
"references/types/HttpTypes/types/types.HttpTypes.AdminWorkflowRunResponse/page.mdx": "2024-09-05T00:11:17.666Z",
"references/types/HttpTypes/types/types.HttpTypes.BatchResponse/page.mdx": "2024-09-05T00:11:17.182Z",
"references/types/WorkflowsSdkTypes/types/types.WorkflowsSdkTypes.Acknowledgement/page.mdx": "2024-09-05T00:11:18.150Z",
@@ -961,7 +961,7 @@ export const generatedEditDates = {
"references/promotion/interfaces/promotion.IPromotionModuleService/page.mdx": "2024-09-06T00:11:38.306Z",
"references/types/EventBusTypes/interfaces/types.EventBusTypes.IEventBusService/page.mdx": "2024-09-06T00:11:07.298Z",
"references/types/TransactionBaseTypes/interfaces/types.TransactionBaseTypes.ITransactionBaseService/page.mdx": "2024-09-06T00:11:08.494Z",
"app/storefront-development/products/inventory/page.mdx": "2024-09-06T10:24:49.161Z",
"app/storefront-development/products/inventory/page.mdx": "2024-09-11T10:08:05.202Z",
"references/auth/IAuthModuleService/methods/auth.IAuthModuleService.updateAuthIdentities/page.mdx": "2024-09-06T11:11:37.710Z",
"references/auth/IAuthModuleService/methods/auth.IAuthModuleService.updateProvider/page.mdx": "2024-09-06T11:11:37.686Z",
"references/auth/IAuthModuleService/methods/auth.IAuthModuleService.updateProviderIdentities/page.mdx": "2024-09-06T11:11:37.726Z",
@@ -1023,5 +1023,6 @@ export const generatedEditDates = {
"references/order/IOrderModuleService/methods/order.IOrderModuleService.retrieveOrderChangeAction/page.mdx": "2024-09-06T11:12:03.598Z",
"references/order/IOrderModuleService/methods/order.IOrderModuleService.updateOrderChangeActions/page.mdx": "2024-09-06T11:12:03.606Z",
"references/types/ModulesSdkTypes/types/types.ModulesSdkTypes.RemoteQueryFunction/page.mdx": "2024-09-06T11:11:37.222Z",
"references/types/types.CommonTypes/page.mdx": "2024-09-06T11:11:35.986Z"
"references/types/types.CommonTypes/page.mdx": "2024-09-06T11:11:35.986Z",
"app/storefront-development/publishable-api-keys/page.mdx": "2024-09-11T09:35:46.683Z"
}
@@ -859,6 +859,10 @@ export const filesMap = [
"filePath": "/www/apps/resources/app/storefront-development/products/variants/page.mdx",
"pathname": "/storefront-development/products/variants"
},
{
"filePath": "/www/apps/resources/app/storefront-development/publishable-api-keys/page.mdx",
"pathname": "/storefront-development/publishable-api-keys"
},
{
"filePath": "/www/apps/resources/app/storefront-development/regions/context/page.mdx",
"pathname": "/storefront-development/regions/context"
+8
View File
@@ -8081,6 +8081,14 @@ export const generatedSidebar = [
"title": "Tips",
"children": []
},
{
"loaded": true,
"isPathHref": true,
"type": "link",
"path": "/storefront-development/publishable-api-keys",
"title": "Publishable API Key",
"children": []
},
{
"type": "separator"
},
+5
View File
@@ -1799,6 +1799,11 @@ export const sidebar = sidebarAttachHrefCommonOptions([
path: "/storefront-development/tips",
title: "Tips",
},
{
type: "link",
path: "/storefront-development/publishable-api-keys",
title: "Publishable API Key",
},
{
type: "separator",
},