Packages

Types

The unified data model — TypeScript interfaces for every eCommerce domain.

The @commercejs/types package defines the shared vocabulary for all CommerceJS packages. It contains only TypeScript interfaces and type definitions — no runtime code.

Installation

pnpm add @commercejs/types

Usage

Import types directly from the package:

import type { Product, Cart, Order, Customer } from '@commercejs/types'
import type { PaymentProvider, PaymentSession } from '@commercejs/types'
import type { CommerceAdapter, CatalogAdapter } from '@commercejs/types'
import type { Profile, SavedAddress, SavedPaymentMethod } from '@commercejs/types'
import type { DeliveryProvider, DeliveryEstimate } from '@commercejs/types'
import type { StorageProvider, StorageUploadResult } from '@commercejs/types'

Domain Types

Product

interface Product {
  id: string
  name: LocalizedString
  slug: string
  description: LocalizedString
  type: ProductType
  price: DiscountablePrice
  sku?: string
  barcode?: string
  quantity?: number
  variants: ProductVariant[]
  options: ProductOption[]
  images: Image[]
  attributes: Attribute[]
  categories: Category[]
  brand?: Brand
  metadata?: Record<string, unknown>
}

Cart

interface Cart {
  id: string
  items: CartItem[]
  totals: CartTotals
  currency: string
  metadata?: Record<string, unknown>
}

interface CartItem {
  id: string
  productId: string
  variantId?: string
  name: LocalizedString
  quantity: number
  price: Price
  image?: Image
}

Order

interface Order {
  id: string
  status: OrderStatus
  fulfillmentStatus: FulfillmentStatus
  items: OrderItem[]
  currency: string
  subtotal: number
  total: number
  shippingTotal: number
  taxTotal: number
  discountTotal: number
  customer: Customer
  shippingAddress: Address
  billingAddress: Address
  paymentMethod?: PaymentMethod
  shippingMethod?: ShippingMethod
  createdAt: string
  updatedAt: string
}

Order Input

For programmatically creating orders:

interface CreateOrderInput {
  items: OrderItemInput[]
  customer: Customer
  shippingAddress: Address
  billingAddress?: Address
  shippingMethod?: ShippingMethod
  paymentMethod?: PaymentMethod
  currency: string
  metadata?: Record<string, unknown>
}

Order Status & History

interface OrderStatusInfo {
  status: OrderStatus
  label: string
  description?: string
}

interface OrderHistoryEntry {
  status: OrderStatus
  timestamp: string
  note?: string
}

interface UpdateOrderStatusInput {
  status: OrderStatus
  note?: string
}

Customer

interface Customer {
  id: string
  email: string
  firstName: string
  lastName: string
  phone?: string
  addresses: Address[]
  metadata?: Record<string, unknown>
}

interface Address {
  id: string
  street: string | null
  street2: string | null
  city: string
  state: string | null
  country: string
  postalCode: string | null
  district: string | null
  nationalAddress: string | null
  isDefault: boolean
}

Profile

Cross-merchant buyer identity for Commerce.js Cloud:

interface Profile {
  id: string
  email: string | null
  phone: string | null
  firstName: string | null
  lastName: string | null
  preferences: Record<string, any> | null
  addresses: SavedAddress[]
  paymentMethods: SavedPaymentMethod[]
  createdAt: string
  updatedAt: string
}

interface SavedAddress {
  id: string
  label: string | null
  firstName: string
  lastName: string
  phone: string | null
  street: string
  street2: string | null
  city: string
  state: string | null
  country: string
  postalCode: string | null
  district: string | null
  nationalAddress: string | null
  additionalNumber: string | null
  lastUsedAt: string | null
  createdAt: string
}

interface SavedPaymentMethod {
  id: string
  provider: string
  type: string
  last4: string
  brand: string | null
  expiryMonth: number | null
  expiryYear: number | null
  billingAddress: Record<string, any> | null
  lastUsedAt: string | null
  createdAt: string
}

interface ProfileMerchantLink {
  profileId: string
  merchantId: string
  adapterCustomerId: string | null
}

Shipping Types

ShippingMethod

type FulfillmentType = 'shipping' | 'local_delivery' | 'pickup'

interface ShippingMethod {
  id: string
  name: LocalizedString
  provider: ShippingProvider | string
  fulfillmentType: FulfillmentType
  estimatedDays: { min: number; max: number }
  estimatedMinutes?: number  // For local delivery (e.g. Armada, Parcel)
  price: Price
  cashOnDelivery: boolean
}

The fulfillmentType field enables the UI to render context-appropriate labels:

TypeUI Label Example
'shipping'3–5 business days
'local_delivery'~30 min delivery
'pickup'Ready for pickup

Payment Types

PaymentProvider

The pluggable interface that all payment gateways implement:

interface PaymentProvider {
  createSession(input: CreatePaymentSessionInput): Promise<PaymentSession>
  confirmSession(sessionId: string): Promise<PaymentSession>
  refund(input: RefundInput): Promise<PaymentSession>
  verifyWebhook(event: PaymentWebhookEvent): Promise<boolean>
}

PaymentSession

Tracks the lifecycle of a single payment:

interface PaymentSession {
  id: string
  providerId: string
  status: PaymentSessionStatus
  amount: number
  currency: string
  redirectUrl: string | null
  providerData?: Record<string, unknown>
  createdAt: string
}

type PaymentSessionStatus =
  | 'pending'
  | 'processing'
  | 'requires_action'
  | 'captured'
  | 'failed'
  | 'cancelled'
  | 'refunded'

