@mohasinac/appkit 3.0.6 → 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/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/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/refunds/__tests__/actions.test.d.ts +1 -0
- package/dist/_internal/server/features/refunds/__tests__/actions.test.js +263 -0
- 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/products/schema.d.ts +8 -8
- package/dist/client.d.ts +9 -0
- package/dist/client.js +9 -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/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/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/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/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/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/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/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 +3 -0
- package/dist/features/events/schemas/index.d.ts +834 -14
- 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/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/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/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/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/products/api/[id]/route.d.ts +4 -4
- package/dist/features/products/api/route.d.ts +2 -2
- 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/schemas/firestore.d.ts +15 -1
- package/dist/features/products/schemas/index.d.ts +12 -12
- package/dist/features/products/schemas/index.js +4 -2
- package/dist/features/products/types/index.d.ts +1 -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/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/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/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/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/repository/__tests__/offer.repository.test.d.ts +1 -0
- package/dist/features/seller/repository/__tests__/offer.repository.test.js +458 -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/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/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 +13 -0
- package/dist/next/routing/route-map.js +6 -0
- package/dist/repositories/index.d.ts +1 -0
- package/dist/repositories/index.js +2 -0
- 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 +3 -1
- 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 +3 -1
- package/dist/server.d.ts +6 -0
- package/dist/server.js +6 -0
- package/dist/styles.css +1 -1
- package/dist/tailwind-utilities.css +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from "vitest";
|
|
2
|
+
// No repository mocks needed — function uses ctx.db directly.
|
|
3
|
+
import { runTriggerEventRaffle } from "../triggerEventRaffle";
|
|
4
|
+
// ── Helpers ─────────────────────────────────────────────────────────────────
|
|
5
|
+
function makeCtx(dbOverrides = {}) {
|
|
6
|
+
return {
|
|
7
|
+
db: buildMockDb(dbOverrides),
|
|
8
|
+
now: new Date("2026-01-01T00:00:00Z"),
|
|
9
|
+
env: vi.fn().mockReturnValue(""),
|
|
10
|
+
logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn() },
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Builds a mock Firestore db that:
|
|
15
|
+
* - eventSnap: resolved by the 'events' collection path
|
|
16
|
+
* - entriesSnap: resolved by the 'eventEntries' collection path
|
|
17
|
+
*/
|
|
18
|
+
function buildMockDb(overrides = {}) {
|
|
19
|
+
const { eventExists = true, eventData = {}, entriesDocs = [], updateFn = vi.fn().mockResolvedValue(undefined), } = overrides;
|
|
20
|
+
const mockUpdate = updateFn;
|
|
21
|
+
// Chain for event: db.collection("events").doc(id).get()
|
|
22
|
+
const eventSnap = { exists: eventExists, data: () => eventData };
|
|
23
|
+
const eventDocRef = { get: vi.fn().mockResolvedValue(eventSnap), update: mockUpdate };
|
|
24
|
+
const eventsCollection = { doc: vi.fn().mockReturnValue(eventDocRef) };
|
|
25
|
+
// Chain for entries: db.collection("eventEntries").where(...).where(...).get()
|
|
26
|
+
const entriesSnap = {
|
|
27
|
+
docs: entriesDocs,
|
|
28
|
+
size: entriesDocs.length,
|
|
29
|
+
};
|
|
30
|
+
const entriesQuery = {
|
|
31
|
+
where: vi.fn().mockReturnThis(),
|
|
32
|
+
get: vi.fn().mockResolvedValue(entriesSnap),
|
|
33
|
+
};
|
|
34
|
+
const entriesCollection = { where: vi.fn().mockReturnValue(entriesQuery) };
|
|
35
|
+
const db = {
|
|
36
|
+
collection: vi.fn((name) => {
|
|
37
|
+
if (name === "events")
|
|
38
|
+
return eventsCollection;
|
|
39
|
+
if (name === "eventEntries")
|
|
40
|
+
return entriesCollection;
|
|
41
|
+
return eventsCollection;
|
|
42
|
+
}),
|
|
43
|
+
mockUpdate, // expose for assertions
|
|
44
|
+
};
|
|
45
|
+
return db;
|
|
46
|
+
}
|
|
47
|
+
function makeEntry(overrides = {}) {
|
|
48
|
+
const { id = "entry-1", userId = "user-ravi", displayName = "Ravi Kumar", points = 0, createdAt = new Date() } = overrides;
|
|
49
|
+
return {
|
|
50
|
+
id,
|
|
51
|
+
data: () => ({ userId, userDisplayName: displayName, points, createdAt }),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const INPUT_BASE = { eventId: "event-summer-raffle" };
|
|
55
|
+
// ── Tests ────────────────────────────────────────────────────────────────────
|
|
56
|
+
describe("runTriggerEventRaffle — event not found", () => {
|
|
57
|
+
it("returns reason=event_not_found when event does not exist", async () => {
|
|
58
|
+
const ctx = makeCtx({ eventExists: false });
|
|
59
|
+
const result = await runTriggerEventRaffle(INPUT_BASE, ctx);
|
|
60
|
+
expect(result.reason).toBe("event_not_found");
|
|
61
|
+
expect(result.raffleEntryCount).toBe(0);
|
|
62
|
+
});
|
|
63
|
+
it("does NOT update eventRef when event not found", async () => {
|
|
64
|
+
const ctx = makeCtx({ eventExists: false });
|
|
65
|
+
await runTriggerEventRaffle(INPUT_BASE, ctx);
|
|
66
|
+
expect(ctx.db.mockUpdate).not.toHaveBeenCalled();
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
describe("runTriggerEventRaffle — already triggered (idempotency)", () => {
|
|
70
|
+
it("returns alreadyTriggered=true when winner already set", async () => {
|
|
71
|
+
const ctx = makeCtx({ eventData: { raffleWinnerUserId: "user-already-won" } });
|
|
72
|
+
const result = await runTriggerEventRaffle(INPUT_BASE, ctx);
|
|
73
|
+
expect(result.alreadyTriggered).toBe(true);
|
|
74
|
+
expect(result.raffleWinnerUserId).toBe("user-already-won");
|
|
75
|
+
});
|
|
76
|
+
it("does NOT query entries or update event when already triggered", async () => {
|
|
77
|
+
const ctx = makeCtx({ eventData: { raffleWinnerUserId: "user-already-won" } });
|
|
78
|
+
await runTriggerEventRaffle(INPUT_BASE, ctx);
|
|
79
|
+
expect(ctx.db.mockUpdate).not.toHaveBeenCalled();
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
describe("runTriggerEventRaffle — no eligible entries", () => {
|
|
83
|
+
it("returns reason=no_eligible_entries when no CONFIRMED entries exist", async () => {
|
|
84
|
+
const ctx = makeCtx({ entriesDocs: [] });
|
|
85
|
+
const result = await runTriggerEventRaffle(INPUT_BASE, ctx);
|
|
86
|
+
expect(result.reason).toBe("no_eligible_entries");
|
|
87
|
+
expect(result.raffleEntryCount).toBe(0);
|
|
88
|
+
});
|
|
89
|
+
it("does NOT update event when no entries", async () => {
|
|
90
|
+
const ctx = makeCtx({ entriesDocs: [] });
|
|
91
|
+
await runTriggerEventRaffle(INPUT_BASE, ctx);
|
|
92
|
+
expect(ctx.db.mockUpdate).not.toHaveBeenCalled();
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
describe("runTriggerEventRaffle — open_raffle (default)", () => {
|
|
96
|
+
it("all confirmed entries are in the pool", async () => {
|
|
97
|
+
const entries = [
|
|
98
|
+
makeEntry({ id: "e1", userId: "user-1" }),
|
|
99
|
+
makeEntry({ id: "e2", userId: "user-2" }),
|
|
100
|
+
makeEntry({ id: "e3", userId: "user-3" }),
|
|
101
|
+
];
|
|
102
|
+
const ctx = makeCtx({ eventData: { raffleType: "open_raffle" }, entriesDocs: entries });
|
|
103
|
+
const result = await runTriggerEventRaffle(INPUT_BASE, ctx);
|
|
104
|
+
expect(["user-1", "user-2", "user-3"]).toContain(result.raffleWinnerUserId);
|
|
105
|
+
});
|
|
106
|
+
it("winner fields written back to event doc", async () => {
|
|
107
|
+
const updateFn = vi.fn().mockResolvedValue(undefined);
|
|
108
|
+
const entries = [makeEntry({ id: "e1", userId: "user-ravi", displayName: "Ravi" })];
|
|
109
|
+
const ctx = makeCtx({ entriesDocs: entries, updateFn });
|
|
110
|
+
await runTriggerEventRaffle(INPUT_BASE, ctx);
|
|
111
|
+
expect(updateFn).toHaveBeenCalledWith(expect.objectContaining({
|
|
112
|
+
raffleWinnerUserId: "user-ravi",
|
|
113
|
+
raffleWinnerDisplayName: "Ravi",
|
|
114
|
+
raffleWinnerEntryId: "e1",
|
|
115
|
+
raffleEntryCount: 1,
|
|
116
|
+
}));
|
|
117
|
+
});
|
|
118
|
+
it("raffleTriggeredAt = ctx.now", async () => {
|
|
119
|
+
const updateFn = vi.fn().mockResolvedValue(undefined);
|
|
120
|
+
const now = new Date("2026-03-15T10:00:00Z");
|
|
121
|
+
const entries = [makeEntry({ id: "e1" })];
|
|
122
|
+
const ctx = makeCtx({ entriesDocs: entries, updateFn });
|
|
123
|
+
ctx.now = now;
|
|
124
|
+
await runTriggerEventRaffle(INPUT_BASE, ctx);
|
|
125
|
+
expect(updateFn).toHaveBeenCalledWith(expect.objectContaining({ raffleTriggeredAt: now }));
|
|
126
|
+
});
|
|
127
|
+
it("raffleEntryCount = total entries (not pool size)", async () => {
|
|
128
|
+
const updateFn = vi.fn().mockResolvedValue(undefined);
|
|
129
|
+
const entries = [
|
|
130
|
+
makeEntry({ id: "e1", userId: "user-1" }),
|
|
131
|
+
makeEntry({ id: "e2", userId: "user-2" }),
|
|
132
|
+
];
|
|
133
|
+
const ctx = makeCtx({ entriesDocs: entries, updateFn });
|
|
134
|
+
await runTriggerEventRaffle({ ...INPUT_BASE, raffleType: "open_raffle" }, ctx);
|
|
135
|
+
expect(updateFn).toHaveBeenCalledWith(expect.objectContaining({ raffleEntryCount: 2 }));
|
|
136
|
+
});
|
|
137
|
+
it("returns correct winner in result object", async () => {
|
|
138
|
+
const entries = [makeEntry({ id: "e1", userId: "user-only", displayName: "Only User" })];
|
|
139
|
+
const ctx = makeCtx({ entriesDocs: entries });
|
|
140
|
+
const result = await runTriggerEventRaffle(INPUT_BASE, ctx);
|
|
141
|
+
expect(result.raffleWinnerUserId).toBe("user-only");
|
|
142
|
+
expect(result.raffleWinnerDisplayName).toBe("Only User");
|
|
143
|
+
expect(result.raffleEntryCount).toBe(1);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
describe("runTriggerEventRaffle — top_n_scorers", () => {
|
|
147
|
+
it("pool limited to top N by points descending", async () => {
|
|
148
|
+
const entries = [
|
|
149
|
+
makeEntry({ id: "e1", userId: "user-low", points: 10 }),
|
|
150
|
+
makeEntry({ id: "e2", userId: "user-high", points: 100 }),
|
|
151
|
+
makeEntry({ id: "e3", userId: "user-mid", points: 50 }),
|
|
152
|
+
];
|
|
153
|
+
const ctx = makeCtx({ entriesDocs: entries });
|
|
154
|
+
// topN=1 means only the highest scorer can win
|
|
155
|
+
const result = await runTriggerEventRaffle({ ...INPUT_BASE, raffleType: "top_n_scorers", topN: 1 }, ctx);
|
|
156
|
+
expect(result.raffleWinnerUserId).toBe("user-high");
|
|
157
|
+
});
|
|
158
|
+
it("topN=2: winner is either top-1 or top-2 scorer, NOT bottom scorer", async () => {
|
|
159
|
+
const entries = [
|
|
160
|
+
makeEntry({ id: "e1", userId: "user-bottom", points: 1 }),
|
|
161
|
+
makeEntry({ id: "e2", userId: "user-top", points: 100 }),
|
|
162
|
+
makeEntry({ id: "e3", userId: "user-second", points: 50 }),
|
|
163
|
+
];
|
|
164
|
+
const ctx = makeCtx({ entriesDocs: entries });
|
|
165
|
+
const result = await runTriggerEventRaffle({ ...INPUT_BASE, raffleType: "top_n_scorers", topN: 2 }, ctx);
|
|
166
|
+
expect(["user-top", "user-second"]).toContain(result.raffleWinnerUserId);
|
|
167
|
+
expect(result.raffleWinnerUserId).not.toBe("user-bottom");
|
|
168
|
+
});
|
|
169
|
+
it("topN=0 → entire pool used (topN disabled)", async () => {
|
|
170
|
+
const entries = [
|
|
171
|
+
makeEntry({ id: "e1", userId: "user-1", points: 10 }),
|
|
172
|
+
makeEntry({ id: "e2", userId: "user-2", points: 20 }),
|
|
173
|
+
];
|
|
174
|
+
const ctx = makeCtx({ entriesDocs: entries });
|
|
175
|
+
const result = await runTriggerEventRaffle({ ...INPUT_BASE, raffleType: "top_n_scorers", topN: 0 }, ctx);
|
|
176
|
+
expect(["user-1", "user-2"]).toContain(result.raffleWinnerUserId);
|
|
177
|
+
});
|
|
178
|
+
it("reads raffleTopN from event when topN not in input", async () => {
|
|
179
|
+
const entries = [
|
|
180
|
+
makeEntry({ id: "e1", userId: "user-low", points: 5 }),
|
|
181
|
+
makeEntry({ id: "e2", userId: "user-high", points: 999 }),
|
|
182
|
+
];
|
|
183
|
+
const ctx = makeCtx({
|
|
184
|
+
eventData: { raffleType: "top_n_scorers", raffleTopN: 1 },
|
|
185
|
+
entriesDocs: entries,
|
|
186
|
+
});
|
|
187
|
+
const result = await runTriggerEventRaffle(INPUT_BASE, ctx);
|
|
188
|
+
expect(result.raffleWinnerUserId).toBe("user-high");
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
describe("runTriggerEventRaffle — top_n_participants", () => {
|
|
192
|
+
it("pool limited to first N by createdAt ascending", async () => {
|
|
193
|
+
const t1 = new Date("2026-01-01");
|
|
194
|
+
const t2 = new Date("2026-01-02");
|
|
195
|
+
const t3 = new Date("2026-01-03");
|
|
196
|
+
const entries = [
|
|
197
|
+
makeEntry({ id: "e3", userId: "user-last", createdAt: t3 }),
|
|
198
|
+
makeEntry({ id: "e1", userId: "user-first", createdAt: t1 }),
|
|
199
|
+
makeEntry({ id: "e2", userId: "user-second", createdAt: t2 }),
|
|
200
|
+
];
|
|
201
|
+
const ctx = makeCtx({ entriesDocs: entries });
|
|
202
|
+
// topN=1 means only the earliest registrant wins
|
|
203
|
+
const result = await runTriggerEventRaffle({ ...INPUT_BASE, raffleType: "top_n_participants", topN: 1 }, ctx);
|
|
204
|
+
expect(result.raffleWinnerUserId).toBe("user-first");
|
|
205
|
+
});
|
|
206
|
+
it("handles Firestore Timestamp-like createdAt objects (via toDate)", async () => {
|
|
207
|
+
const entries = [
|
|
208
|
+
makeEntry({
|
|
209
|
+
id: "e1",
|
|
210
|
+
userId: "user-a",
|
|
211
|
+
createdAt: { toDate: () => new Date("2026-01-01") },
|
|
212
|
+
}),
|
|
213
|
+
makeEntry({
|
|
214
|
+
id: "e2",
|
|
215
|
+
userId: "user-b",
|
|
216
|
+
createdAt: { toDate: () => new Date("2026-01-02") },
|
|
217
|
+
}),
|
|
218
|
+
];
|
|
219
|
+
const ctx = makeCtx({ entriesDocs: entries });
|
|
220
|
+
const result = await runTriggerEventRaffle({ ...INPUT_BASE, raffleType: "top_n_participants", topN: 1 }, ctx);
|
|
221
|
+
expect(result.raffleWinnerUserId).toBe("user-a");
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
describe("runTriggerEventRaffle — input override precedence", () => {
|
|
225
|
+
it("input.raffleType overrides event.raffleType", async () => {
|
|
226
|
+
const entries = [
|
|
227
|
+
makeEntry({ id: "e1", userId: "user-low", points: 1 }),
|
|
228
|
+
makeEntry({ id: "e2", userId: "user-high", points: 999 }),
|
|
229
|
+
];
|
|
230
|
+
// Event says open_raffle, but input says top_n_scorers topN=1
|
|
231
|
+
const ctx = makeCtx({
|
|
232
|
+
eventData: { raffleType: "open_raffle" },
|
|
233
|
+
entriesDocs: entries,
|
|
234
|
+
});
|
|
235
|
+
const result = await runTriggerEventRaffle({ ...INPUT_BASE, raffleType: "top_n_scorers", topN: 1 }, ctx);
|
|
236
|
+
expect(result.raffleWinnerUserId).toBe("user-high");
|
|
237
|
+
});
|
|
238
|
+
it("input.topN overrides event.raffleTopN", async () => {
|
|
239
|
+
const entries = [
|
|
240
|
+
makeEntry({ id: "e1", userId: "user-low", points: 5 }),
|
|
241
|
+
makeEntry({ id: "e2", userId: "user-high", points: 100 }),
|
|
242
|
+
makeEntry({ id: "e3", userId: "user-mid", points: 50 }),
|
|
243
|
+
];
|
|
244
|
+
// Event says topN=3 (all), but input says topN=1 (only highest)
|
|
245
|
+
const ctx = makeCtx({
|
|
246
|
+
eventData: { raffleType: "top_n_scorers", raffleTopN: 3 },
|
|
247
|
+
entriesDocs: entries,
|
|
248
|
+
});
|
|
249
|
+
const result = await runTriggerEventRaffle({ ...INPUT_BASE, raffleType: "top_n_scorers", topN: 1 }, ctx);
|
|
250
|
+
expect(result.raffleWinnerUserId).toBe("user-high");
|
|
251
|
+
});
|
|
252
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
const { mockRecord, mockMapToHttpError } = vi.hoisted(() => ({
|
|
3
|
+
mockRecord: vi.fn().mockResolvedValue(undefined),
|
|
4
|
+
mockMapToHttpError: vi.fn().mockReturnValue({ code: 500, message: "Internal error" }),
|
|
5
|
+
}));
|
|
6
|
+
vi.mock("../../../../../features/server-errors/repository/server-errors.repository", () => ({
|
|
7
|
+
serverErrorsRepository: vi.fn(() => ({ record: mockRecord })),
|
|
8
|
+
}));
|
|
9
|
+
vi.mock("../../../../../errors/error-mapping", () => ({
|
|
10
|
+
mapToHttpError: mockMapToHttpError,
|
|
11
|
+
}));
|
|
12
|
+
import { wrapScheduleHandler, wrapTriggerHandler, wrapCallableHandler, wrapJobHandler, } from "../wrapJobHandler";
|
|
13
|
+
function makeCtx() {
|
|
14
|
+
return {
|
|
15
|
+
db: {},
|
|
16
|
+
now: new Date("2026-01-01"),
|
|
17
|
+
logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn() },
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
vi.clearAllMocks();
|
|
22
|
+
mockRecord.mockResolvedValue(undefined);
|
|
23
|
+
mockMapToHttpError.mockReturnValue({ code: 500, message: "Internal error" });
|
|
24
|
+
});
|
|
25
|
+
// ── wrapScheduleHandler ──────────────────────────────────────────────────────
|
|
26
|
+
describe("wrapScheduleHandler", () => {
|
|
27
|
+
it("returns handler result when handler succeeds", async () => {
|
|
28
|
+
const handler = vi.fn().mockResolvedValue(undefined);
|
|
29
|
+
const wrapped = wrapScheduleHandler("my-job", handler);
|
|
30
|
+
await expect(wrapped(makeCtx())).resolves.toBeUndefined();
|
|
31
|
+
});
|
|
32
|
+
it("persists error to serverErrors when handler throws", async () => {
|
|
33
|
+
const handler = vi.fn().mockRejectedValue(new Error("job failed"));
|
|
34
|
+
const wrapped = wrapScheduleHandler("my-job", handler);
|
|
35
|
+
try {
|
|
36
|
+
await wrapped(makeCtx());
|
|
37
|
+
}
|
|
38
|
+
catch { /* expected */ }
|
|
39
|
+
expect(mockRecord).toHaveBeenCalledWith(expect.objectContaining({ source: "function", route: "my-job" }));
|
|
40
|
+
});
|
|
41
|
+
it("re-throws the original error after persisting", async () => {
|
|
42
|
+
const err = new Error("job failed");
|
|
43
|
+
const handler = vi.fn().mockRejectedValue(err);
|
|
44
|
+
const wrapped = wrapScheduleHandler("my-job", handler);
|
|
45
|
+
await expect(wrapped(makeCtx())).rejects.toThrow("job failed");
|
|
46
|
+
});
|
|
47
|
+
it("persist failure does NOT prevent re-throw", async () => {
|
|
48
|
+
const err = new Error("job failed");
|
|
49
|
+
mockRecord.mockRejectedValue(new Error("DB write failed"));
|
|
50
|
+
const handler = vi.fn().mockRejectedValue(err);
|
|
51
|
+
const wrapped = wrapScheduleHandler("my-job", handler);
|
|
52
|
+
await expect(wrapped(makeCtx())).rejects.toThrow("job failed");
|
|
53
|
+
});
|
|
54
|
+
it("calls mapToHttpError to normalise the error", async () => {
|
|
55
|
+
const err = new Error("Something broke");
|
|
56
|
+
const handler = vi.fn().mockRejectedValue(err);
|
|
57
|
+
const wrapped = wrapScheduleHandler("my-job", handler);
|
|
58
|
+
try {
|
|
59
|
+
await wrapped(makeCtx());
|
|
60
|
+
}
|
|
61
|
+
catch { /* expected */ }
|
|
62
|
+
expect(mockMapToHttpError).toHaveBeenCalledWith(err);
|
|
63
|
+
});
|
|
64
|
+
it("requestId includes handler name", async () => {
|
|
65
|
+
const handler = vi.fn().mockRejectedValue(new Error("oops"));
|
|
66
|
+
const wrapped = wrapScheduleHandler("audit-run", handler);
|
|
67
|
+
try {
|
|
68
|
+
await wrapped(makeCtx());
|
|
69
|
+
}
|
|
70
|
+
catch { /* expected */ }
|
|
71
|
+
const call = mockRecord.mock.calls[0][0];
|
|
72
|
+
expect(call.requestId).toMatch(/audit-run/);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
// ── wrapTriggerHandler ───────────────────────────────────────────────────────
|
|
76
|
+
describe("wrapTriggerHandler", () => {
|
|
77
|
+
const mockEvent = { path: "test/doc1", params: {}, before: null, after: {} };
|
|
78
|
+
it("returns handler result when handler succeeds", async () => {
|
|
79
|
+
const handler = vi.fn().mockResolvedValue(undefined);
|
|
80
|
+
const wrapped = wrapTriggerHandler("trigger-fn", handler);
|
|
81
|
+
await expect(wrapped(mockEvent, makeCtx())).resolves.toBeUndefined();
|
|
82
|
+
});
|
|
83
|
+
it("persists error and re-throws when handler throws", async () => {
|
|
84
|
+
const err = new Error("trigger failed");
|
|
85
|
+
const handler = vi.fn().mockRejectedValue(err);
|
|
86
|
+
const wrapped = wrapTriggerHandler("trigger-fn", handler);
|
|
87
|
+
await expect(wrapped(mockEvent, makeCtx())).rejects.toThrow("trigger failed");
|
|
88
|
+
expect(mockRecord).toHaveBeenCalled();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
// ── wrapCallableHandler ──────────────────────────────────────────────────────
|
|
92
|
+
describe("wrapCallableHandler", () => {
|
|
93
|
+
it("returns handler result when handler succeeds", async () => {
|
|
94
|
+
const handler = vi.fn().mockResolvedValue({ result: "ok" });
|
|
95
|
+
const wrapped = wrapCallableHandler("callable-fn", handler);
|
|
96
|
+
await expect(wrapped({}, makeCtx())).resolves.toEqual({ result: "ok" });
|
|
97
|
+
});
|
|
98
|
+
it("persists error and re-throws when handler throws", async () => {
|
|
99
|
+
const handler = vi.fn().mockRejectedValue(new Error("callable failed"));
|
|
100
|
+
const wrapped = wrapCallableHandler("callable-fn", handler);
|
|
101
|
+
await expect(wrapped({}, makeCtx())).rejects.toThrow("callable failed");
|
|
102
|
+
expect(mockRecord).toHaveBeenCalled();
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
// ── wrapJobHandler ───────────────────────────────────────────────────────────
|
|
106
|
+
describe("wrapJobHandler", () => {
|
|
107
|
+
it("returns handler result for a generic handler", async () => {
|
|
108
|
+
const handler = vi.fn().mockResolvedValue(42);
|
|
109
|
+
const wrapped = wrapJobHandler("generic-fn", handler);
|
|
110
|
+
await expect(wrapped()).resolves.toBe(42);
|
|
111
|
+
});
|
|
112
|
+
it("persists error with handler name and re-throws", async () => {
|
|
113
|
+
const handler = vi.fn().mockRejectedValue(new Error("generic failed"));
|
|
114
|
+
const wrapped = wrapJobHandler("generic-fn", handler);
|
|
115
|
+
await expect(wrapped()).rejects.toThrow("generic failed");
|
|
116
|
+
expect(mockRecord).toHaveBeenCalledWith(expect.objectContaining({ route: "generic-fn", source: "function" }));
|
|
117
|
+
});
|
|
118
|
+
it("extracts JobContext from last arg if it has .now", async () => {
|
|
119
|
+
const now = new Date("2026-06-15T12:00:00Z");
|
|
120
|
+
const handler = vi.fn().mockRejectedValue(new Error("err"));
|
|
121
|
+
const wrapped = wrapJobHandler("fn-with-ctx", handler);
|
|
122
|
+
try {
|
|
123
|
+
await wrapped({ now });
|
|
124
|
+
}
|
|
125
|
+
catch { /* expected */ }
|
|
126
|
+
const call = mockRecord.mock.calls[0][0];
|
|
127
|
+
expect(call.occurredAt).toBe(now.getTime());
|
|
128
|
+
});
|
|
129
|
+
});
|
|
@@ -28,7 +28,7 @@ import type { CategoryType } from "../../../features/categories/types/index";
|
|
|
28
28
|
/** What KIND of action — drives default UI affordance (link vs button vs danger). */
|
|
29
29
|
export type ActionKind = "primary" | "secondary" | "danger" | "ghost" | "link" | "chip";
|
|
30
30
|
/** Resource bucket — keyed top-level in the ACTIONS tree. */
|
|
31
|
-
export type ActionResource = "PRODUCT" | "AUCTION" | "PRE_ORDER" | "PRIZE_DRAW" | "CLASSIFIED" | "DIGITAL_CODE" | "LIVE" | "BUNDLE" | "GROUP" | "CATEGORY" | "BRAND" | "SUBLISTING" | "STORE" | "BLOG" | "EVENT" | "USER" | "SELLER" | "ADMIN" | "CART" | "CHECKOUT" | "NAV" | "MEDIA" | "SUPPORT";
|
|
31
|
+
export type ActionResource = "PRODUCT" | "AUCTION" | "PRE_ORDER" | "PRIZE_DRAW" | "CLASSIFIED" | "DIGITAL_CODE" | "LIVE" | "BUNDLE" | "GROUP" | "CATEGORY" | "BRAND" | "SUBLISTING" | "STORE" | "BLOG" | "EVENT" | "USER" | "SELLER" | "ADMIN" | "CART" | "CHECKOUT" | "NAV" | "MEDIA" | "SUPPORT" | "LOTTERY";
|
|
32
32
|
/** Confirmation modal config — when set, <Button action={...}> opens
|
|
33
33
|
* a confirm dialog before firing the actual handler. */
|
|
34
34
|
export interface ActionConfirmation {
|
|
@@ -1732,6 +1732,52 @@ export const ACTIONS = {
|
|
|
1732
1732
|
},
|
|
1733
1733
|
},
|
|
1734
1734
|
},
|
|
1735
|
+
LOTTERY: {
|
|
1736
|
+
"pull": {
|
|
1737
|
+
id: "lottery.pull",
|
|
1738
|
+
label: "Submit Entry",
|
|
1739
|
+
description: "Submit a lottery pull entry — slot assigned immediately.",
|
|
1740
|
+
kind: "primary",
|
|
1741
|
+
},
|
|
1742
|
+
"flag-entry": {
|
|
1743
|
+
id: "lottery.flag-entry",
|
|
1744
|
+
label: "Flag as Scammer",
|
|
1745
|
+
description: "Flag a lottery entry as fraudulent.",
|
|
1746
|
+
kind: "danger",
|
|
1747
|
+
permissions: ["admin", "moderator"],
|
|
1748
|
+
confirmation: {
|
|
1749
|
+
title: "Flag this entry?",
|
|
1750
|
+
body: "Entry will be marked fraudulent. Their claimed slot stays booked until you manually reopen it.",
|
|
1751
|
+
confirmLabel: "Flag entry",
|
|
1752
|
+
confirmKind: "danger",
|
|
1753
|
+
},
|
|
1754
|
+
},
|
|
1755
|
+
"reopen-slot": {
|
|
1756
|
+
id: "lottery.reopen-slot",
|
|
1757
|
+
label: "Reopen Slot",
|
|
1758
|
+
description: "Free a flagged entry's slot so it can be claimed again.",
|
|
1759
|
+
kind: "secondary",
|
|
1760
|
+
permissions: ["admin"],
|
|
1761
|
+
confirmation: {
|
|
1762
|
+
title: "Reopen this slot?",
|
|
1763
|
+
body: "The slot will be available for new pulls. The flagged entry's slot assignment is removed.",
|
|
1764
|
+
confirmLabel: "Reopen",
|
|
1765
|
+
},
|
|
1766
|
+
},
|
|
1767
|
+
"cancel": {
|
|
1768
|
+
id: "lottery.cancel",
|
|
1769
|
+
label: "Cancel Lottery",
|
|
1770
|
+
description: "Close the draw window and reject pending pulls.",
|
|
1771
|
+
kind: "danger",
|
|
1772
|
+
permissions: ["admin", "moderator"],
|
|
1773
|
+
confirmation: {
|
|
1774
|
+
title: "Cancel lottery?",
|
|
1775
|
+
body: "Draw window closes immediately. Pending pulls rejected.",
|
|
1776
|
+
confirmLabel: "Cancel",
|
|
1777
|
+
confirmKind: "danger",
|
|
1778
|
+
},
|
|
1779
|
+
},
|
|
1780
|
+
},
|
|
1735
1781
|
};
|
|
1736
1782
|
/** Sugar — `act("PRODUCT", "add-to-cart")` reads more naturally at call sites. */
|
|
1737
1783
|
export function act(resource, id) {
|
|
@@ -41,7 +41,7 @@ export declare const productInputSchema: z.ZodObject<{
|
|
|
41
41
|
features?: string[] | undefined;
|
|
42
42
|
shippingInfo?: string | undefined;
|
|
43
43
|
returnPolicy?: string | undefined;
|
|
44
|
-
condition?: "new" | "used" | "refurbished" | "
|
|
44
|
+
condition?: "new" | "used" | "refurbished" | "like_new" | "good" | "fair" | "poor" | "broken" | undefined;
|
|
45
45
|
insurance?: boolean | undefined;
|
|
46
46
|
insuranceCost?: number | undefined;
|
|
47
47
|
shippingPaidBy?: "seller" | "buyer" | undefined;
|
|
@@ -65,7 +65,7 @@ export declare const productInputSchema: z.ZodObject<{
|
|
|
65
65
|
features?: string[] | undefined;
|
|
66
66
|
shippingInfo?: string | undefined;
|
|
67
67
|
returnPolicy?: string | undefined;
|
|
68
|
-
condition?: "new" | "used" | "refurbished" | "
|
|
68
|
+
condition?: "new" | "used" | "refurbished" | "like_new" | "good" | "fair" | "poor" | "broken" | undefined;
|
|
69
69
|
insurance?: boolean | undefined;
|
|
70
70
|
insuranceCost?: number | undefined;
|
|
71
71
|
shippingPaidBy?: "seller" | "buyer" | undefined;
|
|
@@ -114,7 +114,7 @@ export declare const productUpdateSchema: z.ZodObject<{
|
|
|
114
114
|
features?: string[] | undefined;
|
|
115
115
|
shippingInfo?: string | undefined;
|
|
116
116
|
returnPolicy?: string | undefined;
|
|
117
|
-
condition?: "new" | "used" | "refurbished" | "
|
|
117
|
+
condition?: "new" | "used" | "refurbished" | "like_new" | "good" | "fair" | "poor" | "broken" | undefined;
|
|
118
118
|
insurance?: boolean | undefined;
|
|
119
119
|
insuranceCost?: number | undefined;
|
|
120
120
|
shippingPaidBy?: "seller" | "buyer" | undefined;
|
|
@@ -138,7 +138,7 @@ export declare const productUpdateSchema: z.ZodObject<{
|
|
|
138
138
|
features?: string[] | undefined;
|
|
139
139
|
shippingInfo?: string | undefined;
|
|
140
140
|
returnPolicy?: string | undefined;
|
|
141
|
-
condition?: "new" | "used" | "refurbished" | "
|
|
141
|
+
condition?: "new" | "used" | "refurbished" | "like_new" | "good" | "fair" | "poor" | "broken" | undefined;
|
|
142
142
|
insurance?: boolean | undefined;
|
|
143
143
|
insuranceCost?: number | undefined;
|
|
144
144
|
shippingPaidBy?: "seller" | "buyer" | undefined;
|
|
@@ -201,7 +201,7 @@ export declare const auctionInputSchema: z.ZodObject<{
|
|
|
201
201
|
features?: string[] | undefined;
|
|
202
202
|
shippingInfo?: string | undefined;
|
|
203
203
|
returnPolicy?: string | undefined;
|
|
204
|
-
condition?: "new" | "used" | "refurbished" | "
|
|
204
|
+
condition?: "new" | "used" | "refurbished" | "like_new" | "good" | "fair" | "poor" | "broken" | undefined;
|
|
205
205
|
insurance?: boolean | undefined;
|
|
206
206
|
insuranceCost?: number | undefined;
|
|
207
207
|
shippingPaidBy?: "seller" | "buyer" | undefined;
|
|
@@ -233,7 +233,7 @@ export declare const auctionInputSchema: z.ZodObject<{
|
|
|
233
233
|
features?: string[] | undefined;
|
|
234
234
|
shippingInfo?: string | undefined;
|
|
235
235
|
returnPolicy?: string | undefined;
|
|
236
|
-
condition?: "new" | "used" | "refurbished" | "
|
|
236
|
+
condition?: "new" | "used" | "refurbished" | "like_new" | "good" | "fair" | "poor" | "broken" | undefined;
|
|
237
237
|
insurance?: boolean | undefined;
|
|
238
238
|
insuranceCost?: number | undefined;
|
|
239
239
|
shippingPaidBy?: "seller" | "buyer" | undefined;
|
|
@@ -299,7 +299,7 @@ export declare const preOrderInputSchema: z.ZodObject<{
|
|
|
299
299
|
features?: string[] | undefined;
|
|
300
300
|
shippingInfo?: string | undefined;
|
|
301
301
|
returnPolicy?: string | undefined;
|
|
302
|
-
condition?: "new" | "used" | "refurbished" | "
|
|
302
|
+
condition?: "new" | "used" | "refurbished" | "like_new" | "good" | "fair" | "poor" | "broken" | undefined;
|
|
303
303
|
insurance?: boolean | undefined;
|
|
304
304
|
insuranceCost?: number | undefined;
|
|
305
305
|
shippingPaidBy?: "seller" | "buyer" | undefined;
|
|
@@ -327,7 +327,7 @@ export declare const preOrderInputSchema: z.ZodObject<{
|
|
|
327
327
|
features?: string[] | undefined;
|
|
328
328
|
shippingInfo?: string | undefined;
|
|
329
329
|
returnPolicy?: string | undefined;
|
|
330
|
-
condition?: "new" | "used" | "refurbished" | "
|
|
330
|
+
condition?: "new" | "used" | "refurbished" | "like_new" | "good" | "fair" | "poor" | "broken" | undefined;
|
|
331
331
|
insurance?: boolean | undefined;
|
|
332
332
|
insuranceCost?: number | undefined;
|
|
333
333
|
shippingPaidBy?: "seller" | "buyer" | undefined;
|
package/dist/client.d.ts
CHANGED
|
@@ -67,6 +67,15 @@ export { FirebaseClientAuthProvider } from "./providers/firebase-client/index";
|
|
|
67
67
|
export { FirebaseClientRealtimeProvider } from "./providers/firebase-client/index";
|
|
68
68
|
export { EventFormDrawer, EventParticipateView, EventPollWidget } from "./features/events/index";
|
|
69
69
|
export type { EventParticipateViewProps } from "./features/events/index";
|
|
70
|
+
export { LotterySlotGrid } from "./_internal/client/features/lottery/LotterySlotGrid";
|
|
71
|
+
export { LotteryPullForm } from "./_internal/client/features/lottery/LotteryPullForm";
|
|
72
|
+
export { LotteryListView } from "./_internal/client/features/lottery/LotteryListView";
|
|
73
|
+
export { LotteryDetailView } from "./_internal/client/features/lottery/LotteryDetailView";
|
|
74
|
+
export { LotteryEntriesView } from "./_internal/client/features/lottery/LotteryEntriesView";
|
|
75
|
+
export { LotteryAdminSlotView } from "./_internal/client/features/lottery/LotteryAdminSlotView";
|
|
76
|
+
export { LotteryAdminEditView } from "./_internal/client/features/lottery/LotteryAdminEditView";
|
|
77
|
+
export { PrizeDrawLotteryDetailView } from "./_internal/client/features/lottery/PrizeDrawLotteryDetailView";
|
|
78
|
+
export type { LotteryConfig, LotterySlot, ClientLotterySlot, ClientLotteryConfig, LotteryPricingMode, LotteryEntryStatus } from "./features/lottery/types";
|
|
70
79
|
export { BottomSheet } from "./features/layout/index";
|
|
71
80
|
export { ImageUpload } from "./features/media/index";
|
|
72
81
|
export type { ImageUploadProps } from "./features/media/index";
|
package/dist/client.js
CHANGED
|
@@ -118,6 +118,15 @@ export { FirebaseClientRealtimeProvider } from "./providers/firebase-client/inde
|
|
|
118
118
|
// [CLIENT-ONLY]-Cannot run in SSR mode â€" uses browser-only APIs (window, navigator, localStorage, matchMedia, DOM events) that do not exist in Node.js.
|
|
119
119
|
// EventFormDrawer - Component for event form drawer.
|
|
120
120
|
export { EventFormDrawer, EventParticipateView, EventPollWidget } from "./features/events/index";
|
|
121
|
+
// Lottery feature — client components (safe for client bundles — no server imports)
|
|
122
|
+
export { LotterySlotGrid } from "./_internal/client/features/lottery/LotterySlotGrid";
|
|
123
|
+
export { LotteryPullForm } from "./_internal/client/features/lottery/LotteryPullForm";
|
|
124
|
+
export { LotteryListView } from "./_internal/client/features/lottery/LotteryListView";
|
|
125
|
+
export { LotteryDetailView } from "./_internal/client/features/lottery/LotteryDetailView";
|
|
126
|
+
export { LotteryEntriesView } from "./_internal/client/features/lottery/LotteryEntriesView";
|
|
127
|
+
export { LotteryAdminSlotView } from "./_internal/client/features/lottery/LotteryAdminSlotView";
|
|
128
|
+
export { LotteryAdminEditView } from "./_internal/client/features/lottery/LotteryAdminEditView";
|
|
129
|
+
export { PrizeDrawLotteryDetailView } from "./_internal/client/features/lottery/PrizeDrawLotteryDetailView";
|
|
121
130
|
// [CLIENT-ONLY]-Cannot run in SSR mode â€" uses browser-only APIs (window, navigator, localStorage, matchMedia, DOM events) that do not exist in Node.js.
|
|
122
131
|
// BottomSheet - Shared export for bottom sheet.
|
|
123
132
|
export { BottomSheet } from "./features/layout/index";
|
|
@@ -83,9 +83,14 @@ export declare const PRODUCT_FIELDS: {
|
|
|
83
83
|
};
|
|
84
84
|
readonly CONDITION_VALUES: {
|
|
85
85
|
readonly NEW: "new";
|
|
86
|
+
readonly LIKE_NEW: "like_new";
|
|
87
|
+
readonly GOOD: "good";
|
|
88
|
+
readonly FAIR: "fair";
|
|
89
|
+
readonly POOR: "poor";
|
|
86
90
|
readonly USED: "used";
|
|
87
91
|
readonly REFURBISHED: "refurbished";
|
|
88
92
|
readonly BROKEN: "broken";
|
|
93
|
+
readonly GRADED: "graded";
|
|
89
94
|
};
|
|
90
95
|
readonly SHIPPING_PAID_BY_VALUES: {
|
|
91
96
|
readonly SELLER: "seller";
|
|
@@ -111,7 +116,6 @@ export declare const PRODUCT_FIELDS: {
|
|
|
111
116
|
readonly AUCTION: "auction";
|
|
112
117
|
readonly PRE_ORDER: "pre-order";
|
|
113
118
|
readonly PRIZE_DRAW: "prize-draw";
|
|
114
|
-
readonly BUNDLE: "bundle";
|
|
115
119
|
readonly CLASSIFIED: "classified";
|
|
116
120
|
readonly DIGITAL_CODE: "digital-code";
|
|
117
121
|
readonly LIVE: "live";
|
|
@@ -88,9 +88,14 @@ export const PRODUCT_FIELDS = {
|
|
|
88
88
|
},
|
|
89
89
|
CONDITION_VALUES: {
|
|
90
90
|
NEW: "new",
|
|
91
|
+
LIKE_NEW: "like_new",
|
|
92
|
+
GOOD: "good",
|
|
93
|
+
FAIR: "fair",
|
|
94
|
+
POOR: "poor",
|
|
91
95
|
USED: "used",
|
|
92
96
|
REFURBISHED: "refurbished",
|
|
93
97
|
BROKEN: "broken",
|
|
98
|
+
GRADED: "graded",
|
|
94
99
|
},
|
|
95
100
|
SHIPPING_PAID_BY_VALUES: {
|
|
96
101
|
SELLER: "seller",
|
|
@@ -116,7 +121,6 @@ export const PRODUCT_FIELDS = {
|
|
|
116
121
|
AUCTION: "auction",
|
|
117
122
|
PRE_ORDER: "pre-order",
|
|
118
123
|
PRIZE_DRAW: "prize-draw",
|
|
119
|
-
BUNDLE: "bundle",
|
|
120
124
|
CLASSIFIED: "classified",
|
|
121
125
|
DIGITAL_CODE: "digital-code",
|
|
122
126
|
LIVE: "live",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|