@wix/himalaya-cli 0.1576.0 → 0.1577.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 (76) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/loyalty/src/index.d.ts +64 -6
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/online-programs/src/index.d.ts +87 -0
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-loyalty.mjs +15 -3
  4. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-online-programs.mjs +42 -0
  5. package/dist/cli.mjs +10810 -10592
  6. package/dist/preview-assets.generated.bin +0 -0
  7. package/fixtures/wix-canned.json +56 -3
  8. package/guides/one-app-section-mappings.md +1 -1
  9. package/guides/one-app-to-himi-app.md +50 -1
  10. package/guides/sdk-reference.json +133 -9
  11. package/package.json +2 -2
  12. package/templates/beauty-salon/tier5-src/_shared/branded-lite-hosted.ts +1 -0
  13. package/templates/beauty-salon/tier5-src/_shared/owner-load-error.ts +8 -0
  14. package/templates/beauty-salon-owner/dev/index.ts +52 -27
  15. package/templates/beauty-salon-owner/tier5-src/_shared/owner-load-error.ts +8 -0
  16. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-post/index.ts +20 -8
  17. package/templates/branded-lite/config.ts +7 -0
  18. package/templates/branded-lite/dev/index.ts +833 -0
  19. package/templates/branded-lite/himalaya.content.json +3 -0
  20. package/templates/branded-lite/l10n/en.json +4 -2
  21. package/templates/branded-lite/tier5-src/_shared/branded-lite-hosted.ts +1 -0
  22. package/templates/branded-lite/tier5-src/_shared/owner-load-error.ts +8 -0
  23. package/templates/branded-lite/tier5-src/himi-branded-lite-member-programs/index.ts +658 -0
  24. package/templates/community-club/tier5-src/_shared/branded-lite-hosted.ts +1 -0
  25. package/templates/community-club/tier5-src/_shared/owner-load-error.ts +8 -0
  26. package/templates/community-club-owner/dev/index.ts +52 -27
  27. package/templates/community-club-owner/tier5-src/_shared/owner-load-error.ts +8 -0
  28. package/templates/community-club-owner/tier5-src/himi-owner-lite-post/index.ts +20 -8
  29. package/templates/events-meetups/tier5-src/_shared/branded-lite-hosted.ts +1 -0
  30. package/templates/events-meetups/tier5-src/_shared/owner-load-error.ts +8 -0
  31. package/templates/events-meetups-owner/dev/index.ts +52 -27
  32. package/templates/events-meetups-owner/tier5-src/_shared/owner-load-error.ts +8 -0
  33. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-post/index.ts +20 -8
  34. package/templates/gym-fitness/tier5-src/_shared/branded-lite-hosted.ts +1 -0
  35. package/templates/gym-fitness/tier5-src/_shared/owner-load-error.ts +8 -0
  36. package/templates/gym-fitness-owner/dev/index.ts +52 -27
  37. package/templates/gym-fitness-owner/tier5-src/_shared/owner-load-error.ts +8 -0
  38. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-post/index.ts +20 -8
  39. package/templates/himi-chat/tier5-src/_shared/owner-load-error.ts +8 -0
  40. package/templates/nonprofit-cause/tier5-src/_shared/branded-lite-hosted.ts +1 -0
  41. package/templates/nonprofit-cause/tier5-src/_shared/owner-load-error.ts +8 -0
  42. package/templates/nonprofit-cause-owner/dev/index.ts +52 -27
  43. package/templates/nonprofit-cause-owner/tier5-src/_shared/owner-load-error.ts +8 -0
  44. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-post/index.ts +20 -8
  45. package/templates/owner-lite/dev/index.ts +52 -27
  46. package/templates/owner-lite/tier5-src/_shared/owner-load-error.ts +8 -0
  47. package/templates/owner-lite/tier5-src/himi-owner-lite-post/index.ts +20 -8
  48. package/templates/podcast-creator/tier5-src/_shared/branded-lite-hosted.ts +1 -0
  49. package/templates/podcast-creator/tier5-src/_shared/owner-load-error.ts +8 -0
  50. package/templates/podcast-creator-owner/dev/index.ts +52 -27
  51. package/templates/podcast-creator-owner/tier5-src/_shared/owner-load-error.ts +8 -0
  52. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-post/index.ts +20 -8
  53. package/templates/portfolio-creative/tier5-src/_shared/branded-lite-hosted.ts +1 -0
  54. package/templates/portfolio-creative/tier5-src/_shared/owner-load-error.ts +8 -0
  55. package/templates/portfolio-creative-owner/dev/index.ts +52 -27
  56. package/templates/portfolio-creative-owner/tier5-src/_shared/owner-load-error.ts +8 -0
  57. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-post/index.ts +20 -8
  58. package/templates/restaurant/tier5-src/_shared/branded-lite-hosted.ts +1 -0
  59. package/templates/restaurant/tier5-src/_shared/owner-load-error.ts +8 -0
  60. package/templates/restaurant-owner/dev/index.ts +52 -27
  61. package/templates/restaurant-owner/tier5-src/_shared/owner-load-error.ts +8 -0
  62. package/templates/restaurant-owner/tier5-src/himi-owner-lite-post/index.ts +20 -8
  63. package/templates/retail-store/tier5-src/_shared/branded-lite-hosted.ts +1 -0
  64. package/templates/retail-store/tier5-src/_shared/owner-load-error.ts +8 -0
  65. package/templates/retail-store-owner/dev/index.ts +52 -27
  66. package/templates/retail-store-owner/tier5-src/_shared/owner-load-error.ts +8 -0
  67. package/templates/retail-store-owner/tier5-src/himi-owner-lite-post/index.ts +20 -8
  68. package/templates/yoga-studio/config.ts +7 -0
  69. package/templates/yoga-studio/dev/index.ts +833 -0
  70. package/templates/yoga-studio/himalaya.content.json +3 -0
  71. package/templates/yoga-studio/tier5-src/_shared/branded-lite-hosted.ts +1 -0
  72. package/templates/yoga-studio/tier5-src/_shared/owner-load-error.ts +8 -0
  73. package/templates/yoga-studio/tier5-src/himi-branded-lite-member-programs/index.ts +658 -0
  74. package/templates/yoga-studio-owner/dev/index.ts +52 -27
  75. package/templates/yoga-studio-owner/tier5-src/_shared/owner-load-error.ts +8 -0
  76. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-post/index.ts +20 -8
