@wix/himalaya-cli 0.1323.0 → 0.1325.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.
Files changed (193) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/checkout/src/index.d.ts +6 -10
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/order-refs.d.ts +1 -0
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/purchase-fields.d.ts +1 -0
  4. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/screens/src/index.d.ts +9 -35
  5. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/comments-v1/src/extensions.d.ts +79 -0
  6. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/groups/src/extensions.d.ts +221 -14
  7. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/groups/src/index.d.ts +0 -2
  8. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/social-feed/src/index.d.ts +38 -21
  9. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/stores-v1/src/display.d.ts +1 -0
  10. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/checkout.mjs +30 -13
  11. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/iap-checkout.mjs +20 -2
  12. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/screens.mjs +2890 -54
  13. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-comments.mjs +80 -0
  14. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-groups.mjs +45 -17
  15. package/dist/cli.mjs +5 -4
  16. package/fixtures/wix-canned.json +61 -6
  17. package/guides/iap-pricing.md +9 -0
  18. package/guides/iap-screen-adoption.md +77 -0
  19. package/guides/importable-sdks.md +2 -0
  20. package/guides/index.json +6 -0
  21. package/guides/release-notes.md +25 -0
  22. package/guides/sdk-reference.json +539 -32
  23. package/guides/wix-api-usage.md +5 -0
  24. package/package.json +2 -2
  25. package/templates/beauty-salon/config.ts +1 -1
  26. package/templates/beauty-salon/dev/index.ts +46 -18
  27. package/templates/beauty-salon/tier5-src/_shared/collection-contract.ts +1 -1
  28. package/templates/beauty-salon/tier5-src/_shared/collection-service.ts +3 -2
  29. package/templates/beauty-salon/tier5-src/_shared/himi-store-collection.ts +1 -1
  30. package/templates/beauty-salon/tier5-src/_shared/home-service.ts +2 -1
  31. package/templates/beauty-salon/tier5-src/_shared/iap-presentation.ts +53 -0
  32. package/templates/beauty-salon/tier5-src/_shared/iap-worker.ts +42 -0
  33. package/templates/beauty-salon/tier5-src/himi-branded-lite-cart/index.ts +48 -1
  34. package/templates/beauty-salon/tier5-src/himi-branded-lite-home/index.ts +16 -2
  35. package/templates/beauty-salon/tier5-src/himi-branded-lite-order/index.ts +24 -3
  36. package/templates/beauty-salon/tier5-src/himi-branded-lite-plans/index.ts +153 -64
  37. package/templates/beauty-salon/tier5-src/himi-store-product/index.ts +24 -3
  38. package/templates/beauty-salon/tier5-src/himi-store-saved/index.ts +8 -3
  39. package/templates/beauty-salon/tier5-src/himi-store-shop/index.ts +10 -0
  40. package/templates/beauty-salon/tier5-src/wix-spaces-plan-detail/index.ts +8 -3
  41. package/templates/beauty-salon-owner/tier5-src/_shared/collection-contract.ts +1 -1
  42. package/templates/beauty-salon-owner/tier5-src/_shared/collection-service.ts +3 -2
  43. package/templates/beauty-salon-owner/tier5-src/_shared/home-service.ts +2 -1
  44. package/templates/branded-lite/config.ts +1 -8
  45. package/templates/branded-lite/dev/index.ts +46 -134
  46. package/templates/branded-lite/himalaya.content.json +0 -3
  47. package/templates/branded-lite/tier5-src/_shared/collection-contract.ts +1 -1
  48. package/templates/branded-lite/tier5-src/_shared/collection-service.ts +3 -2
  49. package/templates/branded-lite/tier5-src/_shared/himi-store-collection.ts +1 -1
  50. package/templates/branded-lite/tier5-src/_shared/home-service.ts +2 -1
  51. package/templates/branded-lite/tier5-src/_shared/iap-presentation.ts +53 -0
  52. package/templates/branded-lite/tier5-src/himi-branded-lite-cart/index.ts +48 -1
  53. package/templates/branded-lite/tier5-src/himi-branded-lite-home/index.ts +16 -2
  54. package/templates/branded-lite/tier5-src/himi-branded-lite-order/index.ts +24 -3
  55. package/templates/branded-lite/tier5-src/himi-branded-lite-plans/index.ts +153 -64
  56. package/templates/branded-lite/tier5-src/himi-store-product/index.ts +24 -3
  57. package/templates/branded-lite/tier5-src/himi-store-saved/index.ts +8 -3
  58. package/templates/branded-lite/tier5-src/himi-store-shop/index.ts +10 -0
  59. package/templates/branded-lite/tier5-src/wix-spaces-plan-detail/index.ts +8 -3
  60. package/templates/community-club/config.ts +1 -8
  61. package/templates/community-club/dev/index.ts +3 -117
  62. package/templates/community-club/himalaya.content.json +0 -3
  63. package/templates/community-club/tier5-src/_shared/collection-contract.ts +1 -1
  64. package/templates/community-club/tier5-src/_shared/collection-service.ts +3 -2
  65. package/templates/community-club/tier5-src/_shared/home-service.ts +2 -1
  66. package/templates/community-club/tier5-src/_shared/iap-presentation.ts +53 -0
  67. package/templates/community-club/tier5-src/_shared/iap-worker.ts +42 -0
  68. package/templates/community-club/tier5-src/himi-branded-lite-home/index.ts +16 -2
  69. package/templates/community-club-owner/tier5-src/_shared/collection-contract.ts +1 -1
  70. package/templates/community-club-owner/tier5-src/_shared/collection-service.ts +3 -2
  71. package/templates/community-club-owner/tier5-src/_shared/home-service.ts +2 -1
  72. package/templates/events-meetups/config.ts +1 -8
  73. package/templates/events-meetups/dev/index.ts +3 -117
  74. package/templates/events-meetups/himalaya.content.json +0 -3
  75. package/templates/events-meetups/tier5-src/_shared/collection-contract.ts +1 -1
  76. package/templates/events-meetups/tier5-src/_shared/collection-service.ts +3 -2
  77. package/templates/events-meetups/tier5-src/_shared/home-service.ts +2 -1
  78. package/templates/events-meetups/tier5-src/_shared/iap-presentation.ts +53 -0
  79. package/templates/events-meetups/tier5-src/_shared/iap-worker.ts +42 -0
  80. package/templates/events-meetups/tier5-src/himi-branded-lite-home/index.ts +16 -2
  81. package/templates/events-meetups-owner/tier5-src/_shared/collection-contract.ts +1 -1
  82. package/templates/events-meetups-owner/tier5-src/_shared/collection-service.ts +3 -2
  83. package/templates/events-meetups-owner/tier5-src/_shared/home-service.ts +2 -1
  84. package/templates/gym-fitness/config.ts +1 -1
  85. package/templates/gym-fitness/dev/index.ts +46 -18
  86. package/templates/gym-fitness/tier5-src/_shared/collection-contract.ts +1 -1
  87. package/templates/gym-fitness/tier5-src/_shared/collection-service.ts +3 -2
  88. package/templates/gym-fitness/tier5-src/_shared/himi-store-collection.ts +1 -1
  89. package/templates/gym-fitness/tier5-src/_shared/home-service.ts +2 -1
  90. package/templates/gym-fitness/tier5-src/_shared/iap-presentation.ts +53 -0
  91. package/templates/gym-fitness/tier5-src/_shared/iap-worker.ts +42 -0
  92. package/templates/gym-fitness/tier5-src/himi-branded-lite-cart/index.ts +48 -1
  93. package/templates/gym-fitness/tier5-src/himi-branded-lite-home/index.ts +16 -2
  94. package/templates/gym-fitness/tier5-src/himi-branded-lite-order/index.ts +24 -3
  95. package/templates/gym-fitness/tier5-src/himi-branded-lite-plans/index.ts +153 -64
  96. package/templates/gym-fitness/tier5-src/himi-store-product/index.ts +24 -3
  97. package/templates/gym-fitness/tier5-src/himi-store-saved/index.ts +8 -3
  98. package/templates/gym-fitness/tier5-src/himi-store-shop/index.ts +10 -0
  99. package/templates/gym-fitness/tier5-src/wix-spaces-plan-detail/index.ts +8 -3
  100. package/templates/gym-fitness-owner/tier5-src/_shared/collection-contract.ts +1 -1
  101. package/templates/gym-fitness-owner/tier5-src/_shared/collection-service.ts +3 -2
  102. package/templates/gym-fitness-owner/tier5-src/_shared/home-service.ts +2 -1
  103. package/templates/nonprofit-cause/config.ts +1 -8
  104. package/templates/nonprofit-cause/dev/index.ts +29 -129
  105. package/templates/nonprofit-cause/himalaya.content.json +0 -3
  106. package/templates/nonprofit-cause/tier5-src/_shared/collection-contract.ts +1 -1
  107. package/templates/nonprofit-cause/tier5-src/_shared/collection-service.ts +3 -2
  108. package/templates/nonprofit-cause/tier5-src/_shared/home-service.ts +2 -1
  109. package/templates/nonprofit-cause/tier5-src/_shared/iap-presentation.ts +53 -0
  110. package/templates/nonprofit-cause/tier5-src/_shared/iap-worker.ts +42 -0
  111. package/templates/nonprofit-cause/tier5-src/himi-branded-lite-home/index.ts +16 -2
  112. package/templates/nonprofit-cause/tier5-src/himi-branded-lite-plans/index.ts +153 -64
  113. package/templates/nonprofit-cause/tier5-src/wix-spaces-plan-detail/index.ts +8 -3
  114. package/templates/nonprofit-cause-owner/tier5-src/_shared/collection-contract.ts +1 -1
  115. package/templates/nonprofit-cause-owner/tier5-src/_shared/collection-service.ts +3 -2
  116. package/templates/nonprofit-cause-owner/tier5-src/_shared/home-service.ts +2 -1
  117. package/templates/owner-lite/tier5-src/_shared/collection-contract.ts +1 -1
  118. package/templates/owner-lite/tier5-src/_shared/collection-service.ts +3 -2
  119. package/templates/owner-lite/tier5-src/_shared/home-service.ts +2 -1
  120. package/templates/podcast-creator/config.ts +1 -1
  121. package/templates/podcast-creator/dev/index.ts +29 -13
  122. package/templates/podcast-creator/tier5-src/_shared/collection-contract.ts +1 -1
  123. package/templates/podcast-creator/tier5-src/_shared/collection-service.ts +3 -2
  124. package/templates/podcast-creator/tier5-src/_shared/home-service.ts +2 -1
  125. package/templates/podcast-creator/tier5-src/_shared/iap-presentation.ts +53 -0
  126. package/templates/podcast-creator/tier5-src/_shared/iap-worker.ts +42 -0
  127. package/templates/podcast-creator/tier5-src/himi-branded-lite-home/index.ts +16 -2
  128. package/templates/podcast-creator/tier5-src/himi-branded-lite-plans/index.ts +153 -64
  129. package/templates/podcast-creator/tier5-src/wix-spaces-plan-detail/index.ts +8 -3
  130. package/templates/podcast-creator-owner/tier5-src/_shared/collection-contract.ts +1 -1
  131. package/templates/podcast-creator-owner/tier5-src/_shared/collection-service.ts +3 -2
  132. package/templates/podcast-creator-owner/tier5-src/_shared/home-service.ts +2 -1
  133. package/templates/portfolio-creative/config.ts +1 -1
  134. package/templates/portfolio-creative/dev/index.ts +20 -6
  135. package/templates/portfolio-creative/tier5-src/_shared/collection-contract.ts +1 -1
  136. package/templates/portfolio-creative/tier5-src/_shared/collection-service.ts +3 -2
  137. package/templates/portfolio-creative/tier5-src/_shared/himi-store-collection.ts +1 -1
  138. package/templates/portfolio-creative/tier5-src/_shared/home-service.ts +2 -1
  139. package/templates/portfolio-creative/tier5-src/_shared/iap-presentation.ts +53 -0
  140. package/templates/portfolio-creative/tier5-src/_shared/iap-worker.ts +42 -0
  141. package/templates/portfolio-creative/tier5-src/himi-branded-lite-cart/index.ts +48 -1
  142. package/templates/portfolio-creative/tier5-src/himi-branded-lite-home/index.ts +16 -2
  143. package/templates/portfolio-creative/tier5-src/himi-branded-lite-order/index.ts +24 -3
  144. package/templates/portfolio-creative/tier5-src/himi-store-product/index.ts +24 -3
  145. package/templates/portfolio-creative/tier5-src/himi-store-saved/index.ts +8 -3
  146. package/templates/portfolio-creative/tier5-src/himi-store-shop/index.ts +10 -0
  147. package/templates/portfolio-creative-owner/tier5-src/_shared/collection-contract.ts +1 -1
  148. package/templates/portfolio-creative-owner/tier5-src/_shared/collection-service.ts +3 -2
  149. package/templates/portfolio-creative-owner/tier5-src/_shared/home-service.ts +2 -1
  150. package/templates/restaurant/config.ts +1 -1
  151. package/templates/restaurant/dev/index.ts +3 -1
  152. package/templates/restaurant/tier5-src/_shared/collection-contract.ts +1 -1
  153. package/templates/restaurant/tier5-src/_shared/collection-service.ts +3 -2
  154. package/templates/restaurant/tier5-src/_shared/home-service.ts +2 -1
  155. package/templates/restaurant/tier5-src/_shared/iap-presentation.ts +53 -0
  156. package/templates/restaurant/tier5-src/_shared/iap-worker.ts +42 -0
  157. package/templates/restaurant/tier5-src/himi-branded-lite-home/index.ts +16 -2
  158. package/templates/restaurant-owner/tier5-src/_shared/collection-contract.ts +1 -1
  159. package/templates/restaurant-owner/tier5-src/_shared/collection-service.ts +3 -2
  160. package/templates/restaurant-owner/tier5-src/_shared/home-service.ts +2 -1
  161. package/templates/retail-store/config.ts +1 -1
  162. package/templates/retail-store/dev/index.ts +20 -6
  163. package/templates/retail-store/tier5-src/_shared/collection-contract.ts +1 -1
  164. package/templates/retail-store/tier5-src/_shared/collection-service.ts +3 -2
  165. package/templates/retail-store/tier5-src/_shared/himi-store-collection.ts +1 -1
  166. package/templates/retail-store/tier5-src/_shared/home-service.ts +2 -1
  167. package/templates/retail-store/tier5-src/_shared/iap-presentation.ts +53 -0
  168. package/templates/retail-store/tier5-src/_shared/iap-worker.ts +42 -0
  169. package/templates/retail-store/tier5-src/himi-branded-lite-cart/index.ts +48 -1
  170. package/templates/retail-store/tier5-src/himi-branded-lite-home/index.ts +16 -2
  171. package/templates/retail-store/tier5-src/himi-branded-lite-order/index.ts +24 -3
  172. package/templates/retail-store/tier5-src/himi-store-product/index.ts +24 -3
  173. package/templates/retail-store/tier5-src/himi-store-saved/index.ts +8 -3
  174. package/templates/retail-store/tier5-src/himi-store-shop/index.ts +10 -0
  175. package/templates/retail-store-owner/tier5-src/_shared/collection-contract.ts +1 -1
  176. package/templates/retail-store-owner/tier5-src/_shared/collection-service.ts +3 -2
  177. package/templates/retail-store-owner/tier5-src/_shared/home-service.ts +2 -1
  178. package/templates/yoga-studio/config.ts +1 -1
  179. package/templates/yoga-studio/dev/index.ts +29 -13
  180. package/templates/yoga-studio/tier5-src/_shared/collection-contract.ts +1 -1
  181. package/templates/yoga-studio/tier5-src/_shared/collection-service.ts +3 -2
  182. package/templates/yoga-studio/tier5-src/_shared/home-service.ts +2 -1
  183. package/templates/yoga-studio/tier5-src/_shared/iap-presentation.ts +53 -0
  184. package/templates/yoga-studio/tier5-src/himi-branded-lite-home/index.ts +16 -2
  185. package/templates/yoga-studio/tier5-src/himi-branded-lite-plans/index.ts +153 -64
  186. package/templates/yoga-studio/tier5-src/wix-spaces-plan-detail/index.ts +8 -3
  187. package/templates/yoga-studio-owner/tier5-src/_shared/collection-contract.ts +1 -1
  188. package/templates/yoga-studio-owner/tier5-src/_shared/collection-service.ts +3 -2
  189. package/templates/yoga-studio-owner/tier5-src/_shared/home-service.ts +2 -1
  190. package/templates/branded-lite/tier5-src/wix-spaces-create-group/index.ts +0 -29
  191. package/templates/community-club/tier5-src/wix-spaces-create-group/index.ts +0 -29
  192. package/templates/events-meetups/tier5-src/wix-spaces-create-group/index.ts +0 -29
  193. package/templates/nonprofit-cause/tier5-src/wix-spaces-create-group/index.ts +0 -29
