docs: revise commerce modules overview pages (#10738)

* revise API Key Module overview

* revise auth module

* support ref sidebar items

* remove examples

* revise cart module

* revise currency

* revise customer module

* revise fulfillment module

* revise inventory module

* revise order module

* revise payment

* revise pricing module

* revise product module

* revise promotion module

* revise region module

* revise sales channel module

* revise stock location module

* revise store module

* revise tax module

* revise user module

* lint content + fix snippets
This commit is contained in:
Shahed Nasser
2024-12-26 10:32:16 +02:00
committed by GitHub
parent c8f9938865
commit ebca8fed28
112 changed files with 9465 additions and 7731 deletions
@@ -1,306 +0,0 @@
import { CodeTabs, CodeTab } from "docs-ui"
export const metadata = {
title: `Examples of the API Key Module`,
}
# {metadata.title}
In this guide, youll find common examples of how you can use the API Key Module in your application.
<Note>
You should only use the API Key Module's main service when implementing complex customizations. For common cases, check out [available workflows instead](../../../medusa-workflows-reference/page.mdx).
</Note>
## Create an API Key
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
import { Modules } from "@medusajs/framework/utils"
export async function POST(request: MedusaRequest, res: MedusaResponse) {
const apiKeyModuleService = request.scope.resolve(
Modules.API_KEY
)
const apiKey = await apiKeyModuleService.createApiKeys({
title: "Publishable API key",
type: "publishable",
created_by: "user_123",
})
res.json({
api_key: apiKey,
})
}
```
</CodeTab>
<CodeTab label="Next.js App Router" value="nextjs">
```ts
import { NextResponse } from "next/server"
import { initialize as initializeApiKeyModule } from "@medusajs/medusa/api-key"
export async function POST(request: Request) {
const apiKeyModuleService = await initializeApiKeyModule()
const apiKey = await apiKeyModuleService.createApiKeys({
title: "Publishable API key",
type: "publishable",
created_by: "user_123",
})
return NextResponse.json({
api_key: apiKey,
})
}
```
</CodeTab>
</CodeTabs>
---
## List API Keys
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
import { Modules } from "@medusajs/framework/utils"
export async function GET(request: MedusaRequest, res: MedusaResponse) {
const apiKeyModuleService = request.scope.resolve(
Modules.API_KEY
)
res.json({
api_keys: await apiKeyModuleService.listApiKeys(),
})
}
```
</CodeTab>
<CodeTab label="Next.js App Router" value="nextjs">
```ts
import { NextResponse } from "next/server"
import { initialize as initializeApiKeyModule } from "@medusajs/medusa/api-key"
export async function GET(request: Request) {
const apiKeyModuleService = await initializeApiKeyModule()
return NextResponse.json({
api_keys: await apiKeyModuleService.listApiKeys(),
})
}
```
</CodeTab>
</CodeTabs>
---
## Revoke an API Key
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
```ts collapsibleLines="1-9" expandButtonLabel="Show Imports"
import { AuthenticatedMedusaRequest, MedusaResponse } from "@medusajs/framework/http"
import { Modules } from "@medusajs/framework/utils"
export async function POST(
request: AuthenticatedMedusaRequest,
res: MedusaResponse
) {
const apiKeyModuleService = request.scope.resolve(
Modules.API_KEY
)
const revokedKey = await apiKeyModuleService.revoke(request.params.id, {
revoked_by: request.auth_context.actor_id,
})
res.json({
api_key: revokedKey,
})
}
```
</CodeTab>
<CodeTab label="Next.js App Router" value="nextjs">
```ts
import { NextResponse } from "next/server"
import { initialize as initializeApiKeyModule } from "@medusajs/medusa/api-key"
type ContextType = {
params: {
id: string
user_id: string
}
}
export async function POST(request: Request, { params }: ContextType) {
const apiKeyModuleService = await initializeApiKeyModule()
const revokedKey = await apiKeyModuleService.revoke(params.id, {
revoked_by: params.user_id,
})
return NextResponse.json({
api_key: revokedKey,
})
}
```
</CodeTab>
</CodeTabs>
---
## Verify or Authenticate Token
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
```ts
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
import { Modules } from "@medusajs/framework/utils"
export async function POST(request: MedusaRequest, res: MedusaResponse) {
const apiKeyModuleService = request.scope.resolve(
Modules.API_KEY
)
const authenticatedToken = await apiKeyModuleService.authenticate(
request.params.token
)
res.json({
is_authenticated: !!authenticatedToken,
})
}
```
</CodeTab>
<CodeTab label="Next.js App Router" value="nextjs">
```ts
import { NextResponse } from "next/server"
import { initialize as initializeApiKeyModule } from "@medusajs/medusa/api-key"
type ContextType = {
params: {
token: string
}
}
export async function POST(request: Request, { params }: ContextType) {
const apiKeyModuleService = await initializeApiKeyModule()
const authenticatedToken = await apiKeyModuleService.authenticate(
request.params.token
)
return NextResponse.json({
is_authenticated: !!authenticatedToken,
})
}
```
</CodeTab>
</CodeTabs>
---
## Roll API Key
<CodeTabs groupId="app-type">
<CodeTab label="Medusa API Router" value="medusa">
```ts collapsibleLines="1-8" expandButtonLabel="Show Imports"
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "@medusajs/framework/http"
import { Modules } from "@medusajs/framework/utils"
export async function POST(
request: AuthenticatedMedusaRequest,
res: MedusaResponse
) {
const apiKeyModuleService = request.scope.resolve(
Modules.API_KEY
)
const revokedKey = await apiKeyModuleService.revoke(request.params.id, {
revoked_by: request.auth_context.actor_id,
})
const newKey = await apiKeyModuleService.createApiKeys({
title: revokedKey.title,
type: revokedKey.type,
created_by: revokedKey.created_by,
})
res.json({
api_key: newKey,
})
}
```
</CodeTab>
<CodeTab label="Next.js App Router" value="nextjs">
```ts
import { NextResponse } from "next/server"
import { initialize as initializeApiKeyModule } from "@medusajs/medusa/api-key"
type ContextType = {
params: {
id: string
user_id: string
}
}
export async function POST(request: Request, { params }: ContextType) {
const apiKeyModuleService = await initializeApiKeyModule()
const revokedKey = await apiKeyModuleService.revoke(params.id, {
revoked_by: params.user_id,
})
const newKey = await apiKeyModuleService.createApiKeys({
title: revokedKey.title,
type: revokedKey.type,
created_by: revokedKey.created_by,
})
return NextResponse.json({
api_key: newKey,
})
}
```
</CodeTab>
</CodeTabs>
---
## More Examples
The [API Key Module's main service reference](/references/api-key) provides a reference to all the methods available for use with examples for each.
@@ -37,8 +37,8 @@ To retrieve the sales channels of an API key with [Query](!docs!/learn/fundament
const { data: apiKeys } = await query.graph({
entity: "api_key",
fields: [
"sales_channels.*"
]
"sales_channels.*",
],
})
// apiKeys.sales_channels
@@ -55,8 +55,8 @@ import { useQueryGraphStep } from "@medusajs/medusa/core-flows"
const { data: apiKeys } = useQueryGraphStep({
entity: "api_key",
fields: [
"sales_channels.*"
]
"sales_channels.*",
],
})
// apiKeys.sales_channels
@@ -1,4 +1,4 @@
import { CodeTabs, CodeTab } from "docs-ui"
import { CodeTabs, CodeTab, ChildDocs } from "docs-ui"
export const metadata = {
title: `API Key Module`,
@@ -6,132 +6,153 @@ export const metadata = {
# {metadata.title}
The API Key Module provides API-key-related features in your Medusa and Node.js applications.
In this section of the documentation, you will find resources to learn more about the API Key Module and how to use it in your application.
## How to Use API Key Module's Service
Medusa has API-key related features available out-of-the-box through the API Key Module. A [module](!docs!/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features are placed in commerce modules, such as this API Key Module.
Use the API Key Module's main service by resolving from the Medusa container the resource `Modules.API_KEY`.
<Note>
Learn more about why modules are isolated in [this documentation](!docs!/learn/fundamentals/modules/isolation).
</Note>
## API Key Features
- [API Key Types and Management](./concepts/page.mdx): Manage API keys in your store. You can create both publishable and secret API keys for different use cases.
- [Token Verification](./concepts/page.mdx#token-verification): Verify tokens of secret API keys to authenticate users or actions.
- [Revoke Keys](./concepts/page.mdx#api-key-expiration): Revoke keys to disable their use permanently.
- Roll API Keys: Roll API keys by [revoking](/references/api-key/revoke) a key then [re-creating it](/references/api-key/createApiKeys).
---
## How to Use the API Key Module
In your Medusa application, you build flows around commerce modules. A flow is built as a [Workflow](!docs!/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and reliable roll-back mechanism.
You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package.
For example:
<CodeTabs groupId="resource-type">
<CodeTab label="Workflow Step" value="workflow-step">
export const highlights = [
["12", "Modules.API_KEY", "Resolve the module in a step."]
]
```ts title="src/workflows/hello-world/step1.ts"
import { createStep } from "@medusajs/framework/workflows-sdk"
```ts title="src/workflows/create-api-key.ts" highlights={highlights}
import {
createWorkflow,
WorkflowResponse,
createStep,
StepResponse,
} from "@medusajs/framework/workflows-sdk"
import { Modules } from "@medusajs/framework/utils"
const step1 = createStep("step-1", async (_, { container }) => {
const apiKeyModuleService = container.resolve(
Modules.API_KEY
)
const createApiKeyStep = createStep(
"create-api-key",
async ({}, { container }) => {
const apiKeyModuleService = container.resolve(Modules.API_KEY)
const apiKeys = await apiKeyModuleService.listApiKeys()
})
const apiKey = await apiKeyModuleService.createApiKeys({
title: "Publishable API key",
type: "publishable",
created_by: "user_123",
})
return new StepResponse({ apiKey }, apiKey.id)
},
async (apiKeyId, { container }) => {
const apiKeyModuleService = container.resolve(Modules.API_KEY)
await apiKeyModuleService.deleteApiKeys([apiKeyId])
}
)
export const createApiKeyWorkflow = createWorkflow(
"create-api-key",
() => {
const { apiKey } = createApiKeyStep()
return new WorkflowResponse({
apiKey,
})
}
)
```
</CodeTab>
<CodeTab label="API Route" value="api-route">
You can then execute the workflow in your custom API routes, scheduled jobs, or subscribers:
```ts title="src/api/store/custom/route.ts"
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
import { Modules } from "@medusajs/framework/utils"
<CodeTabs group="resource-types">
<CodeTab label="API Route" value="api-route">
```ts title="src/api/workflow/route.ts" highlights={[["11"], ["12"]]} collapsibleLines="1-6" expandButtonLabel="Show Imports"
import type {
MedusaRequest,
MedusaResponse,
} from "@medusajs/framework/http"
import { createApiKeyWorkflow } from "../../workflows/create-api-key"
export async function GET(
request: MedusaRequest,
req: MedusaRequest,
res: MedusaResponse
): Promise<void> {
const apiKeyModuleService = request.scope.resolve(
Modules.API_KEY
)
) {
const { result } = await createApiKeyWorkflow(req.scope)
.run()
res.json({
api_keys: await apiKeyModuleService.listApiKeys(),
})
res.send(result)
}
```
</CodeTab>
<CodeTab label="Subscriber" value="subscribers">
<CodeTab label="Subscriber" value="subscriber">
```ts title="src/subscribers/user-created.ts" highlights={[["11"], ["12"]]} collapsibleLines="1-6" expandButtonLabel="Show Imports"
import {
type SubscriberConfig,
type SubscriberArgs,
} from "@medusajs/framework"
import { createApiKeyWorkflow } from "../workflows/create-api-key"
```ts title="src/subscribers/custom-handler.ts"
import { SubscriberArgs } from "@medusajs/framework"
import { Modules } from "@medusajs/framework/utils"
export default async function handleUserCreated({
event: { data },
container,
}: SubscriberArgs<{ id: string }>) {
const { result } = await createApiKeyWorkflow(container)
.run()
export default async function subscriberHandler({ container }: SubscriberArgs) {
const apiKeyModuleService = container.resolve(
Modules.API_KEY
)
console.log(result)
}
const apiKeys = await apiKeyModuleService.listApiKeys()
export const config: SubscriberConfig = {
event: "user.created",
}
```
</CodeTab>
<CodeTab label="Scheduled Job" value="scheduled-job">
```ts title="src/jobs/run-daily.ts" highlights={[["7"], ["8"]]}
import { MedusaContainer } from "@medusajs/framework/types"
import { createApiKeyWorkflow } from "../workflows/create-api-key"
export default async function myCustomJob(
container: MedusaContainer
) {
const { result } = await createApiKeyWorkflow(container)
.run()
console.log(result)
}
export const config = {
name: "run-once-a-day",
schedule: `0 0 * * *`,
}
```
</CodeTab>
</CodeTabs>
Learn more about workflows in [this documentation](!docs!/learn/fundamentals/workflows).
---
## Features
### API Key Types and Management
Manage API keys in your store. You can create both publishable and secret API keys for different use cases, such as:
- Publishable API Key associated with resources like sales channels.
- Authentication token for admin users to access Admin API Routes.
- Password reset tokens when a user or customer requests to reset their password.
```ts
const pubApiKey = await apiKeyModuleService.createApiKeys({
title: "Publishable API key",
type: "publishable",
created_by: "user_123",
})
const secretApiKey = await apiKeyModuleService.createApiKeys({
title: "Authentication Key",
type: "secret",
created_by: "user_123",
})
```
### Token Verification
Verify tokens of secret API keys to authenticate users or actions, such as verifying a password reset token.
```ts
const authenticatedToken = await apiKeyModuleService.authenticate("sk_123")
if (!authenticatedToken) {
console.error("Couldn't verify token")
} else {
console.log("Token verified successfully!")
}
```
### Revoke Keys
Revoke keys to disable their use permenantly.
```ts
const revokedKey = await apiKeyModuleService.revoke("apk_1", {
revoked_by: "user_123",
})
```
### Roll API Keys
Roll API keys by revoking a key then re-creating it.
```ts
const revokedKey = await apiKeyModuleService.revoke("apk_1", {
revoked_by: "user_123",
})
const newKey = await apiKeyModuleService.createApiKeys({
title: revokedKey.title,
type: revokedKey.type,
created_by: revokedKey.created_by,
})
```
<CommerceModuleSections name="API Key" />