@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
|
@@ -713,8 +713,8 @@ export declare const carouselSlideFirestoreSchema: z.ZodObject<{
|
|
|
713
713
|
createdAt: string | Date | z.objectOutputType<{
|
|
714
714
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
715
715
|
}, z.ZodTypeAny, "passthrough">;
|
|
716
|
-
id: string;
|
|
717
716
|
title: string;
|
|
717
|
+
id: string;
|
|
718
718
|
updatedAt: string | Date | z.objectOutputType<{
|
|
719
719
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
720
720
|
}, z.ZodTypeAny, "passthrough">;
|
|
@@ -822,8 +822,8 @@ export declare const carouselSlideFirestoreSchema: z.ZodObject<{
|
|
|
822
822
|
createdAt: string | Date | z.objectInputType<{
|
|
823
823
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
824
824
|
}, z.ZodTypeAny, "passthrough">;
|
|
825
|
-
id: string;
|
|
826
825
|
title: string;
|
|
826
|
+
id: string;
|
|
827
827
|
updatedAt: string | Date | z.objectInputType<{
|
|
828
828
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
829
829
|
}, z.ZodTypeAny, "passthrough">;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { FirebaseSieveFields, FirebaseSieveResult, SieveModel } from "../../../providers/db-firebase";
|
|
2
|
+
import { BaseRepository } from "../../../providers/db-firebase";
|
|
3
|
+
import { type LotteryEntryDocument } from "../schemas/firestore";
|
|
4
|
+
declare class LotteryEntryRepository extends BaseRepository<LotteryEntryDocument> {
|
|
5
|
+
static readonly SIEVE_FIELDS: FirebaseSieveFields;
|
|
6
|
+
constructor();
|
|
7
|
+
protected mapDoc<D = LotteryEntryDocument>(snap: import("../../../providers/db-firebase").DocumentSnapshot): D;
|
|
8
|
+
/**
|
|
9
|
+
* Get the next sequential userLotteryNumber for a source atomically.
|
|
10
|
+
* Returns current count + 1.
|
|
11
|
+
*/
|
|
12
|
+
nextUserLotteryNumber(sourceId: string, field: "eventId" | "productId"): Promise<number>;
|
|
13
|
+
/**
|
|
14
|
+
* Count entries for a given source and transaction ID.
|
|
15
|
+
* Used to enforce maxPullsPerTransaction.
|
|
16
|
+
*/
|
|
17
|
+
countByTransactionId(sourceId: string, sourceField: "eventId" | "productId", transactionId: string): Promise<number>;
|
|
18
|
+
/**
|
|
19
|
+
* Count entries for a given source and user.
|
|
20
|
+
* Used to enforce maxPullsPerUser.
|
|
21
|
+
*/
|
|
22
|
+
countByUser(sourceId: string, sourceField: "eventId" | "productId", userId: string): Promise<number>;
|
|
23
|
+
/** List all entries for an event/product source. Paginated via Sieve. */
|
|
24
|
+
listForSource(sourceId: string, sourceField: "eventId" | "productId", model: SieveModel): Promise<FirebaseSieveResult<LotteryEntryDocument>>;
|
|
25
|
+
/** List entries for a specific user across all sources. */
|
|
26
|
+
listForUser(userId: string, model: SieveModel): Promise<FirebaseSieveResult<LotteryEntryDocument>>;
|
|
27
|
+
/** Create a lottery entry with PII encryption. */
|
|
28
|
+
createEntry(data: Omit<LotteryEntryDocument, "id">): Promise<LotteryEntryDocument>;
|
|
29
|
+
/** Flag a lottery entry as fraudulent. */
|
|
30
|
+
flagEntry(entryId: string, flagNote: string, flaggedBy: string): Promise<LotteryEntryDocument>;
|
|
31
|
+
}
|
|
32
|
+
export { LotteryEntryRepository };
|
|
33
|
+
export declare const lotteryEntryRepository: LotteryEntryRepository;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { normalizeError } from "../../../errors/normalize";
|
|
2
|
+
import { DatabaseError } from "../../../errors";
|
|
3
|
+
import { serverLogger } from "../../../monitoring";
|
|
4
|
+
import { BaseRepository, prepareForFirestore, } from "../../../providers/db-firebase";
|
|
5
|
+
import { decryptPiiFields, encryptPiiFields, LOTTERY_ENTRY_PII_FIELDS, } from "../../../security";
|
|
6
|
+
import { LOTTERY_ENTRIES_COLLECTION, LOTTERY_ENTRY_FIELDS, } from "../schemas/firestore";
|
|
7
|
+
class LotteryEntryRepository extends BaseRepository {
|
|
8
|
+
constructor() {
|
|
9
|
+
super(LOTTERY_ENTRIES_COLLECTION);
|
|
10
|
+
}
|
|
11
|
+
mapDoc(snap) {
|
|
12
|
+
const raw = super.mapDoc(snap);
|
|
13
|
+
return decryptPiiFields(raw, [
|
|
14
|
+
...LOTTERY_ENTRY_PII_FIELDS,
|
|
15
|
+
]);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Get the next sequential userLotteryNumber for a source atomically.
|
|
19
|
+
* Returns current count + 1.
|
|
20
|
+
*/
|
|
21
|
+
async nextUserLotteryNumber(sourceId, field) {
|
|
22
|
+
try {
|
|
23
|
+
const snapshot = await this.getCollection()
|
|
24
|
+
.where(field, "==", sourceId)
|
|
25
|
+
.get();
|
|
26
|
+
return snapshot.size + 1;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
void normalizeError(error);
|
|
30
|
+
throw new DatabaseError(`Failed to get next lottery number for ${field}=${sourceId}`, error);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Count entries for a given source and transaction ID.
|
|
35
|
+
* Used to enforce maxPullsPerTransaction.
|
|
36
|
+
*/
|
|
37
|
+
async countByTransactionId(sourceId, sourceField, transactionId) {
|
|
38
|
+
try {
|
|
39
|
+
const snapshot = await this.getCollection()
|
|
40
|
+
.where(sourceField, "==", sourceId)
|
|
41
|
+
.where(LOTTERY_ENTRY_FIELDS.TRANSACTION_ID, "==", transactionId)
|
|
42
|
+
.get();
|
|
43
|
+
return snapshot.size;
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
void normalizeError(error);
|
|
47
|
+
throw new DatabaseError(`Failed to count entries for transactionId=${transactionId}`, error);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Count entries for a given source and user.
|
|
52
|
+
* Used to enforce maxPullsPerUser.
|
|
53
|
+
*/
|
|
54
|
+
async countByUser(sourceId, sourceField, userId) {
|
|
55
|
+
try {
|
|
56
|
+
const snapshot = await this.getCollection()
|
|
57
|
+
.where(sourceField, "==", sourceId)
|
|
58
|
+
.where(LOTTERY_ENTRY_FIELDS.USER_ID, "==", userId)
|
|
59
|
+
.where(LOTTERY_ENTRY_FIELDS.STATUS, "!=", "cancelled")
|
|
60
|
+
.get();
|
|
61
|
+
return snapshot.size;
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
void normalizeError(error);
|
|
65
|
+
throw new DatabaseError(`Failed to count entries for userId=${userId}`, error);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** List all entries for an event/product source. Paginated via Sieve. */
|
|
69
|
+
async listForSource(sourceId, sourceField, model) {
|
|
70
|
+
return this.sieveQuery(model, LotteryEntryRepository.SIEVE_FIELDS, {
|
|
71
|
+
baseQuery: this.getCollection().where(sourceField, "==", sourceId),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/** List entries for a specific user across all sources. */
|
|
75
|
+
async listForUser(userId, model) {
|
|
76
|
+
return this.sieveQuery(model, LotteryEntryRepository.SIEVE_FIELDS, {
|
|
77
|
+
baseQuery: this.getCollection().where(LOTTERY_ENTRY_FIELDS.USER_ID, "==", userId),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
/** Create a lottery entry with PII encryption. */
|
|
81
|
+
async createEntry(data) {
|
|
82
|
+
try {
|
|
83
|
+
const encrypted = encryptPiiFields(data, [...LOTTERY_ENTRY_PII_FIELDS]);
|
|
84
|
+
const prepared = prepareForFirestore({ ...encrypted });
|
|
85
|
+
const ref = await this.getCollection().add(prepared);
|
|
86
|
+
const created = await ref.get();
|
|
87
|
+
serverLogger.info("Lottery entry created", {
|
|
88
|
+
entryId: ref.id,
|
|
89
|
+
sourceType: data.sourceType,
|
|
90
|
+
eventId: data.eventId,
|
|
91
|
+
productId: data.productId,
|
|
92
|
+
userId: data.userId,
|
|
93
|
+
userLotteryNumber: data.userLotteryNumber,
|
|
94
|
+
});
|
|
95
|
+
return this.mapDoc(created);
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
void normalizeError(error);
|
|
99
|
+
throw new DatabaseError("Failed to create lottery entry", error);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/** Flag a lottery entry as fraudulent. */
|
|
103
|
+
async flagEntry(entryId, flagNote, flaggedBy) {
|
|
104
|
+
try {
|
|
105
|
+
await this.getCollection().doc(entryId).update(prepareForFirestore({
|
|
106
|
+
isFlagged: true,
|
|
107
|
+
flagNote,
|
|
108
|
+
flaggedBy,
|
|
109
|
+
flaggedAt: new Date(),
|
|
110
|
+
status: "flagged",
|
|
111
|
+
}));
|
|
112
|
+
return this.findByIdOrFail(entryId);
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
void normalizeError(error);
|
|
116
|
+
throw new DatabaseError(`Failed to flag lottery entry ${entryId}`, error);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
LotteryEntryRepository.SIEVE_FIELDS = {
|
|
121
|
+
sourceType: { canFilter: true, canSort: false },
|
|
122
|
+
eventId: { canFilter: true, canSort: false },
|
|
123
|
+
productId: { canFilter: true, canSort: false },
|
|
124
|
+
userId: { canFilter: true, canSort: false },
|
|
125
|
+
status: { canFilter: true, canSort: false },
|
|
126
|
+
submittedAt: { canFilter: true, canSort: true },
|
|
127
|
+
userLotteryNumber: { canFilter: false, canSort: true },
|
|
128
|
+
};
|
|
129
|
+
export { LotteryEntryRepository };
|
|
130
|
+
export const lotteryEntryRepository = new LotteryEntryRepository();
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LotteryEntry Firestore Document Type & Constants
|
|
3
|
+
*/
|
|
4
|
+
import type { LotteryEntryStatus } from "../types";
|
|
5
|
+
export declare const LOTTERY_ENTRIES_COLLECTION: "lotteryEntries";
|
|
6
|
+
export interface LotteryEntryDocument {
|
|
7
|
+
id: string;
|
|
8
|
+
sourceType: "event" | "product";
|
|
9
|
+
/** Set when sourceType === "event" */
|
|
10
|
+
eventId?: string;
|
|
11
|
+
/** Set when sourceType === "product" */
|
|
12
|
+
productId?: string;
|
|
13
|
+
userId: string;
|
|
14
|
+
userDisplayName?: string;
|
|
15
|
+
/** PII — encrypted at rest */
|
|
16
|
+
userEmail?: string;
|
|
17
|
+
/** PII — encrypted at rest; required */
|
|
18
|
+
userPhone: string;
|
|
19
|
+
/** User-provided external payment TX ID */
|
|
20
|
+
transactionId: string;
|
|
21
|
+
/** User-provided time of payment */
|
|
22
|
+
paymentTime: Date;
|
|
23
|
+
/** Slot/item number the user submitted for */
|
|
24
|
+
purchasedItemNumber: number;
|
|
25
|
+
/** Sequential per source (1, 2, 3…) — assigned atomically */
|
|
26
|
+
userLotteryNumber: number;
|
|
27
|
+
/** Filled after draw — assigned slot number */
|
|
28
|
+
assignedPrizeSlotNumber?: number;
|
|
29
|
+
status: LotteryEntryStatus;
|
|
30
|
+
isFlagged: boolean;
|
|
31
|
+
flagNote?: string;
|
|
32
|
+
flaggedBy?: string;
|
|
33
|
+
flaggedAt?: Date;
|
|
34
|
+
submittedAt: Date;
|
|
35
|
+
drawnAt?: Date;
|
|
36
|
+
}
|
|
37
|
+
export declare const LOTTERY_ENTRY_INDEXED_FIELDS: readonly ["sourceType", "eventId", "productId", "userId", "status", "submittedAt", "userLotteryNumber"];
|
|
38
|
+
/** Canonical field name constants for lotteryEntries collection — use instead of hardcoded strings. */
|
|
39
|
+
export declare const LOTTERY_ENTRY_FIELDS: {
|
|
40
|
+
readonly SOURCE_TYPE: "sourceType";
|
|
41
|
+
readonly EVENT_ID: "eventId";
|
|
42
|
+
readonly PRODUCT_ID: "productId";
|
|
43
|
+
readonly USER_ID: "userId";
|
|
44
|
+
readonly STATUS: "status";
|
|
45
|
+
readonly TRANSACTION_ID: "transactionId";
|
|
46
|
+
readonly SUBMITTED_AT: "submittedAt";
|
|
47
|
+
readonly USER_LOTTERY_NUMBER: "userLotteryNumber";
|
|
48
|
+
readonly IS_FLAGGED: "isFlagged";
|
|
49
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LotteryEntry Firestore Document Type & Constants
|
|
3
|
+
*/
|
|
4
|
+
export const LOTTERY_ENTRIES_COLLECTION = "lotteryEntries";
|
|
5
|
+
export const LOTTERY_ENTRY_INDEXED_FIELDS = [
|
|
6
|
+
"sourceType",
|
|
7
|
+
"eventId",
|
|
8
|
+
"productId",
|
|
9
|
+
"userId",
|
|
10
|
+
"status",
|
|
11
|
+
"submittedAt",
|
|
12
|
+
"userLotteryNumber",
|
|
13
|
+
];
|
|
14
|
+
/** Canonical field name constants for lotteryEntries collection — use instead of hardcoded strings. */
|
|
15
|
+
export const LOTTERY_ENTRY_FIELDS = {
|
|
16
|
+
SOURCE_TYPE: "sourceType",
|
|
17
|
+
EVENT_ID: "eventId",
|
|
18
|
+
PRODUCT_ID: "productId",
|
|
19
|
+
USER_ID: "userId",
|
|
20
|
+
STATUS: "status",
|
|
21
|
+
TRANSACTION_ID: "transactionId",
|
|
22
|
+
SUBMITTED_AT: "submittedAt",
|
|
23
|
+
USER_LOTTERY_NUMBER: "userLotteryNumber",
|
|
24
|
+
IS_FLAGGED: "isFlagged",
|
|
25
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod schemas for lottery entry submission and validation.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
export declare const lotteryEntrySubmitSchema: z.ZodObject<{
|
|
6
|
+
transactionId: z.ZodString;
|
|
7
|
+
paymentTime: z.ZodString;
|
|
8
|
+
purchasedItemNumber: z.ZodNumber;
|
|
9
|
+
userPhone: z.ZodString;
|
|
10
|
+
}, "strip", z.ZodTypeAny, {
|
|
11
|
+
transactionId: string;
|
|
12
|
+
userPhone: string;
|
|
13
|
+
paymentTime: string;
|
|
14
|
+
purchasedItemNumber: number;
|
|
15
|
+
}, {
|
|
16
|
+
transactionId: string;
|
|
17
|
+
userPhone: string;
|
|
18
|
+
paymentTime: string;
|
|
19
|
+
purchasedItemNumber: number;
|
|
20
|
+
}>;
|
|
21
|
+
export type LotteryEntrySubmitInput = z.infer<typeof lotteryEntrySubmitSchema>;
|
|
22
|
+
/** Schema for flag action */
|
|
23
|
+
export declare const flagLotteryEntrySchema: z.ZodObject<{
|
|
24
|
+
entryId: z.ZodString;
|
|
25
|
+
flagNote: z.ZodString;
|
|
26
|
+
flaggedByUserId: z.ZodString;
|
|
27
|
+
}, "strip", z.ZodTypeAny, {
|
|
28
|
+
flagNote: string;
|
|
29
|
+
entryId: string;
|
|
30
|
+
flaggedByUserId: string;
|
|
31
|
+
}, {
|
|
32
|
+
flagNote: string;
|
|
33
|
+
entryId: string;
|
|
34
|
+
flaggedByUserId: string;
|
|
35
|
+
}>;
|
|
36
|
+
export type FlagLotteryEntryInput = z.infer<typeof flagLotteryEntrySchema>;
|
|
37
|
+
/** Schema for reopen-slot action */
|
|
38
|
+
export declare const reopenLotterySlotSchema: z.ZodObject<{
|
|
39
|
+
sourceType: z.ZodEnum<["event", "product"]>;
|
|
40
|
+
sourceId: z.ZodString;
|
|
41
|
+
slotNumber: z.ZodNumber;
|
|
42
|
+
adminUserId: z.ZodString;
|
|
43
|
+
}, "strip", z.ZodTypeAny, {
|
|
44
|
+
slotNumber: number;
|
|
45
|
+
sourceType: "product" | "event";
|
|
46
|
+
sourceId: string;
|
|
47
|
+
adminUserId: string;
|
|
48
|
+
}, {
|
|
49
|
+
slotNumber: number;
|
|
50
|
+
sourceType: "product" | "event";
|
|
51
|
+
sourceId: string;
|
|
52
|
+
adminUserId: string;
|
|
53
|
+
}>;
|
|
54
|
+
export type ReopenLotterySlotInput = z.infer<typeof reopenLotterySlotSchema>;
|
|
55
|
+
/** Schema for submit lottery pull (full, server-side) */
|
|
56
|
+
export declare const submitLotteryPullSchema: z.ZodEffects<z.ZodObject<{
|
|
57
|
+
sourceType: z.ZodEnum<["event", "product"]>;
|
|
58
|
+
eventId: z.ZodOptional<z.ZodString>;
|
|
59
|
+
productId: z.ZodOptional<z.ZodString>;
|
|
60
|
+
userId: z.ZodString;
|
|
61
|
+
userDisplayName: z.ZodOptional<z.ZodString>;
|
|
62
|
+
userEmail: z.ZodOptional<z.ZodString>;
|
|
63
|
+
} & {
|
|
64
|
+
transactionId: z.ZodString;
|
|
65
|
+
paymentTime: z.ZodString;
|
|
66
|
+
purchasedItemNumber: z.ZodNumber;
|
|
67
|
+
userPhone: z.ZodString;
|
|
68
|
+
}, "strip", z.ZodTypeAny, {
|
|
69
|
+
userId: string;
|
|
70
|
+
transactionId: string;
|
|
71
|
+
userPhone: string;
|
|
72
|
+
sourceType: "product" | "event";
|
|
73
|
+
paymentTime: string;
|
|
74
|
+
purchasedItemNumber: number;
|
|
75
|
+
productId?: string | undefined;
|
|
76
|
+
userEmail?: string | undefined;
|
|
77
|
+
userDisplayName?: string | undefined;
|
|
78
|
+
eventId?: string | undefined;
|
|
79
|
+
}, {
|
|
80
|
+
userId: string;
|
|
81
|
+
transactionId: string;
|
|
82
|
+
userPhone: string;
|
|
83
|
+
sourceType: "product" | "event";
|
|
84
|
+
paymentTime: string;
|
|
85
|
+
purchasedItemNumber: number;
|
|
86
|
+
productId?: string | undefined;
|
|
87
|
+
userEmail?: string | undefined;
|
|
88
|
+
userDisplayName?: string | undefined;
|
|
89
|
+
eventId?: string | undefined;
|
|
90
|
+
}>, {
|
|
91
|
+
userId: string;
|
|
92
|
+
transactionId: string;
|
|
93
|
+
userPhone: string;
|
|
94
|
+
sourceType: "product" | "event";
|
|
95
|
+
paymentTime: string;
|
|
96
|
+
purchasedItemNumber: number;
|
|
97
|
+
productId?: string | undefined;
|
|
98
|
+
userEmail?: string | undefined;
|
|
99
|
+
userDisplayName?: string | undefined;
|
|
100
|
+
eventId?: string | undefined;
|
|
101
|
+
}, {
|
|
102
|
+
userId: string;
|
|
103
|
+
transactionId: string;
|
|
104
|
+
userPhone: string;
|
|
105
|
+
sourceType: "product" | "event";
|
|
106
|
+
paymentTime: string;
|
|
107
|
+
purchasedItemNumber: number;
|
|
108
|
+
productId?: string | undefined;
|
|
109
|
+
userEmail?: string | undefined;
|
|
110
|
+
userDisplayName?: string | undefined;
|
|
111
|
+
eventId?: string | undefined;
|
|
112
|
+
}>;
|
|
113
|
+
export type SubmitLotteryPullInput = z.infer<typeof submitLotteryPullSchema>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod schemas for lottery entry submission and validation.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
export const lotteryEntrySubmitSchema = z.object({
|
|
6
|
+
transactionId: z.string().min(4, "Transaction ID must be at least 4 characters"),
|
|
7
|
+
paymentTime: z.string().datetime({ message: "Payment time must be a valid ISO datetime" }),
|
|
8
|
+
purchasedItemNumber: z.number().int().min(1, "Item number must be at least 1"),
|
|
9
|
+
userPhone: z
|
|
10
|
+
.string()
|
|
11
|
+
.min(10, "Phone number must be at least 10 digits")
|
|
12
|
+
.regex(/^\+?[\d\s\-()]{10,}$/, "Enter a valid phone number"),
|
|
13
|
+
});
|
|
14
|
+
/** Schema for flag action */
|
|
15
|
+
export const flagLotteryEntrySchema = z.object({
|
|
16
|
+
entryId: z.string().min(1),
|
|
17
|
+
flagNote: z.string().min(1, "Flag note is required"),
|
|
18
|
+
flaggedByUserId: z.string().min(1),
|
|
19
|
+
});
|
|
20
|
+
/** Schema for reopen-slot action */
|
|
21
|
+
export const reopenLotterySlotSchema = z.object({
|
|
22
|
+
sourceType: z.enum(["event", "product"]),
|
|
23
|
+
sourceId: z.string().min(1),
|
|
24
|
+
slotNumber: z.number().int().min(1),
|
|
25
|
+
adminUserId: z.string().min(1),
|
|
26
|
+
});
|
|
27
|
+
/** Schema for submit lottery pull (full, server-side) */
|
|
28
|
+
export const submitLotteryPullSchema = z
|
|
29
|
+
.object({
|
|
30
|
+
sourceType: z.enum(["event", "product"]),
|
|
31
|
+
eventId: z.string().optional(),
|
|
32
|
+
productId: z.string().optional(),
|
|
33
|
+
userId: z.string().min(1),
|
|
34
|
+
userDisplayName: z.string().optional(),
|
|
35
|
+
userEmail: z.string().email().optional(),
|
|
36
|
+
})
|
|
37
|
+
.merge(lotteryEntrySubmitSchema)
|
|
38
|
+
.refine((data) => (data.sourceType === "event" && !!data.eventId) ||
|
|
39
|
+
(data.sourceType === "product" && !!data.productId), { message: "eventId or productId must be provided matching sourceType" });
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lottery feature shared types
|
|
3
|
+
*
|
|
4
|
+
* Used by both event-type lottery and prize-draw-mode lottery.
|
|
5
|
+
* Weight + price fields are server-only — never sent to client consumers.
|
|
6
|
+
*/
|
|
7
|
+
export interface LotterySlot {
|
|
8
|
+
slotNumber: number;
|
|
9
|
+
name: string;
|
|
10
|
+
priceInPaise: number;
|
|
11
|
+
weight: number;
|
|
12
|
+
isBooked: boolean;
|
|
13
|
+
bookedByUserLotteryNumber?: number;
|
|
14
|
+
bookedByUserId?: string;
|
|
15
|
+
bookedByDisplayName?: string;
|
|
16
|
+
}
|
|
17
|
+
/** Slot shape safe to expose to clients — price and weight stripped by adapter. */
|
|
18
|
+
export interface ClientLotterySlot {
|
|
19
|
+
slotNumber: number;
|
|
20
|
+
name: string;
|
|
21
|
+
isBooked: boolean;
|
|
22
|
+
bookedByUserLotteryNumber?: number;
|
|
23
|
+
bookedByDisplayName?: string;
|
|
24
|
+
}
|
|
25
|
+
export type LotteryPricingMode = "uniform" | "variable";
|
|
26
|
+
export interface LotteryConfig {
|
|
27
|
+
slots: LotterySlot[];
|
|
28
|
+
totalSlots: number;
|
|
29
|
+
pricingMode: LotteryPricingMode;
|
|
30
|
+
uniformPriceInPaise?: number;
|
|
31
|
+
drawWindowDurationMinutes: number;
|
|
32
|
+
maxPullsPerTransaction: number;
|
|
33
|
+
maxPullsPerUser: number;
|
|
34
|
+
}
|
|
35
|
+
/** Client-safe config shape — slots have price/weight stripped. */
|
|
36
|
+
export interface ClientLotteryConfig {
|
|
37
|
+
slots: ClientLotterySlot[];
|
|
38
|
+
totalSlots: number;
|
|
39
|
+
pricingMode: LotteryPricingMode;
|
|
40
|
+
drawWindowDurationMinutes: number;
|
|
41
|
+
maxPullsPerTransaction: number;
|
|
42
|
+
maxPullsPerUser: number;
|
|
43
|
+
}
|
|
44
|
+
export type LotteryEntryStatus = "pending" | "drawn" | "won" | "flagged" | "cancelled";
|
|
45
|
+
/** Error codes thrown by lottery actions */
|
|
46
|
+
export type LotteryErrorCode = "LOTTERY_FULL" | "LOTTERY_WINDOW_CLOSED" | "USER_LIMIT_REACHED" | "TX_ALREADY_USED" | "SLOT_NOT_FOUND" | "ENTRY_NOT_FLAGGED";
|
|
47
|
+
export declare class LotteryError extends Error {
|
|
48
|
+
readonly code: LotteryErrorCode;
|
|
49
|
+
constructor(code: LotteryErrorCode, message: string);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Compute the weight for a slot given its price.
|
|
53
|
+
* Lower price → higher weight → more likely to be selected.
|
|
54
|
+
* Weight is always at least 1 (never 0).
|
|
55
|
+
* For uniform pricing: all slots get weight 50.
|
|
56
|
+
*/
|
|
57
|
+
export declare function computeWeight(priceInPaise: number, maxPriceInPaise: number): number;
|
|
58
|
+
/**
|
|
59
|
+
* Pick a slot using weighted random selection.
|
|
60
|
+
* @throws {LotteryError} LOTTERY_FULL when unclaimed is empty.
|
|
61
|
+
*/
|
|
62
|
+
export declare function pickWeightedSlot(unclaimed: LotterySlot[]): LotterySlot;
|
|
63
|
+
/**
|
|
64
|
+
* Assign weights to slots based on pricing mode.
|
|
65
|
+
* Returns a new array with weight populated on every slot.
|
|
66
|
+
*/
|
|
67
|
+
export declare function assignSlotWeights(config: LotteryConfig): LotterySlot[];
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lottery feature shared types
|
|
3
|
+
*
|
|
4
|
+
* Used by both event-type lottery and prize-draw-mode lottery.
|
|
5
|
+
* Weight + price fields are server-only — never sent to client consumers.
|
|
6
|
+
*/
|
|
7
|
+
export class LotteryError extends Error {
|
|
8
|
+
constructor(code, message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.code = code;
|
|
11
|
+
this.name = "LotteryError";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Compute the weight for a slot given its price.
|
|
16
|
+
* Lower price → higher weight → more likely to be selected.
|
|
17
|
+
* Weight is always at least 1 (never 0).
|
|
18
|
+
* For uniform pricing: all slots get weight 50.
|
|
19
|
+
*/
|
|
20
|
+
export function computeWeight(priceInPaise, maxPriceInPaise) {
|
|
21
|
+
if (maxPriceInPaise === 0)
|
|
22
|
+
return 50;
|
|
23
|
+
return Math.max(1, Math.round((1 - priceInPaise / maxPriceInPaise) * 99) + 1);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Pick a slot using weighted random selection.
|
|
27
|
+
* @throws {LotteryError} LOTTERY_FULL when unclaimed is empty.
|
|
28
|
+
*/
|
|
29
|
+
export function pickWeightedSlot(unclaimed) {
|
|
30
|
+
if (unclaimed.length === 0) {
|
|
31
|
+
throw new LotteryError("LOTTERY_FULL", "No unclaimed slots remain.");
|
|
32
|
+
}
|
|
33
|
+
const total = unclaimed.reduce((s, sl) => s + sl.weight, 0);
|
|
34
|
+
let r = Math.random() * total;
|
|
35
|
+
for (const sl of unclaimed) {
|
|
36
|
+
r -= sl.weight;
|
|
37
|
+
if (r <= 0)
|
|
38
|
+
return sl;
|
|
39
|
+
}
|
|
40
|
+
return unclaimed[unclaimed.length - 1];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Assign weights to slots based on pricing mode.
|
|
44
|
+
* Returns a new array with weight populated on every slot.
|
|
45
|
+
*/
|
|
46
|
+
export function assignSlotWeights(config) {
|
|
47
|
+
if (config.pricingMode === "uniform") {
|
|
48
|
+
return config.slots.map((sl) => ({ ...sl, weight: 50 }));
|
|
49
|
+
}
|
|
50
|
+
const maxPrice = Math.max(...config.slots.map((sl) => sl.priceInPaise), 0);
|
|
51
|
+
return config.slots.map((sl) => ({
|
|
52
|
+
...sl,
|
|
53
|
+
weight: computeWeight(sl.priceInPaise, maxPrice),
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|