@mohasinac/appkit 3.2.14 → 3.2.17

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 (100) hide show
  1. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +13 -4
  2. package/dist/_internal/server/jobs/core/listingProcessor.js +2 -1
  3. package/dist/_internal/server/jobs/core/wrapJobHandler.js +2 -1
  4. package/dist/_internal/shared/listing-types/action-tracker.js +1 -1
  5. package/dist/cli/index.js +6 -4
  6. package/dist/client/api/surface-error.js +3 -2
  7. package/dist/client/api/useApiQuery.js +3 -2
  8. package/dist/client/observability/reportClientError.js +3 -2
  9. package/dist/core/Logger.js +5 -4
  10. package/dist/core/StorageManager.js +6 -4
  11. package/dist/core/integration-keys.js +3 -3
  12. package/dist/errors/safe-read.js +2 -2
  13. package/dist/features/about/components/PolicyPageView.js +3 -1
  14. package/dist/features/admin/components/AdminAdEditorView.js +3 -1
  15. package/dist/features/admin/components/AdminAdsView.js +3 -1
  16. package/dist/features/admin/components/AdminBlogEditorView.js +3 -1
  17. package/dist/features/admin/components/AdminBundlesView.js +3 -1
  18. package/dist/features/admin/components/AdminCouponEditorView.js +3 -1
  19. package/dist/features/admin/components/AdminCouponsView.js +5 -2
  20. package/dist/features/admin/components/AdminGroupedListingsView.js +3 -1
  21. package/dist/features/admin/components/AdminNewsletterView.js +3 -1
  22. package/dist/features/admin/components/AdminPayoutsView.js +3 -1
  23. package/dist/features/admin/components/AdminSectionsView.js +3 -1
  24. package/dist/features/admin/repository/chat.repository.js +2 -2
  25. package/dist/features/admin/repository/site-settings.repository.js +1 -1
  26. package/dist/features/auctions/components/MarketplaceAuctionCard.js +3 -1
  27. package/dist/features/auctions/hooks/useRealtimeBids.js +3 -1
  28. package/dist/features/auth/hooks/useAuth.js +2 -1
  29. package/dist/features/blog/repository/blog.repository.js +2 -1
  30. package/dist/features/cart/utils/guest-cart.js +3 -1
  31. package/dist/features/cart/utils/pending-ops.js +5 -2
  32. package/dist/features/categories/hooks/useCategories.js +3 -1
  33. package/dist/features/categories/repository/categories.repository.js +2 -1
  34. package/dist/features/contact/components/ContactForm.js +3 -1
  35. package/dist/features/events/components/AdminEventEditorView.js +5 -2
  36. package/dist/features/events/components/EventBanner.js +5 -2
  37. package/dist/features/events/components/EventOfferCard.js +3 -1
  38. package/dist/features/events/components/EventRafflesSection.js +3 -1
  39. package/dist/features/history/hooks/useHistory.js +10 -5
  40. package/dist/features/history/utils/guest-history.js +3 -1
  41. package/dist/features/homepage/api/carousel/route.js +2 -1
  42. package/dist/features/homepage/api/route.js +2 -1
  43. package/dist/features/homepage/components/AdSlot.js +3 -1
  44. package/dist/features/homepage/components/AnnouncementBar.js +6 -2
  45. package/dist/features/homepage/components/CharacterHotspotForm.js +5 -2
  46. package/dist/features/homepage/components/GoogleReviewsSection.js +3 -1
  47. package/dist/features/homepage/components/NewsletterBanner.js +3 -1
  48. package/dist/features/homepage/lib/live-stats.js +2 -1
  49. package/dist/features/homepage/lib/section-helpers.d.ts +0 -1
  50. package/dist/features/homepage/lib/section-helpers.js +3 -1
  51. package/dist/features/media/MediaPickerModal.js +3 -1
  52. package/dist/features/media/finalize.js +7 -3
  53. package/dist/features/media/upload/MediaUploadField.js +6 -3
  54. package/dist/features/media/upload/MediaUploadList.js +2 -1
  55. package/dist/features/media/upload/video-poster.js +3 -1
  56. package/dist/features/messages/hooks/useConversation.js +2 -1
  57. package/dist/features/messages/hooks/useConversations.js +2 -1
  58. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +3 -1
  59. package/dist/features/products/components/BidHistory.js +3 -1
  60. package/dist/features/products/components/GroupSettingsPanel.js +2 -1
  61. package/dist/features/products/components/PrizeDrawsSection.js +3 -1
  62. package/dist/features/products/components/ShareButton.js +3 -1
  63. package/dist/features/products/repository/products.repository.js +4 -2
  64. package/dist/features/promotions/components/CouponCard.js +3 -1
  65. package/dist/features/reviews/components/ReviewDetailShell.js +3 -1
  66. package/dist/features/scams/components/ScamProfileView.js +3 -1
  67. package/dist/features/scams/repository/scammer.repository.js +2 -1
  68. package/dist/features/search/api/route.js +2 -1
  69. package/dist/features/seller/components/PrintCenterView.js +3 -1
  70. package/dist/features/seller/components/SellerAddressesView.js +2 -1
  71. package/dist/features/site-settings/components/ActionPermissionsManager.js +3 -1
  72. package/dist/features/site-settings/components/NavPermissionsManager.js +3 -1
  73. package/dist/features/whatsapp-bot/helpers/whatsapp.js +4 -2
  74. package/dist/features/wishlist/repository/user-wishlist.repository.js +3 -1
  75. package/dist/features/wishlist/utils/guest-wishlist.js +3 -1
  76. package/dist/http/api-handler.js +5 -2
  77. package/dist/monitoring/cache-metrics.d.ts +0 -4
  78. package/dist/monitoring/cache-metrics.js +4 -2
  79. package/dist/monitoring/client-logger.js +4 -2
  80. package/dist/monitoring/server-logger.js +6 -5
  81. package/dist/next/api/apiHandler.js +2 -1
  82. package/dist/next/api/routeHandler.js +10 -5
  83. package/dist/next/middleware/pii-redactor.js +3 -1
  84. package/dist/next/middleware/pii-scrubber.js +3 -1
  85. package/dist/providers/auth-firebase/helpers.js +2 -1
  86. package/dist/providers/auth-firebase/session.js +2 -1
  87. package/dist/providers/db-firebase/admin.js +3 -1
  88. package/dist/providers/firebase-client/realtime.js +3 -1
  89. package/dist/providers/shipping-shiprocket/index.d.ts +0 -21
  90. package/dist/providers/shipping-shiprocket/index.js +3 -1
  91. package/dist/react/contexts/SessionContext.js +2 -1
  92. package/dist/react/hooks/useFormStatePreservation.js +3 -1
  93. package/dist/seed/seed-market-config.js +3 -1
  94. package/dist/ui/components/ClaimCouponButton.js +5 -2
  95. package/dist/ui/components/NavigationLoader.js +5 -2
  96. package/dist/utils/id-generators.js +3 -1
  97. package/dist/utils/string.formatter.d.ts +0 -3
  98. package/dist/utils/string.formatter.js +3 -1
  99. package/dist/validation/schemas.js +3 -1
  100. package/package.json +1 -1
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { normalizeError } from "../../../errors/normalize";
3
4
  import { useApiMutation } from "@mohasinac/appkit/client";
