@wix/himalaya-cli 0.816.0 → 0.818.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 (126) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/wix-platform/src/index.d.ts +32 -0
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/activity-counters-v1/src/index.d.ts +16 -6
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/analytics/src/index.d.ts +1 -1
  4. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/automations-v1/src/index.d.ts +40 -30
  5. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/badges-v2/src/index.d.ts +23 -13
  6. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/billing-tax-v1/src/index.d.ts +22 -12
  7. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/blog-v3/src/index.d.ts +13 -3
  8. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/bookings-v2/src/index.d.ts +18 -8
  9. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/business-feed/src/index.d.ts +1 -1
  10. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/business-tools-v1/src/index.d.ts +29 -19
  11. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/comments-v1/src/index.d.ts +28 -18
  12. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/contacts/src/index.d.ts +18 -8
  13. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/coupons/src/index.d.ts +1 -1
  14. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/crm-tasks/src/index.d.ts +1 -1
  15. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/dashboard-setup/src/index.d.ts +1 -1
  16. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/data-collections-v1/src/index.d.ts +29 -19
  17. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/donations/src/index.d.ts +20 -10
  18. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/ecom/src/index.d.ts +13 -3
  19. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/email-marketing-v1/src/index.d.ts +29 -19
  20. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/events/src/index.d.ts +1 -1
  21. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/faq-v2/src/index.d.ts +27 -17
  22. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/forms/src/index.d.ts +16 -6
  23. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/forum/src/index.d.ts +16 -6
  24. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/genie-chat/src/index.d.ts +1 -1
  25. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/gift-cards/src/index.d.ts +21 -11
  26. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/groups/src/index.d.ts +14 -4
  27. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/inbox/src/index.d.ts +15 -5
  28. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/invoices/src/index.d.ts +1 -1
  29. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/loyalty/src/index.d.ts +1 -1
  30. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/marketing-v1/src/index.d.ts +16 -6
  31. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/members-v1/src/index.d.ts +1 -1
  32. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/new-releases/src/index.d.ts +1 -1
  33. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/notifications-v3/src/index.d.ts +13 -3
  34. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/online-programs/src/index.d.ts +1 -1
  35. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/portfolio/src/index.d.ts +1 -1
  36. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/pricing-plans/src/index.d.ts +1 -1
  37. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/redirects-v1/src/index.d.ts +13 -3
  38. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/restaurants/src/index.d.ts +18 -8
  39. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/reviews/src/index.d.ts +1 -1
  40. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/seo-v1/src/index.d.ts +15 -5
  41. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/site-list/src/index.d.ts +14 -4
  42. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/site-media/src/index.d.ts +1 -1
  43. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/social-feed/src/index.d.ts +1 -1
  44. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/stores-collections/src/index.d.ts +1 -1
  45. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/stores-v1/src/index.d.ts +13 -3
  46. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/table-reservations/src/index.d.ts +1 -1
  47. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/users/src/index.d.ts +1 -1
  48. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/wix-data/src/index.d.ts +1 -1
  49. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/workflows-v1/src/index.d.ts +17 -7
  50. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/screens.mjs +14 -4
  51. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-activity-counters.mjs +24 -10
  52. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-automations.mjs +100 -58
  53. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-badges.mjs +54 -24
  54. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-billing-tax.mjs +43 -22
  55. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-blog.mjs +18 -4
  56. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-bookings.mjs +36 -14
  57. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-business-tools.mjs +63 -36
  58. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-comments.mjs +62 -34
  59. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-contacts.mjs +35 -14
  60. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-data-collections.mjs +62 -36
  61. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-donations.mjs +37 -18
  62. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-ecom.mjs +14 -4
  63. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-email-marketing.mjs +66 -36
  64. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-faq.mjs +68 -32
  65. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-forms.mjs +25 -10
  66. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-forum.mjs +32 -10
  67. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-gift-cards.mjs +39 -20
  68. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-groups.mjs +18 -6
  69. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-inbox.mjs +22 -8
  70. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-marketing.mjs +23 -10
  71. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-notifications.mjs +18 -4
  72. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-platform.mjs +30 -0
  73. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-redirects.mjs +14 -4
  74. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-restaurants.mjs +32 -14
  75. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-seo.mjs +20 -8
  76. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-site-list.mjs +17 -6
  77. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-stores.mjs +15 -4
  78. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-workflows.mjs +28 -12
  79. package/dist/cli.mjs +58 -14
  80. package/guides/branded-lite-site-binding.md +14 -6
  81. package/guides/sdk-reference.json +398 -230
  82. package/package.json +2 -2
  83. package/templates/beauty-salon/dev/index.ts +1 -181
  84. package/templates/beauty-salon/tier5-src/himi-store-account/index.ts +9 -141
  85. package/templates/beauty-salon-owner/dev/index.ts +564 -0
  86. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-overview/index.ts +220 -0
  87. package/templates/branded-lite/dev/index.ts +1 -181
  88. package/templates/branded-lite/tier5-src/himi-store-account/index.ts +9 -141
  89. package/templates/community-club/dev/index.ts +1 -181
  90. package/templates/community-club/tier5-src/himi-store-account/index.ts +9 -141
  91. package/templates/community-club-owner/dev/index.ts +564 -0
  92. package/templates/community-club-owner/tier5-src/himi-owner-lite-overview/index.ts +220 -0
  93. package/templates/events-meetups/dev/index.ts +1 -181
  94. package/templates/events-meetups/tier5-src/himi-store-account/index.ts +9 -141
  95. package/templates/events-meetups-owner/dev/index.ts +564 -0
  96. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-overview/index.ts +220 -0
  97. package/templates/gym-fitness/dev/index.ts +1 -181
  98. package/templates/gym-fitness/tier5-src/himi-store-account/index.ts +9 -141
  99. package/templates/gym-fitness-owner/dev/index.ts +564 -0
  100. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-overview/index.ts +220 -0
  101. package/templates/nonprofit-cause/dev/index.ts +1 -181
  102. package/templates/nonprofit-cause/tier5-src/himi-store-account/index.ts +9 -141
  103. package/templates/nonprofit-cause-owner/dev/index.ts +564 -0
  104. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-overview/index.ts +220 -0
  105. package/templates/owner-lite/dev/index.ts +564 -0
  106. package/templates/owner-lite/tier5-src/himi-owner-lite-overview/index.ts +220 -0
  107. package/templates/podcast-creator/dev/index.ts +1 -181
  108. package/templates/podcast-creator/tier5-src/himi-store-account/index.ts +9 -141
  109. package/templates/podcast-creator-owner/dev/index.ts +564 -0
  110. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-overview/index.ts +220 -0
  111. package/templates/portfolio-creative/dev/index.ts +1 -181
  112. package/templates/portfolio-creative/tier5-src/himi-store-account/index.ts +9 -141
  113. package/templates/portfolio-creative-owner/dev/index.ts +564 -0
  114. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-overview/index.ts +220 -0
  115. package/templates/restaurant/dev/index.ts +1 -181
  116. package/templates/restaurant/tier5-src/himi-store-account/index.ts +9 -141
  117. package/templates/restaurant-owner/dev/index.ts +564 -0
  118. package/templates/restaurant-owner/tier5-src/himi-owner-lite-overview/index.ts +220 -0
  119. package/templates/retail-store/dev/index.ts +1 -181
  120. package/templates/retail-store/tier5-src/himi-store-account/index.ts +9 -141
  121. package/templates/retail-store-owner/dev/index.ts +564 -0
  122. package/templates/retail-store-owner/tier5-src/himi-owner-lite-overview/index.ts +220 -0
  123. package/templates/yoga-studio/dev/index.ts +1 -181
  124. package/templates/yoga-studio/tier5-src/himi-store-account/index.ts +9 -141
  125. package/templates/yoga-studio-owner/dev/index.ts +564 -0
  126. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-overview/index.ts +220 -0