@@ -65684,16 +65684,17 @@ const SCREENS = runtimeSetting({
65684
65684
  "type": "VStack",
65685
65685
  "props": {
65686
65686
  "spacing": 10,
65687
+ "alignment": "leading",
65687
65688
  "children": [
65688
65689
  {
65689
- "id": "himi_owner_lite_inbox_thread.sk1",
65690
+ "id": "himi_owner_lite_inbox_thread.loading_text",
65690
65691
  "body": {
65691
65692
  "package": "himalaya",
65692
- "type": "Skeleton",
65693
+ "type": "Text",
65693
65694
  "props": {
65694
- "width": 220,
65695
- "height": 44,
65696
- "cornerRadius": 16
65695
+ "text": "Loading conversation…",
65696
+ "style": "body",
65697
+ "color": "textSecondary"
65697
65698
  }
65698
65699
  }
65699
65700
  },
@@ -65701,51 +65702,75 @@ const SCREENS = runtimeSetting({
65701
65702
  "id": "",
65702
65703
  "body": {
65703
65704
  "package": "himalaya",
65704
- "type": "HStack",
65705
+ "type": "VStack",
65705
65706
  "props": {
65707
+ "spacing": 10,
65706
65708
  "children": [
65709
+ {
65710
+ "id": "himi_owner_lite_inbox_thread.sk1",
65711
+ "body": {
65712
+ "package": "himalaya",
65713
+ "type": "Skeleton",
65714
+ "props": {
65715
+ "width": 220,
65716
+ "height": 44,
65717
+ "cornerRadius": 16
65718
+ }
65719
+ }
65720
+ },
65707
65721
  {
65708
65722
  "id": "",
65709
65723
  "body": {
65710
65724
  "package": "himalaya",
65711
- "type": "Spacer",
65712
- "props": {}
65725
+ "type": "HStack",
65726
+ "props": {
65727
+ "children": [
65728
+ {
65729
+ "id": "",
65730
+ "body": {
65731
+ "package": "himalaya",
65732
+ "type": "Spacer",
65733
+ "props": {}
65734
+ }
65735
+ },
65736
+ {
65737
+ "id": "himi_owner_lite_inbox_thread.sk2",
65738
+ "body": {
65739
+ "package": "himalaya",
65740
+ "type": "Skeleton",
65741
+ "props": {
65742
+ "width": 180,
65743
+ "height": 44,
65744
+ "cornerRadius": 16
65745
+ }
65746
+ }
65747
+ }
65748
+ ]
65749
+ }
65713
65750
  }
65714
65751
  },
65715
65752
  {
65716
- "id": "himi_owner_lite_inbox_thread.sk2",
65753
+ "id": "himi_owner_lite_inbox_thread.sk3",
65717
65754
  "body": {
65718
65755
  "package": "himalaya",
65719
65756
  "type": "Skeleton",
65720
65757
  "props": {
65721
- "width": 180,
65722
- "height": 44,
65758
+ "width": 240,
65759
+ "height": 64,
65723
65760
  "cornerRadius": 16
65724
65761
  }
65725
65762
  }
65726
65763
  }
65727
65764
  ]
65728
65765
  }
65729
- }
65730
- },
65731
- {
65732
- "id": "himi_owner_lite_inbox_thread.sk3",
65733
- "body": {
65734
- "package": "himalaya",
65735
- "type": "Skeleton",
65736
- "props": {
65737
- "width": 240,
65738
- "height": 64,
65739
- "cornerRadius": 16
65740
- }
65766
+ },
65767
+ "modifiers": {
65768
+ "fillMaxWidth": true,
65769
+ "accessibilityRole": "decorative"
65741
65770
  }
65742
65771
  }
65743
65772
  ]
65744
65773
  }
65745
- },
65746
- "modifiers": {
65747
- "fillMaxWidth": true,
65748
- "accessibilityRole": "decorative"
65749
65774
  }
65750
65775
  }
65751
65776
  },
