@mohasinac/appkit 4.1.0 → 4.1.3
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/maintenance/index.d.ts +2 -0
- package/dist/_internal/client/features/maintenance/index.js +1 -0
- package/dist/_internal/client/features/maintenance/views/CloudLogsListView.d.ts +9 -0
- package/dist/_internal/client/features/maintenance/views/CloudLogsListView.js +55 -0
- package/dist/_internal/server/features/auctions/index.d.ts +1 -1
- package/dist/_internal/server/features/auctions/index.js +1 -1
- package/dist/_internal/server/features/auctions/service.js +2 -2
- package/dist/_internal/server/features/maintenance/cloud-logs-data.d.ts +50 -0
- package/dist/_internal/server/features/maintenance/cloud-logs-data.js +152 -0
- package/dist/_internal/server/jobs/core/onOrderCreate.d.ts +4 -12
- package/dist/_internal/server/jobs/core/onOrderCreate.js +3 -3
- package/dist/_internal/server/jobs/core/onProductWrite.js +14 -2
- package/dist/_internal/shared/features/auctions/config.d.ts +1 -1
- package/dist/_internal/shared/features/auctions/config.js +1 -1
- package/dist/_internal/shared/features/auctions/schema.js +1 -1
- package/dist/_internal/shared/features/cart/schema.js +2 -2
- package/dist/_internal/shared/features/events/schema.js +1 -1
- package/dist/_internal/shared/features/orders/schema.js +1 -1
- package/dist/_internal/shared/features/products/schema.js +3 -3
- package/dist/_internal/shared/features/promotions/schema.js +3 -3
- package/dist/_internal/shared/fees/calculator.d.ts +6 -7
- package/dist/client.d.ts +4 -4
- package/dist/client.js +4 -2
- package/dist/constants/api-endpoints.d.ts +9 -6
- package/dist/constants/api-endpoints.js +3 -2
- package/dist/contracts/client-payment-gateway.d.ts +1 -2
- package/dist/features/about/components/AboutView.d.ts +6 -16
- package/dist/features/about/components/AboutView.js +3 -3
- package/dist/features/about/index.d.ts +2 -1
- package/dist/features/about/schemas/firestore.d.ts +47 -0
- package/dist/features/about/schemas/firestore.js +6 -0
- package/dist/features/about/schemas/index.d.ts +210 -0
- package/dist/features/about/schemas/index.js +45 -0
- package/dist/features/account/hooks/useProfile.js +3 -0
- package/dist/features/admin/components/AdminCarouselGroupEditorView.d.ts +6 -0
- package/dist/features/admin/components/AdminCarouselGroupEditorView.js +50 -0
- package/dist/features/admin/components/AdminCartsView.js +16 -3
- package/dist/features/admin/components/AdminCouponEditorView.js +2 -2
- package/dist/features/admin/components/AdminCouponsView.js +14 -4
- package/dist/features/admin/components/AdminEmployeeEditorView.js +1 -42
- package/dist/features/admin/components/AdminMediaView.js +1 -1
- package/dist/features/admin/components/AdminNotificationsView.js +31 -19
- package/dist/features/admin/components/AdminOrdersView.js +7 -0
- package/dist/features/admin/components/AdminPayoutsView.js +18 -3
- package/dist/features/admin/components/AdminProductsView.js +17 -2
- package/dist/features/admin/components/AdminReviewsView.js +16 -2
- package/dist/features/admin/components/AdminScammersView.js +7 -0
- package/dist/features/admin/components/AdminSectionsView.js +4 -0
- package/dist/features/admin/components/AdminSiteConfigGuideView.js +1 -1
- package/dist/features/admin/components/AdminSiteSettingsView.js +44 -2
- package/dist/features/admin/components/AdminStoreEditorView.d.ts +2 -1
- package/dist/features/admin/components/AdminStoreEditorView.js +4 -4
- package/dist/features/admin/components/AdminStoresView.js +1 -1
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +23 -5
- package/dist/features/admin/components/AdminSupportTicketsView.js +20 -2
- package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +4 -1
- package/dist/features/admin/components/AdminTesterChecklistView.js +8 -0
- package/dist/features/admin/components/index.d.ts +2 -0
- package/dist/features/admin/components/index.js +1 -0
- package/dist/features/admin/constants/filter-tabs.d.ts +55 -41
- package/dist/features/admin/constants/filter-tabs.js +55 -27
- package/dist/features/admin/schemas/firestore.d.ts +5 -0
- package/dist/features/auctions/actions/bid-actions.js +1 -1
- package/dist/features/auctions/components/AuctionDetailPageView.js +2 -2
- package/dist/features/auctions/components/AuctionsListView.js +8 -1
- package/dist/features/auth/components/LoginForm.js +2 -2
- package/dist/features/auth/components/RegisterForm.js +2 -2
- package/dist/features/auth/permissions/constants.d.ts +16 -0
- package/dist/features/auth/permissions/constants.js +53 -0
- package/dist/features/auth/schemas/firestore.js +1 -0
- package/dist/features/blog/components/BlogFilters.js +1 -1
- package/dist/features/cart/schemas/firestore.d.ts +1 -1
- package/dist/features/categories/schemas/firestore.d.ts +1 -1
- package/dist/features/consultation/components/ConsultationForm.js +1 -1
- package/dist/features/events/components/EventFilters.js +2 -0
- package/dist/features/homepage/components/WelcomeSection.js +2 -2
- package/dist/features/layout/TitleBarLayout.d.ts +2 -2
- package/dist/features/layout/TitleBarLayout.js +4 -4
- package/dist/features/media/AvatarUpload.js +7 -3
- package/dist/features/media/MediaVideo.js +1 -1
- package/dist/features/media/finalize.d.ts +9 -13
- package/dist/features/media/finalize.js +23 -74
- package/dist/features/media/server.d.ts +1 -1
- package/dist/features/media/server.js +1 -1
- package/dist/features/orders/hooks/useOrders.js +16 -4
- package/dist/features/orders/schemas/firestore.d.ts +5 -5
- package/dist/features/payments/schemas/firestore.d.ts +2 -2
- package/dist/features/pre-orders/components/PreOrdersListView.js +7 -0
- package/dist/features/products/components/ArtStickersListView.js +5 -0
- package/dist/features/products/components/ProductDetailPageView.d.ts +7 -1
- package/dist/features/products/components/ProductForm.js +14 -1
- package/dist/features/products/components/ProductsIndexPageView.js +7 -0
- package/dist/features/products/constants/action-defs.d.ts +1 -0
- package/dist/features/products/constants/action-defs.js +1 -0
- package/dist/features/products/schemas/firestore.d.ts +1 -1
- package/dist/features/products/schemas/product-templates.d.ts +1 -1
- package/dist/features/products/types/index.d.ts +4 -0
- package/dist/features/scams/schemas/index.js +2 -2
- package/dist/features/search/components/Search.js +3 -3
- package/dist/features/seller/components/SellerAuctionsView.js +27 -2
- package/dist/features/seller/components/SellerOrdersView.js +1 -1
- package/dist/features/seller/components/SellerPayoutsView.js +24 -10
- package/dist/features/seller/components/SellerPreOrdersView.js +12 -4
- package/dist/features/seller/components/SellerPrizeDrawsView.js +23 -5
- package/dist/features/seller/components/SellerProductShell.d.ts +2 -0
- package/dist/features/seller/components/SellerProductShell.js +1 -1
- package/dist/features/seller/components/SellerProductsView.js +8 -6
- package/dist/features/seller/components/SellerReviewsView.js +27 -6
- package/dist/features/seller/components/index.d.ts +0 -2
- package/dist/features/seller/components/index.js +0 -1
- package/dist/features/stores/components/StoreListingsGuideView.js +2 -1
- package/dist/features/stores/components/StoreProductsView.js +1 -1
- package/dist/features/stores/schemas/firestore.d.ts +11 -0
- package/dist/features/stores/schemas/firestore.js +5 -0
- package/dist/features/stores/schemas/index.d.ts +2 -2
- package/dist/features/tester/actions/checklist-item-actions.d.ts +6 -0
- package/dist/features/tester/actions/checklist-item-actions.js +2 -0
- package/dist/features/tester/components/AdminTesterFeedbackIssuesView.js +13 -2
- package/dist/features/tester/components/AdminTesterFeedbackListView.js +2 -1
- package/dist/features/tester/components/AdminTesterFeedbackReportView.js +9 -5
- package/dist/features/tester/components/TesterHubView.js +34 -21
- package/dist/features/tester/repository/tester-checklist-item.repository.js +1 -0
- package/dist/features/tester/repository/tester-checklist-response.repository.d.ts +18 -4
- package/dist/features/tester/repository/tester-checklist-response.repository.js +43 -8
- package/dist/features/tester/schemas/firestore.d.ts +8 -3
- package/dist/features/tester/schemas/firestore.js +6 -0
- package/dist/features/tester/seed-data/bids-tester-seed-data.d.ts +2 -0
- package/dist/features/tester/seed-data/bids-tester-seed-data.js +37 -0
- package/dist/features/tester/seed-data/coupons-tester-seed-data.d.ts +2 -0
- package/dist/features/tester/seed-data/coupons-tester-seed-data.js +76 -0
- package/dist/features/tester/seed-data/events-tester-seed-data.js +50 -2
- package/dist/features/tester/seed-data/index.d.ts +3 -0
- package/dist/features/tester/seed-data/index.js +3 -0
- package/dist/features/tester/seed-data/orders-tester-seed-data.d.ts +2 -0
- package/dist/features/tester/seed-data/orders-tester-seed-data.js +265 -0
- package/dist/features/tester/seed-data/products-tester-seed-data.js +213 -8
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +294 -12
- package/dist/features/tester/utils/phases.d.ts +31 -0
- package/dist/features/tester/utils/phases.js +46 -0
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +1 -1
- package/dist/features/whatsapp-bot/types/index.d.ts +1 -1
- package/dist/features/wishlist/types/index.d.ts +3 -0
- package/dist/index.d.ts +11 -4
- package/dist/index.js +15 -7
- package/dist/next/api/routeHandler.js +6 -10
- package/dist/next/components/NotFoundView.js +2 -1
- package/dist/next/routing/route-map.d.ts +4 -12
- package/dist/next/routing/route-map.js +2 -4
- package/dist/providers/db-firebase/admin.d.ts +1 -0
- package/dist/providers/db-firebase/admin.js +1 -1
- package/dist/schemas/registry.d.ts +2 -2
- package/dist/seed/addresses-seed-data.js +18 -18
- package/dist/seed/bids-seed-data.js +4 -4
- package/dist/seed/blog-posts-seed-data.js +82 -82
- package/dist/seed/carousel-slides-seed-data.js +14 -10
- package/dist/seed/carousels-seed-data.js +3 -3
- package/dist/seed/cart-seed-data.js +92 -92
- package/dist/seed/claimed-coupons-seed-data.js +10 -10
- package/dist/seed/conversations-seed-data.js +75 -75
- package/dist/seed/coupon-usage-seed-data.js +12 -12
- package/dist/seed/coupons-seed-data.js +41 -41
- package/dist/seed/events-seed-data.js +105 -105
- package/dist/seed/grouped-listings-seed-data.d.ts +2 -137
- package/dist/seed/grouped-listings-seed-data.js +79 -143
- package/dist/seed/history-seed-data.js +38 -38
- package/dist/seed/homepage-sections-seed-data.js +9 -9
- package/dist/seed/index.d.ts +1 -1
- package/dist/seed/index.js +1 -1
- package/dist/seed/manifest.js +4 -4
- package/dist/seed/notifications-seed-data.js +56 -56
- package/dist/seed/offers-seed-data.js +91 -91
- package/dist/seed/orders-seed-data.js +125 -106
- package/dist/seed/payouts-seed-data.js +42 -42
- package/dist/seed/products-auctions-seed-data.js +10 -2
- package/dist/seed/products-classifieds-seed-data.js +48 -5
- package/dist/seed/products-digital-codes-seed-data.js +48 -5
- package/dist/seed/products-live-items-seed-data.js +6 -1
- package/dist/seed/products-prize-draws-seed-data.js +58 -5
- package/dist/seed/products-standard-seed-data.js +40 -8
- package/dist/seed/reviews-seed-data.js +42 -23
- package/dist/seed/scammers-seed-data.js +22 -22
- package/dist/seed/sessions-seed-data.js +7 -7
- package/dist/seed/shipments-seed-data.js +10 -10
- package/dist/seed/site-settings-seed-data.js +82 -0
- package/dist/seed/store-addresses-seed-data.js +2 -2
- package/dist/seed/store-extensions-seed-data.js +93 -93
- package/dist/seed/stores-seed-data.js +2 -0
- package/dist/seed/support-tickets-seed-data.js +47 -47
- package/dist/seed/users-seed-data.js +55 -89
- package/dist/seed/wishlists-seed-data.js +22 -22
- package/dist/server.d.ts +2 -1
- package/dist/server.js +5 -5
- package/dist/styles.css +1 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/PageLoader.js +8 -3
- package/dist/ui/components/Select.d.ts +8 -1
- package/dist/ui/components/Select.js +2 -2
- package/dist/ui/components/SiteMark.d.ts +23 -0
- package/dist/ui/components/SiteMark.js +76 -0
- package/dist/ui/index.d.ts +2 -0
- package/dist/ui/index.js +1 -0
- package/dist/validation/schemas.d.ts +0 -2
- package/dist/validation/schemas.js +0 -2
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +27 -19
|
@@ -5,3 +5,5 @@ export type { ServerErrorDetailViewProps } from "./views/ServerErrorDetailView";
|
|
|
5
5
|
export { MaintenanceDashboardView } from "./views/MaintenanceDashboardView";
|
|
6
6
|
export type { MaintenanceDashboardViewProps } from "./views/MaintenanceDashboardView";
|
|
7
7
|
export { AnalysisRunnerView } from "./views/AnalysisRunnerView";
|
|
8
|
+
export { CloudLogsListView } from "./views/CloudLogsListView";
|
|
9
|
+
export type { CloudLogsListViewProps } from "./views/CloudLogsListView";
|
|
@@ -2,3 +2,4 @@ export { ServerErrorsListView } from "./views/ServerErrorsListView";
|
|
|
2
2
|
export { ServerErrorDetailView } from "./views/ServerErrorDetailView";
|
|
3
3
|
export { MaintenanceDashboardView } from "./views/MaintenanceDashboardView";
|
|
4
4
|
export { AnalysisRunnerView } from "./views/AnalysisRunnerView";
|
|
5
|
+
export { CloudLogsListView } from "./views/CloudLogsListView";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { CloudLogEntry } from "../../../../server/features/maintenance/cloud-logs-data";
|
|
3
|
+
export interface CloudLogsListViewProps {
|
|
4
|
+
title: string;
|
|
5
|
+
subtitle?: string;
|
|
6
|
+
initialEntries: CloudLogEntry[];
|
|
7
|
+
initialNextPageToken: string | null;
|
|
8
|
+
}
|
|
9
|
+
export declare function CloudLogsListView({ title, subtitle, initialEntries, initialNextPageToken, }: CloudLogsListViewProps): React.JSX.Element;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Button, Div, Heading, Span, Table, Tbody, Td, Text, Th, Thead, Tr } from "@mohasinac/appkit";
|
|
5
|
+
import { ADMIN_ENDPOINTS } from "../../../../../constants/api-endpoints";
|
|
6
|
+
import { normalizeError } from "../../../../../errors/normalize";
|
|
7
|
+
const BORDER_STYLE = "1px solid var(--appkit-color-border)";
|
|
8
|
+
const COLUMNS = [
|
|
9
|
+
{ key: "timestampFmt", label: "When", width: "180px" },
|
|
10
|
+
{ key: "severity", label: "Severity", width: "100px" },
|
|
11
|
+
{ key: "resource", label: "Resource" },
|
|
12
|
+
{ key: "messagePreview", label: "Payload excerpt" },
|
|
13
|
+
];
|
|
14
|
+
function fmt(timestamp) {
|
|
15
|
+
const d = new Date(timestamp);
|
|
16
|
+
return Number.isNaN(d.getTime()) ? timestamp : d.toISOString().replace("T", " ").slice(0, 19);
|
|
17
|
+
}
|
|
18
|
+
export function CloudLogsListView({ title, subtitle, initialEntries, initialNextPageToken, }) {
|
|
19
|
+
const [entries, setEntries] = React.useState(initialEntries);
|
|
20
|
+
const [nextPageToken, setNextPageToken] = React.useState(initialNextPageToken);
|
|
21
|
+
const [loadingMore, setLoadingMore] = React.useState(false);
|
|
22
|
+
const [error, setError] = React.useState(null);
|
|
23
|
+
async function loadMore() {
|
|
24
|
+
if (!nextPageToken || loadingMore)
|
|
25
|
+
return;
|
|
26
|
+
setLoadingMore(true);
|
|
27
|
+
setError(null);
|
|
28
|
+
try {
|
|
29
|
+
const url = new URL(ADMIN_ENDPOINTS.MAINTENANCE_CLOUD_LOGS, window.location.origin);
|
|
30
|
+
url.searchParams.set("pageToken", nextPageToken);
|
|
31
|
+
const res = await fetch(url.toString());
|
|
32
|
+
const body = (await res.json());
|
|
33
|
+
if (!res.ok || !body.ok) {
|
|
34
|
+
setError(("error" in body && body.error) || `HTTP ${res.status}`);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
setEntries((prev) => [...prev, ...body.data.entries]);
|
|
38
|
+
setNextPageToken(body.data.nextPageToken);
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
void normalizeError(err);
|
|
42
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
setLoadingMore(false);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return (_jsxs(Div, { style: { padding: "1.5rem", maxWidth: "1400px", margin: "0 auto" }, children: [_jsx(Heading, { level: 1, style: { fontSize: "1.5rem", fontWeight: 600 }, children: title }), subtitle ? (_jsx(Text, { as: "p", style: { color: "var(--appkit-color-text-muted)", marginBottom: "1rem" }, children: subtitle })) : null, _jsxs(Span, { style: { fontSize: "0.85rem", color: "var(--appkit-color-text-muted)" }, children: [entries.length, " entries loaded"] }), error ? (_jsx(Text, { as: "p", style: { color: "var(--appkit-color-error)", marginTop: "0.5rem" }, children: error })) : null, _jsx(Div, { style: { overflowX: "auto", border: BORDER_STYLE, borderRadius: 6, marginTop: "0.75rem" }, children: _jsxs(Table, { style: { width: "100%", borderCollapse: "collapse", fontSize: "0.85rem" }, children: [_jsx(Thead, { style: { background: "var(--appkit-color-bg)" }, children: _jsx(Tr, { children: COLUMNS.map((c) => (_jsx(Th, { style: {
|
|
49
|
+
textAlign: "left",
|
|
50
|
+
padding: "0.5rem 0.75rem",
|
|
51
|
+
borderBottom: BORDER_STYLE,
|
|
52
|
+
width: c.width,
|
|
53
|
+
whiteSpace: "nowrap",
|
|
54
|
+
}, children: c.label }, c.key))) }) }), _jsx(Tbody, { children: entries.length === 0 ? (_jsx(Tr, { children: _jsx(Td, { colSpan: COLUMNS.length, style: { padding: "2rem", textAlign: "center", color: "var(--appkit-color-text-muted)" }, children: "No log entries in the selected window." }) })) : (entries.map((e) => (_jsxs(Tr, { style: { borderBottom: "1px solid var(--appkit-color-border-subtle)" }, children: [_jsx(Td, { style: { padding: "0.5rem 0.75rem", verticalAlign: "top", whiteSpace: "nowrap" }, children: fmt(e.timestamp) }), _jsx(Td, { style: { padding: "0.5rem 0.75rem", verticalAlign: "top" }, children: e.severity }), _jsx(Td, { style: { padding: "0.5rem 0.75rem", verticalAlign: "top" }, children: e.resourceType }), _jsx(Td, { style: { padding: "0.5rem 0.75rem", verticalAlign: "top", fontFamily: "monospace" }, children: e.message })] }, e.id)))) })] }) }), _jsx(Div, { style: { marginTop: "1rem", textAlign: "center" }, children: nextPageToken ? (_jsx(Button, { type: "button", onClick: loadMore, isLoading: loadingMore, children: "Load more" })) : entries.length > 0 ? (_jsx(Text, { style: { color: "var(--appkit-color-text-muted)", fontSize: "0.85rem" }, children: "No more entries." })) : null })] }));
|
|
55
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { getAuctionForDetail, getProductFeaturesForAuction } from "./data";
|
|
2
2
|
export { assertAuctionActive, assertBidAmount, assertNotAuctionOwner, computeMinBid, shouldAutoExtend } from "./service";
|
|
3
3
|
export { placeBidAction } from "./actions";
|
|
4
|
-
export { AUCTIONS_PAGE_SIZE, AUCTIONS_ACTIVE_LIMIT, AUCTION_DEFAULT_EXTENSION_MINUTES,
|
|
4
|
+
export { AUCTIONS_PAGE_SIZE, AUCTIONS_ACTIVE_LIMIT, AUCTION_DEFAULT_EXTENSION_MINUTES, AUCTION_MIN_BID_INCREMENT, AUCTION_SNIPING_WINDOW_SECONDS, } from "../../../shared/features/auctions/config";
|
|
5
5
|
export { renderAuctionOgImage, renderAuctionOg, type AuctionOgData } from "./og";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { getAuctionForDetail, getProductFeaturesForAuction } from "./data";
|
|
2
2
|
export { assertAuctionActive, assertBidAmount, assertNotAuctionOwner, computeMinBid, shouldAutoExtend } from "./service";
|
|
3
3
|
export { placeBidAction } from "./actions";
|
|
4
|
-
export { AUCTIONS_PAGE_SIZE, AUCTIONS_ACTIVE_LIMIT, AUCTION_DEFAULT_EXTENSION_MINUTES,
|
|
4
|
+
export { AUCTIONS_PAGE_SIZE, AUCTIONS_ACTIVE_LIMIT, AUCTION_DEFAULT_EXTENSION_MINUTES, AUCTION_MIN_BID_INCREMENT, AUCTION_SNIPING_WINDOW_SECONDS, } from "../../../shared/features/auctions/config";
|
|
5
5
|
export { renderAuctionOgImage, renderAuctionOg } from "./og";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { productRepository } from "../../../../repositories";
|
|
2
2
|
import { isAuctionListing } from "../../../../features/products/utils/listing-type";
|
|
3
3
|
import { AuctionNotFoundError, AuctionEndedError, BidTooLowError, BidOnOwnAuctionError, } from "../../../shared/features/auctions/errors";
|
|
4
|
-
import {
|
|
4
|
+
import { AUCTION_MIN_BID_INCREMENT, AUCTION_SNIPING_WINDOW_SECONDS, AUCTION_DEFAULT_EXTENSION_MINUTES, } from "../../../shared/features/auctions/config";
|
|
5
5
|
/** Assert an auction exists, is published, and is still active. Returns the product. */
|
|
6
6
|
export async function assertAuctionActive(auctionId) {
|
|
7
7
|
const product = await productRepository.findByIdOrSlug(auctionId).catch(() => null);
|
|
@@ -19,7 +19,7 @@ export async function assertAuctionActive(auctionId) {
|
|
|
19
19
|
/** Compute the minimum valid bid given the current state. */
|
|
20
20
|
export function computeMinBid(product) {
|
|
21
21
|
const current = product.currentBid ?? product.startingBid ?? 0;
|
|
22
|
-
const increment = product.minBidIncrement ??
|
|
22
|
+
const increment = product.minBidIncrement ?? AUCTION_MIN_BID_INCREMENT;
|
|
23
23
|
return current + increment;
|
|
24
24
|
}
|
|
25
25
|
/** Assert a bid amount is valid against the current auction state. */
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Cloud Logging integration for the `/admin/maintenance/cloud-logs`
|
|
3
|
+
* page. Reuses the same 3-tier credential resolution as
|
|
4
|
+
* `providers/db-firebase/admin.ts` (local `firebase-admin-key.json` → Vercel
|
|
5
|
+
* `FIREBASE_ADMIN_*` env vars → Application Default Credentials), so no new
|
|
6
|
+
* env vars are required.
|
|
7
|
+
*
|
|
8
|
+
* Bounded to ONE `Logging#getEntries()` call per invocation — never
|
|
9
|
+
* `getEntriesStream()` in an unbounded loop — to respect the Vercel Hobby
|
|
10
|
+
* 10s sync-function ceiling (CLAUDE.md Rule #6). Pagination is client-driven
|
|
11
|
+
* via `nextPageToken`, not exhausted server-side.
|
|
12
|
+
*
|
|
13
|
+
* `@google-cloud/logging` is a consumer-side (root `package.json`) dependency
|
|
14
|
+
* — it is never imported at module scope here. The `Logging` client is
|
|
15
|
+
* lazily `require()`d inside a function body via `(module as any).require`,
|
|
16
|
+
* exactly like `admin.ts` lazily loads `firebase-admin/*`, so Turbopack never
|
|
17
|
+
* sees a static import of a Node-only client reachable from a client bundle
|
|
18
|
+
* (CLAUDE.md Root Cause #6 / #24). A minimal local interface describes the
|
|
19
|
+
* only surface we call — this file never imports `@google-cloud/logging`'s
|
|
20
|
+
* own types, so it type-checks even though the package is deliberately not
|
|
21
|
+
* listed as an appkit dependency (it lives in the consumer's root
|
|
22
|
+
* `package.json` only, since this integration is Next.js-route-only).
|
|
23
|
+
*/
|
|
24
|
+
export interface CloudLogEntry {
|
|
25
|
+
id: string;
|
|
26
|
+
timestamp: string;
|
|
27
|
+
severity: string;
|
|
28
|
+
resourceType: string;
|
|
29
|
+
resourceLabels: Record<string, string>;
|
|
30
|
+
logName: string;
|
|
31
|
+
message: string;
|
|
32
|
+
}
|
|
33
|
+
export interface ListCloudLogEntriesOpts {
|
|
34
|
+
/** Full Cloud Logging filter string. Defaults to a 24h `resource.type` window (see below). */
|
|
35
|
+
filter?: string;
|
|
36
|
+
/** Capped at 100. Defaults to 50. */
|
|
37
|
+
pageSize?: number;
|
|
38
|
+
/** Opaque continuation token from a previous call's `nextPageToken`. */
|
|
39
|
+
pageToken?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface ListCloudLogEntriesResult {
|
|
42
|
+
entries: CloudLogEntry[];
|
|
43
|
+
nextPageToken: string | null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Bounded, single-page Cloud Logging read. One `getEntries()` call per
|
|
47
|
+
* invocation — the caller drives further pages via `opts.pageToken`
|
|
48
|
+
* (client-side "Load more"), never a server-side exhaust loop.
|
|
49
|
+
*/
|
|
50
|
+
export declare const listCloudLogEntries: (opts?: ListCloudLogEntriesOpts) => Promise<ListCloudLogEntriesResult>;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Cloud Logging integration for the `/admin/maintenance/cloud-logs`
|
|
3
|
+
* page. Reuses the same 3-tier credential resolution as
|
|
4
|
+
* `providers/db-firebase/admin.ts` (local `firebase-admin-key.json` → Vercel
|
|
5
|
+
* `FIREBASE_ADMIN_*` env vars → Application Default Credentials), so no new
|
|
6
|
+
* env vars are required.
|
|
7
|
+
*
|
|
8
|
+
* Bounded to ONE `Logging#getEntries()` call per invocation — never
|
|
9
|
+
* `getEntriesStream()` in an unbounded loop — to respect the Vercel Hobby
|
|
10
|
+
* 10s sync-function ceiling (CLAUDE.md Rule #6). Pagination is client-driven
|
|
11
|
+
* via `nextPageToken`, not exhausted server-side.
|
|
12
|
+
*
|
|
13
|
+
* `@google-cloud/logging` is a consumer-side (root `package.json`) dependency
|
|
14
|
+
* — it is never imported at module scope here. The `Logging` client is
|
|
15
|
+
* lazily `require()`d inside a function body via `(module as any).require`,
|
|
16
|
+
* exactly like `admin.ts` lazily loads `firebase-admin/*`, so Turbopack never
|
|
17
|
+
* sees a static import of a Node-only client reachable from a client bundle
|
|
18
|
+
* (CLAUDE.md Root Cause #6 / #24). A minimal local interface describes the
|
|
19
|
+
* only surface we call — this file never imports `@google-cloud/logging`'s
|
|
20
|
+
* own types, so it type-checks even though the package is deliberately not
|
|
21
|
+
* listed as an appkit dependency (it lives in the consumer's root
|
|
22
|
+
* `package.json` only, since this integration is Next.js-route-only).
|
|
23
|
+
*/
|
|
24
|
+
import { cache } from "react";
|
|
25
|
+
import { parsePrivateKey } from "../../../../providers/db-firebase/admin";
|
|
26
|
+
function loadLogging() {
|
|
27
|
+
return module.require("@google-cloud/logging");
|
|
28
|
+
}
|
|
29
|
+
function nodePath() { return require("path"); }
|
|
30
|
+
function nodeFs() { return require("fs"); }
|
|
31
|
+
// process.cwd() is Node.js-only; access via module.require so the Edge
|
|
32
|
+
// static analyser does not flag this file (mirrors admin.ts).
|
|
33
|
+
function nodeCwd() { return module.require("process").cwd(); }
|
|
34
|
+
// Plain module-scope singleton (not `declare global` + `globalThis`) — this
|
|
35
|
+
// module is only ever reachable through one resolution path per process, so
|
|
36
|
+
// a module-local cache is sufficient and avoids global-augmentation clashes
|
|
37
|
+
// when the same declaration is picked up from both compiled `.d.ts` output
|
|
38
|
+
// and live source under a `file:./appkit` consumer tsconfig include.
|
|
39
|
+
let cachedLoggingClient = null;
|
|
40
|
+
function getCached() {
|
|
41
|
+
return cachedLoggingClient;
|
|
42
|
+
}
|
|
43
|
+
function setCached(client) {
|
|
44
|
+
cachedLoggingClient = client;
|
|
45
|
+
}
|
|
46
|
+
function getLoggingClient() {
|
|
47
|
+
const cached = getCached();
|
|
48
|
+
if (cached)
|
|
49
|
+
return cached;
|
|
50
|
+
const { Logging } = loadLogging();
|
|
51
|
+
const keyPath = nodePath().join(nodeCwd(), "firebase-admin-key.json");
|
|
52
|
+
let client;
|
|
53
|
+
if (nodeFs().existsSync(keyPath)) {
|
|
54
|
+
// Local dev — the JSON key file also carries project_id, so the Logging
|
|
55
|
+
// client resolves the project automatically from `keyFilename`.
|
|
56
|
+
client = new Logging({ keyFilename: keyPath });
|
|
57
|
+
}
|
|
58
|
+
else if (process.env.FIREBASE_ADMIN_PROJECT_ID &&
|
|
59
|
+
process.env.FIREBASE_ADMIN_CLIENT_EMAIL &&
|
|
60
|
+
process.env.FIREBASE_ADMIN_PRIVATE_KEY) {
|
|
61
|
+
// Vercel — same three env vars the Firebase Admin SDK uses.
|
|
62
|
+
client = new Logging({
|
|
63
|
+
projectId: process.env.FIREBASE_ADMIN_PROJECT_ID.trim(),
|
|
64
|
+
credentials: {
|
|
65
|
+
client_email: process.env.FIREBASE_ADMIN_CLIENT_EMAIL.trim(),
|
|
66
|
+
private_key: parsePrivateKey(process.env.FIREBASE_ADMIN_PRIVATE_KEY),
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
else if (
|
|
71
|
+
// Application Default Credentials — Firebase Functions / Cloud Run / GCE.
|
|
72
|
+
process.env.FUNCTION_TARGET ||
|
|
73
|
+
process.env.K_SERVICE ||
|
|
74
|
+
process.env.FIREBASE_CONFIG ||
|
|
75
|
+
process.env.GOOGLE_APPLICATION_CREDENTIALS) {
|
|
76
|
+
const firebaseConfig = process.env.FIREBASE_CONFIG
|
|
77
|
+
? JSON.parse(process.env.FIREBASE_CONFIG)
|
|
78
|
+
: {};
|
|
79
|
+
const projectId = firebaseConfig.projectId ?? process.env.GCLOUD_PROJECT;
|
|
80
|
+
client = new Logging(projectId ? { projectId } : {});
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
throw new Error("@mohasinac/appkit: Cloud Logging credentials not found.\n" +
|
|
84
|
+
"Add firebase-admin-key.json to project root, or set " +
|
|
85
|
+
"FIREBASE_ADMIN_PROJECT_ID, FIREBASE_ADMIN_CLIENT_EMAIL, " +
|
|
86
|
+
"FIREBASE_ADMIN_PRIVATE_KEY environment variables.");
|
|
87
|
+
}
|
|
88
|
+
setCached(client);
|
|
89
|
+
return client;
|
|
90
|
+
}
|
|
91
|
+
const DEFAULT_WINDOW_HOURS = 24;
|
|
92
|
+
const MAX_PAGE_SIZE = 100;
|
|
93
|
+
const DEFAULT_PAGE_SIZE = 50;
|
|
94
|
+
/**
|
|
95
|
+
* This project's Firebase Functions are all 2nd-gen
|
|
96
|
+
* (`firebase-functions/v2/*` — see
|
|
97
|
+
* `_internal/server/functions/bind-all.ts` + `jobs/runtime/adapters/firebase.ts`,
|
|
98
|
+
* which import exclusively from `firebase-functions/v2/{scheduler,firestore,https}`).
|
|
99
|
+
* 2nd-gen Functions run on Cloud Run under the hood, so their log entries
|
|
100
|
+
* carry `resource.type="cloud_run_revision"` — NOT the 1st-gen
|
|
101
|
+
* `"cloud_function"` resource type.
|
|
102
|
+
*/
|
|
103
|
+
const DEFAULT_RESOURCE_TYPE = "cloud_run_revision";
|
|
104
|
+
function buildDefaultFilter() {
|
|
105
|
+
const since = new Date(Date.now() - DEFAULT_WINDOW_HOURS * 3600000).toISOString();
|
|
106
|
+
return `resource.type="${DEFAULT_RESOURCE_TYPE}" AND timestamp>="${since}"`;
|
|
107
|
+
}
|
|
108
|
+
function excerpt(value, max = 300) {
|
|
109
|
+
if (value === null || value === undefined || value === "")
|
|
110
|
+
return "";
|
|
111
|
+
const text = typeof value === "string" ? value : JSON.stringify(value);
|
|
112
|
+
return text.length > max ? text.slice(0, max) + "…" : text;
|
|
113
|
+
}
|
|
114
|
+
function toCloudLogEntry(raw, index) {
|
|
115
|
+
const metadata = raw.metadata ?? {};
|
|
116
|
+
const tsRaw = metadata.timestamp;
|
|
117
|
+
const timestamp = tsRaw instanceof Date
|
|
118
|
+
? tsRaw.toISOString()
|
|
119
|
+
: typeof tsRaw === "string"
|
|
120
|
+
? tsRaw
|
|
121
|
+
: new Date().toISOString();
|
|
122
|
+
const resource = metadata.resource ?? {};
|
|
123
|
+
return {
|
|
124
|
+
id: metadata.insertId ?? `${timestamp}-${index}`,
|
|
125
|
+
timestamp,
|
|
126
|
+
severity: String(metadata.severity ?? "DEFAULT"),
|
|
127
|
+
resourceType: resource.type ?? "unknown",
|
|
128
|
+
resourceLabels: resource.labels ?? {},
|
|
129
|
+
logName: metadata.logName ?? "",
|
|
130
|
+
message: excerpt(raw.data),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Bounded, single-page Cloud Logging read. One `getEntries()` call per
|
|
135
|
+
* invocation — the caller drives further pages via `opts.pageToken`
|
|
136
|
+
* (client-side "Load more"), never a server-side exhaust loop.
|
|
137
|
+
*/
|
|
138
|
+
export const listCloudLogEntries = cache(async (opts = {}) => {
|
|
139
|
+
const pageSize = Math.min(Math.max(opts.pageSize ?? DEFAULT_PAGE_SIZE, 1), MAX_PAGE_SIZE);
|
|
140
|
+
const filter = opts.filter?.trim() ? opts.filter.trim() : buildDefaultFilter();
|
|
141
|
+
const logging = getLoggingClient();
|
|
142
|
+
const [entries, , apiResponse] = await logging.getEntries({
|
|
143
|
+
filter,
|
|
144
|
+
pageSize,
|
|
145
|
+
orderBy: "timestamp desc",
|
|
146
|
+
...(opts.pageToken ? { pageToken: opts.pageToken } : {}),
|
|
147
|
+
});
|
|
148
|
+
return {
|
|
149
|
+
entries: entries.map((e, i) => toCloudLogEntry(e, i)),
|
|
150
|
+
nextPageToken: apiResponse?.nextPageToken || null,
|
|
151
|
+
};
|
|
152
|
+
});
|
|
@@ -1,18 +1,10 @@
|
|
|
1
1
|
import type { JobContext } from "../runtime/types";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
export interface NewOrder {
|
|
7
|
-
buyerDisplayName?: string;
|
|
8
|
-
buyerId?: string;
|
|
9
|
-
items?: OrderItem[];
|
|
10
|
-
totalAmount?: number;
|
|
11
|
-
storeId?: string;
|
|
12
|
-
}
|
|
2
|
+
import type { OrderDocument, OrderDocumentItem } from "../../../../features/orders/schemas/firestore";
|
|
3
|
+
export type NewOrder = Pick<OrderDocument, "userName" | "userId" | "totalPrice" | "storeId"> & {
|
|
4
|
+
items?: Pick<OrderDocumentItem, "productTitle">[];
|
|
5
|
+
};
|
|
13
6
|
export interface HandleOrderCreateInput {
|
|
14
7
|
orderId: string;
|
|
15
8
|
order: NewOrder;
|
|
16
9
|
}
|
|
17
10
|
export declare function handleOrderCreate(input: HandleOrderCreateInput, ctx: JobContext): Promise<void>;
|
|
18
|
-
export {};
|
|
@@ -54,14 +54,14 @@ export async function handleOrderCreate(input, ctx) {
|
|
|
54
54
|
}
|
|
55
55
|
const items = order.items ?? [];
|
|
56
56
|
const firstItem = items[0];
|
|
57
|
-
const firstItemName = firstItem?.
|
|
57
|
+
const firstItemName = firstItem?.productTitle ?? "an item";
|
|
58
58
|
const additionalItemCount = Math.max(0, items.length - 1);
|
|
59
|
-
const buyerName = order.
|
|
59
|
+
const buyerName = order.userName ?? "A customer";
|
|
60
60
|
const message = buildPurchaseAnnouncementMessage({
|
|
61
61
|
buyerName,
|
|
62
62
|
firstItemName,
|
|
63
63
|
additionalItemCount,
|
|
64
|
-
totalAmount: order.
|
|
64
|
+
totalAmount: order.totalPrice ?? 0,
|
|
65
65
|
orderId,
|
|
66
66
|
});
|
|
67
67
|
const adminNumbersRaw = ctx.env("WHATSAPP_ADMIN_NOTIFY_NUMBERS") ?? "";
|
|
@@ -10,6 +10,14 @@ const UNAVAILABLE_PRODUCT_STATUSES = new Set([
|
|
|
10
10
|
ProductStatusValues.ARCHIVED,
|
|
11
11
|
]);
|
|
12
12
|
void UNAVAILABLE_PRODUCT_STATUSES;
|
|
13
|
+
function getEffectiveCategory(doc) {
|
|
14
|
+
if (!doc)
|
|
15
|
+
return null;
|
|
16
|
+
const categorySlugs = doc.categorySlugs;
|
|
17
|
+
if (Array.isArray(categorySlugs) && categorySlugs.length > 0)
|
|
18
|
+
return categorySlugs[0];
|
|
19
|
+
return doc.category ?? null;
|
|
20
|
+
}
|
|
13
21
|
async function getParentIds(categoryId) {
|
|
14
22
|
if (!categoryId)
|
|
15
23
|
return [];
|
|
@@ -63,8 +71,12 @@ export async function handleProductWrite(input, ctx) {
|
|
|
63
71
|
const { productId, before, after } = input;
|
|
64
72
|
const beforeStatus = before?.status ?? null;
|
|
65
73
|
const afterStatus = after?.status ?? null;
|
|
66
|
-
|
|
67
|
-
|
|
74
|
+
// `category` is @deprecated in favor of `categorySlugs[]` — the repository's
|
|
75
|
+
// mapDoc() normalizes this on read, but a raw trigger snapshot bypasses that,
|
|
76
|
+
// so a product written via categorySlugs-only paths would otherwise silently
|
|
77
|
+
// no-op category metrics here. Prefer categorySlugs[0], fall back to legacy category.
|
|
78
|
+
const beforeCategory = getEffectiveCategory(before);
|
|
79
|
+
const afterCategory = getEffectiveCategory(after);
|
|
68
80
|
const beforeStoreId = (before?.storeId || before?.sellerId) ?? null;
|
|
69
81
|
const afterStoreId = (after?.storeId || after?.sellerId) ?? null;
|
|
70
82
|
const isAuction = after?.listingType === PRODUCT_FIELDS.LISTING_TYPE_VALUES.AUCTION;
|
|
@@ -2,5 +2,5 @@ export declare const AUCTIONS_PAGE_SIZE = 20;
|
|
|
2
2
|
export declare const AUCTIONS_ACTIVE_LIMIT = 50;
|
|
3
3
|
export declare const AUCTIONS_SITEMAP_LIMIT = 5000;
|
|
4
4
|
export declare const AUCTION_DEFAULT_EXTENSION_MINUTES = 5;
|
|
5
|
-
export declare const
|
|
5
|
+
export declare const AUCTION_MIN_BID_INCREMENT = 1;
|
|
6
6
|
export declare const AUCTION_SNIPING_WINDOW_SECONDS = 300;
|
|
@@ -2,5 +2,5 @@ export const AUCTIONS_PAGE_SIZE = 20;
|
|
|
2
2
|
export const AUCTIONS_ACTIVE_LIMIT = 50;
|
|
3
3
|
export const AUCTIONS_SITEMAP_LIMIT = 5000;
|
|
4
4
|
export const AUCTION_DEFAULT_EXTENSION_MINUTES = 5;
|
|
5
|
-
export const
|
|
5
|
+
export const AUCTION_MIN_BID_INCREMENT = 1; // ₹1
|
|
6
6
|
export const AUCTION_SNIPING_WINDOW_SECONDS = 300; // 5 minutes — triggers auto-extend
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
export const placeBidSchema = z.object({
|
|
3
3
|
auctionId: z.string().min(1),
|
|
4
|
-
amount: z.number().
|
|
4
|
+
amount: z.number().positive("Bid amount must be a positive number"),
|
|
5
5
|
});
|
|
6
6
|
export const cancelBidSchema = z.object({
|
|
7
7
|
bidId: z.string().min(1),
|
|
@@ -3,7 +3,7 @@ const cartItemBaseSchema = z.object({
|
|
|
3
3
|
productId: z.string().min(1),
|
|
4
4
|
productTitle: z.string(),
|
|
5
5
|
productImage: z.string().default(""),
|
|
6
|
-
price: z.number().
|
|
6
|
+
price: z.number().min(0),
|
|
7
7
|
currency: z.string().default("INR"),
|
|
8
8
|
storeId: z.string(),
|
|
9
9
|
storeName: z.string().default(""),
|
|
@@ -21,7 +21,7 @@ const cartItemBaseSchema = z.object({
|
|
|
21
21
|
]),
|
|
22
22
|
isOffer: z.boolean().optional(),
|
|
23
23
|
offerId: z.string().optional(),
|
|
24
|
-
lockedPrice: z.number().
|
|
24
|
+
lockedPrice: z.number().optional(),
|
|
25
25
|
});
|
|
26
26
|
export const addToCartSchema = cartItemBaseSchema;
|
|
27
27
|
export const updateCartItemSchema = z.object({
|
|
@@ -12,7 +12,7 @@ export const eventInputSchema = z.object({
|
|
|
12
12
|
imageUrl: z.string().url().optional(),
|
|
13
13
|
location: z.string().max(300).optional(),
|
|
14
14
|
isOnline: z.boolean().default(false),
|
|
15
|
-
entryFee: z.number().
|
|
15
|
+
entryFee: z.number().min(0).default(0),
|
|
16
16
|
});
|
|
17
17
|
export const eventUpdateSchema = eventInputSchema.partial().omit({ slug: true });
|
|
18
18
|
export const registerForEventSchema = z.object({
|
|
@@ -14,7 +14,7 @@ export const createOrderSchema = z.object({
|
|
|
14
14
|
items: z.array(z.object({
|
|
15
15
|
productId: z.string().min(1),
|
|
16
16
|
quantity: z.number().int().min(1),
|
|
17
|
-
price: z.number().
|
|
17
|
+
price: z.number().min(0),
|
|
18
18
|
})).min(1, "Order must have at least one item"),
|
|
19
19
|
shippingAddress: addressSchema,
|
|
20
20
|
paymentMethod: z.enum(["razorpay", "cod", "upi"]),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
const priceSchema = z.number().
|
|
2
|
+
const priceSchema = z.number().min(0, "Price must be non-negative");
|
|
3
3
|
const conditionSchema = z.enum(["new", "like_new", "good", "fair", "poor", "used", "refurbished", "broken"]);
|
|
4
4
|
export const productInputSchema = z.object({
|
|
5
5
|
title: z.string().min(3, "Title must be at least 3 characters").max(200),
|
|
@@ -21,7 +21,7 @@ export const productInputSchema = z.object({
|
|
|
21
21
|
returnPolicy: z.string().max(1000).optional(),
|
|
22
22
|
shippingPaidBy: z.enum(["seller", "buyer"]).optional(),
|
|
23
23
|
insurance: z.boolean().optional(),
|
|
24
|
-
insuranceCost: z.number().
|
|
24
|
+
insuranceCost: z.number().min(0).optional(),
|
|
25
25
|
allowOffers: z.boolean().optional(),
|
|
26
26
|
minOfferPercent: z.number().min(0).max(100).optional(),
|
|
27
27
|
features: z.array(z.string()).max(50).optional(),
|
|
@@ -33,7 +33,7 @@ export const auctionInputSchema = productInputSchema.extend({
|
|
|
33
33
|
startingBid: priceSchema,
|
|
34
34
|
reservePrice: priceSchema.optional(),
|
|
35
35
|
buyNowPrice: priceSchema.optional(),
|
|
36
|
-
minBidIncrement: z.number().
|
|
36
|
+
minBidIncrement: z.number().min(1).optional(),
|
|
37
37
|
auctionEndDate: z.string().datetime({ offset: true }),
|
|
38
38
|
autoExtendable: z.boolean().default(false),
|
|
39
39
|
auctionExtensionMinutes: z.number().int().min(1).max(30).optional(),
|
|
@@ -2,7 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import { COUPON_CODE_PATTERN } from "./config";
|
|
3
3
|
export const applyCouponSchema = z.object({
|
|
4
4
|
code: z.string().regex(COUPON_CODE_PATTERN, "Invalid coupon code format").toUpperCase(),
|
|
5
|
-
cartTotal: z.number().
|
|
5
|
+
cartTotal: z.number().min(0),
|
|
6
6
|
productIds: z.array(z.string()).optional(),
|
|
7
7
|
categoryIds: z.array(z.string()).optional(),
|
|
8
8
|
isFirstTimeUser: z.boolean().default(false),
|
|
@@ -15,8 +15,8 @@ export const createCouponSchema = z.object({
|
|
|
15
15
|
sellerId: z.string().optional(),
|
|
16
16
|
discount: z.object({
|
|
17
17
|
value: z.number().min(0),
|
|
18
|
-
maxDiscount: z.number().
|
|
19
|
-
minPurchase: z.number().
|
|
18
|
+
maxDiscount: z.number().min(0).optional(),
|
|
19
|
+
minPurchase: z.number().min(0).default(0),
|
|
20
20
|
}),
|
|
21
21
|
usage: z.object({
|
|
22
22
|
totalLimit: z.number().int().min(1).optional(),
|
|
@@ -17,25 +17,24 @@
|
|
|
17
17
|
export interface FeeCommissionRates {
|
|
18
18
|
platformFeePercent: number;
|
|
19
19
|
gstPercent: number;
|
|
20
|
-
/** Rupee floor (not paise) — matches the existing `minimumTransactionFee` doc convention. */
|
|
21
|
-
minimumTransactionFee?: number;
|
|
20
|
+
/** Rupee floor (not paise) — matches the existing `minimumTransactionFee` doc convention. */ minimumTransactionFee?: number;
|
|
22
21
|
gatewayFeePercent?: number;
|
|
23
22
|
}
|
|
24
23
|
export interface CheckoutFees {
|
|
25
|
-
/** Platform commission in
|
|
24
|
+
/** Platform commission in decimal rupees. */
|
|
26
25
|
platformFee: number;
|
|
27
|
-
/** GST on the platform fee, in
|
|
26
|
+
/** GST on the platform fee, in decimal rupees. */
|
|
28
27
|
gstOnFee: number;
|
|
29
28
|
/** platformFee + gstOnFee, floored at minimumTransactionFee. */
|
|
30
29
|
totalFee: number;
|
|
31
30
|
}
|
|
32
31
|
export declare function computeCheckoutFees(subtotal: number, commissions: FeeCommissionRates): CheckoutFees;
|
|
33
32
|
export interface PayoutDeduction {
|
|
34
|
-
/** Platform commission in
|
|
33
|
+
/** Platform commission in decimal rupees. */
|
|
35
34
|
platformFee: number;
|
|
36
|
-
/** Payment gateway cost, absorbed by the platform from the seller's share, in
|
|
35
|
+
/** Payment gateway cost, absorbed by the platform from the seller's share, in decimal rupees. */
|
|
37
36
|
gatewayFee: number;
|
|
38
|
-
/** GST on the platform fee, in
|
|
37
|
+
/** GST on the platform fee, in decimal rupees. */
|
|
39
38
|
gstOnFee: number;
|
|
40
39
|
/** platformFee + gatewayFee + gstOnFee. */
|
|
41
40
|
totalDeduction: number;
|
package/dist/client.d.ts
CHANGED
|
@@ -17,8 +17,8 @@ export { useApiQuery } from "./client/api/useApiQuery";
|
|
|
17
17
|
export type { UseApiQueryOptions } from "./client/api/useApiQuery";
|
|
18
18
|
export { useFeatureFlags } from "./client/api/useFeatureFlags";
|
|
19
19
|
export type { FeatureFlagState } from "./client/api/useFeatureFlags";
|
|
20
|
-
export { ServerErrorsListView, ServerErrorDetailView, MaintenanceDashboardView, AnalysisRunnerView, } from "./_internal/client/features/maintenance";
|
|
21
|
-
export type { ServerErrorsListViewProps, ServerErrorDetailViewProps, MaintenanceDashboardViewProps, } from "./_internal/client/features/maintenance";
|
|
20
|
+
export { ServerErrorsListView, ServerErrorDetailView, MaintenanceDashboardView, AnalysisRunnerView, CloudLogsListView, } from "./_internal/client/features/maintenance";
|
|
21
|
+
export type { ServerErrorsListViewProps, ServerErrorDetailViewProps, MaintenanceDashboardViewProps, CloudLogsListViewProps, } from "./_internal/client/features/maintenance";
|
|
22
22
|
export { registerClientAuthProvider, getClientAuthProvider, type IClientAuthProvider, } from "./contracts/client-auth";
|
|
23
23
|
export { registerClientRealtimeProvider, getClientRealtimeProvider, type IClientRealtimeProvider, type RealtimeSnapshot, type Unsubscribe, } from "./contracts/client-realtime";
|
|
24
24
|
export { registerClientSessionAdapter, getClientSessionAdapter, type IClientSessionAdapter, type AdapterAuthUser, type AuthUnsubscribe, } from "./contracts/client-session";
|
|
@@ -109,6 +109,7 @@ export type { UseEntityDeleteOptions, UseEntityDeleteReturn } from "./react/hook
|
|
|
109
109
|
export { ROUTES, PUBLIC_ROUTES, PROTECTED_ROUTES, AUTH_ROUTES } from "./constants/index";
|
|
110
110
|
export { SORT_DIR, sortBy } from "./constants/sort";
|
|
111
111
|
export { SIEVE_OP, sieveFilter, sieveAnd, sieveMultiEq } from "./utils/sieve-builder";
|
|
112
|
+
export { formatCurrency } from "./utils/number.formatter";
|
|
112
113
|
export { Container, Grid, Row, Stack } from "./ui/components/Layout";
|
|
113
114
|
export { Div } from "./ui/components/Div";
|
|
114
115
|
export { DynamicBgDiv } from "./ui/components/DynamicBgDiv";
|
|
@@ -163,6 +164,7 @@ export type { AdminSidebarProps, AdminNavItem, AdminNavGroup } from "./features/
|
|
|
163
164
|
export { AdminDashboardView, AdminAnalyticsView, AdminPageViewsReportView, AdminPrizeDrawsView, AdminCarouselView, AdminSublistingCategoriesView, AdminFulfillmentView, DataTable, DataListingView, useAdminListingData, toRecordArray, toStringValue, toRelativeDate } from "./features/admin/index";
|
|
164
165
|
export type { AdminDashboardViewProps, AdminAnalyticsViewProps, AdminAnalyticsViewLabels, AdminPageViewsReportViewProps, AdminPrizeDrawsViewProps, AdminCarouselViewProps, AdminFulfillmentViewProps, AdminListingScaffoldRow, ListingViewConfig } from "./features/admin/index";
|
|
165
166
|
export type { BulkActionItem } from "./ui/components/BulkActionBar";
|
|
167
|
+
export { PERMISSION_GROUPS, PERMISSION_DOMAINS, getPermissionsForDomain, formatPermLabel } from "./features/auth/permissions/constants";
|
|
166
168
|
export { ADMIN_ENDPOINTS } from "./constants/index";
|
|
167
169
|
export { SELLER_ENDPOINTS } from "./constants/index";
|
|
168
170
|
export { TourProvider, useTour } from "./_internal/client/features/tour/TourProvider";
|
|
@@ -334,8 +336,6 @@ export { Toggle } from "./ui/components/Toggle";
|
|
|
334
336
|
export type { ToggleProps } from "./ui/components/Toggle";
|
|
335
337
|
export { SellerStoreCategoriesView } from "./features/seller/components/SellerStoreCategoriesView";
|
|
336
338
|
export type { SellerStoreCategoriesViewProps } from "./features/seller/components/SellerStoreCategoriesView";
|
|
337
|
-
export { SellerTemplatesView } from "./features/seller/components/SellerTemplatesView";
|
|
338
|
-
export type { SellerTemplatesViewProps } from "./features/seller/components/SellerTemplatesView";
|
|
339
339
|
export { SellerPayoutMethodsView } from "./features/seller/components/SellerPayoutMethodsView";
|
|
340
340
|
export type { SellerPayoutMethodsViewProps } from "./features/seller/components/SellerPayoutMethodsView";
|
|
341
341
|
export { SellerShippingConfigsView } from "./features/seller/components/SellerShippingConfigsView";
|
package/dist/client.js
CHANGED
|
@@ -19,7 +19,7 @@ export { useApiQuery } from "./client/api/useApiQuery";
|
|
|
19
19
|
export { useFeatureFlags } from "./client/api/useFeatureFlags";
|
|
20
20
|
// [CLIENT-ONLY] Maintenance UI — listing + detail + dashboard + analysis runner.
|
|
21
21
|
// Consumed by the /admin/maintenance/* page shims.
|
|
22
|
-
export { ServerErrorsListView, ServerErrorDetailView, MaintenanceDashboardView, AnalysisRunnerView, } from "./_internal/client/features/maintenance";
|
|
22
|
+
export { ServerErrorsListView, ServerErrorDetailView, MaintenanceDashboardView, AnalysisRunnerView, CloudLogsListView, } from "./_internal/client/features/maintenance";
|
|
23
23
|
// Provider registration — pure contract modules with zero server dependencies.
|
|
24
24
|
// Exported here so consumers can import registration functions from
|
|
25
25
|
// @mohasinac/appkit/client without pulling in firebase-admin or other server code.
|
|
@@ -170,6 +170,7 @@ export { useEntityDelete } from "./react/hooks/useEntityDelete";
|
|
|
170
170
|
export { ROUTES, PUBLIC_ROUTES, PROTECTED_ROUTES, AUTH_ROUTES } from "./constants/index";
|
|
171
171
|
export { SORT_DIR, sortBy } from "./constants/sort";
|
|
172
172
|
export { SIEVE_OP, sieveFilter, sieveAnd, sieveMultiEq } from "./utils/sieve-builder";
|
|
173
|
+
export { formatCurrency } from "./utils/number.formatter";
|
|
173
174
|
export { Container, Grid, Row, Stack } from "./ui/components/Layout";
|
|
174
175
|
export { Div } from "./ui/components/Div";
|
|
175
176
|
export { DynamicBgDiv } from "./ui/components/DynamicBgDiv";
|
|
@@ -202,6 +203,8 @@ export { ToastProvider, SkipToMain, NavigationLoader } from "./ui/index";
|
|
|
202
203
|
export { ZodSetup } from "./validation/ZodSetup";
|
|
203
204
|
export { AdminSidebar } from "./features/admin/components/AdminSidebar";
|
|
204
205
|
export { AdminDashboardView, AdminAnalyticsView, AdminPageViewsReportView, AdminPrizeDrawsView, AdminCarouselView, AdminSublistingCategoriesView, AdminFulfillmentView, DataTable, DataListingView, useAdminListingData, toRecordArray, toStringValue, toRelativeDate } from "./features/admin/index";
|
|
206
|
+
// S-ADMIN-7 — permission catalog data, shared by AdminEmployeeEditorView and the read-only /admin/permissions page.
|
|
207
|
+
export { PERMISSION_GROUPS, PERMISSION_DOMAINS, getPermissionsForDomain, formatPermLabel } from "./features/auth/permissions/constants";
|
|
205
208
|
export { ADMIN_ENDPOINTS } from "./constants/index";
|
|
206
209
|
export { SELLER_ENDPOINTS } from "./constants/index";
|
|
207
210
|
// P-16 — Tour system (driver.js-backed onboarding walkthrough).
|
|
@@ -327,7 +330,6 @@ export { PhysicalLocationModal } from "./features/seller/components/PhysicalLoca
|
|
|
327
330
|
export { Toggle } from "./ui/components/Toggle";
|
|
328
331
|
// [CLIENT] Wave 4 seller management views.
|
|
329
332
|
export { SellerStoreCategoriesView } from "./features/seller/components/SellerStoreCategoriesView";
|
|
330
|
-
export { SellerTemplatesView } from "./features/seller/components/SellerTemplatesView";
|
|
331
333
|
export { SellerPayoutMethodsView } from "./features/seller/components/SellerPayoutMethodsView";
|
|
332
334
|
export { SellerShippingConfigsView } from "./features/seller/components/SellerShippingConfigsView";
|
|
333
335
|
export { SellerGoogleReviewsView } from "./features/seller/components/SellerGoogleReviewsView";
|