@mohasinac/appkit 4.62.0 → 4.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (391) hide show
  1. package/dist/.build-stamp.json +3 -3
  2. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +8 -29
  3. package/dist/_internal/client/features/layout/filterNavItems.d.ts +28 -0
  4. package/dist/_internal/client/features/layout/filterNavItems.js +35 -0
  5. package/dist/_internal/server/features/ads/booking.d.ts +118 -0
  6. package/dist/_internal/server/features/ads/booking.js +326 -0
  7. package/dist/_internal/server/features/checkout/actions.d.ts +129 -9
  8. package/dist/_internal/server/features/checkout/actions.js +850 -79
  9. package/dist/_internal/server/features/checkout/expand-order-items.d.ts +1 -2
  10. package/dist/_internal/server/features/checkout/expand-order-items.js +32 -0
  11. package/dist/_internal/server/features/checkout/freeze-parts.d.ts +50 -0
  12. package/dist/_internal/server/features/checkout/freeze-parts.js +94 -0
  13. package/dist/_internal/server/features/checkout/value-otp-gate.d.ts +55 -0
  14. package/dist/_internal/server/features/checkout/value-otp-gate.js +60 -0
  15. package/dist/_internal/server/features/dashboard/attention.d.ts +128 -0
  16. package/dist/_internal/server/features/dashboard/attention.js +183 -0
  17. package/dist/_internal/server/features/dashboard/data.d.ts +47 -0
  18. package/dist/_internal/server/features/dashboard/data.js +82 -0
  19. package/dist/_internal/server/features/inventory/reservations.d.ts +99 -0
  20. package/dist/_internal/server/features/inventory/reservations.js +273 -0
  21. package/dist/_internal/server/features/invoicing/allocate.d.ts +63 -0
  22. package/dist/_internal/server/features/invoicing/allocate.js +162 -0
  23. package/dist/_internal/server/features/invoicing/credit-note.d.ts +57 -0
  24. package/dist/_internal/server/features/invoicing/credit-note.js +126 -0
  25. package/dist/_internal/server/features/invoicing/gstr1.d.ts +74 -0
  26. package/dist/_internal/server/features/invoicing/gstr1.js +251 -0
  27. package/dist/_internal/server/features/invoicing/issue.d.ts +96 -0
  28. package/dist/_internal/server/features/invoicing/issue.js +202 -0
  29. package/dist/_internal/server/features/offers/destinations.d.ts +40 -0
  30. package/dist/_internal/server/features/offers/destinations.js +65 -0
  31. package/dist/_internal/server/features/orders/actions.d.ts +8 -1
  32. package/dist/_internal/server/features/orders/actions.js +81 -8
  33. package/dist/_internal/server/features/orders/adapters.js +54 -0
  34. package/dist/_internal/server/features/orders/amend-delivery.d.ts +56 -0
  35. package/dist/_internal/server/features/orders/amend-delivery.js +124 -0
  36. package/dist/_internal/server/features/orders/balance.d.ts +89 -0
  37. package/dist/_internal/server/features/orders/balance.js +256 -0
  38. package/dist/_internal/server/features/orders/cancellation-refund.d.ts +15 -9
  39. package/dist/_internal/server/features/orders/cancellation-refund.js +15 -9
  40. package/dist/_internal/server/features/points/award.js +46 -4
  41. package/dist/_internal/server/features/pricing/actions.d.ts +58 -0
  42. package/dist/_internal/server/features/pricing/actions.js +144 -0
  43. package/dist/_internal/server/features/refunds/actions.js +26 -0
  44. package/dist/_internal/server/features/shipping/book-split.d.ts +86 -0
  45. package/dist/_internal/server/features/shipping/book-split.js +130 -0
  46. package/dist/_internal/server/features/shipping/book.d.ts +61 -0
  47. package/dist/_internal/server/features/shipping/book.js +176 -0
  48. package/dist/_internal/server/features/shipping/courier-block.d.ts +69 -0
  49. package/dist/_internal/server/features/shipping/courier-block.js +264 -0
  50. package/dist/_internal/server/features/site-settings/adapters.d.ts +2 -2
  51. package/dist/_internal/server/features/site-settings/adapters.js +29 -0
  52. package/dist/_internal/server/features/stores/adapters.d.ts +2 -2
  53. package/dist/_internal/server/features/stores/adapters.js +65 -0
  54. package/dist/_internal/server/functions/scheduled.d.ts +2 -1
  55. package/dist/_internal/server/functions/scheduled.js +95 -2
  56. package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +11 -2
  57. package/dist/_internal/server/jobs/core/dailyStatusDigest.d.ts +4 -0
  58. package/dist/_internal/server/jobs/core/dailyStatusDigest.js +19 -2
  59. package/dist/_internal/server/jobs/core/index.d.ts +2 -1
  60. package/dist/_internal/server/jobs/core/index.js +2 -1
  61. package/dist/_internal/server/jobs/core/jobRunners.js +45 -0
  62. package/dist/_internal/server/jobs/core/onJobCreated.d.ts +30 -7
  63. package/dist/_internal/server/jobs/core/onJobCreated.js +78 -45
  64. package/dist/_internal/server/jobs/core/onOrderStatusChange.d.ts +7 -0
  65. package/dist/_internal/server/jobs/core/onOrderStatusChange.js +65 -0
  66. package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +33 -0
  67. package/dist/_internal/server/jobs/core/reservationExpiry.d.ts +17 -0
  68. package/dist/_internal/server/jobs/core/reservationExpiry.js +40 -0
  69. package/dist/_internal/server/jobs/core/runJobOnce.d.ts +48 -0
  70. package/dist/_internal/server/jobs/core/runJobOnce.js +195 -0
  71. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +25 -2
  72. package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
  73. package/dist/_internal/server/jobs/handlers/index.js +1 -0
  74. package/dist/_internal/server/jobs/handlers/onOrderStatusChange.js +17 -0
  75. package/dist/_internal/server/jobs/handlers/reservationExpiry.d.ts +2 -0
  76. package/dist/_internal/server/jobs/handlers/reservationExpiry.js +2 -0
  77. package/dist/_internal/server/notifications/channel-health.d.ts +26 -3
  78. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  79. package/dist/_internal/shared/actions/action-registry.js +296 -0
  80. package/dist/_internal/shared/checkout/coupon-discount.d.ts +43 -1
  81. package/dist/_internal/shared/checkout/coupon-discount.js +26 -1
  82. package/dist/_internal/shared/checkout/order-math.d.ts +174 -0
  83. package/dist/_internal/shared/checkout/order-math.js +159 -0
  84. package/dist/_internal/shared/checkout/refundable-base.d.ts +25 -0
  85. package/dist/_internal/shared/checkout/refundable-base.js +13 -1
  86. package/dist/_internal/shared/checkout/rules/index.d.ts +1 -1
  87. package/dist/_internal/shared/checkout/rules/index.js +1 -1
  88. package/dist/_internal/shared/checkout/rules/payment-gate.d.ts +18 -0
  89. package/dist/_internal/shared/checkout/rules/payment-gate.js +25 -0
  90. package/dist/_internal/shared/checkout/split.d.ts +75 -0
  91. package/dist/_internal/shared/checkout/split.js +120 -0
  92. package/dist/_internal/shared/content/disclaimers.d.ts +88 -0
  93. package/dist/_internal/shared/content/disclaimers.js +217 -0
  94. package/dist/_internal/shared/content/published-values.d.ts +93 -0
  95. package/dist/_internal/shared/content/published-values.js +206 -0
  96. package/dist/_internal/shared/features/admin/integrations.d.ts +139 -0
  97. package/dist/_internal/shared/features/admin/integrations.js +263 -0
  98. package/dist/_internal/shared/features/dashboard/hub-sections.d.ts +72 -0
  99. package/dist/_internal/shared/features/dashboard/hub-sections.js +75 -0
  100. package/dist/_internal/shared/features/emi/choice.d.ts +98 -0
  101. package/dist/_internal/shared/features/emi/choice.js +69 -0
  102. package/dist/_internal/shared/features/emi/group.d.ts +84 -0
  103. package/dist/_internal/shared/features/emi/group.js +126 -0
  104. package/dist/_internal/shared/features/ledger/posting.d.ts +107 -0
  105. package/dist/_internal/shared/features/ledger/posting.js +165 -0
  106. package/dist/_internal/shared/features/ledger/reports.d.ts +76 -0
  107. package/dist/_internal/shared/features/ledger/reports.js +127 -0
  108. package/dist/_internal/shared/features/ledger/rules.d.ts +170 -0
  109. package/dist/_internal/shared/features/ledger/rules.js +221 -0
  110. package/dist/_internal/shared/features/offers/coordination.d.ts +122 -0
  111. package/dist/_internal/shared/features/offers/coordination.js +80 -0
  112. package/dist/_internal/shared/features/orders/delivery-snapshot.d.ts +114 -0
  113. package/dist/_internal/shared/features/orders/delivery-snapshot.js +116 -0
  114. package/dist/_internal/shared/features/orders/dispute-reasons.d.ts +113 -0
  115. package/dist/_internal/shared/features/orders/dispute-reasons.js +181 -0
  116. package/dist/_internal/shared/features/orders/refund-copy.d.ts +1 -1
  117. package/dist/_internal/shared/features/orders/refund-copy.js +18 -1
  118. package/dist/_internal/shared/features/payouts/pay-period.d.ts +91 -0
  119. package/dist/_internal/shared/features/payouts/pay-period.js +104 -0
  120. package/dist/_internal/shared/features/points/accepts.d.ts +29 -0
  121. package/dist/_internal/shared/features/points/accepts.js +49 -0
  122. package/dist/_internal/shared/features/pricing/rate-registry.d.ts +150 -0
  123. package/dist/_internal/shared/features/pricing/rate-registry.js +246 -0
  124. package/dist/_internal/shared/features/shipping/parcel.d.ts +123 -0
  125. package/dist/_internal/shared/features/shipping/parcel.js +139 -0
  126. package/dist/_internal/shared/features/shipping/shared-purchase.d.ts +91 -0
  127. package/dist/_internal/shared/features/shipping/shared-purchase.js +108 -0
  128. package/dist/_internal/shared/features/site-settings/fees.d.ts +16 -8
  129. package/dist/_internal/shared/features/site-settings/fees.js +12 -8
  130. package/dist/_internal/shared/features/site-settings/types.d.ts +11 -0
  131. package/dist/_internal/shared/fees/calculator.d.ts +33 -1
  132. package/dist/_internal/shared/fees/calculator.js +32 -2
  133. package/dist/_internal/shared/fees/explain.d.ts +81 -0
  134. package/dist/_internal/shared/fees/explain.js +101 -0
  135. package/dist/_internal/shared/history/index.d.ts +1 -1
  136. package/dist/_internal/shared/history/index.js +1 -1
  137. package/dist/_internal/shared/history/types.d.ts +7 -1
  138. package/dist/_internal/shared/history/types.js +25 -0
  139. package/dist/client.d.ts +21 -0
  140. package/dist/client.js +43 -0
  141. package/dist/constants/api-endpoints.d.ts +114 -0
  142. package/dist/constants/api-endpoints.js +55 -0
  143. package/dist/constants/field-names.d.ts +42 -0
  144. package/dist/constants/field-names.js +52 -0
  145. package/dist/contracts/index.d.ts +1 -1
  146. package/dist/contracts/shipping.d.ts +45 -0
  147. package/dist/contracts/shipping.js +15 -0
  148. package/dist/features/about/components/AboutView.js +1 -1
  149. package/dist/features/account/components/BuyerAuctionsGuideView.js +4 -1
  150. package/dist/features/account/components/UserOrdersView.js +47 -35
  151. package/dist/features/admin/components/AdminCouponEditorView.js +17 -0
  152. package/dist/features/admin/components/AdminIntegrationsView.d.ts +55 -0
  153. package/dist/features/admin/components/AdminIntegrationsView.js +74 -0
  154. package/dist/features/admin/components/AdminInvoicingView.d.ts +2 -0
  155. package/dist/features/admin/components/AdminInvoicingView.js +65 -0
  156. package/dist/features/admin/components/AdminOrderEditorView.d.ts +33 -1
  157. package/dist/features/admin/components/AdminOrderEditorView.js +81 -3
  158. package/dist/features/admin/components/AdminOrdersGuideView.js +23 -2
  159. package/dist/features/admin/components/AdminOrdersView.js +86 -5
  160. package/dist/features/admin/components/OwnerQuickActions.js +24 -2
  161. package/dist/features/admin/constants/filter-tabs.d.ts +6 -0
  162. package/dist/features/admin/constants/filter-tabs.js +6 -0
  163. package/dist/features/admin/constants/site-settings-tabs.d.ts +1 -1
  164. package/dist/features/admin/hooks/useAdminListingData.js +16 -0
  165. package/dist/features/admin/schemas/admin-user-form.d.ts +2 -2
  166. package/dist/features/admin/schemas/firestore.d.ts +62 -0
  167. package/dist/features/admin/schemas/firestore.js +5 -0
  168. package/dist/features/ads/schemas/booking-write.d.ts +120 -0
  169. package/dist/features/ads/schemas/booking-write.js +75 -0
  170. package/dist/features/ads/schemas/creative-form.d.ts +18 -0
  171. package/dist/features/ads/schemas/creative-form.js +51 -0
  172. package/dist/features/ads/schemas/firestore.d.ts +140 -0
  173. package/dist/features/ads/schemas/firestore.js +109 -0
  174. package/dist/features/auctions/repository/bid.repository.js +3 -1
  175. package/dist/features/audit-log/schemas/firestore.d.ts +140 -0
  176. package/dist/features/audit-log/schemas/firestore.js +89 -0
  177. package/dist/features/auth/actions/profile-actions.d.ts +69 -1
  178. package/dist/features/auth/actions/profile-actions.js +62 -1
  179. package/dist/features/auth/permissions/constants.js +13 -0
  180. package/dist/features/auth/schemas/firestore.d.ts +16 -2
  181. package/dist/features/auth/schemas/firestore.js +2 -1
  182. package/dist/features/blog/actions/blog-actions.d.ts +6 -0
  183. package/dist/features/blog/actions/blog-actions.js +17 -2
  184. package/dist/features/blog/api/route.js +4 -1
  185. package/dist/features/blog/columns/index.js +5 -0
  186. package/dist/features/blog/components/BlogIndexPageView.js +2 -1
  187. package/dist/features/blog/repository/blog.repository.d.ts +4 -0
  188. package/dist/features/blog/repository/blog.repository.js +5 -0
  189. package/dist/features/blog/schemas/blog-form.d.ts +3 -0
  190. package/dist/features/blog/schemas/blog-form.js +1 -0
  191. package/dist/features/blog/schemas/firestore.d.ts +38 -1
  192. package/dist/features/blog/schemas/firestore.js +23 -0
  193. package/dist/features/blog/schemas/index.d.ts +6 -0
  194. package/dist/features/blog/schemas/index.js +2 -0
  195. package/dist/features/blog/types/index.d.ts +2 -0
  196. package/dist/features/cart/components/CartPriceBreakdown.d.ts +25 -1
  197. package/dist/features/cart/components/CartPriceBreakdown.js +29 -6
  198. package/dist/features/cart/components/PointsTenderPicker.d.ts +61 -0
  199. package/dist/features/cart/components/PointsTenderPicker.js +15 -0
  200. package/dist/features/cart/components/StoreAddonsPicker.js +2 -1
  201. package/dist/features/cart/components/index.d.ts +2 -0
  202. package/dist/features/cart/components/index.js +1 -0
  203. package/dist/features/cart/repository/cart.repository.d.ts +33 -0
  204. package/dist/features/cart/repository/cart.repository.js +47 -0
  205. package/dist/features/cart/schemas/firestore.d.ts +116 -0
  206. package/dist/features/contact/email.d.ts +27 -10
  207. package/dist/features/contact/email.js +20 -3
  208. package/dist/features/dashboard/components/DashboardHubView.d.ts +83 -0
  209. package/dist/features/dashboard/components/DashboardHubView.js +56 -0
  210. package/dist/features/dashboard/components/DashboardSectionsClient.d.ts +23 -0
  211. package/dist/features/dashboard/components/DashboardSectionsClient.js +66 -0
  212. package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.d.ts +55 -0
  213. package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.js +175 -0
  214. package/dist/features/dispute-reasons/repository/dispute-reasons.repository.d.ts +62 -0
  215. package/dist/features/dispute-reasons/repository/dispute-reasons.repository.js +108 -0
  216. package/dist/features/dispute-reasons/schemas/firestore.d.ts +62 -0
  217. package/dist/features/dispute-reasons/schemas/firestore.js +40 -0
  218. package/dist/features/events/components/EventSaleBanner.js +1 -1
  219. package/dist/features/faq/components/FAQAccordion.d.ts +13 -1
  220. package/dist/features/faq/components/FAQAccordion.js +29 -4
  221. package/dist/features/faq/components/FAQPageContent.js +2 -2
  222. package/dist/features/gateway-events/schemas/index.d.ts +2 -2
  223. package/dist/features/homepage/schemas/index.d.ts +8 -8
  224. package/dist/features/inventory/schemas/stock-reservation.d.ts +114 -0
  225. package/dist/features/inventory/schemas/stock-reservation.js +103 -0
  226. package/dist/features/invoicing/schemas/firestore.d.ts +112 -0
  227. package/dist/features/invoicing/schemas/firestore.js +45 -0
  228. package/dist/features/invoicing/utils/financial-year.d.ts +43 -0
  229. package/dist/features/invoicing/utils/financial-year.js +53 -0
  230. package/dist/features/jobs/actions/enqueue-job.js +18 -1
  231. package/dist/features/jobs/repository/jobs.repository.d.ts +62 -1
  232. package/dist/features/jobs/repository/jobs.repository.js +84 -1
  233. package/dist/features/jobs/schemas/firestore.d.ts +80 -0
  234. package/dist/features/jobs/schemas/firestore.js +37 -0
  235. package/dist/features/layout/AppLayoutShell.d.ts +9 -1
  236. package/dist/features/layout/AppLayoutShell.js +12 -4
  237. package/dist/features/layout/BottomActions.js +2 -1
  238. package/dist/features/layout/BottomNavbar.d.ts +10 -2
  239. package/dist/features/layout/SideActionDock.js +52 -2
  240. package/dist/features/layout/TitleBarLayout.js +13 -4
  241. package/dist/features/layout/TitleBarLayout.style.css +59 -0
  242. package/dist/features/layout/useCtaReveal.d.ts +16 -1
  243. package/dist/features/layout/useCtaReveal.js +17 -26
  244. package/dist/features/ledger/repository/journal.repository.d.ts +110 -0
  245. package/dist/features/ledger/repository/journal.repository.js +312 -0
  246. package/dist/features/ledger/schemas/expenses.d.ts +87 -0
  247. package/dist/features/ledger/schemas/expenses.js +27 -0
  248. package/dist/features/ledger/schemas/firestore.d.ts +183 -0
  249. package/dist/features/ledger/schemas/firestore.js +69 -0
  250. package/dist/features/lottery/schemas/zod.d.ts +6 -6
  251. package/dist/features/media/MediaImage.js +22 -1
  252. package/dist/features/media/upload/ImageUpload.js +1 -1
  253. package/dist/features/obligations/constants/policies.js +24 -1
  254. package/dist/features/orders/components/BalancePaymentPanel.d.ts +12 -0
  255. package/dist/features/orders/components/BalancePaymentPanel.js +94 -0
  256. package/dist/features/orders/components/OrderPaymentSummary.js +10 -1
  257. package/dist/features/orders/components/OrderProvenanceCard.d.ts +8 -0
  258. package/dist/features/orders/components/OrderProvenanceCard.js +185 -0
  259. package/dist/features/orders/components/RaiseDisputeForm.d.ts +14 -0
  260. package/dist/features/orders/components/RaiseDisputeForm.js +119 -0
  261. package/dist/features/orders/components/RefundRequestView.js +19 -1
  262. package/dist/features/orders/components/index.d.ts +4 -0
  263. package/dist/features/orders/components/index.js +2 -0
  264. package/dist/features/orders/constants/order-lane-tabs.d.ts +69 -0
  265. package/dist/features/orders/constants/order-lane-tabs.js +88 -0
  266. package/dist/features/orders/repository/orders.repository.d.ts +85 -1
  267. package/dist/features/orders/repository/orders.repository.js +205 -6
  268. package/dist/features/orders/schemas/balance.d.ts +40 -0
  269. package/dist/features/orders/schemas/balance.js +47 -0
  270. package/dist/features/orders/schemas/firestore.d.ts +398 -1
  271. package/dist/features/orders/schemas/firestore.js +43 -0
  272. package/dist/features/orders/schemas/index.d.ts +56 -8
  273. package/dist/features/orders/schemas/index.js +12 -0
  274. package/dist/features/orders/types/index.d.ts +47 -0
  275. package/dist/features/orders/utils/courier-block.d.ts +25 -0
  276. package/dist/features/orders/utils/courier-block.js +23 -0
  277. package/dist/features/payment-cases/schemas/firestore.d.ts +26 -1
  278. package/dist/features/payment-cases/schemas/firestore.js +1 -0
  279. package/dist/features/payments/repository/payout.repository.js +3 -2
  280. package/dist/features/payments/schemas/firestore.d.ts +92 -1
  281. package/dist/features/payments/schemas/firestore.js +23 -0
  282. package/dist/features/pricing/components/AdminPricingView.d.ts +13 -0
  283. package/dist/features/pricing/components/AdminPricingView.js +157 -0
  284. package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -2
  285. package/dist/features/products/components/ProductDetailPageView.d.ts +17 -1
  286. package/dist/features/products/components/ProductDetailPageView.js +2 -2
  287. package/dist/features/products/schemas/firestore.d.ts +26 -1
  288. package/dist/features/products/schemas/firestore.js +2 -0
  289. package/dist/features/products/schemas/index.d.ts +2 -2
  290. package/dist/features/products/schemas/product-features.validators.d.ts +10 -10
  291. package/dist/features/promotions/actions/coupon-stacking.d.ts +30 -3
  292. package/dist/features/promotions/actions/coupon-stacking.js +21 -2
  293. package/dist/features/promotions/components/CouponCard.js +13 -0
  294. package/dist/features/promotions/constants/coupon-help.d.ts +2 -2
  295. package/dist/features/promotions/constants/coupon-help.js +9 -1
  296. package/dist/features/promotions/schemas/firestore.d.ts +24 -0
  297. package/dist/features/promotions/schemas/firestore.js +4 -0
  298. package/dist/features/promotions/types/index.d.ts +19 -1
  299. package/dist/features/reviews/repository/reviews.repository.d.ts +14 -0
  300. package/dist/features/reviews/repository/reviews.repository.js +16 -0
  301. package/dist/features/scams/components/ScamProfileView.js +2 -2
  302. package/dist/features/scams/components/ScamRegistryView.js +2 -2
  303. package/dist/features/scams/repository/scammer.repository.js +2 -1
  304. package/dist/features/scams/schemas/firestore.d.ts +2 -1
  305. package/dist/features/scams/schemas/firestore.js +2 -1
  306. package/dist/features/search/action-index/tab-entries.js +1 -1
  307. package/dist/features/seller/actions/offer-actions.js +56 -0
  308. package/dist/features/seller/actions/seller-actions.d.ts +1 -1
  309. package/dist/features/seller/actions/seller-actions.js +37 -3
  310. package/dist/features/seller/components/DispatchForm.d.ts +11 -0
  311. package/dist/features/seller/components/DispatchForm.js +190 -0
  312. package/dist/features/seller/components/SellerOrdersView.js +221 -27
  313. package/dist/features/seller/components/index.d.ts +1 -0
  314. package/dist/features/seller/components/index.js +1 -0
  315. package/dist/features/seller/hooks/useSellerListingData.js +25 -0
  316. package/dist/features/seller/repository/offer.repository.js +4 -3
  317. package/dist/features/seller/schemas/firestore.d.ts +23 -2
  318. package/dist/features/seller/schemas/firestore.js +3 -2
  319. package/dist/features/seller/schemas/index.d.ts +4 -4
  320. package/dist/features/seller/schemas/order-forms.d.ts +61 -4
  321. package/dist/features/seller/schemas/order-forms.js +41 -8
  322. package/dist/features/shipments/schemas/firestore.d.ts +25 -0
  323. package/dist/features/shipments/schemas/validation.d.ts +4 -4
  324. package/dist/features/shipping-boxes/repository/shipping-boxes.repository.d.ts +82 -0
  325. package/dist/features/shipping-boxes/repository/shipping-boxes.repository.js +145 -0
  326. package/dist/features/shipping-boxes/schemas/firestore.d.ts +80 -0
  327. package/dist/features/shipping-boxes/schemas/firestore.js +53 -0
  328. package/dist/features/store-extensions/schemas/report-create-form.d.ts +2 -2
  329. package/dist/features/store-extensions/schemas/shipping-config-form.d.ts +2 -2
  330. package/dist/features/stores/components/StoreOrdersGuideView.js +6 -1
  331. package/dist/features/stores/repository/store.repository.d.ts +18 -0
  332. package/dist/features/stores/repository/store.repository.js +27 -1
  333. package/dist/features/stores/schemas/firestore.d.ts +112 -0
  334. package/dist/features/stores/schemas/firestore.js +20 -0
  335. package/dist/features/stores/schemas/index.d.ts +6 -6
  336. package/dist/features/stores/types/index.d.ts +19 -0
  337. package/dist/features/support/repository/support.repository.js +72 -6
  338. package/dist/features/support/schemas/firestore.d.ts +17 -0
  339. package/dist/features/support/schemas/index.d.ts +8 -8
  340. package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
  341. package/dist/index.d.ts +11 -1
  342. package/dist/index.js +33 -1
  343. package/dist/next/routing/route-map.d.ts +112 -0
  344. package/dist/next/routing/route-map.js +63 -0
  345. package/dist/providers/shipping-shiprocket/index.d.ts +27 -1
  346. package/dist/providers/shipping-shiprocket/index.js +84 -1
  347. package/dist/react/contexts/SessionContext.d.ts +17 -1
  348. package/dist/schemas/registry.d.ts +69 -34
  349. package/dist/schemas/sieve.d.ts +2 -2
  350. package/dist/security/pii-schemas.d.ts +1 -1
  351. package/dist/security/pii-schemas.js +45 -0
  352. package/dist/server-entry.d.ts +2 -2
  353. package/dist/server-entry.js +8 -1
  354. package/dist/server.d.ts +36 -1
  355. package/dist/server.js +183 -1
  356. package/dist/styles.css +412 -80
  357. package/dist/tailwind-utilities.css +1 -1
  358. package/dist/tokens/themes/default-dark.js +1 -0
  359. package/dist/tokens/themes/default-light.js +1 -0
  360. package/dist/tokens/themes/required.d.ts +1 -1
  361. package/dist/tokens/themes/required.js +1 -0
  362. package/dist/tokens/tokens.css +15 -0
  363. package/dist/ui/components/Button.d.ts +10 -1
  364. package/dist/ui/components/Button.js +25 -3
  365. package/dist/ui/components/Chart.d.ts +63 -0
  366. package/dist/ui/components/Chart.js +169 -0
  367. package/dist/ui/components/Chart.style.css +214 -0
  368. package/dist/ui/components/Disclaimer.d.ts +19 -0
  369. package/dist/ui/components/Disclaimer.js +83 -0
  370. package/dist/ui/components/OverflowRow.js +54 -2
  371. package/dist/ui/components/OverflowRow.style.css +38 -0
  372. package/dist/ui/components/RichTextEditor.js +99 -8
  373. package/dist/ui/components/chart-spec.d.ts +68 -0
  374. package/dist/ui/components/chart-spec.js +140 -0
  375. package/dist/ui/components/index.style.css +1 -0
  376. package/dist/ui/components/surface-tokens.d.ts +1 -1
  377. package/dist/ui/components/surface-tokens.js +9 -0
  378. package/dist/ui/components/tabs-overflow.js +64 -11
  379. package/dist/ui/components/toolbar-collapse.d.ts +13 -0
  380. package/dist/ui/components/toolbar-collapse.js +10 -1
  381. package/dist/ui/index.d.ts +8 -0
  382. package/dist/ui/index.js +9 -0
  383. package/dist/ui/rich-text/RichText.d.ts +10 -1
  384. package/dist/ui/rich-text/RichText.js +33 -2
  385. package/dist/ui/rich-text/RichText.style.css +83 -79
  386. package/dist/ui/rich-text/RichTextRenderer.d.ts +30 -1
  387. package/dist/ui/rich-text/RichTextRenderer.js +34 -2
  388. package/dist/ui/rich-text/chart-blocks.d.ts +62 -0
  389. package/dist/ui/rich-text/chart-blocks.js +87 -0
  390. package/package.json +1 -1
  391. package/scripts/seed-cli.mjs +1834 -1822