@@ -194,6 +194,14 @@ export function isTransportFailure(e: unknown): boolean {
194
194
  return TRANSPORT.some((re) => re.test(msg));
195
195
  }
196
196
 
197
+ /** A failed READ says nothing about the record's existence when Wix is
198
+ * unreachable, overloaded or failing. Unlike the legacy bridge predicate this
199
+ * is independent of preview mode; a live preview's gateway failure is one too. */
200
+ export function readWasUnreachable(e: unknown): boolean {
201
+ const msg = String((e as Error)?.message ?? e ?? "");
202
+ return isTransportFailure(e) || /HTTP (?:408|429|5\d{2})\b/.test(msg);
203
+ }
204
+
197
205
  /** Transport failures that happen while CONNECTING — no connection, no route, no such host,
198
206
  * connection refused — so the request provably never left the device. Every other
199
207
  * transport failure (a timeout, a reset, a bad or truncated response, a browser's fetch
@@ -10,7 +10,7 @@ import { getPost, getDraftPost, publishDraftPost, revertDraftPost, deleteDraftPo
10
10
  import { parseRicosJson } from "@himalaya/wix-rich-content";
11
11
  import { openRichLink } from "../_shared/rich-content-link.js";
12
12
  import { richBody } from "../_shared/rich-body.js";
13
- import { ownerLoadError, isBridgeUnavailable, isTransportFailure, isOwnerPreviewDemo, ownerDemoFallback, ownerWriteError, isNotFound } from "../_shared/owner-load-error.js";
13
+ import { ownerLoadError, isBridgeUnavailable, readWasUnreachable, isOwnerPreviewDemo, ownerDemoFallback, ownerWriteError, isNotFound } from "../_shared/owner-load-error.js";
14
14
  import { DEMO_POSTS, DEMO_NOTE, DEMO_SAVE_NOTE } from "../_shared/owner-preview-demo.js";
15
15
  import { stashCopy, copyParam } from "../_shared/himi-copy.js";
16
16
  import { get as dbGet, upsert as dbUpsert, remove as dbRemove, type DbEntity } from "../_shared/owner-local-db.js";
@@ -270,14 +270,24 @@ async function refresh(prev: PostState, id: string, actionMessage = "", opts: {
270
270
  try { post = (await getPost(id)).post; } catch (e) { lastError = postError = e; /* draft-only */ }
