@mohasinac/appkit 2.8.5 → 2.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/_internal/server/features/checkout/actions.js +2 -1
  2. package/dist/_internal/server/features/grouped/data.js +9 -8
  3. package/dist/_internal/server/features/products/data.js +2 -1
  4. package/dist/_internal/server/features/refunds/actions.js +2 -1
  5. package/dist/_internal/server/features/seo/sitemap.js +2 -1
  6. package/dist/_internal/server/jobs/core/countersReconcile.js +4 -4
  7. package/dist/_internal/shared/features/blog/schema.d.ts +4 -4
  8. package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +8 -8
  9. package/dist/constants/field-names.d.ts +3 -0
  10. package/dist/constants/field-names.js +3 -0
  11. package/dist/features/admin/repository/chat.repository.js +7 -6
  12. package/dist/features/auctions/components/AuctionBottomActions.js +3 -4
  13. package/dist/features/auctions/repository/bid.repository.js +12 -12
  14. package/dist/features/blog/actions/blog-actions.d.ts +2 -2
  15. package/dist/features/blog/schemas/index.d.ts +1 -1
  16. package/dist/features/cart/repository/cart.repository.js +2 -1
  17. package/dist/features/categories/repository/categories.repository.js +26 -25
  18. package/dist/features/categories/schemas/firestore.d.ts +1 -0
  19. package/dist/features/categories/schemas/firestore.js +1 -0
  20. package/dist/features/categories/schemas/index.d.ts +10 -10
  21. package/dist/features/events/components/EventParticipateView.js +2 -1
  22. package/dist/features/events/schemas/index.d.ts +3 -3
  23. package/dist/features/faq/actions/faq-actions.d.ts +6 -6
  24. package/dist/features/faq/repository/faqs.repository.js +21 -20
  25. package/dist/features/faq/schemas/index.d.ts +2 -2
  26. package/dist/features/homepage/repository/carousel.repository.js +8 -7
  27. package/dist/features/homepage/repository/carousels.repository.js +2 -1
  28. package/dist/features/homepage/repository/homepage-sections.repository.js +6 -5
  29. package/dist/features/messages/repository/conversations.repository.js +5 -4
  30. package/dist/features/orders/repository/orders.repository.js +13 -13
  31. package/dist/features/products/repository/product-features.repository.js +7 -6
  32. package/dist/features/products/repository/product-templates.repository.js +4 -3
  33. package/dist/features/products/repository/products.repository.js +4 -4
  34. package/dist/features/promotions/repository/claimed-coupons.repository.js +2 -1
  35. package/dist/features/promotions/repository/coupons.repository.js +4 -4
  36. package/dist/features/reviews/repository/reviews.repository.js +2 -2
  37. package/dist/features/scams/repository/scammer.repository.js +3 -3
  38. package/dist/features/search/components/Search.js +11 -0
  39. package/dist/features/support/repository/support.repository.js +8 -7
  40. package/dist/seed/products-auctions-seed-data.js +107 -0
  41. package/package.json +1 -1
@@ -7,6 +7,7 @@
7
7
  * concerns; the action only does transactional order placement.
8
8
  */
9
9
  import { ApiError, ValidationError, NotFoundError, ERROR_MESSAGES } from "../../../../errors";
10
+ import { ORDER_FIELDS } from "../../../../constants/field-names";
10
11
  import { serverLogger } from "../../../../monitoring";
11
12
  import { unitOfWork, siteSettingsRepository, userRepository, storeRepository, couponsRepository, notificationRepository, claimedCouponsRepository, } from "../../../../repositories";
12
13
  import { failedCheckoutRepository } from "../../../../features/checkout/repository/failed-checkout.repository";
