@wix/himalaya-cli 0.1154.0 → 0.1156.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.
@@ -2,6 +2,7 @@ import type { IncomingMessage, ServerResponse } from "node:http";
2
2
  import type { DerivedAppMeta } from "./app-module.js";
3
3
  import { type WixCachePolicy } from "./wix-cache-policy.js";
4
4
  import type { WixMockRule } from "./wix-gateway.js";
5
+ import { type UnmappedPushDestination } from "../../ts/src/wix-push-links.js";
5
6
  import type { PushConfig, FlagConfig, AppControl, TabBarConfig, DrawerConfig, SidebarConfig, SplashConfig, LocaleConfig, NavKind, OrientationConfig, StreamPolicy } from "@wix/himalaya/core";
6
7
  export type { PushConfig, FlagConfig, AppControl, TabBarConfig, DrawerConfig, SidebarConfig, SplashConfig, LocaleConfig, NavKind, OrientationConfig, StreamPolicy };
7
8
  export interface DeepLinkPattern {
@@ -214,6 +215,21 @@ export interface NavBundleContext {
214
215
  serverBaseUrl: string;
215
216
  bundleIntegrity(bundleName: string): string | null;
216
217
  }
218
+ /** The push block an app serves, and what a derived route table could not cover. */
219
+ export interface ServedPush {
220
+ push?: import("@wix/himalaya/core").PushConfig;
221
+ /** True when `routes` were derived rather than authored. */
222
+ derived: boolean;
223
+ unmapped: UnmappedPushDestination[];
224
+ }
225
+ /**
226
+ * The app's push block with its notification routes filled in, when the author opted into Wix
227
+ * push (`payloadAdapter: "wix-ping"`), wrote no `routes` of their own, and the package records its
228
+ * site's verticals (`derivesWixPushRoutes`). Routes then come from those verticals and the screens the router can open,
229
+ * so a build after adding a screen picks it up with no other step. Authored routes — an empty
230
+ * list included — are the author's, and are served untouched.
231
+ */
232
+ export declare function derivePushForApp(app: DerivedAppMeta, linkableScreens?: readonly LinkableScreen[]): ServedPush;
217
233
  export declare function deriveNavigationConfig(app: DerivedAppMeta, bundleCtx?: NavBundleContext): NavigationConfig;
218
234
  export interface AppConfigDocument {
219
235
  config: NavigationConfig;
@@ -1,4 +1,4 @@
1
- import type { AppConfig, AppConfigLike, FunctionsAppConfig } from "@wix/himalaya/core";
1
+ import type { AppConfig, AppConfigLike, FunctionsAppConfig, PushConfig } from "@wix/himalaya/core";
2
2
  import type { IncomingMessage, ServerResponse } from "node:http";
3
3
  import type { ActionHandler } from "./actions/types.js";
4
4
  import type { ScreenDescriptor } from "./builder.js";
@@ -175,8 +175,15 @@ export interface DerivedAppMeta {
175
175
  urlScheme: string;
176
176
  /** Forwarded from AppConfig.cache: the app's declared Wix read cache rules (#3450 follow-up). */
177
177
  cache?: import("@wix/himalaya/core").AppCacheConfig;
178
- /** Forwarded from AppConfig.push for the OTA app-config channel. */
178
+ /** Forwarded from AppConfig.push for the OTA app-config channel, minus the authoring-only
179
+ * `screens` map, which is carried separately below and never served. */
179
180
  push?: import("@wix/himalaya/core").PushConfig;
181
+ /** AppConfig.push.screens — which screen each Wix notification destination opens, for the
182
+ * routes `deriveNavigationConfig` derives when the app wrote none. */
183
+ pushScreens?: PushConfig["screens"];
184
+ /** `provisioning.json` `installedVerticals` — the site's verticals, which decide which Wix
185
+ * notification destinations a derived route table covers. Read from disk at load time. */
186
+ installedVerticals?: string[];
180
187
  /** Forwarded from AppConfig.control for the OTA app-config channel. */
181
188
  control?: import("@wix/himalaya/core").AppControl;
182
189
  /** Forwarded from AppConfig.appLinkHosts for the OTA app-config channel. */
@@ -270,7 +277,8 @@ export interface DerivedAppMeta {
270
277
  /** Android App-Links identity for /.well-known/assetlinks.json. */
271
278
  androidAssetLinks?: import("@wix/himalaya/core").AndroidAssetLinks;
272
279
  }
273
- /** `platforms` is the app's parsed `platforms.json` (RFC 0051 surface envelope).
274
- * Passed IN rather than read here because this module is types-only by design —
275
- * the reader lives in loader.ts, which already touches the filesystem. */
276
- export declare function deriveAppMeta(name: string, m: AppDevModule, platforms?: Record<string, boolean>): DerivedAppMeta;
280
+ /** `platforms` is the app's parsed `platforms.json` (RFC 0051 surface envelope), and
281
+ * `provisioning` the facts read from its `provisioning.json`. Both are passed IN rather than
282
+ * read here because this module is types-only by design — the readers live in loader.ts and
283
+ * provisioning-facts.ts, which already touch the filesystem. */
284
+ export declare function deriveAppMeta(name: string, m: AppDevModule, platforms?: Record<string, boolean>, provisioning?: import("./provisioning-facts.js").ProvisioningFacts): DerivedAppMeta;
@@ -0,0 +1,7 @@
1
+ export interface ProvisioningFacts {
2
+ siteId?: string;
3
+ installedVerticals?: string[];
4
+ }
5
+ /** `<dir>/provisioning.json`'s site and verticals. A missing or unreadable file, or a field of
6
+ * the wrong type, reads as absent: the file is a build input, never a reason to fail one. */
7
+ export declare function readProvisioningFacts(dir: string): ProvisioningFacts;
@@ -1,5 +1,6 @@
1
1
  import type { DesignTokens } from "./tokens.js";
2
2
  import type { PushRoute, PushPayloadAdapter } from "./push-routes.js";
3
+ import type { PushScreenMapEntry } from "./wix-push-links.js";
3
4
  import type { NavigationConfig, SplashConfig } from "./schema.js";
4
5
  import { type LocaleConfig } from "./locale.js";
5
6
  import { type DistributionConfig } from "./distribution.js";
@@ -7,7 +8,7 @@ import type { CmsConfig } from "./cms.js";
7
8
  import { type DataResourcesConfig } from "@wix/himalaya/data-resources";
8
9
  import type { FunctionDefinition, FunctionScheduleRecord } from "@himalaya/functions";
9
10
  export type { CmsConfig, CmsCollectionSpec, CmsFieldSpec, WixFieldType } from "./cms.js";
10
- export type { PushRoute, PushPayloadAdapter };
11
+ export type { PushRoute, PushPayloadAdapter, PushScreenMapEntry };
11
12
  export type { DataResourcesConfig, KvSpec, ResourceEnvironment, ResourceScope } from "@wix/himalaya/data-resources";
12
13
  export { WIX_FIELD_TYPES } from "./cms.js";
13
14
  /** Wix site/environment binding used by the server-function surface. */
@@ -530,6 +531,12 @@ export interface PushConfig {
530
531
  * hand-listing them, so a route can never target a screen the provisioned app
531
532
  * does not have. Honoured by iOS + Android; the web host has no push transport. */
532
533
  routes?: PushRoute[];
534
+ /** Authoring-only: which screen each Wix notification destination opens, keyed by
535
+ * destination id (`{ "store.order": "my_order" }`), when it is not the canonical one.
536
+ * With `payloadAdapter: "wix-ping"` and no `routes`, every build expands this — together
537
+ * with the site's `provisioning.json` verticals and the app's linkable screens — into
538
+ * `routes`. Never served; `himi validate` lists the destinations still unrouted. */
539
+ screens?: Record<string, PushScreenMapEntry>;
533
540
  payloadAdapter?: PushPayloadAdapter;
534
541
  /** A `tier5.<service>.<action>` dispatched on EVERY notification — receipt or tap
535
542
  * — so a worker can keep a badge count or refresh a feed without navigating. It
@@ -0,0 +1,81 @@
1
+ import type { PushRoute } from "./push-routes.js";
2
+ /**
3
+ * The Ping app family a customer app's members register under. Ping treats it exactly as
4
+ * `WixBrandedLite`: member recipients, the site's own credentials by `filterForMetaSite`,
5
+ * the BRANDED link format. One constant, so a revert is a one-line change.
6
+ */
7
+ export declare const DEFAULT_PING_APP_NAME = "WixBrandedWebApp";
8
+ /** One place a member notification can open, and every Wix link shape that names it. */
9
+ export interface WixPushDestination {
10
+ /** `<vertical>.<thing>`, the key an author uses in `push.screens`. */
11
+ id: string;
12
+ /** The vertical `himi site analyze` writes into `provisioning.json` `installedVerticals`. */
13
+ vertical: string;
14
+ /** Owner (`wixUser`) links live in a different Ping recipient space; none are listed yet. */
15
+ audience: "member";
16
+ /** Longest first, which is the order routes are tried in. */
17
+ matches: readonly string[];
18
+ /** The capture that names the item, filled into the screen's param. Absent ⇒ the
19
+ * destination is a list screen and the link carries no param. */
20
+ screenParam?: string;
21
+ /** The branded-lite screen id, which template-derived apps share. */
22
+ canonicalScreen: string;
23
+ }
24
+ export declare const WIX_MEMBER_PUSH_DESTINATIONS: readonly WixPushDestination[];
25
+ /** `push.screens` value: the screen a destination opens, optionally with the param it reads. */
26
+ export type PushScreenMapEntry = string | {
27
+ screenId: string;
28
+ paramKey?: string;
29
+ };
30
+ /** A screen a route may target — the shape of a served `LinkableScreen`, loosely. */
31
+ export interface PushTargetScreen {
32
+ screenId: string;
33
+ paramKeys?: readonly string[];
34
+ }
35
+ export interface UnmappedPushDestination {
36
+ destination: string;
37
+ vertical: string;
38
+ /** `no_screen`: nothing the app can open. `screen_lacks_param`: a detail screen that
39
+ * declares no param key the item id can go in. `param_not_declared`: `push.screens` names a
40
+ * `paramKey` the screen does not declare. */
41
+ reason: "no_screen" | "screen_lacks_param" | "param_not_declared";
42
+ /** The screen that was considered, when there was one. */
43
+ screenId?: string;
44
+ /** The undeclared key, for `param_not_declared`. */
45
+ paramKey?: string;
46
+ }
47
+ export interface DerivedWixPushRoutes {
48
+ routes: PushRoute[];
49
+ unmapped: UnmappedPushDestination[];
50
+ }
51
+ /**
52
+ * Whether a build derives `routes` for this push block: the author opted into Wix links
53
+ * (`payloadAdapter: "wix-ping"`), declared no table of their own, and the package records its
54
+ * site's verticals in provisioning.json — an empty list included, since a screen the app has is
55
+ * routed whatever the verticals say. The build and `himi validate` both ask this, so they agree.
56
+ */
57
+ export declare function derivesWixPushRoutes(push: {
58
+ payloadAdapter?: string;
59
+ routes?: unknown;
60
+ } | undefined, installedVerticals: readonly string[] | undefined): boolean;
61
+ /** The routes for one destination, opening `screenId` and putting the item id in `paramKey`. */
62
+ export declare function wixPushRoutesTo(destination: WixPushDestination, target: {
63
+ scheme: string;
64
+ screenId: string;
65
+ paramKey?: string;
66
+ }): PushRoute[];
67
+ /**
68
+ * The routes an app's screens support, and every destination its site has that the app cannot
69
+ * honour yet. A destination is routed only when its screen is CERTAIN — named in `map`, or the
70
+ * canonical id is one the app has — because a wrong screen is worse than none.
71
+ *
72
+ * The site's verticals, and the author's own `map` entries, decide only what is reported missing.
73
+ * A screen that is there is routed whatever the verticals say: `himi site analyze` cannot detect every vertical (it has no probe for
74
+ * notifications or galleries), and a route to a screen the app has can never open the wrong one.
75
+ */
76
+ export declare function deriveWixPushRoutes(input: {
77
+ verticals: readonly string[];
78
+ scheme: string;
79
+ screens: readonly PushTargetScreen[];
80
+ map?: Readonly<Record<string, PushScreenMapEntry>>;
81
+ }): DerivedWixPushRoutes;
@@ -7909,10 +7909,52 @@ function walk(node, registry, path, out) {
7909
7909
  });
7910
7910
  }
7911
7911
  }
7912
+ const type = typeof obj.type === "string" ? obj.type : "";
7913
+ const colorProps = Object.prototype.hasOwnProperty.call(COLOR_TOKEN_PROPS, type) ? COLOR_TOKEN_PROPS[type] : void 0;
7914
+ const typoProps = Object.prototype.hasOwnProperty.call(TYPOGRAPHY_TOKEN_PROPS, type) ? TYPOGRAPHY_TOKEN_PROPS[type] : void 0;
7915
+ if ((colorProps || typoProps) && obj.props && typeof obj.props === "object") {
7916
+ const props = obj.props;
7917
+ const check = (spec, kind) => {
7918
+ const [arrayKey, leaf] = spec.includes("[].") ? spec.split("[].") : [void 0, spec];
7919
+ const sites = arrayKey ? (Array.isArray(props[arrayKey]) ? props[arrayKey] : []).map((el, i) => [`${path}.props.${arrayKey}[${i}].${leaf}`, el && typeof el === "object" ? el[leaf] : void 0]) : [[`${path}.props.${leaf}`, props[leaf]]];
7920
+ for (const [at, v] of sites) {
7921
+ if (typeof v !== "string" || v === "") continue;
7922
+ if (kind === "color" ? !v.startsWith("#") && !registry.colors.has(v) : !registry.typography.has(v)) {
7923
+ out.push({ path: at, kind, name: v });
7924
+ }
7925
+ }
7926
+ };
7927
+ for (const spec of colorProps ?? []) check(spec, "color");
7928
+ for (const spec of typoProps ?? []) check(spec, "typography");
7929
+ }
7912
7930
  for (const [key, value] of Object.entries(obj)) {
7913
7931
  walk(value, registry, `${path}.${key}`, out);
7914
7932
  }
7915
7933
  }
