@mohasinac/appkit 4.1.1 → 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.
Files changed (187) hide show
  1. package/dist/_internal/client/features/maintenance/index.d.ts +2 -0
  2. package/dist/_internal/client/features/maintenance/index.js +1 -0
  3. package/dist/_internal/client/features/maintenance/views/CloudLogsListView.d.ts +9 -0
  4. package/dist/_internal/client/features/maintenance/views/CloudLogsListView.js +55 -0
  5. package/dist/_internal/server/features/auctions/index.d.ts +1 -1
  6. package/dist/_internal/server/features/auctions/index.js +1 -1
  7. package/dist/_internal/server/features/auctions/service.js +2 -2
  8. package/dist/_internal/server/features/maintenance/cloud-logs-data.d.ts +50 -0
  9. package/dist/_internal/server/features/maintenance/cloud-logs-data.js +152 -0
  10. package/dist/_internal/server/jobs/core/onOrderCreate.d.ts +4 -12
  11. package/dist/_internal/server/jobs/core/onOrderCreate.js +3 -3
  12. package/dist/_internal/server/jobs/core/onProductWrite.js +14 -2
  13. package/dist/_internal/shared/features/auctions/config.d.ts +1 -1
  14. package/dist/_internal/shared/features/auctions/config.js +1 -1
  15. package/dist/_internal/shared/features/auctions/schema.js +1 -1
  16. package/dist/_internal/shared/features/cart/schema.js +2 -2
  17. package/dist/_internal/shared/features/events/schema.js +1 -1
  18. package/dist/_internal/shared/features/orders/schema.js +1 -1
  19. package/dist/_internal/shared/features/products/schema.js +3 -3
  20. package/dist/_internal/shared/features/promotions/schema.js +3 -3
  21. package/dist/_internal/shared/fees/calculator.d.ts +6 -7
  22. package/dist/client.d.ts +4 -4
  23. package/dist/client.js +4 -2
  24. package/dist/constants/api-endpoints.d.ts +9 -6
  25. package/dist/constants/api-endpoints.js +3 -2
  26. package/dist/contracts/client-payment-gateway.d.ts +1 -2
  27. package/dist/features/about/components/AboutView.d.ts +6 -16
  28. package/dist/features/about/components/AboutView.js +3 -3
  29. package/dist/features/about/index.d.ts +2 -1
  30. package/dist/features/about/schemas/firestore.d.ts +47 -0
  31. package/dist/features/about/schemas/firestore.js +6 -0
  32. package/dist/features/about/schemas/index.d.ts +210 -0
  33. package/dist/features/about/schemas/index.js +45 -0
  34. package/dist/features/account/hooks/useProfile.js +3 -0
  35. package/dist/features/admin/components/AdminCarouselGroupEditorView.d.ts +6 -0
  36. package/dist/features/admin/components/AdminCarouselGroupEditorView.js +50 -0
  37. package/dist/features/admin/components/AdminCartsView.js +16 -3
  38. package/dist/features/admin/components/AdminCouponEditorView.js +2 -2
  39. package/dist/features/admin/components/AdminCouponsView.js +14 -4
  40. package/dist/features/admin/components/AdminEmployeeEditorView.js +1 -42
  41. package/dist/features/admin/components/AdminMediaView.js +1 -1
  42. package/dist/features/admin/components/AdminNotificationsView.js +31 -19
  43. package/dist/features/admin/components/AdminOrdersView.js +7 -0
  44. package/dist/features/admin/components/AdminPayoutsView.js +18 -3
  45. package/dist/features/admin/components/AdminProductsView.js +17 -2
  46. package/dist/features/admin/components/AdminReviewsView.js +16 -2
  47. package/dist/features/admin/components/AdminScammersView.js +7 -0
  48. package/dist/features/admin/components/AdminSectionsView.js +4 -0
  49. package/dist/features/admin/components/AdminSiteConfigGuideView.js +1 -1
  50. package/dist/features/admin/components/AdminSiteSettingsView.js +44 -2
  51. package/dist/features/admin/components/AdminStoreEditorView.d.ts +2 -1
  52. package/dist/features/admin/components/AdminStoreEditorView.js +4 -4
  53. package/dist/features/admin/components/AdminStoresView.js +1 -1
  54. package/dist/features/admin/components/AdminSupportTicketDetailView.js +23 -5
  55. package/dist/features/admin/components/AdminSupportTicketsView.js +20 -2
  56. package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +4 -1
  57. package/dist/features/admin/components/AdminTesterChecklistView.js +8 -0
  58. package/dist/features/admin/components/index.d.ts +2 -0
  59. package/dist/features/admin/components/index.js +1 -0
  60. package/dist/features/admin/constants/filter-tabs.d.ts +55 -41
  61. package/dist/features/admin/constants/filter-tabs.js +55 -27
  62. package/dist/features/admin/schemas/firestore.d.ts +5 -0
  63. package/dist/features/auctions/actions/bid-actions.js +1 -1
  64. package/dist/features/auctions/components/AuctionDetailPageView.js +2 -2
  65. package/dist/features/auctions/components/AuctionsListView.js +8 -1
  66. package/dist/features/auth/components/LoginForm.js +2 -2
  67. package/dist/features/auth/components/RegisterForm.js +2 -2
  68. package/dist/features/auth/permissions/constants.d.ts +16 -0
  69. package/dist/features/auth/permissions/constants.js +53 -0
  70. package/dist/features/auth/schemas/firestore.js +1 -0
  71. package/dist/features/blog/components/BlogFilters.js +1 -1
  72. package/dist/features/cart/schemas/firestore.d.ts +1 -1
  73. package/dist/features/categories/schemas/firestore.d.ts +1 -1
  74. package/dist/features/consultation/components/ConsultationForm.js +1 -1
  75. package/dist/features/events/components/EventFilters.js +2 -0
  76. package/dist/features/homepage/components/WelcomeSection.js +2 -2
  77. package/dist/features/layout/TitleBarLayout.d.ts +2 -2
  78. package/dist/features/layout/TitleBarLayout.js +4 -4
  79. package/dist/features/media/AvatarUpload.js +7 -3
  80. package/dist/features/media/MediaVideo.js +1 -1
  81. package/dist/features/media/finalize.d.ts +9 -13
  82. package/dist/features/media/finalize.js +23 -74
  83. package/dist/features/media/server.d.ts +1 -1
  84. package/dist/features/media/server.js +1 -1
  85. package/dist/features/orders/hooks/useOrders.js +16 -4
  86. package/dist/features/orders/schemas/firestore.d.ts +5 -5
  87. package/dist/features/payments/schemas/firestore.d.ts +2 -2
  88. package/dist/features/pre-orders/components/PreOrdersListView.js +7 -0
  89. package/dist/features/products/components/ArtStickersListView.js +5 -0
  90. package/dist/features/products/components/ProductDetailPageView.d.ts +7 -1
  91. package/dist/features/products/components/ProductForm.js +14 -1
  92. package/dist/features/products/components/ProductsIndexPageView.js +7 -0
  93. package/dist/features/products/constants/action-defs.d.ts +1 -0
  94. package/dist/features/products/constants/action-defs.js +1 -0
  95. package/dist/features/products/schemas/firestore.d.ts +1 -1
  96. package/dist/features/products/schemas/product-templates.d.ts +1 -1
  97. package/dist/features/products/types/index.d.ts +4 -0
  98. package/dist/features/scams/schemas/index.js +2 -2
  99. package/dist/features/search/components/Search.js +3 -3
  100. package/dist/features/seller/components/SellerAuctionsView.js +27 -2
  101. package/dist/features/seller/components/SellerOrdersView.js +1 -1
  102. package/dist/features/seller/components/SellerPayoutsView.js +24 -10
  103. package/dist/features/seller/components/SellerPreOrdersView.js +12 -4
  104. package/dist/features/seller/components/SellerPrizeDrawsView.js +23 -5
  105. package/dist/features/seller/components/SellerProductShell.d.ts +2 -0
  106. package/dist/features/seller/components/SellerProductShell.js +1 -1
  107. package/dist/features/seller/components/SellerProductsView.js +8 -6
  108. package/dist/features/seller/components/SellerReviewsView.js +27 -6
  109. package/dist/features/seller/components/index.d.ts +0 -2
  110. package/dist/features/seller/components/index.js +0 -1
  111. package/dist/features/stores/components/StoreListingsGuideView.js +2 -1
  112. package/dist/features/stores/components/StoreProductsView.js +1 -1
  113. package/dist/features/stores/schemas/firestore.d.ts +11 -0
  114. package/dist/features/stores/schemas/firestore.js +5 -0
  115. package/dist/features/stores/schemas/index.d.ts +2 -2
  116. package/dist/features/tester/actions/checklist-item-actions.d.ts +6 -0
  117. package/dist/features/tester/actions/checklist-item-actions.js +2 -0
  118. package/dist/features/tester/components/AdminTesterFeedbackIssuesView.js +13 -2
  119. package/dist/features/tester/components/AdminTesterFeedbackListView.js +2 -1
  120. package/dist/features/tester/components/AdminTesterFeedbackReportView.js +9 -5
  121. package/dist/features/tester/components/TesterHubView.js +34 -21
  122. package/dist/features/tester/repository/tester-checklist-item.repository.js +1 -0
  123. package/dist/features/tester/repository/tester-checklist-response.repository.d.ts +18 -4
  124. package/dist/features/tester/repository/tester-checklist-response.repository.js +43 -8
  125. package/dist/features/tester/schemas/firestore.d.ts +8 -3
  126. package/dist/features/tester/schemas/firestore.js +6 -0
  127. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +21 -9
  128. package/dist/features/tester/utils/phases.d.ts +31 -0
  129. package/dist/features/tester/utils/phases.js +46 -0
  130. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +1 -1
  131. package/dist/features/whatsapp-bot/types/index.d.ts +1 -1
  132. package/dist/features/wishlist/types/index.d.ts +3 -0
  133. package/dist/index.d.ts +11 -4
  134. package/dist/index.js +15 -7
  135. package/dist/next/components/NotFoundView.js +2 -1
  136. package/dist/next/routing/route-map.d.ts +4 -12
  137. package/dist/next/routing/route-map.js +2 -4
  138. package/dist/providers/db-firebase/admin.d.ts +1 -0
  139. package/dist/providers/db-firebase/admin.js +1 -1
  140. package/dist/schemas/registry.d.ts +2 -2
  141. package/dist/seed/addresses-seed-data.js +18 -18
  142. package/dist/seed/bids-seed-data.js +4 -4
  143. package/dist/seed/blog-posts-seed-data.js +82 -82
  144. package/dist/seed/carousel-slides-seed-data.js +14 -10
  145. package/dist/seed/carousels-seed-data.js +3 -3
  146. package/dist/seed/cart-seed-data.js +92 -92
  147. package/dist/seed/claimed-coupons-seed-data.js +10 -10
  148. package/dist/seed/conversations-seed-data.js +75 -75
  149. package/dist/seed/coupon-usage-seed-data.js +12 -12
  150. package/dist/seed/coupons-seed-data.js +41 -41
  151. package/dist/seed/events-seed-data.js +105 -105
  152. package/dist/seed/grouped-listings-seed-data.d.ts +2 -137
  153. package/dist/seed/grouped-listings-seed-data.js +79 -143
  154. package/dist/seed/history-seed-data.js +38 -38
  155. package/dist/seed/homepage-sections-seed-data.js +9 -9
  156. package/dist/seed/notifications-seed-data.js +56 -56
  157. package/dist/seed/offers-seed-data.js +91 -91
  158. package/dist/seed/orders-seed-data.js +121 -106
  159. package/dist/seed/payouts-seed-data.js +42 -42
  160. package/dist/seed/products-auctions-seed-data.js +10 -2
  161. package/dist/seed/products-standard-seed-data.js +40 -8
  162. package/dist/seed/reviews-seed-data.js +42 -23
  163. package/dist/seed/scammers-seed-data.js +22 -22
  164. package/dist/seed/sessions-seed-data.js +7 -7
  165. package/dist/seed/shipments-seed-data.js +10 -10
  166. package/dist/seed/site-settings-seed-data.js +82 -0
  167. package/dist/seed/store-addresses-seed-data.js +2 -2
  168. package/dist/seed/store-extensions-seed-data.js +93 -93
  169. package/dist/seed/stores-seed-data.js +2 -0
  170. package/dist/seed/support-tickets-seed-data.js +47 -47
  171. package/dist/seed/users-seed-data.js +55 -89
  172. package/dist/seed/wishlists-seed-data.js +22 -22
  173. package/dist/server.d.ts +2 -1
  174. package/dist/server.js +5 -5
  175. package/dist/styles.css +1 -1
  176. package/dist/tailwind-utilities.css +1 -1
  177. package/dist/ui/components/PageLoader.js +8 -3
  178. package/dist/ui/components/Select.d.ts +8 -1
  179. package/dist/ui/components/Select.js +2 -2
  180. package/dist/ui/components/SiteMark.d.ts +23 -0
  181. package/dist/ui/components/SiteMark.js +76 -0
  182. package/dist/ui/index.d.ts +2 -0
  183. package/dist/ui/index.js +1 -0
  184. package/dist/validation/schemas.d.ts +0 -2
  185. package/dist/validation/schemas.js +0 -2
  186. package/package.json +1 -1
  187. package/scripts/seed-cli.mjs +17 -15