Delivery Types

DeliveryProvider

The pluggable interface for last-mile delivery services:

interface DeliveryProvider {
  estimate(input: EstimateDeliveryInput): Promise<DeliveryEstimate>
  createDelivery(input: CreateDeliveryInput): Promise<Delivery>
  getDelivery(deliveryId: string): Promise<Delivery>
  cancelDelivery(deliveryId: string): Promise<Delivery>
  verifyWebhook(payload: string | Uint8Array, signature: string): Promise<DeliveryWebhookEvent>
}

Delivery & DeliveryEstimate

interface Delivery {
  id: string
  status: DeliveryStatus
  orderId?: string
  trackingUrl?: string
  driver?: { name: string; phone: string; latitude: number; longitude: number }
  createdAt: string
}

type DeliveryStatus = 'pending' | 'assigned' | 'pickup' | 'in_transit' | 'delivered' | 'cancelled' | 'failed'

interface DeliveryEstimate {
  fee: number
  currency: string
  estimatedDuration: number  // minutes
}

Storage Types

StorageProvider

The pluggable interface for object storage:

interface StorageProvider {
  upload(input: UploadInput): Promise<StorageUploadResult>
  delete(key: string): Promise<void>
  getUrl(key: string): string
  getPresignedUploadUrl(key: string, options?: PresignedUrlOptions): Promise<PresignedUrlResult>
  getPresignedDownloadUrl(key: string, options?: PresignedUrlOptions): Promise<PresignedUrlResult>
}

interface StorageUploadResult {
  key: string
  url: string
}

Adapter Contract

The CommerceAdapter uses a flat API — all domain methods are directly on the adapter object:

interface CommerceAdapter {
  name: string
  capabilities: AdapterDomain[]

  // Catalog
  getProduct(id: string): Promise<Product>
  getProducts(params?: GetProductParams): Promise<PaginatedResult<Product>>
  getCategories(params?: GetCategoriesParams): Promise<Category[]>

  // Cart
  createCart(): Promise<Cart>
  getCart(id: string): Promise<Cart>
  addToCart(cartId: string, input: AddToCartInput): Promise<Cart>
  updateCartItem(cartId: string, itemId: string, quantity: number): Promise<Cart>
  removeFromCart(cartId: string, itemId: string): Promise<Cart>

  // Orders
  createOrder(input: CreateOrderInput): Promise<Order>
  getOrder(id: string): Promise<Order>
  getCustomerOrders(customerId: string): Promise<Order[]>

  // Customers
  login(email: string, password: string): Promise<Customer>
  register(input: RegisterInput): Promise<Customer>
  getCustomer(id: string): Promise<Customer>

  // ... wishlist, reviews, store, promotions, returns, etc.
}

Adapters declare which domains they support via the capabilities array. Unsupported domain methods throw CommerceError with code NOT_SUPPORTED.

Error Handling

import { CommerceError, isCommerceError } from '@commercejs/types'

try {
  const product = await adapter.getProduct('invalid-id')
} catch (err) {
  if (isCommerceError(err)) {
    console.log(err.code)    // 'NOT_FOUND'
    console.log(err.message) // 'Product not found'
  }
}

Available error codes: NOT_FOUND, VALIDATION_ERROR, UNAUTHORIZED, RATE_LIMITED, PROVIDER_ERROR, NOT_IMPLEMENTED.

Orchestrator Types

The three-tier domain model for composable commerce:

import type {
  CommerceOrchestrator,
  UniversalDomains,
  CommonDomains,
  SpecializedDomains,
  DomainMap,
} from '@commercejs/types'

// Universal — always required
interface UniversalDomains {
  catalog: CatalogAdapter
  store: StoreAdapter
}

// Common — optional but widely needed
interface CommonDomains {
  cart?: CartAdapter
  checkout?: CheckoutAdapter
  orders?: OrderAdapter
  customers?: CustomerAdapter
  // ... wishlist, reviews, promotions, brands, countries, locations
}

// Specialized — niche domains
interface SpecializedDomains {
  returns?: ReturnAdapter
  wholesale?: WholesaleAdapter
  auctions?: AuctionAdapter
  rentals?: RentalAdapter
  giftCards?: GiftCardAdapter
}

// The orchestrator provides type-safe domain access
interface CommerceOrchestrator extends UniversalDomains {
  readonly name: string
  readonly capabilities: AdapterDomain[]
  supports(domain: string): boolean
  domain<D extends keyof DomainMap>(key: D): DomainMap[D]
}

Provider Types

NotificationProvider

interface NotificationProvider {
  readonly id: string
  readonly name: string
  readonly channels: NotificationChannel[]
  send(channel: NotificationChannel, message: NotificationMessage): Promise<NotificationResult>
}

type NotificationChannel = 'email' | 'sms' | 'push_web' | 'push_mobile' | 'whatsapp' | 'telegram'

AnalyticsProvider

interface AnalyticsProvider {
  readonly id: string
  readonly name: string
  track(event: string, properties?: Record<string, unknown>): void
  identify(userId: string, traits?: Record<string, unknown>): void
  page(name: string, properties?: Record<string, unknown>): void
}

TaxProvider

interface TaxProvider {
  readonly id: string
  readonly name: string
  calculate(input: TaxCalculationInput): Promise<TaxResult>
  commit(orderId: string, transactionId: string): Promise<void>
  void(transactionId: string): Promise<void>
}