@@ -38,7 +39,7 @@ async function claimDigitalCodeForOrder(db, productId, orderId, userId, opts) {
38
39
  .collection(PRODUCT_COLLECTION)
39
40
  .doc(productId)
40
41
  .collection(PRODUCT_CODES_SUBCOLLECTION);
41
- const snap = await codesRef.where("status", "==", "available").limit(1).get();
42
+ const snap = await codesRef.where(ORDER_FIELDS.STATUS, "==", "available").limit(1).get();
42
43
  if (snap.empty) {
43
44
  serverLogger.warn("claimDigitalCode: code pool exhausted", { productId, orderId });
44
45
  return;
@@ -2,6 +2,7 @@ import { cache } from "react";
2
2
  import { getAdminDb } from "../../../../providers/db-firebase";
3
3
  import { GROUPED_LISTINGS_COLLECTION, } from "../../../../features/grouped/schemas/firestore";
4
4
  import { productRepository } from "../../../../repositories";
5
+ import { PRODUCT_FIELDS, CATEGORY_FIELDS } from "../../../../constants/field-names";
5
6
  import { GROUPED_LISTINGS_FEATURED_LIMIT, GROUPED_LISTINGS_PAGE_SIZE, GROUPED_LISTINGS_SITEMAP_LIMIT, } from "../../../shared/features/grouped/config";
6
7
  function mapDoc(doc) {
7
8
  const data = doc.data();
@@ -43,7 +44,7 @@ export const getGroupedListingForDetail = cache(async (slug) => {
43
44
  const db = getAdminDb();
44
45
  const snap = await db
45
46
  .collection(GROUPED_LISTINGS_COLLECTION)
46
- .where("slug", "==", slug)
47
+ .where(CATEGORY_FIELDS.SLUG, "==", slug)
47
48
  .limit(1)
48
49
  .get();
49
50
  if (snap.empty) {
@@ -77,17 +78,17 @@ export async function listGroupedListings(params = {}) {
77
78
  const db = getAdminDb();
78
79
  let q = db
79
80
  .collection(GROUPED_LISTINGS_COLLECTION)
80
- .where("isActive", "==", true);
81
+ .where(CATEGORY_FIELDS.IS_ACTIVE, "==", true);
81
82
  if (params.featuredOnly)
82
- q = q.where("isFeatured", "==", true);
83
+ q = q.where(CATEGORY_FIELDS.IS_FEATURED, "==", true);
83
84
  if (params.storeId)
84
- q = q.where("storeId", "==", params.storeId);
85
+ q = q.where(PRODUCT_FIELDS.STORE_ID, "==", params.storeId);
85
86
  if (params.brandSlug)
86
- q = q.where("brandSlug", "==", params.brandSlug);
87
+ q = q.where(PRODUCT_FIELDS.BRAND_SLUG, "==", params.brandSlug);
87
88
  if (params.categorySlug)
88
- q = q.where("categorySlug", "==", params.categorySlug);
89
+ q = q.where(PRODUCT_FIELDS.CATEGORY_SLUG, "==", params.categorySlug);
89
90
  const snap = await q
90
- .orderBy("createdAt", "desc")
91
+ .orderBy(PRODUCT_FIELDS.CREATED_AT, "desc")
91
92
  .limit(params.limit ?? GROUPED_LISTINGS_PAGE_SIZE)
92
93
  .get();
93
94
  return snap.docs.map(mapDoc);
@@ -105,7 +106,7 @@ export async function listSitemapGroupedListings() {
105
106
  const db = getAdminDb();
106
107
  const snap = await db
107
108
  .collection(GROUPED_LISTINGS_COLLECTION)
108
- .where("isActive", "==", true)
109
+ .where(CATEGORY_FIELDS.IS_ACTIVE, "==", true)
109
110
  .select("slug", "updatedAt")
110
111
  .limit(GROUPED_LISTINGS_SITEMAP_LIMIT)
111
112
  .get();
@@ -4,6 +4,7 @@ import { reviewRepository } from "../../../../repositories";
4
4
  import { getAdminDb } from "../../../../providers/db-firebase";
5
5
  import { PRODUCT_COLLECTION } from "../../../../features/products/schemas/firestore";
6
6
  import { PRODUCTS_SITEMAP_LIMIT } from "../../../shared/features/products/config";
7
+ import { PRODUCT_FIELDS } from "../../../../constants/field-names";
7
8
  // ---------------------------------------------------------------------------
8
9
  // Request-scoped cache — each function is deduplicated per RSC render tree.
9
10
  // Both generateMetadata() and the page component get the same promise.
@@ -22,7 +23,7 @@ export async function listSitemapProducts() {
22
23
  const db = getAdminDb();
23
24
  const snapshot = await db
24
25
  .collection(PRODUCT_COLLECTION)
25
- .where("status", "==", "published")
26
+ .where(PRODUCT_FIELDS.STATUS, "==", "published")
26
27
  .select("slug", "id", "updatedAt", "listingType")
27
28
  .limit(PRODUCTS_SITEMAP_LIMIT)
28
29
  .get();
@@ -16,6 +16,7 @@
16
16
  import { randomUUID } from "crypto";
17
17
  import { getProviders } from "../../../../contracts/registry";
18
18
  import { orderRepository } from "../../../..";
19
+ import { ORDER_FIELDS } from "../../../../constants/field-names";
19
20
  import { NotFoundError, ValidationError } from "../../../../errors";
20
21
  import { serverLogger } from "../../../../monitoring";
21
22
  import { applyRefundDeductionAction } from "../payouts/actions";
@@ -93,7 +94,7 @@ export async function processRefundAction(input) {
93
94
  .doc(item.productId)
94
95
  .collection(PRODUCT_CODES_SUBCOLLECTION)
95
96
  .where("orderId", "==", input.orderId)
96
- .where("status", "==", "available")
97
+ .where(ORDER_FIELDS.STATUS, "==", "available")
97
98
  .limit(1)
98
99
  .get()
99
100
  .then((snap) => {
@@ -7,6 +7,7 @@ import { CATEGORIES_COLLECTION, CATEGORY_FIELDS } from "../../../../features/cat
7
7
  import { STORE_COLLECTION, STORE_FIELDS } from "../../../../features/stores";
8
8
  import { SCAMMER_COLLECTION } from "../../../../features/scams/schemas/firestore";
9
9
  import { serverLogger } from "../../../../monitoring/server-logger";
10
+ import { PRODUCT_FIELDS } from "../../../../constants/field-names";
10
11
  // Product field strings — matches consumer field-names.ts
11
12
  const PRODUCT_STATUS = "status";
12
13
  const PRODUCT_STATUS_PUBLISHED = "published";
@@ -211,7 +212,7 @@ async function fetchScammerUrls(baseUrl) {
211
212
  const db = getAdminDb();
212
213
  const snap = await db
213
214
  .collection(SCAMMER_COLLECTION)
214
- .where("status", "==", "verified")
215
+ .where(PRODUCT_FIELDS.STATUS, "==", "verified")
215
216
  .select("seo", "updatedAt")
216
217
  .limit(2000)
217
218
  .get();
@@ -7,7 +7,7 @@ const ORDERS_COLLECTION = "orders";
7
7
  async function reconcileCategories(ctx) {
8
8
  const snap = await ctx.db
9
9
  .collection(PRODUCT_COLLECTION)
10
- .where("status", "==", ProductStatusValues.PUBLISHED)
10
+ .where(ORDER_FIELDS.STATUS, "==", ProductStatusValues.PUBLISHED)
11
11
  .limit(QUERY_LIMIT)
12
12
  .get();
13
13
  ctx.logger.info(`[categories] ${snap.size} published products found`);
@@ -63,13 +63,13 @@ async function reconcileStores(ctx) {
63
63
  const [productsSnap, ordersSnap, reviewStats] = await Promise.all([
64
64
  ctx.db
65
65
  .collection(PRODUCT_COLLECTION)
66
- .where("sellerId", "==", sellerId)
67
- .where("status", "==", ProductStatusValues.PUBLISHED)
66
+ .where(ORDER_FIELDS.SELLER_ID, "==", sellerId)
67
+ .where(ORDER_FIELDS.STATUS, "==", ProductStatusValues.PUBLISHED)
68
68
  .limit(QUERY_LIMIT)
69
69
  .get(),
70
70
  ctx.db
71
71
  .collection(ORDERS_COLLECTION)
72
- .where("sellerId", "==", sellerId)
72
+ .where(ORDER_FIELDS.SELLER_ID, "==", sellerId)
73
73
  .where(ORDER_FIELDS.STATUS, "==", ORDER_FIELDS.STATUS_VALUES.DELIVERED)
74
74
  .limit(QUERY_LIMIT)
75
75
  .get(),
@@ -21,8 +21,8 @@ export declare const blogPostInputSchema: z.ZodObject<{
21
21
  content: string;
22
22
  isFeatured: boolean;
23
23
  youtubeId?: string | undefined;
24
- coverImage?: string | undefined;
25
24
  excerpt?: string | undefined;
25
+ coverImage?: string | undefined;
26
26
  metaTitle?: string | undefined;
27
27
  metaDescription?: string | undefined;
28
28
  }, {
@@ -34,8 +34,8 @@ export declare const blogPostInputSchema: z.ZodObject<{
34
34
  youtubeId?: string | undefined;
35
35
  tags?: string[] | undefined;
36
36
  isFeatured?: boolean | undefined;
37
- coverImage?: string | undefined;
38
37
  excerpt?: string | undefined;
38
+ coverImage?: string | undefined;
39
39
  metaTitle?: string | undefined;
40
40
  metaDescription?: string | undefined;
41
41
  }>;
@@ -60,8 +60,8 @@ export declare const blogPostUpdateSchema: z.ZodObject<Omit<{
60
60
  tags?: string[] | undefined;
61
61
  content?: string | undefined;
62
62
  isFeatured?: boolean | undefined;
63
- coverImage?: string | undefined;
64
63
  excerpt?: string | undefined;
64
+ coverImage?: string | undefined;
65
65
  metaTitle?: string | undefined;
66
66
  metaDescription?: string | undefined;
67
67
  }, {
@@ -72,8 +72,8 @@ export declare const blogPostUpdateSchema: z.ZodObject<Omit<{
72
72
  tags?: string[] | undefined;
73
73
  content?: string | undefined;
74
74
  isFeatured?: boolean | undefined;
75
- coverImage?: string | undefined;
76
75
  excerpt?: string | undefined;
76
+ coverImage?: string | undefined;
77
77
  metaTitle?: string | undefined;
78
78
  metaDescription?: string | undefined;
79
79
  }>;
@@ -314,6 +314,10 @@ export declare const bundleUpdateSchema: z.ZodObject<{
314
314
  isActive?: boolean | undefined;
315
315
  bundleProductIds?: string[] | undefined;
316
316
  bundleKind?: "brand" | "special" | undefined;
317
+ bundleItemDetails?: {
318
+ productId: string;
319
+ drawCount?: number | undefined;
320
+ }[] | undefined;
317
321
  bundlePriceInPaise?: number | undefined;
318
322
  bundleQueryRule?: {
319
323
  type: "static";
@@ -329,10 +333,6 @@ export declare const bundleUpdateSchema: z.ZodObject<{
329
333
  limit: number;
330
334
  orderBy?: "price-asc" | "price-desc" | "createdAt-desc" | undefined;
331
335
  } | undefined;
332
- bundleItemDetails?: {
333
- productId: string;
334
- drawCount?: number | undefined;
335
- }[] | undefined;
336
336
  }, {
337
337
  description?: string | undefined;
338
338
  name?: string | undefined;
@@ -344,6 +344,10 @@ export declare const bundleUpdateSchema: z.ZodObject<{
344
344
  isActive?: boolean | undefined;
345
345
  bundleProductIds?: string[] | undefined;
346
346
  bundleKind?: "brand" | "special" | undefined;
347
+ bundleItemDetails?: {
348
+ productId: string;
349
+ drawCount?: number | undefined;
350
+ }[] | undefined;
347
351
  bundlePriceInPaise?: number | undefined;
348
352
  bundleQueryRule?: {
349
353
  type: "static";
@@ -359,10 +363,6 @@ export declare const bundleUpdateSchema: z.ZodObject<{
359
363
  limit: number;
360
364
  orderBy?: "price-asc" | "price-desc" | "createdAt-desc" | undefined;
361
365
  } | undefined;
362
- bundleItemDetails?: {
363
- productId: string;
364
- drawCount?: number | undefined;
365
- }[] | undefined;
366
366
  }>;
367
367
  export type BundleCreateBody = z.infer<typeof bundleCreateSchema>;
368
368
  export type BundleUpdateBody = z.infer<typeof bundleUpdateSchema>;
@@ -410,6 +410,7 @@ export declare const CATEGORY_FIELDS: {
410
410
  readonly IS_FEATURED: "isFeatured";
411
411
  readonly SHOW_ON_HOMEPAGE: "showOnHomepage";
412
412
  readonly ICON: "icon";
413
+ readonly ORDER: "order";
413
414
  readonly DISPLAY_ORDER: "displayOrder";
414
415
  readonly IS_ACTIVE: "isActive";
415
416
  readonly CATEGORY_TYPE: "categoryType";
@@ -599,6 +600,7 @@ export declare const SUPPORT_TICKET_FIELDS: {
599
600
  readonly USER_ID: "userId";
600
601
  readonly STORE_ID: "storeId";
601
602
  readonly SUBJECT: "subject";
603
+ readonly CATEGORY: "category";
602
604
  readonly STATUS: "status";
603
605
  readonly PRIORITY: "priority";
604
606
  readonly CREATED_AT: "createdAt";
@@ -620,6 +622,7 @@ export declare const SUPPORT_TICKET_FIELDS: {
620
622
  };
621
623
  export declare const CAROUSEL_FIELDS: {
622
624
  readonly ID: "id";
625
+ readonly NAME: "name";
623
626
  readonly TITLE: "title";
624
627
  readonly ORDER: "order";
625
628
  readonly ACTIVE: "active";
@@ -449,6 +449,7 @@ export const CATEGORY_FIELDS = {
449
449
  IS_FEATURED: "isFeatured",
450
450
  SHOW_ON_HOMEPAGE: "showOnHomepage",
451
451
  ICON: "icon",
452
+ ORDER: "order",
452
453
  DISPLAY_ORDER: "displayOrder",
453
454
  IS_ACTIVE: "isActive",
454
455
  // SB-UNI — categoryType discriminator (category/brand/sublisting/bundle)
@@ -679,6 +680,7 @@ export const SUPPORT_TICKET_FIELDS = {
679
680
  USER_ID: "userId",
680
681
  STORE_ID: "storeId",
681
682
  SUBJECT: "subject",
683
+ CATEGORY: "category",
682
684
  STATUS: "status",
683
685
  PRIORITY: "priority",
684
686
  CREATED_AT: "createdAt",
@@ -703,6 +705,7 @@ export const SUPPORT_TICKET_FIELDS = {
703
705
  // ============================================================================
704
706
  export const CAROUSEL_FIELDS = {
705
707
  ID: "id",
708
+ NAME: "name",
706
709
  TITLE: "title",
707
710
  ORDER: "order",
708
711
  ACTIVE: "active",
@@ -22,6 +22,7 @@ import { getAdminRealtimeDb } from "../../../providers/db-firebase";
22
22
  import { BaseRepository } from "../../../providers/db-firebase";
23
23
  import { prepareForFirestore } from "../../../providers/db-firebase";
24
24
  import { DatabaseError } from "../../../errors";
25
+ import { CONVERSATION_FIELDS, STORE_FIELDS } from "../../../constants/field-names";
25
26
  import { CHAT_ROOM_COLLECTION } from "../schemas";
26
27
  import { encryptPiiFields, decryptPiiFields, CHAT_PII_FIELDS, } from "../../../security";
27
28
  export { CHAT_ROOM_COLLECTION } from "../schemas";
@@ -72,11 +73,11 @@ class ChatRepository extends BaseRepository {
72
73
  try {
73
74
  const [asBuyer, asSeller] = await Promise.all([
74
75
  this.getCollection()
75
- .where("buyerId", "==", userId)
76
+ .where(CONVERSATION_FIELDS.BUYER_ID, "==", userId)
76
77
  .where("adminDeleted", "==", false)
77
78
  .get(),
78
79
  this.getCollection()
79
- .where("ownerId", "==", userId)
80
+ .where(STORE_FIELDS.OWNER_ID, "==", userId)
80
81
  .where("adminDeleted", "==", false)
81
82
  .get(),
82
83
  ]);
@@ -101,14 +102,14 @@ class ChatRepository extends BaseRepository {
101
102
  try {
102
103
  const [asBuyer, asSeller] = await Promise.all([
103
104
  this.getCollection()
104
- .where("buyerId", "==", userId)
105
+ .where(CONVERSATION_FIELDS.BUYER_ID, "==", userId)
105
106
  .where("adminDeleted", "==", false)
106
- .orderBy("updatedAt", "desc")
107
+ .orderBy(CONVERSATION_FIELDS.UPDATED_AT, "desc")
107
108
  .get(),
108
109
  this.getCollection()
109
- .where("ownerId", "==", userId)
110
+ .where(STORE_FIELDS.OWNER_ID, "==", userId)
110
111
  .where("adminDeleted", "==", false)
111
- .orderBy("updatedAt", "desc")
112
+ .orderBy(CONVERSATION_FIELDS.UPDATED_AT, "desc")
112
113
  .get(),
113
114
  ]);
114
115
  const seen = new Set();
@@ -1,16 +1,15 @@
1
1
  "use client";
2
2
  import { useBottomActions } from "../../layout/hooks/useBottomActions";
3
3
  import { formatCurrency } from "../../../utils/number.formatter";
4
- import { ACTION_ID } from "../../products/constants/action-defs";
4
+ import { ACTION_ID, ACTION_META } from "../../products/constants/action-defs";
5
5
  export function AuctionBottomActions({ currentBid, currency, bidCount, isEnded, }) {
6
+ const placeBidMeta = ACTION_META[ACTION_ID.PLACE_BID];
6
7
  useBottomActions(isEnded
7
8
  ? {}
8
9
  : {
9
10
  actions: [
10
11
  {
11
- id: ACTION_ID.PLACE_BID,
12
- label: "Place Bid",
13
- variant: "primary",
12
+ ...placeBidMeta,
14
13
  onClick: () => {
15
14
  document
16
15
  .getElementById("auction-bid-form")
@@ -63,7 +63,7 @@ export class BidRepository extends BaseRepository {
63
63
  let query = this.db
64
64
  .collection(this.collection)
65
65
  .where(BID_FIELDS.USER_ID, "==", userId)
66
- .orderBy("createdAt", "desc")
66
+ .orderBy(BID_FIELDS.CREATED_AT, "desc")
67
67
  .limit(pageSize + 1);
68
68
  if (startAfterDoc)
69
69
  query = query.startAfter(startAfterDoc);
@@ -86,7 +86,7 @@ export class BidRepository extends BaseRepository {
86
86
  .collection(this.collection)
87
87
  .where(BID_FIELDS.PRODUCT_ID, "==", productId)
88
88
  .where(BID_FIELDS.STATUS, "==", "active")
89
- .orderBy("bidAmount", "desc")
89
+ .orderBy(BID_FIELDS.BID_AMOUNT, "desc")
90
90
  .get();
91
91
  return snapshot.docs.map((doc) => ({
92
92
  id: doc.id,
@@ -169,9 +169,9 @@ export class BidRepository extends BaseRepository {
169
169
  try {
170
170
  const snapshot = await this.db
171
171
  .collection(this.collection)
172
- .where("productId", "==", productId)
173
- .where("status", "==", "active")
174
- .orderBy("bidAmount", "desc")
172
+ .where(BID_FIELDS.PRODUCT_ID, "==", productId)
173
+ .where(BID_FIELDS.STATUS, "==", "active")
174
+ .orderBy(BID_FIELDS.BID_AMOUNT, "desc")
175
175
  .limit(1)
176
176
  .get();
177
177
  if (snapshot.empty) {
@@ -192,8 +192,8 @@ export class BidRepository extends BaseRepository {
192
192
  try {
193
193
  const snapshot = await this.db
194
194
  .collection(this.collection)
195
- .where("productId", "==", productId)
196
- .orderBy("bidAmount", "desc")
195
+ .where(BID_FIELDS.PRODUCT_ID, "==", productId)
196
+ .orderBy(BID_FIELDS.BID_AMOUNT, "desc")
197
197
  .get();
198
198
  return snapshot.docs.map((doc) => this.mapDoc(doc));
199
199
  }
@@ -230,7 +230,7 @@ export class BidRepository extends BaseRepository {
230
230
  // Set all bids for this product to not winning
231
231
  const allBidsSnapshot = await this.db
232
232
  .collection(this.collection)
233
- .where("productId", "==", productId)
233
+ .where(BID_FIELDS.PRODUCT_ID, "==", productId)
234
234
  .get();
235
235
  allBidsSnapshot.docs.forEach((doc) => {
236
236
  batch.update(doc.ref, {
@@ -260,7 +260,7 @@ export class BidRepository extends BaseRepository {
260
260
  const batch = this.db.batch();
261
261
  const bidsSnapshot = await this.db
262
262
  .collection(this.collection)
263
- .where("productId", "==", productId)
263
+ .where(BID_FIELDS.PRODUCT_ID, "==", productId)
264
264
  .get();
265
265
  bidsSnapshot.docs.forEach((doc) => {
266
266
  const bid = doc.data();
@@ -283,7 +283,7 @@ export class BidRepository extends BaseRepository {
283
283
  const batch = this.db.batch();
284
284
  const bidsSnapshot = await this.db
285
285
  .collection(this.collection)
286
- .where("productId", "==", productId)
286
+ .where(BID_FIELDS.PRODUCT_ID, "==", productId)
287
287
  .get();
288
288
  bidsSnapshot.docs.forEach((doc) => {
289
289
  batch.update(doc.ref, {
@@ -303,7 +303,7 @@ export class BidRepository extends BaseRepository {
303
303
  */
304
304
  async countByProduct(productId) {
305
305
  try {
306
- return await getFirestoreCount(this.db.collection(this.collection).where("productId", "==", productId));
306
+ return await getFirestoreCount(this.db.collection(this.collection).where(BID_FIELDS.PRODUCT_ID, "==", productId));
307
307
  }
308
308
  catch (error) {
309
309
  throw new DatabaseError(`Failed to count bids for product: ${productId}`, error);
@@ -314,7 +314,7 @@ export class BidRepository extends BaseRepository {
314
314
  */
315
315
  async countByUser(userId) {
316
316
  try {
317
- return await getFirestoreCount(this.db.collection(this.collection).where("userId", "==", userId));
317
+ return await getFirestoreCount(this.db.collection(this.collection).where(BID_FIELDS.USER_ID, "==", userId));
318
318
  }
319
319
  catch (error) {
320
320
  throw new DatabaseError(`Failed to count bids for user: ${userId}`, error);
@@ -216,6 +216,7 @@ export declare const updateBlogPostSchema: z.ZodObject<{
216
216
  content?: string | undefined;
217
217
  isFeatured?: boolean | undefined;
218
218
  publishedAt?: string | undefined;
219
+ excerpt?: string | undefined;
219
220
  coverImage?: {
220
221
  url: string;
221
222
  type: "image" | "video" | "file";
@@ -225,7 +226,6 @@ export declare const updateBlogPostSchema: z.ZodObject<{
225
226
  url: string;
226
227
  type: "image";
227
228
  } | null | undefined;
228
- excerpt?: string | undefined;
229
229
  authorId?: string | undefined;
230
230
  authorName?: string | undefined;
231
231
  readTimeMinutes?: number | undefined;
@@ -253,13 +253,13 @@ export declare const updateBlogPostSchema: z.ZodObject<{
253
253
  content?: string | undefined;
254
254
  isFeatured?: boolean | undefined;
255
255
  publishedAt?: string | undefined;
256
+ excerpt?: string | undefined;
256
257
  coverImage?: string | {
257
258
  url: string;
258
259
  type: "image" | "video" | "file";
259
260
  alt?: string | undefined;
260
261
  thumbnailUrl?: string | undefined;
261
262
  } | null | undefined;
262
- excerpt?: string | undefined;
263
263
  authorId?: string | undefined;
264
264
  authorName?: string | undefined;
265
265
  readTimeMinutes?: number | undefined;
@@ -180,6 +180,7 @@ export declare const blogPostSchema: z.ZodObject<{
180
180
  content?: string | undefined;
181
181
  isFeatured?: boolean | undefined;
182
182
  publishedAt?: string | undefined;
183
+ excerpt?: string | undefined;
183
184
  coverImage?: string | {
184
185
  url: string;
185
186
  type: "image" | "video" | "file";
@@ -188,7 +189,6 @@ export declare const blogPostSchema: z.ZodObject<{
188
189
  source?: "upload" | "youtube" | "external" | undefined;
189
190
  youtubeId?: string | undefined;
190
191
  } | null | undefined;
191
- excerpt?: string | undefined;
192
192
  authorId?: string | undefined;
193
193
  authorName?: string | undefined;
194
194
  readTimeMinutes?: number | undefined;
@@ -1,5 +1,6 @@
1
1
  import { randomUUID } from "crypto";
2
2
  import { DatabaseError, NotFoundError, ValidationError } from "../../../errors";
3
+ import { CART_FIELDS } from "../../../constants/field-names";
3
4
  const ERR_CART_ITEM_NOT_FOUND = "Cart item not found";
4
5
  const ERR_CART_ITEM_LOCKED = "This item requires payment and cannot be removed or modified.";
5
6
  import { BaseRepository, prepareForFirestore, } from "../../../providers/db-firebase";
@@ -277,7 +278,7 @@ export class CartRepository extends BaseRepository {
277
278
  cutoff.setDate(cutoff.getDate() - ttlDays);
278
279
  const snap = await this.db
279
280
  .collection(this.collection)
280
- .where("updatedAt", "<", cutoff)
281
+ .where(CART_FIELDS.UPDATED_AT, "<", cutoff)
281
282
  .limit(500)
282
283
  .get();
283
284
  return snap.docs.map((d) => d.ref);
@@ -1,6 +1,7 @@
1
1
  import { increment, arrayUnion, arrayRemove, } from "../../../contracts/field-ops";
2
2
  import { DatabaseError } from "../../../errors";
3
3
  import { BaseRepository, prepareForFirestore, } from "../../../providers/db-firebase";
4
+ import { PRODUCT_FIELDS } from "../../../constants/field-names";
4
5
  import { CATEGORY_FIELDS, CATEGORIES_COLLECTION, MIN_ITEMS_FOR_FEATURED, buildCategoryTree, calculateCategoryFields, canBeFeatured, createCategoryId, isValidCategoryMove, } from "../schemas";
5
6
  export class CategoriesRepository extends BaseRepository {
6
7
  constructor() {
@@ -80,9 +81,9 @@ export class CategoriesRepository extends BaseRepository {
80
81
  try {
81
82
  const snapshot = await this.db
82
83
  .collection(this.collection)
83
- .where("tier", "==", 0)
84
- .where("isActive", "==", true)
85
- .orderBy("order", "asc")
84
+ .where(CATEGORY_FIELDS.TIER, "==", 0)
85
+ .where(CATEGORY_FIELDS.IS_ACTIVE, "==", true)
86
+ .orderBy(CATEGORY_FIELDS.ORDER, "asc")
86
87
  .get();
87
88
  return snapshot.docs
88
89
  .map((doc) => this.mapDoc(doc))
@@ -96,8 +97,8 @@ export class CategoriesRepository extends BaseRepository {
96
97
  try {
97
98
  const snapshot = await this.db
98
99
  .collection(this.collection)
99
- .where("isLeaf", "==", true)
100
- .where("isActive", "==", true)
100
+ .where(CATEGORY_FIELDS.IS_LEAF, "==", true)
101
+ .where(CATEGORY_FIELDS.IS_ACTIVE, "==", true)
101
102
  .limit(500)
102
103
  .get();
103
104
  return snapshot.docs.map((doc) => this.mapDoc(doc));
@@ -110,9 +111,9 @@ export class CategoriesRepository extends BaseRepository {
110
111
  try {
111
112
  const snapshot = await this.db
112
113
  .collection(this.collection)
113
- .where("tier", "==", tier)
114
- .where("isActive", "==", true)
115
- .orderBy("order", "asc")
114
+ .where(CATEGORY_FIELDS.TIER, "==", tier)
115
+ .where(CATEGORY_FIELDS.IS_ACTIVE, "==", true)
116
+ .orderBy(CATEGORY_FIELDS.ORDER, "asc")
116
117
  .get();
117
118
  return snapshot.docs
118
119
  .map((doc) => this.mapDoc(doc))
@@ -126,9 +127,9 @@ export class CategoriesRepository extends BaseRepository {
126
127
  try {
127
128
  const snapshot = await this.db
128
129
  .collection(this.collection)
129
- .where("rootId", "==", rootId)
130
- .orderBy("tier", "asc")
131
- .orderBy("order", "asc")
130
+ .where(CATEGORY_FIELDS.ROOT_ID, "==", rootId)
131
+ .orderBy(CATEGORY_FIELDS.TIER, "asc")
132
+ .orderBy(CATEGORY_FIELDS.ORDER, "asc")
132
133
  .get();
133
134
  return snapshot.docs.map((doc) => this.mapDoc(doc));
134
135
  }
@@ -141,7 +142,7 @@ export class CategoriesRepository extends BaseRepository {
141
142
  const snapshot = await this.db
142
143
  .collection(this.collection)
143
144
  .where("parentIds", "array-contains", parentId)
144
- .orderBy("order", "asc")
145
+ .orderBy(CATEGORY_FIELDS.ORDER, "asc")
145
146
  .limit(100)
146
147
  .get();
147
148
  return snapshot.docs
@@ -156,8 +157,8 @@ export class CategoriesRepository extends BaseRepository {
156
157
  try {
157
158
  const snapshot = await this.db
158
159
  .collection(this.collection)
159
- .where("isFeatured", "==", true)
160
- .where("isActive", "==", true)
160
+ .where(CATEGORY_FIELDS.IS_FEATURED, "==", true)
161
+ .where(CATEGORY_FIELDS.IS_ACTIVE, "==", true)
161
162
  .orderBy("featuredPriority", "asc")
162
163
  .get();
163
164
  return snapshot.docs
@@ -173,8 +174,8 @@ export class CategoriesRepository extends BaseRepository {
173
174
  const snapshot = await this.db
174
175
  .collection(this.collection)
175
176
  .where("isBrand", "==", true)
176
- .where("isActive", "==", true)
177
- .orderBy("order", "asc")
177
+ .where(CATEGORY_FIELDS.IS_ACTIVE, "==", true)
178
+ .orderBy(CATEGORY_FIELDS.ORDER, "asc")
178
179
  .get();
179
180
  const brands = snapshot.docs.map((doc) => this.mapDoc(doc));
180
181
  return limit > 0 ? brands.slice(0, limit) : brands;
@@ -368,9 +369,9 @@ export class CategoriesRepository extends BaseRepository {
368
369
  async listByType(type, opts = {}) {
369
370
  let q = this.db
370
371
  .collection(this.collection)
371
- .where("categoryType", "==", type);
372
+ .where(CATEGORY_FIELDS.CATEGORY_TYPE, "==", type);
372
373
  if (opts.activeOnly)
373
- q = q.where("isActive", "==", true);
374
+ q = q.where(CATEGORY_FIELDS.IS_ACTIVE, "==", true);
374
375
  if (opts.limit)
375
376
  q = q.limit(opts.limit);
376
377
  const snap = await q.get();
@@ -380,10 +381,10 @@ export class CategoriesRepository extends BaseRepository {
380
381
  async findBySlugAndType(slug, type) {
381
382
  let q = this.db
382
383
  .collection(this.collection)
383
- .where("slug", "==", slug)
384
+ .where(CATEGORY_FIELDS.SLUG, "==", slug)
384
385
  .limit(1);
385
386
  if (type)
386
- q = q.where("categoryType", "==", type);
387
+ q = q.where(CATEGORY_FIELDS.CATEGORY_TYPE, "==", type);
387
388
  const snap = await q.get();
388
389
  if (snap.empty)
389
390
  return null;
@@ -398,8 +399,8 @@ export class CategoriesRepository extends BaseRepository {
398
399
  const snap = await this.db
399
400
  .collection("products")
400
401
  .where("sublistingCategoryId", "==", sublistingId)
401
- .where("status", "==", "published")
402
- .orderBy("price", "asc")
402
+ .where(PRODUCT_FIELDS.STATUS, "==", "published")
403
+ .orderBy(PRODUCT_FIELDS.PRICE, "asc")
403
404
  .limit(limit)
404
405
  .get();
405
406
  return snap.docs.map((d) => ({ id: d.id, ...d.data() }));
@@ -428,9 +429,9 @@ export class CategoriesRepository extends BaseRepository {
428
429
  async findActiveBrands() {
429
430
  const snap = await this.db
430
431
  .collection(this.collection)
431
- .where("categoryType", "==", "brand")
432
- .where("isActive", "==", true)
433
- .orderBy("order", "asc")
432
+ .where(CATEGORY_FIELDS.CATEGORY_TYPE, "==", "brand")
433
+ .where(CATEGORY_FIELDS.IS_ACTIVE, "==", true)
434
+ .orderBy(CATEGORY_FIELDS.ORDER, "asc")
434
435
  .get();
435
436
  return snap.docs.map((d) => this.mapDoc(d));
436
437
  }
@@ -244,6 +244,7 @@ export declare const CATEGORY_FIELDS: {
244
244
  readonly DISPLAY: "display";
245
245
  readonly IS_ACTIVE: "isActive";
246
246
  readonly IS_SEARCHABLE: "isSearchable";
247
+ readonly CATEGORY_TYPE: "categoryType";
247
248
  readonly CREATED_BY: "createdBy";
248
249
  readonly CREATED_AT: "createdAt";
249
250
  readonly UPDATED_AT: "updatedAt";
@@ -178,6 +178,7 @@ export const CATEGORY_FIELDS = {
178
178
  DISPLAY: "display",
179
179
  IS_ACTIVE: "isActive",
180
180
  IS_SEARCHABLE: "isSearchable",
181
+ CATEGORY_TYPE: "categoryType",
181
182
  CREATED_BY: "createdBy",
182
183
  CREATED_AT: "createdAt",
183
184
  UPDATED_AT: "updatedAt",