@@ -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, AUCTION_MIN_BID_INCREMENT_PAISE, AUCTION_SNIPING_WINDOW_SECONDS, } from "../../../shared/features/auctions/config";
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, AUCTION_MIN_BID_INCREMENT_PAISE, AUCTION_SNIPING_WINDOW_SECONDS, } from "../../../shared/features/auctions/config";
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 { AUCTION_MIN_BID_INCREMENT_PAISE, AUCTION_SNIPING_WINDOW_SECONDS, AUCTION_DEFAULT_EXTENSION_MINUTES, } from "../../../shared/features/auctions/config";
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 ?? AUCTION_MIN_BID_INCREMENT_PAISE;
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
- interface OrderItem {
3
- title?: string;
4
- name?: string;
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?.title ?? firstItem?.name ?? "an item";
57
+ const firstItemName = firstItem?.productTitle ?? "an item";
58
58
  const additionalItemCount = Math.max(0, items.length - 1);
59
- const buyerName = order.buyerDisplayName ?? "A customer";
59
+ const buyerName = order.userName ?? "A customer";
60
60
  const message = buildPurchaseAnnouncementMessage({
61
61
  buyerName,
62
62
  firstItemName,
63
63
  additionalItemCount,
64
- totalAmount: order.totalAmount ?? 0,
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
- const beforeCategory = before?.category ?? null;
67
- const afterCategory = after?.category ?? null;
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 AUCTION_MIN_BID_INCREMENT_PAISE = 100;
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 AUCTION_MIN_BID_INCREMENT_PAISE = 100; // ₹1
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().int().positive("Bid amount must be a positive integer (paise)"),
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().int().min(0),
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().int().optional(),
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().int().min(0).default(0),
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().int().min(0),
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().int().min(0, "Price must be non-negative (paise)");
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().int().min(0).optional(),
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().int().min(1).optional(),
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().int().min(0),
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().int().min(0).optional(),
19
- minPurchase: z.number().int().min(0).default(0),
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 paise. */
24
+ /** Platform commission in decimal rupees. */
26
25
  platformFee: number;
27
- /** GST on the platform fee, in paise. */
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 paise. */
33
+ /** Platform commission in decimal rupees. */
35
34
  platformFee: number;
36
- /** Payment gateway cost, absorbed by the platform from the seller's share, in paise. */
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 paise. */
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";