{"version":3,"sources":["../src/types.ts"],"sourcesContent":["/**\n * F136 — Shop Module: shared types\n *\n * Used by collection schemas, API handlers, Stripe sync, shipping engine.\n * Kept in one file so consumers can `import type { ShopProduct } from\n * '@webhouse/cms-shop/types'` without pulling in any runtime code.\n */\n\n// ── Money ────────────────────────────────────────────────────────────────\n\n/** Three-letter ISO currency code, uppercase. e.g. \"DKK\", \"EUR\", \"SEK\". */\nexport type CurrencyCode = string;\n\n/** Amount in minor units (øre/cents). 12500 DKK = 125,00 kr. Stripe convention. */\nexport type MoneyAmount = number;\n\nexport interface MoneyAmountByCurrency {\n  /** Currency → amount in minor units. e.g. { DKK: 12500, EUR: 1700 } */\n  [currency: CurrencyCode]: MoneyAmount;\n}\n\n// ── Products ─────────────────────────────────────────────────────────────\n\nexport type ProductType =\n  | 'physical'\n  | 'digital'\n  | 'subscription'\n  | 'course'\n  | 'giftcard'\n  | 'booking';\n\nexport type DeliveryType =\n  | 'shipping'\n  | 'digital-download'\n  | 'pickup'\n  | 'booking';\n\nexport interface ProductDimensions {\n  /** Centimetres */\n  lengthCm?: number;\n  widthCm?: number;\n  heightCm?: number;\n  /** Grams */\n  weightG?: number;\n}\n\nexport interface ProductVariant {\n  id: string;\n  sku?: string;\n  /** e.g. { size: \"M\", color: \"blue\" } */\n  attributes: Record<string, string>;\n  priceByCurrency?: MoneyAmountByCurrency;\n  stockQuantity?: number;\n  images?: string[];\n}\n\nexport interface ShopProduct {\n  id: string;\n  slug: string;\n  /** Locale this document represents (DA, EN, …). */\n  locale?: string;\n  /** Group of locale variants share this id. */\n  translationGroup?: string;\n  data: {\n    title: string;\n    description?: string;\n    shortDescription?: string;\n    productType: ProductType;\n    deliveryType?: DeliveryType;\n    category?: string[];\n    tags?: string[];\n    brand?: string;\n    sku?: string;\n    images?: string[];\n    cardImageUrl?: string;\n    /** Per-currency pricing — required for the product to be sellable. */\n    priceByCurrency: MoneyAmountByCurrency;\n    /** Optional crossed-out reference price for sale display. */\n    compareAtPriceByCurrency?: MoneyAmountByCurrency;\n    /** Override per-locale tax behavior. Defaults to the site config. */\n    taxIncluded?: boolean;\n    stockQuantity?: number;\n    lowStockThreshold?: number;\n    /** Sold-out behaviour: hide from listings, show as out-of-stock, or allow backorder. */\n    stockBehavior?: 'hide' | 'out-of-stock' | 'backorder';\n    variants?: ProductVariant[];\n    dimensions?: ProductDimensions;\n    /** Shipping class id (looked up against shipping-rates collection). */\n    shippingClass?: string;\n    /** Stripe Product id once synced. Maintained by the sync hook. */\n    stripeProductId?: string;\n    /** Stripe Price id (per currency) once synced. */\n    stripePriceIds?: Record<CurrencyCode, string>;\n    /** Status: draft, active, archived. Inactive products hide from storefront but remain in admin. */\n    status?: 'draft' | 'active' | 'archived';\n    publishAt?: string;\n    unpublishAt?: string;\n  };\n}\n\n// ── Categories ───────────────────────────────────────────────────────────\n\nexport interface ShopCategory {\n  id: string;\n  slug: string;\n  locale?: string;\n  translationGroup?: string;\n  data: {\n    name: string;\n    description?: string;\n    parent?: string;\n    image?: string;\n    sortOrder?: number;\n    /** Optional per-category SEO. */\n    metaTitle?: string;\n    metaDescription?: string;\n  };\n}\n\n// ── Customers ────────────────────────────────────────────────────────────\n\nexport interface ShopCustomer {\n  id: string;\n  slug: string;  // typically the customer email-hash or stripe id\n  data: {\n    email: string;\n    name?: string;\n    phone?: string;\n    /** Stripe Customer id — populated by checkout. */\n    stripeCustomerId?: string;\n    addresses?: ShopAddress[];\n    /** Locale the customer prefers (drives email + receipt language). */\n    preferredLocale?: string;\n    marketingConsent?: boolean;\n    /** Aggregated lifetime value, recomputed on order paid. */\n    lifetimeValue?: MoneyAmountByCurrency;\n    createdAt: string;\n  };\n}\n\nexport interface ShopAddress {\n  /** \"shipping\" / \"billing\" / \"both\". */\n  kind?: 'shipping' | 'billing' | 'both';\n  name: string;\n  line1: string;\n  line2?: string;\n  postalCode: string;\n  city: string;\n  /** ISO 3166-1 alpha-2. */\n  country: string;\n  region?: string;\n  phone?: string;\n}\n\n// ── Cart ─────────────────────────────────────────────────────────────────\n\nexport interface CartLineItem {\n  productId: string;\n  variantId?: string;\n  /** Snapshot at the time of add — protects cart from price changes mid-flow. */\n  unitPrice: MoneyAmount;\n  currency: CurrencyCode;\n  quantity: number;\n  /** Snapshot of the product title for cart display. */\n  titleSnapshot: string;\n  /** Snapshot of the product image (cardImageUrl) for cart display. */\n  imageSnapshot?: string;\n}\n\nexport interface ShopCart {\n  /** Opaque cart id stored in the session cookie. */\n  id: string;\n  currency: CurrencyCode;\n  items: CartLineItem[];\n  /** Optional discount code applied. */\n  discountCode?: string;\n  /** Computed totals (kept in sync by the cart API). */\n  subtotal: MoneyAmount;\n  discountTotal: MoneyAmount;\n  shippingTotal: MoneyAmount;\n  taxTotal: MoneyAmount;\n  total: MoneyAmount;\n  shippingAddress?: ShopAddress;\n  /** Selected shipping rate id (from the rate engine). */\n  shippingRateId?: string;\n  createdAt: string;\n  updatedAt: string;\n  /** TTL — carts older than 48 h are reaped. */\n  expiresAt: string;\n  /** Optional customer email captured before checkout (for abandonment). */\n  email?: string;\n  /** Locale the cart was created in. */\n  locale?: string;\n}\n\n// ── Orders ───────────────────────────────────────────────────────────────\n\nexport type OrderStatus =\n  | 'pending'\n  | 'paid'\n  | 'fulfilled'\n  | 'shipped'\n  | 'delivered'\n  | 'cancelled'\n  | 'refunded'\n  | 'partially-refunded'\n  | 'failed';\n\nexport interface ShopOrder {\n  id: string;\n  slug: string;  // human-readable order number, e.g. WH-2026-00042\n  data: {\n    status: OrderStatus;\n    customerId?: string;\n    /** Email captured at checkout — present even for guest orders. */\n    email: string;\n    currency: CurrencyCode;\n    items: CartLineItem[];\n    subtotal: MoneyAmount;\n    discountTotal: MoneyAmount;\n    discountCode?: string;\n    shippingTotal: MoneyAmount;\n    shippingMethod?: string;\n    shippingAddress?: ShopAddress;\n    billingAddress?: ShopAddress;\n    taxTotal: MoneyAmount;\n    total: MoneyAmount;\n    /** Stripe ids — populated when checkout completes. */\n    stripeCheckoutSessionId?: string;\n    stripePaymentIntentId?: string;\n    /** Tracking — populated when label is created. */\n    trackingNumber?: string;\n    trackingUrl?: string;\n    shippingProvider?: 'gls' | 'dao' | 'postnord' | 'bring' | 'manual';\n    /** Locale the order was placed in — drives receipt + email templates. */\n    locale?: string;\n    notes?: string;\n    placedAt: string;\n    paidAt?: string;\n    fulfilledAt?: string;\n    shippedAt?: string;\n    deliveredAt?: string;\n    cancelledAt?: string;\n  };\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA;","names":[]}