@mohasinac/appkit 3.2.16 → 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 (95) hide show
  1. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +13 -4
  2. package/dist/cli/index.js +6 -4
  3. package/dist/client/api/surface-error.js +3 -2
  4. package/dist/client/api/useApiQuery.js +3 -2
  5. package/dist/client/observability/reportClientError.js +3 -2
  6. package/dist/core/Logger.js +5 -4
  7. package/dist/core/StorageManager.js +6 -4
  8. package/dist/core/integration-keys.js +3 -3
  9. package/dist/errors/safe-read.js +2 -2
  10. package/dist/features/about/components/PolicyPageView.js +3 -1
  11. package/dist/features/admin/components/AdminAdEditorView.js +3 -1
  12. package/dist/features/admin/components/AdminAdsView.js +3 -1
  13. package/dist/features/admin/components/AdminBlogEditorView.js +3 -1
  14. package/dist/features/admin/components/AdminBundlesView.js +3 -1
  15. package/dist/features/admin/components/AdminCouponEditorView.js +3 -1
  16. package/dist/features/admin/components/AdminCouponsView.js +5 -2
  17. package/dist/features/admin/components/AdminGroupedListingsView.js +3 -1
  18. package/dist/features/admin/components/AdminNewsletterView.js +3 -1
  19. package/dist/features/admin/components/AdminPayoutsView.js +3 -1
  20. package/dist/features/admin/components/AdminSectionsView.js +3 -1
  21. package/dist/features/auctions/components/MarketplaceAuctionCard.js +3 -1
  22. package/dist/features/auctions/hooks/useRealtimeBids.js +3 -1
  23. package/dist/features/auth/hooks/useAuth.js +2 -1
  24. package/dist/features/blog/repository/blog.repository.js +2 -1
  25. package/dist/features/cart/utils/guest-cart.js +3 -1
  26. package/dist/features/cart/utils/pending-ops.js +5 -2
  27. package/dist/features/categories/hooks/useCategories.js +3 -1
  28. package/dist/features/categories/repository/categories.repository.js +2 -1
  29. package/dist/features/contact/components/ContactForm.js +3 -1
  30. package/dist/features/events/components/AdminEventEditorView.js +5 -2
  31. package/dist/features/events/components/EventBanner.js +5 -2
  32. package/dist/features/events/components/EventOfferCard.js +3 -1
  33. package/dist/features/events/components/EventRafflesSection.js +3 -1
  34. package/dist/features/history/hooks/useHistory.js +10 -5
  35. package/dist/features/history/utils/guest-history.js +3 -1
  36. package/dist/features/homepage/api/carousel/route.js +2 -1
  37. package/dist/features/homepage/api/route.js +2 -1
  38. package/dist/features/homepage/components/AdSlot.js +3 -1
  39. package/dist/features/homepage/components/AnnouncementBar.js +6 -2
  40. package/dist/features/homepage/components/CharacterHotspotForm.js +5 -2
  41. package/dist/features/homepage/components/GoogleReviewsSection.js +3 -1
  42. package/dist/features/homepage/components/NewsletterBanner.js +3 -1
  43. package/dist/features/homepage/lib/live-stats.js +2 -1
  44. package/dist/features/homepage/lib/section-helpers.d.ts +0 -1
  45. package/dist/features/homepage/lib/section-helpers.js +3 -1
  46. package/dist/features/media/MediaPickerModal.js +3 -1
  47. package/dist/features/media/finalize.js +7 -3
  48. package/dist/features/media/upload/MediaUploadField.js +6 -3
  49. package/dist/features/media/upload/MediaUploadList.js +2 -1
  50. package/dist/features/media/upload/video-poster.js +3 -1
  51. package/dist/features/messages/hooks/useConversation.js +2 -1
  52. package/dist/features/messages/hooks/useConversations.js +2 -1
  53. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +3 -1
  54. package/dist/features/products/components/BidHistory.js +3 -1
  55. package/dist/features/products/components/GroupSettingsPanel.js +2 -1
  56. package/dist/features/products/components/PrizeDrawsSection.js +3 -1
  57. package/dist/features/products/components/ShareButton.js +3 -1
  58. package/dist/features/products/repository/products.repository.js +4 -2
  59. package/dist/features/promotions/components/CouponCard.js +3 -1
  60. package/dist/features/reviews/components/ReviewDetailShell.js +3 -1
  61. package/dist/features/scams/components/ScamProfileView.js +3 -1
  62. package/dist/features/scams/repository/scammer.repository.js +2 -1
  63. package/dist/features/search/api/route.js +2 -1
  64. package/dist/features/seller/components/PrintCenterView.js +3 -1
  65. package/dist/features/seller/components/SellerAddressesView.js +2 -1
  66. package/dist/features/site-settings/components/ActionPermissionsManager.js +3 -1
  67. package/dist/features/site-settings/components/NavPermissionsManager.js +3 -1
  68. package/dist/features/whatsapp-bot/helpers/whatsapp.js +4 -2
  69. package/dist/features/wishlist/repository/user-wishlist.repository.js +3 -1
  70. package/dist/features/wishlist/utils/guest-wishlist.js +3 -1
  71. package/dist/http/api-handler.js +5 -2
  72. package/dist/monitoring/cache-metrics.d.ts +0 -4
  73. package/dist/monitoring/cache-metrics.js +4 -2
  74. package/dist/monitoring/client-logger.js +4 -2
  75. package/dist/monitoring/server-logger.js +6 -5
  76. package/dist/next/api/apiHandler.js +2 -1
  77. package/dist/next/api/routeHandler.js +10 -5
  78. package/dist/next/middleware/pii-redactor.js +3 -1
  79. package/dist/next/middleware/pii-scrubber.js +3 -1
  80. package/dist/providers/auth-firebase/helpers.js +2 -1
  81. package/dist/providers/auth-firebase/session.js +2 -1
  82. package/dist/providers/db-firebase/admin.js +3 -1
  83. package/dist/providers/firebase-client/realtime.js +3 -1
  84. package/dist/providers/shipping-shiprocket/index.d.ts +0 -21
  85. package/dist/providers/shipping-shiprocket/index.js +3 -1
  86. package/dist/react/contexts/SessionContext.js +2 -1
  87. package/dist/react/hooks/useFormStatePreservation.js +3 -1
  88. package/dist/seed/seed-market-config.js +3 -1
  89. package/dist/ui/components/ClaimCouponButton.js +5 -2
  90. package/dist/ui/components/NavigationLoader.js +5 -2
  91. package/dist/utils/id-generators.js +3 -1
  92. package/dist/utils/string.formatter.d.ts +0 -3
  93. package/dist/utils/string.formatter.js +3 -1
  94. package/dist/validation/schemas.js +3 -1
  95. package/package.json +1 -1
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { normalizeError } from "../../../../errors/normalize";
3
4
  /**
4
5
  * DashboardLayoutClient — unified client island that replaces the ~75 lines of
5
6
  * boilerplate previously duplicated across admin/store/user layout.tsx files.
@@ -49,7 +50,9 @@ function useResponsiveDrawer(storageKey) {
49
50
  if (localStorage.getItem(storageKey) === "true")
50
51
  setDesktopOpen(true);
51
52
  }
52
- catch { /* localStorage unavailable (private-browse / SSR fallback) */ }
53
+ catch (_err) {
54
+ void normalizeError(_err); /* localStorage unavailable (private-browse / SSR fallback) */
55
+ }
53
56
  }, [storageKey]);
