Adapters

Medusa

Medusa V2 platform adapter — maps the Medusa Store API to the unified CommerceAdapter interface.

The @commercejs/adapter-medusa package implements the CommerceAdapter interface for Medusa, the open-source headless commerce platform. It targets the Medusa V2 Store API.

Installation

pnpm add @commercejs/adapter-medusa

Configuration

import { MedusaAdapter } from '@commercejs/adapter-medusa'

const adapter = new MedusaAdapter({
  baseUrl: 'http://localhost:9000',
  publishableApiKey: process.env.MEDUSA_PUBLISHABLE_KEY!,
  defaultRegionId: 'reg_01J...', // optional, used for cart creation
})
OptionTypeRequiredDescription
baseUrlstringYesYour Medusa server URL
publishableApiKeystringYesPublishable API key from Medusa admin
defaultRegionIdstringNoDefault region for cart creation
apiTokenstringNoJWT token for authenticated endpoints
timeoutnumberNoRequest timeout in ms (default: 30000)

Supported Domains

DomainMethodsStatus
CataloggetProducts, getProduct, getCategoriesImplemented
CartcreateCart, getCart, addToCart, updateCartItem, removeFromCart, applyCouponImplemented
CheckoutgetShippingMethods, setShippingAddress, setBillingAddress, setShippingMethod, setPaymentMethod, placeOrderImplemented
Customerlogin, register, logout, getCustomer, updateCustomerImplemented
OrdergetOrder, getCustomerOrdersImplemented
StoregetStoreInfoImplemented
CountrygetCountriesImplemented

Data Mapping

The adapter transforms Medusa V2 Store API responses into unified CommerceJS types.

Product Mapping

Medusa FieldCommerceJS FieldNotes
titlenameWrapped in LocalizedString
handleslugURL-friendly identifier
variants[].calculated_pricepriceConverted from minor units (cents → dollars)
images[].urlimages[].urlMapped to Image type
options[].valuesoptionsMapped to ProductOption
variantsvariantsAlways present in Medusa products

Order Status Mapping

Medusa StatusCommerceJS Status
pendingpending
completeddelivered
archiveddelivered
canceledcancelled
requires_actionprocessing

Price Conversion

Medusa stores all prices in minor units (cents). The adapter automatically converts:

// Medusa: { calculated_amount: 2999, currency_code: 'usd' }
// CommerceJS: { amount: 29.99, currency: 'USD', formatted: '$29.99' }

Usage Examples

Fetch Products

const results = await adapter.getProducts({ query: 'shirt' })
// Returns SearchResult with products, facets, pagination

Cart + Checkout Flow

// Create cart
const cart = await adapter.createCart()

// Add item (variantId is required for Medusa)
await adapter.addToCart(cart.id, {
  productId: 'prod_01',
  variantId: 'var_01',
  quantity: 2,
})

// Set shipping address
await adapter.setShippingAddress(cart.id, {
  firstName: 'Ahmed',
  lastName: 'Ali',
  street: '123 Main St',
  city: 'Riyadh',
  country: 'SA',
  postalCode: '12345',
})

// Get shipping options and select one
const methods = await adapter.getShippingMethods(cart.id)
await adapter.setShippingMethod(cart.id, methods[0].id)

// Place order (completes the cart)
const order = await adapter.placeOrder(cart.id)

Customer Authentication

// Login
const customer = await adapter.login('user@example.com', 'password')

// Register
const newCustomer = await adapter.register({
  email: 'new@example.com',
  password: 'password',
  firstName: 'Test',
  lastName: 'User',
})

Medusa vs Salla

Key differences between the two adapters:

AspectMedusaSalla
CartFull CRUD + API checkoutHosted checkout only
AuthJWT via /auth/customer/emailpassOAuth access tokens
VariantsAlways requiredOptional
PricesMinor units (cents)Major units (10.00)
Store InfoDerived from /regionsDirect /store/info endpoint
Paginationoffset/limitpage/per_page

Error Handling

The adapter wraps Medusa API errors in CommerceError:

import { CommerceError } from '@commercejs/types'

try {
  await adapter.addToCart(cartId, { productId: 'prod_01', quantity: 1 })
} catch (err) {
  if (err instanceof CommerceError) {
    // err.code === 'VALIDATION' (missing variantId)
    // err.statusCode === 400
  }
}

Unsupported domains (wishlist, reviews, promotions, etc.) throw CommerceError with code NOT_SUPPORTED and status 501.