@wix/himalaya-cli 0.917.0 → 0.918.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.
@@ -12881,7 +12881,7 @@
12881
12881
  {
12882
12882
  "name": "isEmptyCurrentCartError",
12883
12883
  "kind": "function",
12884
- "jsdoc": "/** True when a thrown bridge/HTTP error means \"no current cart yet\" — Wix's\n * empty-cart signal. `GET /ecom/v1/carts/current` returns 404 with\n * `OWNED_CART_NOT_FOUND` until the visitor/member adds an item (a current cart\n * is created on first add-to-cart). Native surfaces `HTTP 404 [OWNED_CART_NOT_FOUND]: …`;\n * the web `__webwix` bridge surfaces `HTTP 404: {\"message\":\"Cart not found\",…}`. */",
12884
+ "jsdoc": "/** True when a thrown bridge/HTTP error means \"no current cart yet\" — Wix's\n * empty-cart signal. `GET /ecom/v1/carts/current` answers 404\n * `OWNED_CART_NOT_FOUND` until the visitor/member adds an item (a current cart\n * is created on first add-to-cart), and Wix's own description calls that the\n * expected pre-first-add state.\n *\n * DELIBERATELY NARROW — it keys on the typed application error code, never on the\n * 404 status and no longer on the human message \"Cart not found\". A bare\n * 404 with no code, a 403, a 500, a transport failure and every other cart error\n * code stay real failures and still throw. */",
12885
12885
  "decl": "export function isEmptyCurrentCartError(error: unknown): boolean;"
12886
12886
  },
12887
12887
  {
@@ -12893,7 +12893,7 @@
12893
12893
  {
12894
12894
  "name": "getCurrentCart",
12895
12895
  "kind": "function",
12896
- "jsdoc": "/** Read the current cart — GET /ecom/v1/carts/current. The API wraps the cart in\n * `{ cart: {...} }`; this unwraps it so callers get the cart (line items +\n * subtotal) directly. Verified live. An `OWNED_CART_NOT_FOUND` 404 is the empty\n * cart (never added an item) — returned as `{ lineItems: [] }`, not thrown. */",
12896
+ "jsdoc": "/** Read the current cart — GET /ecom/v1/carts/current. The API wraps the cart in\n * `{ cart: {...} }`; this unwraps it so callers get the cart (line items +\n * subtotal) directly. Verified live. An `OWNED_CART_NOT_FOUND` 404 is the empty\n * cart (never added an item) — resolved as `{ lineItems: [] }`, not thrown, so a\n * signed-out visitor's first mount is a successful read of an empty cart.\n * `{ lineItems: [] }` is the shape every caller already handles: the badge readers\n * sum `(cart.lineItems ?? [])` and the cart screen additionally takes\n * `cart.subtotal?.formattedAmount ?? \"\"` and `(await getCurrentCart()).id || \"\"` —\n * all three degrade to empty/0 on an absent field, so no caller special-cases it. */",
12897
12897
  "decl": "export async function getCurrentCart(): Promise<WixCartDetail>;",
12898
12898
  "http": "GET /ecom/v1/carts/current"
12899
12899
  },
@@ -18923,10 +18923,16 @@
18923
18923
  "jsdoc": "",
18924
18924
  "decl": "export interface MfvNotification {\n id?: string;\n type?: string;\n title?: string;\n message?: string;\n action?: string;\n sentDate?: string;\n /** UNSEEN | SEEN_BUT_UNREAD | READ | … */\n status?: string;\n deeplink?: MfvLink;\n icon?: MfvIcon;\n memberId?: string;\n}"
18925
18925
  },
18926
+ {
18927
+ "name": "__resetMfvRouteForTests",
18928
+ "kind": "function",
18929
+ "jsdoc": "/** Reset the learned route. Tests only — there is no runtime caller. */",
18930
+ "decl": "export function __resetMfvRouteForTests(): void;"
18931
+ },
18926
18932
  {
18927
18933
  "name": "queryNotifications",
18928
18934
  "kind": "function",
18929
- "jsdoc": "/** List the signed-in member's notifications, newest first. MOBILE channel.\n * verify-live: bare gateway path; _api proxy is the documented fallback. */",
18935
+ "jsdoc": "/** List the signed-in member's notifications, newest first. MOBILE channel. */",
18930
18936
  "decl": "export async function queryNotifications(limit = 25): Promise<MfvNotification[]>;"
18931
18937
  },
18932
18938
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.917.0",
3
+ "version": "0.918.0",
4
4
  "type": "module",
5
5
  "description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
6
6
  "keywords": [
@@ -64,5 +64,5 @@
64
64
  "artifactId": "himalaya-cli"
65
65
  }
66
66
  },
67
- "falconPackageHash": "7152abeca53488631b587df6f4efc519c4be90f5ad95fb10c94ee27e"
67
+ "falconPackageHash": "c1b47ea3d5bf730113aa0b5871851e82b129947c5c28bdd9911344a1"
68
68
  }
@@ -1,21 +1,29 @@
1
1
  // himi-branded-lite-forms — branded-lite "Forms" worker with a SAMPLE-DATA fallback
2
2
  // (same pattern as the other branded-lite verticals). Reads the site's real Wix Forms