271
271
  try { draft = (await getDraftPost(id)).draftPost; } catch (e) { lastError = e; /* published-only or missing */ }
272
272
  if (!post && !draft) {
273
- // Both arms swallowed their errors above; surface the DESIGNED bridge
274
- // boundary (and a device with no connection) so the callers' catches can fall
275
- // back to the cached row or the demo post — never "post not found" for a post
276
- // that was only unreachable.
273
+ // Both arms swallowed their errors above. Neither a failed published read
274
+ // nor a missing draft proves the post is gone.
277
275
  // Either read counts: a published-only post's draft read is always a 404, so the
278
276
  // published read's failure is the one that says whether the post was only unreachable.
279
277
  for (const err of [postError, lastError]) {
280
- if (isBridgeUnavailable(err) || isTransportFailure(err)) throw err;
278
+ // getPost may wrap the original read failure when its query fallback is
279
+ // empty. Preserve that cause's status instead of painting the wrapper's
280
+ // "Blog post not found" text for a gateway failure.
281
+ const cause = (err as { cause?: unknown } | undefined)?.cause;
282
+ for (const failure of [cause, err]) {
283
+ if (isBridgeUnavailable(failure) || readWasUnreachable(failure)) throw failure;
284
+ }
285
+ }
286
+ for (const err of [postError, lastError]) {
287
+ // Non-transient access/validation failures keep their status too: the
288
+ // SDK's empty-query wrapper is not the reason this read failed.
289
+ const failure = (err as { cause?: unknown } | undefined)?.cause ?? err;
290
+ if (failure !== undefined && !isNotFound(failure)) throw failure;
281
291
  }
282
292
  // Wix says it is gone on BOTH reads (a published-only post's draft read is a 404 on its
283
293
  // own): its cached row must not outlive it, or an offline load repaints a deleted post.
@@ -361,7 +371,8 @@ const svc = defineService<PostState, {
361
371
  } catch (e) {
362
372
  // Offline: fall back to the last-synced local row before the demo/error paths.
363
373
  // Wix says it is gone (e.g. a delete whose reply was lost): drop the row, never show it.
364
- const cached = isNotFound(e) ? (await cacheDrop(id), null) : await cacheGet(id);
374
+ const cached = isNotFound(e) ? (await cacheDrop(id), null)
375
+ : readWasUnreachable(e) || isBridgeUnavailable(e) ? await cacheGet(id) : null;
365
376
  if (cached) return cachedDetail(s, cached);
366
377
  if (ownerDemoFallback(e)) {
367
378
  const demo = demoDetail(s, id);
@@ -385,7 +396,8 @@ const svc = defineService<PostState, {
385
396
  return loaded;
386
397
  } catch (e) {
387
398
  // Wix says it is gone (e.g. a delete whose reply was lost): drop the row, never show it.
388
- const cached = isNotFound(e) ? (await cacheDrop(s.id), null) : await cacheGet(s.id);
399
+ const cached = isNotFound(e) ? (await cacheDrop(s.id), null)
400
+ : readWasUnreachable(e) || isBridgeUnavailable(e) ? await cacheGet(s.id) : null;
389
401
  if (cached) return cachedDetail(s, cached);
390
402
  if (ownerDemoFallback(e)) {
391
403
  const demo = demoDetail(s, s.id);
@@ -119,6 +119,7 @@ export const HOSTED_SCREEN_VERTICALS: Readonly<Record<string, readonly BrandedLi
119
119
  himi_portfolio: ["portfolio"],
120
120
  himi_portfolio_project: ["portfolio"],
121
121
  himi_programs: ["programs"],
122
+ himi_member_programs: ["programs"],
122
123
  himi_reservations: ["reservations"],
123
124
  himi_reserve: ["restaurants"],
124
125
  himi_review: ["reviews"],
@@ -194,6 +194,14 @@ export function isTransportFailure(e: unknown): boolean {
194
194
  return TRANSPORT.some((re) => re.test(msg));
195
195
  }
196
196
 
197
+ /** A failed READ says nothing about the record's existence when Wix is
198
+ * unreachable, overloaded or failing. Unlike the legacy bridge predicate this
199
+ * is independent of preview mode; a live preview's gateway failure is one too. */
200
+ export function readWasUnreachable(e: unknown): boolean {
201
+ const msg = String((e as Error)?.message ?? e ?? "");
202
+ return isTransportFailure(e) || /HTTP (?:408|429|5\d{2})\b/.test(msg);
203
+ }
204
+
197
205
  /** Transport failures that happen while CONNECTING — no connection, no route, no such host,
198
206
  * connection refused — so the request provably never left the device. Every other
199
207
  * transport failure (a timeout, a reset, a bad or truncated response, a browser's fetch
@@ -65684,16 +65684,17 @@ const SCREENS = runtimeSetting({
65684
65684
  "type": "VStack",
65685
65685
  "props": {
65686
65686
  "spacing": 10,
65687
+ "alignment": "leading",
65687
65688
  "children": [
65688
65689
  {
65689
- "id": "himi_owner_lite_inbox_thread.sk1",
65690
+ "id": "himi_owner_lite_inbox_thread.loading_text",
65690
65691
  "body": {
65691
65692
  "package": "himalaya",
65692
- "type": "Skeleton",
65693
+ "type": "Text",
65693
65694
  "props": {
65694
- "width": 220,
65695
- "height": 44,
65696
- "cornerRadius": 16
65695
+ "text": "Loading conversation…",
65696
+ "style": "body",
65697
+ "color": "textSecondary"
65697
65698
  }
65698
65699
  }
65699
65700
  },
@@ -65701,51 +65702,75 @@ const SCREENS = runtimeSetting({
65701
65702
  "id": "",
65702
65703
  "body": {
65703
65704
  "package": "himalaya",
65704
- "type": "HStack",
65705
+ "type": "VStack",
65705
65706
  "props": {
65707
+ "spacing": 10,
65706
65708
  "children": [
65709
+ {
65710
+ "id": "himi_owner_lite_inbox_thread.sk1",
65711
+ "body": {
65712
+ "package": "himalaya",
65713
+ "type": "Skeleton",
65714
+ "props": {
65715
+ "width": 220,
65716
+ "height": 44,
65717
+ "cornerRadius": 16
65718
+ }
65719
+ }
65720
+ },
65707
65721
  {
65708
65722
  "id": "",
65709
65723
  "body": {
65710
65724
  "package": "himalaya",
65711
- "type": "Spacer",
65712
- "props": {}
65725
+ "type": "HStack",
65726
+ "props": {
65727
+ "children": [
65728
+ {
65729
+ "id": "",
65730
+ "body": {
65731
+ "package": "himalaya",
65732
+ "type": "Spacer",
65733
+ "props": {}
65734
+ }
65735
+ },
65736
+ {
65737
+ "id": "himi_owner_lite_inbox_thread.sk2",
65738
+ "body": {
65739
+ "package": "himalaya",
65740
+ "type": "Skeleton",
65741
+ "props": {
65742
+ "width": 180,
65743
+ "height": 44,
65744
+ "cornerRadius": 16
65745
+ }
65746
+ }
65747
+ }
65748
+ ]
65749
+ }
65713
65750
  }
65714
65751
  },
65715
65752
  {
65716
- "id": "himi_owner_lite_inbox_thread.sk2",
65753
+ "id": "himi_owner_lite_inbox_thread.sk3",
65717
65754
  "body": {
65718
65755
  "package": "himalaya",
65719
65756
  "type": "Skeleton",
65720
65757
  "props": {
65721
- "width": 180,
65722
- "height": 44,
65758
+ "width": 240,
65759
+ "height": 64,
65723
65760
  "cornerRadius": 16
65724
65761
  }
65725
65762
  }
65726
65763
  }
65727
65764
  ]
65728
65765
  }
65729
- }
65730
- },
65731
- {
65732
- "id": "himi_owner_lite_inbox_thread.sk3",
65733
- "body": {
65734
- "package": "himalaya",
65735
- "type": "Skeleton",
65736
- "props": {
65737
- "width": 240,
65738
- "height": 64,
65739
- "cornerRadius": 16
65740
- }
65766
+ },
65767
+ "modifiers": {
65768
+ "fillMaxWidth": true,
65769
+ "accessibilityRole": "decorative"
65741
65770
  }
65742
65771
  }
65743
65772
  ]
65744
65773
  }
65745
- },
65746
- "modifiers": {
65747
- "fillMaxWidth": true,
65748
- "accessibilityRole": "decorative"
65749
65774
  }
65750
65775
  }
65751
65776
  },
@@ -194,6 +194,14 @@ export function isTransportFailure(e: unknown): boolean {
194
194
  return TRANSPORT.some((re) => re.test(msg));
195
195
  }
196
196
 
197
+ /** A failed READ says nothing about the record's existence when Wix is
198
+ * unreachable, overloaded or failing. Unlike the legacy bridge predicate this
199
+ * is independent of preview mode; a live preview's gateway failure is one too. */
200
+ export function readWasUnreachable(e: unknown): boolean {
201
+ const msg = String((e as Error)?.message ?? e ?? "");
202
+ return isTransportFailure(e) || /HTTP (?:408|429|5\d{2})\b/.test(msg);
203
+ }
204
+
197
205
  /** Transport failures that happen while CONNECTING — no connection, no route, no such host,
198
206
  * connection refused — so the request provably never left the device. Every other
199
207
  * transport failure (a timeout, a reset, a bad or truncated response, a browser's fetch
@@ -10,7 +10,7 @@ import { getPost, getDraftPost, publishDraftPost, revertDraftPost, deleteDraftPo
10
10
  import { parseRicosJson } from "@himalaya/wix-rich-content";
11
11
  import { openRichLink } from "../_shared/rich-content-link.js";
12
12
  import { richBody } from "../_shared/rich-body.js";
13
- import { ownerLoadError, isBridgeUnavailable, isTransportFailure, isOwnerPreviewDemo, ownerDemoFallback, ownerWriteError, isNotFound } from "../_shared/owner-load-error.js";
13
+ import { ownerLoadError, isBridgeUnavailable, readWasUnreachable, isOwnerPreviewDemo, ownerDemoFallback, ownerWriteError, isNotFound } from "../_shared/owner-load-error.js";
14
14
  import { DEMO_POSTS, DEMO_NOTE, DEMO_SAVE_NOTE } from "../_shared/owner-preview-demo.js";
15
15
  import { stashCopy, copyParam } from "../_shared/himi-copy.js";
16
16
  import { get as dbGet, upsert as dbUpsert, remove as dbRemove, type DbEntity } from "../_shared/owner-local-db.js";
@@ -270,14 +270,24 @@ async function refresh(prev: PostState, id: string, actionMessage = "", opts: {
270
270
  try { post = (await getPost(id)).post; } catch (e) { lastError = postError = e; /* draft-only */ }
271
271
  try { draft = (await getDraftPost(id)).draftPost; } catch (e) { lastError = e; /* published-only or missing */ }
272
272
  if (!post && !draft) {
273
- // Both arms swallowed their errors above; surface the DESIGNED bridge
274
- // boundary (and a device with no connection) so the callers' catches can fall
275
- // back to the cached row or the demo post — never "post not found" for a post
276
- // that was only unreachable.
273
+ // Both arms swallowed their errors above. Neither a failed published read
274
+ // nor a missing draft proves the post is gone.
277
275
  // Either read counts: a published-only post's draft read is always a 404, so the
278
276
  // published read's failure is the one that says whether the post was only unreachable.
279
277
  for (const err of [postError, lastError]) {
280
- if (isBridgeUnavailable(err) || isTransportFailure(err)) throw err;
278
+ // getPost may wrap the original read failure when its query fallback is
279
+ // empty. Preserve that cause's status instead of painting the wrapper's
280
+ // "Blog post not found" text for a gateway failure.
281
+ const cause = (err as { cause?: unknown } | undefined)?.cause;
282
+ for (const failure of [cause, err]) {
283
+ if (isBridgeUnavailable(failure) || readWasUnreachable(failure)) throw failure;
284
+ }
285
+ }
286
+ for (const err of [postError, lastError]) {
287
+ // Non-transient access/validation failures keep their status too: the
288
+ // SDK's empty-query wrapper is not the reason this read failed.
289
+ const failure = (err as { cause?: unknown } | undefined)?.cause ?? err;
290
+ if (failure !== undefined && !isNotFound(failure)) throw failure;
281
291
  }
282
292
  // Wix says it is gone on BOTH reads (a published-only post's draft read is a 404 on its
283
293
  // own): its cached row must not outlive it, or an offline load repaints a deleted post.
@@ -361,7 +371,8 @@ const svc = defineService<PostState, {
361
371
  } catch (e) {
362
372
  // Offline: fall back to the last-synced local row before the demo/error paths.
363
373
  // Wix says it is gone (e.g. a delete whose reply was lost): drop the row, never show it.
364
- const cached = isNotFound(e) ? (await cacheDrop(id), null) : await cacheGet(id);
374
+ const cached = isNotFound(e) ? (await cacheDrop(id), null)
375
+ : readWasUnreachable(e) || isBridgeUnavailable(e) ? await cacheGet(id) : null;
365
376
  if (cached) return cachedDetail(s, cached);
366
377
  if (ownerDemoFallback(e)) {
367
378
  const demo = demoDetail(s, id);
@@ -385,7 +396,8 @@ const svc = defineService<PostState, {
385
396
  return loaded;
386
397
  } catch (e) {
387
398
  // Wix says it is gone (e.g. a delete whose reply was lost): drop the row, never show it.
388
- const cached = isNotFound(e) ? (await cacheDrop(s.id), null) : await cacheGet(s.id);
399
+ const cached = isNotFound(e) ? (await cacheDrop(s.id), null)
400
+ : readWasUnreachable(e) || isBridgeUnavailable(e) ? await cacheGet(s.id) : null;
389
401
  if (cached) return cachedDetail(s, cached);
390
402
  if (ownerDemoFallback(e)) {
391
403
  const demo = demoDetail(s, s.id);
@@ -119,6 +119,7 @@ export const HOSTED_SCREEN_VERTICALS: Readonly<Record<string, readonly BrandedLi
119
119
  himi_portfolio: ["portfolio"],
120
120
  himi_portfolio_project: ["portfolio"],
121
121
  himi_programs: ["programs"],
122
+ himi_member_programs: ["programs"],
122
123
  himi_reservations: ["reservations"],
123
124
  himi_reserve: ["restaurants"],
124
125
  himi_review: ["reviews"],
@@ -194,6 +194,14 @@ export function isTransportFailure(e: unknown): boolean {
194
194
  return TRANSPORT.some((re) => re.test(msg));
195
195
  }
196
196
 
197
+ /** A failed READ says nothing about the record's existence when Wix is
198
+ * unreachable, overloaded or failing. Unlike the legacy bridge predicate this
199
+ * is independent of preview mode; a live preview's gateway failure is one too. */
200
+ export function readWasUnreachable(e: unknown): boolean {
201
+ const msg = String((e as Error)?.message ?? e ?? "");
202
+ return isTransportFailure(e) || /HTTP (?:408|429|5\d{2})\b/.test(msg);
203
+ }
204
+
197
205
  /** Transport failures that happen while CONNECTING — no connection, no route, no such host,
198
206
  * connection refused — so the request provably never left the device. Every other
199
207
  * transport failure (a timeout, a reset, a bad or truncated response, a browser's fetch
@@ -65760,16 +65760,17 @@ const SCREENS = runtimeSetting({
65760
65760
  "type": "VStack",
65761
65761
  "props": {
65762
65762
  "spacing": 10,
65763
+ "alignment": "leading",
65763
65764
  "children": [
65764
65765
  {
65765
- "id": "himi_owner_lite_inbox_thread.sk1",
65766
+ "id": "himi_owner_lite_inbox_thread.loading_text",
65766
65767
  "body": {
65767
65768
  "package": "himalaya",
65768
- "type": "Skeleton",
65769
+ "type": "Text",
65769
65770
  "props": {
65770
- "width": 220,
65771
- "height": 44,
65772
- "cornerRadius": 16
65771
+ "text": "Loading conversation…",
65772
+ "style": "body",
65773
+ "color": "textSecondary"
65773
65774
  }
65774
65775
  }
65775
65776
  },
@@ -65777,51 +65778,75 @@ const SCREENS = runtimeSetting({
65777
65778
  "id": "",
65778
65779
  "body": {
65779
65780
  "package": "himalaya",
65780
- "type": "HStack",
65781
+ "type": "VStack",
65781
65782
  "props": {
65783
+ "spacing": 10,
65782
65784
  "children": [
65785
+ {
65786
+ "id": "himi_owner_lite_inbox_thread.sk1",
65787
+ "body": {
65788
+ "package": "himalaya",
65789
+ "type": "Skeleton",
65790
+ "props": {
65791
+ "width": 220,
65792
+ "height": 44,
65793
+ "cornerRadius": 16
65794
+ }
65795
+ }
65796
+ },
65783
65797
  {
65784
65798
  "id": "",
65785
65799
  "body": {
65786
65800
  "package": "himalaya",
65787
- "type": "Spacer",
65788
- "props": {}
65801
+ "type": "HStack",
65802
+ "props": {
65803
+ "children": [
65804
+ {
65805
+ "id": "",
65806
+ "body": {
65807
+ "package": "himalaya",
65808
+ "type": "Spacer",
65809
+ "props": {}
65810
+ }
65811
+ },
65812
+ {
65813
+ "id": "himi_owner_lite_inbox_thread.sk2",
65814
+ "body": {
65815
+ "package": "himalaya",
65816
+ "type": "Skeleton",
65817
+ "props": {
65818
+ "width": 180,
65819
+ "height": 44,
65820
+ "cornerRadius": 16
65821
+ }
65822
+ }
65823
+ }
65824
+ ]
65825
+ }
65789
65826
  }
65790
65827
  },
65791
65828
  {
65792
- "id": "himi_owner_lite_inbox_thread.sk2",
65829
+ "id": "himi_owner_lite_inbox_thread.sk3",
65793
65830
  "body": {
65794
65831
  "package": "himalaya",
65795
65832
  "type": "Skeleton",
65796
65833
  "props": {
65797
- "width": 180,
65798
- "height": 44,
65834
+ "width": 240,
65835
+ "height": 64,
65799
65836
  "cornerRadius": 16
65800
65837
  }
65801
65838
  }
65802
65839
  }
65803
65840
  ]
65804
65841
  }
65805
- }
65806
- },
65807
- {
65808
- "id": "himi_owner_lite_inbox_thread.sk3",
65809
- "body": {
65810
- "package": "himalaya",
65811
- "type": "Skeleton",
65812
- "props": {
65813
- "width": 240,
65814
- "height": 64,
65815
- "cornerRadius": 16
65816
- }
65842
+ },
65843
+ "modifiers": {
65844
+ "fillMaxWidth": true,
65845
+ "accessibilityRole": "decorative"
65817
65846
  }
65818
65847
  }
65819
65848
  ]
65820
65849
  }
65821
- },
65822
- "modifiers": {
65823
- "fillMaxWidth": true,
65824
- "accessibilityRole": "decorative"
65825
65850
  }
65826
65851
  }
65827
65852
  },
@@ -194,6 +194,14 @@ export function isTransportFailure(e: unknown): boolean {
194
194
  return TRANSPORT.some((re) => re.test(msg));
195
195
  }
196
196
 
197
+ /** A failed READ says nothing about the record's existence when Wix is
198
+ * unreachable, overloaded or failing. Unlike the legacy bridge predicate this
199
+ * is independent of preview mode; a live preview's gateway failure is one too. */
200
+ export function readWasUnreachable(e: unknown): boolean {
201
+ const msg = String((e as Error)?.message ?? e ?? "");
202
+ return isTransportFailure(e) || /HTTP (?:408|429|5\d{2})\b/.test(msg);
203
+ }
204
+
197
205
  /** Transport failures that happen while CONNECTING — no connection, no route, no such host,
198
206
  * connection refused — so the request provably never left the device. Every other
199
207
  * transport failure (a timeout, a reset, a bad or truncated response, a browser's fetch