54
57
  const open = useCallback(() => {
55
58
  startTransition(() => {
@@ -57,7 +60,9 @@ function useResponsiveDrawer(storageKey) {
57
60
  try {
58
61
  localStorage.setItem(storageKey, "true");
59
62
  }
60
- catch { /* noop */ }
63
+ catch (_err) {
64
+ void normalizeError(_err);
65
+ }
61
66
  setDesktopOpen(true);
62
67
  }
63
68
  else
@@ -70,7 +75,9 @@ function useResponsiveDrawer(storageKey) {
70
75
  try {
71
76
  localStorage.setItem(storageKey, "false");
72
77
  }
73
- catch { /* noop */ }
78
+ catch (_err) {
79
+ void normalizeError(_err);
80
+ }
74
81
  setDesktopOpen(false);
75
82
  }
76
83
  else
@@ -89,7 +96,9 @@ function useResponsiveDrawer(storageKey) {
89
96
  try {
90
97
  localStorage.setItem(storageKey, String(next));
91
98
  }
92
- catch { /* noop */ }
99
+ catch (_err) {
100
+ void normalizeError(_err);
101
+ }
93
102
  return next;
94
103
  });
95
104
  }
package/dist/cli/index.js CHANGED
@@ -14,6 +14,7 @@
14
14
  * import features from "../../features.config";
15
15
  * const messages = await mergeFeatureMessages(locale, features);
16
16
  */
17
+ import { normalizeError } from "../errors/normalize";
17
18
  // ---------------------------------------------------------------------------
18
19
  // withFeatures — next.config.js helper
19
20
  // ---------------------------------------------------------------------------
@@ -145,8 +146,9 @@ async function tryLoadFeatureMessages(featureKey, locale) {
145
146
  const mod = await _dynamicImport(`@mohasinac/appkit/features/${featureKey}/messages/${locale}.json`);
146
147
  return (mod.default ?? mod);
147
148
  }
148
- catch {
149
- return {};
149
+ catch (_err) {
150
+ void normalizeError(_err);
151
+ return {}; // feature message file not present — treat as empty (feature messages are optional per-locale)
150
152
  }
151
153
  }
152
154
  /**
@@ -162,8 +164,8 @@ export async function mergeFeatureMessages(locale, features) {
162
164
  const mod = await _dynamicImport(`../../messages/${locale}.json`);
163
165
  projectMessages = (mod.default ?? mod);
164
166
  }
165
- catch {
166
- // Tolerate missing file (e.g. test environments)
167
+ catch (_err) {
168
+ void normalizeError(_err); // Tolerate missing file project may not have a locale file for this locale yet
167
169
  }
168
170
  const enabledKeys = Object.entries(features)
169
171
  .filter(([key, enabled]) => enabled && key in FEATURE_NAMESPACE_MAP)
@@ -1,4 +1,5 @@
1
1
  import { isApiError } from "./ApiError";
2
+ import { normalizeError } from "../../errors/normalize";
2
3
  import { getErrorDisplay } from "../../errors/error-display-map";
3
4
  export function surfaceError(err, opts) {
4
5
  const { showToast, setFieldError, translate, report } = opts;
@@ -25,8 +26,8 @@ export function surfaceError(err, opts) {
25
26
  stack: err instanceof Error ? err.stack : undefined,
26
27
  });
27
28
  }
28
- catch {
29
- // never let the reporter break the catch path
29
+ catch (_err) {
30
+ void normalizeError(_err); // error reporter must never break the catch path — it is a pure side-effect sink
30
31
  }
31
32
  }
32
33
  // Re-throw if it's a non-Error so framework error boundaries still see it.
@@ -1,4 +1,5 @@
1
1
  "use client";
2
+ import { normalizeError } from "../../errors/normalize";
2
3
  import * as React from "react";
3
4
  import { useQuery, } from "@tanstack/react-query";
4
5
  import { useToast } from "../../ui/components/Toast";
@@ -32,8 +33,8 @@ export function useApiQuery(options) {
32
33
  requestId: err.requestId,
33
34
  });
34
35
  }
35
- catch {
36
- /* never propagate from the reporter */
36
+ catch (_err) {
37
+ void normalizeError(_err); /* never propagate from the reporter — it is a pure observability sink */
37
38
  }
38
39
  }
39
40
  }