3
- // (queryForms); when the site has no Forms app / no forms (the query errors — e.g.
4
- // 403/404/428 — or returns empty), it substitutes representative SAMPLE forms and flags
5
- // `isMock`, so the screen shows a clearly-labelled "Sample content" banner. Real forms
6
- // always win the moment any exist.
3
+ // (queryForms, which REQUIRES a namespace filter — a bare query is answered
4
+ // `400 MISSING_NAMESPACE_FILTER` for every site, #2769); when the site has no Forms
5
+ // app (403/404/428) or has no forms, it substitutes representative SAMPLE forms and
6
+ // flags `isMock`, so the screen shows a clearly-labelled "Sample content" banner.
7
+ // A query that FAILS for any other reason is reported as a failure — sample content
8
+ // there would state "this site has none yet", which the app never established.
9
+ // Real forms always win the moment any exist.
7
10
  import { defineService } from "../_shared/collection-service.js";
11
+ import { copyParam } from "../_shared/himi-copy.js";
8
12
  import { queryForms, type WixForm } from "@himalaya/wix-forms";
9
13
 
10
14
  interface Row { id: string; title: string; subtitle: string }
11
15
  interface S {
12
- status: "loading" | "ready";
16
+ status: "loading" | "ready" | "error";
13
17
  forms: Row[]; emptyText: string;
14
18
  isMock: boolean; notMock: boolean; mockBanner: string;
15
19
  }
16
20
 
17
21
  const STATUS_LABEL: Record<string, string> = { PUBLISHED: "Published", DRAFT: "Draft" };
18
22
 
23
+ /** The Wix Forms namespace the Forms app owns. Booking/event registration forms live
24
+ * in their own namespaces and are not this screen's subject. */
25
+ const FORMS_NAMESPACE = "wix.form_app.form";
26
+
19
27
  function norm(f: WixForm): Row {
20
28
  const title = (f.name || "Form").trim() || "Form";
21
29
  const fieldCount = Array.isArray(f.formFields) ? f.formFields.length : 0;
@@ -24,15 +32,25 @@ function norm(f: WixForm): Row {
24
32
  return { id: f.id || "form", title, subtitle: parts.join(" · ") };
25
33
  }
26
34
 
27
- const MOCK_BANNER = "Sample content — this site has no forms yet.";
35
+ /** Two banners, because the sample rows answer two different questions and only one of
36
+ * them is a statement about the customer's site.
37
+ *
38
+ * There used to be one banner, "this site has no forms yet", shown whenever the rows were
39
+ * samples — including when the query had FAILED. A site WITH forms got told it had none.
40
+ * The sample fallback itself is deliberate and covered by the renderer's offline test,
41
+ * which keeps these verticals showing labelled sample content rather than a blank screen.
42
+ * So what was wrong was never the samples — it was claiming to know something the app had
43
+ * not established. */
44
+ const MOCK_BANNER_EMPTY = "Sample content — this site has no forms yet.";
45
+ const MOCK_BANNER_UNAVAILABLE = "Sample content — this site's forms couldn't be loaded.";
28
46
  const MOCK: Row[] = [
29
47
  { id: "sample-contact", title: "Contact Us", subtitle: "4 fields · Published" },
30
48
  { id: "sample-subscribe", title: "Newsletter Signup", subtitle: "2 fields · Published" },
31
49
  { id: "sample-feedback", title: "Feedback", subtitle: "5 fields · Published" },
32
50
  ];
33
51
 
34
- function mockState(s: S): S {
35
- return { ...s, status: "ready", forms: MOCK.map((r) => ({ ...r })), emptyText: "", isMock: true, notMock: false, mockBanner: MOCK_BANNER };
52
+ function mockState(s: S, banner: string): S {
53
+ return { ...s, status: "ready", forms: MOCK.map((r) => ({ ...r })), emptyText: "", isMock: true, notMock: false, mockBanner: banner };
36
54
  }
37
55
 
38
56
  const svc = defineService<S, { load: (s: S) => Promise<S> }>("himiBrandedForms", {
@@ -40,12 +58,15 @@ const svc = defineService<S, { load: (s: S) => Promise<S> }>("himiBrandedForms",
40
58
  actions: {
41
59
  load: async (s) => {
42
60
  try {
43
- const r = await queryForms({ paging: { limit: 50 } });
61
+ const r = await queryForms({ filter: { namespace: FORMS_NAMESPACE }, paging: { limit: 50 } });
44
62
  const forms = (r.forms ?? []).map(norm);
45
63
  if (forms.length) return { ...s, status: "ready", forms, emptyText: "", isMock: false, notMock: true, mockBanner: "" };
46
- return mockState(s);
64
+ return mockState(s, copyParam("forms.emptyBanner", MOCK_BANNER_EMPTY));
47
65
  } catch {
48
- return mockState(s);
66
+ // The samples still render — a blank screen helps nobody and this vertical
67
+ // deliberately ships a fallback — but the banner no longer asserts the site is
68
+ // empty, because a failed query established no such thing.
69
+ return mockState(s, copyParam("forms.unavailableBanner", MOCK_BANNER_UNAVAILABLE));
49
70
  }
50
71
  },
51
72
  },