4
5
  import React from "react";
5
6
  import { useQuery } from "@tanstack/react-query";
@@ -87,7 +88,8 @@ function toLocalDatetime(iso) {
87
88
  const local = new Date(d.getTime() - offset * 60000);
88
89
  return local.toISOString().slice(0, 16);
89
90
  }
90
- catch {
91
+ catch (_err) {
92
+ void normalizeError(_err);
91
93
  return "";
92
94
  }
93
95
  }
@@ -97,7 +99,8 @@ function toISOString(local) {
97
99
  try {
98
100
  return new Date(local).toISOString();
99
101
  }
100
- catch {
102
+ catch (_err) {
103
+ void normalizeError(_err);
101
104
  return "";
102
105
  }
103
106
  }
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { normalizeError } from "../../../errors/normalize";
3
4
  import { useEffect, useMemo, useState } from "react";
4
5
  import { useEvents } from "../hooks/useEvents";
5
6
  import { Button, Section, TextLink } from "../../../ui";
@@ -12,7 +13,8 @@ export function EventBanner({ storageKey = "dismissed_event_banners", className
12
13
  if (stored)
13
14
  setDismissedIds(JSON.parse(stored));
14
15
  }
15
- catch {
16
+ catch (_err) {
17
+ void normalizeError(_err);
16
18
  // ignore session storage failures
17
19
  }
18
20
  setMounted(true);
@@ -36,7 +38,8 @@ export function EventBanner({ storageKey = "dismissed_event_banners", className
36
38
  try {
37
39
  sessionStorage.setItem(storageKey, JSON.stringify(next));
38
40
  }
39
- catch {
41
+ catch (_err) {
42
+ void normalizeError(_err);
40
43
  // ignore
41
44
  }
42
45
  };
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { normalizeError } from "../../../errors/normalize";
3
4
  import { useState } from "react";
4
5
  import Link from "next/link";
5
6
  import { Code, Div, Heading, Row, Stack, Text } from "../../../ui";
@@ -24,7 +25,8 @@ export function EventOfferCard({ couponCode, offerDescription, title = "Exclusiv
24
25
  setCopied(true);
25
26
  setTimeout(() => setCopied(false), 2000);
26
27
  }
27
- catch {
28
+ catch (_err) {
29
+ void normalizeError(_err);
28
30
  /* clipboard unavailable — leave button as-is */
29
31
  }
30
32
  };
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { normalizeError } from "../../../errors/normalize";
2
3
  import { sieveFilter, sieveAnd, SIEVE_OP } from "@mohasinac/appkit";
3
4
  import { sortBy } from "@mohasinac/appkit";
4
5
  import Link from "next/link";
@@ -23,7 +24,8 @@ export async function EventRafflesSection({ config, }) {
23
24
  });
24
25
  events = (result.items ?? []);
25
26
  }
26
- catch {
27
+ catch (_err) {
28
+ void normalizeError(_err);
27
29
  events = [];
28
30
  }
29
31
  return (_jsx(Section, { padding: "y-2xl", children: _jsx(Container, { size: "xl", children: _jsxs(Stack, { gap: "md", children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 2, size: "2xl", weight: "semibold", color: "primary", children: title }), subtitle ? (_jsx(Text, { size: "sm", color: "muted", children: subtitle })) : null] }), events.length === 0 ? (_jsxs(Stack, { align: "center", gap: "sm", className: "border-dashed text-center", border: "strong", paddingY: "y-3xl", paddingX: "x-lg", rounded: "2xl", children: [_jsx(Text, { size: "sm", color: "muted", children: "No upcoming raffles \u2014 keep an eye on the events page." }), _jsx(Link, { href: String(ROUTES.PUBLIC.EVENTS), className: "text-sm font-medium text-primary hover:underline", children: "Browse all events \u2192" })] })) : (_jsx(Div, { gap: "3", className: "fluid-grid-card", children: events.map((event) => (_jsx(EventCard, { event: event }, event.id))) }))] }) }) }));