7934
+ var COLOR_TOKEN_PROPS = {
7935
+ Badge: ["token"],
7936
+ Card: ["background"],
7937
+ Image: ["tint", "placeholder"],
7938
+ Tag: ["token"],
7939
+ Icon: ["tint"],
7940
+ Toggle: ["trackOn", "trackOff", "thumb"],
7941
+ ProgressBar: ["tint", "trackColor"],
7942
+ ListItem: ["titleColor", "subtitleColor", "overlineColor"],
7943
+ Slider: ["tint"],
7944
+ ActivityIndicator: ["tint"],
7945
+ Label: ["color"],
7946
+ Gauge: ["tint", "rings[].tint"],
7947
+ Rating: ["color"],
7948
+ VoiceNote: ["tint"],
7949
+ Marquee: ["color"],
7950
+ Fab: ["tint"]
7951
+ };
7952
+ var TYPOGRAPHY_TOKEN_PROPS = {
7953
+ ListItem: ["titleStyle", "subtitleStyle"],
7954
+ RichText: ["runs[].style"],
7955
+ Label: ["style"],
7956
+ Marquee: ["style"]
7957
+ };
7916
7958
 
7917
7959
  // ../../core/ts/src/widget-vocabulary.ts
7918
7960
  var WIDGET_FAMILIES = ["ios_home", "ios_lock", "android_home", "web_card", "ios_live_activity", "watch_complication", "car_list"];