@@ -2971,7 +2971,9 @@ const SCREENS = runtimeSetting({
2971
2971
  "integrity": "",
2972
2972
  "contentType": "application/javascript+ts-bundle",
2973
2973
  "declaredCapabilities": [
2974
- "wix_api"
2974
+ "wix_api",
2975
+ "iap",
2976
+ "app_info"
2975
2977
  ],
2976
2978
  "minBinaryVersion": "0.2.0",
2977
2979
  "bundleVersion": "0.0.1"
@@ -8896,7 +8898,9 @@ const SCREENS = runtimeSetting({
8896
8898
  "contentType": "application/javascript+ts-bundle",
8897
8899
  "declaredCapabilities": [
8898
8900
  "wix_api",
8899
- "local_database"
8901
+ "local_database",
8902
+ "iap",
8903
+ "app_info"
8900
8904
  ],
8901
8905
  "minBinaryVersion": "0.1.0",
8902
8906
  "bundleVersion": "0.0.1"
@@ -9364,7 +9368,11 @@ const SCREENS = runtimeSetting({
9364
9368
  "url": "http://localhost:8190/v1/bundles/himi-store-saved",
9365
9369
  "integrity": "",
9366
9370
  "contentType": "application/javascript+ts-bundle",
9367
- "declaredCapabilities": [],
9371
+ "declaredCapabilities": [
9372
+ "wix_api",
9373
+ "iap",
9374
+ "app_info"
9375
+ ],
9368
9376
  "minBinaryVersion": "0.1.0",
9369
9377
  "bundleVersion": "0.0.1"
9370
9378
  }
@@ -10890,7 +10898,9 @@ const SCREENS = runtimeSetting({
10890
10898
  "wix_cashier",
10891
10899
  "open_url",
10892
10900
  "local_database",
10893
- "wix_platform"
10901
+ "wix_platform",
10902
+ "iap",
10903
+ "app_info"
10894
10904
  ],
10895
10905
  "minBinaryVersion": "0.1.0",
10896
10906
  "bundleVersion": "0.0.1"
@@ -25546,7 +25556,8 @@ const SCREENS = runtimeSetting({
25546
25556
  "package": "himalaya",
25547
25557
  "type": "Button",
25548
25558
  "props": {
25549
- "title": "Join on website",
25559
+ "title": "$item.joinLabel",
25560
+ "disabledPath": "$item.joinDisabled",
25550
25561
  "style": "primary",
25551
25562
  "fullWidth": true,
25552
25563
  "action": {
@@ -25567,7 +25578,8 @@ const SCREENS = runtimeSetting({
25567
25578
  "package": "himalaya",
25568
25579
  "type": "Button",
25569
25580
  "props": {
25570
- "title": "Join on website",
25581
+ "title": "$item.joinLabel",
25582
+ "disabledPath": "$item.joinDisabled",
25571
25583
  "style": "secondary",
25572
25584
  "fullWidth": true,
25573
25585
  "action": {
@@ -25748,7 +25760,8 @@ const SCREENS = runtimeSetting({
25748
25760
  "package": "himalaya",
25749
25761
  "type": "Button",
25750
25762
  "props": {
25751
- "title": "Join on website",
25763
+ "title": "$item.joinLabel",
25764
+ "disabledPath": "$item.joinDisabled",
25752
25765
  "style": "primary",
25753
25766
  "fullWidth": true,
25754
25767
  "action": {
@@ -25769,7 +25782,8 @@ const SCREENS = runtimeSetting({
25769
25782
  "package": "himalaya",
25770
25783
  "type": "Button",
25771
25784
  "props": {
25772
- "title": "Join on website",
25785
+ "title": "$item.joinLabel",
25786
+ "disabledPath": "$item.joinDisabled",
25773
25787
  "style": "secondary",
25774
25788
  "fullWidth": true,
25775
25789
  "action": {
@@ -26174,7 +26188,8 @@ const SCREENS = runtimeSetting({
26174
26188
  "package": "himalaya",
26175
26189
  "type": "Button",
26176
26190
  "props": {
26177
- "title": "Join on website",
26191
+ "title": "$item.joinLabel",
26192
+ "disabledPath": "$item.joinDisabled",
26178
26193
  "style": "primary",
26179
26194
  "fullWidth": true,
26180
26195
  "action": {
@@ -26195,7 +26210,8 @@ const SCREENS = runtimeSetting({
26195
26210
  "package": "himalaya",
26196
26211
  "type": "Button",
26197
26212
  "props": {
26198
- "title": "Join on website",
26213
+ "title": "$item.joinLabel",
26214
+ "disabledPath": "$item.joinDisabled",
26199
26215
  "style": "secondary",
26200
26216
  "fullWidth": true,
26201
26217
  "action": {
@@ -26376,7 +26392,8 @@ const SCREENS = runtimeSetting({
26376
26392
  "package": "himalaya",
26377
26393
  "type": "Button",
26378
26394
  "props": {
26379
- "title": "Join on website",
26395
+ "title": "$item.joinLabel",
26396
+ "disabledPath": "$item.joinDisabled",
26380
26397
  "style": "primary",
26381
26398
  "fullWidth": true,
26382
26399
  "action": {
@@ -26397,7 +26414,8 @@ const SCREENS = runtimeSetting({
26397
26414
  "package": "himalaya",
26398
26415
  "type": "Button",
26399
26416
  "props": {
26400
- "title": "Join on website",
26417
+ "title": "$item.joinLabel",
26418
+ "disabledPath": "$item.joinDisabled",
26401
26419
  "style": "secondary",
26402
26420
  "fullWidth": true,
26403
26421
  "action": {
@@ -26975,7 +26993,8 @@ const SCREENS = runtimeSetting({
26975
26993
  "package": "himalaya",
26976
26994
  "type": "Button",
26977
26995
  "props": {
26978
- "title": "Join on website",
26996
+ "title": "$item.joinLabel",
26997
+ "disabledPath": "$item.joinDisabled",
26979
26998
  "style": "primary",
26980
26999
  "fullWidth": true,
26981
27000
  "action": {
@@ -26996,7 +27015,8 @@ const SCREENS = runtimeSetting({
26996
27015
  "package": "himalaya",
26997
27016
  "type": "Button",
26998
27017
  "props": {
26999
- "title": "Join on website",
27018
+ "title": "$item.joinLabel",
27019
+ "disabledPath": "$item.joinDisabled",
27000
27020
  "style": "secondary",
27001
27021
  "fullWidth": true,
27002
27022
  "action": {
@@ -27271,7 +27291,9 @@ const SCREENS = runtimeSetting({
27271
27291
  "wix_api",
27272
27292
  "wix_cashier",
27273
27293
  "open_url",
27274
- "wix_platform"
27294
+ "wix_platform",
27295
+ "iap",
27296
+ "app_info"
27275
27297
  ],
27276
27298
  "minBinaryVersion": "0.1.0",
27277
27299
  "bundleVersion": "0.0.1"
@@ -27527,7 +27549,9 @@ const SCREENS = runtimeSetting({
27527
27549
  "integrity": "",
27528
27550
  "contentType": "application/javascript+ts-bundle",
27529
27551
  "declaredCapabilities": [
27530
- "wix_api"
27552
+ "wix_api",
27553
+ "iap",
27554
+ "app_info"
27531
27555
  ],
27532
27556
  "minBinaryVersion": "0.1.0",
27533
27557
  "bundleVersion": "0.0.1"
@@ -55711,25 +55735,6 @@ const SCREENS = runtimeSetting({
55711
55735
  }
55712
55736
  }
55713
55737
  },
55714
- {
55715
- "id": "himi_groups.new_group",
55716
- "body": {
55717
- "package": "himalaya",
55718
- "type": "Button",
55719
- "props": {
55720
- "title": "New Group",
55721
- "style": "secondary",
55722
- "fullWidth": true,
55723
- "leadingIcon": "plus",
55724
- "action": {
55725
- "actionId": "himi.open",
55726
- "params": {
55727
- "screenId": "himi_create_group"
55728
- }
55729
- }
55730
- }
55731
- }
55732
- },
55733
55738
  {
55734
55739
  "id": "himi_groups.search",
55735
55740
  "body": {
@@ -58110,103 +58115,6 @@ const SCREENS = runtimeSetting({
58110
58115
  "bundleVersion": "0.0.1"
58111
58116
  }
58112
58117
  },
58113
- "himi_create_group": {
58114
- "screenId": "himi_create_group",
58115
- "renderer": "sdui_intent",
58116
- "title": "",
58117
- "schemaVersion": 1,
58118
- "cacheControl": {
58119
- "maxAge": 0,
58120
- "staleWhileRevalidate": 0
58121
- },
58122
- "payload": {
58123
- "id": "himi_create_group.root",
58124
- "body": {
58125
- "package": "himalaya",
58126
- "type": "VStack",
58127
- "props": {
58128
- "spacing": 16,
58129
- "alignment": "leading",
58130
- "children": [
58131
- {
58132
- "id": "himi_create_group.title",
58133
- "body": {
58134
- "package": "himalaya",
58135
- "type": "Text",
58136
- "props": {
58137
- "text": "New Group",
58138
- "style": "title1"
58139
- }
58140
- }
58141
- },
58142
- {
58143
- "id": "",
58144
- "body": {
58145
- "package": "himalaya",
58146
- "type": "Text",
58147
- "props": {
58148
- "text": "$service:spacesCreateGroup.hint",
58149
- "style": "footnote",
58150
- "color": "textSecondary",
58151
- "collapseWhenEmpty": true
58152
- }
58153
- }
58154
- },
58155
- {
58156
- "id": "himi_create_group.name_field",
58157
- "body": {
58158
- "package": "himalaya",
58159
- "type": "TextField",
58160
- "props": {
58161
- "placeholder": "Group name",
58162
- "value": "",
58163
- "onChange": {
58164
- "actionId": "tier5.spacesCreateGroup.setName"
58165
- }
58166
- }
58167
- }
58168
- },
58169
- {
58170
- "id": "himi_create_group.submit",
58171
- "body": {
58172
- "package": "himalaya",
58173
- "type": "Button",
58174
- "props": {
58175
- "title": "Create",
58176
- "style": "primary",
58177
- "fullWidth": true,
58178
- "action": {
58179
- "actionId": "tier5.spacesCreateGroup.submit"
58180
- }
58181
- }
58182
- }
58183
- }
58184
- ]
58185
- }
58186
- },
58187
- "modifiers": {
58188
- "background": {
58189
- "token": "surfacePrimary"
58190
- },
58191
- "padding": {
58192
- "leading": 16,
58193
- "trailing": 16,
58194
- "top": 18,
58195
- "bottom": 28
58196
- }
58197
- }
58198
- },
58199
- "logicBundle": {
58200
- "url": "http://localhost:8190/v1/bundles/wix-spaces-create-group?integrity=",
58201
- "integrity": "",
58202
- "contentType": "application/javascript+ts-bundle",
58203
- "declaredCapabilities": [
58204
- "wix_api"
58205
- ],
58206
- "minBinaryVersion": "0.1.0",
58207
- "bundleVersion": "0.0.1"
58208
- }
58209
- },
58210
58118
  "himi_faq": {
58211
58119
  "screenId": "himi_faq",
58212
58120
  "renderer": "sdui_intent",
@@ -81967,7 +81875,9 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
81967
81875
  "declaredCapabilities": [
81968
81876
  "wix_api",
81969
81877
  "local_database",
81970
- "live_activity"
81878
+ "live_activity",
81879
+ "iap",
81880
+ "app_info"
81971
81881
  ],
81972
81882
  "minBinaryVersion": "0.1.0",
81973
81883
  "bundleVersion": "0.0.1"
@@ -82849,7 +82759,9 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
82849
82759
  "wix_api",
82850
82760
  "share",
82851
82761
  "local_database",
82852
- "open_url"
82762
+ "open_url",
82763
+ "iap",
82764
+ "app_info"
82853
82765
  ],
82854
82766
  "minBinaryVersion": "0.1.0",
82855
82767
  "bundleVersion": "0.0.1"
@@ -58,9 +58,6 @@
58
58
  "himi_coupons": {
59
59
  "displayName": "Offers"
60
60
  },
61
- "himi_create_group": {
62
- "displayName": "Create Group"
63
- },
64
61
  "himi_create_post": {
65
62
  "displayName": "Create Post"
66
63
  },
@@ -87,7 +87,7 @@ export const COLLECTIONS: Record<string, CollectionConfig> = {
87
87
  himiBrandedOrders: { rows: 'rows', title: 'title', subtitle: 'subtitle', view: 'list', backendQuery: true,
88
88
  searchPlaceholder: 'Search by order number', countNoun: ['order', 'orders'], filterValues: ['Not fulfilled', 'Partially fulfilled', 'Fulfilled'],
89
89
  sortLabels: { default: 'Newest', az: 'Oldest', za: 'Order # ↓' } },
90
- himiBrandedPlans: { rows: 'rows', title: 'name', subtitle: 'description', metadata: ['badge', 'priceLine', 'periodLine', 'trialBadge', 'perk1', 'perk2', 'perk3'], view: 'grid', gridColumns: 1, metaMaxLines: 8, countNoun: ['plan', 'plans'] },
90
+ himiBrandedPlans: { rows: 'rows', title: 'name', subtitle: 'description', metadata: ['badge', 'priceLine', 'periodLine', 'trialBadge', 'perk1', 'perk2', 'perk3', 'joinNote'], view: 'grid', gridColumns: 1, metaMaxLines: 8, countNoun: ['plan', 'plans'] },
91
91
  himiBrandedPrograms: { rows: 'rows', title: 'name', subtitle: 'description', image: 'image', view: 'grid' },
92
92
  himiBrandedCoupons: { rows: 'coupons', title: 'name', subtitle: 'subtitle', view: 'list', primaryVerb: { label: 'Get code' } },
93
93
  himiBrandedNotifications: { rows: 'items', title: 'name', subtitle: 'subtitle', image: 'photo', metadata: ['unreadDot'], view: 'list' },
@@ -323,6 +323,7 @@ export function decorateCollection(name: string, def: { state: State; actions?:
323
323
  /** Domain-owned page source with shared query controls. Publishing uses a normal
324
324
  * reducer and reads the private controller snapshot, never an SDUI payload. */
325
325
  export function defineBackendCollection<S extends object, Row extends object>(name: string, options: {
326
+ register?: typeof register;
326
327
  /** Revalidate already opened pages on navigation return; explicit refresh resets. */
327
328
  restorePagesOnLoad?: boolean;
328
329
  /** The load action's argument (onAppear params beyond `copy`), before the query runs — for a
@@ -342,7 +343,7 @@ export function defineBackendCollection<S extends object, Row extends object>(na
342
343
  controller: controller as unknown as BackendCollection['controller'],
343
344
  apply: (state, page) => options.apply(state as S, page as unknown as CollectionQueryState<Row>) as State,
344
345
  });
345
- const handle = register(name, definition);
346
+ const handle = (options.register ?? register)(name, definition);
346
347
  publish = () => handle.collectionDataChanged();
347
348
  return handle;
348
349
  }
@@ -350,7 +351,7 @@ export function defineBackendCollection<S extends object, Row extends object>(na
350
351
  /** Keep the domain service's existing TypeScript API. Extra collection verbs are
351
352
  * dispatched through SDUI and do not widen the native capability surface. */
352
353
  export const defineService: typeof register = ((name: string, def: ServiceDefinition<unknown>) =>
353
- register(name, decorateCollection(name, def as unknown as { state: State; actions?: Record<string, Reducer> }))) as typeof register;
354
+ register(name, { ...def, ...decorateCollection(name, def as unknown as { state: State; actions?: Record<string, Reducer> }) } as ServiceDefinition<State>)) as typeof register;
354
355
 
355
356
  /** Domains can supply their existing saved-items store without putting domain
356
357
  * data or mutations in the shared collection layer. */
@@ -8,7 +8,7 @@ export const storeCollectionSaving: CollectionSaving = {
8
8
  for (const row of rows) {
9
9
  if (typeof row.id !== 'string' || typeof row.name !== 'string') continue;
10
10
  products.set(row.id, { id: row.id, name: row.name,
11
- price: typeof row.subtitle === 'string' ? row.subtitle : '',
11
+ price: typeof row.commercePrice === 'string' ? row.commercePrice : typeof row.subtitle === 'string' ? row.subtitle : '',
12
12
  image: typeof row.image === 'string' ? row.image : '' });
13
13
  }
14
14
  const selected = ids.map(id => products.get(id));
@@ -87,4 +87,5 @@ export function decorateHome(def: { state: State; actions?: Record<string, Actio
87
87
  actions.homeMoveDown = change(id => { const index = prefs.order.indexOf(id); if (index >= 0 && index < prefs.order.length - 1) [prefs.order[index], prefs.order[index + 1]] = [prefs.order[index + 1], prefs.order[index]]; });
88
88
  return { state: derive(def.state), actions };
89
89
  }
90
- export const defineService: typeof register = ((name: string, def: ServiceDefinition<unknown>) => register(name, decorateHome(def as unknown as { state: State; actions?: Record<string, Action> }))) as typeof register;
90
+ export const defineService: typeof register = ((name: string, def: ServiceDefinition<unknown>) =>
91
+ register(name, { ...def, ...decorateHome(def as unknown as { state: State; actions?: Record<string, Action> }) })) as typeof register;
@@ -0,0 +1,53 @@
1
+ import { defineService, type ServiceDefinition } from "@himalaya/state";
2
+ import { createIapCommerce, type IapCommerce } from "@himalaya/iap-checkout";
3
+ import { iapPriceFields, type IapCatalogItem } from "@himalaya/iap";
4
+ import { iapPriceCopy, resetUnhydratedKeysOnOlderRuntime } from "./iap-worker.js";
5
+
6
+ // Presentation only. Checkout, mapping, cache, session and refresh policy stay in the shared flow.
7
+ export function withIapPresentation<S extends object>(options: {
8
+ register?: typeof defineService;
9
+ onCreate?(commerce: IapCommerce): void;
10
+ onContent?(state: S): void;
11
+ items(state: S): IapCatalogItem[];
12
+ present(state: S, price: (id: string, commercePrice?: string) => string, allowed: (id: string) => boolean): S;
13
+ contentActions: string[];
14
+ transientKeys: (keyof S & string)[];
15
+ prefix: string;
16
+ }): typeof defineService {
17
+ return ((name: string, definition: ServiceDefinition<S>) => {
18
+ const commerce = createIapCommerce({ onChange: () => { void service.iapPublish(); } });
19
+ options.onCreate?.(commerce);
20
+ let items: IapCatalogItem[] = [];
21
+ let contentVersion = 0;
22
+ const project = (state: S): S => {
23
+ const price = (id: string, commercePrice?: string) => {
24
+ const item = items.find(item => item.reference.id === id);
25
+ if (!item) return "";
26
+ const view = commerce.pricing.view(item.reference);
27
+ return view.route === "disabled" || view.route === "regular" ? commercePrice ?? item.commerceDisplayPrice ?? "" : iapPriceFields(view, iapPriceCopy(options.prefix)).priceText;
28
+ };
29
+ const allowed = (id: string) => commerce.pricing.checkoutGuard({ kind: "storesProduct", id }).allowed;
30
+ const poll = commerce.pollDirective(`${name}.iapPoll`);
31
+ return { ...options.present(state, price, allowed), ...(poll ? { _poll: poll } : {}) };
32
+ };
33
+ const actions = Object.fromEntries(Object.entries(definition.actions ?? {}).map(([action, reduce]) => [action, async (state: S, ...args: never[]) => {
34
+ const content = options.contentActions.includes(action);
35
+ const version = action === "load" ? ++contentVersion : contentVersion;
36
+ const next = await reduce(state, ...args);
37
+ if (!next || (content && version !== contentVersion)) return undefined;
38
+ if (content) {
39
+ options.onContent?.(next);
40
+ items = options.items(next);
41
+ void commerce.loadPrices(items);
42
+ }
43
+ return project(next);
44
+ }]));
45
+ const service = (options.register ?? defineService)(name, {
46
+ ...definition, notHydrated: [...(definition.notHydrated ?? []), ...options.transientKeys],
47
+ actions: { ...actions, iapPublish: project, iapPoll: async () => { await commerce.poll(); return undefined; },
48
+ iapRefresh: async () => { await commerce.loadPrices(items); return undefined; } },
49
+ });
50
+ resetUnhydratedKeysOnOlderRuntime(service, definition.state, options.transientKeys);
51
+ return service;
52
+ }) as unknown as typeof defineService;
53
+ }
@@ -1,4 +1,7 @@
1
- import { defineService } from "@himalaya/state";
1
+ import { getStoreProduct } from "../_shared/himi-store.js";
2
+ import { iapPriceCopy } from "../_shared/iap-worker.js";
3
+ import { withIapPresentation } from "../_shared/iap-presentation.js";
4
+ import { type IapCommerce, classifyCart } from "@himalaya/iap-checkout";
2
5
  import { createCheckoutFromCurrentCart, createOrder, getCurrentCart, removeLineItemsFromCurrentCart, updateLineItemsQuantity, type WixCartLineItemDetail } from "@himalaya/wix-ecom";
3
6
  import { createRedirectSession } from "@himalaya/wix-redirects";
4
7
  import { session as wixPlatformSession } from "@himalaya/wix-platform";
@@ -6,6 +9,7 @@ import { payCashierOrder } from "@himalaya/checkout";
6
9
 
7
10
  /** Wix Stores appDefId — the vertical that owns a cart/ecom order, and therefore the
8
11
  * `appId` its cashier order is paid under. (Same constant Wix's own tooling uses.) */
12
+ const WIX_STORES_CATALOG_ID = "215238eb-22a5-4c36-9e7b-e7c08025e04e";
9
13
  const WIX_STORES_APP_ID = "1380b703-ce81-ff05-f115-39571d94dfcd";
10
14
 
11
15
  /** The site's metaSiteId for the cashier payment config. Best-effort — the native
@@ -40,6 +44,7 @@ async function cacheDrop(id: string): Promise<void> { try { await dbRemove(ENTIT
40
44
  async function queueWrite(actionId: string, params: Record<string, string>): Promise<void> { try { await enqueue(actionId, params); } catch { /* capability not granted */ } }
41
45
 
42
46
  interface Row {
47
+ catalogReference?: { appId: string; catalogItemId: string; options?: Record<string, unknown> };
43
48
  id: string;
44
49
  name: string;
45
50
  title: string;
@@ -50,6 +55,7 @@ interface Row {
50
55
  /** The "−" control at qty 1 removes the line, so it never dead-ends. */
51
56
  atMinQuantity: boolean;
52
57
  total: string;
58
+ commerceTotal: string;
53
59
  image: string;
54
60
  initial: string;
55
61
  hasImage: boolean;
@@ -59,6 +65,7 @@ interface State {
59
65
  status: "loading" | "ready" | "error";
60
66
  items: Row[];
61
67
  subtotal: string;
68
+ commerceSubtotal?: string;
62
69
  emptyText: string;
63
70
  checkoutHint: string;
64
71
  isLoading: boolean;
@@ -118,6 +125,7 @@ function row(item: WixCartLineItemDetail, index: number): Row {
118
125
  const name = item.productName?.original || copyParam("cart.itemFallbackName", "Cart item");
119
126
  const image = mediaUrl(item);
120
127
  return {
128
+ catalogReference: (item as WixCartLineItemDetail & { catalogReference?: Row["catalogReference"] }).catalogReference,
121
129
  id: item.id || `line-${index}`,
122
130
  name,
123
131
  title: name,
@@ -126,6 +134,7 @@ function row(item: WixCartLineItemDetail, index: number): Row {
126
134
  quantityLabel: `${quantity}`,
127
135
  atMinQuantity: quantity <= 1,
128
136
  total: item.price?.formattedAmount ?? "",
137
+ commerceTotal: item.price?.formattedAmount ?? "",
129
138
  image,
130
139
  initial: (name.trim()[0] || "C").toUpperCase(),
131
140
  hasImage: Boolean(image),
@@ -163,6 +172,7 @@ async function refresh(state: State, checkoutHint = ""): Promise<State> {
163
172
  status: "ready",
164
173
  items,
165
174
  subtotal: cart.subtotal?.formattedAmount ?? "",
175
+ commerceSubtotal: cart.subtotal?.formattedAmount ?? "",
166
176
  emptyText: items.length ? "" : copyParam("cart.emptyText", "Your cart is empty."),
167
177
  checkoutHint,
168
178
  });
@@ -190,6 +200,16 @@ function cartConsumedByOrder(): Pick<State, "items" | "subtotal" | "emptyText" |
190
200
  };
191
201
  }
192
202
 
203
+ let cartPricing: IapCommerce;
204
+ const defineService = withIapPresentation<State>({
205
+ onCreate: commerce => { cartPricing = commerce; },
206
+ prefix: "cart", transientKeys: ["items", "subtotal"], contentActions: ["load", "remove", "increment", "decrement"],
207
+ items: state => state.items.flatMap(row => row.catalogReference?.catalogItemId ? [{ reference: { kind: "storesProduct", id: row.catalogReference.catalogItemId }, commerceDisplayPrice: row.commerceTotal ?? row.total }] : []),
208
+ present: (state, price, allowed) => ({ ...state,
209
+ items: state.items.map(row => ({ ...row, total: row.catalogReference?.catalogItemId ? price(row.catalogReference.catalogItemId, row.commerceTotal ?? row.total) : row.total })),
210
+ subtotal: state.items.length > 0 && state.items.every(row => row.catalogReference?.catalogItemId && allowed(row.catalogReference.catalogItemId)) ? state.commerceSubtotal ?? state.subtotal : "" }),
211
+ });
212
+
193
213
  const svc = defineService<State, {
194
214
  load: (state: State, arg?: unknown) => Promise<State>;
195
215
  remove: (state: State, arg?: unknown) => Promise<State>;
@@ -272,6 +292,25 @@ const svc = defineService<State, {
272
292
  // `createOrder` returning no paymentGatewayOrderId means there is nothing to
273
293
  // charge (fully covered / zero total) — the order already stands.
274
294
  checkout: async (state) => {
295
+ let validatedLines: WixCartLineItemDetail[] = [];
296
+ const signature = (lines: WixCartLineItemDetail[]) => JSON.stringify(lines.map(line => [line.id, line.quantity, (line as WixCartLineItemDetail & { catalogReference?: Row["catalogReference"] }).catalogReference]));
297
+ try {
298
+ const cart = await getCurrentCart();
299
+ const lines = cart.lineItems ?? [];
300
+ if (!lines.length) return derive({ ...state, checkoutHint: copyParam("cart.checkoutEmptyMessage", "Add an item before checkout.") });
301
+ const commerce = cartPricing;
302
+ const items = lines.map(line => (line as WixCartLineItemDetail & { catalogReference?: Row["catalogReference"] }).catalogReference);
303
+ if (items.some(item => !item?.catalogItemId || !item.appId)) return derive({ ...state, checkoutHint: iapPriceCopy("cart").purchaseUnavailable });
304
+ await commerce.loadPrices(items.map((item, index) => ({ reference: { kind: "storesProduct", id: item!.catalogItemId }, commerceDisplayPrice: lines[index].price?.formattedAmount })));
305
+ const classification = classifyCart(items.map((item, index) => ({ route: commerce.pricing.view({ kind: "storesProduct", id: item!.catalogItemId }).route, quantity: lines[index].quantity ?? 1 })));
306
+ if (classification !== "regular") return derive({ ...state, checkoutHint: classification === "mixedRefused" ? copyParam("cart.iapSingleItemOnly", "Buy digital items individually, with quantity 1 and no options.") : iapPriceCopy("cart").purchaseUnavailable });
307
+ const products = await Promise.all(items.map(async item => item!.appId === WIX_STORES_CATALOG_ID ? (await getStoreProduct(item!.catalogItemId)).product : undefined));
308
+ if (products.some(product => product?.productType?.toLowerCase() !== "physical")) return derive({ ...state, checkoutHint: iapPriceCopy("cart").purchaseUnavailable });
309
+ const latest = await getCurrentCart();
310
+ if (signature(latest.lineItems ?? []) !== signature(lines)) return derive({ ...state, checkoutHint: copyParam("cart.changedBeforeCheckout", "Your cart changed. Review it before checking out.") });
311
+ validatedLines = lines;
312
+ } catch { return derive({ ...state, checkoutHint: iapPriceCopy("cart").purchaseUnavailable }); }
313
+
275
314
  if (!state.items.length) return derive({ ...state, checkoutHint: copyParam("cart.checkoutEmptyMessage", "Add an item before checkout.") });
276
315
  try {
277
316
  const checkout = await createCheckoutFromCurrentCart();
@@ -288,6 +327,14 @@ const svc = defineService<State, {
288
327
  appId: WIX_STORES_APP_ID,
289
328
  snapshotId,
290
329
  msid: await resolveMsid(),
330
+ mayCharge: async () => {
331
+ const latest = await getCurrentCart();
332
+ if (signature(latest.lineItems ?? []) !== signature(validatedLines)) return false;
333
+ return validatedLines.every(line => {
334
+ const reference = (line as WixCartLineItemDetail & { catalogReference?: Row["catalogReference"] }).catalogReference;
335
+ return !!reference && cartPricing.pricing.continueCheckoutGuard({ kind: "storesProduct", id: reference.catalogItemId }).allowed;
336
+ });
337
+ },
291
338
  cashierUrl: async () => {
292
339
  const redirect = await createRedirectSession({
293
340
  ecomCheckout: { checkoutId },
@@ -1,6 +1,7 @@
1
1
  import { fetchMemberBookings, type MemberBookingRow } from "../_shared/member-bookings.js";
2
2
  import { memberAccess, assertMemberAccess } from "../_shared/member-access.js";
3
- import { defineService } from "../_shared/home-service.js";
3
+ import { defineService as registerHome } from "../_shared/home-service.js";
4
+ import { withIapPresentation } from "../_shared/iap-presentation.js";
4
5
  import { queryServices, type WixService } from "@himalaya/wix-bookings";
5
6
  import { getPost, queryPosts, type WixPost } from "@himalaya/wix-blog";
6
7
  import { queryGroups, type WixGroup } from "@himalaya/wix-groups";
@@ -68,6 +69,7 @@ interface ProductFeature {
68
69
  /** Device-local catalog saves are useful to visitors too; they are never
69
70
  * presented as account-synced data or mixed with member-only bookings. */
70
71
  interface SavedProductCard {
72
+ commercePrice: string;
71
73
  id: string;
72
74
  name: string;
73
75
  price: string;
@@ -573,7 +575,7 @@ function postCard(post: WixPost): PostCard {
573
575
  function savedProductCard(product: SavedProduct): SavedProductCard {
574
576
  const name = cleanTitle(product.name) || copyParam("home.savedProductFallbackName", "Saved item");
575
577
  const image = product.image ? wixMediaUrl(product.image) : "";
576
- return { id: product.id, name, price: product.price, image, initial: initials(name), hasImage: !!image, noImage: !image, detailScreenId: "himi_product" };
578
+ return { id: product.id, name, price: product.price, commercePrice: product.price, image, initial: initials(name), hasImage: !!image, noImage: !image, detailScreenId: "himi_product" };
577
579
  }
578
580
 
579
581
  function savedPostCard(post: WixPost): SavedPostCard {
@@ -1111,6 +1113,18 @@ async function refresh(state: State, arg?: unknown): Promise<State | undefined>
1111
1113
  weeklyClassCount: current.weeklyClassCount, weeklyClassGoalFraction: current.weeklyClassGoalFraction, weeklyGoalLabel: current.weeklyGoalLabel });
1112
1114
  }
1113
1115
 
1116
+ const defineService = withIapPresentation<State>({
1117
+ register: registerHome, prefix: "home", transientKeys: ["featuredProducts", "savedProducts", "heroPrice"], contentActions: ["refresh"],
1118
+ items: state => [
1119
+ ...state.featuredProducts.map(row => ({ reference: { kind: "storesProduct", id: row.id }, commerceDisplayPrice: row.price })),
1120
+ ...state.savedProducts.map(row => ({ reference: { kind: "storesProduct", id: row.id }, commerceDisplayPrice: row.commercePrice })),
1121
+ ],
1122
+ present: (state, price) => derive({ ...state,
1123
+ featuredProducts: state.featuredProducts.map(row => ({ ...row, price: price(row.id) })),
1124
+ savedProducts: state.savedProducts.map(row => ({ ...row, price: price(row.id, row.commercePrice) })),
1125
+ }),
1126
+ });
1127
+
1114
1128
  const svc = defineService<State, {
1115
1129
  // `State | undefined`, matching the implementation: `refresh` returns undefined on a
1116
1130
  // STALE generation (`if (gen !== refreshGen) return undefined`) so the runtime keeps