@mohasinac/appkit 2.7.53 → 2.7.55

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 (197) hide show
  1. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +1 -1
  2. package/dist/_internal/server/jobs/core/auctionSettlement.js +6 -3
  3. package/dist/_internal/server/jobs/core/bundleStockSync.js +9 -7
  4. package/dist/_internal/server/jobs/core/onProductStockChange.d.ts +12 -3
  5. package/dist/_internal/server/jobs/core/onProductStockChange.js +12 -13
  6. package/dist/_internal/server/jobs/core/onProductWrite.js +1 -3
  7. package/dist/_internal/server/jobs/handlers/onProductStockChange.js +11 -2
  8. package/dist/_internal/server/jobs/runtime/adapters/firebase.js +5 -14
  9. package/dist/_internal/shared/actions/action-registry.js +827 -4
  10. package/dist/_internal/shared/features/events/schema.d.ts +4 -4
  11. package/dist/client.d.ts +2 -0
  12. package/dist/client.js +1 -0
  13. package/dist/constants/api-endpoints.d.ts +3 -0
  14. package/dist/constants/api-endpoints.js +1 -0
  15. package/dist/constants/field-names.d.ts +4 -3
  16. package/dist/constants/field-names.js +8 -8
  17. package/dist/errors/error-codes.d.ts +3 -0
  18. package/dist/errors/error-codes.js +3 -0
  19. package/dist/errors/messages.d.ts +3 -0
  20. package/dist/errors/messages.js +3 -0
  21. package/dist/features/account/components/UserOffersPanel.js +2 -1
  22. package/dist/features/admin/components/AdminAllEventEntriesView.js +4 -3
  23. package/dist/features/admin/components/AdminBidsView.js +5 -3
  24. package/dist/features/admin/components/AdminBlogView.js +3 -2
  25. package/dist/features/admin/components/AdminBrandsView.js +2 -1
  26. package/dist/features/admin/components/AdminBundleEditorView.js +4 -5
  27. package/dist/features/admin/components/AdminBundlesView.js +3 -3
  28. package/dist/features/admin/components/AdminCarouselView.d.ts +2 -1
  29. package/dist/features/admin/components/AdminCarouselView.js +14 -5
  30. package/dist/features/admin/components/AdminCategoriesView.js +2 -1
  31. package/dist/features/admin/components/AdminContactView.d.ts +4 -1
  32. package/dist/features/admin/components/AdminContactView.js +27 -7
  33. package/dist/features/admin/components/AdminCouponsView.d.ts +3 -1
  34. package/dist/features/admin/components/AdminCouponsView.js +17 -3
  35. package/dist/features/admin/components/AdminFaqsView.d.ts +3 -1
  36. package/dist/features/admin/components/AdminFaqsView.js +18 -4
  37. package/dist/features/admin/components/AdminFeaturesView.js +2 -1
  38. package/dist/features/admin/components/AdminMediaView.js +3 -2
  39. package/dist/features/admin/components/AdminNavigationView.js +3 -2
  40. package/dist/features/admin/components/AdminNewsletterView.d.ts +2 -1
  41. package/dist/features/admin/components/AdminNewsletterView.js +13 -4
  42. package/dist/features/admin/components/AdminNotificationsView.js +6 -4
  43. package/dist/features/admin/components/AdminOrdersView.js +4 -3
  44. package/dist/features/admin/components/AdminPayoutsView.js +2 -2
  45. package/dist/features/admin/components/AdminPrizeDrawsView.js +2 -1
  46. package/dist/features/admin/components/AdminProductsView.js +3 -3
  47. package/dist/features/admin/components/AdminReviewsView.js +4 -3
  48. package/dist/features/admin/components/AdminScammersView.js +2 -1
  49. package/dist/features/admin/components/AdminSessionsView.js +5 -3
  50. package/dist/features/admin/components/AdminStoresView.js +2 -2
  51. package/dist/features/admin/components/AdminSublistingCategoriesView.d.ts +5 -1
  52. package/dist/features/admin/components/AdminSublistingCategoriesView.js +12 -3
  53. package/dist/features/admin/components/AdminSupportTicketsView.js +2 -1
  54. package/dist/features/admin/components/AdminTeamView.d.ts +2 -1
  55. package/dist/features/admin/components/AdminTeamView.js +13 -4
  56. package/dist/features/admin/components/AdminUsersView.js +2 -2
  57. package/dist/features/admin/types/product.types.d.ts +1 -1
  58. package/dist/features/admin/types/product.types.js +2 -3
  59. package/dist/features/auctions/actions/bid-actions.d.ts +9 -0
  60. package/dist/features/auctions/actions/bid-actions.js +61 -0
  61. package/dist/features/auctions/components/AuctionDetailPageView.d.ts +2 -1
  62. package/dist/features/auctions/components/AuctionDetailPageView.js +5 -4
  63. package/dist/features/auctions/components/PlaceBidFormClient.d.ts +3 -1
  64. package/dist/features/auctions/components/PlaceBidFormClient.js +32 -2
  65. package/dist/features/auctions/types/index.d.ts +1 -1
  66. package/dist/features/layout/AppLayoutShell.js +1 -1
  67. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +2 -11
  68. package/dist/features/products/api/[id]/route.js +4 -8
  69. package/dist/features/products/api/route.js +1 -3
  70. package/dist/features/products/components/AuctionsIndexListing.js +3 -11
  71. package/dist/features/products/components/PrizeDrawsIndexListing.js +2 -10
  72. package/dist/features/products/components/ProductFilters.d.ts +33 -9
  73. package/dist/features/products/components/ProductFilters.js +6 -29
  74. package/dist/features/products/components/ProductForm.js +2 -3
  75. package/dist/features/products/constants/action-defs.d.ts +86 -7
  76. package/dist/features/products/constants/action-defs.js +99 -7
  77. package/dist/features/products/constants/sieve.d.ts +162 -0
  78. package/dist/features/products/constants/sieve.js +95 -0
  79. package/dist/features/products/repository/products.repository.d.ts +5 -0
  80. package/dist/features/products/repository/products.repository.js +23 -3
  81. package/dist/features/products/schemas/firestore.d.ts +4 -4
  82. package/dist/features/products/schemas/firestore.js +2 -3
  83. package/dist/features/products/schemas/index.d.ts +6 -6
  84. package/dist/features/products/schemas/index.js +2 -6
  85. package/dist/features/products/types/index.d.ts +1 -1
  86. package/dist/features/seller/actions/offer-actions.js +2 -2
  87. package/dist/features/seller/components/QuickProductForm.d.ts +13 -0
  88. package/dist/features/seller/components/QuickProductForm.js +50 -0
  89. package/dist/features/seller/components/SellerAuctionsView.d.ts +4 -1
  90. package/dist/features/seller/components/SellerAuctionsView.js +37 -3
  91. package/dist/features/seller/components/SellerBidsView.js +2 -1
  92. package/dist/features/seller/components/SellerBundlesView.d.ts +3 -1
  93. package/dist/features/seller/components/SellerBundlesView.js +38 -5
  94. package/dist/features/seller/components/SellerClassifiedView.d.ts +3 -1
  95. package/dist/features/seller/components/SellerClassifiedView.js +37 -4
  96. package/dist/features/seller/components/SellerDigitalCodesView.d.ts +3 -1
  97. package/dist/features/seller/components/SellerDigitalCodesView.js +37 -4
  98. package/dist/features/seller/components/SellerGoogleReviewsView.js +2 -1
  99. package/dist/features/seller/components/SellerGroupedListingsView.js +3 -2
  100. package/dist/features/seller/components/SellerLiveView.d.ts +3 -1
  101. package/dist/features/seller/components/SellerLiveView.js +37 -4
  102. package/dist/features/seller/components/SellerOffersPanel.js +2 -1
  103. package/dist/features/seller/components/SellerOffersView.d.ts +4 -1
  104. package/dist/features/seller/components/SellerOffersView.js +8 -3
  105. package/dist/features/seller/components/SellerPayoutsView.d.ts +3 -1
  106. package/dist/features/seller/components/SellerPayoutsView.js +7 -3
  107. package/dist/features/seller/components/SellerPreOrdersView.d.ts +2 -1
  108. package/dist/features/seller/components/SellerPreOrdersView.js +30 -7
  109. package/dist/features/seller/components/SellerPrizeDrawsView.d.ts +2 -1
  110. package/dist/features/seller/components/SellerPrizeDrawsView.js +30 -7
  111. package/dist/features/seller/components/SellerProductShell.js +12 -0
  112. package/dist/features/seller/components/SellerReviewsView.js +2 -1
  113. package/dist/features/seller/components/SellerShippingConfigsView.js +3 -2
  114. package/dist/features/seller/components/SellerStoreCategoriesView.js +6 -5
  115. package/dist/features/seller/components/SellerTemplatesView.js +4 -3
  116. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +30 -16
  117. package/dist/features/wishlist/types/index.d.ts +1 -1
  118. package/dist/index.d.ts +6 -3
  119. package/dist/index.js +6 -4
  120. package/dist/seed/addresses-seed-data.d.ts +2 -18
  121. package/dist/seed/addresses-seed-data.js +137 -203
  122. package/dist/seed/bids-seed-data.d.ts +2 -8
  123. package/dist/seed/bids-seed-data.js +172 -648
  124. package/dist/seed/blog-posts-seed-data.d.ts +0 -5
  125. package/dist/seed/blog-posts-seed-data.js +341 -596
  126. package/dist/seed/carousel-slides-seed-data.d.ts +0 -5
  127. package/dist/seed/carousel-slides-seed-data.js +61 -192
  128. package/dist/seed/carousels-seed-data.js +18 -1
  129. package/dist/seed/cart-seed-data.d.ts +1 -18
  130. package/dist/seed/cart-seed-data.js +116 -293
  131. package/dist/seed/categories-seed-data.d.ts +0 -6
  132. package/dist/seed/categories-seed-data.js +1409 -1537
  133. package/dist/seed/claimed-coupons-seed-data.d.ts +0 -11
  134. package/dist/seed/claimed-coupons-seed-data.js +32 -29
  135. package/dist/seed/conversations-seed-data.d.ts +0 -6
  136. package/dist/seed/conversations-seed-data.js +132 -280
  137. package/dist/seed/coupon-usage-seed-data.d.ts +0 -16
  138. package/dist/seed/coupon-usage-seed-data.js +30 -44
  139. package/dist/seed/coupons-seed-data.d.ts +0 -6
  140. package/dist/seed/coupons-seed-data.js +141 -489
  141. package/dist/seed/events-seed-data.d.ts +0 -6
  142. package/dist/seed/events-seed-data.js +201 -379
  143. package/dist/seed/faq-seed-data.d.ts +0 -14
  144. package/dist/seed/faq-seed-data.js +609 -1184
  145. package/dist/seed/grouped-listings-seed-data.d.ts +119 -8
  146. package/dist/seed/grouped-listings-seed-data.js +148 -233
  147. package/dist/seed/history-seed-data.d.ts +0 -7
  148. package/dist/seed/history-seed-data.js +50 -54
  149. package/dist/seed/homepage-sections-seed-data.d.ts +0 -5
  150. package/dist/seed/homepage-sections-seed-data.js +83 -175
  151. package/dist/seed/index.d.ts +1 -1
  152. package/dist/seed/index.js +1 -1
  153. package/dist/seed/manifest.js +2 -2
  154. package/dist/seed/notifications-seed-data.d.ts +0 -6
  155. package/dist/seed/notifications-seed-data.js +309 -196
  156. package/dist/seed/offers-seed-data.d.ts +0 -8
  157. package/dist/seed/offers-seed-data.js +118 -197
  158. package/dist/seed/orders-seed-data.d.ts +2 -8
  159. package/dist/seed/orders-seed-data.js +248 -1510
  160. package/dist/seed/payouts-seed-data.d.ts +0 -6
  161. package/dist/seed/payouts-seed-data.js +102 -441
  162. package/dist/seed/products-auctions-seed-data.d.ts +1 -14
  163. package/dist/seed/products-auctions-seed-data.js +612 -1084
  164. package/dist/seed/products-preorders-seed-data.d.ts +119 -14
  165. package/dist/seed/products-preorders-seed-data.js +154 -455
  166. package/dist/seed/products-standard-seed-data.d.ts +1 -15
  167. package/dist/seed/products-standard-seed-data.js +1355 -4128
  168. package/dist/seed/reviews-seed-data.d.ts +2 -8
  169. package/dist/seed/reviews-seed-data.js +99 -1182
  170. package/dist/seed/scammers-seed-data.d.ts +0 -15
  171. package/dist/seed/scammers-seed-data.js +36 -37
  172. package/dist/seed/sessions-seed-data.d.ts +0 -13
  173. package/dist/seed/sessions-seed-data.js +58 -335
  174. package/dist/seed/site-settings-seed-data.d.ts +0 -4
  175. package/dist/seed/site-settings-seed-data.js +61 -52
  176. package/dist/seed/store-addresses-seed-data.js +27 -151
  177. package/dist/seed/store-extensions-seed-data.d.ts +0 -7
  178. package/dist/seed/store-extensions-seed-data.js +147 -261
  179. package/dist/seed/stores-seed-data.d.ts +0 -5
  180. package/dist/seed/stores-seed-data.js +222 -184
  181. package/dist/seed/sub-listings-seed-data.d.ts +119 -0
  182. package/dist/seed/sub-listings-seed-data.js +447 -0
  183. package/dist/seed/support-tickets-seed-data.d.ts +0 -7
  184. package/dist/seed/support-tickets-seed-data.js +82 -75
  185. package/dist/seed/users-seed-data.d.ts +0 -5
  186. package/dist/seed/users-seed-data.js +279 -634
  187. package/dist/seed/wishlists-seed-data.d.ts +0 -9
  188. package/dist/seed/wishlists-seed-data.js +36 -52
  189. package/dist/seo/json-ld.js +6 -4
  190. package/dist/styles.css +8052 -3
  191. package/dist/tailwind-utilities.css +1 -1
  192. package/dist/utils/index.d.ts +1 -0
  193. package/dist/utils/index.js +1 -0
  194. package/dist/utils/search-tokens.d.ts +2 -0
  195. package/dist/utils/search-tokens.js +21 -0
  196. package/package.json +2 -2
  197. package/scripts/seed-cli.mjs +2 -2