@@ -1,4 +1,5 @@
1
1
  "use client";
2
+ import { normalizeError } from "../../errors/normalize";
2
3
  const SEEN = new Map();
3
4
  const DEDUPE_WINDOW_MS = 5000;
4
5
  const MAX_SEEN = 32;
@@ -64,7 +65,7 @@ export function reportClientError(payload) {
64
65
  /* swallow — reporting must never throw */
65
66
  });
66
67
  }
67
- catch {
68
- /* swallow — reporting must never throw */
68
+ catch (_err) {
69
+ void normalizeError(_err); /* swallow — error reporting must never throw and break the calling error handler */
69
70
  }
70
71
  }
@@ -8,6 +8,7 @@
8
8
  * `import("@/constants")` call, making this usable in any context.
9
9
  */
10
10
  import { LOGS_ENDPOINTS } from "../constants/api-endpoints";
11
+ import { normalizeError } from "../errors/normalize";
11
12
  export class Logger {
12
13
  constructor(options) {
13
14
  this.logs = [];
@@ -91,8 +92,8 @@ export class Logger {
91
92
  try {
92
93
  localStorage.setItem("app_logs", JSON.stringify(this.logs));
93
94
  }
94
- catch {
95
- // Silently fail
95
+ catch (_err) {
96
+ void normalizeError(_err); // localStorage unavailable or quota exceeded — logger must not crash the app
96
97
  }
97
98
  }
98
99
  async writeToFile(entry) {
@@ -110,8 +111,8 @@ export class Logger {
110
111
  }),
111
112
  });
112
113
  }