@@ -25,7 +25,8 @@ async function fetchAuthHistory() {
25
25
  const json = (await res.json());
26
26
  return json.data?.items ?? [];
27
27
  }
28
- catch {
28
+ catch (_err) {
29
+ void normalizeError(_err);
29
30
  return [];
30
31
  }
31
32
  }
@@ -38,7 +39,8 @@ async function postAuthTrack(args) {
38
39
  body: JSON.stringify(args),
39
40
  });
40
41
  }
41
- catch {
42
+ catch (_err) {
43
+ void normalizeError(_err);
42
44
  // best-effort tracking
43
45
  }
44
46
  }
@@ -49,7 +51,8 @@ async function deleteAuthItem(productId) {
49
51
  credentials: "include",
50
52
  });
51
53
  }
52
- catch {
54
+ catch (_err) {
55
+ void normalizeError(_err);
53
56
  // ignore
54
57
  }
55
58
  }
@@ -60,7 +63,8 @@ async function deleteAuthAll() {
60
63
  credentials: "include",
61
64
  });
62
65
  }
63
- catch {
66
+ catch (_err) {
67
+ void normalizeError(_err);
64
68
  // ignore
65
69
  }
66
70
  }
@@ -146,7 +150,8 @@ export function useHistory(userId) {
146
150
  setItems([]);
147
151
  showToast("History cleared.", "success");
148
152
  }