@@ -102,7 +102,7 @@ export declare const SITE_SETTINGS_TABS: readonly [{
102
102
  readonly description: "Which listing types sellers may create, and their defaults.";
103
103
  readonly keywords: ["listing types", "auctions on", "enable", "categories"];
104
104
  }];
105
- export declare const SITE_SETTINGS_TAB_IDS: ("about" | "shipping" | "notifications" | "contact" | "auction" | "seo" | "listings" | "appearance" | "emi" | "gst" | "watermark" | "integrations" | "limits" | "announcement" | "branding" | "themes" | "fees" | "legal" | "procurement")[];
105
+ export declare const SITE_SETTINGS_TAB_IDS: ("about" | "shipping" | "notifications" | "contact" | "auction" | "seo" | "listings" | "emi" | "legal" | "appearance" | "gst" | "watermark" | "integrations" | "limits" | "announcement" | "branding" | "themes" | "fees" | "procurement")[];
106
106
  /**
107
107
  * The union `?tab=` is validated against.
108
108
  *
@@ -2,6 +2,9 @@
2
2
  import { useQuery } from "@tanstack/react-query";
3
3
  import { apiClient, ApiClientError } from "../../../http/index.js";
4
4
  import { formatCurrency } from "../../../utils/number.formatter.js";
5
+ // The defining module, not a barrel (Root Cause #18). `hasEncPrefix` is a pure
6
+ // string test with no crypto in its import chain, so it is client-safe.
7
+ import { hasEncPrefix } from "../../../security/pii-mask.js";
5
8
  function withQueryParams(endpoint, params) {
6
9
  const hasQuery = endpoint.includes("?");
7
10
  const query = new URLSearchParams(params).toString();
@@ -50,6 +53,19 @@ export function toRecordArray(value) {
50
53
  }
51
54
  export function toStringValue(value, fallback = "-") {
52
55
  if (typeof value === "string") {
56
+ /*
57
+ * 🛑 Ciphertext is not a display value. See the twin in
58
+ * `features/seller/hooks/useSellerListingData.ts` for the full account —
59
+ * the short version is that `mapDoc` does not decrypt, so a route that
60
+ * forgets `revealOrders`/`maskedOrders` hands this a stored `enc:v1:…`
61
+ * blob which is a perfectly ordinary `string` and renders verbatim.
62
+ *
63
+ * `/api/admin/orders` already hit this ("measured live at 3 visible
64
+ * `enc:v1:` strings") and fixed it at the route. This is the backstop for
65
+ * the next one.
66
+ */
67
+ if (hasEncPrefix(value))
68
+ return fallback;
53
69
  return value.trim() || fallback;