@@ -0,0 +1,220 @@
1
+ // Tier-5 bundle: __HIMI_APP_NAME__ — Across your businesses (cross-site rollup).
2
+ //
3
+ // The question this screen answers is the one the Sites list cannot: an owner with three
4
+ // restaurants does not want to know which businesses exist, they want to know WHICH ONE
5
+ // NEEDS THEM RIGHT NOW. Answering that means reading every business at once.
6
+ //
7
+ // Which is exactly what `setActiveSite` cannot do. It re-scopes the whole process — every
8
+ // later call, every worker, the conducted cache and the entity cache move with it — so
9
+ // rolling up N businesses through it would mean N switches, N mints, and the owner's actual
10
+ // scope left wherever the loop happened to stop. `site.forSite(msid)` addresses ONE call at
11
+ // one business without moving anything, so the fan-out below is a plain `Promise.all` and
12
+ // the active business is untouched when it finishes.
13
+ //
14
+ // Reads are two rungs, deliberately:
15
+ // 1. `querySites` — ACCOUNT level (the owner's wixSession2 cookie alone, no per-site
16
+ // instance), so the list loads before any business is picked. Same call the Sites
17
+ // screen makes.
18
+ // 2. per-business `searchOrders` — SITE level, scoped by `site.forSite(msid)`, which sends
19
+ // `wix-site-id` for that call so the transport mints that business's User instance.
20
+ //
21
+ // ONE BUSINESS FAILING MUST NOT BLANK THE ROLLUP. A site the owner has no Stores app on,
22
+ // or one whose mint fails, resolves to `null` and renders as "—" beside the others rather
23
+ // than throwing the whole screen into its error state. A rollup that disappears because one
24
+ // of five businesses is unreachable is worse than one that says so in a row.
25
+
26
+ import { defineService } from "@himalaya/state";
27
+ import { querySites, type WixSite } from "@himalaya/wix-site-list";
28
+ import { site } from "@himalaya/wix-platform";
29
+ import { searchOrders } from "@himalaya/wix-ecom";
30
+ import { ownerLoadError, isBridgeUnavailable, isOwnerPreviewDemo } from "../_shared/owner-load-error.js";
31
+ import { DEMO_SITES, DEMO_NOTE } from "../_shared/owner-preview-demo.js";
32
+ import { stashCopy, copyParam } from "../_shared/himi-copy.js";
33
+
34
+ /** Mirrors the Home dashboard's "needs attention" definition, so a number here means the
35
+ * same thing it means after the owner drills into that business. */
36
+ const ATTENTION_PAYMENT_STATUSES = ["NOT_PAID", "PARTIALLY_PAID"];
37
+ const ATTENTION_FULFILLMENT_STATUSES = ["NOT_FULFILLED", "PARTIALLY_FULFILLED"];
38
+
39
+ /** Cap per business. This is a glance, not the orders list — and it bounds the fan-out on
40
+ * an account with many businesses. A count at the cap reads as "50+". */
41
+ const PER_SITE_LIMIT = 50;
42
+
43
+ interface OverviewRow {
44
+ id: string;
45
+ name: string;
46
+ initial: string;
47
+ /** "3", "50+", or "—" when that business could not be read. */
48
+ attention: string;
49
+ attentionLabel: string;
50
+ /** Drives the row's emphasis without the descriptor needing a comparison. */
51
+ needsAttention: boolean;
52
+ calm: boolean;
53
+ }
54
+
55
+ interface OverviewState {
56
+ status: "loading" | "ready" | "error";
57
+ rows: OverviewRow[];
58
+ summary: string;
59
+ emptyText: string;
60
+ error: string;
61
+ isLoading: boolean;
62
+ notLoading: boolean;
63
+ notErrored: boolean;
64
+ noEmpty: boolean;
65
+ hideContent: boolean;
66
+ demoNote: string;
67
+ notDemo: boolean;
68
+ }
69
+
70
+ function initialOf(name: string): string {
71
+ return (name.trim()[0] || "S").toUpperCase();
72
+ }
73
+
74
+ function countLabel(n: number | null): string {
75
+ if (n === null) return "—";
76
+ return n >= PER_SITE_LIMIT ? `${PER_SITE_LIMIT}+` : String(n);
77
+ }
78
+
79
+ function rowFor(id: string, name: string, count: number | null): OverviewRow {
80
+ const needs = count !== null && count > 0;
81
+ return {
82
+ id,
83
+ name,
84
+ initial: initialOf(name),
85
+ attention: countLabel(count),
86
+ // Reads as ONE phrase with the count rendered beside it — "3" + "orders need
87
+ // attention". So the label never repeats the number, or the row would say "1 · 1 order
88
+ // needs attention".
89
+ attentionLabel: count === null
90
+ ? copyParam("ownerOverview.unavailable", "Couldn’t read this business")
91
+ : count === 0
92
+ ? copyParam("ownerOverview.allClear", "All clear")
93
+ : count === 1
94
+ ? copyParam("ownerOverview.oneNeedsAttention", "order needs attention")
95
+ : copyParam("ownerOverview.manyNeedAttention", "orders need attention"),
96
+ needsAttention: needs,
97
+ calm: !needs,
98
+ };
99
+ }
100
+
101
+ /**
102
+ * Build the whole state from its FOUR real inputs. Everything else is derived here and
103
+ * never inherited.
104
+ *
105
+ * Deliberately not `shape({ ...previous, rows })`: the derived fields are strings and
106
+ * booleans, so a spread carries the previous load's `summary` forward and `??` keeps it —
107
+ * `""` is not nullish. That reads as "the rollup silently kept the last render's headline",
108
+ * which is exactly the bug a spread-and-default shape invites.
109
+ */
110
+ function shape(input: { status: OverviewState["status"]; rows?: OverviewRow[]; error?: string; demoNote?: string }): OverviewState {
111
+ const { status } = input;
112
+ const rows = input.rows ?? [];
113
+ const isLoading = status === "loading";
114
+ const flagged = rows.filter((r) => r.needsAttention).length;
115
+ const demoNote = input.demoNote ?? "";
116
+ return {
117
+ status,
118
+ rows,
119
+ // Leads with the businesses that want the owner, because that is the whole point of
120
+ // the screen. "All caught up" is a real answer, not an empty state.
121
+ summary: rows.length === 0 ? "" : flagged === 0
122
+ ? copyParam("ownerOverview.allCaughtUp", "All caught up across your businesses")
123
+ : flagged === 1
124
+ ? copyParam("ownerOverview.oneBusinessNeedsYou", "1 business needs you")
125
+ : `${flagged} ${copyParam("ownerOverview.manyBusinessesNeedYou", "businesses need you")}`,
126
+ emptyText: rows.length ? "" : copyParam("ownerOverview.empty", "No businesses on this account yet."),
127
+ error: input.error ?? "",
128
+ isLoading,
129
+ notLoading: !isLoading,
130
+ notErrored: status !== "error",
131
+ noEmpty: rows.length > 0 || status !== "ready",
132
+ hideContent: status !== "ready" || rows.length === 0,
133
+ demoNote,
134
+ notDemo: !demoNote,
135
+ };
136
+ }
137
+
138
+ /** Bridge-unavailable fallback: the sample businesses, honestly labelled. */
139
+ function demoRollup(): OverviewState {
140
+ const rows = DEMO_SITES.map((d, i) => rowFor(d.id, d.name, i === 0 ? 2 : 0));
141
+ return shape({ status: "ready", rows, demoNote: copyParam("ownerCommon.demoNote", DEMO_NOTE) });
142
+ }
143
+
144
+ /**
145
+ * One business's "needs attention" count, or null when that business could not be read.
146
+ *
147
+ * `site.forSite(msid)` is handed straight to the generated client as its options bag — it
148
+ * is shaped as one — so this call carries `wix-site-id` for THIS business while the app's
149
+ * active business stays wherever the owner left it.
150
+ */
151
+ async function attentionCount(msid: string): Promise<number | null> {
152
+ try {
153
+ const res = await searchOrders({
154
+ search: {
155
+ filter: {
156
+ archived: false,
157
+ status: { $nin: ["CANCELED", "CANCELLED"] },
158
+ $or: [
159
+ { paymentStatus: { $in: ATTENTION_PAYMENT_STATUSES } },
160
+ { paymentStatus: "PAID", fulfillmentStatus: { $in: ATTENTION_FULFILLMENT_STATUSES } },
161
+ ],
162
+ },
163
+ cursorPaging: { limit: PER_SITE_LIMIT },
164
+ },
165
+ }, site.forSite(msid));
166
+ return (res.orders ?? []).length;
167
+ } catch {
168
+ // Deliberately swallowed per business — see the header. The row says "—".
169
+ return null;
170
+ }
171
+ }
172
+
173
+ async function loadRollup(): Promise<OverviewState> {
174
+ if (isOwnerPreviewDemo()) return demoRollup();
175
+ try {
176
+ const res = await querySites({ query: { cursorPaging: { limit: 50 } } });
177
+ const businesses = (res.sites ?? [])
178
+ .filter((r: WixSite) => r?.id)
179
+ .map((r: WixSite) => ({
180
+ id: r.id || "",
181
+ name: r.displayName || (r as { name?: string }).name || r.id || "Site",
182
+ }));
183
+ if (businesses.length === 0) return shape({ status: "ready", rows: [] });
184
+
185
+ // THE FAN-OUT. Concurrent, one business each, active scope untouched.
186
+ const counts = await Promise.all(businesses.map((b) => attentionCount(b.id)));
187
+ const rows = businesses.map((b, i) => rowFor(b.id, b.name, counts[i]));
188
+ // Businesses that want the owner first; stable by name inside each group so the list
189
+ // does not reshuffle between loads.
190
+ // Plain codepoint compare, NOT localeCompare: the watch and wearable engines ship no
191
+ // ECMA-402, so an Intl-dependent worker either dies or silently mis-sorts there.
192
+ // Ordering business names is not a collation problem worth a wrist failure for.
193
+ rows.sort((a, b) =>
194
+ a.needsAttention === b.needsAttention
195
+ ? (a.name < b.name ? -1 : a.name > b.name ? 1 : 0)
196
+ : (a.needsAttention ? -1 : 1));
197
+ return shape({ status: "ready", rows });
198
+ } catch (e) {
199
+ // Only the ACCOUNT-level list failing gets here; a per-business failure is a row.
200
+ if (isBridgeUnavailable(e)) return demoRollup();
201
+ return shape({ status: "error", rows: [], error: ownerLoadError(e) });
202
+ }
203
+ }
204
+
205
+ const svc = defineService<OverviewState, {
206
+ load: (s: OverviewState, arg?: unknown) => Promise<OverviewState>;
207
+ retry: (s: OverviewState) => Promise<OverviewState>;
208
+ }>("himiOwnerLiteOverview", {
209
+ state: shape({ status: "loading" }),
210
+ actions: {
211
+ load: async (_s, arg) => {
212
+ stashCopy(arg); // absorb the descriptor's onAppear copy-pack param
213
+ return loadRollup();
214
+ },
215
+ retry: async () => loadRollup(),
216
+ },
217
+ });
218
+
219
+ svc.load();
220
+ export { svc };
@@ -4146,183 +4146,6 @@ const SCREENS = runtimeSetting({
4146
4146
  "accessibilityLabel": "himi_account.inbox"
4147
4147
  }
4148
4148
  },
