@mohasinac/appkit 3.2.12 → 3.2.16
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/server/features/products/data.js +5 -1
- package/dist/_internal/server/jobs/core/listingProcessor.js +3 -1
- package/dist/_internal/server/jobs/core/wrapJobHandler.js +3 -2
- package/dist/_internal/shared/listing-types/action-tracker.js +2 -2
- package/dist/features/admin/actions/notification-actions.js +3 -2
- package/dist/features/admin/repository/chat.repository.js +4 -4
- package/dist/features/admin/repository/site-settings.repository.js +8 -4
- package/dist/features/cron/jobs/auction-expiry.job.js +5 -1
- package/dist/features/cron/jobs/preorder-reminder.job.js +5 -1
- package/dist/features/promotions/repository/coupons.repository.js +5 -2
- package/dist/utils/media-url.js +3 -1
- package/dist/validation/url.validator.js +7 -3
- package/package.json +1 -1
|
@@ -2,6 +2,8 @@ import { cache } from "react";
|
|
|
2
2
|
import { productRepository } from "../../../../repositories";
|
|
3
3
|
import { reviewRepository } from "../../../../repositories";
|
|
4
4
|
import { getAdminDb } from "../../../../providers/db-firebase";
|
|
5
|
+
import { normalizeError } from "../../../../errors/normalize";
|
|
6
|
+
import { serverLogger } from "../../../../monitoring/server-logger";
|
|
5
7
|
import { PRODUCT_COLLECTION } from "../../../../features/products/schemas/firestore";
|
|
6
8
|
import { PRODUCTS_SITEMAP_LIMIT } from "../../../shared/features/products/config";
|
|
7
9
|
import { PRODUCT_FIELDS } from "../../../../constants/field-names";
|
|
@@ -46,7 +48,9 @@ export async function listSitemapProducts() {
|
|
|
46
48
|
};
|
|
47
49
|
});
|
|
48
50
|
}
|
|
49
|
-
catch {
|
|
51
|
+
catch (err) {
|
|
52
|
+
void normalizeError(err);
|
|
53
|
+
serverLogger.warn("products-data: listSitemapProducts failed — returning empty", { error: err instanceof Error ? err.message : String(err) });
|
|
50
54
|
return [];
|
|
51
55
|
}
|
|
52
56
|
}
|
|
@@ -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;
|
|
@@ -83,7 +84,8 @@ function decodeCursor(cursor) {
|
|
|
83
84
|
const page = Number(parsed.page);
|
|
84
85
|
return Number.isFinite(page) && page > 0 ? page : null;
|
|
85
86
|
}
|
|
86
|
-
catch {
|
|
87
|
+
catch (_err) {
|
|
88
|
+
void normalizeError(_err); // Malformed base64 or JSON — treat as no cursor
|
|
87
89
|
return null;
|
|
88
90
|
}
|
|
89
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);
|
|
@@ -21,8 +22,8 @@ async function persist(name, err, ctxLike) {
|
|
|
21
22
|
occurredAt: (ctxLike?.now ?? new Date()).getTime(),
|
|
22
23
|
});
|
|
23
24
|
}
|
|
24
|
-
catch {
|
|
25
|
-
|
|
25
|
+
catch (_err) {
|
|
26
|
+
void normalizeError(_err); // Logging the logging failure — only normalize, never re-log
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
export function wrapScheduleHandler(name, handler) {
|
|
@@ -36,8 +36,8 @@ export const actionTracker = {
|
|
|
36
36
|
result.catch((err) => { void normalizeError(err); });
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
-
catch {
|
|
40
|
-
//
|
|
39
|
+
catch (_err) {
|
|
40
|
+
void normalizeError(_err); // Telemetry sink threw synchronously — swallowed so caller always completes
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
43
|
};
|
|
@@ -62,8 +62,9 @@ export async function sendNotification(input) {
|
|
|
62
62
|
userChannelPrefs = fetchedUserDoc?.notificationPreferences?.channels ?? {};
|
|
63
63
|
userTypePrefs = fetchedUserDoc?.notificationPreferences?.types ?? {};
|
|
64
64
|
}
|
|
65
|
-
catch {
|
|
66
|
-
|
|
65
|
+
catch (err) {
|
|
66
|
+
void normalizeError(err);
|
|
67
|
+
serverLogger.warn("notification-actions: user prefs lookup failed — defaulting to all channels enabled", { userId: input.userId, error: err instanceof Error ? err.message : String(err) });
|
|
67
68
|
}
|
|
68
69
|
// If caller didn't supply userEmail, try to decrypt it from the already-fetched user doc.
|
|
69
70
|
const resolvedEmail = userEmail ??
|
|
@@ -181,8 +181,8 @@ class ChatRepository extends BaseRepository {
|
|
|
181
181
|
try {
|
|
182
182
|
await getAdminRealtimeDb().ref(`/chat/${chatId}`).remove();
|
|
183
183
|
}
|
|
184
|
-
catch {
|
|
185
|
-
|
|
184
|
+
catch (_err) {
|
|
185
|
+
void normalizeError(_err); // RTDB cleanup is best-effort — Firestore doc already deleted
|
|
186
186
|
}
|
|
187
187
|
return "deleted";
|
|
188
188
|
}
|
|
@@ -210,8 +210,8 @@ class ChatRepository extends BaseRepository {
|
|
|
210
210
|
try {
|
|
211
211
|
await getAdminRealtimeDb().ref(`/chat/${chatId}`).remove();
|
|
212
212
|
}
|
|
213
|
-
catch {
|
|
214
|
-
//
|
|
213
|
+
catch (_err) {
|
|
214
|
+
void normalizeError(_err); // RTDB cleanup is best-effort — adminDeleted flag already revokes access
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
217
|
catch (error) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { normalizeError } from "../../../errors/normalize";
|
|
2
|
+
import { serverLogger } from "../../../monitoring/server-logger";
|
|
2
3
|
/**
|
|
3
4
|
* Site Settings Repository
|
|
4
5
|
*
|
|
@@ -131,8 +132,9 @@ export class SiteSettingsRepository extends BaseRepository {
|
|
|
131
132
|
try {
|
|
132
133
|
result[key] = decryptSecret(value);
|
|
133
134
|
}
|
|
134
|
-
catch {
|
|
135
|
-
|
|
135
|
+
catch (_err) {
|
|
136
|
+
void normalizeError(_err); // Auth-tag mismatch or key rotation — treat as missing credential
|
|
137
|
+
result[key] = "";
|
|
136
138
|
}
|
|
137
139
|
}
|
|
138
140
|
}
|
|
@@ -210,8 +212,10 @@ export class SiteSettingsRepository extends BaseRepository {
|
|
|
210
212
|
.get();
|
|
211
213
|
return doc.exists;
|
|
212
214
|
}
|
|
213
|
-
catch {
|
|
214
|
-
|
|
215
|
+
catch (err) {
|
|
216
|
+
void normalizeError(err);
|
|
217
|
+
serverLogger.error("site-settings-repo: exists() Firestore read failed — rethrowing to avoid masking missing settings", { error: err instanceof Error ? err.message : String(err) });
|
|
218
|
+
throw err;
|
|
215
219
|
}
|
|
216
220
|
}
|
|
217
221
|
/**
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { sieveFilter, sieveAnd, SIEVE_OP } from "@mohasinac/appkit";
|
|
2
2
|
import { createCronJob } from "../registry";
|
|
3
|
+
import { normalizeError } from "../../../errors/normalize";
|
|
4
|
+
import { serverLogger } from "../../../monitoring/server-logger";
|
|
3
5
|
export function createAuctionExpiryJob(auctionRepo) {
|
|
4
6
|
return createCronJob({
|
|
5
7
|
name: "auctions_expire",
|
|
@@ -26,7 +28,9 @@ export function createAuctionExpiryJob(auctionRepo) {
|
|
|
26
28
|
});
|
|
27
29
|
processed++;
|
|
28
30
|
}
|
|
29
|
-
catch {
|
|
31
|
+
catch (err) {
|
|
32
|
+
void normalizeError(err);
|
|
33
|
+
serverLogger.warn("auction-expiry: per-auction close failed", { auctionId: auction.id, error: err instanceof Error ? err.message : String(err) });
|
|
30
34
|
errors++;
|
|
31
35
|
}
|
|
32
36
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { sieveFilter, sieveAnd, SIEVE_OP } from "@mohasinac/appkit";
|
|
2
2
|
import { createCronJob } from "../registry";
|
|
3
|
+
import { normalizeError } from "../../../errors/normalize";
|
|
4
|
+
import { serverLogger } from "../../../monitoring/server-logger";
|
|
3
5
|
export function createPreOrderReminderJob(preOrderRepo) {
|
|
4
6
|
const sevenDaysFromNow = () => {
|
|
5
7
|
const d = new Date();
|
|
@@ -28,7 +30,9 @@ export function createPreOrderReminderJob(preOrderRepo) {
|
|
|
28
30
|
});
|
|
29
31
|
processed++;
|
|
30
32
|
}
|
|
31
|
-
catch {
|
|
33
|
+
catch (err) {
|
|
34
|
+
void normalizeError(err);
|
|
35
|
+
serverLogger.warn("preorder-reminder: per-order update failed", { orderId: order.id, error: err instanceof Error ? err.message : String(err) });
|
|
32
36
|
errors++;
|
|
33
37
|
}
|
|
34
38
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { normalizeError } from "../../../errors/normalize";
|
|
2
|
+
import { serverLogger } from "../../../monitoring/server-logger";
|
|
2
3
|
/**
|
|
3
4
|
* Coupons Repository
|
|
4
5
|
*
|
|
@@ -270,8 +271,10 @@ export class CouponsRepository extends BaseRepository {
|
|
|
270
271
|
const data = doc.data();
|
|
271
272
|
return data.usageCount ?? 1;
|
|
272
273
|
}
|
|
273
|
-
catch {
|
|
274
|
-
|
|
274
|
+
catch (err) {
|
|
275
|
+
void normalizeError(err);
|
|
276
|
+
serverLogger.error("coupons-repo: getUserCouponUsageCount failed — rethrowing to prevent coupon limit bypass", { userId, couponId, error: err instanceof Error ? err.message : String(err) });
|
|
277
|
+
throw err;
|
|
275
278
|
}
|
|
276
279
|
}
|
|
277
280
|
/**
|
package/dist/utils/media-url.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { MEDIA_ENDPOINTS } from "../constants/api-endpoints";
|
|
2
|
+
import { normalizeError } from "../errors/normalize";
|
|
2
3
|
/**
|
|
3
4
|
* Single source of truth for the Firebase Storage host literal. Every other
|
|
4
5
|
* appkit + consumer module that needs to detect or allowlist this host
|
|
@@ -31,7 +32,8 @@ export function resolveMediaUrl(url) {
|
|
|
31
32
|
}
|
|
32
33
|
return MEDIA_ENDPOINTS.EXT_URL(url);
|
|
33
34
|
}
|
|
34
|
-
catch {
|
|
35
|
+
catch (_err) {
|
|
36
|
+
void normalizeError(_err); // URL constructor throws for non-URL strings (e.g., relative paths) — return original
|
|
35
37
|
return url;
|
|
36
38
|
}
|
|
37
39
|
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* URL Validation Utilities
|
|
3
3
|
*/
|
|
4
|
+
import { normalizeError } from "../errors/normalize";
|
|
4
5
|
export function isValidUrl(url) {
|
|
5
6
|
try {
|
|
6
7
|
new URL(url);
|
|
7
8
|
return true;
|
|
8
9
|
}
|
|
9
|
-
catch {
|
|
10
|
+
catch (_err) {
|
|
11
|
+
void normalizeError(_err); // URL constructor throws TypeError for invalid URL syntax
|
|
10
12
|
return false;
|
|
11
13
|
}
|
|
12
14
|
}
|
|
@@ -17,7 +19,8 @@ export function isValidUrlWithProtocol(url, protocols = ["http", "https"]) {
|
|
|
17
19
|
const urlObj = new URL(url);
|
|
18
20
|
return protocols.includes(urlObj.protocol.replace(":", ""));
|
|
19
21
|
}
|
|
20
|
-
catch {
|
|
22
|
+
catch (_err) {
|
|
23
|
+
void normalizeError(_err); // URL constructor throws TypeError for invalid URL syntax
|
|
21
24
|
return false;
|
|
22
25
|
}
|
|
23
26
|
}
|
|
@@ -30,7 +33,8 @@ export function isExternalUrl(url, currentDomain) {
|
|
|
30
33
|
(typeof window !== "undefined" ? window.location.hostname : "");
|
|
31
34
|
return urlObj.hostname !== currentHost;
|
|
32
35
|
}
|
|
33
|
-
catch {
|
|
36
|
+
catch (_err) {
|
|
37
|
+
void normalizeError(_err); // URL constructor throws TypeError for invalid URL syntax
|
|
34
38
|
return false;
|
|
35
39
|
}
|
|
36
40
|
}
|