54
70
  }
55
71
  if (typeof value === "number" || typeof value === "boolean") {
@@ -82,13 +82,13 @@ export declare const lotteryPullSchema: z.ZodObject<{
82
82
  userPhone: z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>;
83
83
  }, "strip", z.ZodTypeAny, {
84
84
  transactionId: string;
85
- sourceType: "event" | "product";
85
+ sourceType: "product" | "event";
86
86
  paymentTime: string;
87
87
  purchasedItemNumber: number;
88
88
  userPhone?: string | undefined;
89
89
  }, {
90
90
  transactionId: string;
91
- sourceType: "event" | "product";
91
+ sourceType: "product" | "event";
92
92
  paymentTime: string;
93
93
  purchasedItemNumber: number;
94
94
  userPhone?: string | undefined;
@@ -3,6 +3,7 @@
3
3
  * Covers: notifications, chat rooms, site settings
4
4
  */
5
5
  import type { AboutContentDocument } from "../../about/schemas/firestore";
6
+ import type { RateChange } from "../../../_internal/shared/features/pricing/rate-registry";
6
7
  export declare const ADMIN_CHECKOUT_BYPASS_FLAG_KEY: "adminCheckoutBypass";
7
8
  export declare const NOTIFICATION_TYPE_VALUES: readonly ["order_placed", "order_confirmed", "order_shipped", "order_delivered", "order_cancelled", "bid_placed", "bid_outbid", "bid_won", "bid_lost", "auction_ended", "review_approved", "review_replied", "product_available", "promotion", "system", "welcome", "account_action", "support_ticket_update", "scam_report_update", "offer_received", "offer_responded", "offer_expired", "offer_counter_accepted", "refund_initiated", "prize_won", "prize_reveal_expired", "emi_installment_due_soon", "emi_installment_overdue", "payment_review", "catalogue_images_stale", "message_received"];
8
9
  export type NotificationType = (typeof NOTIFICATION_TYPE_VALUES)[number];
@@ -233,6 +234,18 @@ export type SiteSettingsAdPlacement = {
233
234
  label: string;
234
235
  enabled: boolean;
235
236
  reservedHeight: number;
237
+ /**
238
+ * D56 — the flat monthly rate for a self-serve booking of this slot, in
239
+ * rupees. Absent means NOT SOLD: `bookAdSlot` refuses rather than
240
+ * defaulting to zero, because a free booking that looks successful takes
241
+ * the slot, bills nothing, and says nothing about the missing price.
242
+ *
243
+ * 🛑 Editing this does NOT reprice a sold slot. `AdBookingDocument.priceRs`
244
+ * is snapshotted at booking, for the same reason `sourceContext` is
245
+ * written once: the rate is a price somebody agreed to, and re-deriving it
246
+ * later silently rewrites a completed sale.
247
+ */
248
+ priceRsPerPeriod?: number;
236
249
  };
237
250
  /** Embedded in siteSettings.adSettings — a type alias, not a collection root. */
238
251
  export type SiteSettingsAdInventoryItem = {
@@ -690,6 +703,36 @@ export interface SiteSettingsDocument extends BaseDocument {
690
703
  returns: {
691
704
  windowDays: number;
692
705
  };
706
+ /**
707
+ * The support integration's on/off switch.
708
+ *
709
+ * 🛑 The ONLY new integration flag. The other three the admin page switches
710
+ * already have an authoritative field — `payment.razorpayEnabled`,
711
+ * `messaging.emailEnabled` (which `guardSend` reads), and
712
+ * `shipping.provider`. Adding a parallel `integrationSwitches.*` beside
713
+ * those would be a denormalised mirror that drifts the first time one path
714
+ * writes only one of a pair (Root Cause #42), and the page would then
715
+ * disagree with the code that enforces it. The page is a VIEW over the real
716
+ * fields; this is the one field that did not exist.
717
+ *
718
+ * 🛑 Also not under `siteSettings.integrations` — that key is live and holds
719
+ * analytics/tag IDs (GA, FB Pixel, GTM).
720
+ *
721
+ * OFF hides the WHOLE support surface from BUYERS: no nav entry, no ticket
722
+ * list, no contact form. Staff keep full access, so an open ticket is still
723
+ * workable and the employee pay-per-ticket basis survives.
724
+ *
725
+ * 🛑 A buyer mid-conversation loses sight of their thread. That is the
726
+ * owner's decision, accepted knowingly — and the admin row must SAY it
727
+ * rather than implying the switch only stops new tickets.
728
+ *
729
+ * Defaults to `true`: support being reachable is the safe state, and a
730
+ * settings document written before this field existed must not read as
731
+ * "support is off".
732
+ */
733
+ support: {
734
+ enabled: boolean;
735
+ };
693
736
  faq: {
694
737
  variables: {
695
738
  shippingDays: number;
@@ -808,6 +851,25 @@ export interface SiteSettingsDocument extends BaseDocument {
808
851
  * opt-in and require the corresponding credentials to be set.
809
852
  */
810
853
  notificationChannels?: NotificationChannelConfig;
854
+ /**
855
+ * The rate-change log behind `/admin/pricing`. Append-only, newest FIRST,
856
+ * capped at `RATE_CHANGE_LOG_MAX`.
857
+ *
858
+ * 🛑 **An array on the singleton rather than a collection, deliberately.**
859
+ * The page's only query is "the recent history of these 16 rates", which is
860
+ * one document read — and the rates themselves already live here, so a
861
+ * separate collection would mean two reads to render one table and two
862
+ * writes to record one change. It is capped for the same reason
863
+ * `statusHistory` is: an uncapped array on a hot singleton eventually makes
864
+ * every settings read expensive.
865
+ *
866
+ * 🛑 **Not an audit trail, and not a substitute for one.** A `pricing_update`
867
+ * row also goes to `adminAuditLog`, which is queryable and answers "what
868
+ * have admins done lately". This answers the narrower question the pricing
869
+ * page asks — "when did THIS rate last move, and to what" — and it is the
870
+ * one a truncation can safely lose.
871
+ */
872
+ rateChanges?: RateChange[];
811
873
  }
812
874
  export declare const SITE_SETTINGS_COLLECTION: "siteSettings";
813
875
  export declare const SITE_SETTINGS_INDEXED_FIELDS: readonly [];
@@ -377,6 +377,11 @@ export const DEFAULT_SITE_SETTINGS_DATA = {
377
377
  returns: {
378
378
  windowDays: 7,
379
379
  },
380
+ // Reachable is the safe default, and an older settings document with no
381
+ // `support` group must not read as "support is off".
382
+ support: {
383
+ enabled: true,
384
+ },
380
385
  announcementBar: {
381
386
  enabled: true,
382
387
  message: "🎉 Up to 15% Off on Pokémon TCG this week — Use code SAVE15",
@@ -0,0 +1,120 @@
1
+ /**
2
+ * The write contract for a self-serve ad booking.
3
+ *
4
+ * ## 🛑 The shape cannot express moderation, payment or price
5
+ *
6
+ * This is Root Cause #76's rule applied to a surface where the submitter is
7
+ * a member of the public rather than an admin, which makes it sharper: an
8
+ * advertiser who can send `moderation: { state: "approved" }` has not
9
+ * bypassed a check, they have *become* the check. A schema that merely
10
+ * VALIDATED the field would still let `"approved"` through — the field has
11
+ * to be unrepresentable, so `.strict()` turns it into a 400 instead of
12
+ * something the server has to remember to overwrite.
13
+ *
14
+ * Same for `priceRs` (the server reads the rate card; a client-supplied
15
+ * price is a ₹1 banner) and `paymentState` (a booking that declares itself
16
+ * paid is a free slot).
17
+ *
18
+ * `placementId` and `period` ARE accepted: they are what is being bought,
19
+ * and they are also the booking's identity, so the conflict they can cause
20
+ * is a document collision rather than a validation question.
21
+ */
22
+ import { z } from "zod";
23
+ /**
24
+ * 🛑 Creative fields are bounded, and `ctaHref` is http(s)-only.
25
+ *
26
+ * An unbounded `body` is a storage cost per booking and a layout break on
27
+ * every page carrying the slot. A `javascript:` or `data:` CTA is script
28
+ * execution on every page the creative renders on, submitted by a member of
29
+ * the public — this is the one field on this schema where a miss is a
30
+ * security defect rather than a tidiness one.
31
+ */
32
+ export declare const httpUrl: z.ZodEffects<z.ZodString, string, string>;
33
+ export declare const adBookingCreativeSchema: z.ZodObject<{
34
+ title: z.ZodString;
35
+ body: z.ZodOptional<z.ZodString>;
36
+ imageUrl: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
37
+ ctaLabel: z.ZodOptional<z.ZodString>;
38
+ ctaHref: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
39
+ }, "strict", z.ZodTypeAny, {
40
+ title: string;
41
+ body?: string | undefined;
42
+ imageUrl?: string | undefined;
43
+ ctaLabel?: string | undefined;
44
+ ctaHref?: string | undefined;
45
+ }, {
46
+ title: string;
47
+ body?: string | undefined;
48
+ imageUrl?: string | undefined;
49
+ ctaLabel?: string | undefined;
50
+ ctaHref?: string | undefined;
51
+ }>;
52
+ export declare const adBookingWriteSchema: z.ZodObject<{
53
+ placementId: z.ZodString;
54
+ period: z.ZodEffects<z.ZodString, string, string>;
55
+ creative: z.ZodObject<{
56
+ title: z.ZodString;
57
+ body: z.ZodOptional<z.ZodString>;
58
+ imageUrl: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
59
+ ctaLabel: z.ZodOptional<z.ZodString>;
60
+ ctaHref: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
61
+ }, "strict", z.ZodTypeAny, {
62
+ title: string;
63
+ body?: string | undefined;
64
+ imageUrl?: string | undefined;
65
+ ctaLabel?: string | undefined;
66
+ ctaHref?: string | undefined;
67
+ }, {
68
+ title: string;
69
+ body?: string | undefined;
70
+ imageUrl?: string | undefined;
71
+ ctaLabel?: string | undefined;
72
+ ctaHref?: string | undefined;
73
+ }>;
74
+ }, "strict", z.ZodTypeAny, {
75
+ placementId: string;
76
+ period: string;
77
+ creative: {
78
+ title: string;
79
+ body?: string | undefined;
80
+ imageUrl?: string | undefined;
81
+ ctaLabel?: string | undefined;
82
+ ctaHref?: string | undefined;
83
+ };
84
+ }, {
85
+ placementId: string;
86
+ period: string;
87
+ creative: {
88
+ title: string;
89
+ body?: string | undefined;
90
+ imageUrl?: string | undefined;
91
+ ctaLabel?: string | undefined;
92
+ ctaHref?: string | undefined;
93
+ };
94
+ }>;
95
+ export type AdBookingWriteInput = z.infer<typeof adBookingWriteSchema>;
96
+ /**
97
+ * A moderator's verdict.
98
+ *
99
+ * 🛑 A rejection REQUIRES a note, for the same reason an admin offer-cancel
100
+ * does: without one the advertiser's next submission is the same creative
101
+ * again, and the moderator reviews it twice. An approval takes no note
102
+ * because there is nothing to say.
103
+ */
104
+ export declare const adModerationSchema: z.ZodEffects<z.ZodObject<{
105
+ approve: z.ZodBoolean;
106
+ note: z.ZodOptional<z.ZodString>;
107
+ }, "strict", z.ZodTypeAny, {
108
+ approve: boolean;
109
+ note?: string | undefined;
110
+ }, {
111
+ approve: boolean;
112
+ note?: string | undefined;
113
+ }>, {
114
+ approve: boolean;
115
+ note?: string | undefined;
116
+ }, {
117
+ approve: boolean;
118
+ note?: string | undefined;
119
+ }>;
120
+ export type AdModerationInput = z.infer<typeof adModerationSchema>;
@@ -0,0 +1,75 @@
1
+ /**
2
+ * The write contract for a self-serve ad booking.
3
+ *
4
+ * ## 🛑 The shape cannot express moderation, payment or price
5
+ *
6
+ * This is Root Cause #76's rule applied to a surface where the submitter is
7
+ * a member of the public rather than an admin, which makes it sharper: an
8
+ * advertiser who can send `moderation: { state: "approved" }` has not
9
+ * bypassed a check, they have *become* the check. A schema that merely
10
+ * VALIDATED the field would still let `"approved"` through — the field has
11
+ * to be unrepresentable, so `.strict()` turns it into a 400 instead of
12
+ * something the server has to remember to overwrite.
13
+ *
14
+ * Same for `priceRs` (the server reads the rate card; a client-supplied
15
+ * price is a ₹1 banner) and `paymentState` (a booking that declares itself
16
+ * paid is a free slot).
17
+ *
18
+ * `placementId` and `period` ARE accepted: they are what is being bought,
19
+ * and they are also the booking's identity, so the conflict they can cause
20
+ * is a document collision rather than a validation question.
21
+ */
22
+ import { z } from "zod";
23
+ import { isAdPeriod } from "./firestore.js";
24
+ /**
25
+ * 🛑 Creative fields are bounded, and `ctaHref` is http(s)-only.
26
+ *
27
+ * An unbounded `body` is a storage cost per booking and a layout break on
28
+ * every page carrying the slot. A `javascript:` or `data:` CTA is script
29
+ * execution on every page the creative renders on, submitted by a member of
30
+ * the public — this is the one field on this schema where a miss is a
31
+ * security defect rather than a tidiness one.
32
+ */
33
+ /*
34
+ * Exported so `creative-form.ts` reuses the REFINEMENT rather than restating
35
+ * it — the form and the wire must agree on what a link is, and a second copy
36
+ * of a security check is a second thing to forget.
37
+ */
38
+ export const httpUrl = z
39
+ .string()
40
+ .url()
41
+ .refine((u) => /^https?:\/\//i.test(u), "Links must start with http:// or https://");
42
+ export const adBookingCreativeSchema = z
43
+ .object({
44
+ title: z.string().min(2).max(80),
45
+ body: z.string().max(200).optional(),
46
+ imageUrl: httpUrl.optional(),
47
+ ctaLabel: z.string().max(40).optional(),
48
+ ctaHref: httpUrl.optional(),
49
+ })
50
+ .strict();
51
+ export const adBookingWriteSchema = z
52
+ .object({
53
+ placementId: z.string().min(1).max(80),
54
+ period: z.string().refine(isAdPeriod, "Pick a month, as YYYY-MM."),
55
+ creative: adBookingCreativeSchema,
56
+ })
57
+ .strict();
58
+ /**
59
+ * A moderator's verdict.
60
+ *
61
+ * 🛑 A rejection REQUIRES a note, for the same reason an admin offer-cancel
62
+ * does: without one the advertiser's next submission is the same creative
63
+ * again, and the moderator reviews it twice. An approval takes no note
64
+ * because there is nothing to say.
65
+ */
66
+ export const adModerationSchema = z
67
+ .object({
68
+ approve: z.boolean(),
69
+ note: z.string().max(300).optional(),
70
+ })
71
+ .strict()
72
+ .refine((v) => v.approve || (v.note?.trim().length ?? 0) >= 10, {
73
+ message: "Say why it was rejected — the advertiser sees this and will resubmit without it.",
74
+ path: ["note"],
75
+ });
@@ -0,0 +1,18 @@
1
+ import { z } from "zod";
2
+ export declare const adCreativeFormSchema: z.ZodObject<{
3
+ title: z.ZodString;
4
+ body: z.ZodOptional<z.ZodString>;
5
+ ctaLabel: z.ZodOptional<z.ZodString>;
6
+ ctaHref: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"">, z.ZodEffects<z.ZodString, string, string>]>>;
7
+ }, "strip", z.ZodTypeAny, {
8
+ title: string;
9
+ body?: string | undefined;
10
+ ctaLabel?: string | undefined;
11
+ ctaHref?: string | undefined;
12
+ }, {
13
+ title: string;
14
+ body?: string | undefined;
15
+ ctaLabel?: string | undefined;
16
+ ctaHref?: string | undefined;
17
+ }>;
18
+ export type AdCreativeFormValues = z.infer<typeof adCreativeFormSchema>;
@@ -0,0 +1,51 @@
1
+ /*
2
+ * WHY: `/advertise` rendered four hand-wired `<FieldInput>`s inside a bare
3
+ * `<Form>`, so the advertiser's creative had no client-side bounds at
4
+ * all — the only limits were the ones `adBookingCreateSchema` enforces
5
+ * server-side, which the visitor meets as a 400 after submitting. A
6
+ * headline is the single most visible string this platform renders to
7
+ * strangers; it should not be the one field with no feedback until POST.
8
+ *
9
+ * WHAT: The FLAT form shape for the booking creative, annotated so
10
+ * `buildSectionsFromSchema` produces the fields. The wire shape nests
11
+ * these under `creative` (see `booking-write.ts`); the page lifts them
12
+ * at submit.
13
+ *
14
+ * 🛑 It deliberately does NOT carry `placementId` or `period`. Those are
15
+ * chosen by clicking a month in the rate card, not typed — and more to the
16
+ * point, a slot whose availability the server has already decided must not
17
+ * become a text input the advertiser can edit. The booking id IS the lock
18
+ * (`adBookingId`), so a typed period is a way to aim at somebody else's slot.
19
+ *
20
+ * 🛑 Bounds mirror `adCreativeSchema` exactly. Two numbers that merely happen
21
+ * to agree today would drift into a form that accepts what the route refuses,
22
+ * which is the worse of the two failures: it looks like a server fault.
23
+ *
24
+ * EXPORTS: adCreativeFormSchema, type AdCreativeFormValues
25
+ *
26
+ * @tag domain:ads
27
+ * @tag layer:schema
28
+ * @tag pattern:none
29
+ * @tag access:isomorphic
30
+ * @tag consumers:/advertise
31
+ * @tag sideEffects:none
32
+ */
33
+ import { z } from "zod";
34
+ import { annotate } from "../../shell/field-ui-meta.js";
35
+ import { httpUrl } from "./booking-write.js";
36
+ export const adCreativeFormSchema = z.object({
37
+ title: annotate(z.string().trim().min(2, "A headline is required.").max(80, "Keep the headline under 80 characters."), { section: "creative", sectionLabel: "Your creative", sectionRequired: true, quick: true, order: 1, row: "full" }),
38
+ body: annotate(z.string().trim().max(200, "Keep the body under 200 characters.").optional(), { section: "creative", order: 2, row: "full", kind: "textarea" }),
39
+ ctaLabel: annotate(z.string().trim().max(40, "Keep the button text under 40 characters.").optional(), { section: "creative", order: 3, row: "pair" }),
40
+ /*
41
+ * 🛑 `httpUrl`, the same refinement the wire schema uses — a `javascript:`
42
+ * or `data:` CTA on a page we render to strangers is stored XSS with our
43
+ * own domain's credibility behind it. An empty string is allowed through so
44
+ * clearing the field is not an error; the page drops it before POST.
45
+ */
46
+ ctaHref: annotate(z.union([z.literal(""), httpUrl]).optional(), {
47
+ section: "creative",
48
+ order: 4,
49
+ row: "pair",
50
+ }),
51
+ });
@@ -0,0 +1,140 @@
1
+ /**
2
+ * D56 — a SELF-SERVE ad booking: one advertiser, one placement, one period.
3
+ *
4
+ * ## 🛑 Flat fee per slot per period, and explicitly NOT CPM
5
+ *
6
+ * Impression counting is a write per page view, which is the exact cost
7
+ * pattern that suspended this project (Root Cause #104: 3.1M ISR writes
8
+ * against a 200K allowance, 52.52 GB of Fast Origin Transfer against 10 GB,
9
+ * for eleven monthly active users). A flat fee is one write per BOOKING.
10
+ * Nothing here counts anything per render, and nothing should be added that
11
+ * does.
12
+ *
13
+ * ## Why a PERIOD rather than an arbitrary date range
14
+ *
15
+ * The plan's requirement is slot-availability locking — two advertisers must
16
+ * not book the same slot for overlapping dates. Firestore has no range
17
+ * constraint, so an arbitrary `startAt`/`endAt` pair can only be checked by
18
+ * QUERYING for overlaps and then writing, and two concurrent bookings both
19
+ * read "no overlap" and both write. That race is invisible in testing and
20
+ * sells the same slot twice.
21
+ *
22
+ * Discretising to a period makes the conflict a DOCUMENT COLLISION instead:
23
+ * the booking id is derived from `(placementId, period)`, so the second
24
+ * writer fails on an existing document inside its own transaction and
25
+ * Firestore does the locking. There is no query to race against.
26
+ *
27
+ * It also matches what is being sold. "The homepage banner for November" is
28
+ * the product; "the homepage banner from the 9th to the 23rd" is a pricing
29
+ * model nobody asked for and an availability calendar nobody can render.
30
+ */
31
+ import type { BaseDocument } from "../../../_internal/shared/types/base-document";
32
+ export declare const AD_BOOKING_COLLECTION = "adBookings";
33
+ /**
34
+ * A calendar month, `YYYY-MM`.
35
+ *
36
+ * 🛑 A STRING, not a Date. It is an identity — half of the booking's primary
37
+ * key — and a Date would make "the same month" a comparison rather than an
38
+ * equality, which is precisely what the document-collision lock depends on
39
+ * not being.
40
+ */
41
+ export type AdPeriod = string;
42
+ export declare function isAdPeriod(value: string): value is AdPeriod;
43
+ /** The period a date falls in, in UTC. */
44
+ export declare function adPeriodOf(date: Date): AdPeriod;
45
+ /** First instant of a period, UTC. */
46
+ export declare function adPeriodStart(period: AdPeriod): Date;
47
+ /** First instant of the NEXT period — the exclusive end. */
48
+ export declare function adPeriodEnd(period: AdPeriod): Date;
49
+ /**
50
+ * 🛑 The booking id IS the lock. Derived, never generated.
51
+ *
52
+ * Two advertisers booking `banner-home` for `2026-11` compute the same id and
53
+ * the second `tx.create` throws `ALREADY_EXISTS` — which is the whole
54
+ * availability guarantee, enforced by Firestore rather than by a check
55
+ * somebody could forget to run.
56
+ */
57
+ export declare function adBookingId(placementId: string, period: AdPeriod): string;
58
+ /**
59
+ * Payment state. Deliberately coarse: this records whether the slot is PAID
60
+ * FOR, not how. The invoice and the ledger posting are Part 4's job and carry
61
+ * the detail; duplicating any of it here would be two records of one fact.
62
+ */
63
+ export declare const AD_BOOKING_PAYMENT_STATES: readonly ["unpaid", "paid", "refunded"];
64
+ export type AdBookingPaymentState = (typeof AD_BOOKING_PAYMENT_STATES)[number];
65
+ /**
66
+ * Creative moderation. **Nothing renders on the site until `approved`.**
67
+ *
68
+ * 🛑 `pending` is the initial value and there is no way to write `approved`
69
+ * through the advertiser's own schema — see `adBookingWriteSchema`. A
70
+ * self-serve flow where the submitter can set their own moderation state is
71
+ * not moderated; it is a form with an extra field (Root Cause #76 — a field
72
+ * the form can send is a field the form can destroy, here inverted into a
73
+ * field the form can grant itself).
74
+ */
75
+ export declare const AD_MODERATION_STATES: readonly ["pending", "approved", "rejected"];
76
+ export type AdModerationState = (typeof AD_MODERATION_STATES)[number];
77
+ export interface AdBookingCreative {
78
+ title: string;
79
+ body?: string;
80
+ imageUrl?: string;
81
+ ctaLabel?: string;
82
+ ctaHref?: string;
83
+ }
84
+ export interface AdBookingDocument extends BaseDocument {
85
+ /** Matches a `SiteSettingsAdPlacement.id`. */
86
+ placementId: string;
87
+ period: AdPeriod;
88
+ /** Auth uid of the advertiser. */
89
+ advertiserUid: string;
90
+ /** Denormalised for the admin queue — a moderator should not fan out to `users`. */
91
+ advertiserName?: string;
92
+ /**
93
+ * Rupees, SNAPSHOTTED at booking.
94
+ *
95
+ * 🛑 Never recomputed from the live rate card. The rate is a price the
96
+ * advertiser agreed to; re-deriving it at render or invoice time would
97
+ * silently reprice a sold slot the first time an admin edits the card —
98
+ * the same rule `sourceContext` follows for order provenance.
99
+ */
100
+ priceRs: number;
101
+ paymentState: AdBookingPaymentState;
102
+ /** Set by the Part 4 invoicing path once the booking is billed. */
103
+ invoiceId?: string;
104
+ creative: AdBookingCreative;
105
+ moderation: {
106
+ state: AdModerationState;
107
+ /** Required on a rejection — see `moderateAdCreative`. */
108
+ note?: string;
109
+ reviewedAt?: Date;
110
+ /**
111
+ * Staff uid. 🛑 Never returned to the advertiser: who rejected you is
112
+ * not information a self-serve submitter needs, and naming an individual
113
+ * moderator invites them being contacted directly.
114
+ */
115
+ reviewedBy?: string;
116
+ };
117
+ /** Set when an admin or the advertiser cancels. A cancelled booking frees nothing — see below. */
118
+ cancelledAt?: Date;
119
+ cancelledReason?: string;
120
+ }
121
+ /**
122
+ * Does this booking put a creative on the page right now?
123
+ *
124
+ * 🛑 All four conditions, and the order is not an accident — moderation is
125
+ * checked before the calendar so an approved-but-future booking and an
126
+ * unreviewed current one are distinguishable in a debugger.
127
+ */
128
+ export declare function isAdBookingLive(booking: Pick<AdBookingDocument, "moderation" | "paymentState" | "period" | "cancelledAt">, now?: Date): boolean;
129
+ /**
130
+ * 🛑 A cancelled booking KEEPS its document, and therefore keeps the slot
131
+ * locked for its own period.
132
+ *
133
+ * Deleting it would free the slot — which sounds like the point and is the
134
+ * wrong behaviour twice over: the advertiser has paid for a period that has
135
+ * possibly already started, and re-selling a month mid-flight means two
136
+ * creatives were live in one slot at different times with one invoice
137
+ * between them. Freeing a period is an ADMIN act (`releaseAdSlot`), done
138
+ * knowingly, not a side effect of a cancel button.
139
+ */
140
+ export declare const AD_BOOKING_CANCELLED_KEEPS_SLOT = true;