@@ -91,5 +91,5 @@ export function DashboardLayoutClient({ variant, groups, permissions, activeHref
91
91
  const adminGroups = variant === "admin"
92
92
  ? filteredGroups
93
93
  : groups;
94
- return (_jsxs(_Fragment, { children: [variant === "admin" && (_jsx(AdminSidebar, { variant: "sidebar", desktopOpen: desktopOpen, mobileOpen: mobileOpen, activePath: activeHref, groups: adminGroups, onCloseMobile: close, onToggle: toggle, className: className })), variant === "store" && (_jsx(StoreSidebar, { variant: "sidebar", desktopOpen: desktopOpen, mobileOpen: mobileOpen, activeHref: activeHref, items: [], groups: filteredGroups, onCloseMobile: close, onToggle: toggle, className: className })), variant === "user" && (_jsx(UserSidebar, { variant: "sidebar", desktopOpen: desktopOpen, mobileOpen: mobileOpen, items: filteredGroups.flatMap((g) => g.items), groups: filteredGroups, onCloseMobile: close, onToggle: toggle, className: className })), _jsx("div", { className: "w-full px-5 py-8 md:pl-14 md:pr-6 lg:pl-16 lg:pr-10 min-h-[calc(100dvh-var(--header-height,3.5rem))]", children: _jsx("div", { className: "w-full max-w-screen-2xl mx-auto", children: children }) })] }));
94
+ return (_jsxs(_Fragment, { children: [variant === "admin" && (_jsx(AdminSidebar, { variant: "sidebar", desktopOpen: desktopOpen, mobileOpen: mobileOpen, activePath: activeHref, groups: adminGroups, onCloseMobile: close, onToggle: toggle, className: className })), variant === "store" && (_jsx(StoreSidebar, { variant: "sidebar", desktopOpen: desktopOpen, mobileOpen: mobileOpen, activeHref: activeHref, items: [], groups: filteredGroups, onCloseMobile: close, onToggle: toggle, className: className })), variant === "user" && (_jsx(UserSidebar, { variant: "sidebar", desktopOpen: desktopOpen, mobileOpen: mobileOpen, items: filteredGroups.flatMap((g) => g.items), groups: filteredGroups, onCloseMobile: close, onToggle: toggle, className: className })), _jsx("div", { className: "w-full flex-1 flex flex-col px-5 py-8 md:pl-14 md:pr-6 lg:pl-16 lg:pr-10 min-h-[calc(100dvh-var(--header-height,3.5rem))]", children: _jsx("div", { className: "w-full flex-1 max-w-screen-2xl mx-auto", children: children }) })] }));
95
95
  }
@@ -1,12 +1,11 @@
1
1
  import { bidRepository, orderRepository, productRepository, } from "../../../../repositories";
2
2
  import { sendNotification } from "../../../../features/admin/actions/notification-actions";
3
- import { ProductStatusValues } from "../../../../features/products/schemas/firestore";
4
3
  import { AUCTION_MESSAGES } from "../handlers/messages";
5
4
  async function settleAuction(ctx, product) {
6
5
  const activeBids = await bidRepository.getActiveByProduct(product.id);
7
6
  const batch = ctx.db.batch();
8
7
  if (activeBids.length === 0) {
9
- productRepository.updateStatusInBatch(batch, product.id, ProductStatusValues.OUT_OF_STOCK);
8
+ productRepository.updateStatusInBatch(batch, product.id, "archived");
10
9
  await batch.commit();
11
10
  ctx.logger.info(AUCTION_MESSAGES.NO_BIDS_LOG(product.id));
12
11
  return;
@@ -25,7 +24,11 @@ async function settleAuction(ctx, product) {
25
24
  currency: winnerEntry.data.currency,
26
25
  auctionProductId: product.id,
27
26
  });
28
- productRepository.updateStatusInBatch(batch, product.id, ProductStatusValues.SOLD);
27
+ // Two-axis model: mark as sold without changing publish status
28
+ batch.update(ctx.db.collection("products").doc(product.id), {
29
+ isSold: true,
30
+ availableQuantity: 0,
31
+ });
29
32
  await batch.commit();
30
33
  // Fan-out notifications after batch commits.
31
34
  await sendNotification({
@@ -9,11 +9,13 @@
9
9
  import { CATEGORY_FIELDS, PRODUCT_FIELDS, COMMON_FIELDS } from "../../../../constants/field-names";
10
10
  const CATEGORIES_COLLECTION = "categories";
11
11
  const PRODUCT_COLLECTION = "products";
12
- const UNAVAILABLE = new Set([
13
- PRODUCT_FIELDS.STATUS_VALUES.SOLD,
14
- PRODUCT_FIELDS.STATUS_VALUES.OUT_OF_STOCK,
15
- PRODUCT_FIELDS.STATUS_VALUES.DISCONTINUED,
16
- ]);
12
+ function isMemberAvailable(data) {
13
+ if (data.isSold)
14
+ return false;
15
+ if (typeof data.availableQuantity === "number" && data.availableQuantity <= 0)
16
+ return false;
17
+ return data.status === PRODUCT_FIELDS.STATUS_VALUES.PUBLISHED;
18
+ }
17
19
  async function computeBundleStockStatus(productIds, ctx) {
18
20
  if (productIds.length === 0)
19
21
  return "out_of_stock";
@@ -26,8 +28,8 @@ async function computeBundleStockStatus(productIds, ctx) {
26
28
  if (snap.size < chunk.length)
27
29
  return "out_of_stock";
28
30
  for (const doc of snap.docs) {
29
- const status = doc.data().status;
30
- if (!status || UNAVAILABLE.has(status))
31
+ const data = doc.data();
32
+ if (!isMemberAvailable(data))
31
33
  return "out_of_stock";
32
34
  }
33
35
  }
@@ -11,13 +11,22 @@
11
11
  * status didn't transition between "available" and "unavailable".
12
12
  */
13
13
  import type { JobContext } from "../runtime/types";
14
- export declare function isAvailable(status?: string | null): boolean;
14
+ export declare function isAvailable(doc: {
15
+ isSold?: boolean;
16
+ availableQuantity?: number;
17
+ status?: string;
18
+ } | null): boolean;
15
19
  export declare function syncBundlesForProduct(productId: string, ctx: JobContext): Promise<number>;
16
20
  export declare function syncGroupedListingsForProduct(productId: string, ctx: JobContext): Promise<number>;
21
+ export interface ProductStockSnapshot {
22
+ isSold?: boolean;
23
+ availableQuantity?: number;
24
+ status?: string;
25
+ }
17
26
  export interface HandleProductStockChangeInput {
18
27
  productId: string;
19
- beforeStatus: string | null;
20
- afterStatus: string | null;
28
+ before: ProductStockSnapshot | null;
29
+ after: ProductStockSnapshot | null;
21
30
  isDelete: boolean;
22
31
  }
23
32
  export declare function handleProductStockChange(input: HandleProductStockChangeInput, ctx: JobContext): Promise<void>;
@@ -14,16 +14,15 @@ import { CATEGORY_FIELDS, PRODUCT_FIELDS, COMMON_FIELDS } from "../../../../cons
14
14
  const CATEGORIES_COLLECTION = "categories";
15
15
  const GROUPED_LISTINGS_COLLECTION = "groupedListings";
16
16
  const PRODUCT_COLLECTION = "products";
17
- const UNAVAILABLE_STATUSES = new Set([
18
- PRODUCT_FIELDS.STATUS_VALUES.SOLD,
19
- PRODUCT_FIELDS.STATUS_VALUES.OUT_OF_STOCK,
20
- PRODUCT_FIELDS.STATUS_VALUES.DISCONTINUED,
21
- ]);
22
17
  const MIN_ACTIVE_DEFAULT = 2;
23
- export function isAvailable(status) {
24
- if (!status)
18
+ export function isAvailable(doc) {
19
+ if (!doc)
25
20
  return false;
26
- return !UNAVAILABLE_STATUSES.has(status);
21
+ if (doc.isSold)
22
+ return false;
23
+ if (typeof doc.availableQuantity === "number" && doc.availableQuantity <= 0)
24
+ return false;
25
+ return doc.status === PRODUCT_FIELDS.STATUS_VALUES.PUBLISHED;
27
26
  }
28
27
  async function recomputeBundleStatus(productIds, ctx) {
29
28
  if (productIds.length === 0)
@@ -37,8 +36,8 @@ async function recomputeBundleStatus(productIds, ctx) {
37
36
  if (snap.size < chunk.length)
38
37
  return "out_of_stock";
39
38
  for (const doc of snap.docs) {
40
- const status = doc.data().status;
41
- if (!isAvailable(status))
39
+ const data = doc.data();
40
+ if (!isAvailable(data))
42
41
  return "out_of_stock";
43
42
  }
44
43
  }
@@ -86,8 +85,8 @@ export async function syncGroupedListingsForProduct(productId, ctx) {
86
85
  .where("__name__", "in", chunk)
87
86
  .get();
88
87
  for (const doc of productSnap.docs) {
89
- const status = doc.data().status;
90
- if (isAvailable(status))
88
+ const data = doc.data();
89
+ if (isAvailable(data))
91
90
  activeCount++;
92
91
  }
93
92
  }
@@ -105,7 +104,7 @@ export async function syncGroupedListingsForProduct(productId, ctx) {
105
104
  return updated;
106
105
  }
107
106
  export async function handleProductStockChange(input, ctx) {
108
- const { productId, beforeStatus, afterStatus, isDelete } = input;
107
+ const { productId, before: beforeStatus, after: afterStatus, isDelete } = input;
109
108
  const beforeAvailable = isAvailable(beforeStatus);
110
109
  const afterAvailable = isAvailable(afterStatus);
111
110
  const stateFlipped = beforeAvailable !== afterAvailable;
@@ -6,9 +6,7 @@ import { categoriesRepository, storeRepository, } from "../../../../repositories
6
6
  import { ProductStatusValues } from "../../../../features/products/schemas/firestore";
7
7
  import { PRODUCT_FIELDS } from "../../../../constants/field-names";
8
8
  const UNAVAILABLE_PRODUCT_STATUSES = new Set([
9
- ProductStatusValues.SOLD,
10
- ProductStatusValues.OUT_OF_STOCK,
11
- ProductStatusValues.DISCONTINUED,
9
+ ProductStatusValues.ARCHIVED,
12
10
  ]);
13
11
  void UNAVAILABLE_PRODUCT_STATUSES;
14
12
  async function getParentIds(categoryId) {
@@ -1,9 +1,18 @@
1
1
  import { handleProductStockChange } from "../core/onProductStockChange";
2
+ function toSnapshot(doc) {
3
+ if (!doc)
4
+ return null;
5
+ return {
6
+ isSold: doc.isSold,
7
+ availableQuantity: doc.availableQuantity,
8
+ status: doc.status,
9
+ };
10
+ }
2
11
  export const onProductStockChangeHandler = async (event, ctx) => {
3
12
  await handleProductStockChange({
4
13
  productId: event.params.productId,
5
- beforeStatus: event.before?.status ?? null,
6
- afterStatus: event.after?.status ?? null,
14
+ before: toSnapshot(event.before),
15
+ after: toSnapshot(event.after),
7
16
  isDelete: !event.after,
8
17
  }, ctx);
9
18
  };
@@ -127,20 +127,11 @@ export function bindCallable(job, handler, options) {
127
127
  */
128
128
  export function bindHttps(job, handler, options) {
129
129
  const { secretEnvVar, methods = ["POST"], ...httpsOptions } = options;
130
- // Firebase Functions v2 requires secrets to be DECLARED via `secrets: [...]`
131
- // in the `onRequest` options for the runtime to inject them into
132
- // `process.env`. Just *reading* `process.env[secretEnvVar]` returns
133
- // undefined unless the secret is bound here. Declare it via `defineSecret`
134
- // so the deploy step provisions the binding (and developers see the secret
135
- // listed in `firebase deploy` output).
136
- if (secretEnvVar) {
137
- const existing = Array.isArray(httpsOptions.secrets)
138
- ? httpsOptions.secrets
139
- : [];
140
- if (!existing.includes(secretEnvVar)) {
141
- httpsOptions.secrets = [...existing, secretEnvVar];
142
- }
143
- }
130
+ // Secret is provided via functions/.env.<project> (dotenv) rather than
131
+ // Secret Manager binding. Skip adding to `secrets: [...]` that requires
132
+ // roles/secretmanager.secretAccessor on the compute SA which isn't granted
133
+ // yet (Q1-iam). The dotenv file injects into process.env before the
134
+ // function runs, so the auth check below still works.
144
135
  return onRequest(httpsOptions, async (req, res) => {
145
136
  const ctx = buildContext(job);
146
137
  if (secretEnvVar) {