@wix/himalaya-cli 0.1593.0 → 0.1595.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 (24) hide show
  1. package/dist/cli.mjs +4 -3
  2. package/guides/one-app-to-himi-app.md +12 -0
  3. package/package.json +2 -2
  4. package/templates/beauty-salon/dev/index.ts +216 -8
  5. package/templates/beauty-salon/tier5-src/_shared/himi-store-facets.ts +26 -2
  6. package/templates/beauty-salon/tier5-src/himi-branded-lite-category/index.ts +3 -3
  7. package/templates/beauty-salon/tier5-src/himi-branded-lite-shop/index.ts +4 -4
  8. package/templates/branded-lite/dev/index.ts +216 -8
  9. package/templates/branded-lite/tier5-src/_shared/business-chat-transport.ts +9 -0
  10. package/templates/branded-lite/tier5-src/_shared/himi-store-facets.ts +26 -2
  11. package/templates/branded-lite/tier5-src/himi-branded-lite-category/index.ts +3 -3
  12. package/templates/branded-lite/tier5-src/himi-branded-lite-shop/index.ts +3 -3
  13. package/templates/gym-fitness/dev/index.ts +216 -8
  14. package/templates/gym-fitness/tier5-src/_shared/himi-store-facets.ts +26 -2
  15. package/templates/gym-fitness/tier5-src/himi-branded-lite-category/index.ts +3 -3
  16. package/templates/gym-fitness/tier5-src/himi-branded-lite-shop/index.ts +4 -4
  17. package/templates/portfolio-creative/dev/index.ts +216 -8
  18. package/templates/portfolio-creative/tier5-src/_shared/himi-store-facets.ts +26 -2
  19. package/templates/portfolio-creative/tier5-src/himi-branded-lite-category/index.ts +3 -3
  20. package/templates/portfolio-creative/tier5-src/himi-branded-lite-shop/index.ts +4 -4
  21. package/templates/retail-store/dev/index.ts +216 -8
  22. package/templates/retail-store/tier5-src/_shared/himi-store-facets.ts +26 -2
  23. package/templates/retail-store/tier5-src/himi-branded-lite-category/index.ts +3 -3
  24. package/templates/retail-store/tier5-src/himi-branded-lite-shop/index.ts +3 -3