@@ -9050,7 +9050,7 @@ function isFunctionsOnlyConfig(config) {
9050
9050
  function uiConfig(config) {
9051
9051
  return config ?? {};
9052
9052
  }
9053
- function deriveAppMeta(name, m, platforms = {}) {
9053
+ function deriveAppMeta(name, m, platforms = {}, provisioning = {}) {
9054
9054
  const config = m.config;
9055
9055
  return {
9056
9056
  surfaces: config.navigation?.surfaces,
@@ -9061,7 +9061,9 @@ function deriveAppMeta(name, m, platforms = {}) {
9061
9061
  screenIds: Object.keys(m.screens.exact),
9062
9062
  templatedPatterns: (m.screens.templated ?? []).map((t) => t.display),
9063
9063
  urlScheme: m.urlScheme ?? config.navigation?.scheme ?? `himalaya-${name}`,
9064
- push: config.push,
9064
+ push: servedPush(config.push),
9065
+ ...config.push?.screens ? { pushScreens: config.push.screens } : {},
9066
+ ...provisioning.installedVerticals ? { installedVerticals: provisioning.installedVerticals } : {},
9065
9067
  control: config.control,
9066
9068
  appLinkHosts: config.appLinkHosts,
9067
9069
  tabBar: config.navigation?.tabBar,
@@ -9095,6 +9097,11 @@ function deriveAppMeta(name, m, platforms = {}) {
9095
9097
  androidAssetLinks: config.androidAssetLinks
9096
9098
  };
9097
9099
  }
9100
+ function servedPush(push) {
9101
+ if (!push) return void 0;
9102
+ const { screens: _authoringOnly, ...served } = push;
9103
+ return served;
9104
+ }
9098
9105
 
9099
9106
  // ../../core/sdui/src/screen-kit.ts
9100
9107
  function skRect(height, id) {