149
- catch {
153
+ catch (_err) {
154
+ void normalizeError(_err);
150
155
  showToast("Failed to clear history.", "error");
151
156
  }
152
157
  }, [isAuth, showToast]);
@@ -5,6 +5,7 @@
5
5
  * Re-visit semantics mirror server: remove existing entry for productId,
6
6
  * unshift new entry at position 0, then slice to HISTORY_MAX.
7
7
  */
8
+ import { normalizeError } from "../../../errors/normalize";
8
9
  import { HISTORY_MAX } from "../../../constants/limits";
9
10
  const DEFAULT_GUEST_HISTORY_KEY = process.env.NEXT_PUBLIC_APP_ID
10
11
  ? `${process.env.NEXT_PUBLIC_APP_ID}_guest_history`
@@ -24,7 +25,8 @@ function read(storage, key) {
24
25
  const parsed = JSON.parse(raw);
25
26
  return Array.isArray(parsed) ? parsed : [];
26
27
  }
27
- catch {
28
+ catch (_err) {
29
+ void normalizeError(_err);
28
30
  return [];
29
31
  }
30
32
  }
@@ -30,7 +30,8 @@ async function getRoleFromSession(request) {
30
30
  const payload = await session.verifySession(cookie);
31
31
  return payload.role ?? null;
32
32
  }
33
- catch {
33
+ catch (_err) {
34
+ void normalizeError(_err);
34
35
  return null;
35
36
  }
36
37
  }
@@ -30,7 +30,8 @@ async function getRoleFromSession(request) {
30
30
  const payload = await session.verifySession(cookie);
31
31
  return payload.role ?? null;
32
32
  }
33
- catch {
33
+ catch (_err) {
34
+ void normalizeError(_err);
34
35
  return null;
35
36
  }
36
37
  }
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { normalizeError } from "../../../errors/normalize";
3
4
  import { useEffect, useRef, useState } from "react";
4
5
  import { getAdSlot, isAdSlotRenderable } from "../ad-registry";
5
6
  import { useActiveAd } from "../hooks/useActiveAd";
@@ -15,7 +16,8 @@ function AdsenseAd({ config }) {
15
16
  try {
16
17
  (window.adsbygoogle = window.adsbygoogle || []).push({});
17
18
  }
18
- catch {
19
+ catch (_err) {
20
+ void normalizeError(_err);
19
21
  // AdSense not loaded yet — no-op
20
22
  }
21
23
  }, []);
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { normalizeError } from "../../../errors/normalize";
3
4
  import { useState, useEffect } from "react";
4
5
  import { X } from "lucide-react";
5
6
  import { useAuth } from "../../../react/contexts/SessionContext";
@@ -24,7 +25,8 @@ function isLocallyDismissed(message) {
24
25
  return false;
25
26
  return Date.now() - at < ONE_WEEK_MS;
26
27
  }
27
- catch {
28
+ catch (_err) {
29
+ void normalizeError(_err);
28
30
  return false;
29
31
  }
30
32
  }
@@ -32,7 +34,9 @@ function saveLocalDismissal(message) {
32
34
  try {
33
35
  localStorage.setItem(STORAGE_KEY, JSON.stringify({ hash: hashBannerMessage(message), at: Date.now() }));
34
36
  }
35
- catch { /* quota exceeded — ignore */ }
37
+ catch (_err) {
38
+ void normalizeError(_err); /* quota exceeded — ignore */
39
+ }
36
40
  }