package/dist/cli.mjs CHANGED
@@ -21591,7 +21591,7 @@ var init_contained_dev_module = __esm({
21591
21591
  // ../authoring-kit/ensure-templates.mjs
21592
21592
  import { spawnSync as spawnSync3 } from "node:child_process";
21593
21593
  import { randomUUID as randomUUID3 } from "node:crypto";
21594
- import { existsSync as existsSync15, mkdirSync as mkdirSync9, readFileSync as readFileSync16, readdirSync as readdirSync11, renameSync as renameSync5, rmSync as rmSync5, statSync as statSync5, writeFileSync as writeFileSync9 } from "node:fs";
21594
+ import { existsSync as existsSync15, mkdirSync as mkdirSync9, readFileSync as readFileSync16, readdirSync as readdirSync11, renameSync as renameSync5, rmSync as rmSync5, rmdirSync as rmdirSync2, statSync as statSync5, writeFileSync as writeFileSync9 } from "node:fs";
21595
21595
  import { dirname as dirname11, join as join14, relative as relative4, resolve as resolve15 } from "node:path";
21596
21596
  import { fileURLToPath as fileURLToPath9 } from "node:url";
21597
21597
  function stampPath(outRoot) {
@@ -27530,6 +27530,7 @@ function resolveIdiom(tokens2, ctx = {}) {
27530
27530
  var IDIOM_CONTEXTS, UNSAFE_KEYS;
27531
27531
  var init_idiom = __esm({
27532
27532
  "../../core/ts/src/idiom.ts"() {
27533
+ "use strict";
27533
27534
  init_define_HHP_CATALOG();
27534
27535
  IDIOM_CONTEXTS = {
27535
27536
  ios: { native: ["ios"] },
@@ -157806,7 +157807,7 @@ __export(app_source_exports, {
157806
157807
  zipAppSource: () => zipAppSource
157807
157808
  });
157808
157809
  import { createHash as createHash25 } from "node:crypto";
157809
- import { readdirSync as readdirSync28, lstatSync as lstatSync15, readFileSync as readFileSync55, mkdirSync as mkdirSync26, writeFileSync as writeFileSync21, existsSync as existsSync49, rmSync as rmSync16, rmdirSync as rmdirSync2, unlinkSync as unlinkSync3 } from "node:fs";
157810
+ import { readdirSync as readdirSync28, lstatSync as lstatSync15, readFileSync as readFileSync55, mkdirSync as mkdirSync26, writeFileSync as writeFileSync21, existsSync as existsSync49, rmSync as rmSync16, rmdirSync as rmdirSync3, unlinkSync as unlinkSync3 } from "node:fs";
157810
157811
  import { join as join42, resolve as resolve44, sep as sep13 } from "node:path";
157811
157812
  import { createRequire as createRequire4 } from "node:module";
157812
157813
  import { deflateRawSync as deflateRawSync2 } from "node:zlib";
@@ -158064,7 +158065,7 @@ function pruneEmptyDirs(root, rel, needed, removed) {
158064
158065
  empty2 = false;
158065
158066
  continue;
158066
158067
  }
158067
- rmdirSync2(join42(root, childRel));
158068
+ rmdirSync3(join42(root, childRel));
158068
158069
  removed.push(`${posix5}/`);
158069
158070
  }
158070
158071
  return empty2;
@@ -533,6 +533,18 @@ Apply these interpretation rules:
533
533
  without observer/listener fields. Do not infer a count badge for every custom
534
534
  component. Inspect its implementation and retain unknown behavior as unresolved.
535
535
 
536
+ Branded Lite's nav worker already counts the three source badges. Bind the bell to
537
+ `$service:brandedLiteNav.notificationsBadge` (the member's unseen notifications, read for the site the
538
+ native bridge is bound to), the chat button to `$service:brandedLiteNav.chatBadge` (the member's unread
539
+ business chatrooms, as the server counts them, capped at 100) and the cart button to
540
+ `$service:brandedLiteNav.cartBadge` (the shopper's cart item count, every line's quantity). Each is `null`
541
+ while unavailable (a Visitor's bell and chat, offline, a failed or stale read, an old binary or the web
542
+ for the bell) and the shell shows no badge for `null` or 0, so none is ever a fake zero. They refresh at
543
+ launch, whenever the signed-in identity changes (the previous identity's numbers go first), on every
544
+ foreground and on every notification receipt, and a read that finishes after the identity changed is
545
+ dropped. They do not poll: a screen that changes the cart (an add-to-cart, a checkout) must call
546
+ `tier5.brandedLiteNav.refreshBadges` itself, or the cart badge waits for the next trigger.
547
+
536
548
  Use a live `badge: { kind: "count", valuePath: "$service:sourceBadges.count" }`
537
549
  only after implementing the actual source counter. Preserve the source button
538
550
  ID, or map its current `top-bar` coverage row to the target `screenId` and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.1593.0",
3
+ "version": "0.1595.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": [
@@ -72,5 +72,5 @@
72
72
  "artifactId": "himalaya-cli"
73
73
  }
74
74
  },
75
- "falconPackageHash": "fb54e208c094140390368b7d75ef82ca0bffeb791cc24cb79670e599"
75
+ "falconPackageHash": "3dd5ff2b3474a615c124360272caab3992a905c773199cb98dcd52df"
76
76
  }
@@ -8991,7 +8991,33 @@ const SCREENS = runtimeSetting({
8991
8991
  "top": 2,
8992
8992
  "bottom": 2
8993
8993
  },
8994
- "hiddenPath": "$item.notOnSale"
8994
+ "hiddenPath": "$item.saleTagHidden"
8995
+ }
8996
+ },
8997
+ {
8998
+ "id": "",
8999
+ "body": {
9000
+ "package": "himalaya",
9001
+ "type": "Text",
9002
+ "props": {
9003
+ "text": "$item.ribbon",
9004
+ "style": "caption",
9005
+ "color": "accentPrimary",
9006
+ "maxLines": 1
9007
+ }
9008
+ },
9009
+ "modifiers": {
9010
+ "background": {
9011
+ "token": "accentSurface"
9012
+ },
9013
+ "cornerRadius": 6,
9014
+ "padding": {
9015
+ "leading": 6,
9016
+ "trailing": 6,
9017
+ "top": 2,
9018
+ "bottom": 2
9019
+ },
9020
+ "hiddenPath": "$item.noRibbon"
8995
9021
  }
8996
9022
  },
8997
9023
  {
@@ -9434,7 +9460,33 @@ const SCREENS = runtimeSetting({
9434
9460
  "top": 2,
9435
9461
  "bottom": 2
9436
9462
  },
9437
- "hiddenPath": "$item.notOnSale"
9463
+ "hiddenPath": "$item.saleTagHidden"
9464
+ }
9465
+ },
9466
+ {
9467
+ "id": "",
9468
+ "body": {
9469
+ "package": "himalaya",
9470
+ "type": "Text",
9471
+ "props": {
9472
+ "text": "$item.ribbon",
9473
+ "style": "caption",
9474
+ "color": "accentPrimary",
9475
+ "maxLines": 1
9476
+ }
9477
+ },
9478
+ "modifiers": {
9479
+ "background": {
9480
+ "token": "accentSurface"
9481
+ },
9482
+ "cornerRadius": 6,
9483
+ "padding": {
9484
+ "leading": 6,
9485
+ "trailing": 6,
9486
+ "top": 2,
9487
+ "bottom": 2
9488
+ },
9489
+ "hiddenPath": "$item.noRibbon"
9438
9490
  }
9439
9491
  },
9440
9492
  {
@@ -9909,7 +9961,33 @@ const SCREENS = runtimeSetting({
9909
9961
  "top": 2,
9910
9962
  "bottom": 2
9911
9963
  },
9912
- "hiddenPath": "$item.notOnSale"
9964
+ "hiddenPath": "$item.saleTagHidden"
9965
+ }
9966
+ },
9967
+ {
9968
+ "id": "",
9969
+ "body": {
9970
+ "package": "himalaya",
9971
+ "type": "Text",
9972
+ "props": {
9973
+ "text": "$item.ribbon",
9974
+ "style": "caption",
9975
+ "color": "accentPrimary",
9976
+ "maxLines": 1
9977
+ }
9978
+ },
9979
+ "modifiers": {
9980
+ "background": {
9981
+ "token": "accentSurface"
9982
+ },
9983
+ "cornerRadius": 6,
9984
+ "padding": {
9985
+ "leading": 6,
9986
+ "trailing": 6,
9987
+ "top": 2,
9988
+ "bottom": 2
9989
+ },
9990
+ "hiddenPath": "$item.noRibbon"
9913
9991
  }
9914
9992
  },
9915
9993
  {
@@ -10360,7 +10438,33 @@ const SCREENS = runtimeSetting({
10360
10438
  "top": 2,
10361
10439
  "bottom": 2
10362
10440
  },
10363
- "hiddenPath": "$item.notOnSale"
10441
+ "hiddenPath": "$item.saleTagHidden"
10442
+ }
10443
+ },
10444
+ {
10445
+ "id": "",
10446
+ "body": {
10447
+ "package": "himalaya",
10448
+ "type": "Text",
10449
+ "props": {
10450
+ "text": "$item.ribbon",
10451
+ "style": "caption",
10452
+ "color": "accentPrimary",
10453
+ "maxLines": 1
10454
+ }
10455
+ },
10456
+ "modifiers": {
10457
+ "background": {
10458
+ "token": "accentSurface"
10459
+ },
10460
+ "cornerRadius": 6,
10461
+ "padding": {
10462
+ "leading": 6,
10463
+ "trailing": 6,
10464
+ "top": 2,
10465
+ "bottom": 2
10466
+ },
10467
+ "hiddenPath": "$item.noRibbon"
10364
10468
  }
10365
10469
  },
10366
10470
  {
@@ -12990,7 +13094,33 @@ const SCREENS = runtimeSetting({
12990
13094
  "top": 2,
12991
13095
  "bottom": 2
12992
13096
  },
12993
- "hiddenPath": "$item.notOnSale"
13097
+ "hiddenPath": "$item.saleTagHidden"
13098
+ }
13099
+ },
13100
+ {
13101
+ "id": "",
13102
+ "body": {
13103
+ "package": "himalaya",
13104
+ "type": "Text",
13105
+ "props": {
13106
+ "text": "$item.ribbon",
13107
+ "style": "caption",
13108
+ "color": "accentPrimary",
13109
+ "maxLines": 1
13110
+ }
13111
+ },
13112
+ "modifiers": {
13113
+ "background": {
13114
+ "token": "accentSurface"
13115
+ },
13116
+ "cornerRadius": 6,
13117
+ "padding": {
13118
+ "leading": 6,
13119
+ "trailing": 6,
13120
+ "top": 2,
13121
+ "bottom": 2
13122
+ },
13123
+ "hiddenPath": "$item.noRibbon"
12994
13124
  }
12995
13125
  },
12996
13126
  {
@@ -13446,7 +13576,33 @@ const SCREENS = runtimeSetting({
13446
13576
  "top": 2,
13447
13577
  "bottom": 2
13448
13578
  },
13449
- "hiddenPath": "$item.notOnSale"
13579
+ "hiddenPath": "$item.saleTagHidden"
13580
+ }
13581
+ },
13582
+ {
13583
+ "id": "",
13584
+ "body": {
13585
+ "package": "himalaya",
13586
+ "type": "Text",
13587
+ "props": {
13588
+ "text": "$item.ribbon",
13589
+ "style": "caption",
13590
+ "color": "accentPrimary",
13591
+ "maxLines": 1
13592
+ }
13593
+ },
13594
+ "modifiers": {
13595
+ "background": {
13596
+ "token": "accentSurface"
13597
+ },
13598
+ "cornerRadius": 6,
13599
+ "padding": {
13600
+ "leading": 6,
13601
+ "trailing": 6,
13602
+ "top": 2,
13603
+ "bottom": 2
13604
+ },
13605
+ "hiddenPath": "$item.noRibbon"
13450
13606
  }
13451
13607
  },
13452
13608
  {
@@ -13934,7 +14090,33 @@ const SCREENS = runtimeSetting({
13934
14090
  "top": 2,
13935
14091
  "bottom": 2
13936
14092
  },
13937
- "hiddenPath": "$item.notOnSale"
14093
+ "hiddenPath": "$item.saleTagHidden"
14094
+ }
14095
+ },
14096
+ {
14097
+ "id": "",
14098
+ "body": {
14099
+ "package": "himalaya",
14100
+ "type": "Text",
14101
+ "props": {
14102
+ "text": "$item.ribbon",
14103
+ "style": "caption",
14104
+ "color": "accentPrimary",
14105
+ "maxLines": 1
14106
+ }
14107
+ },
14108
+ "modifiers": {
14109
+ "background": {
14110
+ "token": "accentSurface"
14111
+ },
14112
+ "cornerRadius": 6,
14113
+ "padding": {
14114
+ "leading": 6,
14115
+ "trailing": 6,
14116
+ "top": 2,
14117
+ "bottom": 2
14118
+ },
14119
+ "hiddenPath": "$item.noRibbon"
13938
14120
  }
13939
14121
  },
13940
14122
  {
@@ -14398,7 +14580,33 @@ const SCREENS = runtimeSetting({
14398
14580
  "top": 2,
14399
14581
  "bottom": 2
14400
14582
  },
14401
- "hiddenPath": "$item.notOnSale"
14583
+ "hiddenPath": "$item.saleTagHidden"
14584
+ }
14585
+ },
14586
+ {
14587
+ "id": "",
14588
+ "body": {
14589
+ "package": "himalaya",
14590
+ "type": "Text",
14591
+ "props": {
14592
+ "text": "$item.ribbon",
14593
+ "style": "caption",
14594
+ "color": "accentPrimary",
14595
+ "maxLines": 1
14596
+ }
14597
+ },
14598
+ "modifiers": {
14599
+ "background": {
14600
+ "token": "accentSurface"
14601
+ },
14602
+ "cornerRadius": 6,
14603
+ "padding": {
14604
+ "leading": 6,
14605
+ "trailing": 6,
14606
+ "top": 2,
14607
+ "bottom": 2
14608
+ },
14609
+ "hiddenPath": "$item.noRibbon"
14402
14610
  }
14403
14611
  },
14404
14612
  {
@@ -58,8 +58,14 @@ export interface ProductCard {
58
58
  swatch1: string; swatch2: string; swatch3: string; swatch4: string; swatch5: string;
59
59
  swatch1Hidden: boolean; swatch2Hidden: boolean; swatch3Hidden: boolean; swatch4Hidden: boolean; swatch5Hidden: boolean;
60
60
  noSwatches: boolean;
61
- /** Hides the Sale tag / swatch row when it has nothing to show. */
61
+ /** Hides the tag row (Sale tag, ribbon, swatches) when it has nothing to show. */
62
62
  noTagRow: boolean;
63
+ /** The merchant's ribbon text ("New", "Best Seller"…), "" when the product has none. The ribbon replaces
64
+ * the price-derived Sale tag, so a product never carries two tags. */
65
+ ribbon: string;
66
+ noRibbon: boolean;
67
+ /** Hides the price-derived Sale tag: the product is not on sale, or its ribbon takes the tag's place. */
68
+ saleTagHidden: boolean;
63
69
  /** The Wix price before any App Store presentation rewrites `price`. */
64
70
  commercePrice: string;
65
71
  /** Original Wix sale metadata retained when App Store presentation hides it. */
@@ -179,6 +185,21 @@ function swatchFields(hexes: string[], onSale: boolean) {
179
185
  };
180
186
  }
181
187
 
188
+ /** The ribbon the merchant set, whichever catalog answered: V3 `{ id, name }`, V1 a plain string. Read through a
189
+ * local type, not a `StoreProduct` member: other workers already extend that type with their own `ribbon`. */
190
+ export function ribbonText(p: StoreProduct): string {
191
+ const ribbon = (p as { ribbon?: unknown }).ribbon;
192
+ const name = typeof ribbon === "string" ? ribbon : typeof (ribbon as { name?: unknown } | null | undefined)?.name === "string" ? (ribbon as { name: string }).name : "";
193
+ return name.trim();
194
+ }
195
+
196
+ /** What the tag row (Sale tag, ribbon, swatches) shows. One rule for every screen that rebuilds it, including
197
+ * after the App Store presentation changes `onSale`: the ribbon wins over the Sale tag, so a product never
198
+ * carries two, and the row hides when it has nothing to show. */
199
+ export function tagFields(onSale: boolean, noSwatches: boolean, ribbon: string | undefined) {
200
+ return { ribbon: ribbon ?? "", noRibbon: !ribbon, saleTagHidden: !onSale || !!ribbon, noTagRow: !onSale && noSwatches && !ribbon };
201
+ }
202
+
182
203
  export function productCard(p: StoreProduct, saved: Set<string> = savedIds()): ProductCard {
183
204
  const { now, was } = prices(p);
184
205
  const groups = productOptions(p);
@@ -187,11 +208,14 @@ export function productCard(p: StoreProduct, saved: Set<string> = savedIds()): P
187
208
  const image = productImage(p);
188
209
  const id = p.id ?? "";
189
210
  const onSale = !!was;
211
+ const ribbon = ribbonText(p);
212
+ const swatches = swatchFields((color?.choices ?? []).map((c) => c.colorCode ?? ""), onSale);
190
213
  return {
191
214
  id, name, image, hasImage: !!image, noImage: !image, initial: initials(name),
192
215
  price: now, wasPrice: was, onSale, notOnSale: !onSale,
193
216
  saved: saved.has(id), notSaved: !saved.has(id),
194
- ...swatchFields((color?.choices ?? []).map((c) => c.colorCode ?? ""), onSale),
217
+ ...swatches,
218
+ ...tagFields(onSale, swatches.noSwatches, ribbon),
195
219
  commercePrice: now,
196
220
  detailScreenId: "himi_product",
197
221
  };
@@ -7,7 +7,7 @@ import { searchStoreProducts, type StoreProduct } from "../_shared/himi-store.js
7
7
  import { createCollectionQuery } from "../_shared/collection-query.js";
8
8
  import { detailInputId, presence, presenceAfterError, type PresenceFlags } from "../_shared/detail-presence.js";
9
9
  import { stashCopy, copyParam, copyTemplate } from "../_shared/himi-copy.js";
10
- import { FACETS_BOOT, PAGE_SIZE, applyFacets, currencyOf, facetActions, idOf, readViewPrefs, toRows, toggleSaved, type FacetState } from "../_shared/himi-store-facets.js";
10
+ import { FACETS_BOOT, PAGE_SIZE, applyFacets, currencyOf, facetActions, idOf, readViewPrefs, tagFields, toRows, toggleSaved, type FacetState } from "../_shared/himi-store-facets.js";
11
11
  import { withIapPresentation } from "../_shared/iap-presentation.js";
12
12
 
13
13
  interface State extends FacetState, PresenceFlags {
@@ -187,8 +187,8 @@ const register = withIapPresentation<State>({
187
187
  const onSale = stored.commerceOnSale ?? row.onSale;
188
188
  return { ...row, price: price(row.id, row.commercePrice) || row.price,
189
189
  commerceWasPrice: wasPrice, commerceOnSale: onSale,
190
- ...(apple(row.id) ? { wasPrice: "", onSale: false, notOnSale: true, noTagRow: row.noSwatches }
191
- : { wasPrice, onSale, notOnSale: !onSale, noTagRow: !onSale && row.noSwatches }),
190
+ ...(apple(row.id) ? { wasPrice: "", onSale: false, notOnSale: true, ...tagFields(false, row.noSwatches, row.ribbon) }
191
+ : { wasPrice, onSale, notOnSale: !onSale, ...tagFields(onSale, row.noSwatches, row.ribbon) }),
192
192
  };
193
193
  }) }),
194
194
  });
@@ -16,7 +16,7 @@ import { withIapPresentation } from "../_shared/iap-presentation.js";
16
16
  import { stashCopy, copyParam, copyTemplate } from "../_shared/himi-copy.js";
17
17
  import { loadStoreCategories, type StoreCategoryCard } from "../_shared/himi-store-categories.js";
18
18
  import {
19
- FACETS_BOOT, PAGE_SIZE, applyFacets, countText, currencyOf, facetActions, idOf, option, readViewPrefs, selected, toRows, toggleSaved,
19
+ FACETS_BOOT, PAGE_SIZE, applyFacets, countText, currencyOf, facetActions, idOf, option, readViewPrefs, selected, tagFields, toRows, toggleSaved,
20
20
  type FacetState, type Option, type ProductCard, type Row,
21
21
  } from "../_shared/himi-store-facets.js";
22
22
 
@@ -187,7 +187,7 @@ function cachedCard(value: unknown): CachedCard | undefined {
187
187
  price, wasPrice: "", onSale: false, notOnSale: true, saved: false, notSaved: true,
188
188
  swatch1: "", swatch2: "", swatch3: "", swatch4: "", swatch5: "",
189
189
  swatch1Hidden: true, swatch2Hidden: true, swatch3Hidden: true, swatch4Hidden: true, swatch5Hidden: true,
190
- noSwatches: true, noTagRow: true, commercePrice: raw.commercePrice ?? price,
190
+ noSwatches: true, ...tagFields(false, true, ""), commercePrice: raw.commercePrice ?? price,
191
191
  detailScreenId: raw.detailScreenId || "himi_product", legacyCache: true,
192
192
  };
193
193
  }
@@ -616,7 +616,7 @@ const register = withIapPresentation<S>({
616
616
  wasPrice: "",
617
617
  onSale: false,
618
618
  notOnSale: true,
619
- noTagRow: row.noSwatches,
619
+ ...tagFields(false, row.noSwatches, row.ribbon),
620
620
  };
621
621
  return {
622
622
  ...row,
@@ -624,7 +624,7 @@ const register = withIapPresentation<S>({
624
624
  wasPrice,
625
625
  onSale,
626
626
  notOnSale: !onSale,
627
- noTagRow: !onSale && row.noSwatches,
627
+ ...tagFields(onSale, row.noSwatches, row.ribbon),
628
628
  };
629
629
  }) }),
630
630
  });