@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.
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +13 -4
- package/dist/_internal/server/jobs/core/listingProcessor.js +2 -1
- package/dist/_internal/server/jobs/core/wrapJobHandler.js +2 -1
- package/dist/_internal/shared/listing-types/action-tracker.js +1 -1
- package/dist/cli/index.js +6 -4
- package/dist/client/api/surface-error.js +3 -2
- package/dist/client/api/useApiQuery.js +3 -2
- package/dist/client/observability/reportClientError.js +3 -2
- package/dist/core/Logger.js +5 -4
- package/dist/core/StorageManager.js +6 -4
- package/dist/core/integration-keys.js +3 -3
- package/dist/errors/safe-read.js +2 -2
- package/dist/features/about/components/PolicyPageView.js +3 -1
- package/dist/features/admin/components/AdminAdEditorView.js +3 -1
- package/dist/features/admin/components/AdminAdsView.js +3 -1
- package/dist/features/admin/components/AdminBlogEditorView.js +3 -1
- package/dist/features/admin/components/AdminBundlesView.js +3 -1
- package/dist/features/admin/components/AdminCouponEditorView.js +3 -1
- package/dist/features/admin/components/AdminCouponsView.js +5 -2
- package/dist/features/admin/components/AdminGroupedListingsView.js +3 -1
- package/dist/features/admin/components/AdminNewsletterView.js +3 -1
- package/dist/features/admin/components/AdminPayoutsView.js +3 -1
- package/dist/features/admin/components/AdminSectionsView.js +3 -1
- package/dist/features/admin/repository/chat.repository.js +2 -2
- package/dist/features/admin/repository/site-settings.repository.js +1 -1
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +3 -1
- package/dist/features/auctions/hooks/useRealtimeBids.js +3 -1
- package/dist/features/auth/hooks/useAuth.js +2 -1
- package/dist/features/blog/repository/blog.repository.js +2 -1
- package/dist/features/cart/utils/guest-cart.js +3 -1
- package/dist/features/cart/utils/pending-ops.js +5 -2
- package/dist/features/categories/hooks/useCategories.js +3 -1
- package/dist/features/categories/repository/categories.repository.js +2 -1
- package/dist/features/contact/components/ContactForm.js +3 -1
- package/dist/features/events/components/AdminEventEditorView.js +5 -2
- package/dist/features/events/components/EventBanner.js +5 -2
- package/dist/features/events/components/EventOfferCard.js +3 -1
- package/dist/features/events/components/EventRafflesSection.js +3 -1
- package/dist/features/history/hooks/useHistory.js +10 -5
- package/dist/features/history/utils/guest-history.js +3 -1
- package/dist/features/homepage/api/carousel/route.js +2 -1
- package/dist/features/homepage/api/route.js +2 -1
- package/dist/features/homepage/components/AdSlot.js +3 -1
- package/dist/features/homepage/components/AnnouncementBar.js +6 -2
- package/dist/features/homepage/components/CharacterHotspotForm.js +5 -2
- package/dist/features/homepage/components/GoogleReviewsSection.js +3 -1
- package/dist/features/homepage/components/NewsletterBanner.js +3 -1
- package/dist/features/homepage/lib/live-stats.js +2 -1
- package/dist/features/homepage/lib/section-helpers.d.ts +0 -1
- package/dist/features/homepage/lib/section-helpers.js +3 -1
- package/dist/features/media/MediaPickerModal.js +3 -1
- package/dist/features/media/finalize.js +7 -3
- package/dist/features/media/upload/MediaUploadField.js +6 -3
- package/dist/features/media/upload/MediaUploadList.js +2 -1
- package/dist/features/media/upload/video-poster.js +3 -1
- package/dist/features/messages/hooks/useConversation.js +2 -1
- package/dist/features/messages/hooks/useConversations.js +2 -1
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +3 -1
- package/dist/features/products/components/BidHistory.js +3 -1
- package/dist/features/products/components/GroupSettingsPanel.js +2 -1
- package/dist/features/products/components/PrizeDrawsSection.js +3 -1
- package/dist/features/products/components/ShareButton.js +3 -1
- package/dist/features/products/repository/products.repository.js +4 -2
- package/dist/features/promotions/components/CouponCard.js +3 -1
- package/dist/features/reviews/components/ReviewDetailShell.js +3 -1
- package/dist/features/scams/components/ScamProfileView.js +3 -1
- package/dist/features/scams/repository/scammer.repository.js +2 -1
- package/dist/features/search/api/route.js +2 -1
- package/dist/features/seller/components/PrintCenterView.js +3 -1
- package/dist/features/seller/components/SellerAddressesView.js +2 -1
- package/dist/features/site-settings/components/ActionPermissionsManager.js +3 -1
- package/dist/features/site-settings/components/NavPermissionsManager.js +3 -1
- package/dist/features/whatsapp-bot/helpers/whatsapp.js +4 -2
- package/dist/features/wishlist/repository/user-wishlist.repository.js +3 -1
- package/dist/features/wishlist/utils/guest-wishlist.js +3 -1
- package/dist/http/api-handler.js +5 -2
- package/dist/monitoring/cache-metrics.d.ts +0 -4
- package/dist/monitoring/cache-metrics.js +4 -2
- package/dist/monitoring/client-logger.js +4 -2
- package/dist/monitoring/server-logger.js +6 -5
- package/dist/next/api/apiHandler.js +2 -1
- package/dist/next/api/routeHandler.js +10 -5
- package/dist/next/middleware/pii-redactor.js +3 -1
- package/dist/next/middleware/pii-scrubber.js +3 -1
- package/dist/providers/auth-firebase/helpers.js +2 -1
- package/dist/providers/auth-firebase/session.js +2 -1
- package/dist/providers/db-firebase/admin.js +3 -1
- package/dist/providers/firebase-client/realtime.js +3 -1
- package/dist/providers/shipping-shiprocket/index.d.ts +0 -21
- package/dist/providers/shipping-shiprocket/index.js +3 -1
- package/dist/react/contexts/SessionContext.js +2 -1
- package/dist/react/hooks/useFormStatePreservation.js +3 -1
- package/dist/seed/seed-market-config.js +3 -1
- package/dist/ui/components/ClaimCouponButton.js +5 -2
- package/dist/ui/components/NavigationLoader.js +5 -2
- package/dist/utils/id-generators.js +3 -1
- package/dist/utils/string.formatter.d.ts +0 -3
- package/dist/utils/string.formatter.js +3 -1
- package/dist/validation/schemas.js +3 -1
- 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
|
|
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 {
|
|
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 {
|
|
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 {
|
|
99
|
+
catch (_err) {
|
|
100
|
+
void normalizeError(_err);
|
|
101
|
+
}
|
|
93
102
|
return next;
|
|
94
103
|
});
|
|
95
104
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* (`p` directly) or infinite-mode (forward `cursor` from previous response).
|
|
8
8
|
*/
|
|
9
9
|
import { bidRepository, blogRepository, categoriesRepository, couponsRepository, eventEntryRepository, eventRepository, faqsRepository, homepageSectionsRepository, notificationRepository, orderRepository, payoutRepository, productFeaturesRepository, productRepository, productTemplateRepository, reviewRepository, scammerRepository, storeRepository, userRepository, } from "../../../../repositories";
|
|
10
|
+
import { normalizeError } from "../../../../errors/normalize";
|
|
10
11
|
const DEFAULT_SORT = "-createdAt";
|
|
11
12
|
const DEFAULT_PAGE = 1;
|
|
12
13
|
const DEFAULT_PAGE_SIZE = 20;
|
|
@@ -84,7 +85,7 @@ function decodeCursor(cursor) {
|
|
|
84
85
|
return Number.isFinite(page) && page > 0 ? page : null;
|
|
85
86
|
}
|
|
86
87
|
catch (_err) {
|
|
87
|
-
// Malformed base64 or JSON — treat as no cursor
|
|
88
|
+
void normalizeError(_err); // Malformed base64 or JSON — treat as no cursor
|
|
88
89
|
return null;
|
|
89
90
|
}
|
|
90
91
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* UI sees a row for every Cloud Function failure.
|
|
8
8
|
*/
|
|
9
9
|
import { mapToHttpError } from "../../../../errors/error-mapping";
|
|
10
|
+
import { normalizeError } from "../../../../errors/normalize";
|
|
10
11
|
import { serverErrorsRepository } from "../../../../features/server-errors/repository/server-errors.repository";
|
|
11
12
|
async function persist(name, err, ctxLike) {
|
|
12
13
|
const mapped = mapToHttpError(err);
|
|
@@ -22,7 +23,7 @@ async function persist(name, err, ctxLike) {
|
|
|
22
23
|
});
|
|
23
24
|
}
|
|
24
25
|
catch (_err) {
|
|
25
|
-
// Logging the logging failure
|
|
26
|
+
void normalizeError(_err); // Logging the logging failure — only normalize, never re-log
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
export function wrapScheduleHandler(name, handler) {
|
|
@@ -37,7 +37,7 @@ export const actionTracker = {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
catch (_err) {
|
|
40
|
-
// Telemetry sink threw synchronously — swallowed so
|
|
40
|
+
void normalizeError(_err); // Telemetry sink threw synchronously — swallowed so caller always completes
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
43
|
};
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
}
|
package/dist/core/Logger.js
CHANGED
|
@@ -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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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 || "",
|
package/dist/errors/safe-read.js
CHANGED
|
@@ -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
|
|
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") {
|
|
@@ -182,7 +182,7 @@ class ChatRepository extends BaseRepository {
|
|
|
182
182
|
await getAdminRealtimeDb().ref(`/chat/${chatId}`).remove();
|
|
183
183
|
}
|
|
184
184
|
catch (_err) {
|
|
185
|
-
// RTDB cleanup is best-effort — Firestore doc already deleted
|
|
185
|
+
void normalizeError(_err); // RTDB cleanup is best-effort — Firestore doc already deleted
|
|
186
186
|
}
|
|
187
187
|
return "deleted";
|
|
188
188
|
}
|
|
@@ -211,7 +211,7 @@ class ChatRepository extends BaseRepository {
|
|
|
211
211
|
await getAdminRealtimeDb().ref(`/chat/${chatId}`).remove();
|
|
212
212
|
}
|
|
213
213
|
catch (_err) {
|
|
214
|
-
// RTDB cleanup is best-effort — adminDeleted flag
|
|
214
|
+
void normalizeError(_err); // RTDB cleanup is best-effort — adminDeleted flag already revokes access
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
217
|
catch (error) {
|
|
@@ -133,7 +133,7 @@ export class SiteSettingsRepository extends BaseRepository {
|
|
|
133
133
|
result[key] = decryptSecret(value);
|
|
134
134
|
}
|
|
135
135
|
catch (_err) {
|
|
136
|
-
// Auth-tag mismatch or
|
|
136
|
+
void normalizeError(_err); // Auth-tag mismatch or key rotation — treat as missing credential
|
|
137
137
|
result[key] = "";
|
|
138
138
|
}
|
|
139
139
|
}
|
|
@@ -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
|
};
|
|
@@ -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 {
|