@wix/himalaya-cli 0.817.0 → 0.819.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 +23 -6
  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 };