113
- catch {
114
- // Silently fail
114
+ catch (_err) {
115
+ void normalizeError(_err); // remote log endpoint unavailable — logger must not crash the app
115
116
  }
116
117
  }
117
118
  debug(message, data) {
@@ -29,8 +29,9 @@ export class StorageManager {
29
29
  const storage = type === "local" ? window.localStorage : window.sessionStorage;
30
30
  return storage ?? null;
31
31
  }
32
- catch {
33
- return null;
32
+ catch (_err) {
33
+ void normalizeError(_err);
34
+ return null; // localStorage/sessionStorage unavailable (SSR, cross-origin iframe, or security policy)
34
35
  }
35
36
  }
36
37
  generateKey(key) {
@@ -138,8 +139,9 @@ export class StorageManager {
138
139
  storage.removeItem(testKey);
139
140
  return true;
140
141
  }
141
- catch {
142
- return false;
142
+ catch (_err) {
143
+ void normalizeError(_err);
144
+ return false; // storage blocked by browser security policy or private mode
143
145
  }
144
146
  }
145
147
  getAll(options) {
@@ -14,6 +14,7 @@
14
14
  * const razorpay = new Razorpay({ key_id: keys.razorpayKeyId, key_secret: keys.razorpayKeySecret });
15
15
  */
16
16
  import { siteSettingsRepository } from "../repositories";
17
+ import { normalizeError } from "../errors/normalize";
17
18
  const EMPTY_KEYS = {
18
19
  razorpayKeyId: "",
19
20
  razorpayKeySecret: "",
@@ -41,9 +42,8 @@ export async function resolveKeys() {
41
42
  try {
42
43
  db = await siteSettingsRepository.getDecryptedCredentials();
43
44
  }
44
- catch {
45
- // Preserve legacy letitrip behavior: Firestore failures must still fall
46
- // through to env-based defaults instead of failing key resolution.
45
+ catch (_err) {
46
+ void normalizeError(_err); // Firestore unavailable fall through to env-based defaults for backward compatibility
47
47
  }
48
48
  const value = {
49
49
  razorpayKeyId: db.razorpayKeyId || process.env.RAZORPAY_KEY_ID || "",
@@ -31,8 +31,8 @@ export async function safeRead(fn, opts) {
31
31
  stack: err instanceof Error ? err.stack : undefined,
32
32
  });
33
33
  }
34
- catch {
35
- // reporter itself must never propagate; safeRead is a safety net.
34
+ catch (_err) {
35
+ void normalizeError(_err); // error reporter must never propagate safeRead is a last-resort safety net
36
36
  }
37
37
  return opts.fallback;
38
38
  }
@@ -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 { Row } from "@mohasinac/appkit/ui";
3
4
  import { ROUTES } from "../../../constants";
4
5
  import { PAGE_CONTAINER } from "../../../_internal/shared/styles/page";
@@ -28,7 +29,8 @@ export async function PolicyPageView({ policy, }) {
28
29
  const legalPages = settings.legalPages ?? {};
29
30
  adminHtml = legalPages[firestoreFieldMap[policy]] ?? "";
30
31
  }
31
- catch {
32
+ catch (_err) {
33
+ void normalizeError(_err);
32
34
  // Firestore unavailable — fall back to i18n
33
35
  }
34
36
  // i18n fallback sections
@@ -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 { useApiMutation } from "@mohasinac/appkit/client";
4
5
  import React from "react";
5
6
  import { useQuery } from "@tanstack/react-query";
@@ -20,7 +21,8 @@ function validateThirdPartyUrl(url, issues) {
20
21
  issues.push("Third-party ad URL must be https");
21
22
  }
22
23
  }
23
- catch {
24
+ catch (_err) {
25
+ void normalizeError(_err);
24
26
  issues.push("Third-party ad URL must be a valid URL");
25
27
  }
26
28
  }
@@ -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 { useApiMutation } from "@mohasinac/appkit/client";
4
5
  import React from "react";
5
6
  import { useQuery, useQueryClient } from "@tanstack/react-query";
@@ -135,7 +136,8 @@ export function AdminAdsView({ endpoint = ADMIN_ENDPOINTS.ADS, labels = {}, crea
135
136
  issues.push("Third-party script URL must be https");
136
137
  }
137
138
  }
138
- catch {
139
+ catch (_err) {
140
+ void normalizeError(_err);
139
141
  issues.push("Third-party script URL must be a valid URL");
140
142
  }
141
143
  }
@@ -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";
@@ -57,7 +58,8 @@ function toDateInputValue(val) {
57
58
  try {
58
59
  return new Date(val).toISOString().split("T")[0];
59
60
  }
60
- catch {
61
+ catch (_err) {
62
+ void normalizeError(_err);
61
63
  return "";
62
64
  }
63
65
  }
@@ -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 { Row, SIEVE_OP, sieveFilter } from "@mohasinac/appkit";
4
5
  import { sortBy } from "@mohasinac/appkit";
5
6
  import { useState, useCallback } from "react";
@@ -50,7 +51,8 @@ export function AdminBundlesView({ getEditHref, newHref }) {
50
51
  throw new Error("Rebuild failed");
51
52
  toast.showToast("Bundle stock rebuilt.", "success");
52
53
  }
53
- catch {
54
+ catch (_err) {
55
+ void normalizeError(_err);
54
56
  toast.showToast("Failed to rebuild bundle stock.", "error");
55
57
  }
56
58
  finally {
@@ -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 { Row } from "@mohasinac/appkit/ui";
4
5
  import { useApiMutation } from "@mohasinac/appkit/client";
5
6
  import React from "react";
@@ -43,7 +44,8 @@ function toDateInputValue(val) {
43
44
  try {
44
45
  return new Date(val).toISOString().split("T")[0];
45
46
  }
46
- catch {
47
+ catch (_err) {
48
+ void normalizeError(_err);
47
49
  return "";
48
50
  }
49
51
  }
@@ -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 { SIEVE_OP, Stack, sieveFilter } from "@mohasinac/appkit";
4
5
  import { sortBy } from "@mohasinac/appkit";
5
6
  import React, { useCallback } from "react";
@@ -26,7 +27,8 @@ export function AdminCouponsView({ children, onBulkArchive, onBulkDelete, ...pro
26
27
  showToast(currentlyActive ? "Coupon deactivated." : "Coupon activated.", "success");
27
28
  queryClient.invalidateQueries({ queryKey: ["admin", "coupons"] });
28
29
  }
29
- catch {
30
+ catch (_err) {
31
+ void normalizeError(_err);
30
32
  showToast("Could not update coupon status.", "error");
31
33
  }
32
34
  }, [showToast, queryClient]);
@@ -36,7 +38,8 @@ export function AdminCouponsView({ children, onBulkArchive, onBulkDelete, ...pro
36
38
  showToast("Coupon deleted.", "success");
37
39
  queryClient.invalidateQueries({ queryKey: ["admin", "coupons"] });
38
40
  }
39
- catch {
41
+ catch (_err) {
42
+ void normalizeError(_err);
40
43
  showToast("Could not delete coupon.", "error");
41
44
  }
42
45
  }, [showToast, queryClient]);
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { normalizeError } from "../../../errors/normalize";
3
4
  /**
4
5
  * AdminGroupedListingsView — admin moderation view for grouped product listings.
5
6
  * W1-29 — pairs with the new GET /api/admin/grouped-listings endpoint.
@@ -25,7 +26,8 @@ function ReassignProductsDrawer({ state, onClose, onSaved, }) {
25
26
  onSaved();
26
27
  onClose();
27
28
  }
28
- catch {
29
+ catch (_err) {
30
+ void normalizeError(_err);
29
31
  showToast("Failed to save changes.", "error");
30
32
  }
31
33
  finally {
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { normalizeError } from "../../../errors/normalize";
3
4
  import { useApiMutation } from "@mohasinac/appkit/client";
4
5
  import { sieveFilter, SIEVE_OP } from "@mohasinac/appkit";
5
6
  import { sortBy } from "@mohasinac/appkit";
@@ -45,7 +46,8 @@ export function AdminNewsletterView({ children, onBulkUnsubscribe, ...props }) {
45
46
  a.click();
46
47
  URL.revokeObjectURL(url);
47
48
  }
48
- catch {
49
+ catch (_err) {
50
+ void normalizeError(_err);
49
51
  showToast("Failed to export CSV.", "error");
50
52
  }
51
53
  }, [showToast]);
@@ -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 { sieveFilter, SIEVE_OP } from "@mohasinac/appkit";
5
6
  import { sortBy } from "@mohasinac/appkit";
@@ -48,7 +49,8 @@ export function AdminPayoutsView({ children, ...props }) {
48
49
  a.click();
49
50
  URL.revokeObjectURL(url);
50
51
  }
51
- catch {
52
+ catch (_err) {
53
+ void normalizeError(_err);
52
54
  toast.showToast("CSV export failed.", "error");
53
55
  }
54
56
  };
@@ -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, useQueryClient } from "@tanstack/react-query";
@@ -172,7 +173,8 @@ export function AdminSectionsView({ children }) {
172
173
  try {
173
174
  parsedConfig = JSON.parse(configJson);
174
175
  }
175
- catch {
176
+ catch (_err) {
177
+ void normalizeError(_err);
176
178
  throw new Error("Config must be valid JSON.");
177
179
  }
178
180
  if (mode === "create") {
@@ -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, useEffect, useRef, useState } from "react";
4
5
  import { useRouter } from "next/navigation";
5
6
  import { Clock, Gavel, Heart, Play, ShoppingBag, Star } from "lucide-react";
@@ -145,7 +146,8 @@ export function MarketplaceAuctionCard({ product, buyoutPrice, className = "", v
145
146
  try {
146
147
  await toggle();
147
148
  }
148
- catch {
149
+ catch (_err) {
150
+ void normalizeError(_err);
149
151
  // The hook rolls back optimistic state when the mutation fails.
150
152
  }
151
153
  }, [toggle]);
@@ -1,4 +1,5 @@
1
1
  "use client";
2
+ import { normalizeError } from "../../../errors/normalize";
2
3
  import { useEffect, useState } from "react";
3
4
  import { logger } from "../../../core/Logger";
4
5
  import { BID_ENDPOINTS } from "../../../constants/api-endpoints";
@@ -41,7 +42,8 @@ export function useRealtimeBids(productId, getEndpoint = BID_ENDPOINTS.REALTIME)
41
42
  setConnected(false);
42
43
  }
43
44
  }
44
- catch {
45
+ catch (_err) {
46
+ void normalizeError(_err);
45
47
  logger.warn("[useRealtimeBids] Failed to parse SSE message");
46
48
  }
47
49
  };
@@ -15,7 +15,8 @@ export function useCurrentUser(opts) {
15
15
  try {
16
16
  return await apiClient.get(AUTH_ENDPOINTS.ME);
17
17
  }
18
- catch {
18
+ catch (_err) {
19
+ void normalizeError(_err);
19
20
  return null;
20
21
  }
21
22
  },
@@ -71,7 +71,8 @@ class BlogRepository extends BaseRepository {
71
71
  .doc(id)
72
72
  .update({ [BLOG_POST_FIELDS.VIEWS]: increment(1) });
73
73
  }
74
- catch {
74
+ catch (_err) {
75
+ void normalizeError(_err);
75
76
  // Fire-and-forget by design.
76
77
  }
77
78
  }
@@ -1,3 +1,4 @@
1
+ import { normalizeError } from "../../../errors/normalize";
1
2
  import { CART_MAX_ITEMS } from "../../../constants/limits";
2
3
  const DEFAULT_GUEST_CART_KEY = process.env.NEXT_PUBLIC_APP_ID
3
4
  ? `${process.env.NEXT_PUBLIC_APP_ID}_guest_cart`
@@ -29,7 +30,8 @@ function readItems(storage, key) {
29
30
  const parsed = JSON.parse(raw);
30
31
  return Array.isArray(parsed) ? parsed : [];
31
32
  }
32
- catch {
33
+ catch (_err) {
34
+ void normalizeError(_err);
33
35
  return [];
34
36
  }
35
37
  }
@@ -5,6 +5,7 @@
5
5
  * Written to localStorage so they survive page refreshes.
6
6
  * The sync manager replays these and clears them after a successful push.
7
7
  */
8
+ import { normalizeError } from "../../../errors/normalize";
8
9
  const APP_ID = () => typeof process !== "undefined" && process.env.NEXT_PUBLIC_APP_ID
9
10
  ? process.env.NEXT_PUBLIC_APP_ID
10
11
  : "letitrip";
@@ -23,7 +24,8 @@ function read(key) {
23
24
  const parsed = JSON.parse(raw);
24
25
  return Array.isArray(parsed) ? parsed : [];
25
26
  }
26
- catch {
27
+ catch (_err) {
28
+ void normalizeError(_err);
27
29
  return [];
28
30
  }
29
31
  }
@@ -33,7 +35,8 @@ function write(key, items) {
33
35
  try {
34
36
  localStorage.setItem(key, JSON.stringify(items));
35
37
  }
36
- catch {
38
+ catch (_err) {
39
+ void normalizeError(_err);
37
40
  // storage quota exceeded — best effort
38
41
  }
39
42
  }
@@ -1,4 +1,5 @@
1
1
  "use client";
2
+ import { normalizeError } from "../../../errors/normalize";
2
3
  import { useMemo } from "react";
3
4
  import { useQuery } from "@tanstack/react-query";
4
5
  import { apiClient } from "../../../http";
@@ -76,7 +77,8 @@ export function useCategoryDetail(slug, opts) {
76
77
  try {
77
78
  return await apiClient.get(categoryEndpoint);
78
79
  }
79
- catch {
80
+ catch (_err) {
81
+ void normalizeError(_err);
80
82
  return null;
81
83
  }
82
84
  },
@@ -460,7 +460,8 @@ export class CategoriesRepository extends BaseRepository {
460
460
  .doc(categoryId)
461
461
  .update({ [CATEGORY_FIELDS.VIEW_COUNT]: increment(1) });
462
462
  }
463
- catch {
463
+ catch (_err) {
464
+ void normalizeError(_err);
464
465
  // View analytics must not break category read path.
465
466
  }
466
467
  }
@@ -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, useCallback } from "react";
4
5
  import { Button, Div, Heading, Span, Stack, Text, Textarea } from "../../../ui";
5
6
  const CLS_FIELD_ERROR = "text-error";
@@ -41,7 +42,8 @@ export function ContactForm({ onSubmit, labels = {}, className = "", }) {
41
42
  setSubmitted(true);
42
43
  setForm(INITIAL_FORM);
43
44
  }
44
- catch {
45
+ catch (_err) {
46
+ void normalizeError(_err);
45
47
  setSubmitError(labels.errorGeneric ?? "Something went wrong. Please try again.");
46
48
  }
47
49
  finally {
@@ -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
  };