37
41
  export function AnnouncementBar({ message, className = "", onDismiss }) {
38
42
  const { user } = useAuth();
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { normalizeError } from "../../../errors/normalize";
3
4
  import { useState, useRef } from "react";
4
5
  import Image from "next/image";
5
6
  import { Button, Details, Div, Heading, Input, Label, Li, Row, Span, Stack, Summary, Text, Textarea, Ul } from "../../../ui";
@@ -45,7 +46,8 @@ export function CharacterHotspotForm({ initial, onUploadImage, onSave, onAfterSa
45
46
  const url = await onUploadImage(file);
46
47
  setImageUrl(url);
47
48
  }
48
- catch {
49
+ catch (_err) {
50
+ void normalizeError(_err);
49
51
  setError("Image upload failed.");
50
52
  }
51
53
  finally {
@@ -101,7 +103,8 @@ export function CharacterHotspotForm({ initial, onUploadImage, onSave, onAfterSa
101
103
  await onAfterSave?.();
102
104
  setSuccess(true);
103
105
  }
104
- catch {
106
+ catch (_err) {
107
+ void normalizeError(_err);
105
108
  setError("Save failed. Check your connection and try again.");
106
109
  }
107
110
  finally {
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { normalizeError } from "../../../errors/normalize";
2
3
  import { Div, Heading, Row, Section, Span, Stack, Text } from "../../../ui";
3
4
  import { siteSettingsRepository } from "../../admin/repository/site-settings.repository";
4
5
  import { fetchGoogleReviews } from "../lib/google-reviews-fetcher";
@@ -57,7 +58,8 @@ export async function GoogleReviewsSection(config) {
57
58
  aggregateRating = result.aggregateRating;
58
59
  totalRatings = result.totalRatings;
59
60
  }
60
- catch {
61
+ catch (_err) {
62
+ void normalizeError(_err);
61
63
  // Fail silently — empty state shown
62
64
  }
63
65
  const gridClass = layout === "carousel"
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { normalizeError } from "../../../errors/normalize";
3
4
  import { useState } from "react";
4
5
  import { Button, Div, Heading, Span, Text, } from "../../../ui";
5
6
  import { DynamicBgDiv } from "../../../ui/components/DynamicBgDiv";
@@ -22,7 +23,8 @@ export function NewsletterBanner({ onSubscribe, eyebrow = "STAY CONNECTED", head
22
23
  setEmail("");
23
24
  setSuccess(true);
24
25
  }
25
- catch {
26
+ catch (_err) {
27
+ void normalizeError(_err);
26
28
  setError(true);
27
29
  }
28
30
  finally {
@@ -79,7 +79,8 @@ export async function fetchLiveStats(requests) {
79
79
  const count = await getFirestoreCount(query);
80
80
  result[key] = String(count);
81
81
  }
82
- catch {
82
+ catch (_err) {
83
+ void normalizeError(_err);
83
84
  // silently fall back to static value
84
85
  }
85
86
  })());
@@ -1,5 +1,4 @@
1
1
  /** Shared string helpers for homepage section rendering. */
2
- /** Strip leading emoji/symbols that admins sometimes prefix onto DB titles. */
3
2
  export declare function cleanTitle(raw: string | undefined): string | undefined;
4
3
  /** Parse a ProseMirror/Tiptap JSON welcome description to plain text, or return as-is. */
5
4
  export declare function parseWelcomeDescription(description: string | undefined): string;
@@ -1,5 +1,6 @@
1
1
  /** Shared string helpers for homepage section rendering. */
2
2
  /** Strip leading emoji/symbols that admins sometimes prefix onto DB titles. */
3
+ import { normalizeError } from "../../../errors/normalize";
3
4
  export function cleanTitle(raw) {
4
5
  if (!raw)
5
6
  return raw;
@@ -19,7 +20,8 @@ export function parseWelcomeDescription(description) {
19
20
  .trim();
20
21
  return extracted || description;
21
22
  }
22
- catch {
23
+ catch (_err) {
24
+ void normalizeError(_err);
23
25
  return description;
24
26
  }
25
27
  }
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { normalizeError } from "../../errors/normalize";
3
4
  import React, { useState, useCallback } from "react";
4
5
  import { Modal } from "../../ui/components/Modal";
5
6
  import { Button, Div, Input, Label, Row, Stack, Text, Alert } from "../../ui";
@@ -96,7 +97,8 @@ export function MediaPickerModal({ isOpen, onClose, onSelect, accept = "image/*"
96
97
  try {
97
98
  new URL(trimmed);
98
99
  }
99
- catch {
100
+ catch (_err) {
101
+ void normalizeError(_err);
100
102
  setUrlError("Enter a valid URL starting with https://");
101
103
  return;
102
104
  }
@@ -1,3 +1,4 @@
1
+ import { normalizeError } from "../../errors/normalize";
1
2
  import { getAdminStorage } from "../../providers/db-firebase";
2
3
  import { FIREBASE_STORAGE_HOST, GCS_HOST } from "../../utils/media-url";
3
4
  import { mediaAssetsRepository } from "./repository/media-assets.repository";
@@ -24,7 +25,8 @@ export function extractStoragePathFromUrl(url, bucketName) {
24
25
  }
25
26
  return null;
26
27
  }
27
- catch {
28
+ catch (_err) {
29
+ void normalizeError(_err);
28
30
  return null;
29
31
  }
30
32
  }
@@ -70,7 +72,8 @@ export async function finalizeStagedMediaUrl(url) {
70
72
  await mediaAssetsRepository.promoteToFinalized(shortId, finalPath);
71
73
  }
72
74
  }
73
- catch {
75
+ catch (_err) {
76
+ void normalizeError(_err);
74
77
  // Non-fatal: URL is still valid; proxy will serve whatever storagePath points to.
75
78
  }
76
79
  return url; // URL is stable — same before and after the file move
@@ -82,7 +85,8 @@ export async function finalizeStagedMediaUrl(url) {
82
85
  const finalPath = await moveToFinalPath(rawPath);
83
86
  return `${PROXY_URL_PREFIX}${finalPath}`;
84
87
  }
85
- catch {
88
+ catch (_err) {
89
+ void normalizeError(_err);
86
90
  return url;
87
91
  }
88
92
  }
@@ -57,7 +57,8 @@ function filenameFromUrl(url) {
57
57
  const parts = new URL(url).pathname.split("/");
58
58
  return decodeURIComponent(parts[parts.length - 1] || url);
59
59
  }
60
- catch {
60
+ catch (_err) {
61
+ void normalizeError(_err);
61
62
  return url;
62
63
  }
63
64
  }
@@ -71,7 +72,8 @@ function extractYouTubeId(input) {
71
72
  return (url.searchParams.get("v") ||
72
73
  (url.hostname === "youtu.be" ? url.pathname.slice(1) : null));
73
74
  }
74
- catch {
75
+ catch (_err) {
76
+ void normalizeError(_err);
75
77
  return null;
76
78
  }
77
79
  }
@@ -135,7 +137,8 @@ kind, accept: acceptProp, maxSizeMB: maxSizeMBProp, disabled = false, helperText
135
137
  try {
136
138
  new URL(trimmed);
137
139
  }
138
- catch {
140
+ catch (_err) {
141
+ void normalizeError(_err);
139
142
  setExtError("Enter a valid URL.");
140
143
  return;
141
144
  }
@@ -15,7 +15,8 @@ function fileNameFromUrl(url) {
15
15
  const parts = new URL(url).pathname.split("/");
16
16
  return decodeURIComponent(parts[parts.length - 1] || url);
17
17
  }
18
- catch {
18
+ catch (_err) {
19
+ void normalizeError(_err);
19
20
  return url;
20
21
  }
21
22
  }
@@ -20,6 +20,7 @@
20
20
  * media asset, so the existing server-side Sharp watermark is applied when
21
21
  * the poster is fetched via /api/media/<slug>.
22
22
  */
23
+ import { normalizeError } from "../../../errors/normalize";
23
24
  const TARGET_FRAME_TIME_SECONDS = 0.5;
24
25
  const JPEG_QUALITY = 0.85;
25
26
  const LOAD_TIMEOUT_MS = 10000;
@@ -97,7 +98,8 @@ export async function extractVideoPosterFrame(file) {
97
98
  return null;
98
99
  return { blob, width, height };
99
100
  }
100
- catch {
101
+ catch (_err) {
102
+ void normalizeError(_err);
101
103
  return null;
102
104
  }
103
105
  finally {
@@ -78,7 +78,8 @@ export function useConversation(conversationId) {
78
78
  unsubscribe();
79
79
  };
80
80
  }
81
- catch {
81
+ catch (_err) {
82
+ void normalizeError(_err);
82
83
  // Realtime provider not registered — falls back to one-shot fetch above.
83
84
  setIsConnected(false);
84
85
  return undefined;
@@ -52,7 +52,8 @@ export function useConversations(userId) {
52
52
  });
53
53
  return unsubscribe;
54
54
  }
55
- catch {
55
+ catch (_err) {
56
+ void normalizeError(_err);
56
57
  // Realtime provider not registered — non-fatal; list still works.
57
58
  return undefined;
58
59
  }
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { normalizeError } from "../../../errors/normalize";
3
4
  import { useCallback } from "react";
4
5
  import { useRouter } from "next/navigation";
5
6
  import { useLongPress } from "../../../react/hooks/useLongPress";
@@ -51,7 +52,8 @@ export function MarketplacePreorderCard({ product, className = "", variant = "gr
51
52
  try {
52
53
  await toggle();
53
54
  }
54
- catch {
55
+ catch (_err) {
56
+ void normalizeError(_err);
55
57
  // The hook rolls back optimistic state when the mutation fails.
56
58
  }
57
59
  }, [toggle]);
@@ -1,4 +1,5 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { normalizeError } from "../../../errors/normalize";
2
3
  import React from "react";
3
4
  import { Div, Heading, Span, Stack, Text } from "../../../ui";
4
5
  import { formatCurrency } from "../../../utils/number.formatter";
@@ -13,7 +14,8 @@ function formatBidDate(raw) {
13
14
  minute: "2-digit",
14
15
  });
15
16
  }
16
- catch {
17
+ catch (_err) {
18
+ void normalizeError(_err);
17
19
  return raw;
18
20
  }
19
21
  }
@@ -43,7 +43,8 @@ export function GroupSettingsPanel({ productId, productSlug, groupId, isGroupPar
43
43
  const res = (await apiClient.get(`/api/products/group/${encodeURIComponent(groupId)}`));
44
44
  setChildren(res.data?.items ?? []);
45
45
  }
46
- catch {
46
+ catch (_err) {
47
+ void normalizeError(_err);
47
48
  setChildren([]);
48
49
  }
49
50
  finally {
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { normalizeError } from "../../../errors/normalize";
2
3
  import { sieveFilter, sieveAnd, SIEVE_OP } from "@mohasinac/appkit";
3
4
  import { sortBy } from "@mohasinac/appkit";
4
5
  import Link from "next/link";
@@ -23,7 +24,8 @@ export async function PrizeDrawsSection({ config, }) {
23
24
  });
24
25
  draws = (result.items ?? []);
25
26
  }
26
- catch {
27
+ catch (_err) {
28
+ void normalizeError(_err);
27
29
  draws = [];
28
30
  }
29
31
  return (_jsx(Section, { padding: "y-2xl", children: _jsx(Container, { size: "xl", children: _jsxs(Stack, { gap: "md", children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 2, size: "2xl", weight: "semibold", color: "primary", children: title }), subtitle ? (_jsx(Text, { size: "sm", color: "muted", children: subtitle })) : null] }), draws.length === 0 ? (_jsxs(Stack, { align: "center", gap: "sm", className: "border-dashed text-center", border: "strong", paddingY: "y-3xl", paddingX: "x-lg", rounded: "2xl", children: [_jsx(Text, { size: "sm", color: "muted", children: "No active prize draws \u2014 new draws are announced regularly." }), _jsx(Link, { href: String(ROUTES.PUBLIC.AUCTIONS), className: "text-sm font-medium text-primary hover:underline", children: "Browse live auctions \u2192" })] })) : (_jsx(Div, { gap: "3", className: "fluid-grid-card", children: draws.map((draw) => (_jsx(InteractiveProductCard, { product: draw, href: String(ROUTES.PUBLIC.PRODUCT_DETAIL(draw.slug ?? draw.id ?? "")) }, draw.id))) }))] }) }) }));
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { normalizeError } from "../../../errors/normalize";
3
4
  import { useState } from "react";
4
5
  export function ShareButton({ title, text, className = "" }) {
5
6
  const [copied, setCopied] = useState(false);
@@ -10,7 +11,8 @@ export function ShareButton({ title, text, className = "" }) {
10
11
  await navigator.share({ title: title ?? document.title, text, url });
11
12
  return;
12
13
  }
13
- catch {
14
+ catch (_err) {
15
+ void normalizeError(_err);
14
16
  // user cancelled or browser blocked — fall through to clipboard
15
17
  }
16
18
  }
@@ -107,7 +107,8 @@ export class ProductRepository extends BaseRepository {
107
107
  const doc = await this.findById(candidateId);
108
108
  return !!doc;
109
109
  }
110
- catch {
110
+ catch (_err) {
111
+ void normalizeError(_err);
111
112
  return false;
112
113
  }
113
114
  });
@@ -372,7 +373,8 @@ export class ProductRepository extends BaseRepository {
372
373
  [PRODUCT_FIELDS.VIEW_COUNT]: increment(1),
373
374
  });
374
375
  }
375
- catch {
376
+ catch (_err) {
377
+ void normalizeError(_err);
376
378
  // View analytics must not break product read path.
377
379
  }
378
380
  }
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { normalizeError } from "../../../errors/normalize";
3
4
  import { useState } from "react";
4
5
  import { Pencil, Trash2, ToggleLeft, ToggleRight } from "lucide-react";
5
6
  import { Badge, BaseListingCard, ConfirmDeleteModal, Div, Row, Span, Stack, Text } from "../../../ui";
@@ -125,7 +126,8 @@ export function CouponCard({ coupon, labels: labelsProp, onCopy, className = "",
125
126
  body: JSON.stringify({ couponCode: n.code, source: claimSource }),
126
127
  });
127
128
  }
128
- catch {
129
+ catch (_err) {
130
+ void normalizeError(_err);
129
131
  /* anon/network — non-fatal */
130
132
  }
131
133
  if (typeof window !== "undefined") {
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { normalizeError } from "../../../errors/normalize";
3
4
  import { useState, useEffect, useCallback } from "react";
4
5
  const __P = {
5
6
  p4: "p-4",
@@ -72,7 +73,8 @@ export function ReviewDetailShell({ review, storeHref }) {
72
73
  setVoted(true);
73
74
  localStorage.setItem(storageKey, "1");
74
75
  }
75
- catch {
76
+ catch (_err) {
77
+ void normalizeError(_err);
76
78
  // silently fail
77
79
  }
78
80
  finally {
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { normalizeError } from "../../../errors/normalize";
2
3
  const CLS_OUTLINE_BTN = "appkit-button appkit-button--outline appkit-button--md flex w-full items-center gap-2";
3
4
  import Link from "next/link";
4
5
  import { Shield, Phone, Wallet, Mail, AlertOctagon, Flag, Eye, Users, Calendar, ExternalLink, FileText, MessageSquare, Link2, } from "lucide-react";
@@ -13,7 +14,8 @@ function formatDate(d) {
13
14
  try {
14
15
  return new Date(d).toLocaleDateString("en-IN", { dateStyle: "medium" });
15
16
  }
16
- catch {
17
+ catch (_err) {
18
+ void normalizeError(_err);
17
19
  return String(d);
18
20
  }
19
21
  }
@@ -84,7 +84,8 @@ class ScammerRepository extends BaseRepository {
84
84
  .doc(id)
85
85
  .update({ [SCAMMER_FIELDS.VIEWS]: increment(1) });
86
86
  }
87
- catch {
87
+ catch (_err) {
88
+ void normalizeError(_err);
88
89
  // Fire-and-forget by design.
89
90
  }
90
91
  }
@@ -65,7 +65,8 @@ export async function GET(request) {
65
65
  try {
66
66
  siteSettings = await getSiteSettingsGlobal();
67
67
  }
68
- catch {
68
+ catch (_err) {
69
+ void normalizeError(_err);
69
70
  siteSettings = null;
70
71
  }
71
72
  if (listingType && siteSettings && !isListingTypeEnabled(listingType, siteSettings)) {
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { normalizeError } from "../../../errors/normalize";
3
4
  import { useEffect, useRef, useState } from "react";
4
5
  import JsBarcode from "jsbarcode";
5
6
  import { Heading, Text } from "../../../ui/components/Typography";
@@ -20,7 +21,8 @@ function ProductLabel({ product }) {
20
21
  margin: 8,
21
22
  });
22
23
  }
23
- catch {
24
+ catch (_err) {
25
+ void normalizeError(_err);
24
26
  // Invalid barcode value — render nothing
25
27
  }
26
28
  }