@wix/himalaya-cli 0.980.0 → 0.982.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.
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/push/src/index.d.ts +31 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/define-app.d.ts +40 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/idiom.d.ts +59 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/index.d.ts +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/tokens.d.ts +22 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/core.mjs +67 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/push.mjs +21 -0
- package/dist/cli.mjs +301 -92
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/headless-loop.md +30 -15
- package/guides/sdk-reference.json +12 -0
- package/package.json +2 -2
package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/push/src/index.d.ts
CHANGED
|
@@ -95,3 +95,34 @@ export declare function listDelivered(): Promise<DeliveredNotification[]>;
|
|
|
95
95
|
export declare function clearDelivered(ids?: string[]): Promise<void>;
|
|
96
96
|
/** Capability version, for bundles that gate on min binary version. */
|
|
97
97
|
export declare const version = 1;
|
|
98
|
+
/** One notification, as a worker sees it. Every field is always present; an
|
|
99
|
+
* absent one reads as `""` rather than `undefined`, so a `$service:` binding at
|
|
100
|
+
* a field this payload omitted renders nothing instead of the text "undefined". */
|
|
101
|
+
export interface NotificationEvent {
|
|
102
|
+
/** Ping template that produced it, e.g. "stores.order_shipped". */
|
|
103
|
+
templateId: string;
|
|
104
|
+
/** Ping topic, e.g. "stores". */
|
|
105
|
+
topic: string;
|
|
106
|
+
/** The site the payload named, when it named one. */
|
|
107
|
+
metaSiteId: string;
|
|
108
|
+
/** Stable per-notification id — the key to deduplicate on. */
|
|
109
|
+
notificationId: string;
|
|
110
|
+
/** The link exactly as delivered, before any route translation. */
|
|
111
|
+
link: string;
|
|
112
|
+
/** What the route table translated `link` into, or `""` when no route
|
|
113
|
+
* matched. Empty is NOT an error: the notification still arrived, and a
|
|
114
|
+
* worker may want to count one it cannot open. */
|
|
115
|
+
resolvedLink: string;
|
|
116
|
+
/** True only when the user TAPPED. A foreground receipt is `false` and must
|
|
117
|
+
* not be treated as intent to navigate. */
|
|
118
|
+
tapped: boolean;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Read the params a dispatched `observerAction` receives.
|
|
122
|
+
*
|
|
123
|
+
* Runs on the untrusted edge of the bridge, so it never throws whatever arrives.
|
|
124
|
+
* `tapped` needs this reader more than the rest: the bridge stringifies every
|
|
125
|
+
* param, so a worker testing `params.tapped` truthily would read the string
|
|
126
|
+
* `"false"` as a tap.
|
|
127
|
+
*/
|
|
128
|
+
export declare function readNotificationEvent(params: unknown): NotificationEvent;
|
package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/define-app.d.ts
CHANGED
|
@@ -80,6 +80,38 @@ export interface AppCommerceConfig {
|
|
|
80
80
|
/** Copy-pack overrides for the paywall. */
|
|
81
81
|
copy?: Record<string, string>;
|
|
82
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* RFC 0059 §3.2 — the idiom policy: which named overlay from `tokens.json`'s `idiom` block a
|
|
85
|
+
* surface wears. `policy` is a tag, and each value owns its own sibling fields; the union
|
|
86
|
+
* makes the type checker reject the combinations the RFC rules out, not only the gate
|
|
87
|
+
* (`core/dev-server/tests/idiom-overlay-parity.test.ts`).
|
|
88
|
+
*
|
|
89
|
+
* - `follow-surface` (the default INSIDE a declared block): each surface wears the overlay
|
|
90
|
+
* for its own idiom — `ios` on the iOS renderer, `material` on Android, `desktop` on a
|
|
91
|
+
* desktop-class window. `surfaces` pins individual surfaces, keyed by catalog surface id
|
|
92
|
+
* like `NavigationConfig.surfaces`; `fallback` names the overlay for a surface with no
|
|
93
|
+
* idiom of its own. An overlay the app never authored resolves to base.
|
|
94
|
+
* - `pinned`: every surface wears the one overlay `pin` names. `surfaces` is not allowed —
|
|
95
|
+
* pinning one overlay and then overriding it per surface is `follow-surface`.
|
|
96
|
+
* - `none`: a declared opt-out. Same pixels as omitting the block, but on the record.
|
|
97
|
+
*/
|
|
98
|
+
export type IdiomPolicy = {
|
|
99
|
+
policy?: "follow-surface";
|
|
100
|
+
/** Catalog surface id (`phone` | `tablet` | `desktop` | `mac` | …) → overlay name. */
|
|
101
|
+
surfaces?: Record<string, string>;
|
|
102
|
+
fallback?: string;
|
|
103
|
+
pin?: never;
|
|
104
|
+
} | {
|
|
105
|
+
policy: "pinned";
|
|
106
|
+
pin: string;
|
|
107
|
+
surfaces?: never;
|
|
108
|
+
fallback?: never;
|
|
109
|
+
} | {
|
|
110
|
+
policy: "none";
|
|
111
|
+
surfaces?: never;
|
|
112
|
+
fallback?: never;
|
|
113
|
+
pin?: never;
|
|
114
|
+
};
|
|
83
115
|
export interface AppConfig {
|
|
84
116
|
/** Reverse-DNS app id, e.g. "com.wix.owner". */
|
|
85
117
|
id: string;
|
|
@@ -338,6 +370,14 @@ export interface AppConfig {
|
|
|
338
370
|
workerSubtreeScreens?: string[];
|
|
339
371
|
/** RFC 0010 — navigation structure + deep-link mapping, served OTA. */
|
|
340
372
|
navigation?: NavigationConfig;
|
|
373
|
+
/**
|
|
374
|
+
* RFC 0059 — how each surface picks its overlay from `tokens.json`'s `idiom` block.
|
|
375
|
+
*
|
|
376
|
+
* Two defaults, deliberately different: OMIT this block and the policy is `none` (base
|
|
377
|
+
* tokens, byte-identical to an app that never heard of idiom); DECLARE it without a
|
|
378
|
+
* `policy` and you get `follow-surface`. See `IdiomPolicy`.
|
|
379
|
+
*/
|
|
380
|
+
idiom?: IdiomPolicy;
|
|
341
381
|
/**
|
|
342
382
|
* App-declared Wix REST cache rules. The app controls per-endpoint opt-out
|
|
343
383
|
* (`cacheable: false`) and TTL; the server renders the EFFECTIVE policy by
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { IdiomPolicy } from "./define-app.js";
|
|
2
|
+
/** What a runtime tells the resolver about where it is drawing. */
|
|
3
|
+
export interface IdiomContext {
|
|
4
|
+
/**
|
|
5
|
+
* The overlays this runtime natively wears, most specific first: `["ios"]` on iOS,
|
|
6
|
+
* `["material"]` on Android, `["desktop", "ios"]` on macOS (RFC 0059 §7.1: a Mac wears
|
|
7
|
+
* `desktop`, falling back to `ios` when the app authored no `desktop` overlay). Empty ⇒ no
|
|
8
|
+
* native idiom (the web, today), so only `surfaces`, `fallback` or a pin can select one.
|
|
9
|
+
*/
|
|
10
|
+
native?: readonly string[];
|
|
11
|
+
/** Catalog surface id this frame renders on (`phone`, `tablet`, `mac`, …); keys `surfaces`. */
|
|
12
|
+
surface?: string;
|
|
13
|
+
}
|
|
14
|
+
/** The token-document fields resolution reads. `idiomPolicy` is stamped from `config.ts`. */
|
|
15
|
+
export interface IdiomDocument {
|
|
16
|
+
idiom?: Record<string, unknown>;
|
|
17
|
+
idiomPolicy?: IdiomPolicy;
|
|
18
|
+
}
|
|
19
|
+
/** The runtime contexts, in one place so the web host, RN and the tests agree on the names. */
|
|
20
|
+
export declare const IDIOM_CONTEXTS: {
|
|
21
|
+
readonly ios: {
|
|
22
|
+
readonly native: readonly ["ios"];
|
|
23
|
+
};
|
|
24
|
+
readonly android: {
|
|
25
|
+
readonly native: readonly ["material"];
|
|
26
|
+
};
|
|
27
|
+
readonly mac: {
|
|
28
|
+
readonly native: readonly ["desktop", "ios"];
|
|
29
|
+
readonly surface: "mac";
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* The overlay a surface wears, or `undefined` for the base look. Never throws: an absent or
|
|
34
|
+
* malformed policy, or a name the app never authored, resolves to base (RFC 0059 §3.3).
|
|
35
|
+
*
|
|
36
|
+
* - no policy, or `none` → base
|
|
37
|
+
* - `pinned` → `pin`
|
|
38
|
+
* - `follow-surface` (the default inside a declared block), first AUTHORED of:
|
|
39
|
+
* `surfaces[ctx.surface]`, then each of `ctx.native`, then `fallback`.
|
|
40
|
+
*/
|
|
41
|
+
export declare function selectIdiomOverlay(doc: IdiomDocument, ctx?: IdiomContext): string | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* Deep-merge one overlay over a base token document: objects merge key by key, and arrays and
|
|
44
|
+
* scalars replace. One rule is colour-specific, because a colour token has two shapes: a
|
|
45
|
+
* per-appearance overlay (`{ "dark": "#…" }`) over a single-hex base keeps the base as its
|
|
46
|
+
* `light` arm, so restyling one appearance never erases the others.
|
|
47
|
+
*/
|
|
48
|
+
export declare function mergeIdiomOverlay<T extends Record<string, unknown>>(base: T, overlay: Record<string, unknown>): T;
|
|
49
|
+
/**
|
|
50
|
+
* The token document a surface actually wears. Returns the SAME object when no overlay is
|
|
51
|
+
* selected, so an app that declares no idiom resolves byte-identically to before (the #2924
|
|
52
|
+
* opt-in guarantee).
|
|
53
|
+
*
|
|
54
|
+
* Resolution is FINAL: the merged result drops `idiomPolicy`, so resolving it again is a no-op
|
|
55
|
+
* under any context. That matters because resolved tokens get re-resolved — a scoped-theme
|
|
56
|
+
* subtree re-derives its resolvers from them, a native runtime may re-register `current` — and
|
|
57
|
+
* a second pass under a different context must not stack another overlay on the first.
|
|
58
|
+
*/
|
|
59
|
+
export declare function resolveIdiom<T extends object>(tokens: T, ctx?: IdiomContext): T;
|
package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export * from "./validation.js";
|
|
|
9
9
|
export * from "./widget-vocabulary.js";
|
|
10
10
|
export * from "./preview-surfaces.js";
|
|
11
11
|
export * from "./tokens.js";
|
|
12
|
+
export * from "./idiom.js";
|
|
12
13
|
export * from "./tier-caps.js";
|
|
13
14
|
export * from "./flags.js";
|
|
14
15
|
export * from "./flags-engine.js";
|
package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/tokens.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { IdiomPolicy } from "./define-app.js";
|
|
1
2
|
export type ColorScheme = "light" | "dark" | "highContrast";
|
|
2
3
|
export type ColorValue = string | {
|
|
3
4
|
light: string;
|
|
@@ -38,7 +39,28 @@ export interface DesignTokens {
|
|
|
38
39
|
* a comfortable column and a tablet/desktop fills more without running edge to
|
|
39
40
|
* edge. Absent ⇒ platform default (web 480/760, native fill). */
|
|
40
41
|
contentMaxWidth?: ResponsiveSize;
|
|
42
|
+
/** RFC 0059 — named idiom overlays, keyed by IDIOM (`ios`, `material`, `desktop`), not by
|
|
43
|
+
* platform. Which one a surface wears is `config.ts`'s `idiom` policy; with no policy the
|
|
44
|
+
* block is inert and base tokens resolve exactly as before. */
|
|
45
|
+
idiom?: Record<string, IdiomOverlay>;
|
|
46
|
+
/** RFC 0059 — the app's `config.ts` `idiom` policy, STAMPED into the served document by the
|
|
47
|
+
* dev-server (and so into every release snapshot) so each runtime can select an overlay
|
|
48
|
+
* in `register` with no second fetch. Derived, never authored in `tokens.json`. */
|
|
49
|
+
idiomPolicy?: IdiomPolicy;
|
|
41
50
|
}
|
|
51
|
+
/** Every field optional, at every depth: an idiom overlay restyles only what it names. */
|
|
52
|
+
export type DeepPartial<T> = T extends readonly (infer U)[] ? readonly DeepPartial<U>[] : T extends object ? {
|
|
53
|
+
[K in keyof T]?: DeepPartial<T[K]>;
|
|
54
|
+
} : T;
|
|
55
|
+
/**
|
|
56
|
+
* RFC 0059 §3.1 — one named idiom overlay: a partial token set deep-merged over the base,
|
|
57
|
+
* before appearance (`light`/`dark`/`highContrast`) resolves. It may only restyle tokens the
|
|
58
|
+
* base already declares — `core/dev-server/tests/idiom-overlay-parity.test.ts` enforces that.
|
|
59
|
+
*
|
|
60
|
+
* Not overlayable: `contentMaxWidth` (a Projection concern that RFC 0041 size classes own),
|
|
61
|
+
* `fontFaces` (the served font declaration, derived rather than authored) and `idiom` itself.
|
|
62
|
+
*/
|
|
63
|
+
export type IdiomOverlay = DeepPartial<Omit<DesignTokens, "idiom" | "idiomPolicy" | "contentMaxWidth" | "fontFaces">>;
|
|
42
64
|
/**
|
|
43
65
|
* One face in a font declaration.
|
|
44
66
|
*
|
|
@@ -9434,6 +9434,69 @@ function isComponentAllowed(surface, componentType) {
|
|
|
9434
9434
|
return row[gate.family] ? { allowed: true } : { allowed: false, reason: `not in the ${gate.family} allowlist` };
|
|
9435
9435
|
}
|
|
9436
9436
|
|
|
9437
|
+
// ../../core/ts/src/idiom.ts
|
|
9438
|
+
var IDIOM_CONTEXTS = {
|
|
9439
|
+
ios: { native: ["ios"] },
|
|
9440
|
+
android: { native: ["material"] },
|
|
9441
|
+
mac: { native: ["desktop", "ios"], surface: "mac" }
|
|
9442
|
+
};
|
|
9443
|
+
function authored(overlays, name) {
|
|
9444
|
+
return typeof name === "string" && overlays !== void 0 && Object.hasOwn(overlays, name) && overlays[name] !== null && typeof overlays[name] === "object" && !Array.isArray(overlays[name]);
|
|
9445
|
+
}
|
|
9446
|
+
function selectIdiomOverlay(doc, ctx = {}) {
|
|
9447
|
+
const policy = doc.idiomPolicy;
|
|
9448
|
+
const overlays = doc.idiom;
|
|
9449
|
+
const isRecord3 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
9450
|
+
if (!isRecord3(policy) || !isRecord3(overlays)) return void 0;
|
|
9451
|
+
const kind = policy.policy ?? "follow-surface";
|
|
9452
|
+
if (kind === "none") return void 0;
|
|
9453
|
+
if (kind === "pinned") return authored(overlays, policy.pin) ? policy.pin : void 0;
|
|
9454
|
+
if (kind !== "follow-surface") return void 0;
|
|
9455
|
+
const surfaces = policy.surfaces;
|
|
9456
|
+
const candidates = [
|
|
9457
|
+
ctx.surface !== void 0 && isRecord3(surfaces) && Object.hasOwn(surfaces, ctx.surface) ? surfaces[ctx.surface] : void 0,
|
|
9458
|
+
...ctx.native ?? [],
|
|
9459
|
+
policy.fallback
|
|
9460
|
+
];
|
|
9461
|
+
return candidates.find((c) => authored(overlays, c));
|
|
9462
|
+
}
|
|
9463
|
+
var UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
9464
|
+
function isPlainObject(v) {
|
|
9465
|
+
return v !== null && typeof v === "object" && !Array.isArray(v);
|
|
9466
|
+
}
|
|
9467
|
+
function deepMerge(base, overlay) {
|
|
9468
|
+
if (!isPlainObject(overlay) || !isPlainObject(base)) return overlay;
|
|
9469
|
+
const out = { ...base };
|
|
9470
|
+
for (const [key, value] of Object.entries(overlay)) {
|
|
9471
|
+
if (UNSAFE_KEYS.has(key)) continue;
|
|
9472
|
+
out[key] = Object.hasOwn(base, key) ? deepMerge(base[key], value) : value;
|
|
9473
|
+
}
|
|
9474
|
+
return out;
|
|
9475
|
+
}
|
|
9476
|
+
function mergeIdiomOverlay(base, overlay) {
|
|
9477
|
+
const merged = deepMerge(base, overlay);
|
|
9478
|
+
const baseColors = base.colors;
|
|
9479
|
+
const overlayColors = overlay.colors;
|
|
9480
|
+
if (isPlainObject(baseColors) && isPlainObject(overlayColors)) {
|
|
9481
|
+
const colors = { ...merged.colors };
|
|
9482
|
+
for (const [name, value] of Object.entries(overlayColors)) {
|
|
9483
|
+
if (UNSAFE_KEYS.has(name)) continue;
|
|
9484
|
+
const was = Object.hasOwn(baseColors, name) ? baseColors[name] : void 0;
|
|
9485
|
+
if (typeof was === "string" && isPlainObject(value)) colors[name] = { light: was, ...value };
|
|
9486
|
+
}
|
|
9487
|
+
merged.colors = colors;
|
|
9488
|
+
}
|
|
9489
|
+
return merged;
|
|
9490
|
+
}
|
|
9491
|
+
function resolveIdiom(tokens, ctx = {}) {
|
|
9492
|
+
const doc = tokens;
|
|
9493
|
+
const name = selectIdiomOverlay(doc, ctx);
|
|
9494
|
+
if (name === void 0) return tokens;
|
|
9495
|
+
const merged = mergeIdiomOverlay(tokens, doc.idiom[name]);
|
|
9496
|
+
const { idiomPolicy: _applied, ...final } = merged;
|
|
9497
|
+
return final;
|
|
9498
|
+
}
|
|
9499
|
+
|
|
9437
9500
|
// ../../core/ts/src/tier-caps.ts
|
|
9438
9501
|
function summarize(descriptor) {
|
|
9439
9502
|
const rendererTier = descriptor.renderer === "sdui_intent" ? "tier1" : descriptor.renderer === "sdui_layout" ? "tier2" : descriptor.renderer === "webview_native_bridge" ? "tier3" : "tier4";
|
|
@@ -12825,6 +12888,7 @@ export {
|
|
|
12825
12888
|
ICON_NORMALIZED_INDEX,
|
|
12826
12889
|
ICON_STROKE_WIDTH,
|
|
12827
12890
|
ICON_VIEW_BOX,
|
|
12891
|
+
IDIOM_CONTEXTS,
|
|
12828
12892
|
LAUNCH_MANIFEST_SCHEMA,
|
|
12829
12893
|
LAUNCH_NAMESPACE,
|
|
12830
12894
|
LINK_MOUNT_PATHS,
|
|
@@ -12889,12 +12953,14 @@ export {
|
|
|
12889
12953
|
isViewTarget,
|
|
12890
12954
|
isWidgetFamilySurface,
|
|
12891
12955
|
layoutDirection,
|
|
12956
|
+
mergeIdiomOverlay,
|
|
12892
12957
|
parseNumeric,
|
|
12893
12958
|
primarySubtag,
|
|
12894
12959
|
resolveAppIdentity,
|
|
12895
12960
|
resolveAppLocale,
|
|
12896
12961
|
resolveColor,
|
|
12897
12962
|
resolveIcon,
|
|
12963
|
+
resolveIdiom,
|
|
12898
12964
|
resolveKeyboard,
|
|
12899
12965
|
resolveMode,
|
|
12900
12966
|
resolveOrientationEnvelope,
|
|
@@ -12904,6 +12970,7 @@ export {
|
|
|
12904
12970
|
resolveSurfaceNav,
|
|
12905
12971
|
resolveSurfaceViewKey,
|
|
12906
12972
|
screenDescriptorSchema,
|
|
12973
|
+
selectIdiomOverlay,
|
|
12907
12974
|
shouldRevealError,
|
|
12908
12975
|
stripOriginParams,
|
|
12909
12976
|
summarize,
|
|
@@ -70,6 +70,26 @@ function normalizePermission(s) {
|
|
|
70
70
|
return s === "granted" || s === "denied" ? s : "undetermined";
|
|
71
71
|
}
|
|
72
72
|
var version = 1;
|
|
73
|
+
function readNotificationEvent(params) {
|
|
74
|
+
const p = params && typeof params === "object" ? params : {};
|
|
75
|
+
const str = (key) => {
|
|
76
|
+
const v = p[key];
|
|
77
|
+
if (v === void 0 || v === null) return "";
|
|
78
|
+
return typeof v === "string" ? v : String(v);
|
|
79
|
+
};
|
|
80
|
+
const raw = str("tapped").toLowerCase();
|
|
81
|
+
return {
|
|
82
|
+
templateId: str("templateId"),
|
|
83
|
+
topic: str("topic"),
|
|
84
|
+
metaSiteId: str("metaSiteId"),
|
|
85
|
+
notificationId: str("notificationId"),
|
|
86
|
+
link: str("link"),
|
|
87
|
+
resolvedLink: str("resolvedLink"),
|
|
88
|
+
// Absent or unrecognized ⇒ a RECEIPT. Guessing "tap" would navigate a user
|
|
89
|
+
// who never asked to go anywhere.
|
|
90
|
+
tapped: raw === "true" || raw === "1"
|
|
91
|
+
};
|
|
92
|
+
}
|
|
73
93
|
export {
|
|
74
94
|
cancelAllLocal,
|
|
75
95
|
cancelLocal,
|
|
@@ -79,6 +99,7 @@ export {
|
|
|
79
99
|
getDeviceToken,
|
|
80
100
|
getPermissionStatus,
|
|
81
101
|
listDelivered,
|
|
102
|
+
readNotificationEvent,
|
|
82
103
|
requestPermission,
|
|
83
104
|
scheduleLocal,
|
|
84
105
|
setBadge,
|