@mohasinac/appkit 4.26.0 → 4.28.0
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/lottery/LotteryAdminEditView.d.ts +16 -16
- package/dist/_internal/client/features/lottery/LotteryAdminEditView.js +29 -6
- package/dist/_internal/client/features/lottery/LotteryListView.js +13 -1
- package/dist/_internal/server/features/bundles/data.d.ts +19 -0
- package/dist/_internal/server/features/bundles/data.js +32 -0
- package/dist/_internal/server/features/bundles/index.d.ts +1 -1
- package/dist/_internal/server/features/bundles/index.js +1 -1
- package/dist/_internal/server/features/checkout/actions.js +6 -4
- package/dist/_internal/server/features/classified/metadata.js +3 -1
- package/dist/_internal/server/features/digital-code/metadata.js +3 -1
- package/dist/_internal/server/features/live/metadata.js +3 -1
- package/dist/_internal/server/features/refunds/actions.js +3 -2
- package/dist/_internal/server/features/reviews/actions.js +3 -2
- package/dist/_internal/server/features/seo/sitemap.js +189 -40
- package/dist/_internal/server/jobs/core/listingProcessor.d.ts +0 -1
- package/dist/_internal/server/jobs/core/listingProcessor.js +19 -1
- package/dist/_internal/shared/actions/action-registry.js +14 -0
- package/dist/_internal/shared/checkout/order-math.d.ts +25 -3
- package/dist/_internal/shared/features/checkout/config.d.ts +3 -3
- package/dist/_internal/shared/features/checkout/config.js +6 -3
- package/dist/client.d.ts +32 -2
- package/dist/client.js +37 -2
- package/dist/constants/api-endpoints.d.ts +21 -3
- package/dist/constants/api-endpoints.js +14 -1
- package/dist/constants/field-names.d.ts +2 -2
- package/dist/constants/field-names.js +2 -2
- package/dist/core/newsletter.repository.js +14 -1
- package/dist/features/about/components/FAQPageView.js +1 -1
- package/dist/features/about/components/FeesView.js +1 -1
- package/dist/features/account/components/AddressForm.d.ts +2 -0
- package/dist/features/account/components/AddressForm.js +5 -1
- package/dist/features/account/components/UserBidsView.js +1 -1
- package/dist/features/account/components/UserSidebar.js +1 -1
- package/dist/features/account/components/UserSupportView.js +24 -2
- package/dist/features/account/hooks/useAddresses.d.ts +29 -1
- package/dist/features/account/hooks/useAddresses.js +4 -1
- package/dist/features/account/hooks/useProfile.d.ts +1 -1
- package/dist/features/account/hooks/useProfile.js +1 -1
- package/dist/features/addresses/repository/addresses.repository.d.ts +13 -0
- package/dist/features/addresses/repository/addresses.repository.js +19 -0
- package/dist/features/admin/actions/chat-actions.js +5 -1
- package/dist/features/admin/components/AdminAdsView.js +1 -1
- package/dist/features/admin/components/AdminBidsView.js +6 -1
- package/dist/features/admin/components/AdminCarouselGroupEditorView.d.ts +9 -1
- package/dist/features/admin/components/AdminCarouselGroupEditorView.js +42 -10
- package/dist/features/admin/components/AdminCarouselView.js +1 -1
- package/dist/features/admin/components/AdminFeatureEditorView.js +1 -1
- package/dist/features/admin/components/AdminGroupedListingsView.js +14 -2
- package/dist/features/admin/components/AdminSidebar.js +1 -1
- package/dist/features/admin/components/AdminViewCards.js +2 -2
- package/dist/features/admin/components/DataTable.js +2 -2
- package/dist/features/admin/schemas/firestore.js +9 -3
- package/dist/features/auctions/actions/bid-actions.js +45 -4
- package/dist/features/auctions/components/AuctionBottomActions.d.ts +21 -6
- package/dist/features/auctions/components/AuctionBottomActions.js +42 -11
- package/dist/features/auctions/components/AuctionDetailPageView.d.ts +8 -3
- package/dist/features/auctions/components/AuctionDetailPageView.js +2 -2
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +4 -5
- package/dist/features/auctions/components/PlaceBidFormClient.d.ts +27 -2
- package/dist/features/auctions/components/PlaceBidFormClient.js +42 -20
- package/dist/features/auth/components/SocialAuthButtons.js +1 -1
- package/dist/features/auth/hooks/useAuth.d.ts +23 -1
- package/dist/features/auth/hooks/useAuth.js +27 -1
- package/dist/features/auth/permissions/constants.d.ts +1 -1
- package/dist/features/auth/permissions/constants.js +3 -0
- package/dist/features/auth/repository/session.repository.d.ts +16 -1
- package/dist/features/auth/repository/session.repository.js +23 -0
- package/dist/features/auth/repository/user.repository.js +13 -2
- package/dist/features/blog/components/BlogListView.js +2 -2
- package/dist/features/cart/components/CartPriceBreakdown.d.ts +11 -1
- package/dist/features/cart/components/CartPriceBreakdown.js +3 -3
- package/dist/features/cart/components/StoreAddonsPicker.d.ts +9 -0
- package/dist/features/cart/components/StoreAddonsPicker.js +15 -5
- package/dist/features/cart/components/index.d.ts +1 -1
- package/dist/features/cart/components/index.js +1 -1
- package/dist/features/cart/hooks/useGuestCartMerge.d.ts +8 -1
- package/dist/features/cart/hooks/useGuestCartMerge.js +2 -1
- package/dist/features/cart/utils/line-total.d.ts +25 -0
- package/dist/features/cart/utils/line-total.js +26 -0
- package/dist/features/catalogue/repository/catalogue.repository.d.ts +12 -0
- package/dist/features/catalogue/repository/catalogue.repository.js +15 -0
- package/dist/features/categories/components/CategoryTree.js +2 -2
- package/dist/features/contact/components/ContactForm.js +1 -1
- package/dist/features/copilot/hooks/useCopilotFeedback.d.ts +1 -1
- package/dist/features/copilot/hooks/useCopilotFeedback.js +1 -1
- package/dist/features/events/components/AdminEventEditorView.js +16 -9
- package/dist/features/events/components/AdminEventEntriesView.js +7 -13
- package/dist/features/events/components/EventRafflesSection.js +14 -2
- package/dist/features/events/components/EventStatusBadge.js +1 -1
- package/dist/features/events/components/event-entry-detail-fields.d.ts +24 -0
- package/dist/features/events/components/event-entry-detail-fields.js +13 -0
- package/dist/features/faq/components/ContactCTA.js +1 -1
- package/dist/features/faq/components/FAQHelpfulButtons.js +2 -2
- package/dist/features/faq/repository/faqs.repository.d.ts +16 -1
- package/dist/features/faq/repository/faqs.repository.js +64 -54
- package/dist/features/faq/schemas/firestore.d.ts +3 -2
- package/dist/features/faq/schemas/firestore.js +2 -2
- package/dist/features/faq/schemas/index.d.ts +3 -3
- package/dist/features/faq/schemas/index.js +1 -1
- package/dist/features/filters/FilterFacetSection.js +2 -2
- package/dist/features/forms/Toggle.js +1 -1
- package/dist/features/grouped/components/GroupedListingEditorView.d.ts +18 -0
- package/dist/features/grouped/components/GroupedListingEditorView.js +192 -0
- package/dist/features/homepage/components/AdvertisementBanner.js +2 -2
- package/dist/features/homepage/components/BrandsSection.js +1 -1
- package/dist/features/homepage/components/CTABannerSection.js +1 -1
- package/dist/features/homepage/components/HomepageCustomerReviewsSection.js +1 -1
- package/dist/features/homepage/components/HomepageSectionBoundary.d.ts +39 -0
- package/dist/features/homepage/components/HomepageSectionBoundary.js +49 -0
- package/dist/features/homepage/components/ShopByCategorySection.js +1 -1
- package/dist/features/homepage/components/WelcomeSection.js +1 -1
- package/dist/features/homepage/lib/section-renderer.js +2 -1
- package/dist/features/layout/AppLayoutShell.js +5 -5
- package/dist/features/layout/BottomActions.js +5 -5
- package/dist/features/layout/BottomSheet.js +1 -1
- package/dist/features/layout/MainNavbar.js +1 -1
- package/dist/features/layout/NavbarLayout.js +1 -1
- package/dist/features/layout/TitleBarLayout.js +3 -3
- package/dist/features/layout/hooks/useFormBottomActions.d.ts +11 -1
- package/dist/features/layout/hooks/useFormBottomActions.js +16 -2
- package/dist/features/lottery/schemas/config-write.d.ts +141 -0
- package/dist/features/lottery/schemas/config-write.js +139 -0
- package/dist/features/media/MediaPickerModal.js +3 -1
- package/dist/features/media/MediaVideo.js +4 -2
- package/dist/features/media/components/MediaSlider.js +1 -1
- package/dist/features/orders/components/OrdersList.js +2 -2
- package/dist/features/payments/repository/payout.repository.d.ts +11 -1
- package/dist/features/payments/repository/payout.repository.js +14 -6
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +3 -2
- package/dist/features/pre-orders/components/PreOrderBadge.js +1 -1
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +1 -1
- package/dist/features/products/columns/productTableColumns.js +3 -3
- package/dist/features/products/components/CompareOverlay.js +1 -1
- package/dist/features/products/components/PrizeDrawDetailPageView.js +1 -1
- package/dist/features/products/components/PrizeDrawEntryActions.js +2 -2
- package/dist/features/products/components/PrizeDrawsSection.js +5 -1
- package/dist/features/products/components/ProductDetailActions.js +11 -7
- package/dist/features/products/components/ProductDetailPageView.js +3 -3
- package/dist/features/products/components/ProductFeatureBadges.js +2 -2
- package/dist/features/products/components/ProductFeaturesSelector.js +1 -1
- package/dist/features/products/components/ProductFilters.js +15 -8
- package/dist/features/products/components/ProductGrid.js +8 -17
- package/dist/features/products/components/ProductTabs.js +7 -4
- package/dist/features/products/components/ProductTabsShell.js +2 -7
- package/dist/features/products/constants/action-defs.d.ts +21 -4
- package/dist/features/products/constants/action-defs.js +7 -3
- package/dist/features/products/hooks/useRelatedProducts.js +2 -1
- package/dist/features/products/repository/products.repository.d.ts +1 -1
- package/dist/features/products/repository/products.repository.js +27 -13
- package/dist/features/products/schemas/firestore.d.ts +3 -2
- package/dist/features/products/schemas/firestore.js +1 -1
- package/dist/features/reviews/actions/review-actions.d.ts +8 -1
- package/dist/features/reviews/actions/review-actions.js +14 -3
- package/dist/features/reviews/components/ReviewDetailShell.js +10 -4
- package/dist/features/reviews/components/ReviewModal.js +1 -1
- package/dist/features/reviews/repository/reviews.repository.d.ts +25 -1
- package/dist/features/reviews/repository/reviews.repository.js +53 -13
- package/dist/features/reviews/schemas/firestore.d.ts +6 -0
- package/dist/features/scams/components/ScamRegistryView.js +2 -2
- package/dist/features/search/components/Search.js +3 -3
- package/dist/features/search/components/SearchResultsSection.js +1 -1
- package/dist/features/seller/components/SellerAddressesView.js +3 -1
- package/dist/features/seller/components/SellerBidsView.js +6 -1
- package/dist/features/seller/components/SellerSidebar.js +1 -1
- package/dist/features/shell/SectionForm.d.ts +21 -1
- package/dist/features/shell/SectionForm.js +15 -3
- package/dist/features/shell/build-sections.js +10 -1
- package/dist/features/shell/field-ui-meta.d.ts +21 -0
- package/dist/features/shipments/components/AdminShipmentLotItemsView.js +23 -6
- package/dist/features/site-settings/components/ActionPermissionsManager.js +1 -1
- package/dist/features/store-extensions/repository/store-extensions.repositories.d.ts +21 -4
- package/dist/features/store-extensions/repository/store-extensions.repositories.js +24 -4
- package/dist/features/store-extensions/schemas/shipping-config-form.js +13 -0
- package/dist/features/store-extensions/schemas/store-category-form.js +1 -1
- package/dist/features/stores/actions/store-query-actions.js +25 -1
- package/dist/features/stores/components/InteractiveStoreCard.js +1 -1
- package/dist/features/stores/components/StoreHeader.js +1 -1
- package/dist/features/stores/components/StoreNavTabs.js +20 -8
- package/dist/features/support/repository/support.repository.d.ts +12 -0
- package/dist/features/support/repository/support.repository.js +15 -0
- package/dist/features/support/schemas/ticket-create-form.d.ts +33 -0
- package/dist/features/support/schemas/ticket-create-form.js +82 -0
- package/dist/features/tester/seed-data/products-tester-seed-data.js +108 -2
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +235 -13
- package/dist/features/wishlist/components/WishlistHeartButton.d.ts +55 -0
- package/dist/features/wishlist/components/WishlistHeartButton.js +52 -0
- package/dist/features/wishlist/components/index.d.ts +2 -1
- package/dist/features/wishlist/components/index.js +1 -1
- package/dist/index.d.ts +10 -3
- package/dist/index.js +19 -4
- package/dist/monitoring/error-tracking.js +39 -5
- package/dist/monitoring/server-logger.js +70 -32
- package/dist/next/components/ErrorView.js +1 -1
- package/dist/next/routing/route-map.d.ts +39 -7
- package/dist/next/routing/route-map.js +34 -4
- package/dist/providers/db-firebase/base.repository.d.ts +30 -0
- package/dist/providers/db-firebase/base.repository.js +56 -9
- package/dist/react/ErrorBoundary.js +9 -1
- package/dist/react/contexts/SessionContext.js +6 -2
- package/dist/react/hooks/useAuthGate.d.ts +22 -0
- package/dist/react/hooks/useAuthGate.js +86 -7
- package/dist/schemas/registry.d.ts +3 -3
- package/dist/security/index.d.ts +1 -1
- package/dist/security/index.js +1 -1
- package/dist/security/pii-encrypt.d.ts +13 -5
- package/dist/security/pii-encrypt.js +132 -6
- package/dist/security/pii-schemas.d.ts +20 -4
- package/dist/security/pii-schemas.js +23 -5
- package/dist/seed/_helpers/product-search-txt.d.ts +18 -0
- package/dist/seed/_helpers/product-search-txt.js +33 -0
- package/dist/seed/faq-seed-data.d.ts +16 -0
- package/dist/seed/faq-seed-data.js +22 -1
- package/dist/seed/products-art-seed-data.js +49 -7
- package/dist/seed/products-auctions-seed-data.js +12 -4
- package/dist/seed/products-classifieds-seed-data.d.ts +5 -0
- package/dist/seed/products-classifieds-seed-data.js +65 -9
- package/dist/seed/products-digital-codes-seed-data.d.ts +5 -0
- package/dist/seed/products-digital-codes-seed-data.js +65 -9
- package/dist/seed/products-live-items-seed-data.d.ts +5 -0
- package/dist/seed/products-live-items-seed-data.js +33 -5
- package/dist/seed/products-preorders-seed-data.d.ts +1 -1
- package/dist/seed/products-preorders-seed-data.js +6 -2
- package/dist/seed/products-prize-draws-seed-data.d.ts +5 -0
- package/dist/seed/products-prize-draws-seed-data.js +57 -8
- package/dist/seed/products-standard-seed-data.js +6 -2
- package/dist/seed/products-stickers-seed-data.js +49 -7
- package/dist/seed/site-settings-seed-data.js +5 -3
- package/dist/seo/json-ld.d.ts +44 -2
- package/dist/seo/json-ld.js +57 -11
- package/dist/server.d.ts +1 -1
- package/dist/server.js +1 -1
- package/dist/styles.css +368 -90
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/index.d.ts +1 -1
- package/dist/tokens/index.js +1 -1
- package/dist/tokens/themes/default-dark.js +6 -0
- package/dist/tokens/themes/default-light.js +5 -0
- package/dist/tokens/tokens.css +84 -0
- package/dist/ui/DataTable.js +1 -1
- package/dist/ui/DataTable.style.css +3 -3
- package/dist/ui/components/BulkActionBar.style.css +1 -3
- package/dist/ui/components/Button.js +15 -6
- package/dist/ui/components/Dropdown.style.css +1 -4
- package/dist/ui/components/FilterChipGroup.js +1 -1
- package/dist/ui/components/FilterDrawer.style.css +1 -1
- package/dist/ui/components/Icon.d.ts +53 -0
- package/dist/ui/components/Icon.js +41 -0
- package/dist/ui/components/IconButton.d.ts +13 -0
- package/dist/ui/components/IconButton.js +13 -0
- package/dist/ui/components/IconButton.style.css +18 -10
- package/dist/ui/components/ListingLayout.style.css +2 -10
- package/dist/ui/components/ListingToolbar.js +6 -6
- package/dist/ui/components/Modal.js +1 -1
- package/dist/ui/components/PaginatedSelect.style.css +3 -3
- package/dist/ui/components/Pagination.style.css +1 -6
- package/dist/ui/components/RichTextEditor.js +1 -1
- package/dist/ui/components/RowActionMenu.style.css +1 -1
- package/dist/ui/components/SideDrawer.style.css +1 -1
- package/dist/ui/components/Slider.js +1 -1
- package/dist/ui/components/TabBarShell.d.ts +78 -0
- package/dist/ui/components/TabBarShell.js +95 -0
- package/dist/ui/components/Tabs.js +12 -8
- package/dist/ui/components/Tabs.style.css +249 -41
- package/dist/ui/components/ViewToggle.style.css +1 -5
- package/dist/ui/components/tabs-overflow.d.ts +17 -0
- package/dist/ui/components/tabs-overflow.js +142 -0
- package/dist/ui/icons/icon-registry.d.ts +38 -0
- package/dist/ui/icons/icon-registry.js +37 -0
- package/dist/ui/index.d.ts +6 -0
- package/dist/ui/index.js +3 -0
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/media-url.d.ts +27 -4
- package/dist/utils/media-url.js +37 -6
- package/dist/utils/search-txt.d.ts +71 -0
- package/dist/utils/search-txt.js +118 -0
- package/package.json +1 -1
|
@@ -18,10 +18,11 @@
|
|
|
18
18
|
* @tag consumers:seed/index.ts,seed/runner.ts
|
|
19
19
|
* @tag sideEffects:none
|
|
20
20
|
*/
|
|
21
|
+
import { withProductSearchTxt } from "./_helpers/product-search-txt";
|
|
21
22
|
import { PRODUCT_FIELDS } from "../constants/field-names";
|
|
22
|
-
import {
|
|
23
|
+
import { buildSearchTxt } from "../utils/search-txt";
|
|
23
24
|
import { seedExtMedia } from "./_helpers/media";
|
|
24
|
-
|
|
25
|
+
const _rawproductsPrizeDrawsSeedData = [
|
|
25
26
|
{
|
|
26
27
|
id: "prizedraw-beyblade-mystery-box",
|
|
27
28
|
slug: "prizedraw-beyblade-mystery-box",
|
|
@@ -66,7 +67,14 @@ export const productsPrizeDrawsSeedData = [
|
|
|
66
67
|
tags: ["prize-draw", "mystery-box"],
|
|
67
68
|
createdAt: new Date("2026-05-01"),
|
|
68
69
|
updatedAt: new Date("2026-05-01"),
|
|
69
|
-
|
|
70
|
+
searchTxt: buildSearchTxt([
|
|
71
|
+
"Beyblade Mystery Box — Prize Draw",
|
|
72
|
+
"Buy an entry and reveal your prize instantly.",
|
|
73
|
+
"Beyblade",
|
|
74
|
+
"brand-beyblade",
|
|
75
|
+
["Spinning Tops"],
|
|
76
|
+
["prize-draw", "mystery-box"],
|
|
77
|
+
]),
|
|
70
78
|
},
|
|
71
79
|
{
|
|
72
80
|
id: "prizedraw-beyblade-scheduled-demo",
|
|
@@ -110,7 +118,14 @@ export const productsPrizeDrawsSeedData = [
|
|
|
110
118
|
tags: ["prize-draw", "mystery-box"],
|
|
111
119
|
createdAt: new Date("2026-05-01"),
|
|
112
120
|
updatedAt: new Date("2026-05-01"),
|
|
113
|
-
|
|
121
|
+
searchTxt: buildSearchTxt([
|
|
122
|
+
"Beyblade Champion's Draw — Prize Draw",
|
|
123
|
+
"Two entries, two prizes, revealed automatically at close or sellout.",
|
|
124
|
+
"Beyblade",
|
|
125
|
+
"brand-beyblade",
|
|
126
|
+
["Spinning Tops"],
|
|
127
|
+
["prize-draw", "mystery-box"],
|
|
128
|
+
]),
|
|
114
129
|
},
|
|
115
130
|
// --- Partially sold: prizeCurrentEntries > 0, main seed never exercised this before ---
|
|
116
131
|
{
|
|
@@ -162,7 +177,14 @@ export const productsPrizeDrawsSeedData = [
|
|
|
162
177
|
tags: ["prize-draw", "mystery-box", "chase-top"],
|
|
163
178
|
createdAt: new Date("2026-08-15"),
|
|
164
179
|
updatedAt: new Date("2026-08-19"),
|
|
165
|
-
|
|
180
|
+
searchTxt: buildSearchTxt([
|
|
181
|
+
"Beyblade X Legendary Vault — Prize Draw",
|
|
182
|
+
"6 entries, 6 prizes, over half already sold.",
|
|
183
|
+
"Takara-Tomy",
|
|
184
|
+
"brand-takara-tomy",
|
|
185
|
+
["Beyblade X", "Spinning Tops"],
|
|
186
|
+
["prize-draw", "mystery-box", "chase-top"],
|
|
187
|
+
]),
|
|
166
188
|
},
|
|
167
189
|
// --- Closed + revealed: real winners, isWon:true — permanent-catalog example (previously only in tester sandbox) ---
|
|
168
190
|
{
|
|
@@ -208,7 +230,14 @@ export const productsPrizeDrawsSeedData = [
|
|
|
208
230
|
tags: ["prize-draw", "mystery-box"],
|
|
209
231
|
createdAt: new Date("2026-08-05"),
|
|
210
232
|
updatedAt: new Date("2026-08-12"),
|
|
211
|
-
|
|
233
|
+
searchTxt: buildSearchTxt([
|
|
234
|
+
"Metal Fight Mystery Draw — Ended (Revealed)",
|
|
235
|
+
"This draw has closed and every prize has been revealed.",
|
|
236
|
+
"Takara-Tomy",
|
|
237
|
+
"brand-takara-tomy",
|
|
238
|
+
["Beyblade Metal Fight", "Spinning Tops"],
|
|
239
|
+
["prize-draw", "mystery-box"],
|
|
240
|
+
]),
|
|
212
241
|
},
|
|
213
242
|
// --- Nearly sold out, scheduled reveal ---
|
|
214
243
|
{
|
|
@@ -259,7 +288,14 @@ export const productsPrizeDrawsSeedData = [
|
|
|
259
288
|
tags: ["prize-draw", "mystery-box"],
|
|
260
289
|
createdAt: new Date("2026-08-17"),
|
|
261
290
|
updatedAt: new Date("2026-08-19"),
|
|
262
|
-
|
|
291
|
+
searchTxt: buildSearchTxt([
|
|
292
|
+
"Beyblade Burst Collector's Draw — Almost Sold Out",
|
|
293
|
+
"Only 1 entry left, 4 of 5 slots already claimed.",
|
|
294
|
+
"Beyblade",
|
|
295
|
+
"brand-beyblade",
|
|
296
|
+
["Beyblade Burst", "Spinning Tops"],
|
|
297
|
+
["prize-draw", "mystery-box"],
|
|
298
|
+
]),
|
|
263
299
|
},
|
|
264
300
|
// --- High-value vintage vault, multi-image collage per prize ---
|
|
265
301
|
{
|
|
@@ -308,7 +344,14 @@ export const productsPrizeDrawsSeedData = [
|
|
|
308
344
|
tags: ["prize-draw", "mystery-box", "vintage-collectible"],
|
|
309
345
|
createdAt: new Date("2026-08-18"),
|
|
310
346
|
updatedAt: new Date("2026-08-18"),
|
|
311
|
-
|
|
347
|
+
searchTxt: buildSearchTxt([
|
|
348
|
+
"Beyblade Original Vintage Vault — Prize Draw",
|
|
349
|
+
"High-value original-series vault, multi-angle photos per prize.",
|
|
350
|
+
"Beyblade",
|
|
351
|
+
"brand-beyblade",
|
|
352
|
+
["Beyblade Original", "Spinning Tops"],
|
|
353
|
+
["prize-draw", "mystery-box", "vintage-collectible"],
|
|
354
|
+
]),
|
|
312
355
|
},
|
|
313
356
|
{
|
|
314
357
|
// Closed, but with slots still unsold and `isSold: false`.
|
|
@@ -360,3 +403,9 @@ export const productsPrizeDrawsSeedData = [
|
|
|
360
403
|
updatedAt: new Date("2026-08-24"),
|
|
361
404
|
},
|
|
362
405
|
];
|
|
406
|
+
/**
|
|
407
|
+
* Every record gains `searchTxt` here rather than inline, so a fixture added at
|
|
408
|
+
* the bottom of the array cannot ship without it — which is exactly how the
|
|
409
|
+
* sold/depleted fixture in this file ended up unsearchable.
|
|
410
|
+
*/
|
|
411
|
+
export const productsPrizeDrawsSeedData = _rawproductsPrizeDrawsSeedData.map(withProductSearchTxt);
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
* @tag sideEffects:none
|
|
24
24
|
*/
|
|
25
25
|
import { PRODUCT_FIELDS } from "../constants/field-names";
|
|
26
|
-
import {
|
|
26
|
+
import { buildSearchTxt } from "../utils/search-txt";
|
|
27
27
|
import { seedExtMedia } from "./_helpers/media";
|
|
28
28
|
/*
|
|
29
29
|
* Real Beyblade attributes per fixture — Root Cause #6 (standard was the
|
|
@@ -170,7 +170,11 @@ function withTokens(p) {
|
|
|
170
170
|
tags: [],
|
|
171
171
|
featured: false,
|
|
172
172
|
...p,
|
|
173
|
-
|
|
173
|
+
searchTxt: buildSearchTxt([
|
|
174
|
+
p.title, p.description, p.brand, p.brandSlug,
|
|
175
|
+
p.categoryNames, p.tags, p.features, p.condition,
|
|
176
|
+
p.specifications?.map((s) => `${s.name} ${s.value}`),
|
|
177
|
+
]),
|
|
174
178
|
};
|
|
175
179
|
}
|
|
176
180
|
const _rawProductsStandardSeedData = [
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* @tag sideEffects:none
|
|
18
18
|
*/
|
|
19
19
|
import { PRODUCT_FIELDS } from "../constants/field-names";
|
|
20
|
-
import {
|
|
20
|
+
import { buildSearchTxt } from "../utils/search-txt";
|
|
21
21
|
import { seedExtMedia } from "./_helpers/media";
|
|
22
22
|
export const productsStickersSeedData = [
|
|
23
23
|
{
|
|
@@ -50,7 +50,14 @@ export const productsStickersSeedData = [
|
|
|
50
50
|
tags: ["stickers", "vintage-collectible"],
|
|
51
51
|
createdAt: new Date("2026-08-17"),
|
|
52
52
|
updatedAt: new Date("2026-08-17"),
|
|
53
|
-
|
|
53
|
+
searchTxt: buildSearchTxt([
|
|
54
|
+
"Beyblade Original Classic — Sticker Sheet",
|
|
55
|
+
"5x5 cm sticker sheet featuring Dranzer, Driger, Draciel, and Dragoon.",
|
|
56
|
+
"Beyblade",
|
|
57
|
+
"brand-beyblade",
|
|
58
|
+
["Beyblade Original", "Spinning Tops"],
|
|
59
|
+
["stickers", "vintage-collectible"],
|
|
60
|
+
]),
|
|
54
61
|
},
|
|
55
62
|
{
|
|
56
63
|
id: "stickers-beyblade-x-holographic-pack",
|
|
@@ -85,7 +92,14 @@ export const productsStickersSeedData = [
|
|
|
85
92
|
tags: ["stickers"],
|
|
86
93
|
createdAt: new Date("2026-08-18"),
|
|
87
94
|
updatedAt: new Date("2026-08-19"),
|
|
88
|
-
|
|
95
|
+
searchTxt: buildSearchTxt([
|
|
96
|
+
"Beyblade X Holographic Sticker Pack",
|
|
97
|
+
"Holographic-finish sticker pack featuring the current Beyblade X lineup.",
|
|
98
|
+
"Takara-Tomy",
|
|
99
|
+
"brand-takara-tomy",
|
|
100
|
+
["Beyblade X", "Spinning Tops"],
|
|
101
|
+
["stickers"],
|
|
102
|
+
]),
|
|
89
103
|
},
|
|
90
104
|
{
|
|
91
105
|
id: "stickers-beyblade-burst-diecut-set",
|
|
@@ -117,7 +131,14 @@ export const productsStickersSeedData = [
|
|
|
117
131
|
tags: ["stickers"],
|
|
118
132
|
createdAt: new Date("2026-08-19"),
|
|
119
133
|
updatedAt: new Date("2026-08-19"),
|
|
120
|
-
|
|
134
|
+
searchTxt: buildSearchTxt([
|
|
135
|
+
"Beyblade Burst Die-Cut Sticker Set (6-Pack)",
|
|
136
|
+
"Individually die-cut vinyl stickers of 6 fan-favorite Burst tops.",
|
|
137
|
+
"Beyblade",
|
|
138
|
+
"brand-beyblade",
|
|
139
|
+
["Beyblade Burst", "Spinning Tops"],
|
|
140
|
+
["stickers"],
|
|
141
|
+
]),
|
|
121
142
|
},
|
|
122
143
|
{
|
|
123
144
|
id: "stickers-beyblade-metal-retro-sheet",
|
|
@@ -149,7 +170,14 @@ export const productsStickersSeedData = [
|
|
|
149
170
|
tags: ["stickers", "vintage-collectible", "limited-run"],
|
|
150
171
|
createdAt: new Date("2026-08-19"),
|
|
151
172
|
updatedAt: new Date("2026-08-19"),
|
|
152
|
-
|
|
173
|
+
searchTxt: buildSearchTxt([
|
|
174
|
+
"Metal Fight Retro Sticker Sheet — Limited /500",
|
|
175
|
+
"Limited-edition retro-styled sticker sheet, numbered out of 500.",
|
|
176
|
+
"Takara-Tomy",
|
|
177
|
+
"brand-takara-tomy",
|
|
178
|
+
["Beyblade Metal Fight", "Spinning Tops"],
|
|
179
|
+
["stickers", "vintage-collectible", "limited-run"],
|
|
180
|
+
]),
|
|
153
181
|
},
|
|
154
182
|
{
|
|
155
183
|
id: "stickers-beyblade-x-glow-in-dark",
|
|
@@ -184,7 +212,14 @@ export const productsStickersSeedData = [
|
|
|
184
212
|
tags: ["stickers"],
|
|
185
213
|
createdAt: new Date("2026-08-19"),
|
|
186
214
|
updatedAt: new Date("2026-08-19"),
|
|
187
|
-
|
|
215
|
+
searchTxt: buildSearchTxt([
|
|
216
|
+
"Beyblade X Glow-in-the-Dark Sticker Pack",
|
|
217
|
+
"Charge under light and watch the Beyblade X logos glow in the dark.",
|
|
218
|
+
"Takara-Tomy",
|
|
219
|
+
"brand-takara-tomy",
|
|
220
|
+
["Beyblade X", "Spinning Tops"],
|
|
221
|
+
["stickers"],
|
|
222
|
+
]),
|
|
188
223
|
},
|
|
189
224
|
{
|
|
190
225
|
// Sold-out fixture — see the art file's equivalent for the shape rationale.
|
|
@@ -219,6 +254,13 @@ export const productsStickersSeedData = [
|
|
|
219
254
|
tags: ["stickers", "sold-out"],
|
|
220
255
|
createdAt: new Date("2026-08-24"),
|
|
221
256
|
updatedAt: new Date("2026-08-24"),
|
|
222
|
-
|
|
257
|
+
searchTxt: buildSearchTxt([
|
|
258
|
+
"Beyblade Metal Fight Sticker Sheet (Sold Out)",
|
|
259
|
+
"The original Metal Fight sticker sheet run, now fully sold out.",
|
|
260
|
+
"Beyblade",
|
|
261
|
+
"brand-beyblade",
|
|
262
|
+
["Beyblade Metal", "Spinning Tops"],
|
|
263
|
+
["stickers", "sold-out"],
|
|
264
|
+
]),
|
|
223
265
|
},
|
|
224
266
|
];
|
|
@@ -418,11 +418,13 @@ export const siteSettingsSeedData = {
|
|
|
418
418
|
codDepositPercent: 10,
|
|
419
419
|
codHandlingFeeMin: 200,
|
|
420
420
|
codHandlingFeePercent: 10,
|
|
421
|
-
|
|
421
|
+
// Enabled so a seeded install actually shows the add-ons — see the matching
|
|
422
|
+
// comment on DEFAULT_SITE_SETTINGS_DATA.commissions.
|
|
423
|
+
whatsappNotifyFeeEnabled: true,
|
|
422
424
|
whatsappNotifyFee: 10,
|
|
423
|
-
giftWrapFeeEnabled:
|
|
425
|
+
giftWrapFeeEnabled: true,
|
|
424
426
|
giftWrapFee: 49,
|
|
425
|
-
shipmentProtectionFeeEnabled:
|
|
427
|
+
shipmentProtectionFeeEnabled: true,
|
|
426
428
|
shipmentProtectionFeePercent: 2,
|
|
427
429
|
shipmentProtectionFeeMin: 30,
|
|
428
430
|
sellerShippingFixed: 0,
|
package/dist/seo/json-ld.d.ts
CHANGED
|
@@ -36,6 +36,25 @@ export interface ProductJsonLdInput {
|
|
|
36
36
|
auctionEndDate?: Date;
|
|
37
37
|
/** Canonical discriminator (SB1-G Phase 4). */
|
|
38
38
|
listingType?: ListingType;
|
|
39
|
+
/**
|
|
40
|
+
* Denormalised rating, straight off `ProductDocument.avgRating` /
|
|
41
|
+
* `.reviewCount` — so emitting it costs **zero** extra Firestore reads.
|
|
42
|
+
*
|
|
43
|
+
* Merged into THIS node rather than emitted as a separate `Product` via
|
|
44
|
+
* `aggregateRatingJsonLd`, which builds a second node carrying only
|
|
45
|
+
* name/url/aggregateRating and no `offers`. Two `Product` nodes for one page
|
|
46
|
+
* duplicates the entity, and a `Product` with no offers is incomplete for
|
|
47
|
+
* Google — merging is the shape that actually earns review stars.
|
|
48
|
+
*
|
|
49
|
+
* Deliberately NOT accompanied by per-review `Review` nodes: schema.org
|
|
50
|
+
* `Review.author` is personal data, and reviewer names are masked on public
|
|
51
|
+
* surfaces (`maskPublicReview`). The stars in a SERP come from the aggregate,
|
|
52
|
+
* so this yields the full benefit with no identity exposure.
|
|
53
|
+
*/
|
|
54
|
+
rating?: {
|
|
55
|
+
average: number;
|
|
56
|
+
count: number;
|
|
57
|
+
};
|
|
39
58
|
}
|
|
40
59
|
export interface ReviewJsonLdInput {
|
|
41
60
|
id: string;
|
|
@@ -74,7 +93,30 @@ export declare function aggregateRatingJsonLd(product: Pick<ProductJsonLdInput,
|
|
|
74
93
|
export declare function breadcrumbJsonLd(items: BreadcrumbJsonLdItem[]): Record<string, JsonLdValue>;
|
|
75
94
|
export declare function faqJsonLd(faqs: FaqJsonLdInput[]): Record<string, JsonLdValue>;
|
|
76
95
|
export declare function blogPostJsonLd(post: BlogPostJsonLdInput): Record<string, JsonLdValue>;
|
|
77
|
-
|
|
78
|
-
|
|
96
|
+
/**
|
|
97
|
+
* Site-identity options for the two site-wide nodes.
|
|
98
|
+
*
|
|
99
|
+
* These used to read `NEXT_PUBLIC_SITE_NAME` / `NEXT_PUBLIC_SITE_URL` directly,
|
|
100
|
+
* with fallbacks of `"App"` and `""`. Two live consequences:
|
|
101
|
+
*
|
|
102
|
+
* - Production had `NEXT_PUBLIC_SITE_NAME="Letitrip"` — the wrong casing, which
|
|
103
|
+
* CLAUDE.md's brand rule explicitly forbids — so every page emitted
|
|
104
|
+
* `Organization.name: "Letitrip"`, the string Google may show in a Knowledge
|
|
105
|
+
* Panel. A brand name should not be settable by a mis-typed env var.
|
|
106
|
+
* - With the env unset the nodes emit `name: "App"` and `url: ""`, which is a
|
|
107
|
+
* valid-looking but wrong entity rather than a visible failure.
|
|
108
|
+
*
|
|
109
|
+
* Callers pass their real config (the consumer has `SEO_CONFIG.siteName` /
|
|
110
|
+
* `.siteUrl` from appkit.config.js, the single canonical host definition). The
|
|
111
|
+
* env values remain as a fallback so existing callers keep working.
|
|
112
|
+
*/
|
|
113
|
+
export interface SiteIdentityOptions {
|
|
114
|
+
siteName?: string;
|
|
115
|
+
siteUrl?: string;
|
|
116
|
+
/** Real social/profile URLs — feeds schema.org `sameAs`, which drives entity recognition. */
|
|
117
|
+
sameAs?: readonly string[];
|
|
118
|
+
}
|
|
119
|
+
export declare function organizationJsonLd(opts?: SiteIdentityOptions): Record<string, JsonLdValue>;
|
|
120
|
+
export declare function searchBoxJsonLd(opts?: SiteIdentityOptions): Record<string, JsonLdValue>;
|
|
79
121
|
export declare function auctionJsonLd(auction: ProductJsonLdInput): Record<string, JsonLdValue>;
|
|
80
122
|
export {};
|
package/dist/seo/json-ld.js
CHANGED
|
@@ -14,15 +14,42 @@
|
|
|
14
14
|
*/
|
|
15
15
|
const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL ?? "";
|
|
16
16
|
const SITE_NAME = process.env.NEXT_PUBLIC_SITE_NAME ?? "App";
|
|
17
|
+
/**
|
|
18
|
+
* schema.org requires ABSOLUTE URLs. A relative `image` or `item` is not a
|
|
19
|
+
* lenient-parse case — Google rejects the property, and `image` is *required*
|
|
20
|
+
* for Product rich results, so a relative one costs the whole rich result.
|
|
21
|
+
*
|
|
22
|
+
* `productJsonLd` prefixed `url` and `offers.url` with SITE_URL but passed
|
|
23
|
+
* `image[]` through untouched, so every product emitted four relative
|
|
24
|
+
* `/api/media/ext?...` image URLs and no product could earn a rich result.
|
|
25
|
+
*
|
|
26
|
+
* Leaves already-absolute URLs (and `data:` URIs) alone. Returns undefined for
|
|
27
|
+
* an empty value so `JSON.stringify` drops the key rather than emitting `""`.
|
|
28
|
+
*/
|
|
29
|
+
function absoluteUrl(value, base = SITE_URL) {
|
|
30
|
+
const v = value?.trim();
|
|
31
|
+
if (!v)
|
|
32
|
+
return undefined;
|
|
33
|
+
if (/^(https?:)?\/\//i.test(v) || v.startsWith("data:"))
|
|
34
|
+
return v;
|
|
35
|
+
if (!base)
|
|
36
|
+
return undefined; // no base to resolve against — omit rather than emit a bare path
|
|
37
|
+
return `${base.replace(/\/+$/, "")}/${v.replace(/^\/+/, "")}`;
|
|
38
|
+
}
|
|
17
39
|
import { ProductStatusValues } from "../features/products/schemas";
|
|
18
40
|
import { getDefaultCurrency } from "../core/baseline-resolver";
|
|
19
41
|
// --- Helpers -----------------------------------------------------------------
|
|
20
42
|
export function productJsonLd(product) {
|
|
21
43
|
const url = `${SITE_URL}/products/${product.slug}`;
|
|
44
|
+
// Absolutise, then de-duplicate: `mainImage` is very often also `images[0]`,
|
|
45
|
+
// which produced the same URL twice in the emitted array.
|
|
22
46
|
const images = [
|
|
23
47
|
...(product.mainImage ? [product.mainImage] : []),
|
|
24
48
|
...(product.images || []),
|
|
25
|
-
]
|
|
49
|
+
]
|
|
50
|
+
.map((img) => absoluteUrl(img))
|
|
51
|
+
.filter((img) => Boolean(img))
|
|
52
|
+
.filter((img, i, arr) => arr.indexOf(img) === i);
|
|
26
53
|
return {
|
|
27
54
|
"@context": "https://schema.org",
|
|
28
55
|
"@type": "Product",
|
|
@@ -47,6 +74,18 @@ export function productJsonLd(product) {
|
|
|
47
74
|
? { "@type": "Organization", name: product.sellerName }
|
|
48
75
|
: undefined,
|
|
49
76
|
},
|
|
77
|
+
// Google requires ratingValue AND a positive reviewCount; a zero-count
|
|
78
|
+
// AggregateRating is invalid and suppresses the whole rich result, so omit
|
|
79
|
+
// the key entirely rather than emitting an empty one.
|
|
80
|
+
aggregateRating: product.rating && product.rating.count > 0 && product.rating.average > 0
|
|
81
|
+
? {
|
|
82
|
+
"@type": "AggregateRating",
|
|
83
|
+
ratingValue: product.rating.average,
|
|
84
|
+
reviewCount: product.rating.count,
|
|
85
|
+
bestRating: 5,
|
|
86
|
+
worstRating: 1,
|
|
87
|
+
}
|
|
88
|
+
: undefined,
|
|
50
89
|
};
|
|
51
90
|
}
|
|
52
91
|
export function reviewJsonLd(review) {
|
|
@@ -123,32 +162,39 @@ export function blogPostJsonLd(post) {
|
|
|
123
162
|
mainEntityOfPage: { "@type": "WebPage", "@id": url },
|
|
124
163
|
};
|
|
125
164
|
}
|
|
126
|
-
export function organizationJsonLd() {
|
|
165
|
+
export function organizationJsonLd(opts) {
|
|
166
|
+
const name = opts?.siteName?.trim() || SITE_NAME;
|
|
167
|
+
const base = (opts?.siteUrl?.trim() || SITE_URL).replace(/\/+$/, "");
|
|
168
|
+
// `sameAs: []` was hardcoded empty while appkit.config.js carried real
|
|
169
|
+
// socialUrls that nothing read. An empty array is worse than omitting the key.
|
|
170
|
+
const sameAs = (opts?.sameAs ?? []).filter(Boolean);
|
|
127
171
|
return {
|
|
128
172
|
"@context": "https://schema.org",
|
|
129
173
|
"@type": "Organization",
|
|
130
|
-
name
|
|
131
|
-
url:
|
|
132
|
-
logo:
|
|
133
|
-
sameAs: [],
|
|
174
|
+
name,
|
|
175
|
+
url: base || undefined,
|
|
176
|
+
logo: absoluteUrl("/icons/icon-512x512.png", base),
|
|
177
|
+
sameAs: sameAs.length > 0 ? [...sameAs] : undefined,
|
|
134
178
|
contactPoint: {
|
|
135
179
|
"@type": "ContactPoint",
|
|
136
180
|
contactType: "customer support",
|
|
137
|
-
url:
|
|
181
|
+
url: absoluteUrl("/contact", base),
|
|
138
182
|
},
|
|
139
183
|
};
|
|
140
184
|
}
|
|
141
|
-
export function searchBoxJsonLd() {
|
|
185
|
+
export function searchBoxJsonLd(opts) {
|
|
186
|
+
const name = opts?.siteName?.trim() || SITE_NAME;
|
|
187
|
+
const base = (opts?.siteUrl?.trim() || SITE_URL).replace(/\/+$/, "");
|
|
142
188
|
return {
|
|
143
189
|
"@context": "https://schema.org",
|
|
144
190
|
"@type": "WebSite",
|
|
145
|
-
name
|
|
146
|
-
url:
|
|
191
|
+
name,
|
|
192
|
+
url: base || undefined,
|
|
147
193
|
potentialAction: {
|
|
148
194
|
"@type": "SearchAction",
|
|
149
195
|
target: {
|
|
150
196
|
"@type": "EntryPoint",
|
|
151
|
-
urlTemplate: `${
|
|
197
|
+
urlTemplate: `${base}/search?q={search_term_string}`,
|
|
152
198
|
},
|
|
153
199
|
"query-input": "required name=search_term_string",
|
|
154
200
|
},
|
package/dist/server.d.ts
CHANGED
|
@@ -501,7 +501,7 @@ export { GoogleReviewsSection } from "./features/homepage/components/GoogleRevie
|
|
|
501
501
|
export type { GoogleReviewsSectionProps } from "./features/homepage/components/GoogleReviewsSection";
|
|
502
502
|
export { getProductForDetail, listSitemapProducts, computeRelatedItems, toProductItem, type SitemapProduct, type RelatedItemsResult, } from "./_internal/server/features/products/index";
|
|
503
503
|
export { listPublicProducts, parsePublicProductParams, defaultAvailabilityForListingTypes, PUBLIC_PRODUCT_MAX_PAGE_SIZE, ANY_STATUS, type PublicProductListInput, type PublicProductListResult, type PublicProductListOptions, type PublicProductExecutor, type PublicProductQuery, } from "./_internal/server/features/products/index";
|
|
504
|
-
export { getBundleForDetail, listBundleMembers, listFeaturedBundles, getRelatedBundles, resolveBundleMemberIds, resolveBundleOriginalTotal, resolveBundleCategorySlugs, buildBundleMetadata, renderBundleOg, renderBundleOgImage, addBundleToCartAction, type BundleDataOptions, type BundleMetadataOptions, type BundleOgData, } from "./_internal/server/features/bundles/index";
|
|
504
|
+
export { getBundleForDetail, listBundleMembers, listFeaturedBundles, getRelatedBundles, resolveBundleMemberIds, resolveBundleOriginalTotal, findBundleMemberStores, resolveBundleCategorySlugs, buildBundleMetadata, renderBundleOg, renderBundleOgImage, addBundleToCartAction, type BundleDataOptions, type BundleMetadataOptions, type BundleOgData, } from "./_internal/server/features/bundles/index";
|
|
505
505
|
export { getGroupsForProduct, getGroupsWithItemsForProduct, getGroupsForCategory, getGroupsForBrand } from "./_internal/server/features/grouped/index";
|
|
506
506
|
export { getGroupedListingForDetail, getGroupedListingWithItems, buildGroupedListingMetadata, renderGroupedListingOg, type GroupedListingWithItems, type GroupedListingMetadataOptions, } from "./_internal/server/features/grouped/index";
|
|
507
507
|
export { toPublicGroupMember, toPublicGroupMembers, type PublicGroupMember, } from "./_internal/server/features/products/group-members";
|
package/dist/server.js
CHANGED
|
@@ -1356,7 +1356,7 @@ export { getProductForDetail, listSitemapProducts, computeRelatedItems, toProduc
|
|
|
1356
1356
|
// share it so their filter semantics cannot drift (Root Cause #30).
|
|
1357
1357
|
export { listPublicProducts, parsePublicProductParams, defaultAvailabilityForListingTypes, PUBLIC_PRODUCT_MAX_PAGE_SIZE, ANY_STATUS, } from "./_internal/server/features/products/index";
|
|
1358
1358
|
// S-SBUNI-3/4 2026-05-13 — bundle data/metadata/og layer.
|
|
1359
|
-
export { getBundleForDetail, listBundleMembers, listFeaturedBundles, getRelatedBundles, resolveBundleMemberIds, resolveBundleOriginalTotal, resolveBundleCategorySlugs, buildBundleMetadata, renderBundleOg, renderBundleOgImage, addBundleToCartAction, } from "./_internal/server/features/bundles/index";
|
|
1359
|
+
export { getBundleForDetail, listBundleMembers, listFeaturedBundles, getRelatedBundles, resolveBundleMemberIds, resolveBundleOriginalTotal, findBundleMemberStores, resolveBundleCategorySlugs, buildBundleMetadata, renderBundleOg, renderBundleOgImage, addBundleToCartAction, } from "./_internal/server/features/bundles/index";
|
|
1360
1360
|
export { getGroupsForProduct, getGroupsWithItemsForProduct, getGroupsForCategory, getGroupsForBrand } from "./_internal/server/features/grouped/index";
|
|
1361
1361
|
// Public /groups/{slug} page — data, metadata and OG.
|
|
1362
1362
|
export { getGroupedListingForDetail, getGroupedListingWithItems, buildGroupedListingMetadata, renderGroupedListingOg, } from "./_internal/server/features/grouped/index";
|