@mohasinac/appkit 3.0.4 → 3.1.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.
- package/dist/_internal/client/features/lottery/LotteryAdminEditView.d.ts +42 -0
- package/dist/_internal/client/features/lottery/LotteryAdminEditView.js +86 -0
- package/dist/_internal/client/features/lottery/LotteryAdminSlotView.d.ts +14 -0
- package/dist/_internal/client/features/lottery/LotteryAdminSlotView.js +46 -0
- package/dist/_internal/client/features/lottery/LotteryDetailView.d.ts +28 -0
- package/dist/_internal/client/features/lottery/LotteryDetailView.js +17 -0
- package/dist/_internal/client/features/lottery/LotteryEntriesView.d.ts +23 -0
- package/dist/_internal/client/features/lottery/LotteryEntriesView.js +58 -0
- package/dist/_internal/client/features/lottery/LotteryListView.d.ts +21 -0
- package/dist/_internal/client/features/lottery/LotteryListView.js +25 -0
- package/dist/_internal/client/features/lottery/LotteryPullForm.d.ts +19 -0
- package/dist/_internal/client/features/lottery/LotteryPullForm.js +65 -0
- package/dist/_internal/client/features/lottery/LotterySlotGrid.d.ts +13 -0
- package/dist/_internal/client/features/lottery/LotterySlotGrid.js +21 -0
- package/dist/_internal/client/features/lottery/PrizeDrawLotteryDetailView.d.ts +28 -0
- package/dist/_internal/client/features/lottery/PrizeDrawLotteryDetailView.js +18 -0
- package/dist/_internal/server/features/auctions/__tests__/service.test.d.ts +1 -0
- package/dist/_internal/server/features/auctions/__tests__/service.test.js +140 -0
- package/dist/_internal/server/features/auctions/data.d.ts +2 -4
- package/dist/_internal/server/features/auctions/data.js +3 -9
- package/dist/_internal/server/features/checkout/__tests__/actions.test.d.ts +1 -0
- package/dist/_internal/server/features/checkout/__tests__/actions.test.js +600 -0
- package/dist/_internal/server/features/classified/adapters.d.ts +2 -15
- package/dist/_internal/server/features/classified/adapters.js +2 -17
- package/dist/_internal/server/features/classified/data.d.ts +1 -6
- package/dist/_internal/server/features/classified/data.js +2 -10
- package/dist/_internal/server/features/digital-code/adapters.d.ts +2 -15
- package/dist/_internal/server/features/digital-code/adapters.js +2 -17
- package/dist/_internal/server/features/digital-code/data.d.ts +1 -6
- package/dist/_internal/server/features/digital-code/data.js +2 -10
- package/dist/_internal/server/features/live/adapters.d.ts +2 -15
- package/dist/_internal/server/features/live/adapters.js +2 -17
- package/dist/_internal/server/features/live/data.d.ts +1 -6
- package/dist/_internal/server/features/live/data.js +2 -10
- package/dist/_internal/server/features/lottery/actions.d.ts +43 -0
- package/dist/_internal/server/features/lottery/actions.js +243 -0
- package/dist/_internal/server/features/lottery/adapters.d.ts +9 -0
- package/dist/_internal/server/features/lottery/adapters.js +21 -0
- package/dist/_internal/server/features/lottery/data.d.ts +20 -0
- package/dist/_internal/server/features/lottery/data.js +41 -0
- package/dist/_internal/server/features/lottery/metadata.d.ts +6 -0
- package/dist/_internal/server/features/lottery/metadata.js +31 -0
- package/dist/_internal/server/features/pre-orders/data.d.ts +2 -4
- package/dist/_internal/server/features/pre-orders/data.js +3 -9
- package/dist/_internal/server/features/prize-draws/actions.d.ts +2 -0
- package/dist/_internal/server/features/prize-draws/actions.js +22 -0
- package/dist/_internal/server/features/prize-draws/data.d.ts +1 -17
- package/dist/_internal/server/features/prize-draws/data.js +2 -20
- package/dist/_internal/server/features/prize-draws/index.d.ts +3 -1
- package/dist/_internal/server/features/prize-draws/index.js +2 -0
- package/dist/_internal/server/features/prize-draws/service.d.ts +3 -0
- package/dist/_internal/server/features/prize-draws/service.js +19 -0
- package/dist/_internal/server/features/refunds/__tests__/actions.test.d.ts +1 -0
- package/dist/_internal/server/features/refunds/__tests__/actions.test.js +263 -0
- package/dist/_internal/server/features/shared/listing-adapters.d.ts +19 -0
- package/dist/_internal/server/features/shared/listing-adapters.js +20 -0
- package/dist/_internal/server/features/shared/listing-data-factory.d.ts +9 -0
- package/dist/_internal/server/features/shared/listing-data-factory.js +33 -0
- package/dist/_internal/server/features/stores/data.d.ts +3 -14
- package/dist/_internal/server/features/stores/data.js +6 -44
- package/dist/_internal/server/jobs/core/__tests__/auctionSettlement.test.d.ts +1 -0
- package/dist/_internal/server/jobs/core/__tests__/auctionSettlement.test.js +249 -0
- package/dist/_internal/server/jobs/core/__tests__/onBidPlaced.test.d.ts +1 -0
- package/dist/_internal/server/jobs/core/__tests__/onBidPlaced.test.js +201 -0
- package/dist/_internal/server/jobs/core/__tests__/onOrderCreate.test.d.ts +1 -0
- package/dist/_internal/server/jobs/core/__tests__/onOrderCreate.test.js +169 -0
- package/dist/_internal/server/jobs/core/__tests__/onOrderStatusChange.test.d.ts +1 -0
- package/dist/_internal/server/jobs/core/__tests__/onOrderStatusChange.test.js +148 -0
- package/dist/_internal/server/jobs/core/__tests__/onProductStockChange.test.d.ts +1 -0
- package/dist/_internal/server/jobs/core/__tests__/onProductStockChange.test.js +210 -0
- package/dist/_internal/server/jobs/core/__tests__/onReviewWrite.test.d.ts +1 -0
- package/dist/_internal/server/jobs/core/__tests__/onReviewWrite.test.js +190 -0
- package/dist/_internal/server/jobs/core/__tests__/onUserBanChange.test.d.ts +1 -0
- package/dist/_internal/server/jobs/core/__tests__/onUserBanChange.test.js +161 -0
- package/dist/_internal/server/jobs/core/__tests__/payoutBatch.test.d.ts +1 -0
- package/dist/_internal/server/jobs/core/__tests__/payoutBatch.test.js +302 -0
- package/dist/_internal/server/jobs/core/__tests__/triggerEventRaffle.test.d.ts +1 -0
- package/dist/_internal/server/jobs/core/__tests__/triggerEventRaffle.test.js +252 -0
- package/dist/_internal/server/jobs/core/__tests__/wrapJobHandler.test.d.ts +1 -0
- package/dist/_internal/server/jobs/core/__tests__/wrapJobHandler.test.js +129 -0
- package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
- package/dist/_internal/shared/actions/action-registry.js +46 -0
- package/dist/_internal/shared/features/cart/schema.d.ts +8 -8
- package/dist/_internal/shared/features/cart/schema.js +3 -0
- package/dist/_internal/shared/features/products/schema.d.ts +8 -8
- package/dist/_internal/shared/listing-types/_registry.js +2 -0
- package/dist/_internal/shared/listing-types/auction/schema.d.ts +3 -1
- package/dist/_internal/shared/listing-types/auction/schema.js +7 -1
- package/dist/_internal/shared/listing-types/classified/schema.d.ts +2 -1
- package/dist/_internal/shared/listing-types/classified/schema.js +3 -1
- package/dist/_internal/shared/listing-types/digital-code/schema.d.ts +3 -1
- package/dist/_internal/shared/listing-types/digital-code/schema.js +7 -1
- package/dist/_internal/shared/listing-types/live/schema.d.ts +2 -1
- package/dist/_internal/shared/listing-types/live/schema.js +3 -1
- package/dist/_internal/shared/listing-types/pre-order/schema.d.ts +3 -1
- package/dist/_internal/shared/listing-types/pre-order/schema.js +7 -1
- package/dist/_internal/shared/listing-types/prize-draw/schema.d.ts +3 -1
- package/dist/_internal/shared/listing-types/prize-draw/schema.js +13 -1
- package/dist/_internal/shared/listing-types/standard/schema.d.ts +2 -1
- package/dist/_internal/shared/listing-types/standard/schema.js +4 -1
- package/dist/_internal/shared/types/base-document.d.ts +15 -0
- package/dist/_internal/shared/types/base-document.js +1 -0
- package/dist/_internal/shared/types/index.d.ts +2 -0
- package/dist/_internal/shared/types/index.js +1 -0
- package/dist/client.d.ts +13 -4
- package/dist/client.js +11 -2
- package/dist/constants/api-endpoints.d.ts +12 -0
- package/dist/constants/api-endpoints.js +4 -0
- package/dist/constants/field-names.d.ts +5 -1
- package/dist/constants/field-names.js +5 -1
- package/dist/features/addresses/repository/__tests__/addresses.repository.test.d.ts +1 -0
- package/dist/features/addresses/repository/__tests__/addresses.repository.test.js +386 -0
- package/dist/features/addresses/schemas/firestore.d.ts +2 -4
- package/dist/features/admin/api/bids/route.d.ts +2 -2
- package/dist/features/admin/api/coupons/route.d.ts +2 -2
- package/dist/features/admin/api/products/route.d.ts +2 -2
- package/dist/features/admin/api/reviews/route.d.ts +2 -2
- package/dist/features/admin/components/AdminFulfillmentView.d.ts +6 -0
- package/dist/features/admin/components/AdminFulfillmentView.js +107 -0
- package/dist/features/admin/components/AdminProductEditorView.js +21 -9
- package/dist/features/admin/components/AdminProductsView.js +3 -0
- package/dist/features/admin/components/DataListingView.d.ts +1 -0
- package/dist/features/admin/components/index.d.ts +2 -0
- package/dist/features/admin/components/index.js +1 -0
- package/dist/features/admin/repository/__tests__/notification.repository.test.d.ts +1 -0
- package/dist/features/admin/repository/__tests__/notification.repository.test.js +356 -0
- package/dist/features/admin/repository/__tests__/site-settings.repository.test.d.ts +1 -0
- package/dist/features/admin/repository/__tests__/site-settings.repository.test.js +298 -0
- package/dist/features/admin/schemas/firestore.d.ts +3 -8
- package/dist/features/auctions/repository/__tests__/bid.repository.test.d.ts +1 -0
- package/dist/features/auctions/repository/__tests__/bid.repository.test.js +290 -0
- package/dist/features/auctions/schemas/firestore.d.ts +2 -4
- package/dist/features/auctions/schemas/index.d.ts +2 -2
- package/dist/features/auth/api/route.d.ts +2 -2
- package/dist/features/auth/repository/__tests__/session.repository.test.d.ts +1 -0
- package/dist/features/auth/repository/__tests__/session.repository.test.js +310 -0
- package/dist/features/auth/repository/__tests__/session.test.d.ts +1 -0
- package/dist/features/auth/repository/__tests__/session.test.js +146 -0
- package/dist/features/auth/repository/__tests__/sms-counter.repository.test.d.ts +1 -0
- package/dist/features/auth/repository/__tests__/sms-counter.repository.test.js +171 -0
- package/dist/features/auth/repository/__tests__/sms-counter.test.d.ts +1 -0
- package/dist/features/auth/repository/__tests__/sms-counter.test.js +88 -0
- package/dist/features/auth/repository/__tests__/token.repository.test.d.ts +1 -0
- package/dist/features/auth/repository/__tests__/token.repository.test.js +260 -0
- package/dist/features/auth/repository/__tests__/token.test.d.ts +1 -0
- package/dist/features/auth/repository/__tests__/token.test.js +140 -0
- package/dist/features/auth/repository/__tests__/user.repository.test.d.ts +1 -0
- package/dist/features/auth/repository/__tests__/user.repository.test.js +352 -0
- package/dist/features/auth/repository/__tests__/user.test.d.ts +1 -0
- package/dist/features/auth/repository/__tests__/user.test.js +226 -0
- package/dist/features/auth/repository/session.repository.js +10 -1
- package/dist/features/before-after/schemas/index.d.ts +2 -2
- package/dist/features/blog/schemas/firestore.d.ts +2 -4
- package/dist/features/blog/schemas/index.d.ts +4 -4
- package/dist/features/cart/repository/__tests__/cart.repository.test.d.ts +1 -0
- package/dist/features/cart/repository/__tests__/cart.repository.test.js +371 -0
- package/dist/features/cart/repository/cart.repository.js +2 -2
- package/dist/features/cart/schemas/firestore.d.ts +2 -4
- package/dist/features/categories/api/[id]/route.d.ts +4 -4
- package/dist/features/categories/api/route.d.ts +2 -2
- package/dist/features/categories/repository/__tests__/categories.repository.test.d.ts +1 -0
- package/dist/features/categories/repository/__tests__/categories.repository.test.js +813 -0
- package/dist/features/categories/schemas/firestore.d.ts +2 -4
- package/dist/features/categories/schemas/index.d.ts +4 -4
- package/dist/features/events/components/EventCard.js +1 -0
- package/dist/features/events/repository/__tests__/event.repository.test.d.ts +1 -0
- package/dist/features/events/repository/__tests__/event.repository.test.js +299 -0
- package/dist/features/events/schemas/firestore.d.ts +5 -4
- package/dist/features/events/schemas/index.d.ts +836 -16
- package/dist/features/events/schemas/index.js +80 -1
- package/dist/features/events/types/index.d.ts +4 -1
- package/dist/features/faq/repository/__tests__/faqs.repository.test.d.ts +1 -0
- package/dist/features/faq/repository/__tests__/faqs.repository.test.js +311 -0
- package/dist/features/faq/schemas/firestore.d.ts +2 -4
- package/dist/features/faq/schemas/index.d.ts +2 -2
- package/dist/features/grouped/schemas/index.d.ts +2 -2
- package/dist/features/history/repository/__tests__/user-history.repository.test.d.ts +1 -0
- package/dist/features/history/repository/__tests__/user-history.repository.test.js +180 -0
- package/dist/features/homepage/api/[id]/route.d.ts +4 -4
- package/dist/features/homepage/api/carousel/[id]/route.d.ts +4 -4
- package/dist/features/homepage/api/carousel/route.d.ts +2 -2
- package/dist/features/homepage/api/route.d.ts +2 -2
- package/dist/features/homepage/repository/__tests__/carousel.repository.test.d.ts +1 -0
- package/dist/features/homepage/repository/__tests__/carousel.repository.test.js +182 -0
- package/dist/features/homepage/repository/__tests__/homepage-sections.repository.test.d.ts +1 -0
- package/dist/features/homepage/repository/__tests__/homepage-sections.repository.test.js +185 -0
- package/dist/features/homepage/schemas/firestore.d.ts +4 -12
- package/dist/features/homepage/schemas/index.d.ts +2 -2
- package/dist/features/lottery/repository/lottery-entry.repository.d.ts +33 -0
- package/dist/features/lottery/repository/lottery-entry.repository.js +130 -0
- package/dist/features/lottery/schemas/firestore.d.ts +49 -0
- package/dist/features/lottery/schemas/firestore.js +25 -0
- package/dist/features/lottery/schemas/zod.d.ts +113 -0
- package/dist/features/lottery/schemas/zod.js +39 -0
- package/dist/features/lottery/types/index.d.ts +67 -0
- package/dist/features/lottery/types/index.js +55 -0
- package/dist/features/messages/repository/__tests__/conversations.repository.test.d.ts +1 -0
- package/dist/features/messages/repository/__tests__/conversations.repository.test.js +257 -0
- package/dist/features/messages/schemas/firestore.d.ts +2 -4
- package/dist/features/messages/schemas/index.d.ts +2 -2
- package/dist/features/orders/repository/__tests__/orders.repository.test.d.ts +1 -0
- package/dist/features/orders/repository/__tests__/orders.repository.test.js +211 -0
- package/dist/features/orders/repository/orders.repository.d.ts +5 -0
- package/dist/features/orders/repository/orders.repository.js +26 -0
- package/dist/features/orders/schemas/firestore.d.ts +9 -5
- package/dist/features/orders/schemas/firestore.js +3 -0
- package/dist/features/payments/repository/__tests__/payout.repository.test.d.ts +1 -0
- package/dist/features/payments/repository/__tests__/payout.repository.test.js +292 -0
- package/dist/features/payments/schemas/firestore.d.ts +2 -4
- package/dist/features/pre-orders/schemas/index.d.ts +2 -2
- package/dist/features/products/api/[id]/route.d.ts +4 -4
- package/dist/features/products/api/route.d.ts +2 -2
- package/dist/features/products/constants/action-defs.d.ts +16 -0
- package/dist/features/products/constants/action-defs.js +16 -0
- package/dist/features/products/constants/listing-tabs.d.ts +48 -0
- package/dist/features/products/constants/listing-tabs.js +12 -0
- package/dist/features/products/repository/__tests__/product-features.repository.test.d.ts +1 -0
- package/dist/features/products/repository/__tests__/product-features.repository.test.js +329 -0
- package/dist/features/products/repository/__tests__/products.repository.test.d.ts +1 -0
- package/dist/features/products/repository/__tests__/products.repository.test.js +607 -0
- package/dist/features/products/repository/products.repository.d.ts +37 -0
- package/dist/features/products/repository/products.repository.js +28 -1
- package/dist/features/products/schemas/firestore.d.ts +23 -7
- package/dist/features/products/schemas/firestore.js +2 -0
- package/dist/features/products/schemas/index.d.ts +18 -18
- package/dist/features/products/schemas/index.js +4 -2
- package/dist/features/products/types/index.d.ts +3 -1
- package/dist/features/promotions/repository/__tests__/claimed-coupons.repository.test.d.ts +1 -0
- package/dist/features/promotions/repository/__tests__/claimed-coupons.repository.test.js +219 -0
- package/dist/features/promotions/repository/__tests__/coupons.repository.test.d.ts +1 -0
- package/dist/features/promotions/repository/__tests__/coupons.repository.test.js +480 -0
- package/dist/features/promotions/schemas/firestore.d.ts +2 -4
- package/dist/features/promotions/schemas/index.d.ts +4 -4
- package/dist/features/reviews/api/[id]/route.d.ts +4 -4
- package/dist/features/reviews/api/route.d.ts +2 -2
- package/dist/features/reviews/repository/__tests__/reviews.repository.test.d.ts +1 -0
- package/dist/features/reviews/repository/__tests__/reviews.repository.test.js +327 -0
- package/dist/features/reviews/schemas/firestore.d.ts +2 -4
- package/dist/features/reviews/schemas/index.d.ts +2 -2
- package/dist/features/scams/repository/__tests__/scammer.repository.test.d.ts +1 -0
- package/dist/features/scams/repository/__tests__/scammer.repository.test.js +385 -0
- package/dist/features/scams/schemas/firestore.d.ts +2 -4
- package/dist/features/scams/schemas/index.d.ts +4 -4
- package/dist/features/search/repository/__tests__/search.repository.test.d.ts +1 -0
- package/dist/features/search/repository/__tests__/search.repository.test.js +369 -0
- package/dist/features/search/schemas/index.d.ts +2 -2
- package/dist/features/seller/api/coupons/route.d.ts +2 -2
- package/dist/features/seller/api/offers/route.d.ts +2 -2
- package/dist/features/seller/api/products/route.d.ts +2 -2
- package/dist/features/seller/api/store/route.d.ts +2 -2
- package/dist/features/seller/components/BarcodeField.d.ts +17 -0
- package/dist/features/seller/components/BarcodeField.js +30 -0
- package/dist/features/seller/components/FulfillmentView.d.ts +5 -0
- package/dist/features/seller/components/FulfillmentView.js +120 -0
- package/dist/features/seller/components/PrintCenterView.d.ts +3 -1
- package/dist/features/seller/components/PrintCenterView.js +52 -4
- package/dist/features/seller/components/SellerProductShell.d.ts +2 -0
- package/dist/features/seller/components/SellerProductShell.js +2 -1
- package/dist/features/seller/components/index.d.ts +4 -0
- package/dist/features/seller/components/index.js +2 -0
- package/dist/features/seller/repository/__tests__/offer.repository.test.d.ts +1 -0
- package/dist/features/seller/repository/__tests__/offer.repository.test.js +458 -0
- package/dist/features/seller/schemas/index.d.ts +2 -2
- package/dist/features/store-extensions/schemas/firestore.d.ts +12 -44
- package/dist/features/stores/components/StoreClassifiedsListing.d.ts +5 -0
- package/dist/features/stores/components/StoreClassifiedsListing.js +48 -0
- package/dist/features/stores/components/StoreClassifiedsPageView.d.ts +4 -0
- package/dist/features/stores/components/StoreClassifiedsPageView.js +20 -0
- package/dist/features/stores/components/StoreDetailLayoutView.js +23 -2
- package/dist/features/stores/components/StoreDigitalCodesListing.d.ts +5 -0
- package/dist/features/stores/components/StoreDigitalCodesListing.js +48 -0
- package/dist/features/stores/components/StoreDigitalCodesPageView.d.ts +4 -0
- package/dist/features/stores/components/StoreDigitalCodesPageView.js +20 -0
- package/dist/features/stores/components/StoreLiveItemsListing.d.ts +5 -0
- package/dist/features/stores/components/StoreLiveItemsListing.js +48 -0
- package/dist/features/stores/components/StoreLiveItemsPageView.d.ts +4 -0
- package/dist/features/stores/components/StoreLiveItemsPageView.js +20 -0
- package/dist/features/stores/components/index.d.ts +9 -0
- package/dist/features/stores/components/index.js +3 -0
- package/dist/features/stores/repository/__tests__/store.repository.test.d.ts +1 -0
- package/dist/features/stores/repository/__tests__/store.repository.test.js +261 -0
- package/dist/features/stores/schemas/firestore.d.ts +2 -4
- package/dist/features/stores/schemas/index.d.ts +4 -4
- package/dist/features/support/repository/__tests__/support.repository.test.d.ts +1 -0
- package/dist/features/support/repository/__tests__/support.repository.test.js +312 -0
- package/dist/features/support/schemas/firestore.d.ts +2 -4
- package/dist/features/support/schemas/index.d.ts +2 -2
- package/dist/features/wishlist/repository/__tests__/user-wishlist.repository.test.d.ts +1 -0
- package/dist/features/wishlist/repository/__tests__/user-wishlist.repository.test.js +139 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +17 -0
- package/dist/next/api/routeHandler.d.ts +1 -1
- package/dist/next/routing/route-map.d.ts +24 -0
- package/dist/next/routing/route-map.js +11 -0
- package/dist/repositories/index.d.ts +1 -0
- package/dist/repositories/index.js +2 -0
- package/dist/schemas/registry.d.ts +24 -24
- package/dist/security/index.d.ts +1 -1
- package/dist/security/index.js +1 -1
- package/dist/security/pii-schemas.d.ts +2 -0
- package/dist/security/pii-schemas.js +6 -0
- package/dist/seed/actions/demo-seed-actions.d.ts +1 -1
- package/dist/seed/events-seed-data.js +85 -2
- package/dist/seed/grouped-listings-seed-data.d.ts +5 -2
- package/dist/seed/index.d.ts +1 -0
- package/dist/seed/index.js +1 -0
- package/dist/seed/lottery-entries-seed-data.d.ts +2 -0
- package/dist/seed/lottery-entries-seed-data.js +108 -0
- package/dist/seed/manifest.js +1 -0
- package/dist/seed/products-preorders-seed-data.d.ts +5 -2
- package/dist/seed/products-standard-seed-data.js +8 -0
- package/dist/server-entry.d.ts +3 -0
- package/dist/server-entry.js +3 -0
- package/dist/server.d.ts +10 -4
- package/dist/server.js +6 -0
- package/dist/styles.css +1 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/utils/id-generators.d.ts +8 -0
- package/dist/utils/id-generators.js +14 -0
- package/package.json +2 -1
|
@@ -1,17 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Prize Draw data layer — OG-coverage-followup 2026-05-23.
|
|
3
|
-
*
|
|
4
|
-
* Prize draws live as products with `listingType:"prize-draw"`. This file
|
|
5
|
-
* wraps the repo call in `React.cache` so the OG renderer and any future
|
|
6
|
-
* page/generateMetadata pair share one Firestore read per request.
|
|
7
|
-
*/
|
|
8
|
-
import type { ProductDocument } from "../../../../features/products/schemas/firestore";
|
|
9
|
-
export interface PrizeDrawDataOptions {
|
|
10
|
-
_reserved?: never;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Fetch a single prize-draw product by slug or id. Returns null when the
|
|
14
|
-
* slug is empty or no matching product exists. The caller is responsible
|
|
15
|
-
* for asserting `listingType === "prize-draw"` if a strict gate is required.
|
|
16
|
-
*/
|
|
17
|
-
export declare const getPrizeDrawForDetail: (slugOrId: string, _opts?: PrizeDrawDataOptions) => Promise<ProductDocument | null>;
|
|
1
|
+
export declare const getPrizeDrawForDetail: (slugOrId: string) => Promise<import("../../../..").ProductDocument | null>;
|
|
@@ -1,20 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* Prize draws live as products with `listingType:"prize-draw"`. This file
|
|
5
|
-
* wraps the repo call in `React.cache` so the OG renderer and any future
|
|
6
|
-
* page/generateMetadata pair share one Firestore read per request.
|
|
7
|
-
*/
|
|
8
|
-
import { cache } from "react";
|
|
9
|
-
import { productRepository } from "../../../../repositories";
|
|
10
|
-
/**
|
|
11
|
-
* Fetch a single prize-draw product by slug or id. Returns null when the
|
|
12
|
-
* slug is empty or no matching product exists. The caller is responsible
|
|
13
|
-
* for asserting `listingType === "prize-draw"` if a strict gate is required.
|
|
14
|
-
*/
|
|
15
|
-
export const getPrizeDrawForDetail = cache(async (slugOrId, _opts) => {
|
|
16
|
-
void _opts;
|
|
17
|
-
if (!slugOrId)
|
|
18
|
-
return null;
|
|
19
|
-
return (await productRepository.findByIdOrSlug(slugOrId).catch(() => null)) ?? null;
|
|
20
|
-
});
|
|
1
|
+
import { makeGetListingForDetail } from "../shared/listing-data-factory";
|
|
2
|
+
export const getPrizeDrawForDetail = makeGetListingForDetail("prize-draw");
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
export { getPrizeDrawForDetail
|
|
1
|
+
export { getPrizeDrawForDetail } from "./data";
|
|
2
|
+
export { enterPrizeDrawAction } from "./actions";
|
|
3
|
+
export { assertPrizeDrawOpen } from "./service";
|
|
2
4
|
export { renderPrizeDrawOg, renderPrizeDrawOgImage, type PrizeDrawOgData, } from "./og";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ValidationError, CapacityError, ExpiredError } from "../../../shared/errors/index";
|
|
2
|
+
/** Assert the prize draw is accepting entries (published, reveal not started, slots not exhausted). */
|
|
3
|
+
export function assertPrizeDrawOpen(product) {
|
|
4
|
+
if (product.listingType !== "prize-draw") {
|
|
5
|
+
throw new ValidationError("Not a prize draw listing.");
|
|
6
|
+
}
|
|
7
|
+
if (product.status !== "published") {
|
|
8
|
+
throw new ValidationError("Prize draw is not active.");
|
|
9
|
+
}
|
|
10
|
+
const max = product.prizeMaxEntries ?? null;
|
|
11
|
+
const current = product.prizeCurrentEntries ?? 0;
|
|
12
|
+
if (typeof max === "number" && current >= max) {
|
|
13
|
+
throw new CapacityError("Prize draw is fully subscribed.");
|
|
14
|
+
}
|
|
15
|
+
const reveal = product.prizeRevealWindowStart;
|
|
16
|
+
if (reveal && new Date(reveal) <= new Date()) {
|
|
17
|
+
throw new ExpiredError("Prize draw entry window");
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
// vi.hoisted: these must be declared before vi.mock factories reference them
|
|
3
|
+
const { mockOrderFindById, mockPostRefundEvent, mockPaymentRefund, mockApplyRefundDeduction, mockCodesGet, } = vi.hoisted(() => {
|
|
4
|
+
const mockCodesQuery = {
|
|
5
|
+
where: vi.fn(),
|
|
6
|
+
limit: vi.fn(),
|
|
7
|
+
get: vi.fn(),
|
|
8
|
+
};
|
|
9
|
+
mockCodesQuery.where.mockReturnValue(mockCodesQuery);
|
|
10
|
+
mockCodesQuery.limit.mockReturnValue(mockCodesQuery);
|
|
11
|
+
return {
|
|
12
|
+
mockOrderFindById: vi.fn(),
|
|
13
|
+
mockPostRefundEvent: vi.fn(),
|
|
14
|
+
mockPaymentRefund: vi.fn(),
|
|
15
|
+
mockApplyRefundDeduction: vi.fn(),
|
|
16
|
+
mockCodesGet: mockCodesQuery.get,
|
|
17
|
+
_mockCodesQuery: mockCodesQuery,
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
// Mock appkit/server BEFORE other imports to avoid loading broken dist/client.js
|
|
21
|
+
vi.mock("@mohasinac/appkit/server", () => ({
|
|
22
|
+
wrapAction: async (fn) => {
|
|
23
|
+
try {
|
|
24
|
+
const data = await fn();
|
|
25
|
+
return { ok: true, data };
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
29
|
+
return { ok: false, error: msg };
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
isSoftBanned: vi.fn(() => false),
|
|
33
|
+
}));
|
|
34
|
+
vi.mock("../../../../../", () => ({
|
|
35
|
+
orderRepository: {
|
|
36
|
+
findById: mockOrderFindById,
|
|
37
|
+
postRefundEvent: mockPostRefundEvent,
|
|
38
|
+
},
|
|
39
|
+
}));
|
|
40
|
+
vi.mock("../../../../../contracts/registry", () => ({
|
|
41
|
+
getProviders: vi.fn(() => ({
|
|
42
|
+
payment: { refund: mockPaymentRefund },
|
|
43
|
+
})),
|
|
44
|
+
}));
|
|
45
|
+
// Mock the firebase-admin sub-module that provides getAdminDb
|
|
46
|
+
// Chain: db.collection(PRODUCTS).doc(productId).collection(CODES).where("orderId","==",orderId).limit(1).get()
|
|
47
|
+
vi.mock("../../../../../providers/db-firebase/admin", () => {
|
|
48
|
+
const mockCodesQuery = { where: vi.fn(), limit: vi.fn(), get: mockCodesGet };
|
|
49
|
+
mockCodesQuery.where.mockReturnValue(mockCodesQuery);
|
|
50
|
+
mockCodesQuery.limit.mockReturnValue(mockCodesQuery);
|
|
51
|
+
const mockCodesCollection = { where: vi.fn() };
|
|
52
|
+
mockCodesCollection.where.mockReturnValue(mockCodesQuery);
|
|
53
|
+
const mockDoc = { collection: vi.fn(() => mockCodesCollection) };
|
|
54
|
+
const mockTopCollection = { doc: vi.fn(() => mockDoc) };
|
|
55
|
+
const mockDb = { collection: vi.fn(() => mockTopCollection) };
|
|
56
|
+
return { getAdminDb: () => mockDb, getAdminAuth: vi.fn(), getAdminStorage: vi.fn() };
|
|
57
|
+
});
|
|
58
|
+
vi.mock("../../payouts/actions", () => ({
|
|
59
|
+
applyRefundDeductionAction: mockApplyRefundDeduction,
|
|
60
|
+
}));
|
|
61
|
+
vi.mock("../../../../../errors/normalize", () => ({ normalizeError: vi.fn() }));
|
|
62
|
+
vi.mock("../../../../../monitoring", () => ({
|
|
63
|
+
serverLogger: { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() },
|
|
64
|
+
}));
|
|
65
|
+
import { processRefundAction } from "../actions";
|
|
66
|
+
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
67
|
+
function makeOrder(overrides = {}) {
|
|
68
|
+
return {
|
|
69
|
+
id: "order-1",
|
|
70
|
+
storeId: "store-A",
|
|
71
|
+
totalPrice: 10000,
|
|
72
|
+
paymentMethod: "razorpay",
|
|
73
|
+
paymentId: "pay_abc123",
|
|
74
|
+
isNonRefundable: false,
|
|
75
|
+
items: [],
|
|
76
|
+
...overrides,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function refundInput(overrides = {}) {
|
|
80
|
+
return {
|
|
81
|
+
orderId: "order-1",
|
|
82
|
+
type: "partial",
|
|
83
|
+
amountInPaise: 5000,
|
|
84
|
+
reason: "damaged item",
|
|
85
|
+
confirmIrrevocable: true,
|
|
86
|
+
refundedBy: "admin-uid",
|
|
87
|
+
method: "manual",
|
|
88
|
+
...overrides,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
beforeEach(() => {
|
|
92
|
+
vi.clearAllMocks();
|
|
93
|
+
mockOrderFindById.mockResolvedValue(makeOrder());
|
|
94
|
+
mockPostRefundEvent.mockResolvedValue(undefined);
|
|
95
|
+
mockPaymentRefund.mockResolvedValue({ id: "rfnd_123" });
|
|
96
|
+
mockApplyRefundDeduction.mockResolvedValue(undefined);
|
|
97
|
+
mockCodesGet.mockResolvedValue({ empty: true, docs: [] });
|
|
98
|
+
});
|
|
99
|
+
// ─── Tests ──────────────────────────────────────────────────────────────────
|
|
100
|
+
describe("processRefundAction — validation guards", () => {
|
|
101
|
+
it("order not found → ok: false", async () => {
|
|
102
|
+
mockOrderFindById.mockResolvedValue(null);
|
|
103
|
+
const result = await processRefundAction(refundInput());
|
|
104
|
+
expect(result.ok).toBe(false);
|
|
105
|
+
expect(result.error).toMatch(/not found/i);
|
|
106
|
+
});
|
|
107
|
+
it("amount <= 0 → ok: false (validation)", async () => {
|
|
108
|
+
const result = await processRefundAction(refundInput({ amountInPaise: 0 }));
|
|
109
|
+
expect(result.ok).toBe(false);
|
|
110
|
+
});
|
|
111
|
+
it("negative amount → ok: false (validation)", async () => {
|
|
112
|
+
const result = await processRefundAction(refundInput({ amountInPaise: -100 }));
|
|
113
|
+
expect(result.ok).toBe(false);
|
|
114
|
+
});
|
|
115
|
+
it("amount > order.totalPrice → ok: false", async () => {
|
|
116
|
+
const result = await processRefundAction(refundInput({ amountInPaise: 10001 }));
|
|
117
|
+
expect(result.ok).toBe(false);
|
|
118
|
+
expect(result.error).toMatch(/exceeds/i);
|
|
119
|
+
});
|
|
120
|
+
it("amount === order.totalPrice → ok: true (full refund, not exceeds)", async () => {
|
|
121
|
+
const result = await processRefundAction(refundInput({ amountInPaise: 10000 }));
|
|
122
|
+
expect(result.ok).toBe(true);
|
|
123
|
+
});
|
|
124
|
+
it("isNonRefundable: true → ok: false", async () => {
|
|
125
|
+
mockOrderFindById.mockResolvedValue(makeOrder({ isNonRefundable: true }));
|
|
126
|
+
const result = await processRefundAction(refundInput());
|
|
127
|
+
expect(result.ok).toBe(false);
|
|
128
|
+
expect(result.error).toMatch(/non-refundable/i);
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
describe("processRefundAction — digital code guard", () => {
|
|
132
|
+
it("digital code already claimed → ok: false", async () => {
|
|
133
|
+
mockOrderFindById.mockResolvedValue(makeOrder({
|
|
134
|
+
items: [{ productId: "digital-prod-1", listingType: "digital-code" }],
|
|
135
|
+
}));
|
|
136
|
+
mockCodesGet.mockResolvedValue({
|
|
137
|
+
empty: false,
|
|
138
|
+
docs: [{ data: () => ({ status: "claimed" }) }],
|
|
139
|
+
});
|
|
140
|
+
const result = await processRefundAction(refundInput());
|
|
141
|
+
expect(result.ok).toBe(false);
|
|
142
|
+
expect(result.error).toMatch(/digital code|revealed/i);
|
|
143
|
+
});
|
|
144
|
+
it("digital code with status 'available' → refund allowed", async () => {
|
|
145
|
+
mockOrderFindById.mockResolvedValue(makeOrder({
|
|
146
|
+
items: [{ productId: "digital-prod-1", listingType: "digital-code" }],
|
|
147
|
+
}));
|
|
148
|
+
mockCodesGet.mockResolvedValue({
|
|
149
|
+
empty: false,
|
|
150
|
+
docs: [{ data: () => ({ status: "available" }) }],
|
|
151
|
+
});
|
|
152
|
+
const result = await processRefundAction(refundInput());
|
|
153
|
+
expect(result.ok).toBe(true);
|
|
154
|
+
});
|
|
155
|
+
it("no digital code items → digital code check is skipped", async () => {
|
|
156
|
+
mockOrderFindById.mockResolvedValue(makeOrder({ items: [] }));
|
|
157
|
+
const result = await processRefundAction(refundInput());
|
|
158
|
+
expect(result.ok).toBe(true);
|
|
159
|
+
expect(mockCodesGet).not.toHaveBeenCalled();
|
|
160
|
+
});
|
|
161
|
+
it("digital code collection query returns empty → refund allowed", async () => {
|
|
162
|
+
mockOrderFindById.mockResolvedValue(makeOrder({
|
|
163
|
+
items: [{ productId: "digital-prod-1", listingType: "digital-code" }],
|
|
164
|
+
}));
|
|
165
|
+
mockCodesGet.mockResolvedValue({ empty: true, docs: [] });
|
|
166
|
+
const result = await processRefundAction(refundInput());
|
|
167
|
+
expect(result.ok).toBe(true);
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
describe("processRefundAction — Razorpay path", () => {
|
|
171
|
+
it("calls payment.refund with correct paymentId and amount", async () => {
|
|
172
|
+
const result = await processRefundAction(refundInput({
|
|
173
|
+
method: "razorpay",
|
|
174
|
+
razorpayPaymentId: "pay_abc123",
|
|
175
|
+
amountInPaise: 5000,
|
|
176
|
+
}));
|
|
177
|
+
expect(result.ok).toBe(true);
|
|
178
|
+
expect(mockPaymentRefund).toHaveBeenCalledWith("pay_abc123", 5000);
|
|
179
|
+
});
|
|
180
|
+
it("Razorpay refund API failure → ok: false, postRefundEvent NOT called", async () => {
|
|
181
|
+
mockPaymentRefund.mockRejectedValue(new Error("Razorpay API error"));
|
|
182
|
+
const result = await processRefundAction(refundInput({
|
|
183
|
+
method: "razorpay",
|
|
184
|
+
razorpayPaymentId: "pay_abc123",
|
|
185
|
+
}));
|
|
186
|
+
expect(result.ok).toBe(false);
|
|
187
|
+
expect(mockPostRefundEvent).not.toHaveBeenCalled();
|
|
188
|
+
});
|
|
189
|
+
it("razorpayRefundId from provider is stored in event", async () => {
|
|
190
|
+
mockPaymentRefund.mockResolvedValue({ id: "rfnd_xyz789" });
|
|
191
|
+
await processRefundAction(refundInput({
|
|
192
|
+
method: "razorpay",
|
|
193
|
+
razorpayPaymentId: "pay_abc123",
|
|
194
|
+
}));
|
|
195
|
+
expect(mockPostRefundEvent).toHaveBeenCalledWith("order-1", expect.objectContaining({ razorpayRefundId: "rfnd_xyz789" }), expect.any(Boolean));
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
describe("processRefundAction — manual path", () => {
|
|
199
|
+
it("does NOT call payment.refund for manual refunds", async () => {
|
|
200
|
+
await processRefundAction(refundInput({ method: "manual" }));
|
|
201
|
+
expect(mockPaymentRefund).not.toHaveBeenCalled();
|
|
202
|
+
});
|
|
203
|
+
it("calls postRefundEvent without razorpayRefundId", async () => {
|
|
204
|
+
await processRefundAction(refundInput({ method: "manual" }));
|
|
205
|
+
const event = mockPostRefundEvent.mock.calls[0][1];
|
|
206
|
+
expect(event.razorpayRefundId).toBeUndefined();
|
|
207
|
+
});
|
|
208
|
+
it("stores manualTransactionId when provided", async () => {
|
|
209
|
+
await processRefundAction(refundInput({ method: "manual", manualTransactionId: "TXN123" }));
|
|
210
|
+
const event = mockPostRefundEvent.mock.calls[0][1];
|
|
211
|
+
expect(event.manualTransactionId).toBe("TXN123");
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
describe("processRefundAction — success path", () => {
|
|
215
|
+
it("calls orderRepository.postRefundEvent with correct orderId", async () => {
|
|
216
|
+
await processRefundAction(refundInput());
|
|
217
|
+
expect(mockPostRefundEvent).toHaveBeenCalledWith("order-1", expect.any(Object), expect.any(Boolean));
|
|
218
|
+
});
|
|
219
|
+
it("partial amount: isFull = false passed to postRefundEvent", async () => {
|
|
220
|
+
await processRefundAction(refundInput({ amountInPaise: 5000 }));
|
|
221
|
+
const isFull = mockPostRefundEvent.mock.calls[0][2];
|
|
222
|
+
expect(isFull).toBe(false);
|
|
223
|
+
});
|
|
224
|
+
it("full amount: isFull = true passed to postRefundEvent", async () => {
|
|
225
|
+
await processRefundAction(refundInput({ amountInPaise: 10000 }));
|
|
226
|
+
const isFull = mockPostRefundEvent.mock.calls[0][2];
|
|
227
|
+
expect(isFull).toBe(true);
|
|
228
|
+
});
|
|
229
|
+
it("returns ok: true with success: true and a refundId UUID", async () => {
|
|
230
|
+
const result = await processRefundAction(refundInput());
|
|
231
|
+
expect(result.ok).toBe(true);
|
|
232
|
+
const data = result.data;
|
|
233
|
+
expect(data.success).toBe(true);
|
|
234
|
+
expect(data.refundId).toMatch(/^[0-9a-f-]{36}$/i);
|
|
235
|
+
});
|
|
236
|
+
it("event contains reason, refundedBy, and refundedAt", async () => {
|
|
237
|
+
await processRefundAction(refundInput({ reason: "broken product", refundedBy: "admin-1" }));
|
|
238
|
+
const event = mockPostRefundEvent.mock.calls[0][1];
|
|
239
|
+
expect(event.reason).toBe("broken product");
|
|
240
|
+
expect(event.refundedBy).toBe("admin-1");
|
|
241
|
+
expect(event.refundedAt).toBeInstanceOf(Date);
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
describe("processRefundAction — payout deduction", () => {
|
|
245
|
+
it("triggers applyRefundDeductionAction when order has storeId", async () => {
|
|
246
|
+
await processRefundAction(refundInput({ amountInPaise: 5000 }));
|
|
247
|
+
expect(mockApplyRefundDeduction).toHaveBeenCalledWith(expect.objectContaining({
|
|
248
|
+
storeId: "store-A",
|
|
249
|
+
orderId: "order-1",
|
|
250
|
+
refundedAmountInPaise: 5000,
|
|
251
|
+
}));
|
|
252
|
+
});
|
|
253
|
+
it("does NOT call applyRefundDeductionAction when order has no storeId", async () => {
|
|
254
|
+
mockOrderFindById.mockResolvedValue(makeOrder({ storeId: undefined }));
|
|
255
|
+
await processRefundAction(refundInput());
|
|
256
|
+
expect(mockApplyRefundDeduction).not.toHaveBeenCalled();
|
|
257
|
+
});
|
|
258
|
+
it("deduction failure does NOT fail the refund (fire-and-forget)", async () => {
|
|
259
|
+
mockApplyRefundDeduction.mockRejectedValue(new Error("Payout service unavailable"));
|
|
260
|
+
const result = await processRefundAction(refundInput());
|
|
261
|
+
expect(result.ok).toBe(true);
|
|
262
|
+
});
|
|
263
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ProductDocument } from "../../../../features/products/schemas/firestore";
|
|
2
|
+
export interface BaseListingClientShape {
|
|
3
|
+
id: string;
|
|
4
|
+
title: string;
|
|
5
|
+
description: string;
|
|
6
|
+
price: number;
|
|
7
|
+
priceLabel: string;
|
|
8
|
+
currency: string;
|
|
9
|
+
mainImage: string | null;
|
|
10
|
+
images: string[];
|
|
11
|
+
storeId: string;
|
|
12
|
+
storeName: string | null;
|
|
13
|
+
category: string;
|
|
14
|
+
tags: string[];
|
|
15
|
+
status: ProductDocument["status"];
|
|
16
|
+
createdAt: string;
|
|
17
|
+
}
|
|
18
|
+
/** Maps the 11 shared fields from a raw Firestore ProductDocument. */
|
|
19
|
+
export declare function mapBaseListingFields(doc: ProductDocument): BaseListingClientShape;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { formatCurrency } from "../../../../utils/number.formatter";
|
|
2
|
+
/** Maps the 11 shared fields from a raw Firestore ProductDocument. */
|
|
3
|
+
export function mapBaseListingFields(doc) {
|
|
4
|
+
return {
|
|
5
|
+
id: doc.id,
|
|
6
|
+
title: doc.title,
|
|
7
|
+
description: doc.description,
|
|
8
|
+
price: doc.price,
|
|
9
|
+
priceLabel: formatCurrency(doc.price, doc.currency ?? "INR"),
|
|
10
|
+
currency: doc.currency ?? "INR",
|
|
11
|
+
mainImage: doc.mainImage || doc.images?.[0] || null,
|
|
12
|
+
images: doc.images ?? [],
|
|
13
|
+
storeId: doc.storeId,
|
|
14
|
+
storeName: doc.storeName ?? null,
|
|
15
|
+
category: doc.categorySlugs?.[0] ?? doc.category ?? "",
|
|
16
|
+
tags: doc.tags ?? [],
|
|
17
|
+
status: doc.status,
|
|
18
|
+
createdAt: doc.createdAt instanceof Date ? doc.createdAt.toISOString() : String(doc.createdAt),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ListingType } from "../../../../features/products/types";
|
|
2
|
+
import type { ProductDocument } from "../../../../features/products/schemas/firestore";
|
|
3
|
+
import type { ProductFeatureDocument } from "../../../../features/products/schemas/product-features";
|
|
4
|
+
export declare function makeGetListingForDetail(type: ListingType): (slugOrId: string) => Promise<ProductDocument | null>;
|
|
5
|
+
export declare const getProductFeaturesForStore: (storeId: string | null) => Promise<ProductFeatureDocument[]>;
|
|
6
|
+
export declare function makeGetStoreListingsInitial(type: ListingType, pageSize: number): (storeId: string, page?: number) => Promise<{
|
|
7
|
+
items: ProductDocument[];
|
|
8
|
+
total: number;
|
|
9
|
+
}>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { cache } from "react";
|
|
2
|
+
import { productRepository } from "../../../../repositories";
|
|
3
|
+
import { loadProductFeaturesForStore } from "../../../../features/products/repository/loadProductFeatures";
|
|
4
|
+
// Returns a React.cache()-wrapped fetch gated on one listing type.
|
|
5
|
+
// The guard prevents cross-type URL collisions (e.g. /auctions/classified-slug returning wrong product).
|
|
6
|
+
export function makeGetListingForDetail(type) {
|
|
7
|
+
return cache(async (slugOrId) => {
|
|
8
|
+
if (!slugOrId)
|
|
9
|
+
return null;
|
|
10
|
+
const product = await productRepository.findByIdOrSlug(slugOrId).catch(() => undefined);
|
|
11
|
+
if (!product || product.listingType !== type)
|
|
12
|
+
return null;
|
|
13
|
+
return product;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
// Product-feature badges are keyed by store, not listing type.
|
|
17
|
+
// Per-type data.ts files re-export this under a type-specific name.
|
|
18
|
+
export const getProductFeaturesForStore = cache(async (storeId) => loadProductFeaturesForStore(storeId).catch(() => []));
|
|
19
|
+
// Returns a React.cache()-wrapped function for store SSR first-page data.
|
|
20
|
+
// Export names in stores/data.ts stay identical so consumers need no changes.
|
|
21
|
+
export function makeGetStoreListingsInitial(type, pageSize) {
|
|
22
|
+
return cache(async (storeId, page = 1) => {
|
|
23
|
+
const result = await productRepository
|
|
24
|
+
.list({
|
|
25
|
+
filters: `storeId==${storeId},status==published,listingType==${type}`,
|
|
26
|
+
sorts: "-createdAt",
|
|
27
|
+
page,
|
|
28
|
+
pageSize,
|
|
29
|
+
})
|
|
30
|
+
.catch(() => null);
|
|
31
|
+
return { items: result?.items ?? [], total: result?.total ?? 0 };
|
|
32
|
+
});
|
|
33
|
+
}
|
|
@@ -1,27 +1,16 @@
|
|
|
1
1
|
import type { StoreDocument } from "../../../../features/stores/schemas/firestore";
|
|
2
|
-
import type { ProductDocument } from "../../../../features/products/schemas/firestore";
|
|
3
2
|
/** Full store document by slug — deduped per request via React.cache(). */
|
|
4
3
|
export declare const getStoreForDetail: (slug: string) => Promise<StoreDocument | null>;
|
|
5
|
-
/**
|
|
6
|
-
* Published products for a store detail page.
|
|
7
|
-
* Returns the first page used for SSR initial data.
|
|
8
|
-
*/
|
|
9
4
|
export declare const listStoreProductsInitial: (storeId: string, page?: number) => Promise<{
|
|
10
|
-
items: ProductDocument[];
|
|
5
|
+
items: import("../../../..").ProductDocument[];
|
|
11
6
|
total: number;
|
|
12
7
|
}>;
|
|
13
|
-
/**
|
|
14
|
-
* Published auctions for a store detail page.
|
|
15
|
-
*/
|
|
16
8
|
export declare const listStoreAuctionsInitial: (storeId: string, page?: number) => Promise<{
|
|
17
|
-
items: ProductDocument[];
|
|
9
|
+
items: import("../../../..").ProductDocument[];
|
|
18
10
|
total: number;
|
|
19
11
|
}>;
|
|
20
|
-
/**
|
|
21
|
-
* Published pre-orders for a store detail page.
|
|
22
|
-
*/
|
|
23
12
|
export declare const listStorePreOrdersInitial: (storeId: string, page?: number) => Promise<{
|
|
24
|
-
items: ProductDocument[];
|
|
13
|
+
items: import("../../../..").ProductDocument[];
|
|
25
14
|
total: number;
|
|
26
15
|
}>;
|
|
27
16
|
/** Stores for sitemap generation. */
|
|
@@ -1,54 +1,16 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
import { cache } from "react";
|
|
3
|
-
import { storeRepository
|
|
3
|
+
import { storeRepository } from "../../../../repositories";
|
|
4
4
|
import { STORES_PRODUCTS_PAGE_SIZE, STORES_SITEMAP_LIMIT, } from "../../../shared/features/stores/config";
|
|
5
|
+
import { makeGetStoreListingsInitial } from "../shared/listing-data-factory";
|
|
5
6
|
/** Full store document by slug — deduped per request via React.cache(). */
|
|
6
7
|
export const getStoreForDetail = cache(async (slug) => {
|
|
7
8
|
return (await storeRepository.findBySlug(slug).catch(() => undefined)) ?? null;
|
|
8
9
|
});
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export const listStoreProductsInitial = cache(async (storeId, page = 1) => {
|
|
14
|
-
const result = await productRepository
|
|
15
|
-
.list({
|
|
16
|
-
filters: `storeId==${storeId},status==published,listingType==standard`,
|
|
17
|
-
sorts: "-createdAt",
|
|
18
|
-
page,
|
|
19
|
-
pageSize: STORES_PRODUCTS_PAGE_SIZE,
|
|
20
|
-
})
|
|
21
|
-
.catch(() => null);
|
|
22
|
-
return { items: result?.items ?? [], total: result?.total ?? 0 };
|
|
23
|
-
});
|
|
24
|
-
/**
|
|
25
|
-
* Published auctions for a store detail page.
|
|
26
|
-
*/
|
|
27
|
-
export const listStoreAuctionsInitial = cache(async (storeId, page = 1) => {
|
|
28
|
-
const result = await productRepository
|
|
29
|
-
.list({
|
|
30
|
-
filters: `storeId==${storeId},status==published,listingType==auction`,
|
|
31
|
-
sorts: "-createdAt",
|
|
32
|
-
page,
|
|
33
|
-
pageSize: STORES_PRODUCTS_PAGE_SIZE,
|
|
34
|
-
})
|
|
35
|
-
.catch(() => null);
|
|
36
|
-
return { items: result?.items ?? [], total: result?.total ?? 0 };
|
|
37
|
-
});
|
|
38
|
-
/**
|
|
39
|
-
* Published pre-orders for a store detail page.
|
|
40
|
-
*/
|
|
41
|
-
export const listStorePreOrdersInitial = cache(async (storeId, page = 1) => {
|
|
42
|
-
const result = await productRepository
|
|
43
|
-
.list({
|
|
44
|
-
filters: `storeId==${storeId},status==published,listingType==pre-order`,
|
|
45
|
-
sorts: "-createdAt",
|
|
46
|
-
page,
|
|
47
|
-
pageSize: STORES_PRODUCTS_PAGE_SIZE,
|
|
48
|
-
})
|
|
49
|
-
.catch(() => null);
|
|
50
|
-
return { items: result?.items ?? [], total: result?.total ?? 0 };
|
|
51
|
-
});
|
|
10
|
+
// Collapse of three near-identical 14-line functions via factory — export names unchanged.
|
|
11
|
+
export const listStoreProductsInitial = makeGetStoreListingsInitial("standard", STORES_PRODUCTS_PAGE_SIZE);
|
|
12
|
+
export const listStoreAuctionsInitial = makeGetStoreListingsInitial("auction", STORES_PRODUCTS_PAGE_SIZE);
|
|
13
|
+
export const listStorePreOrdersInitial = makeGetStoreListingsInitial("pre-order", STORES_PRODUCTS_PAGE_SIZE);
|
|
52
14
|
/** Stores for sitemap generation. */
|
|
53
15
|
export const listSitemapStores = cache(async () => {
|
|
54
16
|
const result = await storeRepository
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|