@mohasinac/appkit 2.7.50 → 2.7.53
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/server/jobs/core/__tests__/couponExpiry.test.d.ts +1 -0
- package/dist/_internal/server/jobs/core/__tests__/couponExpiry.test.js +65 -0
- package/dist/_internal/server/jobs/core/__tests__/listingProcessor.test.d.ts +1 -0
- package/dist/_internal/server/jobs/core/__tests__/listingProcessor.test.js +163 -0
- package/dist/_internal/server/jobs/core/__tests__/mediaTmpCleanup.test.d.ts +1 -0
- package/dist/_internal/server/jobs/core/__tests__/mediaTmpCleanup.test.js +115 -0
- package/dist/_internal/server/jobs/core/__tests__/pendingOrderTimeout.test.d.ts +1 -0
- package/dist/_internal/server/jobs/core/__tests__/pendingOrderTimeout.test.js +96 -0
- package/dist/client.d.ts +29 -6
- package/dist/client.js +16 -4
- package/dist/constants/api-endpoints.d.ts +42 -0
- package/dist/constants/api-endpoints.js +14 -0
- package/dist/features/_guide-cls.d.ts +13 -0
- package/dist/features/_guide-cls.js +14 -0
- package/dist/features/about/components/HelpPageView.js +29 -26
- package/dist/features/account/components/BuyerAccountGuideView.d.ts +1 -0
- package/dist/features/account/components/BuyerAccountGuideView.js +39 -0
- package/dist/features/account/components/BuyerAuctionsGuideView.d.ts +1 -0
- package/dist/features/account/components/BuyerAuctionsGuideView.js +38 -0
- package/dist/features/account/components/BuyerOrdersGuideView.d.ts +1 -0
- package/dist/features/account/components/BuyerOrdersGuideView.js +48 -0
- package/dist/features/account/components/BuyerShoppingGuideView.d.ts +1 -0
- package/dist/features/account/components/BuyerShoppingGuideView.js +38 -0
- package/dist/features/admin/components/AdminAnalyticsGuideView.d.ts +1 -0
- package/dist/features/admin/components/AdminAnalyticsGuideView.js +24 -0
- package/dist/features/admin/components/AdminBlogEditorView.js +100 -77
- package/dist/features/admin/components/AdminBundleEditorView.js +20 -14
- package/dist/features/admin/components/AdminBundlesView.d.ts +1 -3
- package/dist/features/admin/components/AdminBundlesView.js +173 -52
- package/dist/features/admin/components/AdminCatalogGuideView.d.ts +1 -0
- package/dist/features/admin/components/AdminCatalogGuideView.js +28 -0
- package/dist/features/admin/components/AdminContentGuideView.d.ts +1 -0
- package/dist/features/admin/components/AdminContentGuideView.js +36 -0
- package/dist/features/admin/components/AdminCouponEditorView.js +1 -1
- package/dist/features/admin/components/AdminGuideHubView.d.ts +5 -0
- package/dist/features/admin/components/AdminGuideHubView.js +79 -0
- package/dist/features/admin/components/AdminOrdersGuideView.d.ts +1 -0
- package/dist/features/admin/components/AdminOrdersGuideView.js +44 -0
- package/dist/features/admin/components/AdminProductsView.js +8 -3
- package/dist/features/admin/components/AdminSiteConfigGuideView.d.ts +1 -0
- package/dist/features/admin/components/AdminSiteConfigGuideView.js +21 -0
- package/dist/features/admin/components/AdminStoresGuideView.d.ts +1 -0
- package/dist/features/admin/components/AdminStoresGuideView.js +32 -0
- package/dist/features/admin/components/AdminTeamGuideView.d.ts +1 -0
- package/dist/features/admin/components/AdminTeamGuideView.js +33 -0
- package/dist/features/admin/components/AdminTrustGuideView.d.ts +1 -0
- package/dist/features/admin/components/AdminTrustGuideView.js +40 -0
- package/dist/features/admin/components/AdminUsersGuideView.d.ts +1 -0
- package/dist/features/admin/components/AdminUsersGuideView.js +38 -0
- package/dist/features/categories/components/CategoryBundlesListing.js +3 -33
- package/dist/features/categories/components/index.d.ts +0 -2
- package/dist/features/categories/components/index.js +0 -1
- package/dist/features/events/components/AdminEventEditorView.js +223 -269
- package/dist/features/grouped/repository/grouped-listings.repository.d.ts +9 -0
- package/dist/features/grouped/repository/grouped-listings.repository.js +12 -0
- package/dist/features/media/upload/MediaUploadField.js +1 -1
- package/dist/features/pre-orders/components/PreOrdersIndexListing.js +3 -1
- package/dist/features/products/components/AuctionsIndexListing.js +3 -1
- package/dist/features/products/components/MarketplaceBundleCard.d.ts +21 -0
- package/dist/features/products/components/MarketplaceBundleCard.js +56 -0
- package/dist/features/products/components/ProductsIndexListing.js +3 -1
- package/dist/features/products/components/index.d.ts +2 -4
- package/dist/features/products/components/index.js +1 -2
- package/dist/features/promotions/schemas/firestore.js +1 -1
- package/dist/features/reviews/components/index.d.ts +0 -2
- package/dist/features/reviews/components/index.js +0 -1
- package/dist/features/seller/components/BrandInlineSelect.js +23 -3
- package/dist/features/seller/components/CategoryInlineSelect.js +20 -3
- package/dist/features/seller/components/SellerAnalyticsAlertsView.d.ts +6 -0
- package/dist/features/seller/components/SellerAnalyticsAlertsView.js +124 -0
- package/dist/features/seller/components/SellerAnalyticsView.d.ts +2 -0
- package/dist/features/seller/components/SellerAnalyticsView.js +17 -9
- package/dist/features/seller/components/SellerBundlesView.d.ts +5 -0
- package/dist/features/seller/components/SellerBundlesView.js +104 -0
- package/dist/features/seller/components/SellerClassifiedView.d.ts +5 -0
- package/dist/features/seller/components/SellerClassifiedView.js +113 -0
- package/dist/features/seller/components/SellerDashboardView.js +19 -7
- package/dist/features/seller/components/SellerDigitalCodesView.d.ts +5 -0
- package/dist/features/seller/components/SellerDigitalCodesView.js +115 -0
- package/dist/features/seller/components/SellerGoogleReviewsView.d.ts +14 -0
- package/dist/features/seller/components/SellerGoogleReviewsView.js +95 -0
- package/dist/features/seller/components/SellerGroupedListingsView.d.ts +6 -0
- package/dist/features/seller/components/SellerGroupedListingsView.js +112 -0
- package/dist/features/seller/components/SellerLiveView.d.ts +5 -0
- package/dist/features/seller/components/SellerLiveView.js +113 -0
- package/dist/features/seller/components/SellerOrdersView.js +18 -2
- package/dist/features/seller/components/SellerPayoutMethodsView.d.ts +7 -0
- package/dist/features/seller/components/SellerPayoutMethodsView.js +120 -0
- package/dist/features/seller/components/SellerPayoutSettingsView.js +50 -12
- package/dist/features/seller/components/SellerProductShell.d.ts +1 -1
- package/dist/features/seller/components/SellerProductShell.js +9 -7
- package/dist/features/seller/components/SellerProductsFilterDrawer.js +3 -1
- package/dist/features/seller/components/SellerProductsView.js +48 -54
- package/dist/features/seller/components/SellerShippingConfigsView.d.ts +7 -0
- package/dist/features/seller/components/SellerShippingConfigsView.js +149 -0
- package/dist/features/seller/components/SellerShippingView.js +37 -10
- package/dist/features/seller/components/SellerStoreCategoriesView.d.ts +9 -0
- package/dist/features/seller/components/SellerStoreCategoriesView.js +122 -0
- package/dist/features/seller/components/SellerStorefrontView.d.ts +0 -7
- package/dist/features/seller/components/SellerStorefrontView.js +26 -29
- package/dist/features/seller/components/SellerTemplatesView.d.ts +10 -0
- package/dist/features/seller/components/SellerTemplatesView.js +265 -0
- package/dist/features/seller/components/index.d.ts +26 -0
- package/dist/features/seller/components/index.js +13 -0
- package/dist/features/stores/api/[storeSlug]/reviews/route.js +49 -7
- package/dist/features/stores/components/StoreCapabilitiesGuideView.d.ts +3 -0
- package/dist/features/stores/components/StoreCapabilitiesGuideView.js +101 -0
- package/dist/features/stores/components/StoreFinanceGuideView.d.ts +3 -0
- package/dist/features/stores/components/StoreFinanceGuideView.js +79 -0
- package/dist/features/stores/components/StoreGuideHubView.d.ts +5 -0
- package/dist/features/stores/components/StoreGuideHubView.js +89 -0
- package/dist/features/stores/components/StoreListingsGuideView.d.ts +3 -0
- package/dist/features/stores/components/StoreListingsGuideView.js +151 -0
- package/dist/features/stores/components/StoreOrdersGuideView.d.ts +3 -0
- package/dist/features/stores/components/StoreOrdersGuideView.js +122 -0
- package/dist/features/stores/components/StoreReviewsListing.js +100 -23
- package/dist/features/stores/components/StoreSettingsGuideView.d.ts +3 -0
- package/dist/features/stores/components/StoreSettingsGuideView.js +56 -0
- package/dist/features/stores/components/index.d.ts +12 -1
- package/dist/features/stores/components/index.js +6 -1
- package/dist/features/stores/hooks/useStores.d.ts +5 -0
- package/dist/features/stores/hooks/useStores.js +10 -0
- package/dist/features/stores/manifest.js +1 -1
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +13 -2
- package/dist/index.d.ts +54 -9
- package/dist/index.js +58 -15
- package/dist/next/routing/route-map.d.ts +55 -0
- package/dist/next/routing/route-map.js +25 -0
- package/dist/providers/db-firebase/__tests__/filter-aliases.test.d.ts +1 -0
- package/dist/providers/db-firebase/__tests__/filter-aliases.test.js +93 -0
- package/dist/providers/db-firebase/sieve.d.ts +49 -0
- package/dist/providers/db-firebase/sieve.js +61 -8
- package/dist/repositories/index.d.ts +1 -0
- package/dist/repositories/index.js +2 -0
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/ListingToolbar.d.ts +8 -1
- package/dist/ui/components/ListingToolbar.js +4 -2
- package/dist/ui/components/__tests__/BulkActionBar.test.d.ts +1 -0
- package/dist/ui/components/__tests__/BulkActionBar.test.js +96 -0
- package/dist/ui/components/__tests__/ListingToolbar.test.d.ts +1 -0
- package/dist/ui/components/__tests__/ListingToolbar.test.js +125 -0
- package/dist/ui/index.d.ts +1 -1
- package/package.json +8 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
vi.mock("../../../../../repositories", () => ({
|
|
3
|
+
couponsRepository: {
|
|
4
|
+
getExpiredActiveRefs: vi.fn(),
|
|
5
|
+
deactivateInBatch: vi.fn(),
|
|
6
|
+
},
|
|
7
|
+
}));
|
|
8
|
+
import { runCouponExpiry } from "../couponExpiry";
|
|
9
|
+
import { couponsRepository } from "../../../../../repositories";
|
|
10
|
+
function makeBatch() {
|
|
11
|
+
return { commit: vi.fn().mockResolvedValue(undefined) };
|
|
12
|
+
}
|
|
13
|
+
function makeCtx(batchOverride) {
|
|
14
|
+
const batch = batchOverride ?? makeBatch();
|
|
15
|
+
return {
|
|
16
|
+
job: "coupon-expiry",
|
|
17
|
+
db: { batch: vi.fn(() => batch) },
|
|
18
|
+
logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn() },
|
|
19
|
+
env: vi.fn(),
|
|
20
|
+
now: new Date("2026-01-15T12:00:00Z"),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
vi.clearAllMocks();
|
|
25
|
+
});
|
|
26
|
+
describe("runCouponExpiry", () => {
|
|
27
|
+
it("returns early and does not commit when no expired coupons", async () => {
|
|
28
|
+
couponsRepository.getExpiredActiveRefs.mockResolvedValue([]);
|
|
29
|
+
const ctx = makeCtx();
|
|
30
|
+
await runCouponExpiry(ctx);
|
|
31
|
+
expect(ctx.db.batch).not.toHaveBeenCalled();
|
|
32
|
+
});
|
|
33
|
+
it("calls getExpiredActiveRefs with ctx.now", async () => {
|
|
34
|
+
couponsRepository.getExpiredActiveRefs.mockResolvedValue([]);
|
|
35
|
+
const ctx = makeCtx();
|
|
36
|
+
await runCouponExpiry(ctx);
|
|
37
|
+
expect(couponsRepository.getExpiredActiveRefs).toHaveBeenCalledWith(ctx.now);
|
|
38
|
+
});
|
|
39
|
+
it("deactivates each expired coupon in the batch", async () => {
|
|
40
|
+
const refs = [{ id: "coupon-1" }, { id: "coupon-2" }];
|
|
41
|
+
couponsRepository.getExpiredActiveRefs.mockResolvedValue(refs);
|
|
42
|
+
const batch = makeBatch();
|
|
43
|
+
const ctx = makeCtx(batch);
|
|
44
|
+
await runCouponExpiry(ctx);
|
|
45
|
+
expect(couponsRepository.deactivateInBatch).toHaveBeenCalledTimes(2);
|
|
46
|
+
expect(couponsRepository.deactivateInBatch).toHaveBeenCalledWith(batch, refs[0]);
|
|
47
|
+
expect(couponsRepository.deactivateInBatch).toHaveBeenCalledWith(batch, refs[1]);
|
|
48
|
+
});
|
|
49
|
+
it("commits the batch when there are expired coupons", async () => {
|
|
50
|
+
const refs = [{ id: "coupon-1" }];
|
|
51
|
+
couponsRepository.getExpiredActiveRefs.mockResolvedValue(refs);
|
|
52
|
+
const batch = makeBatch();
|
|
53
|
+
const ctx = makeCtx(batch);
|
|
54
|
+
await runCouponExpiry(ctx);
|
|
55
|
+
expect(batch.commit).toHaveBeenCalledOnce();
|
|
56
|
+
});
|
|
57
|
+
it("does not deactivate or commit when refs is empty", async () => {
|
|
58
|
+
couponsRepository.getExpiredActiveRefs.mockResolvedValue([]);
|
|
59
|
+
const batch = makeBatch();
|
|
60
|
+
const ctx = makeCtx(batch);
|
|
61
|
+
await runCouponExpiry(ctx);
|
|
62
|
+
expect(couponsRepository.deactivateInBatch).not.toHaveBeenCalled();
|
|
63
|
+
expect(batch.commit).not.toHaveBeenCalled();
|
|
64
|
+
});
|
|
65
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
// Mock all repository imports before importing the module under test.
|
|
3
|
+
vi.mock("../../../../../repositories", () => ({
|
|
4
|
+
productRepository: { list: vi.fn() },
|
|
5
|
+
blogRepository: { listAll: vi.fn() },
|
|
6
|
+
eventRepository: { list: vi.fn() },
|
|
7
|
+
couponsRepository: { list: vi.fn() },
|
|
8
|
+
storeRepository: { listStores: vi.fn() },
|
|
9
|
+
categoriesRepository: { list: vi.fn() },
|
|
10
|
+
bidRepository: { list: vi.fn() },
|
|
11
|
+
payoutRepository: { list: vi.fn() },
|
|
12
|
+
orderRepository: { listAll: vi.fn() },
|
|
13
|
+
reviewRepository: { listAll: vi.fn() },
|
|
14
|
+
faqsRepository: { list: vi.fn() },
|
|
15
|
+
notificationRepository: { list: vi.fn() },
|
|
16
|
+
scammerRepository: { listAll: vi.fn() },
|
|
17
|
+
productFeaturesRepository: { list: vi.fn() },
|
|
18
|
+
homepageSectionsRepository: { list: vi.fn() },
|
|
19
|
+
userRepository: { list: vi.fn() },
|
|
20
|
+
eventEntryRepository: { listForEvent: vi.fn() },
|
|
21
|
+
productTemplateRepository: { listByStore: vi.fn() },
|
|
22
|
+
}));
|
|
23
|
+
import { runListingProcessor } from "../listingProcessor";
|
|
24
|
+
import { productRepository, blogRepository, eventRepository, couponsRepository, storeRepository, } from "../../../../../repositories";
|
|
25
|
+
function makeCtx() {
|
|
26
|
+
return {
|
|
27
|
+
job: "test",
|
|
28
|
+
db: {},
|
|
29
|
+
logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn() },
|
|
30
|
+
env: vi.fn(),
|
|
31
|
+
now: new Date(),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const EMPTY_RESULT = {
|
|
35
|
+
items: [],
|
|
36
|
+
total: 0,
|
|
37
|
+
page: 1,
|
|
38
|
+
pageSize: 20,
|
|
39
|
+
totalPages: 0,
|
|
40
|
+
hasMore: false,
|
|
41
|
+
};
|
|
42
|
+
beforeEach(() => {
|
|
43
|
+
vi.clearAllMocks();
|
|
44
|
+
productRepository.list.mockResolvedValue(EMPTY_RESULT);
|
|
45
|
+
blogRepository.listAll.mockResolvedValue(EMPTY_RESULT);
|
|
46
|
+
eventRepository.list.mockResolvedValue(EMPTY_RESULT);
|
|
47
|
+
couponsRepository.list.mockResolvedValue(EMPTY_RESULT);
|
|
48
|
+
storeRepository.listStores.mockResolvedValue(EMPTY_RESULT);
|
|
49
|
+
});
|
|
50
|
+
describe("runListingProcessor", () => {
|
|
51
|
+
it("throws 400 when body is missing collection", async () => {
|
|
52
|
+
const ctx = makeCtx();
|
|
53
|
+
await expect(runListingProcessor({}, ctx)).rejects.toMatchObject({ httpStatus: 400, message: "Missing collection" });
|
|
54
|
+
});
|
|
55
|
+
it("throws 400 for an unsupported collection name", async () => {
|
|
56
|
+
const ctx = makeCtx();
|
|
57
|
+
await expect(runListingProcessor({ collection: "nonexistent" }, ctx)).rejects.toMatchObject({ httpStatus: 400 });
|
|
58
|
+
});
|
|
59
|
+
it("calls the correct lister for 'products'", async () => {
|
|
60
|
+
const ctx = makeCtx();
|
|
61
|
+
await runListingProcessor({ collection: "products", f: "status==published" }, ctx);
|
|
62
|
+
expect(productRepository.list).toHaveBeenCalledWith(expect.objectContaining({ filters: "status==published" }), {});
|
|
63
|
+
});
|
|
64
|
+
it("calls blogRepository for 'blogPosts'", async () => {
|
|
65
|
+
const ctx = makeCtx();
|
|
66
|
+
await runListingProcessor({ collection: "blogPosts" }, ctx);
|
|
67
|
+
expect(blogRepository.listAll).toHaveBeenCalled();
|
|
68
|
+
});
|
|
69
|
+
it("calls eventRepository for 'events'", async () => {
|
|
70
|
+
const ctx = makeCtx();
|
|
71
|
+
await runListingProcessor({ collection: "events" }, ctx);
|
|
72
|
+
expect(eventRepository.list).toHaveBeenCalled();
|
|
73
|
+
});
|
|
74
|
+
it("passes filters and sorts to the lister", async () => {
|
|
75
|
+
const ctx = makeCtx();
|
|
76
|
+
await runListingProcessor({
|
|
77
|
+
collection: "products",
|
|
78
|
+
f: "brand==hasbro",
|
|
79
|
+
s: "-price",
|
|
80
|
+
}, ctx);
|
|
81
|
+
expect(productRepository.list).toHaveBeenCalledWith(expect.objectContaining({ filters: "brand==hasbro", sorts: "-price" }), {});
|
|
82
|
+
});
|
|
83
|
+
it("uses default sort when s is absent", async () => {
|
|
84
|
+
const ctx = makeCtx();
|
|
85
|
+
await runListingProcessor({ collection: "products" }, ctx);
|
|
86
|
+
expect(productRepository.list).toHaveBeenCalledWith(expect.objectContaining({ sorts: "-createdAt" }), {});
|
|
87
|
+
});
|
|
88
|
+
it("clamps pageSize to MAX_PAGE_SIZE (100)", async () => {
|
|
89
|
+
const ctx = makeCtx();
|
|
90
|
+
await runListingProcessor({ collection: "products", ps: 999 }, ctx);
|
|
91
|
+
expect(productRepository.list).toHaveBeenCalledWith(expect.objectContaining({ pageSize: "100" }), {});
|
|
92
|
+
});
|
|
93
|
+
it("uses DEFAULT_PAGE_SIZE when ps is 0", async () => {
|
|
94
|
+
const ctx = makeCtx();
|
|
95
|
+
await runListingProcessor({ collection: "products", ps: 0 }, ctx);
|
|
96
|
+
expect(productRepository.list).toHaveBeenCalledWith(expect.objectContaining({ pageSize: "20" }), {});
|
|
97
|
+
});
|
|
98
|
+
it("uses DEFAULT_PAGE_SIZE when ps is negative", async () => {
|
|
99
|
+
const ctx = makeCtx();
|
|
100
|
+
await runListingProcessor({ collection: "products", ps: -5 }, ctx);
|
|
101
|
+
expect(productRepository.list).toHaveBeenCalledWith(expect.objectContaining({ pageSize: "20" }), {});
|
|
102
|
+
});
|
|
103
|
+
it("reads page from p param", async () => {
|
|
104
|
+
const ctx = makeCtx();
|
|
105
|
+
await runListingProcessor({ collection: "products", p: 3 }, ctx);
|
|
106
|
+
expect(productRepository.list).toHaveBeenCalledWith(expect.objectContaining({ page: "3" }), {});
|
|
107
|
+
});
|
|
108
|
+
it("decodes a valid cursor and uses its page over p", async () => {
|
|
109
|
+
// Encode page=5 as a cursor
|
|
110
|
+
const cursor = Buffer.from(JSON.stringify({ page: 5 }), "utf8").toString("base64");
|
|
111
|
+
const ctx = makeCtx();
|
|
112
|
+
await runListingProcessor({ collection: "products", cursor, p: 1 }, ctx);
|
|
113
|
+
expect(productRepository.list).toHaveBeenCalledWith(expect.objectContaining({ page: "5" }), {});
|
|
114
|
+
});
|
|
115
|
+
it("falls back to p when cursor is invalid base64 JSON", async () => {
|
|
116
|
+
const ctx = makeCtx();
|
|
117
|
+
await runListingProcessor({ collection: "products", cursor: "!!!notbase64!!!", p: 2 }, ctx);
|
|
118
|
+
expect(productRepository.list).toHaveBeenCalledWith(expect.objectContaining({ page: "2" }), {});
|
|
119
|
+
});
|
|
120
|
+
it("encodes the next cursor when hasMore is true", async () => {
|
|
121
|
+
productRepository.list.mockResolvedValue({
|
|
122
|
+
...EMPTY_RESULT,
|
|
123
|
+
hasMore: true,
|
|
124
|
+
page: 1,
|
|
125
|
+
});
|
|
126
|
+
const ctx = makeCtx();
|
|
127
|
+
const result = await runListingProcessor({ collection: "products", p: 1 }, ctx);
|
|
128
|
+
expect(result.cursor).not.toBeNull();
|
|
129
|
+
// Decode and verify it points to page 2
|
|
130
|
+
const decoded = JSON.parse(Buffer.from(result.cursor, "base64").toString("utf8"));
|
|
131
|
+
expect(decoded.page).toBe(2);
|
|
132
|
+
});
|
|
133
|
+
it("returns null cursor when hasMore is false", async () => {
|
|
134
|
+
const ctx = makeCtx();
|
|
135
|
+
const result = await runListingProcessor({ collection: "products" }, ctx);
|
|
136
|
+
expect(result.cursor).toBeNull();
|
|
137
|
+
});
|
|
138
|
+
it("passes baseOpts to the lister", async () => {
|
|
139
|
+
const ctx = makeCtx();
|
|
140
|
+
await runListingProcessor({
|
|
141
|
+
collection: "products",
|
|
142
|
+
baseOpts: { storeId: "store-abc" },
|
|
143
|
+
}, ctx);
|
|
144
|
+
expect(productRepository.list).toHaveBeenCalledWith(expect.any(Object), { storeId: "store-abc" });
|
|
145
|
+
});
|
|
146
|
+
it("calls stores lister with activeOnly=true by default", async () => {
|
|
147
|
+
const ctx = makeCtx();
|
|
148
|
+
await runListingProcessor({ collection: "stores" }, ctx);
|
|
149
|
+
expect(storeRepository.listStores).toHaveBeenCalledWith(expect.any(Object), true);
|
|
150
|
+
});
|
|
151
|
+
it("returns the items from the lister result", async () => {
|
|
152
|
+
const items = [{ id: "p1" }, { id: "p2" }];
|
|
153
|
+
productRepository.list.mockResolvedValue({
|
|
154
|
+
...EMPTY_RESULT,
|
|
155
|
+
items,
|
|
156
|
+
total: 2,
|
|
157
|
+
});
|
|
158
|
+
const ctx = makeCtx();
|
|
159
|
+
const result = await runListingProcessor({ collection: "products" }, ctx);
|
|
160
|
+
expect(result.items).toEqual(items);
|
|
161
|
+
expect(result.total).toBe(2);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
vi.mock("../../../../../providers/db-firebase/admin-storage-lite", () => ({
|
|
3
|
+
getAdminStorageLite: vi.fn(),
|
|
4
|
+
}));
|
|
5
|
+
import { runMediaTmpCleanup } from "../mediaTmpCleanup";
|
|
6
|
+
import { getAdminStorageLite } from "../../../../../providers/db-firebase/admin-storage-lite";
|
|
7
|
+
function makeCtx(envOverrides = {}) {
|
|
8
|
+
return {
|
|
9
|
+
job: "media-tmp-cleanup",
|
|
10
|
+
db: {},
|
|
11
|
+
logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn() },
|
|
12
|
+
env: (key) => envOverrides[key],
|
|
13
|
+
now: new Date("2026-01-15T12:00:00Z"),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function makeFile(name, updatedOffset, cutoffBase) {
|
|
17
|
+
const updated = new Date(cutoffBase.getTime() + updatedOffset).toISOString();
|
|
18
|
+
return {
|
|
19
|
+
name,
|
|
20
|
+
getMetadata: vi.fn().mockResolvedValue([{ updated }]),
|
|
21
|
+
delete: vi.fn().mockResolvedValue(undefined),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function setupBucket(files) {
|
|
25
|
+
const bucket = {
|
|
26
|
+
getFiles: vi.fn().mockResolvedValue([files]),
|
|
27
|
+
};
|
|
28
|
+
getAdminStorageLite.mockReturnValue({
|
|
29
|
+
bucket: vi.fn(() => bucket),
|
|
30
|
+
});
|
|
31
|
+
return bucket;
|
|
32
|
+
}
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
vi.clearAllMocks();
|
|
35
|
+
delete process.env.FIREBASE_ADMIN_STORAGE_BUCKET;
|
|
36
|
+
delete process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET;
|
|
37
|
+
});
|
|
38
|
+
describe("runMediaTmpCleanup", () => {
|
|
39
|
+
it("does nothing when no files exist under tmp/", async () => {
|
|
40
|
+
setupBucket([]);
|
|
41
|
+
const ctx = makeCtx();
|
|
42
|
+
await runMediaTmpCleanup(ctx);
|
|
43
|
+
// Should complete without error
|
|
44
|
+
});
|
|
45
|
+
it("skips files newer than the TTL cutoff", async () => {
|
|
46
|
+
// cutoff = now - 24h; file updated 1ms AFTER cutoff → not stale
|
|
47
|
+
const ctx = makeCtx();
|
|
48
|
+
const cutoff = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
|
49
|
+
const newFile = makeFile("tmp/new-file.jpg", 1000, cutoff); // updated after cutoff
|
|
50
|
+
setupBucket([newFile]);
|
|
51
|
+
await runMediaTmpCleanup(ctx);
|
|
52
|
+
expect(newFile.delete).not.toHaveBeenCalled();
|
|
53
|
+
});
|
|
54
|
+
it("deletes files older than the TTL cutoff", async () => {
|
|
55
|
+
const ctx = makeCtx();
|
|
56
|
+
const cutoff = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
|
57
|
+
const oldFile = makeFile("tmp/old-file.jpg", -1000, cutoff); // updated before cutoff
|
|
58
|
+
setupBucket([oldFile]);
|
|
59
|
+
await runMediaTmpCleanup(ctx);
|
|
60
|
+
expect(oldFile.delete).toHaveBeenCalledOnce();
|
|
61
|
+
});
|
|
62
|
+
it("uses MEDIA_TMP_TTL_HOURS env var to override default TTL", async () => {
|
|
63
|
+
const ctx = makeCtx({ MEDIA_TMP_TTL_HOURS: "1" });
|
|
64
|
+
// With 1h TTL, cutoff = now - 1h
|
|
65
|
+
// A file updated 2h ago should be deleted
|
|
66
|
+
const cutoff = new Date(Date.now() - 1 * 60 * 60 * 1000);
|
|
67
|
+
const twoHourOldFile = makeFile("tmp/old.jpg", -60 * 60 * 1000, cutoff);
|
|
68
|
+
setupBucket([twoHourOldFile]);
|
|
69
|
+
await runMediaTmpCleanup(ctx);
|
|
70
|
+
expect(twoHourOldFile.delete).toHaveBeenCalledOnce();
|
|
71
|
+
});
|
|
72
|
+
it("swallows 404 errors without logging them as errors", async () => {
|
|
73
|
+
const ctx = makeCtx();
|
|
74
|
+
const cutoff = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
|
75
|
+
const staleFile = makeFile("tmp/gone.jpg", -1000, cutoff);
|
|
76
|
+
const notFoundErr = Object.assign(new Error("Not found"), { code: 404 });
|
|
77
|
+
staleFile.delete.mockRejectedValue(notFoundErr);
|
|
78
|
+
setupBucket([staleFile]);
|
|
79
|
+
await expect(runMediaTmpCleanup(ctx)).resolves.toBeUndefined();
|
|
80
|
+
expect(ctx.logger.error).not.toHaveBeenCalledWith("Failed to delete tmp file", expect.anything(), expect.anything());
|
|
81
|
+
});
|
|
82
|
+
it("logs a non-404 delete error but continues processing", async () => {
|
|
83
|
+
const ctx = makeCtx();
|
|
84
|
+
const cutoff = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
|
85
|
+
const failFile = makeFile("tmp/fail.jpg", -1000, cutoff);
|
|
86
|
+
const okFile = makeFile("tmp/ok.jpg", -2000, cutoff);
|
|
87
|
+
const genericErr = Object.assign(new Error("Permission denied"), { code: 403 });
|
|
88
|
+
failFile.delete.mockRejectedValue(genericErr);
|
|
89
|
+
setupBucket([failFile, okFile]);
|
|
90
|
+
await runMediaTmpCleanup(ctx);
|
|
91
|
+
expect(ctx.logger.error).toHaveBeenCalledWith("Failed to delete tmp file", genericErr, expect.any(Object));
|
|
92
|
+
expect(okFile.delete).toHaveBeenCalledOnce();
|
|
93
|
+
});
|
|
94
|
+
it("skips files missing updated/timeCreated metadata", async () => {
|
|
95
|
+
const ctx = makeCtx();
|
|
96
|
+
const noMetaFile = {
|
|
97
|
+
name: "tmp/no-meta.jpg",
|
|
98
|
+
getMetadata: vi.fn().mockResolvedValue([{}]),
|
|
99
|
+
delete: vi.fn(),
|
|
100
|
+
};
|
|
101
|
+
setupBucket([noMetaFile]);
|
|
102
|
+
await runMediaTmpCleanup(ctx);
|
|
103
|
+
expect(noMetaFile.delete).not.toHaveBeenCalled();
|
|
104
|
+
});
|
|
105
|
+
it("throws when bucket.getFiles itself fails", async () => {
|
|
106
|
+
const bucket = {
|
|
107
|
+
getFiles: vi.fn().mockRejectedValue(new Error("Storage unavailable")),
|
|
108
|
+
};
|
|
109
|
+
getAdminStorageLite.mockReturnValue({
|
|
110
|
+
bucket: vi.fn(() => bucket),
|
|
111
|
+
});
|
|
112
|
+
const ctx = makeCtx();
|
|
113
|
+
await expect(runMediaTmpCleanup(ctx)).rejects.toThrow("Storage unavailable");
|
|
114
|
+
});
|
|
115
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
vi.mock("../../../../../repositories", () => ({
|
|
3
|
+
orderRepository: {
|
|
4
|
+
getTimedOutPending: vi.fn(),
|
|
5
|
+
cancelInBatch: vi.fn(),
|
|
6
|
+
},
|
|
7
|
+
}));
|
|
8
|
+
vi.mock("../../../../../features/admin/actions/notification-actions", () => ({
|
|
9
|
+
sendNotification: vi.fn().mockResolvedValue(undefined),
|
|
10
|
+
}));
|
|
11
|
+
vi.mock("../../handlers/messages", () => ({
|
|
12
|
+
ORDER_MESSAGES: {
|
|
13
|
+
CANCELLED_TITLE: "Order cancelled",
|
|
14
|
+
CANCELLED_TIMEOUT_MESSAGE: (title, hours) => `${title} cancelled after ${hours}h`,
|
|
15
|
+
},
|
|
16
|
+
}));
|
|
17
|
+
import { runPendingOrderTimeout } from "../pendingOrderTimeout";
|
|
18
|
+
import { orderRepository } from "../../../../../repositories";
|
|
19
|
+
import { sendNotification } from "../../../../../features/admin/actions/notification-actions";
|
|
20
|
+
function makeBatch() {
|
|
21
|
+
return { commit: vi.fn().mockResolvedValue(undefined) };
|
|
22
|
+
}
|
|
23
|
+
function makeCtxWithBatch(envOverrides = {}) {
|
|
24
|
+
const batch = makeBatch();
|
|
25
|
+
const ctx = {
|
|
26
|
+
job: "pending-order-timeout",
|
|
27
|
+
db: { batch: vi.fn(() => batch) },
|
|
28
|
+
logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn() },
|
|
29
|
+
env: (key) => envOverrides[key],
|
|
30
|
+
now: new Date("2026-01-15T12:00:00Z"),
|
|
31
|
+
};
|
|
32
|
+
return { ctx, batch };
|
|
33
|
+
}
|
|
34
|
+
function makeCtx(envOverrides = {}) {
|
|
35
|
+
return makeCtxWithBatch(envOverrides).ctx;
|
|
36
|
+
}
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
vi.clearAllMocks();
|
|
39
|
+
sendNotification.mockResolvedValue(undefined);
|
|
40
|
+
});
|
|
41
|
+
describe("runPendingOrderTimeout", () => {
|
|
42
|
+
it("returns early when no timed-out orders exist", async () => {
|
|
43
|
+
orderRepository.getTimedOutPending.mockResolvedValue([]);
|
|
44
|
+
const ctx = makeCtx();
|
|
45
|
+
await runPendingOrderTimeout(ctx);
|
|
46
|
+
expect(ctx.db.batch).not.toHaveBeenCalled();
|
|
47
|
+
expect(sendNotification).not.toHaveBeenCalled();
|
|
48
|
+
});
|
|
49
|
+
it("uses DEFAULT_TIMEOUT_HOURS (24) when env var is unset", async () => {
|
|
50
|
+
orderRepository.getTimedOutPending.mockResolvedValue([]);
|
|
51
|
+
const ctx = makeCtx();
|
|
52
|
+
await runPendingOrderTimeout(ctx);
|
|
53
|
+
expect(orderRepository.getTimedOutPending).toHaveBeenCalledWith(24);
|
|
54
|
+
});
|
|
55
|
+
it("uses ORDER_TIMEOUT_HOURS from env when set", async () => {
|
|
56
|
+
orderRepository.getTimedOutPending.mockResolvedValue([]);
|
|
57
|
+
const ctx = makeCtx({ ORDER_TIMEOUT_HOURS: "48" });
|
|
58
|
+
await runPendingOrderTimeout(ctx);
|
|
59
|
+
expect(orderRepository.getTimedOutPending).toHaveBeenCalledWith(48);
|
|
60
|
+
});
|
|
61
|
+
it("cancels timed-out orders in the batch", async () => {
|
|
62
|
+
const ref1 = { id: "order-ref-1" };
|
|
63
|
+
const ref2 = { id: "order-ref-2" };
|
|
64
|
+
const timedOut = [
|
|
65
|
+
{ ref: ref1, data: { userId: "u1", productTitle: "Charizard", id: "order-1" } },
|
|
66
|
+
{ ref: ref2, data: { userId: "u2", productTitle: "Blastoise", id: "order-2" } },
|
|
67
|
+
];
|
|
68
|
+
orderRepository.getTimedOutPending.mockResolvedValue(timedOut);
|
|
69
|
+
const { ctx, batch } = makeCtxWithBatch();
|
|
70
|
+
await runPendingOrderTimeout(ctx);
|
|
71
|
+
expect(orderRepository.cancelInBatch).toHaveBeenCalledTimes(2);
|
|
72
|
+
expect(orderRepository.cancelInBatch).toHaveBeenCalledWith(batch, ref1);
|
|
73
|
+
expect(orderRepository.cancelInBatch).toHaveBeenCalledWith(batch, ref2);
|
|
74
|
+
expect(batch.commit).toHaveBeenCalledOnce();
|
|
75
|
+
});
|
|
76
|
+
it("sends a notification for each cancelled order", async () => {
|
|
77
|
+
const timedOut = [
|
|
78
|
+
{ ref: {}, data: { userId: "u1", productTitle: "Charizard", id: "order-1" } },
|
|
79
|
+
{ ref: {}, data: { userId: "u2", productTitle: "Blastoise", id: "order-2" } },
|
|
80
|
+
];
|
|
81
|
+
orderRepository.getTimedOutPending.mockResolvedValue(timedOut);
|
|
82
|
+
const ctx = makeCtx();
|
|
83
|
+
await runPendingOrderTimeout(ctx);
|
|
84
|
+
expect(sendNotification).toHaveBeenCalledTimes(2);
|
|
85
|
+
expect(sendNotification).toHaveBeenCalledWith(expect.objectContaining({ userId: "u1", type: "order_cancelled", relatedId: "order-1" }));
|
|
86
|
+
});
|
|
87
|
+
it("does not throw when a notification fails (Promise.allSettled)", async () => {
|
|
88
|
+
const timedOut = [
|
|
89
|
+
{ ref: {}, data: { userId: "u1", productTitle: "Pikachu", id: "order-x" } },
|
|
90
|
+
];
|
|
91
|
+
orderRepository.getTimedOutPending.mockResolvedValue(timedOut);
|
|
92
|
+
sendNotification.mockRejectedValue(new Error("Notification failed"));
|
|
93
|
+
const ctx = makeCtx();
|
|
94
|
+
await expect(runPendingOrderTimeout(ctx)).resolves.toBeUndefined();
|
|
95
|
+
});
|
|
96
|
+
});
|
package/dist/client.d.ts
CHANGED
|
@@ -57,6 +57,8 @@ export type { SessionProviderProps } from "./react/contexts/SessionContext";
|
|
|
57
57
|
export { ThemeProvider } from "./react/contexts/ThemeContext";
|
|
58
58
|
export { useUrlTable } from "./react/hooks/useUrlTable";
|
|
59
59
|
export type { UseUrlTableOptions } from "./react/hooks/useUrlTable";
|
|
60
|
+
export { useBulkSelection } from "./react/hooks/useBulkSelection";
|
|
61
|
+
export type { UseBulkSelectionOptions, UseBulkSelectionReturn } from "./react/hooks/useBulkSelection";
|
|
60
62
|
export { ROUTES, PUBLIC_ROUTES, PROTECTED_ROUTES, AUTH_ROUTES } from "./constants/index";
|
|
61
63
|
export { Container, Grid, Row, Stack } from "./ui/components/Layout";
|
|
62
64
|
export { Div } from "./ui/components/Div";
|
|
@@ -99,9 +101,11 @@ export { ZodSetup } from "./validation/ZodSetup";
|
|
|
99
101
|
export type { ZodSetupProps } from "./validation/ZodSetup";
|
|
100
102
|
export { AdminSidebar } from "./features/admin/components/AdminSidebar";
|
|
101
103
|
export type { AdminSidebarProps, AdminNavItem, AdminNavGroup } from "./features/admin/components/AdminSidebar";
|
|
102
|
-
export { AdminDashboardView, AdminAnalyticsView, AdminListingScaffold, AdminPrizeDrawsView, useAdminListingData, toRecordArray, toStringValue, toRelativeDate, toRupees } from "./features/admin/index";
|
|
103
|
-
export type { AdminDashboardViewProps, AdminAnalyticsViewProps, AdminAnalyticsViewLabels, AdminPrizeDrawsViewProps } from "./features/admin/index";
|
|
104
|
+
export { AdminDashboardView, AdminAnalyticsView, AdminListingScaffold, AdminPrizeDrawsView, AdminCarouselView, AdminSublistingCategoriesView, DataTable, useAdminListingData, toRecordArray, toStringValue, toRelativeDate, toRupees } from "./features/admin/index";
|
|
105
|
+
export type { AdminDashboardViewProps, AdminAnalyticsViewProps, AdminAnalyticsViewLabels, AdminPrizeDrawsViewProps, AdminCarouselViewProps } from "./features/admin/index";
|
|
106
|
+
export type { BulkActionItem } from "./ui/components/BulkActionBar";
|
|
104
107
|
export { ADMIN_ENDPOINTS } from "./constants/index";
|
|
108
|
+
export { apiClient, ApiClientError } from "./http/index";
|
|
105
109
|
export { UserSidebar } from "./features/account/components/UserSidebar";
|
|
106
110
|
export type { UserSidebarProps, UserNavItem, UserNavGroup } from "./features/account/components/UserSidebar";
|
|
107
111
|
export { CouponsIndexListing } from "./features/promotions/components/CouponsIndexListing";
|
|
@@ -122,10 +126,9 @@ export type { Address, AddressFormData } from "./features/account/index";
|
|
|
122
126
|
export { AddressBook, AddressCard, AddressForm } from "./features/account/index";
|
|
123
127
|
export type { AddressCardAddress, AddressCardProps } from "./features/account/index";
|
|
124
128
|
export { useProfile, useUpdateProfile } from "./features/account/index";
|
|
125
|
-
export { CategoryProductsView
|
|
129
|
+
export { CategoryProductsView } from "./features/categories/index";
|
|
126
130
|
export type { CategoryItem } from "./features/categories/index";
|
|
127
131
|
export { MediaImage } from "./features/media/index";
|
|
128
|
-
export { ReviewsListView } from "./features/reviews/index";
|
|
129
132
|
export { StoreSidebar, SellerSidebar } from "./features/seller/components/SellerSidebar";
|
|
130
133
|
export type { StoreNavItem, StoreNavGroup, SellerNavItem } from "./features/seller/components/SellerSidebar";
|
|
131
134
|
export { StoreProductsView, StoreAboutView } from "./features/stores/index";
|
|
@@ -147,6 +150,8 @@ export type { WishlistCapEventDetail } from "./features/wishlist/hooks/useWishli
|
|
|
147
150
|
export { getGuestWishlistItems, addToGuestWishlist, removeFromGuestWishlist, isInGuestWishlist, clearGuestWishlist, getGuestWishlistCount, getGuestWishlistByType, } from "./features/wishlist/utils/guest-wishlist";
|
|
148
151
|
export { InteractiveProductCard } from "./features/products/index";
|
|
149
152
|
export type { InteractiveProductCardProps } from "./features/products/index";
|
|
153
|
+
export { MarketplaceBundleCard } from "./features/products/components/MarketplaceBundleCard";
|
|
154
|
+
export type { MarketplaceBundleCardProps, MarketplaceBundleCardData, MarketplaceBundleCardLabels, } from "./features/products/components/MarketplaceBundleCard";
|
|
150
155
|
export { CompareOverlay } from "./features/products/components/CompareOverlay";
|
|
151
156
|
export type { CompareOverlayProps, CompareOverlayLabels, CompareProductLike, } from "./features/products/components/CompareOverlay";
|
|
152
157
|
export { COMPARE_MAX_ITEMS } from "./features/products/constants/action-defs";
|
|
@@ -189,8 +194,8 @@ export { UserOffersPanel } from "./features/account/components/UserOffersPanel";
|
|
|
189
194
|
export type { UserOffersPanelProps } from "./features/account/components/UserOffersPanel";
|
|
190
195
|
export { SellerDashboardView as StoreDashboardView, SellerDashboardView, useSellerDashboard as useStoreDashboard, useSellerDashboard } from "./features/seller/index";
|
|
191
196
|
export type { SellerDashboardViewProps as StoreDashboardViewProps, SellerDashboardViewProps } from "./features/seller/index";
|
|
192
|
-
export { SellerPayoutSettingsView, SellerShippingView, SellerReviewsView, SellerPayoutRequestView, SellerAnalyticsStats, SellerTopProducts, SellerAnalyticsView, SellerPayoutsView, SellerCouponEditorView, SellerBidsView, SellerAddressesView, SellerPreOrdersView, SellerPrizeDrawsView, PrintCenterView } from "./features/seller/components/index";
|
|
193
|
-
export type { SellerPayoutSettingsViewProps, SellerShippingViewProps, SellerReviewsViewProps, SellerPayoutRequestViewProps, SellerAnalyticsViewProps, SellerPayoutsViewProps, SellerCouponEditorViewProps, CouponEditorDraft, SellerBidsViewProps, SellerAddressesViewProps, SellerPreOrdersViewProps, SellerPrizeDrawsViewProps } from "./features/seller/components/index";
|
|
197
|
+
export { SellerPayoutSettingsView, SellerShippingView, SellerReviewsView, SellerPayoutRequestView, SellerAnalyticsStats, SellerTopProducts, SellerAnalyticsView, SellerPayoutsView, SellerCouponEditorView, SellerBidsView, SellerAddressesView, SellerPreOrdersView, SellerPrizeDrawsView, PrintCenterView, SellerOffersView, SellerGroupedListingsView, StoreGroupedListingsView, SellerAnalyticsAlertsView, StoreAnalyticsAlertsView } from "./features/seller/components/index";
|
|
198
|
+
export type { SellerPayoutSettingsViewProps, SellerShippingViewProps, SellerReviewsViewProps, SellerPayoutRequestViewProps, SellerAnalyticsViewProps, SellerPayoutsViewProps, SellerCouponEditorViewProps, CouponEditorDraft, SellerBidsViewProps, SellerAddressesViewProps, SellerPreOrdersViewProps, SellerPrizeDrawsViewProps, SellerOffersViewProps, SellerGroupedListingsViewProps, SellerAnalyticsAlertsViewProps } from "./features/seller/components/index";
|
|
194
199
|
export type { SellerAnalyticsSummary, SellerAnalyticsTopProduct } from "./features/seller/types/index";
|
|
195
200
|
export { UserAccountHubView, UserOrdersView, OrderDetailView, UserNotificationsView, UserReturnsView, UserSupportView, useNotifications } from "./features/account/index";
|
|
196
201
|
export type { UserAccountHubViewProps, UserAccountHubViewLabels, UserOrdersViewProps, UserOrdersViewLabels, OrderDetailViewProps, OrderDetailViewLabels, UserNotificationsViewProps, UserNotificationsViewLabels, UserReturnsViewProps, UserReturnsViewLabels, UserSupportViewProps } from "./features/account/index";
|
|
@@ -248,3 +253,21 @@ export { PhysicalLocationModal } from "./features/seller/components/PhysicalLoca
|
|
|
248
253
|
export type { PhysicalLocation } from "./features/seller/components/PhysicalLocationModal";
|
|
249
254
|
export { Toggle } from "./ui/components/Toggle";
|
|
250
255
|
export type { ToggleProps } from "./ui/components/Toggle";
|
|
256
|
+
export { SellerStoreCategoriesView } from "./features/seller/components/SellerStoreCategoriesView";
|
|
257
|
+
export type { SellerStoreCategoriesViewProps } from "./features/seller/components/SellerStoreCategoriesView";
|
|
258
|
+
export { SellerTemplatesView } from "./features/seller/components/SellerTemplatesView";
|
|
259
|
+
export type { SellerTemplatesViewProps } from "./features/seller/components/SellerTemplatesView";
|
|
260
|
+
export { SellerPayoutMethodsView } from "./features/seller/components/SellerPayoutMethodsView";
|
|
261
|
+
export type { SellerPayoutMethodsViewProps } from "./features/seller/components/SellerPayoutMethodsView";
|
|
262
|
+
export { SellerShippingConfigsView } from "./features/seller/components/SellerShippingConfigsView";
|
|
263
|
+
export type { SellerShippingConfigsViewProps } from "./features/seller/components/SellerShippingConfigsView";
|
|
264
|
+
export { SellerGoogleReviewsView } from "./features/seller/components/SellerGoogleReviewsView";
|
|
265
|
+
export type { SellerGoogleReviewsViewProps } from "./features/seller/components/SellerGoogleReviewsView";
|
|
266
|
+
export { SellerBundlesView } from "./features/seller/components/SellerBundlesView";
|
|
267
|
+
export type { SellerBundlesViewProps } from "./features/seller/components/SellerBundlesView";
|
|
268
|
+
export { SellerClassifiedView } from "./features/seller/components/SellerClassifiedView";
|
|
269
|
+
export type { SellerClassifiedViewProps } from "./features/seller/components/SellerClassifiedView";
|
|
270
|
+
export { SellerDigitalCodesView } from "./features/seller/components/SellerDigitalCodesView";
|
|
271
|
+
export type { SellerDigitalCodesViewProps } from "./features/seller/components/SellerDigitalCodesView";
|
|
272
|
+
export { SellerLiveView } from "./features/seller/components/SellerLiveView";
|
|
273
|
+
export type { SellerLiveViewProps } from "./features/seller/components/SellerLiveView";
|
package/dist/client.js
CHANGED
|
@@ -121,6 +121,7 @@ export { useMediaUpload } from "./features/media/index";
|
|
|
121
121
|
export { SessionProvider, useSession } from "./react/contexts/SessionContext";
|
|
122
122
|
export { ThemeProvider } from "./react/contexts/ThemeContext";
|
|
123
123
|
export { useUrlTable } from "./react/hooks/useUrlTable";
|
|
124
|
+
export { useBulkSelection } from "./react/hooks/useBulkSelection";
|
|
124
125
|
// Client-safe constants, UI primitives, and views
|
|
125
126
|
export { ROUTES, PUBLIC_ROUTES, PROTECTED_ROUTES, AUTH_ROUTES } from "./constants/index";
|
|
126
127
|
export { Container, Grid, Row, Stack } from "./ui/components/Layout";
|
|
@@ -149,8 +150,9 @@ export { Search } from "./features/search/components";
|
|
|
149
150
|
export { ToastProvider, SkipToMain, NavigationLoader } from "./ui/index";
|
|
150
151
|
export { ZodSetup } from "./validation/ZodSetup";
|
|
151
152
|
export { AdminSidebar } from "./features/admin/components/AdminSidebar";
|
|
152
|
-
export { AdminDashboardView, AdminAnalyticsView, AdminListingScaffold, AdminPrizeDrawsView, useAdminListingData, toRecordArray, toStringValue, toRelativeDate, toRupees } from "./features/admin/index";
|
|
153
|
+
export { AdminDashboardView, AdminAnalyticsView, AdminListingScaffold, AdminPrizeDrawsView, AdminCarouselView, AdminSublistingCategoriesView, DataTable, useAdminListingData, toRecordArray, toStringValue, toRelativeDate, toRupees } from "./features/admin/index";
|
|
153
154
|
export { ADMIN_ENDPOINTS } from "./constants/index";
|
|
155
|
+
export { apiClient, ApiClientError } from "./http/index";
|
|
154
156
|
export { UserSidebar } from "./features/account/components/UserSidebar";
|
|
155
157
|
export { CouponsIndexListing } from "./features/promotions/components/CouponsIndexListing";
|
|
156
158
|
export { NotificationBell } from "./features/account/components/NotificationBell";
|
|
@@ -162,9 +164,8 @@ export { CartView, CartItemRow, CartSummary, CartDrawer, CheckoutView, CheckoutS
|
|
|
162
164
|
export { useAddresses, useCreateAddress, useUpdateAddress, useDeleteAddress, useSetDefaultAddress, useAddress } from "./features/account/index";
|
|
163
165
|
export { AddressBook, AddressCard, AddressForm } from "./features/account/index";
|
|
164
166
|
export { useProfile, useUpdateProfile } from "./features/account/index";
|
|
165
|
-
export { CategoryProductsView
|
|
167
|
+
export { CategoryProductsView } from "./features/categories/index";
|
|
166
168
|
export { MediaImage } from "./features/media/index";
|
|
167
|
-
export { ReviewsListView } from "./features/reviews/index";
|
|
168
169
|
export { StoreSidebar, SellerSidebar } from "./features/seller/components/SellerSidebar";
|
|
169
170
|
export { StoreProductsView, StoreAboutView } from "./features/stores/index";
|
|
170
171
|
export { SearchView } from "./features/search/index";
|
|
@@ -177,6 +178,7 @@ export { WishlistCapWatcher } from "./features/wishlist/components/WishlistCapWa
|
|
|
177
178
|
export { useWishlistCount, useWishlistCountWithLimit, WISHLIST_CAP_EVENT } from "./features/wishlist/hooks/useWishlistCount";
|
|
178
179
|
export { getGuestWishlistItems, addToGuestWishlist, removeFromGuestWishlist, isInGuestWishlist, clearGuestWishlist, getGuestWishlistCount, getGuestWishlistByType, } from "./features/wishlist/utils/guest-wishlist";
|
|
179
180
|
export { InteractiveProductCard } from "./features/products/index";
|
|
181
|
+
export { MarketplaceBundleCard } from "./features/products/components/MarketplaceBundleCard";
|
|
180
182
|
export { CompareOverlay } from "./features/products/components/CompareOverlay";
|
|
181
183
|
export { COMPARE_MAX_ITEMS } from "./features/products/constants/action-defs";
|
|
182
184
|
// Messages — RTDB-pinged Firestore conversations (D5 + VC7)
|
|
@@ -208,7 +210,7 @@ export { FeatureBadge, FeatureBadgeList } from "./features/products/components/F
|
|
|
208
210
|
export { SellerOffersPanel } from "./features/seller/components/SellerOffersPanel";
|
|
209
211
|
export { UserOffersPanel } from "./features/account/components/UserOffersPanel";
|
|
210
212
|
export { SellerDashboardView as StoreDashboardView, SellerDashboardView, useSellerDashboard as useStoreDashboard, useSellerDashboard } from "./features/seller/index";
|
|
211
|
-
export { SellerPayoutSettingsView, SellerShippingView, SellerReviewsView, SellerPayoutRequestView, SellerAnalyticsStats, SellerTopProducts, SellerAnalyticsView, SellerPayoutsView, SellerCouponEditorView, SellerBidsView, SellerAddressesView, SellerPreOrdersView, SellerPrizeDrawsView, PrintCenterView } from "./features/seller/components/index";
|
|
213
|
+
export { SellerPayoutSettingsView, SellerShippingView, SellerReviewsView, SellerPayoutRequestView, SellerAnalyticsStats, SellerTopProducts, SellerAnalyticsView, SellerPayoutsView, SellerCouponEditorView, SellerBidsView, SellerAddressesView, SellerPreOrdersView, SellerPrizeDrawsView, PrintCenterView, SellerOffersView, SellerGroupedListingsView, StoreGroupedListingsView, SellerAnalyticsAlertsView, StoreAnalyticsAlertsView } from "./features/seller/components/index";
|
|
212
214
|
export { UserAccountHubView, UserOrdersView, OrderDetailView, UserNotificationsView, UserReturnsView, UserSupportView, useNotifications } from "./features/account/index";
|
|
213
215
|
export { useOrders, useOrder, OrdersList } from "./features/orders/index";
|
|
214
216
|
export { useCouponValidate } from "./features/promotions/hooks/useCouponValidate";
|
|
@@ -258,3 +260,13 @@ export { LiveItemDetailView } from "./_internal/client/features/live/LiveItemDet
|
|
|
258
260
|
export { PhysicalLocationModal } from "./features/seller/components/PhysicalLocationModal";
|
|
259
261
|
// [CLIENT-ONLY] — Toggle switch primitive.
|
|
260
262
|
export { Toggle } from "./ui/components/Toggle";
|
|
263
|
+
// [CLIENT] Wave 4 seller management views.
|
|
264
|
+
export { SellerStoreCategoriesView } from "./features/seller/components/SellerStoreCategoriesView";
|
|
265
|
+
export { SellerTemplatesView } from "./features/seller/components/SellerTemplatesView";
|
|
266
|
+
export { SellerPayoutMethodsView } from "./features/seller/components/SellerPayoutMethodsView";
|
|
267
|
+
export { SellerShippingConfigsView } from "./features/seller/components/SellerShippingConfigsView";
|
|
268
|
+
export { SellerGoogleReviewsView } from "./features/seller/components/SellerGoogleReviewsView";
|
|
269
|
+
export { SellerBundlesView } from "./features/seller/components/SellerBundlesView";
|
|
270
|
+
export { SellerClassifiedView } from "./features/seller/components/SellerClassifiedView";
|
|
271
|
+
export { SellerDigitalCodesView } from "./features/seller/components/SellerDigitalCodesView";
|
|
272
|
+
export { SellerLiveView } from "./features/seller/components/SellerLiveView";
|