4149
- {
4150
- "id": "",
4151
- "body": {
4152
- "package": "himalaya",
4153
- "type": "VStack",
4154
- "props": {
4155
- "spacing": 8,
4156
- "alignment": "leading",
4157
- "children": [
4158
- {
4159
- "id": "himi_account.sites_title",
4160
- "body": {
4161
- "package": "himalaya",
4162
- "type": "Text",
4163
- "props": {
4164
- "text": "$service:himiStoreAccount.sitesTitle",
4165
- "style": "title3"
4166
- }
4167
- }
4168
- },
4169
- {
4170
- "id": "",
4171
- "body": {
4172
- "package": "himalaya",
4173
- "type": "Text",
4174
- "props": {
4175
- "text": "Switch the active site. Home and verticals reload under that site.",
4176
- "style": "footnote",
4177
- "color": "textSecondary"
4178
- }
4179
- }
4180
- },
4181
- {
4182
- "id": "himi_account.sites",
4183
- "body": {
4184
- "package": "himalaya",
4185
- "type": "LazyList",
4186
- "props": {
4187
- "itemsPath": "$service:himiStoreAccount.sites",
4188
- "spacing": 8,
4189
- "items": [
4190
- {
4191
- "id": "",
4192
- "body": {
4193
- "package": "himalaya",
4194
- "type": "HStack",
4195
- "props": {
4196
- "spacing": 12,
4197
- "children": [
4198
- {
4199
- "id": "",
4200
- "body": {
4201
- "package": "himalaya",
4202
- "type": "Image",
4203
- "props": {
4204
- "url": "$item.image",
4205
- "width": 48,
4206
- "height": 48,
4207
- "contentMode": "fill",
4208
- "shape": "rounded",
4209
- "contentDescription": ""
4210
- }
4211
- }
4212
- },
4213
- {
4214
- "id": "",
4215
- "body": {
4216
- "package": "himalaya",
4217
- "type": "VStack",
4218
- "props": {
4219
- "spacing": 2,
4220
- "alignment": "leading",
4221
- "children": [
4222
- {
4223
- "id": "",
4224
- "body": {
4225
- "package": "himalaya",
4226
- "type": "Text",
4227
- "props": {
4228
- "text": "$item.name",
4229
- "style": "bodyEmphasis",
4230
- "collapseWhenEmpty": true
4231
- }
4232
- }
4233
- },
4234
- {
4235
- "id": "",
4236
- "body": {
4237
- "package": "himalaya",
4238
- "type": "Text",
4239
- "props": {
4240
- "text": "$item.role",
4241
- "style": "caption",
4242
- "color": "textSecondary",
4243
- "collapseWhenEmpty": true
4244
- }
4245
- }
4246
- }
4247
- ]
4248
- }
4249
- }
4250
- },
4251
- {
4252
- "id": "",
4253
- "body": {
4254
- "package": "himalaya",
4255
- "type": "Spacer",
4256
- "props": {}
4257
- }
4258
- },
4259
- {
4260
- "id": "",
4261
- "body": {
4262
- "package": "himalaya",
4263
- "type": "Text",
4264
- "props": {
4265
- "text": "$item.activeLabel",
4266
- "style": "caption",
4267
- "color": "accentPrimary",
4268
- "collapseWhenEmpty": true
4269
- }
4270
- }
4271
- },
4272
- {
4273
- "id": "",
4274
- "body": {
4275
- "package": "himalaya",
4276
- "type": "Icon",
4277
- "props": {
4278
- "name": "chevron_right",
4279
- "size": 16,
4280
- "tint": "textTertiary"
4281
- }
4282
- }
4283
- }
4284
- ]
4285
- }
4286
- },
4287
- "modifiers": {
4288
- "background": {
4289
- "token": "surfaceElevated"
4290
- },
4291
- "border": {
4292
- "width": 1,
4293
- "color": {
4294
- "token": "border"
4295
- }
4296
- },
4297
- "cornerRadius": 8,
4298
- "padding": {
4299
- "leading": 12,
4300
- "trailing": 12,
4301
- "top": 10,
4302
- "bottom": 10
4303
- },
4304
- "onTap": {
4305
- "actionId": "tier5.himiStoreAccount.selectSite",
4306
- "params": {
4307
- "siteId": "$item.id"
4308
- }
4309
- },
4310
- "pressFeedback": "scale",
4311
- "haptic": "light",
4312
- "accessibilityLabel": "himi_account.site_row"
4313
- }
4314
- }
4315
- ]
4316
- }
4317
- }
4318
- }
4319
- ]
4320
- }
4321
- },
4322
- "modifiers": {
4323
- "hiddenPath": "$service:himiStoreAccount.noSites"
4324
- }
4325
- },
4326
4149
  {
4327
4150
  "id": "",
4328
4151
  "body": {
@@ -4903,10 +4726,7 @@ const SCREENS = runtimeSetting({
4903
4726
  "bottom": 28
4904
4727
  },
4905
4728
  "onAppear": {
4906
- "actionId": "tier5.himiStoreAccount.refresh",
4907
- "params": {
4908
- "defaultSiteId": "development-site"
4909
- }
4729
+ "actionId": "tier5.himiStoreAccount.refresh"
4910
4730
  }
4911
4731
  }
4912
4732
  },
@@ -1,30 +1,24 @@
1
1
  // Tier-5 bundle: himi-store — visitor/member account state.
2
+ //
3
+ // SINGLE-SITE BY DESIGN. A Branded Lite build talks to exactly one Wix site, and the
4
+ // binding is the baked Headless `clientId` itself:
5
+ // there is no metaSiteId to move and Wix will not route a consumer token minted for one
6
+ // client at another site. This worker therefore has no site picker — Profile used to carry
7
+ // a "Your sites" list that dispatched `branded_lite.select_site`, which changed the
8
+ // `wix-site-id` header and nothing else, so every read stayed on the baked site while the
9
+ // UI claimed otherwise. Managing several businesses is Owner Lite's job (account auth, a
10
+ // real Sites List, and per-call site scope via `site.forSite`).
2
11
  import { defineService } from "@himalaya/state";
3
12
  import { dispatch } from "@himalaya/dispatch";
4
13
  import { searchOrders, type WixOrder } from "@himalaya/wix-ecom";
5
- import { querySites } from "@himalaya/wix-site-list";
6
- import { forgetCatalogVersion } from "@himalaya/wix-stores";
7
14
  import { guestProfile, loadMemberProfile, strOf, fmtDate, titleCase, type AccountActivityRow } from "../_shared/himi-account";
8
15
  import { stashCopy, copyParam, copyTemplate } from "../_shared/himi-copy.js";
9
16
 
10
- const ACTIVE_SITE_KEY = "himi.brandedLite.activeSiteId";
11
-
12
- interface StorageLike {
13
- getItem(key: string): string | null;
14
- setItem(key: string, value: string): void;
15
- }
16
-
17
17
  interface AuthRouteInput {
18
18
  intent?: string;
19
19
  contextName?: string;
20
20
  returnScreenId?: string;
21
21
  returnId?: string;
22
- defaultSiteId?: string;
23
- }
24
-
25
- function storage(): StorageLike | undefined {
26
- const host = globalThis as { himalaya?: { storage?: StorageLike }; localStorage?: StorageLike };
27
- return host.himalaya?.storage ?? host.localStorage;
28
22
  }
29
23
 
30
24
  /** Mid-flow open params land on `himalaya.input` (paramKeys on himi_account). */
@@ -33,40 +27,6 @@ function routeInput(): AuthRouteInput {
33
27
  return input && typeof input === "object" ? input : {};
34
28
  }
35
29
 
36
- interface SiteRow {
37
- id: string;
38
- name: string;
39
- role: string;
40
- image: string;
41
- isActive: boolean;
42
- notActive: boolean;
43
- activeLabel: string;
44
- }
45
-
46
- function siteThumb(id: string): string {
47
- return id ? `https://www.wix.com/site-thumbnail/${id}` : "";
48
- }
49
-
50
- function readActiveSiteId(fallback = ""): string {
51
- try {
52
- return (storage()?.getItem(ACTIVE_SITE_KEY) || "").trim() || fallback;
53
- } catch {
54
- return fallback;
55
- }
56
- }
57
-
58
- function writeActiveSiteId(id: string): void {
59
- try {
60
- storage()?.setItem(ACTIVE_SITE_KEY, id);
61
- } catch { /* ignore */ }
62
- }
63
-
64
- function defaultSiteIdFromArg(arg: unknown): string {
65
- if (!arg || typeof arg !== "object") return "";
66
- const raw = (arg as { defaultSiteId?: unknown }).defaultSiteId;
67
- return typeof raw === "string" ? raw.trim() : "";
68
- }
69
-
70
30
  function strField(arg: unknown, key: string): string {
71
31
  if (!arg || typeof arg !== "object") return "";
72
32
  const raw = (arg as Record<string, unknown>)[key];
@@ -144,37 +104,6 @@ function authHeadline(s: S, isRegistering: boolean, isRecovering: boolean): { au
144
104
  }
145
105
  }
146
106
 
147
- async function loadSites(activeId: string, fallbackId: string): Promise<SiteRow[]> {
148
- const active = activeId || fallbackId;
149
- try {
150
- const sitesRes = await querySites({ query: { cursorPaging: { limit: 50 } } });
151
- const rows = (sitesRes.sites ?? []).map((site): SiteRow => {
152
- const id = site.id || "";
153
- const isActive = !!active && id === active;
154
- return {
155
- id,
156
- name: site.displayName || site.name || id,
157
- role: isActive ? copyParam("storeAccount.siteRoleActive", "Current") : copyParam("storeAccount.siteRoleMember", "Site"),
158
- image: siteThumb(id),
159
- isActive,
160
- notActive: !isActive,
161
- activeLabel: isActive ? copyParam("storeAccount.siteActiveBadge", "Active") : "",
162
- };
163
- }).filter((r) => !!r.id);
164
- if (rows.length) return rows;
165
- } catch { /* fall through to seed */ }
166
- if (!fallbackId) return [];
167
- return [{
168
- id: fallbackId,
169
- name: copyParam("storeAccount.siteFallbackName", "This site"),
170
- role: copyParam("storeAccount.siteRoleActive", "Current"),
171
- image: siteThumb(fallbackId),
172
- isActive: true,
173
- notActive: false,
174
- activeLabel: copyParam("storeAccount.siteActiveBadge", "Active"),
175
- }];
176
- }
177
-
178
107
  interface S {
179
108
  status: "loading" | "ready";
180
109
  isMember: boolean;
@@ -224,20 +153,12 @@ interface S {
224
153
  activityEmptyText: string;
225
154
  hasActivity: boolean;
226
155
  noActivity: boolean;
227
- sitesTitle: string;
228
- sites: SiteRow[];
229
- hasSites: boolean;
230
- noSites: boolean;
231
- activeSiteId: string;
232
- defaultSiteId: string;
233
156
  }
234
157
 
235
158
  function derive(s: S): S {
236
159
  const isRegistering = !!s.isRegistering;
237
160
  const isRecovering = !!s.isRecovering;
238
161
  const hasActivity = s.activityRows.length > 0;
239
- const sites = s.sites ?? [];
240
- const hasSites = s.isMember && sites.length > 0;
241
162
  const headline = authHeadline(s, isRegistering, isRecovering);
242
163
  const hasReturnPath = !!s.isMember && !!s.returnScreenId;
243
164
  return {
@@ -252,10 +173,6 @@ function derive(s: S): S {
252
173
  hideSignInChoices: isRegistering || isRecovering,
253
174
  hasActivity,
254
175
  noActivity: !hasActivity,
255
- sites,
256
- hasSites,
257
- noSites: !hasSites,
258
- sitesTitle: copyParam("storeAccount.sitesTitle", "Your sites"),
259
176
  authTitle: headline.authTitle,
260
177
  authBody: headline.authBody,
261
178
  hasReturnPath,
@@ -307,19 +224,15 @@ async function orderRows(memberEmail: string): Promise<AccountActivityRow[]> {
307
224
  }
308
225
 
309
226
  async function probe(s: S, arg?: unknown): Promise<S> {
310
- const defaultSiteId = defaultSiteIdFromArg(arg) || s.defaultSiteId || "";
311
227
  const intent = authIntentFromArg(arg, s);
312
228
  const profile = await loadMemberProfile(copyParam("storeAccount.guestDetail", "Sign in to keep your cart and orders connected."));
313
229
  let activityRows: AccountActivityRow[] = [];
314
- let sites: SiteRow[] = [];
315
- const activeSiteId = readActiveSiteId(defaultSiteId);
316
230
  if (profile.isMember) {
317
231
  try {
318
232
  activityRows = await orderRows(profile.memberEmail);
319
233
  } catch {
320
234
  activityRows = [];
321
235
  }
322
- sites = await loadSites(activeSiteId, defaultSiteId);
323
236
  }
324
237
  return derive({
325
238
  ...s,
@@ -344,9 +257,6 @@ async function probe(s: S, arg?: unknown): Promise<S> {
344
257
  activityEmptyText: profile.isMember
345
258
  ? copyParam("storeAccount.activityEmptyMember", "No previous orders for this member yet.")
346
259
  : copyParam("storeAccount.activityEmptyGuest", "Sign in to see orders."),
347
- sites,
348
- activeSiteId,
349
- defaultSiteId,
350
260
  });
351
261
  }
352
262
 
@@ -389,7 +299,6 @@ const svc = defineService<S, {
389
299
  signIn: (s: S) => Promise<S>;
390
300
  register: (s: S) => Promise<S>;
391
301
  signOut: (s: S) => Promise<S>;
392
- selectSite: (s: S, arg?: unknown) => Promise<S>;
393
302
  }>("himiStoreAccount", {
394
303
  state: derive({
395
304
  status: "loading",
@@ -432,12 +341,6 @@ const svc = defineService<S, {
432
341
  activityEmptyText: "No previous orders for this member yet.",
433
342
  hasActivity: false,
434
343
  noActivity: true,
435
- sitesTitle: "Your sites",
436
- sites: [],
437
- hasSites: false,
438
- noSites: true,
439
- activeSiteId: "",
440
- defaultSiteId: "",
441
344
  }),
442
345
  actions: {
443
346
  load: (s, arg) => { stashCopy(arg); return probe(s, arg); },
@@ -521,7 +424,6 @@ const svc = defineService<S, {
521
424
  // user logs out. This is the one transition that unmounts Email too, so unlike
522
425
  // the mode switches it clears BOTH tokens.
523
426
  ...NO_FOCUS_ALL,
524
- sites: [] as SiteRow[],
525
427
  activityRows: [] as AccountActivityRow[],
526
428
  activityEmptyText: copyParam("storeAccount.activityEmptyGuest", "Sign in to see orders."),
527
429
  authIntent: "",
@@ -531,40 +433,6 @@ const svc = defineService<S, {
531
433
  };
532
434
  return derive(cleared);
533
435
  },
534
- selectSite: async (s, arg) => {
535
- const siteId = typeof arg === "string"
536
- ? arg.trim()
537
- : strOf((arg as { siteId?: unknown; id?: unknown })?.siteId
538
- ?? (arg as { siteId?: unknown; id?: unknown })?.id).trim();
539
- if (!siteId || siteId === s.activeSiteId) return derive(s);
540
- writeActiveSiteId(siteId);
541
- // The Stores SDK persists the resolved catalog version app-wide, and the new
542
- // site may run the other one. This is the only place that knows the site
543
- // changed, so it is the only place that can say so.
544
- //
545
- // Cleared BEFORE the dispatch because native may remount us before it settles,
546
- // and again AFTER it, because a read interleaving that await would re-resolve
547
- // against the bridge that has not been re-scoped yet and re-persist the value
548
- // we just dropped. Both are cheap; missing either leaves a wrong answer behind.
549
- forgetCatalogVersion();
550
- const sites = (s.sites ?? []).map((row) => {
551
- const isActive = row.id === siteId;
552
- return {
553
- ...row,
554
- isActive,
555
- notActive: !isActive,
556
- role: isActive
557
- ? copyParam("storeAccount.siteRoleActive", "Current")
558
- : copyParam("storeAccount.siteRoleMember", "Site"),
559
- activeLabel: isActive ? copyParam("storeAccount.siteActiveBadge", "Active") : "",
560
- };
561
- });
562
- try {
563
- await dispatch("branded_lite.select_site", { siteId });
564
- } catch { /* native may remount before the promise settles */ }
565
- forgetCatalogVersion();
566
- return derive({ ...s, activeSiteId: siteId, sites });
567
- },
568
436
  },
569
437
  });
570
438