@wix/himalaya-cli 0.1544.0 → 0.1545.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/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/agent/src/index.d.ts +5 -2
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/state/src/index.d.ts +14 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/state/src/read.d.ts +60 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/activity-counters-v1/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/ai-site-chat/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/analytics/src/index.d.ts +42 -2
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/async-jobs/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/automations-v1/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/badges-v2/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/billing-tax-v1/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/blog-v3/src/extensions.d.ts +5 -4
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/blog-v3/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/bookings-v2/src/extensions.d.ts +4 -4
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/bookings-v2/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/business-feed/src/index.d.ts +11 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/business-tools-v1/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/chat-web/src/index.d.ts +22 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/comments-v1/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/contacts/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/coupons/src/index.d.ts +24 -2
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/crm-tasks/src/index.d.ts +11 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/dashboard-setup/src/index.d.ts +11 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/data-collections-v1/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/donations/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/ecom/src/extensions.d.ts +6 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/ecom/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/email-marketing-v1/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/events/src/index.d.ts +24 -2
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/faq-v2/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/forms/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/forum/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/genie-chat/src/index.d.ts +11 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/gift-cards/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/groups/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/inbox/src/extensions.d.ts +2 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/inbox/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/invoices/src/index.d.ts +24 -2
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/loyalty/src/index.d.ts +28 -4
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/marketing-v1/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/members-feed-viewer/src/index.d.ts +23 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/members-v1/src/index.d.ts +25 -3
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/new-releases/src/index.d.ts +23 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/notification-preferences/src/index.d.ts +23 -2
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/notifications-v3/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/online-programs/src/index.d.ts +25 -3
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/portfolio/src/index.d.ts +25 -3
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/pricing-plans/src/index.d.ts +28 -6
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/redirects-v1/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/restaurants/src/extensions.d.ts +2 -2
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/restaurants/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/reviews/src/index.d.ts +24 -2
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/seo-v1/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/site-list/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/site-media/src/index.d.ts +11 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/social-feed/src/index.d.ts +23 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/stores-collections/src/display.d.ts +3 -2
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/stores-collections/src/index.d.ts +27 -3
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/stores-v1/src/catalog.d.ts +7 -7
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/stores-v1/src/display.d.ts +4 -3
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/stores-v1/src/extensions.d.ts +2 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/stores-v1/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/table-reservations/src/index.d.ts +25 -3
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/users/src/index.d.ts +23 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/video/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/wix-data/src/index.d.ts +27 -3
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/workflows-v1/src/index.d.ts +19 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk-auto/_shared/runtime.generated.d.ts +8 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/checkout.mjs +12 -4
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/screens.mjs +36 -11
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/state.mjs +206 -12
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-activity-counters.mjs +19 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-ai-site-chat.mjs +19 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-analytics.mjs +21 -7
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-async-jobs.mjs +19 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-automations.mjs +19 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-badges.mjs +19 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-billing-tax.mjs +19 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-blog.mjs +31 -14
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-bookings.mjs +26 -12
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-business-tools.mjs +20 -6
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-chat-web.mjs +29 -7
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-comments.mjs +28 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-contacts.mjs +19 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-coupons.mjs +14 -6
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-data-collections.mjs +19 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-data.mjs +15 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-donations.mjs +19 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-ecom.mjs +33 -16
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-email-marketing.mjs +19 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-events.mjs +14 -6
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-faq.mjs +20 -6
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-forms.mjs +19 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-forum.mjs +19 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-gift-cards.mjs +19 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-groups.mjs +19 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-inbox.mjs +21 -7
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-invoices.mjs +14 -6
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-loyalty.mjs +16 -8
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-marketing.mjs +19 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-members-feed-viewer.mjs +21 -10
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-members.mjs +17 -8
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-new-releases.mjs +17 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-notification-preferences.mjs +20 -6
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-notifications.mjs +19 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-online-programs.mjs +16 -8
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-portfolio.mjs +16 -8
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-pricing-plans.mjs +22 -14
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-redirects.mjs +19 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-restaurants.mjs +22 -7
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-reviews.mjs +14 -6
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-rich-content-editor.mjs +3 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-seo.mjs +19 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-site-list.mjs +19 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-social-feed.mjs +15 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-stores-collections.mjs +20 -10
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-stores.mjs +116 -83
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-table-reservations.mjs +16 -8
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-users.mjs +15 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-video.mjs +9 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-workflows.mjs +19 -5
- package/dist/cli.mjs +90 -57
- package/dist/preview-assets.generated.bin +0 -0
- package/fixtures/wix-canned.json +8 -8
- package/guides/dynamic-list.service.ts +38 -29
- package/guides/form-submit.service.ts +2 -1
- package/guides/index.json +6 -0
- package/guides/offline-reading.md +63 -0
- package/guides/recipe-dynamic-list.md +2 -0
- package/guides/recipe-four-state.md +1 -0
- package/guides/sdk-reference.json +225 -99
- package/guides/testing-himi-apps.md +2 -0
- package/guides/tier-5-add-a-screen.md +2 -0
- package/package.json +2 -2
- package/templates/beauty-salon/dev/index.ts +4 -3
- package/templates/beauty-salon/tier5-src/_shared/collection-service.ts +6 -9
- package/templates/beauty-salon/tier5-src/_shared/iap-presentation.ts +7 -3
- package/templates/beauty-salon/tier5-src/himi-branded-lite-home/index.ts +1 -1
- package/templates/beauty-salon/tier5-src/himi-branded-lite-orders/index.ts +3 -0
- package/templates/beauty-salon-owner/dev/index.ts +19 -19
- package/templates/beauty-salon-owner/tier5-src/_shared/collection-service.ts +6 -9
- package/templates/beauty-salon-owner/tier5-src/_shared/owner-module-data.ts +1 -1
- package/templates/branded-lite/dev/index.ts +38 -20
- package/templates/branded-lite/tier5-src/_shared/collection-query-legacy.ts +194 -0
- package/templates/branded-lite/tier5-src/_shared/collection-query.ts +158 -99
- package/templates/branded-lite/tier5-src/_shared/collection-service.ts +31 -11
- package/templates/branded-lite/tier5-src/_shared/iap-presentation.ts +7 -3
- package/templates/branded-lite/tier5-src/_shared/read-service.ts +255 -0
- package/templates/branded-lite/tier5-src/himi-branded-lite-home/index.ts +1 -1
- package/templates/branded-lite/tier5-src/himi-branded-lite-orders/index.ts +3 -0
- package/templates/branded-lite/tier5-src/himi-branded-lite-shop/index.ts +202 -159
- package/templates/branded-lite/tier5-src/himi-store-product/index.ts +130 -201
- package/templates/community-club/dev/index.ts +4 -4
- package/templates/community-club/tier5-src/_shared/collection-service.ts +6 -9
- package/templates/community-club/tier5-src/_shared/iap-presentation.ts +7 -3
- package/templates/community-club/tier5-src/himi-branded-lite-home/index.ts +1 -1
- package/templates/community-club-owner/dev/index.ts +19 -19
- package/templates/community-club-owner/tier5-src/_shared/collection-service.ts +6 -9
- package/templates/community-club-owner/tier5-src/_shared/owner-module-data.ts +1 -1
- package/templates/events-meetups/dev/index.ts +3 -3
- package/templates/events-meetups/tier5-src/_shared/collection-service.ts +6 -9
- package/templates/events-meetups/tier5-src/_shared/iap-presentation.ts +7 -3
- package/templates/events-meetups/tier5-src/himi-branded-lite-home/index.ts +1 -1
- package/templates/events-meetups-owner/dev/index.ts +17 -17
- package/templates/events-meetups-owner/tier5-src/_shared/collection-service.ts +6 -9
- package/templates/events-meetups-owner/tier5-src/_shared/owner-module-data.ts +1 -1
- package/templates/gym-fitness/dev/index.ts +5 -4
- package/templates/gym-fitness/tier5-src/_shared/collection-service.ts +6 -9
- package/templates/gym-fitness/tier5-src/_shared/iap-presentation.ts +7 -3
- package/templates/gym-fitness/tier5-src/himi-branded-lite-home/index.ts +1 -1
- package/templates/gym-fitness/tier5-src/himi-branded-lite-orders/index.ts +3 -0
- package/templates/gym-fitness-owner/dev/index.ts +20 -20
- package/templates/gym-fitness-owner/tier5-src/_shared/collection-service.ts +6 -9
- package/templates/gym-fitness-owner/tier5-src/_shared/owner-module-data.ts +1 -1
- package/templates/nonprofit-cause/dev/index.ts +4 -4
- package/templates/nonprofit-cause/tier5-src/_shared/collection-service.ts +6 -9
- package/templates/nonprofit-cause/tier5-src/_shared/iap-presentation.ts +7 -3
- package/templates/nonprofit-cause/tier5-src/himi-branded-lite-home/index.ts +1 -1
- package/templates/nonprofit-cause-owner/dev/index.ts +18 -18
- package/templates/nonprofit-cause-owner/tier5-src/_shared/collection-service.ts +6 -9
- package/templates/nonprofit-cause-owner/tier5-src/_shared/owner-module-data.ts +1 -1
- package/templates/owner-lite/dev/index.ts +20 -20
- package/templates/owner-lite/tier5-src/_shared/collection-service.ts +6 -9
- package/templates/owner-lite/tier5-src/_shared/owner-module-data.ts +1 -1
- package/templates/podcast-creator/dev/index.ts +4 -4
- package/templates/podcast-creator/tier5-src/_shared/collection-service.ts +6 -9
- package/templates/podcast-creator/tier5-src/_shared/iap-presentation.ts +7 -3
- package/templates/podcast-creator/tier5-src/himi-branded-lite-home/index.ts +1 -1
- package/templates/podcast-creator-owner/dev/index.ts +19 -19
- package/templates/podcast-creator-owner/tier5-src/_shared/collection-service.ts +6 -9
- package/templates/podcast-creator-owner/tier5-src/_shared/owner-module-data.ts +1 -1
- package/templates/portfolio-creative/dev/index.ts +5 -4
- package/templates/portfolio-creative/tier5-src/_shared/collection-service.ts +6 -9
- package/templates/portfolio-creative/tier5-src/_shared/iap-presentation.ts +7 -3
- package/templates/portfolio-creative/tier5-src/himi-branded-lite-home/index.ts +1 -1
- package/templates/portfolio-creative/tier5-src/himi-branded-lite-orders/index.ts +3 -0
- package/templates/portfolio-creative-owner/dev/index.ts +19 -19
- package/templates/portfolio-creative-owner/tier5-src/_shared/collection-service.ts +6 -9
- package/templates/portfolio-creative-owner/tier5-src/_shared/owner-module-data.ts +1 -1
- package/templates/restaurant/dev/index.ts +3 -3
- package/templates/restaurant/tier5-src/_shared/collection-service.ts +6 -9
- package/templates/restaurant/tier5-src/_shared/iap-presentation.ts +7 -3
- package/templates/restaurant/tier5-src/himi-branded-lite-home/index.ts +1 -1
- package/templates/restaurant-owner/dev/index.ts +20 -20
- package/templates/restaurant-owner/tier5-src/_shared/collection-service.ts +6 -9
- package/templates/restaurant-owner/tier5-src/_shared/owner-module-data.ts +1 -1
- package/templates/retail-store/dev/index.ts +19 -1
- package/templates/retail-store/tier5-src/_shared/collection-query-legacy.ts +194 -0
- package/templates/retail-store/tier5-src/_shared/collection-query.ts +158 -99
- package/templates/retail-store/tier5-src/_shared/collection-service.ts +31 -11
- package/templates/retail-store/tier5-src/_shared/iap-presentation.ts +7 -3
- package/templates/retail-store/tier5-src/_shared/read-service.ts +255 -0
- package/templates/retail-store/tier5-src/himi-branded-lite-home/index.ts +1 -1
- package/templates/retail-store/tier5-src/himi-branded-lite-orders/index.ts +3 -0
- package/templates/retail-store/tier5-src/himi-branded-lite-shop/index.ts +202 -159
- package/templates/retail-store/tier5-src/himi-store-product/index.ts +130 -201
- package/templates/retail-store-owner/dev/index.ts +18 -18
- package/templates/retail-store-owner/tier5-src/_shared/collection-service.ts +6 -9
- package/templates/retail-store-owner/tier5-src/_shared/owner-module-data.ts +1 -1
- package/templates/yoga-studio/dev/index.ts +4 -4
- package/templates/yoga-studio/tier5-src/_shared/collection-service.ts +6 -9
- package/templates/yoga-studio/tier5-src/_shared/iap-presentation.ts +7 -3
- package/templates/yoga-studio/tier5-src/himi-branded-lite-home/index.ts +1 -1
- package/templates/yoga-studio-owner/dev/index.ts +18 -18
- package/templates/yoga-studio-owner/tier5-src/_shared/collection-service.ts +6 -9
- package/templates/yoga-studio-owner/tier5-src/_shared/owner-module-data.ts +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { withReadLifecycle, readOptions } from "../_shared/read-service.js";
|
|
1
2
|
import { withOnlineWrites, offlineWritesEnabled, offlineWriteMessage } from "../_shared/online-actions.js";
|
|
2
3
|
import { defineService as registerState } from "@himalaya/state";
|
|
3
4
|
// Tier-5 bundle: himi-store — product detail.
|
|
@@ -6,7 +7,10 @@ import { storesAppleSalesEnabled, storesProductOrders, type IapCommerce, type Ia
|
|
|
6
7
|
import { iapPriceCopy, iapPurchaseCopy } from "../_shared/iap-worker.js";
|
|
7
8
|
import { share as shareSheet } from "@himalaya/share";
|
|
8
9
|
import { addToCurrentCart, getCurrentCart } from "@himalaya/wix-ecom";
|
|
9
|
-
import {
|
|
10
|
+
import { upsert, enqueue, type DbEntity } from "@himalaya/local-db";
|
|
11
|
+
|
|
12
|
+
async function cartPut(row: DbEntity): Promise<void> { try { await upsert("cart", row); } catch { /* capability not granted */ } }
|
|
13
|
+
async function queueWrite(actionId: string, params: Record<string, string>): Promise<void> { try { await enqueue(actionId, params); } catch { /* capability not granted */ } }
|
|
10
14
|
import { getStoreProduct, plainText, productImage, productPrice, wixMediaUrl, productGallery as sdkProductGallery, WIX_DETAIL_IMAGE, type StoreProduct,
|
|
11
15
|
productOptions, defaultSelection, isSelectionComplete, selectionSummary, cartOptionsPayload,
|
|
12
16
|
type StoreOption, type StoreOptionChoice, type StoreOptionSelection } from "../_shared/himi-store.js";
|
|
@@ -17,21 +21,6 @@ import { isProductSaved, toggleSavedProduct } from "../_shared/himi-store-saved.
|
|
|
17
21
|
import { openRichLink } from "../_shared/rich-content-link.js";
|
|
18
22
|
import { richBody } from "../_shared/rich-body.js";
|
|
19
23
|
|
|
20
|
-
// Offline-first (data-offline): the detail is a public READ-THROUGH — when the live
|
|
21
|
-
// product fetch fails (offline) fall back to the last-synced row the catalog cached
|
|
22
|
-
// under the `products` entity. `addToCart` is WRITE-BEHIND against the `cart` entity —
|
|
23
|
-
// the line is cached OPTIMISTICALLY, then the Wix write is attempted; if it can't
|
|
24
|
-
// reach the bridge/network the add is ENQUEUED for replay on reconnect. Every local-db
|
|
25
|
-
// call is wrapped so a build without the `local_database` grant behaves exactly as
|
|
26
|
-
// before (online-only, no cache/queue).
|
|
27
|
-
const PRODUCTS_ENTITY = "products";
|
|
28
|
-
const CART_ENTITY = "cart";
|
|
29
|
-
async function readCachedProduct(id: string): Promise<DbEntity | null> {
|
|
30
|
-
try { return await get(PRODUCTS_ENTITY, id); } catch { /* capability not granted → online-only */ return null; }
|
|
31
|
-
}
|
|
32
|
-
async function cartPut(row: DbEntity): Promise<void> { try { await upsert(CART_ENTITY, row); } catch { /* capability not granted */ } }
|
|
33
|
-
async function queueWrite(actionId: string, params: Record<string, string>): Promise<void> { try { await enqueue(actionId, params); } catch { /* capability not granted */ } }
|
|
34
|
-
|
|
35
24
|
/** Live cart size (sum of line-item quantities) for the top-bar cart badge.
|
|
36
25
|
* Best-effort: a cart error just yields 0 (badge hidden), never fails the screen. */
|
|
37
26
|
async function cartItemCount(): Promise<number> {
|
|
@@ -95,25 +84,6 @@ function productPolicyBody(product: StoreProduct, kind: "returns" | "shipping"):
|
|
|
95
84
|
* DIFFERENT product (drop the picks) from the same product coming back (keep them). */
|
|
96
85
|
let lastLoadedId: string | undefined;
|
|
97
86
|
let productLoadSequence = 0;
|
|
98
|
-
let booting = true;
|
|
99
|
-
let bootLoad: { id: string; state: Promise<S> } | undefined;
|
|
100
|
-
|
|
101
|
-
/** The host replays the screen's onAppear load right after the module-scope one: that one replay
|
|
102
|
-
* joins the boot load instead of reading the product, cart and App Store prices again. Any later
|
|
103
|
-
* entry loads afresh, since the cart, the saved flag or a purchase may have changed meanwhile. */
|
|
104
|
-
function joinedLoad(id: string, load: () => Promise<S>): Promise<S> {
|
|
105
|
-
if (booting) {
|
|
106
|
-
booting = false;
|
|
107
|
-
const current = { id, state: load() };
|
|
108
|
-
bootLoad = current;
|
|
109
|
-
const settle = () => { if (bootLoad === current) bootLoad = undefined; };
|
|
110
|
-
current.state.then(settle, settle);
|
|
111
|
-
return current.state;
|
|
112
|
-
}
|
|
113
|
-
const replayed = bootLoad;
|
|
114
|
-
bootLoad = undefined;
|
|
115
|
-
return replayed?.id === id ? replayed.state : load();
|
|
116
|
-
}
|
|
117
87
|
|
|
118
88
|
interface OptionSlots {
|
|
119
89
|
opt1Label: string; opt1Chips: OptionChip[]; opt1Selected: string[]; opt1SelectedId: string; opt1Placeholder: string; noOpt1: boolean;
|
|
@@ -280,6 +250,7 @@ interface S {
|
|
|
280
250
|
emptyText: string;
|
|
281
251
|
isLoading: boolean;
|
|
282
252
|
notLoading: boolean;
|
|
253
|
+
hideContent: boolean;
|
|
283
254
|
isErrored: boolean;
|
|
284
255
|
notErrored: boolean;
|
|
285
256
|
noEmpty: boolean;
|
|
@@ -435,6 +406,7 @@ function derive(s: S): S {
|
|
|
435
406
|
notAdded: !s.added,
|
|
436
407
|
isLoading: s.status === "loading",
|
|
437
408
|
notLoading: s.status !== "loading",
|
|
409
|
+
hideContent: s.status !== "ready" || !s.name,
|
|
438
410
|
isErrored: s.status === "error",
|
|
439
411
|
notErrored: s.status !== "error",
|
|
440
412
|
noEmpty: s.status === "loading" || s.status === "error" || !empty,
|
|
@@ -460,11 +432,11 @@ const NOT_APPLE: IapPurchaseFields = { appleRoute: false, accessReady: false, bu
|
|
|
460
432
|
|
|
461
433
|
let productPricing: IapCommerce;
|
|
462
434
|
let checkoutEntered = false;
|
|
463
|
-
const
|
|
435
|
+
const registerProduct = withIapPresentation<S>({
|
|
464
436
|
register: withOnlineWrites(registerState, ["beginAdd", "addToCart", "buy"], { derive, messageFields: action => action === "buy" ? ["buyNote"] : ["cartHint"] }),
|
|
465
437
|
adapters: SELLS_THROUGH_APPLE ? [storesProductOrders] : [],
|
|
466
438
|
onCreate: commerce => { productPricing = commerce; }, prefix: "product",
|
|
467
|
-
transientKeys: ["price", "optionsIncomplete", "cartHint", "cartHidden", "buyHidden", "buyLabel", "buyDisabled", "buyNote", "purchasedNote", "addedSheetPresented", "shareHint"], contentActions: ["load", "
|
|
439
|
+
transientKeys: ["price", "optionsIncomplete", "cartHint", "cartHidden", "buyHidden", "buyLabel", "buyDisabled", "buyNote", "purchasedNote", "addedSheetPresented", "shareHint"], contentActions: ["load", "readChanged"], concurrentPublishActions: ["buy"],
|
|
468
440
|
items: state => inputId() ? [{ reference: { kind: "storesProduct", id: inputId() }, commerceDisplayPrice: state.price }] : [],
|
|
469
441
|
present: (state, price, allowed) => {
|
|
470
442
|
const purchase = applePurchase(state);
|
|
@@ -475,14 +447,33 @@ const defineService = withIapPresentation<S>({
|
|
|
475
447
|
return {
|
|
476
448
|
...state, price: price(inputId()), ...(purchase.appleRoute ? { wasPrice: "", wasPriceEmpty: false, notOnSale: true } : {}), optionsIncomplete: derive(state).optionsIncomplete || !allowed(inputId()) || lastProduct?.productType?.toLowerCase() === "digital",
|
|
477
449
|
cartHint, noCartHint: !cartHint || state.added, addDisabled: state.addDisabled || blocked,
|
|
478
|
-
cartHidden: purchase.appleRoute,
|
|
479
|
-
buyHidden: !purchase.appleRoute || purchase.accessReady, buyLabel: purchase.buyLabel, buyDisabled: purchase.buyDisabled,
|
|
450
|
+
cartHidden: state.status !== "ready" || !state.name || purchase.appleRoute,
|
|
451
|
+
buyHidden: state.status !== "ready" || !state.name || !purchase.appleRoute || purchase.accessReady, buyLabel: purchase.buyLabel, buyDisabled: purchase.buyDisabled,
|
|
480
452
|
buyNote: state.buyNote === offlineWriteMessage ? state.buyNote : purchase.buyNote,
|
|
481
453
|
purchasedNote: purchase.accessReady ? copyParam("product.purchasedText", "Purchased") : "",
|
|
482
454
|
};
|
|
483
455
|
},
|
|
484
456
|
});
|
|
485
457
|
|
|
458
|
+
// Read recovery commits content before IAP sidecars project prices. Cache and network
|
|
459
|
+
// reads stay inside one safe read lifecycle; price publications never become read results.
|
|
460
|
+
const defineService = withReadLifecycle(registerProduct, "load", {
|
|
461
|
+
// Missing route input is authored local content, not a server response or cache hit.
|
|
462
|
+
localResult: () => !inputId(),
|
|
463
|
+
onInvalidate: () => {
|
|
464
|
+
productLoadSequence++;
|
|
465
|
+
lastProduct = undefined;
|
|
466
|
+
lastLoadedId = undefined;
|
|
467
|
+
cartBadgeEpoch++;
|
|
468
|
+
},
|
|
469
|
+
unavailable: state => {
|
|
470
|
+
lastProduct = undefined;
|
|
471
|
+
lastLoadedId = undefined;
|
|
472
|
+
return { ...derive(state as unknown as S) };
|
|
473
|
+
},
|
|
474
|
+
authoredFallback: state => !inputId() ? { ...derive({ ...state, status: "ready", emptyText: copyParam("product.notFoundText", "Product not found.") } as unknown as S) } : undefined,
|
|
475
|
+
});
|
|
476
|
+
|
|
486
477
|
/** The App Store action, only for the one shape it sells: digital, with no options to choose, read
|
|
487
478
|
* from the product loaded for the id on screen (as Add to cart is). A cached product whose
|
|
488
479
|
* options were never read is not known to have none. */
|
|
@@ -502,7 +493,8 @@ function enterCheckout(): void {
|
|
|
502
493
|
checkoutEntered = true;
|
|
503
494
|
}
|
|
504
495
|
|
|
505
|
-
const
|
|
496
|
+
const onlineService = defineService;
|
|
497
|
+
const svc = onlineService<S, {
|
|
506
498
|
load: (s: S, arg?: unknown) => Promise<S>;
|
|
507
499
|
setQuantity: (s: S, arg?: unknown) => S;
|
|
508
500
|
toggleReturnPolicy: (s: S) => S;
|
|
@@ -510,7 +502,6 @@ const svc = defineService<S, {
|
|
|
510
502
|
selectOption: (s: S, arg?: unknown) => S;
|
|
511
503
|
addToCart: (s: S) => Promise<S>;
|
|
512
504
|
beginAdd: (s: S, arg?: unknown) => S;
|
|
513
|
-
paintCached: (s: S, arg?: unknown) => S;
|
|
514
505
|
setCartCount: (s: S, arg?: unknown) => S;
|
|
515
506
|
share: (s: S) => Promise<S>;
|
|
516
507
|
toggleSave: (s: S) => S;
|
|
@@ -565,7 +556,7 @@ const svc = defineService<S, {
|
|
|
565
556
|
notAdded: true,
|
|
566
557
|
emptyText: "",
|
|
567
558
|
isLoading: true,
|
|
568
|
-
notLoading: false,
|
|
559
|
+
notLoading: false, hideContent: true,
|
|
569
560
|
isErrored: false,
|
|
570
561
|
notErrored: true,
|
|
571
562
|
noEmpty: true,
|
|
@@ -600,146 +591,106 @@ const svc = defineService<S, {
|
|
|
600
591
|
purchasedNote: "",
|
|
601
592
|
}),
|
|
602
593
|
actions: {
|
|
603
|
-
load: (s, arg): Promise<S> => {
|
|
594
|
+
load: async (s, arg): Promise<S> => {
|
|
604
595
|
stashCopy(arg);
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
596
|
+
enterCheckout();
|
|
597
|
+
const sequence = ++productLoadSequence;
|
|
598
|
+
const id = inputId();
|
|
599
|
+
// A managed refresh retains the raw product used by the still-visible snapshot.
|
|
600
|
+
// Navigation and legacy loaders keep their existing reset behavior.
|
|
601
|
+
if (!readOptions(arg) || id !== lastLoadedId) lastProduct = undefined;
|
|
602
|
+
// Storage problems must not prevent browsing or buying a product.
|
|
603
|
+
let saved = false;
|
|
604
|
+
try { saved = isProductSaved(id); } catch { /* save action reports a retryable error */ }
|
|
605
|
+
s = { ...s, saved, saveHint: "",
|
|
606
|
+
...(id !== lastLoadedId ? { adding: false, added: false, shareHint: "", addedSheetPresented: false, quantity: 1, showOptionErrors: false, returnPolicyExpanded: false, shippingInfoExpanded: false } : {}) };
|
|
607
|
+
// A fresh navigation into the product resets any quantity left over
|
|
608
|
+
// from a previous visit to the same worker instance.
|
|
609
|
+
if (!id) {
|
|
608
610
|
lastProduct = undefined;
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
const
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
const
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
const
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
const
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
// A group with exactly one choice is chosen for the shopper; a real choice
|
|
667
|
-
// is left blank so the pick is deliberate.
|
|
668
|
-
const optionGroups = productOptions(p);
|
|
669
|
-
const sale = productSale(p);
|
|
670
|
-
// A pooled screen re-appearing re-runs `load`. Wiping `selection` there means a
|
|
671
|
-
// trip to the cart and back silently clears the size the shopper picked and
|
|
672
|
-
// re-disables the CTA with no explanation. Carry the picks when this is the SAME
|
|
673
|
-
// product, and only for a choice the product still offers — a stale id would
|
|
674
|
-
// resolve to no variant and block the cart just as silently.
|
|
675
|
-
const carried: StoreOptionSelection = {};
|
|
676
|
-
if (id === lastLoadedId) {
|
|
677
|
-
for (const g of optionGroups) {
|
|
678
|
-
const chosen = s.selection[g.id];
|
|
679
|
-
if (chosen && g.choices.some((c) => c.id === chosen)) carried[g.id] = chosen;
|
|
680
|
-
}
|
|
611
|
+
lastLoadedId = undefined;
|
|
612
|
+
return derive({ ...s, status: "ready", quantity: 1, optionGroups: [], selection: {}, optionsUnknown: false, descriptionJson: "", emptyText: copyParam("product.notFoundText", "Product not found.") });
|
|
613
|
+
}
|
|
614
|
+
// The cart count only feeds the top-bar badge: ask for it NOW, beside the product, instead
|
|
615
|
+
// of after it — it used to add a whole cart round trip before the page could paint.
|
|
616
|
+
const cartCount = readOptions(arg)?.cache === "only-if-cached" ? Promise.resolve(s.cartCount) : cartItemCount();
|
|
617
|
+
// The badge must never hold the page: remember the count if it is already in, and
|
|
618
|
+
// publish it separately if it lands after the product (#3468 review).
|
|
619
|
+
let cartKnown: number | undefined;
|
|
620
|
+
void cartCount.then((n) => { cartKnown = n; }, () => {});
|
|
621
|
+
// The live product read goes out FIRST too — the local-db read below must never delay it.
|
|
622
|
+
// Settled into a value so a failure is handled where it is awaited, never unhandled.
|
|
623
|
+
// DESCRIPTION widens the default fieldset with the V3 Ricos description (a V1 catalog ignores it).
|
|
624
|
+
const live = getStoreProduct(id, ["DESCRIPTION"], readOptions(arg)).then(
|
|
625
|
+
(r) => ({ ok: true as const, r }),
|
|
626
|
+
(error) => ({ ok: false as const, error }),
|
|
627
|
+
);
|
|
628
|
+
const outcome = await live;
|
|
629
|
+
if (sequence !== productLoadSequence || id !== inputId()) return svc.getState() as S;
|
|
630
|
+
// The cache may have painted AFTER this network read started. Check the
|
|
631
|
+
// current state when the response lands, not the captured loading state.
|
|
632
|
+
const current = svc.getState() as S;
|
|
633
|
+
const painted = current.status === "ready" && lastLoadedId === id;
|
|
634
|
+
// Once painted the page is INTERACTIVE while the live read is on the wire: the visitor may
|
|
635
|
+
// save, change the quantity or add to cart. Build on the state as it is NOW, and keep what
|
|
636
|
+
// they did — overwriting it would untick a stored save, reset the quantity, and drop the
|
|
637
|
+
// in-flight add's `adding` guard (a second tap would add the line twice).
|
|
638
|
+
const base: S = painted ? current : s;
|
|
639
|
+
const keep = painted
|
|
640
|
+
? { saved: base.saved, saveHint: base.saveHint, quantity: base.quantity, adding: base.adding, added: base.added, cartHint: base.cartHint }
|
|
641
|
+
: { cartHint: "", quantity: 1 };
|
|
642
|
+
const badge = (): number => {
|
|
643
|
+
if (painted && (base.adding || base.added)) return base.cartCount;
|
|
644
|
+
if (cartKnown !== undefined) return cartKnown;
|
|
645
|
+
const epoch = cartBadgeEpoch;
|
|
646
|
+
void cartCount.then((n) => { void svc.setCartCount({ count: n, epoch }); }, () => {});
|
|
647
|
+
return base.cartCount;
|
|
648
|
+
};
|
|
649
|
+
if (outcome.ok) {
|
|
650
|
+
const p = (outcome.r.product ?? (outcome.r as unknown as StoreProduct)) as StoreProduct;
|
|
651
|
+
const name = cleanTitle(p.name) || "Product";
|
|
652
|
+
const image = productImage(p, WIX_DETAIL_IMAGE);
|
|
653
|
+
lastProduct = p;
|
|
654
|
+
// A group with exactly one choice is chosen for the shopper; a real choice
|
|
655
|
+
// is left blank so the pick is deliberate.
|
|
656
|
+
const optionGroups = productOptions(p);
|
|
657
|
+
const sale = productSale(p);
|
|
658
|
+
// A pooled screen re-appearing re-runs `load`. Wiping `selection` there means a
|
|
659
|
+
// trip to the cart and back silently clears the size the shopper picked and
|
|
660
|
+
// re-disables the CTA with no explanation. Carry the picks when this is the SAME
|
|
661
|
+
// product, and only for a choice the product still offers — a stale id would
|
|
662
|
+
// resolve to no variant and block the cart just as silently.
|
|
663
|
+
const carried: StoreOptionSelection = {};
|
|
664
|
+
if (id === lastLoadedId) {
|
|
665
|
+
for (const g of optionGroups) {
|
|
666
|
+
const chosen = base.selection[g.id];
|
|
667
|
+
if (chosen && g.choices.some((c) => c.id === chosen)) carried[g.id] = chosen;
|
|
681
668
|
}
|
|
682
|
-
lastLoadedId = id;
|
|
683
|
-
return derive({
|
|
684
|
-
...base,
|
|
685
|
-
...keep,
|
|
686
|
-
status: "ready",
|
|
687
|
-
optionGroups,
|
|
688
|
-
selection: { ...defaultSelection(optionGroups), ...carried },
|
|
689
|
-
optionsUnknown: false,
|
|
690
|
-
name,
|
|
691
|
-
...sale,
|
|
692
|
-
commercePrice: sale.price,
|
|
693
|
-
skuLabel: skuOf(p) ? `SKU: ${skuOf(p)}` : "",
|
|
694
|
-
returnPolicyBody: productPolicyBody(p, "returns") || copyParam("product.returnPolicyBody", "") || copyParam("product.policyUnavailable", "Policy details have not been provided by this store."),
|
|
695
|
-
shippingInfoBody: productPolicyBody(p, "shipping") || copyParam("product.shippingInfoBody", "") || copyParam("product.policyUnavailable", "Policy details have not been provided by this store."),
|
|
696
|
-
...productBody(p),
|
|
697
|
-
image,
|
|
698
|
-
gallery: productGallery(p),
|
|
699
|
-
initial: (name[0] || "#").toUpperCase(),
|
|
700
|
-
shareUrl: productShareUrl(p),
|
|
701
|
-
cartCount: badge(),
|
|
702
|
-
emptyText: "",
|
|
703
|
-
});
|
|
704
|
-
}
|
|
705
|
-
// Offline: fall back to the last-synced cached product row before the error state.
|
|
706
|
-
if (synced) {
|
|
707
|
-
const name = String(synced.name ?? "") || "Product";
|
|
708
|
-
const image = String(synced.image ?? "");
|
|
709
|
-
// The cached list row carries no options, and guessing "none" would offer
|
|
710
|
-
// a one-tap Add to cart for a product that needs a colour and a size. So
|
|
711
|
-
// the offline detail shows no picker AND marks the options UNKNOWN, which
|
|
712
|
-
// keeps `optionsIncomplete` true: the CTA stays disabled and `addToCart`
|
|
713
|
-
// refuses. `cartHint` carries the reason, because the options card is hidden
|
|
714
|
-
// on `noOptions` and would otherwise leave a dead button unexplained.
|
|
715
|
-
lastProduct = undefined;
|
|
716
|
-
lastLoadedId = undefined;
|
|
717
|
-
return derive({
|
|
718
|
-
...base,
|
|
719
|
-
...keep,
|
|
720
|
-
status: "ready",
|
|
721
|
-
optionGroups: [],
|
|
722
|
-
selection: {},
|
|
723
|
-
optionsUnknown: true,
|
|
724
|
-
name,
|
|
725
|
-
price: String(synced.subtitle ?? ""),
|
|
726
|
-
wasPrice: "",
|
|
727
|
-
skuLabel: "",
|
|
728
|
-
returnPolicyBody: "",
|
|
729
|
-
shippingInfoBody: "",
|
|
730
|
-
description: "",
|
|
731
|
-
descriptionJson: "",
|
|
732
|
-
image,
|
|
733
|
-
initial: String(synced.initial ?? "") || (name[0] || "#").toUpperCase(),
|
|
734
|
-
cartHint: copyParam("product.cartHintOffline", "Reconnect to choose options and add this to your cart."),
|
|
735
|
-
cartCount: badge(),
|
|
736
|
-
emptyText: "",
|
|
737
|
-
});
|
|
738
669
|
}
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
670
|
+
lastLoadedId = id;
|
|
671
|
+
return derive({
|
|
672
|
+
...base,
|
|
673
|
+
...keep,
|
|
674
|
+
status: "ready",
|
|
675
|
+
optionGroups,
|
|
676
|
+
selection: { ...defaultSelection(optionGroups), ...carried },
|
|
677
|
+
optionsUnknown: false,
|
|
678
|
+
name,
|
|
679
|
+
...sale,
|
|
680
|
+
commercePrice: sale.price,
|
|
681
|
+
skuLabel: skuOf(p) ? `SKU: ${skuOf(p)}` : "",
|
|
682
|
+
returnPolicyBody: productPolicyBody(p, "returns") || copyParam("product.returnPolicyBody", "") || copyParam("product.policyUnavailable", "Policy details have not been provided by this store."),
|
|
683
|
+
shippingInfoBody: productPolicyBody(p, "shipping") || copyParam("product.shippingInfoBody", "") || copyParam("product.policyUnavailable", "Policy details have not been provided by this store."),
|
|
684
|
+
...productBody(p),
|
|
685
|
+
image,
|
|
686
|
+
gallery: productGallery(p),
|
|
687
|
+
initial: (name[0] || "#").toUpperCase(),
|
|
688
|
+
shareUrl: productShareUrl(p),
|
|
689
|
+
cartCount: badge(),
|
|
690
|
+
emptyText: "",
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
throw outcome.error;
|
|
743
694
|
},
|
|
744
695
|
// The stepper fires onChange with { value } on every tap; clamp 1–99 and
|
|
745
696
|
// ignore unparsable/garbage args instead of silently zeroing the quantity.
|
|
@@ -788,29 +739,7 @@ const svc = defineService<S, {
|
|
|
788
739
|
const n = Math.max(0, Math.floor(Number(count)));
|
|
789
740
|
return Number.isFinite(n) ? derive({ ...s, cartCount: n }) : s;
|
|
790
741
|
},
|
|
791
|
-
|
|
792
|
-
const row = (arg ?? {}) as DbEntity;
|
|
793
|
-
const name = String(row.name ?? "") || "Product";
|
|
794
|
-
return derive({
|
|
795
|
-
...s,
|
|
796
|
-
status: "ready",
|
|
797
|
-
name,
|
|
798
|
-
price: String(row.subtitle ?? ""),
|
|
799
|
-
commercePrice: String(row.subtitle ?? ""),
|
|
800
|
-
description: "",
|
|
801
|
-
descriptionJson: "",
|
|
802
|
-
image: String(row.image ?? ""),
|
|
803
|
-
gallery: [],
|
|
804
|
-
initial: String(row.initial ?? "") || (name[0] || "#").toUpperCase(),
|
|
805
|
-
// The synced list row carries no options: until the live read says what they are,
|
|
806
|
-
// they are UNKNOWN, which keeps the CTA disabled — never a one-tap Add to cart for a
|
|
807
|
-
// product that needs a size. The live read replaces this a moment later.
|
|
808
|
-
optionGroups: [],
|
|
809
|
-
optionsUnknown: true,
|
|
810
|
-
emptyText: "",
|
|
811
|
-
quantity: 1,
|
|
812
|
-
});
|
|
813
|
-
},
|
|
742
|
+
|
|
814
743
|
addToCart: async (s) => {
|
|
815
744
|
const id = inputId();
|
|
816
745
|
if (!productPricing.pricing.checkoutGuard({ kind: "storesProduct", id }).allowed || lastProduct?.productType?.toLowerCase() === "digital") return derive({ ...s, cartHint: iapPriceCopy("product").purchaseUnavailable });
|
|
@@ -8270,7 +8270,7 @@ const SCREENS = runtimeSetting({
|
|
|
8270
8270
|
"package": "himalaya",
|
|
8271
8271
|
"type": "Text",
|
|
8272
8272
|
"props": {
|
|
8273
|
-
"text": "Showing
|
|
8273
|
+
"text": "Showing previously loaded content · may be outdated",
|
|
8274
8274
|
"style": "caption",
|
|
8275
8275
|
"color": "textSecondary"
|
|
8276
8276
|
}
|
|
@@ -11836,7 +11836,7 @@ const SCREENS = runtimeSetting({
|
|
|
11836
11836
|
"package": "himalaya",
|
|
11837
11837
|
"type": "Text",
|
|
11838
11838
|
"props": {
|
|
11839
|
-
"text": "Showing
|
|
11839
|
+
"text": "Showing previously loaded content · may be outdated",
|
|
11840
11840
|
"style": "caption",
|
|
11841
11841
|
"color": "textSecondary"
|
|
11842
11842
|
}
|
|
@@ -14914,7 +14914,7 @@ const SCREENS = runtimeSetting({
|
|
|
14914
14914
|
"package": "himalaya",
|
|
14915
14915
|
"type": "Text",
|
|
14916
14916
|
"props": {
|
|
14917
|
-
"text": "Showing
|
|
14917
|
+
"text": "Showing previously loaded content · may be outdated",
|
|
14918
14918
|
"style": "caption",
|
|
14919
14919
|
"color": "textSecondary"
|
|
14920
14920
|
}
|
|
@@ -17340,7 +17340,7 @@ const SCREENS = runtimeSetting({
|
|
|
17340
17340
|
"package": "himalaya",
|
|
17341
17341
|
"type": "Text",
|
|
17342
17342
|
"props": {
|
|
17343
|
-
"text": "Showing
|
|
17343
|
+
"text": "Showing previously loaded content · may be outdated",
|
|
17344
17344
|
"style": "caption",
|
|
17345
17345
|
"color": "textSecondary"
|
|
17346
17346
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { withOnlineWrites } from './online-actions.js';
|
|
2
1
|
import { defineService as register, type ServiceDefinition } from '@himalaya/state';
|
|
3
2
|
import { COLLECTIONS, COLLECTION_CHROME_MIN_ITEMS, initialCollection, normalizeCollection, projectCollection, collectionId, collectionActionsLabel, type CollectionRow } from './collection-contract.js';
|
|
4
3
|
import { localPreferences, type PreferenceRuntime } from './local-preferences.js';
|
|
@@ -95,10 +94,7 @@ export function decorateCollection(name: string, def: { state: State; actions?:
|
|
|
95
94
|
if (sort === 'default' || sort === 'az' || sort === 'za') { prefs.sort = sort; changed = true; }
|
|
96
95
|
}
|
|
97
96
|
if (Object.prototype.hasOwnProperty.call(input, 'collectionFilter')) {
|
|
98
|
-
const
|
|
99
|
-
// Old links to Saved must migrate with the stored preference when this
|
|
100
|
-
// collection no longer exposes that filter.
|
|
101
|
-
const filter = config.rowStyle === 'flat' && requestedFilter === 'saved' ? 'all' : requestedFilter;
|
|
97
|
+
const filter = String(input.collectionFilter ?? '');
|
|
102
98
|
const configured = config.filterValues ?? [];
|
|
103
99
|
const rows = Array.isArray(state[config.rows]) ? state[config.rows] as CollectionRow[] : [];
|
|
104
100
|
const derived = config.filter ? rows.map(row => String(row[config.filter!] ?? '')).filter(Boolean) : [];
|
|
@@ -142,7 +138,7 @@ export function decorateCollection(name: string, def: { state: State; actions?:
|
|
|
142
138
|
copyParam('collection.itemActionsFor', 'Actions for {title}'), copyParam('collection.itemActions', 'Item actions'));
|
|
143
139
|
});
|
|
144
140
|
if (previewId && !rows.some(row => collectionId(row) === previewId)) previewId = '';
|
|
145
|
-
const filterChoices = [{ id: 'all', label: copyParam('collection.all', 'All') },
|
|
141
|
+
const filterChoices = [{ id: 'all', label: copyParam('collection.all', 'All') }, { id: 'saved', label: copyParam('collection.saved', 'Saved') },
|
|
146
142
|
...projected.filters.map(label => ({ id: `value:${label}`, label: copyParam(`collection.filter.${label}`, label) }))];
|
|
147
143
|
const loading = s.status === 'loading' || s.isLoading === true;
|
|
148
144
|
// Older domain reducers expose `errored` rather than `isErrored`; backend
|
|
@@ -223,7 +219,7 @@ export function decorateCollection(name: string, def: { state: State; actions?:
|
|
|
223
219
|
? [copyParam(`collection.${name}.countOne`, config.countNoun[0]), copyParam(`collection.${name}.countMany`, config.countNoun[1])] : undefined }),
|
|
224
220
|
selectedSummary: `${prefs.selectedIds.length} ${copyParam('collection.selected', 'selected')}`,
|
|
225
221
|
filterChoices,
|
|
226
|
-
chips: config.filterValues
|
|
222
|
+
chips: config.filterValues ? filterChoices.filter(choice => ['all', 'saved', prefs.filter].includes(choice.id)) : filterChoices,
|
|
227
223
|
} };
|
|
228
224
|
};
|
|
229
225
|
const actions: Record<string, Reducer> = {};
|
|
@@ -374,8 +370,9 @@ export function defineBackendCollection<S extends object, Row extends object>(na
|
|
|
374
370
|
controller: controller as unknown as BackendCollection['controller'],
|
|
375
371
|
apply: (state, page) => options.apply(state as S, page as unknown as CollectionQueryState<Row>) as State,
|
|
376
372
|
});
|
|
377
|
-
|
|
378
|
-
|
|
373
|
+
// Compatibility starters retain their existing mutation behavior; accept the
|
|
374
|
+
// current authoring contract without enabling the offline-write rollout.
|
|
375
|
+
const handle = (options.register ?? register)(name, definition);
|
|
379
376
|
// Registration restored the state a cold boot saved: the page it showed is this run's, before the first load. Only
|
|
380
377
|
// when the service's own rows came back with it: a bundle that keeps them out of the restore (its `notHydrated`)
|
|
381
378
|
// starts its first load as before, never from rows it chose not to restore. Rows that came back empty are the
|
|
@@ -103,6 +103,8 @@ export function withIapPresentation<S extends object>(options: {
|
|
|
103
103
|
// scopeLanded is the completion of the active load, not a stale load result. It
|
|
104
104
|
// must publish even if another overlapping onAppear load advanced contentVersion.
|
|
105
105
|
if (!next || (content && action !== "scopeLanded" && version !== contentVersion)) return undefined;
|
|
106
|
+
// A committed read projection supersedes older load results still carrying a skeleton.
|
|
107
|
+
if (action === "readChanged" && definition.readLifecycle) contentVersion++;
|
|
106
108
|
if (content) {
|
|
107
109
|
options.onContent?.(next);
|
|
108
110
|
const nextItems = options.items(next);
|
|
@@ -130,9 +132,11 @@ export function withIapPresentation<S extends object>(options: {
|
|
|
130
132
|
};
|
|
131
133
|
try {
|
|
132
134
|
const next = reduce(state, ...args);
|
|
133
|
-
//
|
|
134
|
-
//
|
|
135
|
-
|
|
135
|
+
// A cached read projection must commit before another onAppear can consume it.
|
|
136
|
+
// Other content actions retain their scheduling: shop filters and panels can
|
|
137
|
+
// change while a load is pending, and their existing completion order matters.
|
|
138
|
+
const synchronousReadProjection = action === "readChanged" && !!definition.readLifecycle;
|
|
139
|
+
if ((content && !synchronousReadProjection) || (next && typeof (next as Promise<S | undefined>).then === "function")) {
|
|
136
140
|
return (async () => {
|
|
137
141
|
try { return presentResult(await next); }
|
|
138
142
|
finally { finished(); }
|
|
@@ -250,7 +250,7 @@ interface State {
|
|
|
250
250
|
hideFeaturedSkeleton: boolean;
|
|
251
251
|
welcome: string;
|
|
252
252
|
refreshedAt: string;
|
|
253
|
-
/** The resolved home layout preset (
|
|
253
|
+
/** The resolved home layout preset (shared slot discriminator).
|
|
254
254
|
* Plain string, never a proto enum — a `$service:` casePath decodes it as a
|
|
255
255
|
* JSON string and unknown values fall through to the shipped defaultCase. */
|
|
256
256
|
effectiveLayout: string;
|