orionplace-react 0.7.7 → 0.8.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/README.md +7 -614
- package/bin/orionplace-react.mjs +10 -176
- package/package.json +7 -59
- package/LICENSE +0 -21
- package/runtime/app.d.mts +0 -6
- package/runtime/app.mjs +0 -48
- package/runtime/marketplace.d.mts +0 -129
- package/runtime/marketplace.mjs +0 -905
- package/src/install.mjs +0 -356
- package/src/project-readme.mjs +0 -442
- package/src/service.mjs +0 -186
- package/src/setup.mjs +0 -274
- package/src/sitemap.mjs +0 -93
- package/src/update.mjs +0 -36
- package/src/validation.mjs +0 -27
- package/templates/app/StorefrontShell.tsx +0 -443
- package/templates/app/[[...path]]/page.app.tsx +0 -11
- package/templates/app/_storefront/ActivityPage.tsx +0 -23
- package/templates/app/_storefront/AddressesPage.tsx +0 -29
- package/templates/app/_storefront/AppRoutes.tsx +0 -184
- package/templates/app/_storefront/ArticlePage.tsx +0 -84
- package/templates/app/_storefront/CartPage.tsx +0 -53
- package/templates/app/_storefront/CatalogPage.tsx +0 -37
- package/templates/app/_storefront/CategoryPage.tsx +0 -68
- package/templates/app/_storefront/ContactPage.tsx +0 -32
- package/templates/app/_storefront/HomePage.tsx +0 -140
- package/templates/app/_storefront/JournalPage.tsx +0 -36
- package/templates/app/_storefront/LogoutPage.tsx +0 -91
- package/templates/app/_storefront/ManufacturersPage.tsx +0 -64
- package/templates/app/_storefront/OrdersPage.tsx +0 -129
- package/templates/app/_storefront/PrivacyPage.tsx +0 -15
- package/templates/app/_storefront/ProductPage.tsx +0 -113
- package/templates/app/_storefront/ProfilePage.tsx +0 -75
- package/templates/app/_storefront/PromoPage.tsx +0 -66
- package/templates/app/_storefront/PromocodesPage.tsx +0 -17
- package/templates/app/_storefront/SearchPage.tsx +0 -225
- package/templates/app/_storefront/SellersPage.tsx +0 -166
- package/templates/app/_storefront/StorefrontErrorRoute.tsx +0 -42
- package/templates/app/_storefront/StorefrontPageMetadata.tsx +0 -117
- package/templates/app/_storefront/StorefrontPageStatus.tsx +0 -61
- package/templates/app/_storefront/StorefrontProductStructuredData.tsx +0 -77
- package/templates/app/_storefront/StoresPage.tsx +0 -53
- package/templates/app/_storefront/SubscriptionsPage.tsx +0 -62
- package/templates/app/_storefront/SupportPage.tsx +0 -141
- package/templates/app/_storefront/TariffsPage.tsx +0 -180
- package/templates/app/_storefront/UnsubscribePage.tsx +0 -29
- package/templates/app/_storefront/WalletPage.tsx +0 -78
- package/templates/app/_storefront/WishlistPage.tsx +0 -79
- package/templates/app/_storefront/storefrontRoutes.tsx +0 -769
- package/templates/app/_storefront/useAccountWallet.ts +0 -27
- package/templates/app/_storefront/useBlogComments.ts +0 -389
- package/templates/app/_storefront/useProductSearch.ts +0 -242
- package/templates/app/_storefront/useStorefrontNavigation.ts +0 -36
- package/templates/app/activity/page.tsx +0 -9
- package/templates/app/addresses/page.tsx +0 -9
- package/templates/app/api/[...orionplace]/route.ts +0 -21
- package/templates/app/browse/page.tsx +0 -27
- package/templates/app/cart/page.tsx +0 -9
- package/templates/app/catalog/page.tsx +0 -9
- package/templates/app/category/[id]/page.tsx +0 -9
- package/templates/app/contact/page.tsx +0 -9
- package/templates/app/error.tsx +0 -7
- package/templates/app/featured/page.tsx +0 -9
- package/templates/app/global-error.tsx +0 -61
- package/templates/app/globals.css +0 -58
- package/templates/app/journal/[id]/page.tsx +0 -9
- package/templates/app/journal/page.tsx +0 -9
- package/templates/app/layout.app.tsx +0 -20
- package/templates/app/layout.tsx +0 -66
- package/templates/app/logout/page.tsx +0 -9
- package/templates/app/manufacturers/page.tsx +0 -9
- package/templates/app/not-found.tsx +0 -5
- package/templates/app/orders/page.tsx +0 -9
- package/templates/app/page.module.css +0 -137
- package/templates/app/page.tsx +0 -9
- package/templates/app/privacy/page.tsx +0 -9
- package/templates/app/product/[id]/page.tsx +0 -9
- package/templates/app/profile/page.tsx +0 -9
- package/templates/app/promo/[id]/page.tsx +0 -9
- package/templates/app/promocodes/page.tsx +0 -9
- package/templates/app/ps3/blog/[...orionplace]/route.ts +0 -13
- package/templates/app/robots.txt/route.ts +0 -11
- package/templates/app/sellers/page.tsx +0 -9
- package/templates/app/sitemap.xml/route.ts +0 -12
- package/templates/app/storefront.module.css +0 -406
- package/templates/app/stores/page.tsx +0 -9
- package/templates/app/subscriptions/page.tsx +0 -9
- package/templates/app/tariffs/[slug]/[id]/page.tsx +0 -9
- package/templates/app/tariffs/page.tsx +0 -9
- package/templates/app/tickets/page.tsx +0 -9
- package/templates/app/unsubscribe/page.tsx +0 -9
- package/templates/app/wallet/page.tsx +0 -9
- package/templates/app/wishlist/page.tsx +0 -9
- package/templates/components/orionplace/account/AccountActivity.README.md +0 -70
- package/templates/components/orionplace/account/AccountActivity.module.css +0 -16
- package/templates/components/orionplace/account/AccountActivity.tsx +0 -94
- package/templates/components/orionplace/account/AccountPromocodes.README.md +0 -70
- package/templates/components/orionplace/account/AccountPromocodes.module.css +0 -92
- package/templates/components/orionplace/account/AccountPromocodes.tsx +0 -257
- package/templates/components/orionplace/account/AccountSection.README.md +0 -46
- package/templates/components/orionplace/account/AccountSection.module.css +0 -110
- package/templates/components/orionplace/account/AccountSection.tsx +0 -109
- package/templates/components/orionplace/account/ProfileAvatar.README.md +0 -48
- package/templates/components/orionplace/account/ProfileAvatar.module.css +0 -31
- package/templates/components/orionplace/account/ProfileAvatar.tsx +0 -138
- package/templates/components/orionplace/account/ProfileDeleteAccount.README.md +0 -59
- package/templates/components/orionplace/account/ProfileDeleteAccount.module.css +0 -51
- package/templates/components/orionplace/account/ProfileDeleteAccount.tsx +0 -171
- package/templates/components/orionplace/account/ProfileDetailsForm.README.md +0 -48
- package/templates/components/orionplace/account/ProfileDetailsForm.module.css +0 -35
- package/templates/components/orionplace/account/ProfileDetailsForm.tsx +0 -183
- package/templates/components/orionplace/account/ProfileEmailSettings.README.md +0 -52
- package/templates/components/orionplace/account/ProfileEmailSettings.module.css +0 -51
- package/templates/components/orionplace/account/ProfileEmailSettings.tsx +0 -276
- package/templates/components/orionplace/account/ProfilePasswordForm.README.md +0 -45
- package/templates/components/orionplace/account/ProfilePasswordForm.module.css +0 -43
- package/templates/components/orionplace/account/ProfilePasswordForm.tsx +0 -227
- package/templates/components/orionplace/account/ProfileSignIn.README.md +0 -64
- package/templates/components/orionplace/account/ProfileSignIn.module.css +0 -86
- package/templates/components/orionplace/account/ProfileSignIn.tsx +0 -463
- package/templates/components/orionplace/account/SignInHistory.README.md +0 -52
- package/templates/components/orionplace/account/SignInHistory.module.css +0 -81
- package/templates/components/orionplace/account/SignInHistory.tsx +0 -231
- package/templates/components/orionplace/account/StorefrontLogout.README.md +0 -48
- package/templates/components/orionplace/account/StorefrontLogout.module.css +0 -166
- package/templates/components/orionplace/account/StorefrontLogout.tsx +0 -73
- package/templates/components/orionplace/account/StorefrontProfile.README.md +0 -71
- package/templates/components/orionplace/account/StorefrontProfile.module.css +0 -65
- package/templates/components/orionplace/account/StorefrontProfile.tsx +0 -189
- package/templates/components/orionplace/account/account.module.css +0 -1180
- package/templates/components/orionplace/account/profile.module.css +0 -696
- package/templates/components/orionplace/address/AddressForm.README.md +0 -152
- package/templates/components/orionplace/address/AddressForm.module.css +0 -336
- package/templates/components/orionplace/address/AddressForm.tsx +0 -827
- package/templates/components/orionplace/address/StorefrontAddresses.README.md +0 -99
- package/templates/components/orionplace/address/StorefrontAddresses.module.css +0 -271
- package/templates/components/orionplace/address/StorefrontAddresses.tsx +0 -438
- package/templates/components/orionplace/banners/MainBanner.README.md +0 -65
- package/templates/components/orionplace/banners/MainBanner.module.css +0 -112
- package/templates/components/orionplace/banners/MainBanner.tsx +0 -159
- package/templates/components/orionplace/blog/BlogArticle.README.md +0 -183
- package/templates/components/orionplace/blog/BlogArticle.module.css +0 -333
- package/templates/components/orionplace/blog/BlogArticle.tsx +0 -545
- package/templates/components/orionplace/blog/BlogCommentForm.README.md +0 -51
- package/templates/components/orionplace/blog/BlogCommentForm.module.css +0 -93
- package/templates/components/orionplace/blog/BlogCommentForm.tsx +0 -125
- package/templates/components/orionplace/blog/BlogComments.README.md +0 -98
- package/templates/components/orionplace/blog/BlogComments.module.css +0 -151
- package/templates/components/orionplace/blog/BlogComments.tsx +0 -590
- package/templates/components/orionplace/blog/BlogPostCard.README.md +0 -51
- package/templates/components/orionplace/blog/BlogPostCard.module.css +0 -167
- package/templates/components/orionplace/blog/BlogPostCard.tsx +0 -177
- package/templates/components/orionplace/blog/BlogPostGroup.README.md +0 -49
- package/templates/components/orionplace/blog/BlogPostGroup.module.css +0 -37
- package/templates/components/orionplace/blog/BlogPostGroup.tsx +0 -129
- package/templates/components/orionplace/blog/StorefrontJournal.README.md +0 -105
- package/templates/components/orionplace/blog/StorefrontJournal.module.css +0 -387
- package/templates/components/orionplace/blog/StorefrontJournal.tsx +0 -549
- package/templates/components/orionplace/branding/BrandLogos.README.md +0 -29
- package/templates/components/orionplace/branding/BrandLogos.module.css +0 -7
- package/templates/components/orionplace/branding/BrandLogos.tsx +0 -30
- package/templates/components/orionplace/cart/CartCheckoutDetails.README.md +0 -96
- package/templates/components/orionplace/cart/CartCheckoutDetails.module.css +0 -159
- package/templates/components/orionplace/cart/CartCheckoutDetails.tsx +0 -381
- package/templates/components/orionplace/cart/CartDeliverySelector.README.md +0 -166
- package/templates/components/orionplace/cart/CartDeliverySelector.module.css +0 -105
- package/templates/components/orionplace/cart/CartDeliverySelector.tsx +0 -679
- package/templates/components/orionplace/cart/CartItemOptions.README.md +0 -172
- package/templates/components/orionplace/cart/CartItemOptions.module.css +0 -113
- package/templates/components/orionplace/cart/CartItemOptions.tsx +0 -503
- package/templates/components/orionplace/cart/CartLineItem.README.md +0 -138
- package/templates/components/orionplace/cart/CartLineItem.module.css +0 -57
- package/templates/components/orionplace/cart/CartLineItem.tsx +0 -263
- package/templates/components/orionplace/cart/CartPreview.README.md +0 -99
- package/templates/components/orionplace/cart/CartPreview.module.css +0 -225
- package/templates/components/orionplace/cart/CartPreview.tsx +0 -188
- package/templates/components/orionplace/cart/DeliveryMap.README.md +0 -65
- package/templates/components/orionplace/cart/DeliveryMap.module.css +0 -32
- package/templates/components/orionplace/cart/DeliveryMap.tsx +0 -131
- package/templates/components/orionplace/cart/StorefrontCart.README.md +0 -281
- package/templates/components/orionplace/cart/StorefrontCart.module.css +0 -460
- package/templates/components/orionplace/cart/StorefrontCart.tsx +0 -937
- package/templates/components/orionplace/catalog/CatalogHeader.README.md +0 -136
- package/templates/components/orionplace/catalog/CatalogHeader.module.css +0 -387
- package/templates/components/orionplace/catalog/CatalogHeader.tsx +0 -644
- package/templates/components/orionplace/catalog/CatalogRepresentative.README.md +0 -68
- package/templates/components/orionplace/catalog/CatalogRepresentative.tsx +0 -51
- package/templates/components/orionplace/catalog/StorefrontCatalog.README.md +0 -120
- package/templates/components/orionplace/catalog/StorefrontCatalog.module.css +0 -179
- package/templates/components/orionplace/catalog/StorefrontCatalog.tsx +0 -304
- package/templates/components/orionplace/categories/CategoryGroup.README.md +0 -68
- package/templates/components/orionplace/categories/CategoryGroup.module.css +0 -110
- package/templates/components/orionplace/categories/CategoryGroup.tsx +0 -123
- package/templates/components/orionplace/categories/StorefrontCategory.README.md +0 -155
- package/templates/components/orionplace/categories/StorefrontCategory.module.css +0 -148
- package/templates/components/orionplace/categories/StorefrontCategory.tsx +0 -225
- package/templates/components/orionplace/contact/AboutPage.README.md +0 -40
- package/templates/components/orionplace/contact/AboutPage.module.css +0 -216
- package/templates/components/orionplace/contact/AboutPage.tsx +0 -191
- package/templates/components/orionplace/contact/ContactForm.README.md +0 -93
- package/templates/components/orionplace/contact/ContactForm.module.css +0 -264
- package/templates/components/orionplace/contact/ContactForm.tsx +0 -382
- package/templates/components/orionplace/contact/EmailUnsubscribe.README.md +0 -67
- package/templates/components/orionplace/contact/EmailUnsubscribe.module.css +0 -95
- package/templates/components/orionplace/contact/EmailUnsubscribe.tsx +0 -130
- package/templates/components/orionplace/contact/StorefrontContact.README.md +0 -73
- package/templates/components/orionplace/contact/StorefrontContact.module.css +0 -101
- package/templates/components/orionplace/contact/StorefrontContact.tsx +0 -62
- package/templates/components/orionplace/currencies/MainCurrencySwitcher.README.md +0 -37
- package/templates/components/orionplace/currencies/MainCurrencySwitcher.tsx +0 -68
- package/templates/components/orionplace/events/EventEnrollmentDialog.README.md +0 -108
- package/templates/components/orionplace/events/EventEnrollmentDialog.module.css +0 -110
- package/templates/components/orionplace/events/EventEnrollmentDialog.tsx +0 -315
- package/templates/components/orionplace/events/EventsBlock.README.md +0 -58
- package/templates/components/orionplace/events/EventsBlock.module.css +0 -101
- package/templates/components/orionplace/events/EventsBlock.tsx +0 -109
- package/templates/components/orionplace/legal/CookieNotice.README.md +0 -42
- package/templates/components/orionplace/legal/CookieNotice.module.css +0 -48
- package/templates/components/orionplace/legal/CookieNotice.tsx +0 -82
- package/templates/components/orionplace/legal/StorefrontPrivacy.README.md +0 -49
- package/templates/components/orionplace/legal/StorefrontPrivacy.module.css +0 -166
- package/templates/components/orionplace/legal/StorefrontPrivacy.tsx +0 -83
- package/templates/components/orionplace/locale/MainLanguageSwitcher.README.md +0 -46
- package/templates/components/orionplace/locale/MainLanguageSwitcher.module.css +0 -196
- package/templates/components/orionplace/locale/MainLanguageSwitcher.tsx +0 -387
- package/templates/components/orionplace/manufacturers/ManufacturerIndex.README.md +0 -83
- package/templates/components/orionplace/manufacturers/ManufacturerIndex.module.css +0 -271
- package/templates/components/orionplace/manufacturers/ManufacturerIndex.tsx +0 -218
- package/templates/components/orionplace/manufacturers/StorefrontManufacturers.README.md +0 -122
- package/templates/components/orionplace/manufacturers/StorefrontManufacturers.module.css +0 -92
- package/templates/components/orionplace/manufacturers/StorefrontManufacturers.tsx +0 -455
- package/templates/components/orionplace/orders/OrderDetails.README.md +0 -116
- package/templates/components/orionplace/orders/OrderDetails.module.css +0 -730
- package/templates/components/orionplace/orders/OrderDetails.tsx +0 -693
- package/templates/components/orionplace/orders/OrderPaymentForm.README.md +0 -92
- package/templates/components/orionplace/orders/OrderPaymentForm.module.css +0 -105
- package/templates/components/orionplace/orders/OrderPaymentForm.tsx +0 -90
- package/templates/components/orionplace/orders/StorefrontOrders.README.md +0 -131
- package/templates/components/orionplace/orders/StorefrontOrders.module.css +0 -633
- package/templates/components/orionplace/orders/StorefrontOrders.tsx +0 -922
- package/templates/components/orionplace/payments/PaymentPanel.README.md +0 -114
- package/templates/components/orionplace/payments/PaymentPanel.module.css +0 -134
- package/templates/components/orionplace/payments/PaymentPanel.tsx +0 -76
- package/templates/components/orionplace/products/HoverImageViewer.README.md +0 -62
- package/templates/components/orionplace/products/HoverImageViewer.module.css +0 -88
- package/templates/components/orionplace/products/HoverImageViewer.tsx +0 -179
- package/templates/components/orionplace/products/ProductCard.README.md +0 -154
- package/templates/components/orionplace/products/ProductCard.module.css +0 -333
- package/templates/components/orionplace/products/ProductCard.tsx +0 -730
- package/templates/components/orionplace/products/ProductCardActions.README.md +0 -84
- package/templates/components/orionplace/products/ProductCardActions.module.css +0 -146
- package/templates/components/orionplace/products/ProductCardActions.tsx +0 -311
- package/templates/components/orionplace/products/ProductCardBadges.README.md +0 -44
- package/templates/components/orionplace/products/ProductCardBadges.module.css +0 -15
- package/templates/components/orionplace/products/ProductCardBadges.tsx +0 -78
- package/templates/components/orionplace/products/ProductCardDescription.README.md +0 -33
- package/templates/components/orionplace/products/ProductCardDescription.module.css +0 -6
- package/templates/components/orionplace/products/ProductCardDescription.tsx +0 -43
- package/templates/components/orionplace/products/ProductCardFavorite.README.md +0 -52
- package/templates/components/orionplace/products/ProductCardFavorite.module.css +0 -64
- package/templates/components/orionplace/products/ProductCardFavorite.tsx +0 -90
- package/templates/components/orionplace/products/ProductCardPrice.README.md +0 -33
- package/templates/components/orionplace/products/ProductCardPrice.module.css +0 -22
- package/templates/components/orionplace/products/ProductCardPrice.tsx +0 -50
- package/templates/components/orionplace/products/ProductCardRating.README.md +0 -33
- package/templates/components/orionplace/products/ProductCardRating.module.css +0 -7
- package/templates/components/orionplace/products/ProductCardRating.tsx +0 -56
- package/templates/components/orionplace/products/ProductCardSeller.README.md +0 -36
- package/templates/components/orionplace/products/ProductCardSeller.module.css +0 -31
- package/templates/components/orionplace/products/ProductCardSeller.tsx +0 -61
- package/templates/components/orionplace/products/ProductCardStockNotice.README.md +0 -36
- package/templates/components/orionplace/products/ProductCardStockNotice.module.css +0 -8
- package/templates/components/orionplace/products/ProductCardStockNotice.tsx +0 -35
- package/templates/components/orionplace/products/ProductCardTitle.README.md +0 -30
- package/templates/components/orionplace/products/ProductCardTitle.module.css +0 -13
- package/templates/components/orionplace/products/ProductCardTitle.tsx +0 -31
- package/templates/components/orionplace/products/ProductCardVariants.README.md +0 -77
- package/templates/components/orionplace/products/ProductCardVariants.module.css +0 -97
- package/templates/components/orionplace/products/ProductCardVariants.tsx +0 -350
- package/templates/components/orionplace/products/ProductGroup.README.md +0 -91
- package/templates/components/orionplace/products/ProductGroup.module.css +0 -64
- package/templates/components/orionplace/products/ProductGroup.tsx +0 -186
- package/templates/components/orionplace/products/ProductPreorderDialog.README.md +0 -89
- package/templates/components/orionplace/products/ProductPreorderDialog.module.css +0 -320
- package/templates/components/orionplace/products/ProductPreorderDialog.tsx +0 -346
- package/templates/components/orionplace/products/ProductReviewForm.README.md +0 -72
- package/templates/components/orionplace/products/ProductReviewForm.module.css +0 -217
- package/templates/components/orionplace/products/ProductReviewForm.tsx +0 -288
- package/templates/components/orionplace/products/ProductReviewGallery.README.md +0 -61
- package/templates/components/orionplace/products/ProductReviewGallery.module.css +0 -108
- package/templates/components/orionplace/products/ProductReviewGallery.tsx +0 -110
- package/templates/components/orionplace/products/ProductReviewImageViewer.README.md +0 -60
- package/templates/components/orionplace/products/ProductReviewImageViewer.module.css +0 -59
- package/templates/components/orionplace/products/ProductReviewImageViewer.tsx +0 -312
- package/templates/components/orionplace/products/ProductReviews.README.md +0 -137
- package/templates/components/orionplace/products/ProductReviews.module.css +0 -602
- package/templates/components/orionplace/products/ProductReviews.tsx +0 -944
- package/templates/components/orionplace/products/ProductSecondaryVariantModal.README.md +0 -67
- package/templates/components/orionplace/products/ProductSecondaryVariantModal.module.css +0 -79
- package/templates/components/orionplace/products/ProductSecondaryVariantModal.tsx +0 -324
- package/templates/components/orionplace/products/ProductSpecificationsDialog.README.md +0 -52
- package/templates/components/orionplace/products/ProductSpecificationsDialog.module.css +0 -138
- package/templates/components/orionplace/products/ProductSpecificationsDialog.tsx +0 -117
- package/templates/components/orionplace/products/StorefrontProduct.README.md +0 -200
- package/templates/components/orionplace/products/StorefrontProduct.module.css +0 -767
- package/templates/components/orionplace/products/StorefrontProduct.tsx +0 -1339
- package/templates/components/orionplace/products/StorefrontWishlist.README.md +0 -162
- package/templates/components/orionplace/products/StorefrontWishlist.module.css +0 -71
- package/templates/components/orionplace/products/StorefrontWishlist.tsx +0 -402
- package/templates/components/orionplace/promo/PromoProducts.README.md +0 -133
- package/templates/components/orionplace/promo/PromoProducts.module.css +0 -68
- package/templates/components/orionplace/promo/PromoProducts.tsx +0 -345
- package/templates/components/orionplace/search/MainSearch.README.md +0 -73
- package/templates/components/orionplace/search/MainSearch.module.css +0 -202
- package/templates/components/orionplace/search/MainSearch.tsx +0 -217
- package/templates/components/orionplace/search/ProductSearchResults.README.md +0 -166
- package/templates/components/orionplace/search/ProductSearchResults.module.css +0 -361
- package/templates/components/orionplace/search/ProductSearchResults.tsx +0 -359
- package/templates/components/orionplace/search/SearchFilters.README.md +0 -109
- package/templates/components/orionplace/search/SearchFilters.module.css +0 -274
- package/templates/components/orionplace/search/SearchFilters.tsx +0 -439
- package/templates/components/orionplace/sellers/SellerFilters.README.md +0 -66
- package/templates/components/orionplace/sellers/SellerFilters.module.css +0 -232
- package/templates/components/orionplace/sellers/SellerFilters.tsx +0 -201
- package/templates/components/orionplace/sellers/SellerPhotoGallery.README.md +0 -72
- package/templates/components/orionplace/sellers/SellerPhotoGallery.module.css +0 -314
- package/templates/components/orionplace/sellers/SellerPhotoGallery.tsx +0 -335
- package/templates/components/orionplace/sellers/SellerSummary.README.md +0 -62
- package/templates/components/orionplace/sellers/SellerSummary.module.css +0 -182
- package/templates/components/orionplace/sellers/SellerSummary.tsx +0 -107
- package/templates/components/orionplace/sellers/StorefrontSellers.README.md +0 -120
- package/templates/components/orionplace/sellers/StorefrontSellers.module.css +0 -147
- package/templates/components/orionplace/sellers/StorefrontSellers.tsx +0 -360
- package/templates/components/orionplace/shared/OrionplaceAvatar.README.md +0 -35
- package/templates/components/orionplace/shared/OrionplaceAvatar.module.css +0 -35
- package/templates/components/orionplace/shared/OrionplaceAvatar.tsx +0 -61
- package/templates/components/orionplace/shared/OrionplaceBreadcrumbs.README.md +0 -33
- package/templates/components/orionplace/shared/OrionplaceBreadcrumbs.module.css +0 -81
- package/templates/components/orionplace/shared/OrionplaceBreadcrumbs.tsx +0 -91
- package/templates/components/orionplace/shared/OrionplaceEmptyState.README.md +0 -37
- package/templates/components/orionplace/shared/OrionplaceEmptyState.module.css +0 -126
- package/templates/components/orionplace/shared/OrionplaceEmptyState.tsx +0 -78
- package/templates/components/orionplace/shared/OrionplaceImage.README.md +0 -45
- package/templates/components/orionplace/shared/OrionplaceImage.module.css +0 -22
- package/templates/components/orionplace/shared/OrionplaceImage.tsx +0 -97
- package/templates/components/orionplace/shared/OrionplaceInfoHint.README.md +0 -31
- package/templates/components/orionplace/shared/OrionplaceInfoHint.module.css +0 -59
- package/templates/components/orionplace/shared/OrionplaceInfoHint.tsx +0 -126
- package/templates/components/orionplace/shared/OrionplacePasswordInput.README.md +0 -39
- package/templates/components/orionplace/shared/OrionplacePasswordInput.module.css +0 -79
- package/templates/components/orionplace/shared/OrionplacePasswordInput.tsx +0 -103
- package/templates/components/orionplace/shared/OrionplaceSearchSelect.README.md +0 -97
- package/templates/components/orionplace/shared/OrionplaceSearchSelect.module.css +0 -246
- package/templates/components/orionplace/shared/OrionplaceSearchSelect.tsx +0 -367
- package/templates/components/orionplace/shared/OrionplaceSelect.README.md +0 -69
- package/templates/components/orionplace/shared/OrionplaceSelect.module.css +0 -233
- package/templates/components/orionplace/shared/OrionplaceSelect.tsx +0 -439
- package/templates/components/orionplace/shared/StorefrontErrorPage.README.md +0 -52
- package/templates/components/orionplace/shared/StorefrontErrorPage.module.css +0 -141
- package/templates/components/orionplace/shared/StorefrontErrorPage.tsx +0 -103
- package/templates/components/orionplace/shared/StorefrontPagination.README.md +0 -45
- package/templates/components/orionplace/shared/StorefrontPagination.module.css +0 -69
- package/templates/components/orionplace/shared/StorefrontPagination.tsx +0 -158
- package/templates/components/orionplace/shared/dialogs.css +0 -36
- package/templates/components/orionplace/shared/emptyStateArt.ts +0 -231
- package/templates/components/orionplace/shared/features.module.css +0 -162
- package/templates/components/orionplace/social/SocialLinks.README.md +0 -16
- package/templates/components/orionplace/social/SocialLinks.module.css +0 -36
- package/templates/components/orionplace/social/SocialLinks.tsx +0 -59
- package/templates/components/orionplace/storefront/StorefrontAccount.README.md +0 -59
- package/templates/components/orionplace/storefront/StorefrontAccount.module.css +0 -159
- package/templates/components/orionplace/storefront/StorefrontAccount.tsx +0 -303
- package/templates/components/orionplace/storefront/StorefrontCartButton.README.md +0 -47
- package/templates/components/orionplace/storefront/StorefrontCartButton.module.css +0 -88
- package/templates/components/orionplace/storefront/StorefrontCartButton.tsx +0 -54
- package/templates/components/orionplace/storefront/StorefrontFooter.README.md +0 -55
- package/templates/components/orionplace/storefront/StorefrontFooter.module.css +0 -118
- package/templates/components/orionplace/storefront/StorefrontFooter.tsx +0 -168
- package/templates/components/orionplace/storefront/StorefrontHeader.README.md +0 -150
- package/templates/components/orionplace/storefront/StorefrontHeader.module.css +0 -186
- package/templates/components/orionplace/storefront/StorefrontHeader.tsx +0 -389
- package/templates/components/orionplace/storefront/StorefrontHome.README.md +0 -138
- package/templates/components/orionplace/storefront/StorefrontHome.module.css +0 -116
- package/templates/components/orionplace/storefront/StorefrontHome.tsx +0 -282
- package/templates/components/orionplace/storefront/StorefrontWishlistButton.README.md +0 -51
- package/templates/components/orionplace/storefront/StorefrontWishlistButton.module.css +0 -95
- package/templates/components/orionplace/storefront/StorefrontWishlistButton.tsx +0 -80
- package/templates/components/orionplace/stores/StorefrontStores.README.md +0 -87
- package/templates/components/orionplace/stores/StorefrontStores.module.css +0 -218
- package/templates/components/orionplace/stores/StorefrontStores.tsx +0 -397
- package/templates/components/orionplace/subscriptions/StorefrontSubscriptions.README.md +0 -183
- package/templates/components/orionplace/subscriptions/StorefrontSubscriptions.module.css +0 -347
- package/templates/components/orionplace/subscriptions/StorefrontSubscriptions.tsx +0 -884
- package/templates/components/orionplace/subscriptions/StorefrontTariff.README.md +0 -124
- package/templates/components/orionplace/subscriptions/StorefrontTariff.module.css +0 -311
- package/templates/components/orionplace/subscriptions/StorefrontTariff.tsx +0 -485
- package/templates/components/orionplace/subscriptions/StorefrontTariffs.README.md +0 -115
- package/templates/components/orionplace/subscriptions/StorefrontTariffs.module.css +0 -219
- package/templates/components/orionplace/subscriptions/StorefrontTariffs.tsx +0 -367
- package/templates/components/orionplace/subscriptions/SubscriptionCancelDialog.README.md +0 -67
- package/templates/components/orionplace/subscriptions/SubscriptionCancelDialog.tsx +0 -175
- package/templates/components/orionplace/subscriptions/SubscriptionChangeDialog.README.md +0 -95
- package/templates/components/orionplace/subscriptions/SubscriptionChangeDialog.tsx +0 -634
- package/templates/components/orionplace/subscriptions/SubscriptionDialog.module.css +0 -453
- package/templates/components/orionplace/subscriptions/SubscriptionExtendDialog.README.md +0 -75
- package/templates/components/orionplace/subscriptions/SubscriptionExtendDialog.tsx +0 -384
- package/templates/components/orionplace/subscriptions/SubscriptionPlanSummary.README.md +0 -116
- package/templates/components/orionplace/subscriptions/SubscriptionPlanSummary.module.css +0 -168
- package/templates/components/orionplace/subscriptions/SubscriptionPlanSummary.tsx +0 -236
- package/templates/components/orionplace/subscriptions/SubscriptionRemoteDetails.README.md +0 -123
- package/templates/components/orionplace/subscriptions/SubscriptionRemoteDetails.module.css +0 -57
- package/templates/components/orionplace/subscriptions/SubscriptionRemoteDetails.tsx +0 -101
- package/templates/components/orionplace/subscriptions/SubscriptionRenewalDialog.README.md +0 -109
- package/templates/components/orionplace/subscriptions/SubscriptionRenewalDialog.tsx +0 -253
- package/templates/components/orionplace/support/StorefrontSupport.README.md +0 -157
- package/templates/components/orionplace/support/StorefrontSupport.tsx +0 -1040
- package/templates/components/orionplace/support/Support.module.css +0 -1133
- package/templates/components/orionplace/support/TicketConversation.README.md +0 -105
- package/templates/components/orionplace/support/TicketConversation.tsx +0 -502
- package/templates/components/orionplace/support/TicketImage.README.md +0 -52
- package/templates/components/orionplace/support/TicketImage.tsx +0 -254
- package/templates/components/orionplace/support/TicketItemCard.README.md +0 -66
- package/templates/components/orionplace/support/TicketItemCard.tsx +0 -140
- package/templates/components/orionplace/support/TicketMessageForm.README.md +0 -88
- package/templates/components/orionplace/support/TicketMessageForm.tsx +0 -261
- package/templates/components/orionplace/support/TicketSubscriptionCard.README.md +0 -53
- package/templates/components/orionplace/support/TicketSubscriptionCard.tsx +0 -118
- package/templates/components/orionplace/tariffs/TariffCard.README.md +0 -108
- package/templates/components/orionplace/tariffs/TariffCard.module.css +0 -86
- package/templates/components/orionplace/tariffs/TariffCard.tsx +0 -225
- package/templates/components/orionplace/tariffs/TariffCardDescription.README.md +0 -40
- package/templates/components/orionplace/tariffs/TariffCardDescription.module.css +0 -72
- package/templates/components/orionplace/tariffs/TariffCardDescription.tsx +0 -58
- package/templates/components/orionplace/tariffs/TariffCardFeatures.README.md +0 -58
- package/templates/components/orionplace/tariffs/TariffCardFeatures.module.css +0 -60
- package/templates/components/orionplace/tariffs/TariffCardFeatures.tsx +0 -140
- package/templates/components/orionplace/tariffs/TariffCardImage.README.md +0 -36
- package/templates/components/orionplace/tariffs/TariffCardImage.module.css +0 -8
- package/templates/components/orionplace/tariffs/TariffCardImage.tsx +0 -32
- package/templates/components/orionplace/tariffs/TariffCardPrices.README.md +0 -82
- package/templates/components/orionplace/tariffs/TariffCardPrices.module.css +0 -142
- package/templates/components/orionplace/tariffs/TariffCardPrices.tsx +0 -191
- package/templates/components/orionplace/tariffs/TariffCardTitle.README.md +0 -32
- package/templates/components/orionplace/tariffs/TariffCardTitle.module.css +0 -9
- package/templates/components/orionplace/tariffs/TariffCardTitle.tsx +0 -29
- package/templates/components/orionplace/tariffs/TariffCards.README.md +0 -88
- package/templates/components/orionplace/tariffs/TariffCards.module.css +0 -24
- package/templates/components/orionplace/tariffs/TariffCards.tsx +0 -44
- package/templates/components/orionplace/tariffs/TariffSubscriptionModal.README.md +0 -92
- package/templates/components/orionplace/tariffs/TariffSubscriptionModal.module.css +0 -214
- package/templates/components/orionplace/tariffs/TariffSubscriptionModal.tsx +0 -299
- package/templates/components/orionplace/theme/OrionplaceThemeProvider.README.md +0 -30
- package/templates/components/orionplace/theme/OrionplaceThemeProvider.module.css +0 -8
- package/templates/components/orionplace/theme/OrionplaceThemeProvider.tsx +0 -32
- package/templates/components/orionplace/units/UnitSwitcher.README.md +0 -35
- package/templates/components/orionplace/units/UnitSwitcher.tsx +0 -58
- package/templates/components/orionplace/wallet/StorefrontWallet.README.md +0 -154
- package/templates/components/orionplace/wallet/StorefrontWallet.module.css +0 -507
- package/templates/components/orionplace/wallet/StorefrontWallet.tsx +0 -915
- package/templates/components/orionplace/wallet/WalletBalance.README.md +0 -46
- package/templates/components/orionplace/wallet/WalletBalance.module.css +0 -46
- package/templates/components/orionplace/wallet/WalletBalance.tsx +0 -51
- package/templates/components/orionplace/wallet/WalletTopUpForm.README.md +0 -54
- package/templates/components/orionplace/wallet/WalletTopUpForm.module.css +0 -152
- package/templates/components/orionplace/wallet/WalletTopUpForm.tsx +0 -181
- package/templates/hooks/useAccountActivity.ts +0 -251
- package/templates/hooks/useAccountAddresses.ts +0 -81
- package/templates/hooks/useAccountPromocodes.ts +0 -91
- package/templates/hooks/useOrionplaceActionMenu.ts +0 -118
- package/templates/hooks/useOrionplaceAddressForm.ts +0 -262
- package/templates/hooks/useOrionplaceApi.ts +0 -98
- package/templates/hooks/useOrionplaceAppLoad.ts +0 -66
- package/templates/hooks/useOrionplaceBlogReading.ts +0 -351
- package/templates/hooks/useOrionplaceDialog.ts +0 -85
- package/templates/hooks/useOrionplaceHomeProducts.ts +0 -97
- package/templates/hooks/useOrionplaceMap.tsx +0 -230
- package/templates/hooks/useOrionplaceMediaFormat.ts +0 -33
- package/templates/hooks/useOrionplaceProduct.ts +0 -28
- package/templates/hooks/useOrionplaceProfile.ts +0 -347
- package/templates/hooks/useOrionplaceReviews.ts +0 -352
- package/templates/hooks/useOrionplaceStableHeight.ts +0 -65
- package/templates/hooks/useOrionplaceStorefront.tsx +0 -575
- package/templates/hooks/useOrionplaceTariffPurchase.ts +0 -212
- package/templates/interfaces/orionplace/accounts/IContact.ts +0 -21
- package/templates/interfaces/orionplace/accounts/IEmailNotificationLocale.ts +0 -17
- package/templates/interfaces/orionplace/accounts/IEmailVerification.ts +0 -59
- package/templates/interfaces/orionplace/accounts/IProfileActions.ts +0 -38
- package/templates/interfaces/orionplace/accounts/IProfileData.ts +0 -125
- package/templates/interfaces/orionplace/accounts/IProfileMedia.ts +0 -17
- package/templates/interfaces/orionplace/accounts/IStorefrontProfile.ts +0 -54
- package/templates/interfaces/orionplace/address/IAddressCitySuggestion.ts +0 -19
- package/templates/interfaces/orionplace/address/IAddressEditor.ts +0 -9
- package/templates/interfaces/orionplace/address/IAddressLocationSuggestion.ts +0 -22
- package/templates/interfaces/orionplace/address/IAddressRegionSearch.ts +0 -30
- package/templates/interfaces/orionplace/address/IAddressSuggestion.ts +0 -20
- package/templates/interfaces/orionplace/address/IUserAddress.ts +0 -87
- package/templates/interfaces/orionplace/apiBase/TMethod.ts +0 -1
- package/templates/interfaces/orionplace/appBase/IAppLoad.ts +0 -16
- package/templates/interfaces/orionplace/appBase/IAppLoadCommon.ts +0 -47
- package/templates/interfaces/orionplace/appBase/IApploadUserProfile.ts +0 -15
- package/templates/interfaces/orionplace/appBase/IForm.ts +0 -21
- package/templates/interfaces/orionplace/appBase/ISEO.ts +0 -21
- package/templates/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonBanner.ts +0 -11
- package/templates/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonContact.ts +0 -8
- package/templates/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonCurrency.ts +0 -15
- package/templates/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonEvents.ts +0 -18
- package/templates/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonLocale.ts +0 -14
- package/templates/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonLogos.ts +0 -6
- package/templates/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonPath.ts +0 -22
- package/templates/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonSEO.ts +0 -26
- package/templates/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonSocial.ts +0 -15
- package/templates/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonTariff.ts +0 -7
- package/templates/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonUnit.ts +0 -12
- package/templates/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonVariables.ts +0 -8
- package/templates/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonVisualSettings.ts +0 -11
- package/templates/interfaces/orionplace/appBase/appLoadCommon/IAppLoadCommonWalletValue.ts +0 -3
- package/templates/interfaces/orionplace/blog/IBlogApi.ts +0 -247
- package/templates/interfaces/orionplace/blog/IBlogPostPreview.ts +0 -30
- package/templates/interfaces/orionplace/cart/ICartActions.ts +0 -67
- package/templates/interfaces/orionplace/cart/ICartData.ts +0 -382
- package/templates/interfaces/orionplace/cart/ICartDeliveryActions.ts +0 -68
- package/templates/interfaces/orionplace/cart/ICartModal.ts +0 -22
- package/templates/interfaces/orionplace/cart/IDeliveryMap.ts +0 -29
- package/templates/interfaces/orionplace/catalog/ICatalogDirectory.ts +0 -75
- package/templates/interfaces/orionplace/category/ICategory.ts +0 -41
- package/templates/interfaces/orionplace/domains/IDomain.ts +0 -13
- package/templates/interfaces/orionplace/forms/ICustomerSubfilter.ts +0 -19
- package/templates/interfaces/orionplace/index.ts +0 -64
- package/templates/interfaces/orionplace/marketing/IPromoActions.ts +0 -51
- package/templates/interfaces/orionplace/orders/IOrderActions.ts +0 -99
- package/templates/interfaces/orionplace/orders/IOrderHistory.ts +0 -259
- package/templates/interfaces/orionplace/orders/IProductPreorder.ts +0 -31
- package/templates/interfaces/orionplace/payments/IInvoice.ts +0 -147
- package/templates/interfaces/orionplace/products/IProduct.ts +0 -262
- package/templates/interfaces/orionplace/products/IProductFeedbackApi.ts +0 -218
- package/templates/interfaces/orionplace/products/IProductSearchApi.ts +0 -146
- package/templates/interfaces/orionplace/products/IProductSearchFacets.ts +0 -35
- package/templates/interfaces/orionplace/products/IProductSecondaryVariantRequest.ts +0 -15
- package/templates/interfaces/orionplace/products/IProductSpecification.ts +0 -14
- package/templates/interfaces/orionplace/products/IWishlist.ts +0 -22
- package/templates/interfaces/orionplace/sellers/ISellerDirectory.ts +0 -70
- package/templates/interfaces/orionplace/shared/IBreadcrumb.ts +0 -10
- package/templates/interfaces/orionplace/shared/IGeoCoordinates.ts +0 -4
- package/templates/interfaces/orionplace/shared/IStorefrontControls.ts +0 -6
- package/templates/interfaces/orionplace/shared/ITransformValue.ts +0 -3
- package/templates/interfaces/orionplace/state.ts +0 -4
- package/templates/interfaces/orionplace/stores/IStoreDirectory.ts +0 -63
- package/templates/interfaces/orionplace/subscribeOptions/ISubscribeOption.ts +0 -9
- package/templates/interfaces/orionplace/subscribeTariff/ISubscribeTariff.ts +0 -56
- package/templates/interfaces/orionplace/subscribeTariff/ITariffSelection.ts +0 -11
- package/templates/interfaces/orionplace/subscribes/ISubscribe.ts +0 -28
- package/templates/interfaces/orionplace/subscribes/ISubscriptionApi.ts +0 -127
- package/templates/interfaces/orionplace/tickets/ICustomerTicketApi.ts +0 -223
- package/templates/interfaces/orionplace/transport.ts +0 -34
- package/templates/lib/orionplace/accountLabels.ts +0 -29
- package/templates/lib/orionplace/activityLabels.ts +0 -96
- package/templates/lib/orionplace/activityPresentation.ts +0 -9
- package/templates/lib/orionplace/addressChanges.ts +0 -26
- package/templates/lib/orionplace/addressPresentation.ts +0 -58
- package/templates/lib/orionplace/api.ts +0 -326
- package/templates/lib/orionplace/appLoadClient.ts +0 -80
- package/templates/lib/orionplace/appLoadResult.ts +0 -120
- package/templates/lib/orionplace/appLoadServer.ts +0 -183
- package/templates/lib/orionplace/blogArticle.ts +0 -122
- package/templates/lib/orionplace/blogArticleHtml.ts +0 -371
- package/templates/lib/orionplace/blogComments.ts +0 -102
- package/templates/lib/orionplace/blogImageViewer.ts +0 -84
- package/templates/lib/orionplace/blogJournal.ts +0 -128
- package/templates/lib/orionplace/blogLabels.ts +0 -158
- package/templates/lib/orionplace/blogPresentation.ts +0 -67
- package/templates/lib/orionplace/blogProductPlacements.ts +0 -105
- package/templates/lib/orionplace/browseLabels.ts +0 -145
- package/templates/lib/orionplace/cartAddress.ts +0 -86
- package/templates/lib/orionplace/cartController.ts +0 -104
- package/templates/lib/orionplace/cartLabels.ts +0 -390
- package/templates/lib/orionplace/cartOptions.ts +0 -115
- package/templates/lib/orionplace/cartPreview.ts +0 -135
- package/templates/lib/orionplace/cartPromo.ts +0 -150
- package/templates/lib/orionplace/cartShipment.ts +0 -61
- package/templates/lib/orionplace/cartSnapshot.ts +0 -21
- package/templates/lib/orionplace/catalog.ts +0 -150
- package/templates/lib/orionplace/categoryLabels.ts +0 -29
- package/templates/lib/orionplace/contact.ts +0 -47
- package/templates/lib/orionplace/contactLabels.ts +0 -152
- package/templates/lib/orionplace/currency.ts +0 -128
- package/templates/lib/orionplace/deliveryMap.ts +0 -86
- package/templates/lib/orionplace/directoryLabels.ts +0 -198
- package/templates/lib/orionplace/domain.ts +0 -21
- package/templates/lib/orionplace/errorPageLabels.ts +0 -89
- package/templates/lib/orionplace/eventEnrollment.ts +0 -22
- package/templates/lib/orionplace/featureData.ts +0 -28
- package/templates/lib/orionplace/featureLabels.ts +0 -406
- package/templates/lib/orionplace/featuredLabels.ts +0 -38
- package/templates/lib/orionplace/footerLabels.ts +0 -53
- package/templates/lib/orionplace/guestSession.ts +0 -55
- package/templates/lib/orionplace/headerLabels.ts +0 -98
- package/templates/lib/orionplace/homeContent.ts +0 -193
- package/templates/lib/orionplace/homeLabels.ts +0 -74
- package/templates/lib/orionplace/htmlText.ts +0 -51
- package/templates/lib/orionplace/manufacturerDirectory.ts +0 -71
- package/templates/lib/orionplace/manufacturerIndex.ts +0 -107
- package/templates/lib/orionplace/modalWindow.ts +0 -109
- package/templates/lib/orionplace/nativeApp.ts +0 -365
- package/templates/lib/orionplace/navigation.tsx +0 -121
- package/templates/lib/orionplace/notice.ts +0 -22
- package/templates/lib/orionplace/orderLabels.ts +0 -458
- package/templates/lib/orionplace/orderPresentation.ts +0 -574
- package/templates/lib/orionplace/pageMetadata.ts +0 -361
- package/templates/lib/orionplace/pageSeo.ts +0 -662
- package/templates/lib/orionplace/paginationScroll.ts +0 -131
- package/templates/lib/orionplace/phone.ts +0 -22
- package/templates/lib/orionplace/presentation.ts +0 -84
- package/templates/lib/orionplace/privacyLabels.ts +0 -273
- package/templates/lib/orionplace/productActionLabels.ts +0 -87
- package/templates/lib/orionplace/productAvailability.ts +0 -30
- package/templates/lib/orionplace/productGallery.ts +0 -64
- package/templates/lib/orionplace/productLabels.ts +0 -119
- package/templates/lib/orionplace/productListLocation.ts +0 -130
- package/templates/lib/orionplace/productPage.ts +0 -308
- package/templates/lib/orionplace/productPhotos.ts +0 -67
- package/templates/lib/orionplace/productSearch.ts +0 -280
- package/templates/lib/orionplace/productSeller.ts +0 -56
- package/templates/lib/orionplace/productStructuredData.ts +0 -221
- package/templates/lib/orionplace/profile.ts +0 -169
- package/templates/lib/orionplace/profileLabels.ts +0 -227
- package/templates/lib/orionplace/promoLabels.ts +0 -111
- package/templates/lib/orionplace/promoPresentation.ts +0 -381
- package/templates/lib/orionplace/reviewLabels.ts +0 -256
- package/templates/lib/orionplace/reviewPresentation.ts +0 -64
- package/templates/lib/orionplace/reviewScope.ts +0 -38
- package/templates/lib/orionplace/searchFilters.ts +0 -99
- package/templates/lib/orionplace/searchHistory.ts +0 -144
- package/templates/lib/orionplace/sellerDirectory.ts +0 -120
- package/templates/lib/orionplace/seo.ts +0 -52
- package/templates/lib/orionplace/serverApi.ts +0 -158
- package/templates/lib/orionplace/serverLocale.ts +0 -29
- package/templates/lib/orionplace/serverMetadata.ts +0 -93
- package/templates/lib/orionplace/serverRecords.ts +0 -31
- package/templates/lib/orionplace/serverRoute.tsx +0 -59
- package/templates/lib/orionplace/sessionLabels.ts +0 -38
- package/templates/lib/orionplace/signInReturn.ts +0 -89
- package/templates/lib/orionplace/storeDirectory.ts +0 -47
- package/templates/lib/orionplace/storefrontRecords.ts +0 -42
- package/templates/lib/orionplace/subscriptionChanges.ts +0 -120
- package/templates/lib/orionplace/subscriptionLabels.ts +0 -100
- package/templates/lib/orionplace/subscriptionManageLabels.ts +0 -422
- package/templates/lib/orionplace/subscriptionPlans.ts +0 -122
- package/templates/lib/orionplace/subscriptionRemote.ts +0 -85
- package/templates/lib/orionplace/subscriptionUsage.ts +0 -58
- package/templates/lib/orionplace/tariffLabels.ts +0 -176
- package/templates/lib/orionplace/tariffPage.ts +0 -54
- package/templates/lib/orionplace/tariffVariables.ts +0 -174
- package/templates/lib/orionplace/tariffs.ts +0 -241
- package/templates/lib/orionplace/ticketItems.ts +0 -75
- package/templates/lib/orionplace/ticketLabels.ts +0 -428
- package/templates/lib/orionplace/ticketLocation.ts +0 -79
- package/templates/lib/orionplace/ticketRequests.ts +0 -70
- package/templates/lib/orionplace/walletTransaction.ts +0 -105
- package/templates/orionplace/COMPONENT-DOWNLOAD.md +0 -66
- package/templates/orionplace/COMPONENTS.md +0 -35
- package/templates/providers/OrionplaceProvider.tsx +0 -191
- package/templates/proxy.ts +0 -63
- package/templates/stores/orionplace.ts +0 -282
- package/templates/stores/orionplaceBrowse.ts +0 -89
- package/templates/stores/orionplaceCatalog.ts +0 -162
- package/templates/stores/orionplaceProducts.ts +0 -389
- package/templates/stores/orionplaceScope.ts +0 -104
- package/templates/stores/orionplaceSelections.ts +0 -130
- package/templates/themes/orionplace.ts +0 -106
package/runtime/marketplace.mjs
DELETED
|
@@ -1,905 +0,0 @@
|
|
|
1
|
-
import { chown, mkdir, readFile, readdir, rename, stat, unlink, writeFile } from 'node:fs/promises';
|
|
2
|
-
import { dirname, relative, resolve } from 'node:path';
|
|
3
|
-
import {
|
|
4
|
-
getDefaultAutoSelectFamilyAttemptTimeout,
|
|
5
|
-
isIP,
|
|
6
|
-
setDefaultAutoSelectFamilyAttemptTimeout,
|
|
7
|
-
} from 'node:net';
|
|
8
|
-
|
|
9
|
-
const environment = process.env;
|
|
10
|
-
|
|
11
|
-
// Node gives each resolved backend address 250 ms to connect before it moves
|
|
12
|
-
// on. Over slower links (VPNs, distant regions) every attempt can expire, and
|
|
13
|
-
// the request fails although the backend is reachable. Allow more time per
|
|
14
|
-
// address; a longer value already chosen by the application is kept.
|
|
15
|
-
const connectTimeout = 2_000;
|
|
16
|
-
if (getDefaultAutoSelectFamilyAttemptTimeout() < connectTimeout) {
|
|
17
|
-
setDefaultAutoSelectFamilyAttemptTimeout(connectTimeout);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// A backend answer may take up to 30 seconds. A file upload (multipart form:
|
|
21
|
-
// review photos, cart option files, ticket attachments) also has to send the
|
|
22
|
-
// file first; at 3 Mbit/s a 10 MB file alone takes about 30 seconds, so
|
|
23
|
-
// uploads get 5 minutes.
|
|
24
|
-
const requestTimeout = 30_000;
|
|
25
|
-
const uploadTimeout = 300_000;
|
|
26
|
-
|
|
27
|
-
/** @param {Request} request */
|
|
28
|
-
export function marketplaceRequestTimeout(request) {
|
|
29
|
-
const contentType = request.headers.get('content-type') ?? '';
|
|
30
|
-
|
|
31
|
-
return contentType.toLowerCase().startsWith('multipart/form-data')
|
|
32
|
-
? uploadTimeout
|
|
33
|
-
: requestTimeout;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const hostnamePattern =
|
|
37
|
-
/^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
38
|
-
|
|
39
|
-
// Blog media is served outside /api by the backend's guarded /ps3 routes.
|
|
40
|
-
// Only these read-only paths are forwarded; other /ps3 files stay private.
|
|
41
|
-
const blogMediaPattern =
|
|
42
|
-
/^\/ps3\/blog\/posts\/(?:images\/\d+|videos\/\d+(?:\/preview)?)$/;
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* API answers are never stored. A media file keeps the backend's own browser
|
|
46
|
-
* cache rule when the backend allows it (a published public blog image:
|
|
47
|
-
* "private, max-age=…"); "private" keeps it out of shared caches.
|
|
48
|
-
*/
|
|
49
|
-
export function marketplaceCacheControl(media, upstream) {
|
|
50
|
-
const value = upstream.headers.get('cache-control') ?? '';
|
|
51
|
-
return media && upstream.ok && /\bprivate\b/i.test(value) && /\bmax-age=\d+/i.test(value) && !/no-store|no-cache/i.test(value)
|
|
52
|
-
? value
|
|
53
|
-
: 'no-store';
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/** @param {string} pathname */
|
|
57
|
-
export function isMarketplaceMediaPath(pathname) {
|
|
58
|
-
return blogMediaPattern.test(pathname);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/** @param {unknown} value */
|
|
62
|
-
export function normalizeFrontDomain(value) {
|
|
63
|
-
if (typeof value !== 'string') {
|
|
64
|
-
return null;
|
|
65
|
-
}
|
|
66
|
-
const domain = value.split(',')[0].trim().toLowerCase().replace(/\.$/, '');
|
|
67
|
-
return hostnamePattern.test(domain) && !isIP(domain) ? domain : null;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/** @param {Request} request @param {string} mimic */
|
|
71
|
-
export function resolveFrontDomain(
|
|
72
|
-
request,
|
|
73
|
-
mimic = environment.MIMIC_FRONT_DOMAIN || '',
|
|
74
|
-
) {
|
|
75
|
-
// The hosting proxy must overwrite these headers. Public hosts win over MIMIC.
|
|
76
|
-
for (const candidate of [
|
|
77
|
-
request.headers.get('x-front-domain'),
|
|
78
|
-
request.headers.get('x-forwarded-host'),
|
|
79
|
-
request.headers.get('host'),
|
|
80
|
-
new URL(request.url).hostname,
|
|
81
|
-
]) {
|
|
82
|
-
const domain = normalizeFrontDomain(candidate);
|
|
83
|
-
if (domain) {
|
|
84
|
-
return domain;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
return normalizeFrontDomain(mimic);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/** @param {Request} request @param {{mimicFrontDomain?: string}} configuration */
|
|
91
|
-
export async function readMarketplace(request, configuration = {}) {
|
|
92
|
-
const domain = resolveFrontDomain(request, configuration.mimicFrontDomain);
|
|
93
|
-
if (!domain) {
|
|
94
|
-
throw new Error('Invalid storefront domain');
|
|
95
|
-
}
|
|
96
|
-
return readMarketplaceDomain(domain);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* The marketplace of one storefront domain: its `sitemaps/<domain>.cfg` in
|
|
101
|
-
* the project (`root`, the working directory by default).
|
|
102
|
-
* @param {string} name @param {{root?: string}} options
|
|
103
|
-
*/
|
|
104
|
-
export async function readMarketplaceDomain(name, options = {}) {
|
|
105
|
-
const domain = normalizeFrontDomain(name);
|
|
106
|
-
if (!domain) {
|
|
107
|
-
throw new Error('Invalid storefront domain');
|
|
108
|
-
}
|
|
109
|
-
const directory = marketplaceConfigDirectory(options.root);
|
|
110
|
-
const source = await readFile(resolve(directory, `${domain}.cfg`), 'utf8');
|
|
111
|
-
const lines = source
|
|
112
|
-
.split(/\r?\n/)
|
|
113
|
-
.map((line) => line.trim())
|
|
114
|
-
.filter((line) => line && !line.startsWith('#'));
|
|
115
|
-
if (lines.length !== 1) {
|
|
116
|
-
throw new Error('Expected one API URL');
|
|
117
|
-
}
|
|
118
|
-
const value = lines[0];
|
|
119
|
-
const api = new URL(value.includes('://') ? value : `https://${value}`);
|
|
120
|
-
api.pathname = api.pathname.replace(/\/+$/, '');
|
|
121
|
-
if (
|
|
122
|
-
api.protocol !== 'https:' ||
|
|
123
|
-
!hostnamePattern.test(api.hostname) ||
|
|
124
|
-
!api.hostname.endsWith('.orionplace.app') ||
|
|
125
|
-
isIP(api.hostname) ||
|
|
126
|
-
api.port ||
|
|
127
|
-
api.username ||
|
|
128
|
-
api.password ||
|
|
129
|
-
api.search ||
|
|
130
|
-
api.hash ||
|
|
131
|
-
api.pathname !== '/api'
|
|
132
|
-
) {
|
|
133
|
-
throw new Error('Expected https://<project>.orionplace.app/api');
|
|
134
|
-
}
|
|
135
|
-
return { domain, api };
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/** The folder of the domain files (`SITEMAPS_DIR`, or `sitemaps`). */
|
|
139
|
-
export function marketplaceConfigDirectory(root = process.cwd()) {
|
|
140
|
-
return environment.SITEMAPS_DIR
|
|
141
|
-
? resolve(root, environment.SITEMAPS_DIR)
|
|
142
|
-
: resolve(root, 'sitemaps');
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// The network can drop a pooled connection to the backend (a reset somewhere
|
|
146
|
-
// between this server and the API host). The request then fails before any
|
|
147
|
-
// answer arrives, so a request that is safe to repeat gets one more try on a
|
|
148
|
-
// new connection instead of a failed page.
|
|
149
|
-
const droppedConnection = new Set([
|
|
150
|
-
'ECONNRESET',
|
|
151
|
-
'ECONNABORTED',
|
|
152
|
-
'EPIPE',
|
|
153
|
-
'UND_ERR_SOCKET',
|
|
154
|
-
'UND_ERR_CLOSED',
|
|
155
|
-
]);
|
|
156
|
-
// Application Load only reads, and its body is a small JSON object; a larger
|
|
157
|
-
// body is streamed once without a retry.
|
|
158
|
-
const appLoadPath = /^\/api\/appload\/?$/;
|
|
159
|
-
const repeatBodyLimit = 64 * 1024;
|
|
160
|
-
|
|
161
|
-
/** @param {any} error */
|
|
162
|
-
function connectionDropped(error) {
|
|
163
|
-
return droppedConnection.has(error?.cause?.code ?? error?.code);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* The upstream body and whether the request may be sent twice: GET and HEAD
|
|
168
|
-
* have no body; Application Load keeps its small body for a second try.
|
|
169
|
-
* @param {Request} request @param {string} pathname
|
|
170
|
-
* @returns {Promise<{body: any, repeatable: boolean}>}
|
|
171
|
-
*/
|
|
172
|
-
async function upstreamBody(request, pathname) {
|
|
173
|
-
if (['GET', 'HEAD'].includes(request.method)) {
|
|
174
|
-
return { body: undefined, repeatable: true };
|
|
175
|
-
}
|
|
176
|
-
if (!request.body || !appLoadPath.test(pathname)) {
|
|
177
|
-
return { body: request.body, repeatable: false };
|
|
178
|
-
}
|
|
179
|
-
const reader = request.body.getReader();
|
|
180
|
-
const chunks = [];
|
|
181
|
-
let size = 0;
|
|
182
|
-
for (;;) {
|
|
183
|
-
const { done, value } = await reader.read();
|
|
184
|
-
if (done) {
|
|
185
|
-
return { body: Buffer.concat(chunks), repeatable: true };
|
|
186
|
-
}
|
|
187
|
-
chunks.push(value);
|
|
188
|
-
size += value.byteLength;
|
|
189
|
-
if (size > repeatBodyLimit) {
|
|
190
|
-
const body = new ReadableStream({
|
|
191
|
-
start(controller) {
|
|
192
|
-
for (const chunk of chunks) {
|
|
193
|
-
controller.enqueue(chunk);
|
|
194
|
-
}
|
|
195
|
-
},
|
|
196
|
-
async pull(controller) {
|
|
197
|
-
const next = await reader.read();
|
|
198
|
-
if (next.done) {
|
|
199
|
-
controller.close();
|
|
200
|
-
} else {
|
|
201
|
-
controller.enqueue(next.value);
|
|
202
|
-
}
|
|
203
|
-
},
|
|
204
|
-
cancel(reason) {
|
|
205
|
-
return reader.cancel(reason);
|
|
206
|
-
},
|
|
207
|
-
});
|
|
208
|
-
return { body, repeatable: false };
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/** @param {number} status @param {string} message */
|
|
214
|
-
function failure(status, message) {
|
|
215
|
-
return Response.json(
|
|
216
|
-
{ error: message },
|
|
217
|
-
{
|
|
218
|
-
status,
|
|
219
|
-
headers: {
|
|
220
|
-
'Cache-Control': 'no-store',
|
|
221
|
-
'Vary': 'Host, X-Forwarded-Host, X-Front-Domain',
|
|
222
|
-
},
|
|
223
|
-
},
|
|
224
|
-
);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/** @param {Request} request @param {{mimicFrontDomain?: string}} configuration */
|
|
228
|
-
export async function forwardMarketplace(request, configuration = {}) {
|
|
229
|
-
let tenant;
|
|
230
|
-
try {
|
|
231
|
-
tenant = await readMarketplace(request, configuration);
|
|
232
|
-
} catch {
|
|
233
|
-
return failure(
|
|
234
|
-
503,
|
|
235
|
-
'Storefront domain configuration is missing or invalid',
|
|
236
|
-
);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const incoming = new URL(request.url);
|
|
240
|
-
const media = isMarketplaceMediaPath(incoming.pathname);
|
|
241
|
-
if (!incoming.pathname.startsWith('/api/') && !media) {
|
|
242
|
-
return failure(404, 'Unknown API path');
|
|
243
|
-
}
|
|
244
|
-
if (media && !['GET', 'HEAD'].includes(request.method)) {
|
|
245
|
-
return failure(405, 'Media is read-only');
|
|
246
|
-
}
|
|
247
|
-
// Prevent encoded separators or traversal from escaping the /api namespace.
|
|
248
|
-
let path;
|
|
249
|
-
try {
|
|
250
|
-
path = decodeURIComponent(incoming.pathname);
|
|
251
|
-
} catch {
|
|
252
|
-
return failure(400, 'Invalid API path');
|
|
253
|
-
}
|
|
254
|
-
if (
|
|
255
|
-
path.includes('\\') ||
|
|
256
|
-
/%(?:2e|2f|5c)/i.test(path) ||
|
|
257
|
-
path.split('/').some((part) => part === '.' || part === '..')
|
|
258
|
-
) {
|
|
259
|
-
return failure(400, 'Invalid API path');
|
|
260
|
-
}
|
|
261
|
-
const target = new URL(
|
|
262
|
-
incoming.pathname + incoming.search,
|
|
263
|
-
tenant.api.origin,
|
|
264
|
-
);
|
|
265
|
-
if (
|
|
266
|
-
media
|
|
267
|
-
? !isMarketplaceMediaPath(target.pathname)
|
|
268
|
-
: !target.pathname.startsWith('/api/')
|
|
269
|
-
) {
|
|
270
|
-
return failure(400, 'Invalid API path');
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
const origin = request.headers.get('origin');
|
|
274
|
-
const publicHost = request.headers.get('host') || incoming.host;
|
|
275
|
-
const originHosts = [publicHost, tenant.domain];
|
|
276
|
-
if (!['GET', 'HEAD', 'OPTIONS'].includes(request.method)) {
|
|
277
|
-
try {
|
|
278
|
-
if (
|
|
279
|
-
request.headers.get('sec-fetch-site') === 'cross-site' ||
|
|
280
|
-
(origin && !originHosts.includes(new URL(origin).host))
|
|
281
|
-
) {
|
|
282
|
-
return failure(403, 'Cross-site API request rejected');
|
|
283
|
-
}
|
|
284
|
-
} catch {
|
|
285
|
-
return failure(403, 'Invalid Origin');
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// An allowlist excludes hop-by-hop and client-supplied routing headers.
|
|
290
|
-
const headers = new Headers();
|
|
291
|
-
for (const name of [
|
|
292
|
-
'accept',
|
|
293
|
-
'content-type',
|
|
294
|
-
'authorization',
|
|
295
|
-
'cookie',
|
|
296
|
-
'origin',
|
|
297
|
-
'referer',
|
|
298
|
-
'x-csrftoken',
|
|
299
|
-
'accept-language',
|
|
300
|
-
'user-agent',
|
|
301
|
-
'x-tz',
|
|
302
|
-
'range',
|
|
303
|
-
]) {
|
|
304
|
-
const value = request.headers.get(name);
|
|
305
|
-
if (value) {
|
|
306
|
-
headers.set(name, value);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
headers.set('X-Front-Domain', tenant.domain);
|
|
310
|
-
// The backend accepts forms from the storefront domain's own origin. A public
|
|
311
|
-
// host that shows this storefront (MIMIC, a preview host or a local port)
|
|
312
|
-
// passed the same-origin check above, so it is sent as that origin.
|
|
313
|
-
let ownOrigin = false;
|
|
314
|
-
try {
|
|
315
|
-
ownOrigin = Boolean(origin) && originHosts.includes(new URL(origin).host);
|
|
316
|
-
} catch {
|
|
317
|
-
ownOrigin = false;
|
|
318
|
-
}
|
|
319
|
-
if (ownOrigin) {
|
|
320
|
-
headers.set('origin', `https://${tenant.domain}`);
|
|
321
|
-
}
|
|
322
|
-
headers.set('Accept-Encoding', 'identity');
|
|
323
|
-
const clientIp =
|
|
324
|
-
request.headers.get('x-init-ip') ||
|
|
325
|
-
request.headers.get('x-real-ip') ||
|
|
326
|
-
request.headers.get('x-forwarded-for')?.split(',')[0]?.trim();
|
|
327
|
-
if (clientIp) {
|
|
328
|
-
headers.set('X-Init-Ip', clientIp);
|
|
329
|
-
}
|
|
330
|
-
/** @type {RequestInit & { duplex: 'half' }} */
|
|
331
|
-
const options = {
|
|
332
|
-
method: request.method,
|
|
333
|
-
headers,
|
|
334
|
-
redirect: 'manual',
|
|
335
|
-
cache: 'no-store',
|
|
336
|
-
signal: AbortSignal.any([
|
|
337
|
-
request.signal,
|
|
338
|
-
AbortSignal.timeout(marketplaceRequestTimeout(request)),
|
|
339
|
-
]),
|
|
340
|
-
duplex: 'half',
|
|
341
|
-
};
|
|
342
|
-
let upstream;
|
|
343
|
-
try {
|
|
344
|
-
const { body, repeatable } = await upstreamBody(request, incoming.pathname);
|
|
345
|
-
if (body !== undefined) {
|
|
346
|
-
options.body = body;
|
|
347
|
-
}
|
|
348
|
-
try {
|
|
349
|
-
upstream = await fetch(target, options);
|
|
350
|
-
} catch (error) {
|
|
351
|
-
if (!repeatable || !connectionDropped(error) || options.signal.aborted) {
|
|
352
|
-
throw error;
|
|
353
|
-
}
|
|
354
|
-
console.warn(
|
|
355
|
-
`[orionplace] Backend connection dropped (${error?.cause?.code ?? error?.code}), retrying once`,
|
|
356
|
-
);
|
|
357
|
-
upstream = await fetch(target, options);
|
|
358
|
-
}
|
|
359
|
-
} catch (error) {
|
|
360
|
-
// The browser receives only the status; keep the cause in the server log.
|
|
361
|
-
if (!request.signal.aborted) {
|
|
362
|
-
const cause = error?.cause?.code ?? error?.message ?? String(error);
|
|
363
|
-
console.error(`[orionplace] Backend request failed: ${cause}`);
|
|
364
|
-
}
|
|
365
|
-
return failure(502, 'Marketplace backend is unavailable');
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
const responseHeaders = new Headers();
|
|
369
|
-
for (const name of [
|
|
370
|
-
'content-type',
|
|
371
|
-
'content-disposition',
|
|
372
|
-
'www-authenticate',
|
|
373
|
-
'retry-after',
|
|
374
|
-
'allow',
|
|
375
|
-
'accept-ranges',
|
|
376
|
-
'content-range',
|
|
377
|
-
]) {
|
|
378
|
-
const value = upstream.headers.get(name);
|
|
379
|
-
if (value) {
|
|
380
|
-
responseHeaders.set(name, value);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
// Keep each cookie separate; remove the backend Domain attribute only.
|
|
384
|
-
for (const cookie of upstream.headers.getSetCookie()) {
|
|
385
|
-
responseHeaders.append(
|
|
386
|
-
'Set-Cookie',
|
|
387
|
-
cookie.replace(/;\s*Domain=[^;]*/gi, ''),
|
|
388
|
-
);
|
|
389
|
-
}
|
|
390
|
-
const location = upstream.headers.get('location');
|
|
391
|
-
if (location) {
|
|
392
|
-
const destination = new URL(location, target);
|
|
393
|
-
responseHeaders.set(
|
|
394
|
-
'Location',
|
|
395
|
-
destination.origin === tenant.api.origin
|
|
396
|
-
? destination.pathname + destination.search + destination.hash
|
|
397
|
-
: destination.href,
|
|
398
|
-
);
|
|
399
|
-
}
|
|
400
|
-
responseHeaders.set('Cache-Control', marketplaceCacheControl(media, upstream));
|
|
401
|
-
responseHeaders.set('Vary', 'Host, X-Forwarded-Host, X-Front-Domain');
|
|
402
|
-
// fetch decodes compressed bodies: do not reuse upstream Content-Length/Encoding.
|
|
403
|
-
return new Response(upstream.body, {
|
|
404
|
-
status: upstream.status,
|
|
405
|
-
statusText: upstream.statusText,
|
|
406
|
-
headers: responseHeaders,
|
|
407
|
-
});
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
// ---------------------------------------------------------------------------
|
|
411
|
-
// robots.txt and sitemap.xml
|
|
412
|
-
//
|
|
413
|
-
// The sitemap lists the storefront's public pages in every language the
|
|
414
|
-
// marketplace offers (`?locale=<code>` links, with hreflang alternates): the
|
|
415
|
-
// home, catalog and directory pages, the journal and its publications when
|
|
416
|
-
// the blog is on, the subscription plans when there are any, every public
|
|
417
|
-
// category and every product on sale. It is built from the backend's public
|
|
418
|
-
// API and kept for an hour per storefront domain in
|
|
419
|
-
// node_modules/.cache/orionplace/sitemaps/<domain>.json (ORIONPLACE_CACHE_DIR
|
|
420
|
-
// moves it). "orionplace-<framework> sitemap rebuild" rebuilds that file at
|
|
421
|
-
// once; the running storefront serves the new file without a restart.
|
|
422
|
-
// Paths in ORIONPLACE_NOINDEX_PATHS are left out when the sitemap is served.
|
|
423
|
-
|
|
424
|
-
export const SITEMAP_LIFETIME = 60 * 60 * 1000;
|
|
425
|
-
const sitemapPageSize = 100;
|
|
426
|
-
const sitemapMaxPages = 500;
|
|
427
|
-
const sitemapMaxUrls = 50_000;
|
|
428
|
-
const sitemapVersion = 1;
|
|
429
|
-
/** Built sitemaps of this process, for when the cache folder is read-only. */
|
|
430
|
-
const sitemapMemory = new Map();
|
|
431
|
-
/** @type {Map<string, Promise<object>>} */
|
|
432
|
-
const sitemapBuilds = new Map();
|
|
433
|
-
|
|
434
|
-
/** The public origin a crawler used: the storefront host, or a local one. */
|
|
435
|
-
export function marketplacePublicOrigin(request, tenantDomain = '') {
|
|
436
|
-
const url = new URL(request.url);
|
|
437
|
-
const host = normalizeFrontDomain(
|
|
438
|
-
request.headers.get('x-forwarded-host') ?? request.headers.get('host') ?? '',
|
|
439
|
-
);
|
|
440
|
-
if (host) {
|
|
441
|
-
return `https://${host}`;
|
|
442
|
-
}
|
|
443
|
-
const local = /^(?:localhost|127(?:\.\d{1,3}){3}|\[::1\])$/.test(url.hostname);
|
|
444
|
-
return local || !tenantDomain ? url.origin : `https://${tenantDomain}`;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
/**
|
|
448
|
-
* Pages kept out of search engines: ORIONPLACE_NOINDEX_PATHS lists path
|
|
449
|
-
* prefixes separated by spaces or commas, for example "/catalog /category
|
|
450
|
-
* /product" on a demo or staging storefront. Those pages answer with
|
|
451
|
-
* `X-Robots-Tag: noindex, follow` and the sitemap leaves them out. Empty
|
|
452
|
-
* (the default) keeps every public page indexable.
|
|
453
|
-
*/
|
|
454
|
-
export function noindexPathPrefixes(value = environment.ORIONPLACE_NOINDEX_PATHS) {
|
|
455
|
-
return String(value ?? '')
|
|
456
|
-
.split(/[\s,]+/)
|
|
457
|
-
.map((item) => item.trim().replace(/\/+$/, ''))
|
|
458
|
-
.filter((item) => /^\/[A-Za-z0-9._~\/-]+$/.test(item));
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
/** Whether a page path is kept out of search engines (see noindexPathPrefixes). */
|
|
462
|
-
export function marketplaceNoindexPath(pathname, value = environment.ORIONPLACE_NOINDEX_PATHS) {
|
|
463
|
-
const path = String(pathname ?? '');
|
|
464
|
-
return noindexPathPrefixes(value)
|
|
465
|
-
.some((prefix) => path === prefix || path.startsWith(`${prefix}/`));
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
/** The sitemap pages search engines may index. */
|
|
469
|
-
export function sitemapIndexedPages(pages, value = environment.ORIONPLACE_NOINDEX_PATHS) {
|
|
470
|
-
return noindexPathPrefixes(value).length
|
|
471
|
-
? pages.filter((page) => !marketplaceNoindexPath(page.path, value))
|
|
472
|
-
: pages;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
/** @param {string} origin */
|
|
476
|
-
export function marketplaceRobots(origin) {
|
|
477
|
-
return `User-agent: *\nDisallow: /api/\nAllow: /\n\nSitemap: ${origin}/sitemap.xml\n`;
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
/** @param {Request} request @param {{mimicFrontDomain?: string}} configuration */
|
|
481
|
-
export async function marketplaceRobotsResponse(request, configuration = {}) {
|
|
482
|
-
let domain = '';
|
|
483
|
-
try {
|
|
484
|
-
domain = (await readMarketplace(request, configuration)).domain;
|
|
485
|
-
} catch {
|
|
486
|
-
domain = '';
|
|
487
|
-
}
|
|
488
|
-
return new Response(
|
|
489
|
-
marketplaceRobots(marketplacePublicOrigin(request, domain)),
|
|
490
|
-
{
|
|
491
|
-
headers: {
|
|
492
|
-
'Content-Type': 'text/plain; charset=utf-8',
|
|
493
|
-
'Cache-Control': 'public, max-age=3600',
|
|
494
|
-
'Vary': 'Host, X-Forwarded-Host, X-Front-Domain',
|
|
495
|
-
},
|
|
496
|
-
},
|
|
497
|
-
);
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
/** @param {string} value */
|
|
501
|
-
function escapeXml(value) {
|
|
502
|
-
return value.replace(/[<>&"']/g, (character) => ({
|
|
503
|
-
'<': '<', '>': '>', '&': '&', '"': '"', "'": ''',
|
|
504
|
-
})[character]);
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
/** @param {unknown} value */
|
|
508
|
-
function publicId(value) {
|
|
509
|
-
const id = Number(value);
|
|
510
|
-
return Number.isSafeInteger(id) && id > 0 ? id : null;
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
/** The marketplace's languages from /appload `init.locale`. */
|
|
514
|
-
export function sitemapLocales(locales) {
|
|
515
|
-
const codes = Object.entries(locales && typeof locales === 'object' ? locales : {})
|
|
516
|
-
.map(([key, item]) => String(item?.code || key).trim().toLowerCase())
|
|
517
|
-
.filter((code) => /^[a-z]{2,3}(?:-[a-z0-9]{2,8})*$/.test(code));
|
|
518
|
-
return [...new Set(codes)].sort();
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
/** A product edit time (ISO 8601) or a blog post day ({date: 'DD.MM.YYYY'}). */
|
|
522
|
-
export function sitemapLastmod(value, now = Date.now()) {
|
|
523
|
-
if (typeof value === 'string' && value) {
|
|
524
|
-
const time = Date.parse(value);
|
|
525
|
-
return Number.isFinite(time) && time <= now + 60_000
|
|
526
|
-
? new Date(time).toISOString().replace(/\.\d{3}Z$/, 'Z')
|
|
527
|
-
: null;
|
|
528
|
-
}
|
|
529
|
-
const match = /^(\d{2})\.(\d{2})\.(\d{4})$/.exec(value?.date ?? '');
|
|
530
|
-
if (!match) {
|
|
531
|
-
return null;
|
|
532
|
-
}
|
|
533
|
-
const [, day, month, year] = match;
|
|
534
|
-
const time = Date.UTC(Number(year), Number(month) - 1, Number(day));
|
|
535
|
-
const date = new Date(time);
|
|
536
|
-
return date.getUTCDate() === Number(day) &&
|
|
537
|
-
date.getUTCMonth() === Number(month) - 1 &&
|
|
538
|
-
time <= now + 24 * 60 * 60 * 1000
|
|
539
|
-
? `${year}-${month}-${day}`
|
|
540
|
-
: null;
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
/** The API path (under /api) of a route named in /appload `unauth.paths`. */
|
|
544
|
-
export function sitemapApiPath(paths, name) {
|
|
545
|
-
for (const group of Object.values(paths ?? {})) {
|
|
546
|
-
for (const route of Object.values(group ?? {})) {
|
|
547
|
-
if (route?.url_name === name) {
|
|
548
|
-
const target = String(route.target ?? '').split('/{')[0].replace(/^\/+/, '');
|
|
549
|
-
return target.startsWith('api/') ? `/${target}` : null;
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
return null;
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
/** Public categories, parents before children. */
|
|
557
|
-
export function sitemapCategoryIds(categories) {
|
|
558
|
-
const ids = [];
|
|
559
|
-
const visit = (category) => {
|
|
560
|
-
const id = publicId(category?.id);
|
|
561
|
-
if (id && category?.is_public) {
|
|
562
|
-
ids.push(id);
|
|
563
|
-
}
|
|
564
|
-
(category?.childs ?? []).forEach(visit);
|
|
565
|
-
};
|
|
566
|
-
(Array.isArray(categories) ? categories : []).forEach(visit);
|
|
567
|
-
return [...new Set(ids)];
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
/**
|
|
571
|
-
* One <url> per page and language, each with alternates for its languages.
|
|
572
|
-
* A page with its own `locales` (a publication written in some languages
|
|
573
|
-
* only) is listed in those of the marketplace's languages.
|
|
574
|
-
* @param {string} origin
|
|
575
|
-
* @param {{path: string, lastmod?: string | null, locales?: string[]}[]} pages
|
|
576
|
-
* @param {string[]} locales
|
|
577
|
-
*/
|
|
578
|
-
export function marketplaceSitemapXml(origin, pages, locales) {
|
|
579
|
-
const href = (path, code) => {
|
|
580
|
-
const url = new URL(path, `${origin}/`);
|
|
581
|
-
if (code) {
|
|
582
|
-
url.searchParams.set('locale', code);
|
|
583
|
-
}
|
|
584
|
-
return escapeXml(url.toString());
|
|
585
|
-
};
|
|
586
|
-
const urls = [];
|
|
587
|
-
for (const page of pages) {
|
|
588
|
-
const own = page.locales
|
|
589
|
-
? locales.filter((code) => page.locales.includes(code))
|
|
590
|
-
: locales;
|
|
591
|
-
if (page.locales && !own.length) {
|
|
592
|
-
continue;
|
|
593
|
-
}
|
|
594
|
-
const codes = own.length ? own : [''];
|
|
595
|
-
const alternates = own.length > 1
|
|
596
|
-
? own.map((code) =>
|
|
597
|
-
` <xhtml:link rel="alternate" hreflang="${escapeXml(code)}" href="${href(page.path, code)}" />\n`).join('')
|
|
598
|
-
: '';
|
|
599
|
-
const lastmod = page.lastmod ? ` <lastmod>${escapeXml(page.lastmod)}</lastmod>\n` : '';
|
|
600
|
-
for (const code of codes) {
|
|
601
|
-
if (urls.length >= sitemapMaxUrls) {
|
|
602
|
-
break;
|
|
603
|
-
}
|
|
604
|
-
urls.push(` <url>\n <loc>${href(page.path, code)}</loc>\n${lastmod}${alternates} </url>\n`);
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
return '<?xml version="1.0" encoding="UTF-8"?>\n' +
|
|
608
|
-
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">\n' +
|
|
609
|
-
urls.join('') +
|
|
610
|
-
'</urlset>\n';
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
/** @param {{domain: string, api: URL}} tenant @param {string} path @param {unknown} body */
|
|
614
|
-
async function sitemapRequest(tenant, path, body) {
|
|
615
|
-
const response = await fetch(new URL(path, tenant.api.origin), {
|
|
616
|
-
method: 'POST',
|
|
617
|
-
headers: {
|
|
618
|
-
'Content-Type': 'application/json',
|
|
619
|
-
'Accept': 'application/json',
|
|
620
|
-
'X-Front-Domain': tenant.domain,
|
|
621
|
-
},
|
|
622
|
-
body: JSON.stringify(body),
|
|
623
|
-
cache: 'no-store',
|
|
624
|
-
signal: AbortSignal.timeout(requestTimeout),
|
|
625
|
-
});
|
|
626
|
-
if (!response.ok) {
|
|
627
|
-
throw new Error(`${path} answered ${response.status}`);
|
|
628
|
-
}
|
|
629
|
-
return response.json();
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
/** Every record of a paginated list (`page_data[key].data` + `rpag`). */
|
|
633
|
-
async function sitemapList(tenant, path, key, filters = {}) {
|
|
634
|
-
const records = new Map();
|
|
635
|
-
let page = 1;
|
|
636
|
-
for (let count = 0; count < sitemapMaxPages; count++) {
|
|
637
|
-
const payload = await sitemapRequest(tenant, path, {
|
|
638
|
-
filters,
|
|
639
|
-
paginate: { page, pp_items: sitemapPageSize },
|
|
640
|
-
});
|
|
641
|
-
const list = payload?.page_data?.[key];
|
|
642
|
-
if (!Array.isArray(list?.data)) {
|
|
643
|
-
throw new Error(`${path} returned no ${key} list`);
|
|
644
|
-
}
|
|
645
|
-
for (const record of list.data) {
|
|
646
|
-
const id = publicId(record?.id);
|
|
647
|
-
if (id) {
|
|
648
|
-
records.set(id, record);
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
const next = Number(list.rpag?.next_page_number);
|
|
652
|
-
if (!list.rpag?.has_next || !Number.isSafeInteger(next) || next <= page) {
|
|
653
|
-
return [...records.values()];
|
|
654
|
-
}
|
|
655
|
-
page = next;
|
|
656
|
-
}
|
|
657
|
-
throw new Error(`${path} has more than ${sitemapMaxPages} pages`);
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
/** Products on sale and in stock states a shopper can open. */
|
|
661
|
-
function productOnSale(product) {
|
|
662
|
-
const status = Number(product?.status?.status ?? product?.status);
|
|
663
|
-
return [2, -2, -3].includes(status);
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
/** Blog publications that are published. */
|
|
667
|
-
function postPublished(post) {
|
|
668
|
-
const state = post?.publishing_state?.int ?? post?.publishing_state;
|
|
669
|
-
return state === undefined || state === null || Number(state) === 1;
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
/** The languages a publication is written in (it has a title there). */
|
|
673
|
-
function postLocales(post) {
|
|
674
|
-
return Object.entries(post?.locale && typeof post.locale === 'object' ? post.locale : {})
|
|
675
|
-
.filter(([, text]) => typeof text?.post_title === 'string' && text.post_title.trim())
|
|
676
|
-
.map(([code]) => code.toLowerCase());
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
/** @param {{domain: string, api: URL}} tenant */
|
|
680
|
-
async function buildMarketplaceSitemap(tenant) {
|
|
681
|
-
const appload = await sitemapRequest(tenant, '/api/appload', {
|
|
682
|
-
detalize_mode: 'light',
|
|
683
|
-
ignore_cache: false,
|
|
684
|
-
});
|
|
685
|
-
const init = appload?.page_data?.init;
|
|
686
|
-
const paths = appload?.page_data?.unauth?.paths;
|
|
687
|
-
if (!init || !Array.isArray(init.catalog)) {
|
|
688
|
-
throw new Error('appload returned no catalog');
|
|
689
|
-
}
|
|
690
|
-
const locales = sitemapLocales(init.locale);
|
|
691
|
-
const categories = sitemapCategoryIds(init.catalog);
|
|
692
|
-
const blogPath = sitemapApiPath(paths, 'blog_posts_get');
|
|
693
|
-
const searchPath = sitemapApiPath(paths, 'products_search');
|
|
694
|
-
const [products, posts] = await Promise.all([
|
|
695
|
-
searchPath && categories.length
|
|
696
|
-
? sitemapList(tenant, searchPath, 'products', { categories })
|
|
697
|
-
: [],
|
|
698
|
-
blogPath ? sitemapList(tenant, blogPath, 'posts') : [],
|
|
699
|
-
]);
|
|
700
|
-
const postPages = posts
|
|
701
|
-
.filter(postPublished)
|
|
702
|
-
.sort((left, right) => left.id - right.id)
|
|
703
|
-
.map((post) => ({
|
|
704
|
-
path: `/journal/${post.id}`,
|
|
705
|
-
lastmod: sitemapLastmod(post.date_updated),
|
|
706
|
-
locales: postLocales(post),
|
|
707
|
-
}));
|
|
708
|
-
const newestPost = postPages.map((page) => page.lastmod).filter(Boolean).sort().at(-1) ?? null;
|
|
709
|
-
const pages = [
|
|
710
|
-
{ path: '/' },
|
|
711
|
-
{ path: '/catalog' },
|
|
712
|
-
...(blogPath ? [{ path: '/journal', lastmod: newestPost }] : []),
|
|
713
|
-
...(init.tariffs?.data?.length ? [{ path: '/tariffs' }] : []),
|
|
714
|
-
{ path: '/manufacturers' },
|
|
715
|
-
...(init.visual_settings?.single_seller_mode ? [] : [{ path: '/sellers' }]),
|
|
716
|
-
{ path: '/stores' },
|
|
717
|
-
{ path: '/contact' },
|
|
718
|
-
{ path: '/privacy' },
|
|
719
|
-
...categories.map((id) => ({ path: `/category/${id}` })),
|
|
720
|
-
...products
|
|
721
|
-
.filter(productOnSale)
|
|
722
|
-
.map((product) => ({
|
|
723
|
-
path: `/product/${product.id}`,
|
|
724
|
-
lastmod: sitemapLastmod(product.date_updated),
|
|
725
|
-
})),
|
|
726
|
-
...postPages,
|
|
727
|
-
];
|
|
728
|
-
return {
|
|
729
|
-
version: sitemapVersion,
|
|
730
|
-
domain: tenant.domain,
|
|
731
|
-
built: new Date().toISOString(),
|
|
732
|
-
locales,
|
|
733
|
-
pages,
|
|
734
|
-
};
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
/** How many <url> entries a built sitemap has. */
|
|
738
|
-
export function sitemapUrlCount(sitemap) {
|
|
739
|
-
let count = 0;
|
|
740
|
-
for (const page of sitemapIndexedPages(sitemap.pages)) {
|
|
741
|
-
const own = page.locales
|
|
742
|
-
? sitemap.locales.filter((code) => page.locales.includes(code))
|
|
743
|
-
: sitemap.locales;
|
|
744
|
-
count += page.locales ? own.length : Math.max(own.length, 1);
|
|
745
|
-
}
|
|
746
|
-
return Math.min(count, sitemapMaxUrls);
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
/** The cache folder of built sitemaps. */
|
|
750
|
-
export function sitemapCacheDirectory(root = process.cwd()) {
|
|
751
|
-
return environment.ORIONPLACE_CACHE_DIR
|
|
752
|
-
? resolve(root, environment.ORIONPLACE_CACHE_DIR, 'sitemaps')
|
|
753
|
-
: resolve(root, 'node_modules', '.cache', 'orionplace', 'sitemaps');
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
/** @param {string} domain @param {string} root */
|
|
757
|
-
function sitemapCachePath(domain, root) {
|
|
758
|
-
return resolve(sitemapCacheDirectory(root), `${domain}.json`);
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
/** A cached sitemap of the domain, or null. @param {string} domain */
|
|
762
|
-
export async function readSitemapCache(domain, root = process.cwd()) {
|
|
763
|
-
let sitemap;
|
|
764
|
-
try {
|
|
765
|
-
sitemap = JSON.parse(await readFile(sitemapCachePath(domain, root), 'utf8'));
|
|
766
|
-
} catch {
|
|
767
|
-
return null;
|
|
768
|
-
}
|
|
769
|
-
return sitemap?.version === sitemapVersion &&
|
|
770
|
-
sitemap.domain === domain &&
|
|
771
|
-
Number.isFinite(Date.parse(sitemap.built)) &&
|
|
772
|
-
Array.isArray(sitemap.locales) &&
|
|
773
|
-
Array.isArray(sitemap.pages)
|
|
774
|
-
? sitemap
|
|
775
|
-
: null;
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
/**
|
|
779
|
-
* Write the cache file. When root writes it (sudo), the folders it creates
|
|
780
|
-
* and the file go to the project owner, so the storefront service can
|
|
781
|
-
* replace them later.
|
|
782
|
-
*/
|
|
783
|
-
async function writeSitemapCache(sitemap, root) {
|
|
784
|
-
const path = sitemapCachePath(sitemap.domain, root);
|
|
785
|
-
const temporary = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
786
|
-
await mkdir(dirname(path), { recursive: true });
|
|
787
|
-
try {
|
|
788
|
-
await writeFile(temporary, JSON.stringify(sitemap), { mode: 0o644 });
|
|
789
|
-
await rename(temporary, path);
|
|
790
|
-
} catch (error) {
|
|
791
|
-
await unlink(temporary).catch(() => {});
|
|
792
|
-
throw error;
|
|
793
|
-
}
|
|
794
|
-
if (process.getuid?.() === 0) {
|
|
795
|
-
const owner = await stat(root);
|
|
796
|
-
if (owner.uid !== 0) {
|
|
797
|
-
let cursor = path;
|
|
798
|
-
while (cursor !== root && !relative(root, cursor).startsWith('..')) {
|
|
799
|
-
const info = await stat(cursor);
|
|
800
|
-
if (info.uid === 0) {
|
|
801
|
-
await chown(cursor, owner.uid, owner.gid);
|
|
802
|
-
}
|
|
803
|
-
cursor = dirname(cursor);
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
}
|
|
807
|
-
return path;
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
/** @param {{domain: string, api: URL}} tenant @param {string} root */
|
|
811
|
-
function buildOnce(tenant, root) {
|
|
812
|
-
let build = sitemapBuilds.get(tenant.domain);
|
|
813
|
-
if (!build) {
|
|
814
|
-
build = buildMarketplaceSitemap(tenant)
|
|
815
|
-
.then(async (sitemap) => {
|
|
816
|
-
sitemapMemory.set(tenant.domain, sitemap);
|
|
817
|
-
try {
|
|
818
|
-
await writeSitemapCache(sitemap, root);
|
|
819
|
-
} catch (error) {
|
|
820
|
-
console.error(`[orionplace] Sitemap cache not written: ${error?.code ?? error?.message ?? error}`);
|
|
821
|
-
}
|
|
822
|
-
return sitemap;
|
|
823
|
-
})
|
|
824
|
-
.finally(() => sitemapBuilds.delete(tenant.domain));
|
|
825
|
-
sitemapBuilds.set(tenant.domain, build);
|
|
826
|
-
}
|
|
827
|
-
return build;
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
/**
|
|
831
|
-
* Rebuild the sitemap of one storefront domain now and store it where the
|
|
832
|
-
* running storefront reads it (the "sitemap rebuild" command).
|
|
833
|
-
* @param {string} domain @param {{root?: string}} options
|
|
834
|
-
*/
|
|
835
|
-
export async function rebuildMarketplaceSitemap(domain, options = {}) {
|
|
836
|
-
const root = resolve(options.root ?? process.cwd());
|
|
837
|
-
const tenant = await readMarketplaceDomain(domain, { root });
|
|
838
|
-
const sitemap = await buildMarketplaceSitemap(tenant);
|
|
839
|
-
const path = await writeSitemapCache(sitemap, root);
|
|
840
|
-
return {
|
|
841
|
-
domain: tenant.domain,
|
|
842
|
-
path,
|
|
843
|
-
built: sitemap.built,
|
|
844
|
-
urls: sitemapUrlCount(sitemap),
|
|
845
|
-
pages: sitemap.pages.length,
|
|
846
|
-
publications: sitemap.pages.filter((page) => page.path.startsWith('/journal/')).length,
|
|
847
|
-
};
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
/** The storefront domains of the project (its `sitemaps/*.cfg` files). */
|
|
851
|
-
export async function marketplaceDomains(root = process.cwd()) {
|
|
852
|
-
let names;
|
|
853
|
-
try {
|
|
854
|
-
names = await readdir(marketplaceConfigDirectory(root));
|
|
855
|
-
} catch (error) {
|
|
856
|
-
if (error?.code === 'ENOENT') {
|
|
857
|
-
return [];
|
|
858
|
-
}
|
|
859
|
-
throw error;
|
|
860
|
-
}
|
|
861
|
-
return names
|
|
862
|
-
.filter((name) => name.endsWith('.cfg'))
|
|
863
|
-
.map((name) => normalizeFrontDomain(name.slice(0, -4)))
|
|
864
|
-
.filter(Boolean)
|
|
865
|
-
.sort();
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
/** @param {Request} request @param {{mimicFrontDomain?: string}} configuration */
|
|
869
|
-
export async function marketplaceSitemapResponse(request, configuration = {}) {
|
|
870
|
-
let tenant;
|
|
871
|
-
try {
|
|
872
|
-
tenant = await readMarketplace(request, configuration);
|
|
873
|
-
} catch {
|
|
874
|
-
return failure(503, 'Storefront domain configuration is missing or invalid');
|
|
875
|
-
}
|
|
876
|
-
const root = process.cwd();
|
|
877
|
-
const fresh = (sitemap) =>
|
|
878
|
-
sitemap && Date.now() - Date.parse(sitemap.built) < SITEMAP_LIFETIME;
|
|
879
|
-
// The file wins when it is newer: a "sitemap rebuild" replaced it.
|
|
880
|
-
const file = await readSitemapCache(tenant.domain, root);
|
|
881
|
-
const memory = sitemapMemory.get(tenant.domain);
|
|
882
|
-
const newest = [file, memory]
|
|
883
|
-
.filter(Boolean)
|
|
884
|
-
.sort((left, right) => Date.parse(right.built) - Date.parse(left.built))[0];
|
|
885
|
-
let sitemap = fresh(newest) ? newest : null;
|
|
886
|
-
if (!sitemap) {
|
|
887
|
-
try {
|
|
888
|
-
sitemap = await buildOnce(tenant, root);
|
|
889
|
-
} catch (error) {
|
|
890
|
-
console.error(`[orionplace] Sitemap build failed: ${error?.message ?? error}`);
|
|
891
|
-
if (!newest) {
|
|
892
|
-
return failure(502, 'Marketplace backend is unavailable');
|
|
893
|
-
}
|
|
894
|
-
sitemap = newest;
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
const origin = marketplacePublicOrigin(request, tenant.domain);
|
|
898
|
-
return new Response(marketplaceSitemapXml(origin, sitemapIndexedPages(sitemap.pages), sitemap.locales), {
|
|
899
|
-
headers: {
|
|
900
|
-
'Content-Type': 'application/xml; charset=utf-8',
|
|
901
|
-
'Cache-Control': 'public, max-age=3600',
|
|
902
|
-
'Vary': 'Host, X-Forwarded-Host, X-Front-Domain',
|
|
903
|
-
},
|
|
904
|
-
});
|
|
905
|
-
}
|