@wix/himalaya-cli 0.1499.0 → 0.1501.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/cli.mjs +6 -4
- package/guides/sdk-reference.json +29 -384
- package/guides/splash-screens.md +56 -2
- package/package.json +2 -2
- package/templates/branded-lite/dev/index.ts +112 -25
- package/templates/branded-lite/tier5-src/_shared/business-chat-presenter.ts +24 -4
- package/templates/branded-lite/tier5-src/business-chat/index.ts +68 -20
package/dist/cli.mjs
CHANGED
|
@@ -2576,10 +2576,11 @@ __export(splash_exports, {
|
|
|
2576
2576
|
import { existsSync as existsSync3, readFileSync as readFileSync4, readdirSync as readdirSync3 } from "node:fs";
|
|
2577
2577
|
import { dirname as dirname4, join as join5 } from "node:path";
|
|
2578
2578
|
function parseSplashConfig(configTs) {
|
|
2579
|
-
const block = /splash
|
|
2579
|
+
const block = /["']?splash["']?\s*[:=]\s*\{([^}]*)\}/.exec(configTs);
|
|
2580
2580
|
if (!block) return {};
|
|
2581
|
-
const backgroundColor = /backgroundColor
|
|
2582
|
-
|
|
2581
|
+
const backgroundColor = /["']?backgroundColor["']?\s*:\s*["']([^"']+)["']/.exec(block[1])?.[1];
|
|
2582
|
+
const logoAsset = /["']?logoAsset["']?\s*:\s*["']([^"']*)["']/.exec(block[1])?.[1];
|
|
2583
|
+
return { ...backgroundColor ? { backgroundColor } : {}, ...logoAsset !== void 0 ? { logoAsset } : {} };
|
|
2583
2584
|
}
|
|
2584
2585
|
function nativeConfigInputTokens(configTs) {
|
|
2585
2586
|
const declared = configTs ? parseSplashConfig(configTs).backgroundColor : void 0;
|
|
@@ -22149,6 +22150,7 @@ function resolveIdiom(tokens2, ctx = {}) {
|
|
|
22149
22150
|
var IDIOM_CONTEXTS, UNSAFE_KEYS;
|
|
22150
22151
|
var init_idiom = __esm({
|
|
22151
22152
|
"../../core/ts/src/idiom.ts"() {
|
|
22153
|
+
"use strict";
|
|
22152
22154
|
IDIOM_CONTEXTS = {
|
|
22153
22155
|
ios: { native: ["ios"] },
|
|
22154
22156
|
android: { native: ["material"] },
|
|
@@ -147009,7 +147011,7 @@ var init_template_trim = __esm({
|
|
|
147009
147011
|
return Array.isArray(items) ? items : void 0;
|
|
147010
147012
|
};
|
|
147011
147013
|
NAV_SCREEN_KEYS = /* @__PURE__ */ new Set(["screenId", "parentScreenId", "contentScreenId", "badgeScreenId"]);
|
|
147012
|
-
WORKER_SCREEN_PARAMS = /* @__PURE__ */ new Set(["signInScreen"]);
|
|
147014
|
+
WORKER_SCREEN_PARAMS = /* @__PURE__ */ new Set(["signInScreen", "productScreen", "serviceScreen"]);
|
|
147013
147015
|
sorted = (xs2) => [...new Set(xs2)].sort();
|
|
147014
147016
|
refuse3 = (e2) => ({ code: 2, result: { ok: false, error: e2.message, ...e2.detail } });
|
|
147015
147017
|
plural = (n2, word) => `${n2} ${word}${n2 === 1 ? "" : "s"}`;
|
|
@@ -1987,7 +1987,7 @@
|
|
|
1987
1987
|
"name": "IAP_CATALOG_KINDS",
|
|
1988
1988
|
"kind": "const",
|
|
1989
1989
|
"jsdoc": "/** The Wix entity types `himi store iap` writes into its Wix→Apple mapping, so a mapping\n * backend can serve that export without translating kinds. */",
|
|
1990
|
-
"decl": "export const IAP_CATALOG_KINDS = [\"onlineProgram\", \"storesProduct\", \"pricingPlan\"
|
|
1990
|
+
"decl": "export const IAP_CATALOG_KINDS = [\"onlineProgram\", \"storesProduct\", \"pricingPlan\"] as const;"
|
|
1991
1991
|
},
|
|
1992
1992
|
{
|
|
1993
1993
|
"name": "IapCatalogKind",
|
|
@@ -2119,19 +2119,7 @@
|
|
|
2119
2119
|
"name": "AppleSaleRule",
|
|
2120
2120
|
"kind": "interface",
|
|
2121
2121
|
"jsdoc": "/** How the App Store sells one vertical's Wix item: the purchases catalog's `appProductId` for it, and\n * the only product type the purchase flow sells it as. */",
|
|
2122
|
-
"decl": "export interface AppleSaleRule {\n appProductId(entityId: string): string;\n productType: \"NON_CONSUMABLE\"
|
|
2123
|
-
},
|
|
2124
|
-
{
|
|
2125
|
-
"name": "BOOKINGS_APPLE_SALES_ENABLED",
|
|
2126
|
-
"kind": "const",
|
|
2127
|
-
"jsdoc": "",
|
|
2128
|
-
"decl": "export const BOOKINGS_APPLE_SALES_ENABLED = false;"
|
|
2129
|
-
},
|
|
2130
|
-
{
|
|
2131
|
-
"name": "EVENTS_APPLE_SALES_ENABLED",
|
|
2132
|
-
"kind": "const",
|
|
2133
|
-
"jsdoc": "",
|
|
2134
|
-
"decl": "export const EVENTS_APPLE_SALES_ENABLED = false;"
|
|
2122
|
+
"decl": "export interface AppleSaleRule {\n appProductId(entityId: string): string;\n productType: \"NON_CONSUMABLE\";\n}"
|
|
2135
2123
|
},
|
|
2136
2124
|
{
|
|
2137
2125
|
"name": "STORES_ITEM_PAYMENT_ENABLED",
|
|
@@ -2157,17 +2145,11 @@
|
|
|
2157
2145
|
"jsdoc": "/** One-time unlimited plans sell through the App Store. Proven live in Sandbox on 2026-10-19: a member's\n * online plan order is charged with one cashier item whose id is the plan id, so StartPayment maps it to the\n * plan's Apple product, and the order reads ACTIVE and PAID. Recurring and time-limited plans stay outside\n * this rule; their Billing lifecycle is unfinished. */",
|
|
2158
2146
|
"decl": "export const PRICING_PLAN_APPLE_SALES_ENABLED = true;"
|
|
2159
2147
|
},
|
|
2160
|
-
{
|
|
2161
|
-
"name": "AppleSaleOptions",
|
|
2162
|
-
"kind": "interface",
|
|
2163
|
-
"jsdoc": "/**\n * The one definition `himi store iap connect` writes mappings by and the mapping source reads them by,\n * keyed by catalog kind. wix-iap StartPayment maps the cashier order's single item id, and Online\n * Programs builds that order with the program id as the item id; programs are one-time unlocks.\n * Wix Stores and one-time unlimited Pricing Plans join only with their independent switches.\n */",
|
|
2164
|
-
"decl": "export interface AppleSaleOptions {\n storesAppleSalesEnabled?: boolean;\n storesItemPaymentEnabled?: boolean;\n pricingPlanAppleSalesEnabled?: boolean;\n bookingsAppleSalesEnabled?: boolean;\n eventsAppleSalesEnabled?: boolean;\n}"
|
|
2165
|
-
},
|
|
2166
2148
|
{
|
|
2167
2149
|
"name": "appleSaleRules",
|
|
2168
2150
|
"kind": "function",
|
|
2169
|
-
"jsdoc": "
|
|
2170
|
-
"decl": "export function appleSaleRules(options:
|
|
2151
|
+
"jsdoc": "/**\n * The one definition `himi store iap connect` writes mappings by and the mapping source reads them by,\n * keyed by catalog kind. wix-iap StartPayment maps the cashier order's single item id, and Online\n * Programs builds that order with the program id as the item id; programs are one-time unlocks.\n * Wix Stores and one-time unlimited Pricing Plans join only with their independent switches.\n */",
|
|
2152
|
+
"decl": "export function appleSaleRules(options: { storesAppleSalesEnabled?: boolean; storesItemPaymentEnabled?: boolean; pricingPlanAppleSalesEnabled?: boolean } = {}): Readonly<Record<string, AppleSaleRule>>;"
|
|
2171
2153
|
},
|
|
2172
2154
|
{
|
|
2173
2155
|
"name": "APPLE_SALE_RULES",
|
|
@@ -2175,12 +2157,6 @@
|
|
|
2175
2157
|
"jsdoc": "",
|
|
2176
2158
|
"decl": "export const APPLE_SALE_RULES = appleSaleRules();"
|
|
2177
2159
|
},
|
|
2178
|
-
{
|
|
2179
|
-
"name": "APPLE_PROVISIONING_RULES",
|
|
2180
|
-
"kind": "const",
|
|
2181
|
-
"jsdoc": "/** Catalog setup may precede activation; purchases still require the independent sales switches. */",
|
|
2182
|
-
"decl": "export const APPLE_PROVISIONING_RULES: Readonly<Record<string, AppleSaleRule>> = {\n ...APPLE_SALE_RULES, bookingsService: ATTENDANCE_SALE_RULE, eventsTicket: ATTENDANCE_SALE_RULE,\n};"
|
|
2183
|
-
},
|
|
2184
2160
|
{
|
|
2185
2161
|
"name": "HostCallExpectation",
|
|
2186
2162
|
"kind": "interface",
|
|
@@ -2221,7 +2197,7 @@
|
|
|
2221
2197
|
"name": "StartPaymentErrorCode",
|
|
2222
2198
|
"kind": "type",
|
|
2223
2199
|
"jsdoc": "",
|
|
2224
|
-
"decl": "export type StartPaymentErrorCode = \"NOT_PENDING\" | \"WRONG_PAYMENT_METHOD\" | \"NOT_ORDER_BUYER\" | \"UNSUPPORTED_ORDER\"\n | \"PRODUCT_NOT_AVAILABLE\" | \"ALREADY_OWNED\"
|
|
2200
|
+
"decl": "export type StartPaymentErrorCode = \"NOT_PENDING\" | \"WRONG_PAYMENT_METHOD\" | \"NOT_ORDER_BUYER\" | \"UNSUPPORTED_ORDER\"\n | \"PRODUCT_NOT_AVAILABLE\" | \"ALREADY_OWNED\";"
|
|
2225
2201
|
},
|
|
2226
2202
|
{
|
|
2227
2203
|
"name": "StartItemPaymentErrorCode",
|
|
@@ -2352,54 +2328,6 @@
|
|
|
2352
2328
|
"jsdoc": "/** Whether the host fences protected calls to the captured member (`identityBound`). Web does not. */",
|
|
2353
2329
|
"decl": "export function readIdentityBound(): boolean;"
|
|
2354
2330
|
},
|
|
2355
|
-
{
|
|
2356
|
-
"name": "AppleAttendanceRoute",
|
|
2357
|
-
"kind": "type",
|
|
2358
|
-
"jsdoc": "",
|
|
2359
|
-
"decl": "export type AppleAttendanceRoute = \"appleIap\" | \"wixPayments\" | \"decide\";"
|
|
2360
|
-
},
|
|
2361
|
-
{
|
|
2362
|
-
"name": "BookingAttendance",
|
|
2363
|
-
"kind": "interface",
|
|
2364
|
-
"jsdoc": "",
|
|
2365
|
-
"decl": "export interface BookingAttendance extends AttendancePrice {\n kind: \"bookingsService\";\n type?: string;\n capacity?: number;\n maxParticipantsPerBooking?: number;\n conferencing?: boolean;\n locations?: readonly string[];\n onlineBooking?: boolean;\n onlinePayment?: boolean;\n deposit?: boolean;\n}"
|
|
2366
|
-
},
|
|
2367
|
-
{
|
|
2368
|
-
"name": "TicketAttendance",
|
|
2369
|
-
"kind": "interface",
|
|
2370
|
-
"jsdoc": "",
|
|
2371
|
-
"decl": "export interface TicketAttendance extends AttendancePrice {\n kind: \"eventsTicket\";\n location?: string;\n registration?: string;\n eventStatus?: string;\n saleStatus?: string;\n}"
|
|
2372
|
-
},
|
|
2373
|
-
{
|
|
2374
|
-
"name": "classifyForApple",
|
|
2375
|
-
"kind": "function",
|
|
2376
|
-
"jsdoc": "/** Delivery metadata decides the route; online booking and online payment alone never do. */",
|
|
2377
|
-
"decl": "export function classifyForApple(item: BookingAttendance | TicketAttendance, currency: string): AppleAttendanceRoute;"
|
|
2378
|
-
},
|
|
2379
|
-
{
|
|
2380
|
-
"name": "attendanceCheckoutRoute",
|
|
2381
|
-
"kind": "function",
|
|
2382
|
-
"jsdoc": "/** Applies platform support and activation switches without sending uncertain iOS offers to web checkout. */",
|
|
2383
|
-
"decl": "export function attendanceCheckoutRoute(item: BookingAttendance | TicketAttendance, currency: string, platform: string): \"regular\" | \"appleIap\" | \"blocked\";"
|
|
2384
|
-
},
|
|
2385
|
-
{
|
|
2386
|
-
"name": "bookingAttendanceOf",
|
|
2387
|
-
"kind": "function",
|
|
2388
|
-
"jsdoc": "/** Preserves missing Wix service fields as unknown so absent metadata cannot authorize a payment route. */",
|
|
2389
|
-
"decl": "export function bookingAttendanceOf(raw: unknown): BookingAttendance;"
|
|
2390
|
-
},
|
|
2391
|
-
{
|
|
2392
|
-
"name": "ticketAttendanceOf",
|
|
2393
|
-
"kind": "function",
|
|
2394
|
-
"jsdoc": "/** Combines event delivery and ticket-definition pricing metadata for conservative route classification. */",
|
|
2395
|
-
"decl": "export function ticketAttendanceOf(event: unknown, definition: unknown): TicketAttendance;"
|
|
2396
|
-
},
|
|
2397
|
-
{
|
|
2398
|
-
"name": "availableTicketAttendanceOf",
|
|
2399
|
-
"kind": "function",
|
|
2400
|
-
"jsdoc": "/** Reads the buyer-visible checkout projection; hidden/off-sale inclusions and unknown pricing stay unresolved. */",
|
|
2401
|
-
"decl": "export function availableTicketAttendanceOf(event: unknown, ticket: unknown): TicketAttendance;"
|
|
2402
|
-
},
|
|
2403
2331
|
{
|
|
2404
2332
|
"name": "ProductType",
|
|
2405
2333
|
"kind": "type",
|
|
@@ -2517,7 +2445,7 @@
|
|
|
2517
2445
|
{
|
|
2518
2446
|
"name": "purchaseForVerification",
|
|
2519
2447
|
"kind": "function",
|
|
2520
|
-
"jsdoc": "/** Apple
|
|
2448
|
+
"jsdoc": "/** Apple non-consumables only. The token comes from authenticated backend context.\n * Leaves the transaction unfinished. Never falls back to legacy purchase on old binaries. */",
|
|
2521
2449
|
"decl": "export async function purchaseForVerification(input: { productId: string; appAccountToken: string }): Promise<VerificationPurchaseResult>;"
|
|
2522
2450
|
},
|
|
2523
2451
|
{
|
|
@@ -2579,7 +2507,7 @@
|
|
|
2579
2507
|
"name": "\"./iap-verticals/index.js\"",
|
|
2580
2508
|
"kind": "reexport",
|
|
2581
2509
|
"jsdoc": "",
|
|
2582
|
-
"decl": "export { onlineProgramOrders, pricingPlanOrders, storesProductOrders,
|
|
2510
|
+
"decl": "export { onlineProgramOrders, pricingPlanOrders, storesProductOrders, classifyCart } from \"./iap-verticals/index.js\";"
|
|
2583
2511
|
},
|
|
2584
2512
|
{
|
|
2585
2513
|
"name": "\"./order-refs.js\"",
|
|
@@ -2675,7 +2603,7 @@
|
|
|
2675
2603
|
"name": "IapOrderItem",
|
|
2676
2604
|
"kind": "interface",
|
|
2677
2605
|
"jsdoc": "/** One item a screen sells. `reference` is the same catalog reference its price came from. */",
|
|
2678
|
-
"decl": "export interface IapOrderItem {\n reference: CatalogReference;\n /**
|
|
2606
|
+
"decl": "export interface IapOrderItem {\n reference: CatalogReference;\n /** eCom catalog reference, required for a Wix Stores item. */\n catalogReference?: { appId: string; catalogItemId: string; options?: Record<string, unknown> };\n /** Only 1 is supported. */\n quantity?: number;\n}"
|
|
2679
2607
|
},
|
|
2680
2608
|
{
|
|
2681
2609
|
"name": "VerticalRef",
|
|
@@ -2693,7 +2621,7 @@
|
|
|
2693
2621
|
"name": "OrderAttempt",
|
|
2694
2622
|
"kind": "type",
|
|
2695
2623
|
"jsdoc": "/** `open`: a pending order the cashier can charge. `granted`: the vertical already gives the\n * member access, so nothing is sold. */",
|
|
2696
|
-
"decl": "export type OrderAttempt
|
|
2624
|
+
"decl": "export type OrderAttempt =\n | { status: \"open\"; cashierOrderId: string; verticalRef: VerticalRef }\n | { status: \"granted\" }\n | { status: \"refused\"; reason: OrderFailureCode }\n | { status: \"unavailable\" }\n | { status: \"sessionChanged\" };"
|
|
2697
2625
|
},
|
|
2698
2626
|
{
|
|
2699
2627
|
"name": "AccessRead",
|
|
@@ -2705,7 +2633,7 @@
|
|
|
2705
2633
|
"name": "IapOrderAdapter",
|
|
2706
2634
|
"kind": "interface",
|
|
2707
2635
|
"jsdoc": "/** The only per-vertical code. Every call goes through the session-bound bridge it is given. */",
|
|
2708
|
-
"decl": "export interface IapOrderAdapter {\n /** The catalog kind it sells (`onlineProgram`, `pricingPlan`, `storesProduct`, or a custom one). */\n readonly kind: string;\n
|
|
2636
|
+
"decl": "export interface IapOrderAdapter {\n /** The catalog kind it sells (`onlineProgram`, `pricingPlan`, `storesProduct`, or a custom one). */\n readonly kind: string;\n /** Structural check before any call: one item, quantity 1, a supported shape. */\n eligibility(item: IapOrderItem): IapEligibility;\n /** Opens, or reuses the vertical's own open, order for the signed-in member. */\n openOrder(item: IapOrderItem, bridge: SessionBoundBridge): Promise<OrderAttempt>;\n /** Re-reads an order opened earlier; `open` only while it can still be paid. */\n reopenOrder(order: { cashierOrderId: string; verticalRef: VerticalRef }, bridge: SessionBoundBridge): Promise<OrderAttempt>;\n /** The vertical's authoritative answer for the order's item and the signed-in member. */\n readAccess(verticalRef: VerticalRef, bridge: SessionBoundBridge): Promise<AccessRead>;\n /** The member's access to an item before any order exists (bought through Wix, say). Read-only:\n * never opens or prepares an order. An adapter without it shows Get access until a sale says otherwise. */\n currentAccess?(item: IapOrderItem, bridge: SessionBoundBridge): Promise<AccessRead>;\n /** When the platform enables StartItemPayment, an eligible item whose order wix-iap places itself\n * instead of `openOrder`. Null for an item outside that shape, which keeps `openOrder`. */\n itemPayment?(item: IapOrderItem): ItemPayment | null;\n}"
|
|
2709
2637
|
},
|
|
2710
2638
|
{
|
|
2711
2639
|
"name": "OrderPartitionKey",
|
|
@@ -2717,7 +2645,7 @@
|
|
|
2717
2645
|
"name": "OrderRefStage",
|
|
2718
2646
|
"kind": "type",
|
|
2719
2647
|
"jsdoc": "/** `startingItem`: a StartItemPayment was or is about to be sent and its answer is not stored, so\n * the service may have placed an order this device knows nothing of; nothing else is sold for the\n * item until it expires. `held`: Apple charged, and CompletePayment refused the proof without\n * recording it, so the transaction stays unfinished and is retried. `needsSupport`: recorded and\n * refused for good. */",
|
|
2720
|
-
"decl": "export type OrderRefStage = \"startingItem\" | \"
|
|
2648
|
+
"decl": "export type OrderRefStage = \"startingItem\" | \"ordered\" | \"charged\" | \"started\" | \"submitted\" | \"held\" | \"needsSupport\";"
|
|
2721
2649
|
},
|
|
2722
2650
|
{
|
|
2723
2651
|
"name": "OrderRef",
|
|
@@ -2819,7 +2747,7 @@
|
|
|
2819
2747
|
"name": "IapPurchaseCopy",
|
|
2820
2748
|
"kind": "interface",
|
|
2821
2749
|
"jsdoc": "/** Labels from the screen's copy pack; the shared layer only chooses between them. */",
|
|
2822
|
-
"decl": "export interface IapPurchaseCopy {\n buy: string;\n
|
|
2750
|
+
"decl": "export interface IapPurchaseCopy {\n buy: string;\n processing: string;\n awaitingApproval: string;\n unavailable: string;\n signInRequired: string;\n retry: string;\n priceChanged: string;\n support: string;\n}"
|
|
2823
2751
|
},
|
|
2824
2752
|
{
|
|
2825
2753
|
"name": "IapPurchaseFields",
|
|
@@ -2906,7 +2834,7 @@
|
|
|
2906
2834
|
"name": "StartOptions",
|
|
2907
2835
|
"kind": "interface",
|
|
2908
2836
|
"jsdoc": "",
|
|
2909
|
-
"decl": "export interface StartOptions {\n /** Groups related activities (e.g. \"order\", \"timer\", \"ride\"). Maps to the iOS\n * ActivityKit attributes type / the Android notification channel + tag. */\n activityType: string;\n /** The widget-safe SDUI tree rendered on the lock screen + Dynamic Island /\n * Live Update notification. */\n content: LiveActivityComponent;\n /** Optional one-line title (Android Live Update headline / accessibility). */\n title?: string;\n /** Mark the activity stale after this many ms (iOS staleDate). 0 ⇒ no hint. */\n staleAfterMs?: number;\n /** Optional per-Dynamic-Island-slot subtrees; omitted slots fall back to title/glyph. */\n regions?: LiveActivityRegions;\n /** Exact record route in the host app. Older binaries may open the app root. */\n deepLink?: string;\n /** Request an ActivityKit push token; the host must register it with its authenticated runtime. */\n pushUpdates?: boolean;\n /**\n * #2050 — the record this activity tracks. Present ⇒ the runtime records a scoped\n * mapping and the host registers an authenticated subscription, so the serve plane\n * can push ordered background frames. Absent ⇒ foreground-only, unchanged.\n *\n * On iOS pair it with `pushUpdates: true`: without the ActivityKit push token there\n * is nothing for the host to register, so the mapping would be recorded and never\n * addressed.\n */\n session?: LiveSessionRef;\n /** Android promotion is opt-in for a user-followed, bounded, time-sensitive\n * activity. The system may still keep it as an ordinary notification. */\n promoted?: boolean;\n
|
|
2837
|
+
"decl": "export interface StartOptions {\n /** Groups related activities (e.g. \"order\", \"timer\", \"ride\"). Maps to the iOS\n * ActivityKit attributes type / the Android notification channel + tag. */\n activityType: string;\n /** The widget-safe SDUI tree rendered on the lock screen + Dynamic Island /\n * Live Update notification. */\n content: LiveActivityComponent;\n /** Optional one-line title (Android Live Update headline / accessibility). */\n title?: string;\n /** Mark the activity stale after this many ms (iOS staleDate). 0 ⇒ no hint. */\n staleAfterMs?: number;\n /** Optional per-Dynamic-Island-slot subtrees; omitted slots fall back to title/glyph. */\n regions?: LiveActivityRegions;\n /** Exact record route in the host app. Older binaries may open the app root. */\n deepLink?: string;\n /** Request an ActivityKit push token; the host must register it with its authenticated runtime. */\n pushUpdates?: boolean;\n /**\n * #2050 — the record this activity tracks. Present ⇒ the runtime records a scoped\n * mapping and the host registers an authenticated subscription, so the serve plane\n * can push ordered background frames. Absent ⇒ foreground-only, unchanged.\n *\n * On iOS pair it with `pushUpdates: true`: without the ActivityKit push token there\n * is nothing for the host to register, so the mapping would be recorded and never\n * addressed.\n */\n session?: LiveSessionRef;\n /** Android promotion is opt-in for a user-followed, bounded, time-sensitive\n * activity. The system may still keep it as an ordinary notification. */\n promoted?: boolean;\n}"
|
|
2910
2838
|
},
|
|
2911
2839
|
{
|
|
2912
2840
|
"name": "UpdateOptions",
|
|
@@ -9035,25 +8963,7 @@
|
|
|
9035
8963
|
"name": "WixServiceFixedPayment",
|
|
9036
8964
|
"kind": "interface",
|
|
9037
8965
|
"jsdoc": "",
|
|
9038
|
-
"decl": "export interface WixServiceFixedPayment {\n price?: WixServiceMoney;\n
|
|
9039
|
-
},
|
|
9040
|
-
{
|
|
9041
|
-
"name": "WixServiceVariedPayment",
|
|
9042
|
-
"kind": "interface",
|
|
9043
|
-
"jsdoc": "",
|
|
9044
|
-
"decl": "export interface WixServiceVariedPayment {\n defaultPrice?: WixServiceMoney;\n deposit?: WixServiceMoney;\n minPrice?: WixServiceMoney;\n maxPrice?: WixServiceMoney;\n}"
|
|
9045
|
-
},
|
|
9046
|
-
{
|
|
9047
|
-
"name": "WixServiceCustomPayment",
|
|
9048
|
-
"kind": "interface",
|
|
9049
|
-
"jsdoc": "",
|
|
9050
|
-
"decl": "export interface WixServiceCustomPayment {\n description?: string;\n}"
|
|
9051
|
-
},
|
|
9052
|
-
{
|
|
9053
|
-
"name": "WixServicePaymentOptions",
|
|
9054
|
-
"kind": "interface",
|
|
9055
|
-
"jsdoc": "",
|
|
9056
|
-
"decl": "export interface WixServicePaymentOptions {\n online?: boolean;\n inPerson?: boolean;\n deposit?: boolean;\n pricingPlan?: boolean;\n}"
|
|
8966
|
+
"decl": "export interface WixServiceFixedPayment {\n price?: WixServiceMoney;\n}"
|
|
9057
8967
|
},
|
|
9058
8968
|
{
|
|
9059
8969
|
"name": "WixServiceRateLabel",
|
|
@@ -9065,199 +8975,25 @@
|
|
|
9065
8975
|
"name": "WixServicePayment",
|
|
9066
8976
|
"kind": "interface",
|
|
9067
8977
|
"jsdoc": "",
|
|
9068
|
-
"decl": "export interface WixServicePayment {\n
|
|
9069
|
-
},
|
|
9070
|
-
{
|
|
9071
|
-
"name": "WixServiceDuration",
|
|
9072
|
-
"kind": "interface",
|
|
9073
|
-
"jsdoc": "",
|
|
9074
|
-
"decl": "export interface WixServiceDuration {\n minutes?: number;\n}"
|
|
9075
|
-
},
|
|
9076
|
-
{
|
|
9077
|
-
"name": "WixServiceHourlyConfig",
|
|
9078
|
-
"kind": "interface",
|
|
9079
|
-
"jsdoc": "",
|
|
9080
|
-
"decl": "export interface WixServiceHourlyConfig {\n minDurationInMinutes?: number;\n maxDurationInMinutes?: number;\n}"
|
|
9081
|
-
},
|
|
9082
|
-
{
|
|
9083
|
-
"name": "WixServiceDailyConfig",
|
|
9084
|
-
"kind": "interface",
|
|
9085
|
-
"jsdoc": "",
|
|
9086
|
-
"decl": "export interface WixServiceDailyConfig {\n minDurationInDays?: number;\n maxDurationInDays?: number;\n}"
|
|
9087
|
-
},
|
|
9088
|
-
{
|
|
9089
|
-
"name": "WixServiceDurationRange",
|
|
9090
|
-
"kind": "interface",
|
|
9091
|
-
"jsdoc": "",
|
|
9092
|
-
"decl": "export interface WixServiceDurationRange {\n hourOptions?: WixServiceHourlyConfig;\n dayOptions?: WixServiceDailyConfig;\n unitType?: string;\n}"
|
|
8978
|
+
"decl": "export interface WixServicePayment {\n fixed?: WixServiceFixedPayment;\n rateLabel?: WixServiceRateLabel;\n price?: number;\n currency?: string;\n}"
|
|
9093
8979
|
},
|
|
9094
8980
|
{
|
|
9095
8981
|
"name": "WixServiceAvailabilityConstraints",
|
|
9096
8982
|
"kind": "interface",
|
|
9097
8983
|
"jsdoc": "",
|
|
9098
|
-
"decl": "export interface WixServiceAvailabilityConstraints {\n
|
|
8984
|
+
"decl": "export interface WixServiceAvailabilityConstraints {\n sessionDurations?: number[];\n}"
|
|
9099
8985
|
},
|
|
9100
8986
|
{
|
|
9101
8987
|
"name": "WixServiceSchedule",
|
|
9102
8988
|
"kind": "interface",
|
|
9103
8989
|
"jsdoc": "",
|
|
9104
|
-
"decl": "export interface WixServiceSchedule {\n
|
|
9105
|
-
},
|
|
9106
|
-
{
|
|
9107
|
-
"name": "WixServiceImage",
|
|
9108
|
-
"kind": "interface",
|
|
9109
|
-
"jsdoc": "",
|
|
9110
|
-
"decl": "export interface WixServiceImage {\n id?: string;\n url?: string;\n height?: number;\n width?: number;\n altText?: string;\n}"
|
|
9111
|
-
},
|
|
9112
|
-
{
|
|
9113
|
-
"name": "WixServiceMediaItem",
|
|
9114
|
-
"kind": "interface",
|
|
9115
|
-
"jsdoc": "",
|
|
9116
|
-
"decl": "export interface WixServiceMediaItem {\n image?: WixServiceImage;\n}"
|
|
9117
|
-
},
|
|
9118
|
-
{
|
|
9119
|
-
"name": "WixServiceMedia",
|
|
9120
|
-
"kind": "interface",
|
|
9121
|
-
"jsdoc": "",
|
|
9122
|
-
"decl": "export interface WixServiceMedia {\n items?: WixServiceMediaItem[];\n mainMedia?: WixServiceMediaItem;\n coverMedia?: WixServiceMediaItem;\n}"
|
|
9123
|
-
},
|
|
9124
|
-
{
|
|
9125
|
-
"name": "WixServiceStreetAddress",
|
|
9126
|
-
"kind": "interface",
|
|
9127
|
-
"jsdoc": "",
|
|
9128
|
-
"decl": "export interface WixServiceStreetAddress {\n number?: string;\n name?: string;\n apt?: string;\n}"
|
|
9129
|
-
},
|
|
9130
|
-
{
|
|
9131
|
-
"name": "WixServiceAddress",
|
|
9132
|
-
"kind": "interface",
|
|
9133
|
-
"jsdoc": "",
|
|
9134
|
-
"decl": "export interface WixServiceAddress {\n streetAddress?: WixServiceStreetAddress;\n addressLine?: string;\n country?: string;\n subdivision?: string;\n city?: string;\n postalCode?: string;\n formattedAddress?: string;\n}"
|
|
9135
|
-
},
|
|
9136
|
-
{
|
|
9137
|
-
"name": "WixServiceBusinessLocation",
|
|
9138
|
-
"kind": "interface",
|
|
9139
|
-
"jsdoc": "",
|
|
9140
|
-
"decl": "export interface WixServiceBusinessLocation {\n id?: string;\n name?: string;\n default?: boolean;\n address?: WixServiceAddress;\n}"
|
|
9141
|
-
},
|
|
9142
|
-
{
|
|
9143
|
-
"name": "WixServiceCustomLocation",
|
|
9144
|
-
"kind": "interface",
|
|
9145
|
-
"jsdoc": "",
|
|
9146
|
-
"decl": "export interface WixServiceCustomLocation {\n id?: string;\n address?: WixServiceAddress;\n}"
|
|
9147
|
-
},
|
|
9148
|
-
{
|
|
9149
|
-
"name": "WixServiceLocation",
|
|
9150
|
-
"kind": "interface",
|
|
9151
|
-
"jsdoc": "",
|
|
9152
|
-
"decl": "export interface WixServiceLocation {\n id?: string;\n type?: string;\n business?: WixServiceBusinessLocation;\n custom?: WixServiceCustomLocation;\n calculatedAddress?: WixServiceAddress;\n}"
|
|
9153
|
-
},
|
|
9154
|
-
{
|
|
9155
|
-
"name": "WixServiceOnlineBooking",
|
|
9156
|
-
"kind": "interface",
|
|
9157
|
-
"jsdoc": "",
|
|
9158
|
-
"decl": "export interface WixServiceOnlineBooking {\n enabled?: boolean;\n requireManualApproval?: boolean;\n allowMultipleRequests?: boolean;\n}"
|
|
9159
|
-
},
|
|
9160
|
-
{
|
|
9161
|
-
"name": "WixServiceConferencing",
|
|
9162
|
-
"kind": "interface",
|
|
9163
|
-
"jsdoc": "",
|
|
9164
|
-
"decl": "export interface WixServiceConferencing {\n enabled?: boolean;\n}"
|
|
9165
|
-
},
|
|
9166
|
-
{
|
|
9167
|
-
"name": "WixServicePolicyDescription",
|
|
9168
|
-
"kind": "interface",
|
|
9169
|
-
"jsdoc": "",
|
|
9170
|
-
"decl": "export interface WixServicePolicyDescription {\n enabled?: boolean;\n description?: string;\n}"
|
|
9171
|
-
},
|
|
9172
|
-
{
|
|
9173
|
-
"name": "WixServiceLimitEarlyBookingPolicy",
|
|
9174
|
-
"kind": "interface",
|
|
9175
|
-
"jsdoc": "",
|
|
9176
|
-
"decl": "export interface WixServiceLimitEarlyBookingPolicy {\n enabled?: boolean;\n earliestBookingInMinutes?: number;\n}"
|
|
9177
|
-
},
|
|
9178
|
-
{
|
|
9179
|
-
"name": "WixServiceLimitLateBookingPolicy",
|
|
9180
|
-
"kind": "interface",
|
|
9181
|
-
"jsdoc": "",
|
|
9182
|
-
"decl": "export interface WixServiceLimitLateBookingPolicy {\n enabled?: boolean;\n latestBookingInMinutes?: number;\n}"
|
|
9183
|
-
},
|
|
9184
|
-
{
|
|
9185
|
-
"name": "WixServiceBookAfterStartPolicy",
|
|
9186
|
-
"kind": "interface",
|
|
9187
|
-
"jsdoc": "",
|
|
9188
|
-
"decl": "export interface WixServiceBookAfterStartPolicy {\n enabled?: boolean;\n}"
|
|
9189
|
-
},
|
|
9190
|
-
{
|
|
9191
|
-
"name": "WixServiceCancellationPolicy",
|
|
9192
|
-
"kind": "interface",
|
|
9193
|
-
"jsdoc": "",
|
|
9194
|
-
"decl": "export interface WixServiceCancellationPolicy {\n enabled?: boolean;\n limitLatestCancellation?: boolean;\n latestCancellationInMinutes?: number;\n}"
|
|
9195
|
-
},
|
|
9196
|
-
{
|
|
9197
|
-
"name": "WixServiceReschedulePolicy",
|
|
9198
|
-
"kind": "interface",
|
|
9199
|
-
"jsdoc": "",
|
|
9200
|
-
"decl": "export interface WixServiceReschedulePolicy {\n enabled?: boolean;\n limitLatestReschedule?: boolean;\n latestRescheduleInMinutes?: number;\n}"
|
|
9201
|
-
},
|
|
9202
|
-
{
|
|
9203
|
-
"name": "WixServiceWaitlistPolicy",
|
|
9204
|
-
"kind": "interface",
|
|
9205
|
-
"jsdoc": "",
|
|
9206
|
-
"decl": "export interface WixServiceWaitlistPolicy {\n enabled?: boolean;\n capacity?: number;\n reservationTimeInMinutes?: number;\n}"
|
|
9207
|
-
},
|
|
9208
|
-
{
|
|
9209
|
-
"name": "WixServiceParticipantsPolicy",
|
|
9210
|
-
"kind": "interface",
|
|
9211
|
-
"jsdoc": "",
|
|
9212
|
-
"decl": "export interface WixServiceParticipantsPolicy {\n maxParticipantsPerBooking?: number;\n}"
|
|
9213
|
-
},
|
|
9214
|
-
{
|
|
9215
|
-
"name": "WixServiceCancellationWindow",
|
|
9216
|
-
"kind": "interface",
|
|
9217
|
-
"jsdoc": "",
|
|
9218
|
-
"decl": "export interface WixServiceCancellationWindow {\n amount?: WixServiceMoney;\n percentage?: string;\n startInMinutes?: number;\n}"
|
|
9219
|
-
},
|
|
9220
|
-
{
|
|
9221
|
-
"name": "WixServiceCancellationFeePolicy",
|
|
9222
|
-
"kind": "interface",
|
|
9223
|
-
"jsdoc": "",
|
|
9224
|
-
"decl": "export interface WixServiceCancellationFeePolicy {\n enabled?: boolean;\n cancellationWindows?: WixServiceCancellationWindow[];\n}"
|
|
9225
|
-
},
|
|
9226
|
-
{
|
|
9227
|
-
"name": "WixServiceBookingPolicy",
|
|
9228
|
-
"kind": "interface",
|
|
9229
|
-
"jsdoc": "",
|
|
9230
|
-
"decl": "export interface WixServiceBookingPolicy {\n id?: string;\n name?: string;\n customPolicyDescription?: WixServicePolicyDescription;\n limitEarlyBookingPolicy?: WixServiceLimitEarlyBookingPolicy;\n limitLateBookingPolicy?: WixServiceLimitLateBookingPolicy;\n bookAfterStartPolicy?: WixServiceBookAfterStartPolicy;\n cancellationPolicy?: WixServiceCancellationPolicy;\n reschedulePolicy?: WixServiceReschedulePolicy;\n waitlistPolicy?: WixServiceWaitlistPolicy;\n participantsPolicy?: WixServiceParticipantsPolicy;\n cancellationFeePolicy?: WixServiceCancellationFeePolicy;\n}"
|
|
9231
|
-
},
|
|
9232
|
-
{
|
|
9233
|
-
"name": "WixServiceStaffMember",
|
|
9234
|
-
"kind": "interface",
|
|
9235
|
-
"jsdoc": "",
|
|
9236
|
-
"decl": "export interface WixServiceStaffMember {\n staffMemberId?: string;\n name?: string;\n mainMedia?: WixServiceMediaItem;\n}"
|
|
9237
|
-
},
|
|
9238
|
-
{
|
|
9239
|
-
"name": "WixServiceStaffMemberDetails",
|
|
9240
|
-
"kind": "interface",
|
|
9241
|
-
"jsdoc": "",
|
|
9242
|
-
"decl": "export interface WixServiceStaffMemberDetails {\n staffMembers?: WixServiceStaffMember[];\n}"
|
|
9243
|
-
},
|
|
9244
|
-
{
|
|
9245
|
-
"name": "WixServicePageUrl",
|
|
9246
|
-
"kind": "interface",
|
|
9247
|
-
"jsdoc": "",
|
|
9248
|
-
"decl": "export interface WixServicePageUrl {\n relativePath?: string;\n url?: string;\n}"
|
|
9249
|
-
},
|
|
9250
|
-
{
|
|
9251
|
-
"name": "WixServiceUrls",
|
|
9252
|
-
"kind": "interface",
|
|
9253
|
-
"jsdoc": "",
|
|
9254
|
-
"decl": "export interface WixServiceUrls {\n servicePage?: WixServicePageUrl;\n bookingPage?: WixServicePageUrl;\n}"
|
|
8990
|
+
"decl": "export interface WixServiceSchedule {\n availabilityConstraints?: WixServiceAvailabilityConstraints;\n}"
|
|
9255
8991
|
},
|
|
9256
8992
|
{
|
|
9257
8993
|
"name": "WixService",
|
|
9258
8994
|
"kind": "interface",
|
|
9259
8995
|
"jsdoc": "",
|
|
9260
|
-
"decl": "export interface WixService {\n id: string;\n name?: string;\n description?: string;\n
|
|
8996
|
+
"decl": "export interface WixService {\n id: string;\n name?: string;\n description?: string;\n duration?: number;\n payment?: WixServicePayment;\n schedule?: WixServiceSchedule;\n price?: number;\n category?: string;\n}"
|
|
9261
8997
|
},
|
|
9262
8998
|
{
|
|
9263
8999
|
"name": "WixServicesSearchPaging",
|
|
@@ -9289,12 +9025,6 @@
|
|
|
9289
9025
|
"jsdoc": "",
|
|
9290
9026
|
"decl": "export interface WixGetServiceResponse {\n service: WixService;\n}"
|
|
9291
9027
|
},
|
|
9292
|
-
{
|
|
9293
|
-
"name": "WixGetServiceOptions",
|
|
9294
|
-
"kind": "interface",
|
|
9295
|
-
"jsdoc": "",
|
|
9296
|
-
"decl": "export interface WixGetServiceOptions {\n conditionalFields?: string[];\n}"
|
|
9297
|
-
},
|
|
9298
9028
|
{
|
|
9299
9029
|
"name": "WixServiceWrite",
|
|
9300
9030
|
"kind": "interface",
|
|
@@ -9433,13 +9163,13 @@
|
|
|
9433
9163
|
"name": "WixServicePayment",
|
|
9434
9164
|
"kind": "interface",
|
|
9435
9165
|
"jsdoc": "",
|
|
9436
|
-
"decl": "export interface WixServicePayment {\n
|
|
9166
|
+
"decl": "export interface WixServicePayment {\n fixed?: { price?: WixServiceMoney };\n rateLabel?: { amount?: string; currency?: string };\n /** @deprecated Legacy flat payment shape. */\n price?: number;\n /** @deprecated Legacy flat payment shape. */\n currency?: string;\n}"
|
|
9437
9167
|
},
|
|
9438
9168
|
{
|
|
9439
9169
|
"name": "WixService",
|
|
9440
9170
|
"kind": "interface",
|
|
9441
9171
|
"jsdoc": "",
|
|
9442
|
-
"decl": "export interface WixService {\n id: string;\n /** Optimistic-concurrency token — required by every v2 write (updateService reads it if omitted). */\n revision?: string;\n name?: string;\n description?: string;\n /**
|
|
9172
|
+
"decl": "export interface WixService {\n id: string;\n /** Optimistic-concurrency token — required by every v2 write (updateService reads it if omitted). */\n revision?: string;\n name?: string;\n description?: string;\n /** Session length in minutes. */\n duration?: number;\n /** Raw Bookings v2 response shape. */\n payment?: WixServicePayment;\n schedule?: { availabilityConstraints?: { sessionDurations?: number[] } };\n /** @deprecated Compatibility projection populated by `decodeService`. */\n price?: number;\n /** @deprecated Legacy v1 compatibility field. */\n category?: string;\n}"
|
|
9443
9173
|
},
|
|
9444
9174
|
{
|
|
9445
9175
|
"name": "decodeService",
|
|
@@ -9518,8 +9248,9 @@
|
|
|
9518
9248
|
{
|
|
9519
9249
|
"name": "getService",
|
|
9520
9250
|
"kind": "function",
|
|
9521
|
-
"jsdoc": "/** Fetch a single service by id — GET /bookings/v2/services/{id}. Visitor-readable\n * (public GA route, not the owner `_api/` gateway). The detail/edit-prefill source
|
|
9522
|
-
"decl": "export async function getService(serviceId: string
|
|
9251
|
+
"jsdoc": "/** Fetch a single service by id — GET /bookings/v2/services/{id}. Visitor-readable\n * (public GA route, not the owner `_api/` gateway). The detail/edit-prefill source. */",
|
|
9252
|
+
"decl": "export async function getService(serviceId: string): Promise<WixGetServiceResponse>;",
|
|
9253
|
+
"http": "GET /bookings/v2/services/{…}"
|
|
9523
9254
|
},
|
|
9524
9255
|
{
|
|
9525
9256
|
"name": "WixServiceWrite",
|
|
@@ -9635,54 +9366,6 @@
|
|
|
9635
9366
|
"decl": "export function cancelBookingAsMember(bookingId: string, revision: string, notify = true): Promise<WixUpdateBookingResponse>;",
|
|
9636
9367
|
"http": "POST /bookings/v2/bookings/{…}/cancel"
|
|
9637
9368
|
},
|
|
9638
|
-
{
|
|
9639
|
-
"name": "WixWaitlistContact",
|
|
9640
|
-
"kind": "interface",
|
|
9641
|
-
"jsdoc": "",
|
|
9642
|
-
"decl": "export interface WixWaitlistContact {\n email: string;\n firstName?: string;\n lastName?: string;\n}"
|
|
9643
|
-
},
|
|
9644
|
-
{
|
|
9645
|
-
"name": "WixWaitlistRegistration",
|
|
9646
|
-
"kind": "interface",
|
|
9647
|
-
"jsdoc": "",
|
|
9648
|
-
"decl": "export interface WixWaitlistRegistration {\n id?: string;\n bookingId?: string;\n waitingResource?: string;\n status?: string;\n availableActions?: { leave?: boolean; enroll?: boolean };\n}"
|
|
9649
|
-
},
|
|
9650
|
-
{
|
|
9651
|
-
"name": "WixWaitlistEntry",
|
|
9652
|
-
"kind": "interface",
|
|
9653
|
-
"jsdoc": "",
|
|
9654
|
-
"decl": "export interface WixWaitlistEntry {\n /** The waitlisted session id. */\n waitingResource?: string;\n registrations?: WixWaitlistRegistration[];\n}"
|
|
9655
|
-
},
|
|
9656
|
-
{
|
|
9657
|
-
"name": "WixRegisterToWaitlistResponse",
|
|
9658
|
-
"kind": "interface",
|
|
9659
|
-
"jsdoc": "",
|
|
9660
|
-
"decl": "export interface WixRegisterToWaitlistResponse {\n registrationId?: string;\n booking?: { id?: string; status?: string };\n}"
|
|
9661
|
-
},
|
|
9662
|
-
{
|
|
9663
|
-
"name": "registerToWaitlist",
|
|
9664
|
-
"kind": "function",
|
|
9665
|
-
"jsdoc": "/** Register the signed-in member to a full session's waitlist —\n * POST /bookings/v1/waitlist/register. `sessionId` is the availability slot's\n * `sessionId`. Wix answers with an error when the session has no waitlist or it is\n * full, so offer this only while the entry reports `waitingList.openSpots > 0`.\n * @scope member — requires a signed-in site member; `contact.email` is theirs. Only name and\n * email are sent, so a booking form with other required fields can refuse it. */",
|
|
9666
|
-
"decl": "export function registerToWaitlist(sessionId: string, contact: WixWaitlistContact): Promise<WixRegisterToWaitlistResponse>;",
|
|
9667
|
-
"http": "POST /bookings/v1/waitlist/register",
|
|
9668
|
-
"scope": "member"
|
|
9669
|
-
},
|
|
9670
|
-
{
|
|
9671
|
-
"name": "listWaitlists",
|
|
9672
|
-
"kind": "function",
|
|
9673
|
-
"jsdoc": "/** The waitlists of the given sessions — GET /bookings/v1/waitlist/list (public data).\n * Each registration carries its `bookingId`, which is how a member's own place is found.\n * @scope visitor — an anonymous visitor session is enough. */",
|
|
9674
|
-
"decl": "export function listWaitlists(sessionIds: string[]): Promise<{ list?: WixWaitlistEntry[] }>;",
|
|
9675
|
-
"http": "GET /bookings/v1/waitlist/list",
|
|
9676
|
-
"scope": "visitor"
|
|
9677
|
-
},
|
|
9678
|
-
{
|
|
9679
|
-
"name": "leaveWaitlist",
|
|
9680
|
-
"kind": "function",
|
|
9681
|
-
"jsdoc": "/** Leave a waitlist — POST /bookings/v1/waitlist/leave. Wix also cancels the pending\n * booking the registration created, and offers the place to the next registrant.\n * @scope member — requires the signed-in member who registered; `registrationId` comes from\n * `listWaitlists`. */",
|
|
9682
|
-
"decl": "export function leaveWaitlist(registrationId: string, sessionId: string): Promise<{ registrationId?: string; waitingResource?: string }>;",
|
|
9683
|
-
"http": "POST /bookings/v1/waitlist/leave",
|
|
9684
|
-
"scope": "member"
|
|
9685
|
-
},
|
|
9686
9369
|
{
|
|
9687
9370
|
"name": "isBookingPolicyViolation",
|
|
9688
9371
|
"kind": "function",
|
|
@@ -16158,30 +15841,6 @@
|
|
|
16158
15841
|
"decl": "export async function getCurrentCart(): Promise<WixCartDetail>;",
|
|
16159
15842
|
"http": "GET /ecom/v1/carts/current"
|
|
16160
15843
|
},
|
|
16161
|
-
{
|
|
16162
|
-
"name": "addCouponToCurrentCart",
|
|
16163
|
-
"kind": "function",
|
|
16164
|
-
"jsdoc": "/** Add a coupon to the visitor/member's current cart — POST\n * /ecom/v2/carts/current/add-coupon. Wix validates it against the current cart.\n * @scope visitor — uses the active shopper's cart; Wix rejects an invalid coupon. */",
|
|
16165
|
-
"decl": "export function addCouponToCurrentCart(code: string): Promise<{ cart?: WixCartDetail }>;",
|
|
16166
|
-
"http": "POST /ecom/v2/carts/current/add-coupon",
|
|
16167
|
-
"scope": "visitor"
|
|
16168
|
-
},
|
|
16169
|
-
{
|
|
16170
|
-
"name": "removeCouponFromCurrentCart",
|
|
16171
|
-
"kind": "function",
|
|
16172
|
-
"jsdoc": "/** Remove a coupon from the current cart — POST /ecom/v2/carts/current/remove-coupon.\n * @scope visitor — uses the active shopper's cart; a missing coupon ID is rejected. */",
|
|
16173
|
-
"decl": "export function removeCouponFromCurrentCart(couponId: string): Promise<{ cart?: WixCartDetail }>;",
|
|
16174
|
-
"http": "POST /ecom/v2/carts/current/remove-coupon",
|
|
16175
|
-
"scope": "visitor"
|
|
16176
|
-
},
|
|
16177
|
-
{
|
|
16178
|
-
"name": "calculateCurrentCart",
|
|
16179
|
-
"kind": "function",
|
|
16180
|
-
"jsdoc": "/** Recalculate the current cart after a coupon change.\n * @scope visitor — uses the active shopper's cart and returns its updated totals. */",
|
|
16181
|
-
"decl": "export function calculateCurrentCart(): Promise<{ cart?: WixCartDetail }>;",
|
|
16182
|
-
"http": "POST /ecom/v2/carts/current/calculate",
|
|
16183
|
-
"scope": "visitor"
|
|
16184
|
-
},
|
|
16185
15844
|
{
|
|
16186
15845
|
"name": "WixRemoveLineItemsResponse",
|
|
16187
15846
|
"kind": "interface",
|
|
@@ -17886,8 +17545,8 @@
|
|
|
17886
17545
|
{
|
|
17887
17546
|
"name": "WixEventFieldset",
|
|
17888
17547
|
"kind": "type",
|
|
17889
|
-
"jsdoc": "/** Events v3 response fieldsets (`RequestedFields`). A bare read returns the base fieldset;\n * each value adds fields: `DETAILS` → `shortDescription`, `mainImage`, `calendarUrls`;\n * `TEXTS` → the Ricos `description`; `REGISTRATION` → `registration`; `URLS` → `eventPageUrl
|
|
17890
|
-
"decl": "export type WixEventFieldset = \"DETAILS\" | \"TEXTS\" | \"REGISTRATION\" | \"URLS\"
|
|
17548
|
+
"jsdoc": "/** Events v3 response fieldsets (`RequestedFields`). A bare read returns the base fieldset;\n * each value adds fields: `DETAILS` → `shortDescription`, `mainImage`, `calendarUrls`;\n * `TEXTS` → the Ricos `description`; `REGISTRATION` → `registration`; `URLS` → `eventPageUrl`. */",
|
|
17549
|
+
"decl": "export type WixEventFieldset = \"DETAILS\" | \"TEXTS\" | \"REGISTRATION\" | \"URLS\";"
|
|
17891
17550
|
},
|
|
17892
17551
|
{
|
|
17893
17552
|
"name": "WixEventRichContent",
|
|
@@ -17994,7 +17653,7 @@
|
|
|
17994
17653
|
"name": "WixAvailableTicket",
|
|
17995
17654
|
"kind": "interface",
|
|
17996
17655
|
"jsdoc": "",
|
|
17997
|
-
"decl": "export interface WixAvailableTicket {\n id?: string;\n
|
|
17656
|
+
"decl": "export interface WixAvailableTicket {\n id?: string;\n name?: string;\n description?: string;\n price?: WixTicketPrice;\n free?: boolean;\n limitPerCheckout?: number;\n orderIndex?: number;\n saleStatus?: string;\n}"
|
|
17998
17657
|
},
|
|
17999
17658
|
{
|
|
18000
17659
|
"name": "WixQueryAvailableTicketsResponse",
|
|
@@ -18002,14 +17661,6 @@
|
|
|
18002
17661
|
"jsdoc": "",
|
|
18003
17662
|
"decl": "export interface WixQueryAvailableTicketsResponse {\n definitions?: WixAvailableTicket[];\n}"
|
|
18004
17663
|
},
|
|
18005
|
-
{
|
|
18006
|
-
"name": "getTicketDefinition",
|
|
18007
|
-
"kind": "function",
|
|
18008
|
-
"jsdoc": "/** Read management pricing/visibility for a required ticket-definition ID; absence is not a free offer.\n * Authorization errors propagate and must block checkout.\n * @scope owner — Wix documents app/user identity with Manage Ticket Definitions permission.\n * Member checkout uses queryAvailableTickets; LiftGear member reads returned 403 here.\n * @see https://dev.wix.com/docs/api-reference/business-solutions/events/event-management/ticket-definitions-v3/get-ticket-definition\n */",
|
|
18009
|
-
"decl": "export function getTicketDefinition(id: string): Promise<{ ticketDefinition?: { id?: string; eventId?: string; hidden?: boolean; saleStatus?: string; pricingMethod?: { pricingType?: string; fixedPrice?: { value?: string; currency?: string } } } }>;",
|
|
18010
|
-
"http": "GET /events/v3/ticket-definitions/{…}",
|
|
18011
|
-
"scope": "owner"
|
|
18012
|
-
},
|
|
18013
17664
|
{
|
|
18014
17665
|
"name": "WixTicketQuantity",
|
|
18015
17666
|
"kind": "interface",
|
|
@@ -25049,7 +24700,7 @@
|
|
|
25049
24700
|
"name": "StoreProduct",
|
|
25050
24701
|
"kind": "interface",
|
|
25051
24702
|
"jsdoc": "",
|
|
25052
|
-
"decl": "export interface StoreProduct {\n id?: string;\n productType?: string;\n name?: string;\n slug?: string;\n description?: string;\n plainDescription?: string;\n /** Both gallery layouts: V1 `mainMedia`/`items`, V3 `main`/`itemsInfo.items`. */\n media?: {\n mainMedia?: WixMediaSlot;\n main?: WixMediaSlot;\n items?: WixMediaSlot[];\n itemsInfo?: { items?: WixMediaSlot[] };\n };\n price?: { formatted?: { price?: string }; price?: number; currency?: string };\n priceData?: { formatted?: { price?: string }; price?: number; currency?: string };\n currency?: string;\n actualPriceRange?: {\n minValue?: { amount?: string; formattedAmount?: string; currency?: string };\n maxValue?: { amount?: string; formattedAmount?: string; currency?: string };\n };\n /**
|
|
24703
|
+
"decl": "export interface StoreProduct {\n id?: string;\n productType?: string;\n name?: string;\n slug?: string;\n description?: string;\n plainDescription?: string;\n /** Both gallery layouts: V1 `mainMedia`/`items`, V3 `main`/`itemsInfo.items`. */\n media?: {\n mainMedia?: WixMediaSlot;\n main?: WixMediaSlot;\n items?: WixMediaSlot[];\n itemsInfo?: { items?: WixMediaSlot[] };\n };\n price?: { formatted?: { price?: string }; price?: number; currency?: string };\n priceData?: { formatted?: { price?: string }; price?: number; currency?: string };\n currency?: string;\n actualPriceRange?: {\n minValue?: { amount?: string; formattedAmount?: string; currency?: string };\n maxValue?: { amount?: string; formattedAmount?: string; currency?: string };\n };\n /** Option groups, both spellings: V1 `productOptions`, V3 `options`. Declared\n * because the wire carries them on BOTH catalogs and this type denying them is\n * what let every template product screen drop the colour/size picker. Shapes\n * differ per catalog, so read them with `productOptions()` from ./options. */\n productOptions?: unknown[];\n options?: unknown[];\n /** V3 purchasable variants. The cart addresses a V3 option choice by `variantId`,\n * which `cartOptionsPayload()` resolves out of this. */\n variantsInfo?: { variants?: unknown[] };\n}"
|
|
25053
24704
|
},
|
|
25054
24705
|
{
|
|
25055
24706
|
"name": "StoreProductsResponse",
|
|
@@ -25088,12 +24739,6 @@
|
|
|
25088
24739
|
"jsdoc": "/**\n * EVERY image on the product, sized, in wire order — the gallery a detail screen\n * pages through, not just the one tile `productImage` returns.\n *\n * It reads both catalog layouts (V1 `media.items`, V3 `media.itemsInfo.items`) and\n * falls back to the primary image when the product carries no gallery, so a caller\n * always gets a non-empty list for a product that has any image at all. Empty slots\n * and duplicates are dropped.\n *\n * Exported because the gallery union was being re-derived by hand in ~10 template\n * workers, each free to miss a layout — which is exactly how a V3 store silently\n * lost its thumbnails. Defaults to the LIST budget like `productImage`; pass\n * `WIX_DETAIL_IMAGE` for a full-bleed pager, or `null` for the stored originals.\n */",
|
|
25089
24740
|
"decl": "export function productGallery(p: StoreProduct, size: WixImageSize | null = WIX_LIST_IMAGE): string[];"
|
|
25090
24741
|
},
|
|
25091
|
-
{
|
|
25092
|
-
"name": "normalizeFormattedPrice",
|
|
25093
|
-
"kind": "function",
|
|
25094
|
-
"jsdoc": "/** Formats Wix-provided price text consistently for display. A recognized symbol after an\n * English-style number moves before the amount; locale-specific decimal and grouping formats\n * remain unchanged. */",
|
|
25095
|
-
"decl": "export function normalizeFormattedPrice(formatted: string): string;"
|
|
25096
|
-
},
|
|
25097
24742
|
{
|
|
25098
24743
|
"name": "plainText",
|
|
25099
24744
|
"kind": "function",
|
|
@@ -25219,7 +24864,7 @@
|
|
|
25219
24864
|
"name": "WixCollectionsMetadata",
|
|
25220
24865
|
"kind": "interface",
|
|
25221
24866
|
"jsdoc": "",
|
|
25222
|
-
"decl": "export interface WixCollectionsMetadata {\n items?: number;\n
|
|
24867
|
+
"decl": "export interface WixCollectionsMetadata {\n items?: number;\n offset?: number;\n}"
|
|
25223
24868
|
},
|
|
25224
24869
|
{
|
|
25225
24870
|
"name": "WixQueryCollectionsRequest",
|
|
@@ -25338,7 +24983,7 @@
|
|
|
25338
24983
|
"name": "queryStoreCategories",
|
|
25339
24984
|
"kind": "function",
|
|
25340
24985
|
"jsdoc": "/** V3 visitor read: list store categories (the V3 replacement for `queryCollections`).\n * POST /categories/v1/categories/query — `treeReference.appNamespace` is REQUIRED. */",
|
|
25341
|
-
"decl": "export function queryStoreCategories(limit = 50
|
|
24986
|
+
"decl": "export function queryStoreCategories(limit = 50): Promise<StoreCategoriesResponse>;",
|
|
25342
24987
|
"http": "POST /categories/v1/categories/query"
|
|
25343
24988
|
},
|
|
25344
24989
|
{
|
package/guides/splash-screens.md
CHANGED
|
@@ -199,8 +199,8 @@ holding the readiness wait there would defeat the point of making this layer OTA
|
|
|
199
199
|
Two seams, and only one of them needs work:
|
|
200
200
|
|
|
201
201
|
- **OS splash → in-app surface.** The background is **already continuous** — both layers
|
|
202
|
-
resolve the same colour token —
|
|
203
|
-
|
|
202
|
+
resolve the same colour token — Android fades a declared gradient over this opaque base in 400 ms.
|
|
203
|
+
The *content* also eases in, so `HimalayaSplashView` / `HimalayaSplash` ease the
|
|
204
204
|
logo and caption in over `contentFadeInMs`.
|
|
205
205
|
- **In-app surface → real content.** Fades out over a fixed `exitFadeMs` (350 ms), via
|
|
206
206
|
`.splashExitAnimation(ready:)` on iOS and `HimalayaSplashHost` on Android.
|
|
@@ -340,3 +340,57 @@ Note that the `splash` accessibility id / `testTag` on some apps today belongs t
|
|
|
340
340
|
- [designing-himi-screens.md](designing-himi-screens.md) — composing the launch moment as design.
|
|
341
341
|
- [RFC 0012](../core/schema/RFC/0012-screen-rollout-and-authoring.md) — the binary/OTA seam.
|
|
342
342
|
- [RFC 0021](../core/schema/RFC/0021-design-kits.md) — why the background is a token.
|
|
343
|
+
|
|
344
|
+
### Branded-lite logo and handoff
|
|
345
|
+
|
|
346
|
+
Use the baked branded-lite app icon as the in-app logo:
|
|
347
|
+
|
|
348
|
+
```ts
|
|
349
|
+
splash: { enabled: true, logoAsset: "branded_lite_app_icon", logoWidth: 160 }
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
Hide the logo on both Android splash layers with an **explicit empty string**:
|
|
353
|
+
|
|
354
|
+
```ts
|
|
355
|
+
splash: { enabled: true, logoAsset: "" }
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
`logoWidth` is the square in-app logo size in logical points/dp (default 96 for absent or non-positive values). It does not resize Android's OS-controlled icon slot.
|
|
359
|
+
Omitting `logoAsset` retains existing behavior: no in-app logo; the OS uses the
|
|
360
|
+
launcher icon. An empty value also produces no in-app logo on iOS, macOS and web.
|
|
361
|
+
Android 12+ always reserves an icon slot: the build emits a transparent splash
|
|
362
|
+
icon when hidden, while preserving the actual launcher icon. This native change
|
|
363
|
+
requires a new binary; changing the served block alone only changes the in-app layer.
|
|
364
|
+
|
|
365
|
+
A declared `splash.backgroundColor` now overrides branded-lite's provisioning
|
|
366
|
+
primary color for the native launch background, in both light and dark appearance.
|
|
367
|
+
Without it the provisioning color remains the default. For a gradient, set this
|
|
368
|
+
token to its first/top color. Android and iOS/macOS paint that solid color first and fade the
|
|
369
|
+
gradient over it in 400 ms (immediate with reduce motion or Determinism).
|
|
370
|
+
The Android branded-lite shell mounts its first screen beneath the splash after
|
|
371
|
+
seeding and dismisses after that screen draws a descriptor (including a worker's
|
|
372
|
+
initial loading state) or an error. Explicit `readySignal: "first_content"`
|
|
373
|
+
retains the WebView page-loaded signal. `maxHoldMs` remains the hard deadline;
|
|
374
|
+
auth gates also count as first content. The iOS branded-lite shell likewise mounts its
|
|
375
|
+
content beneath the overlay and waits for loaded content or an error to appear,
|
|
376
|
+
within the same deadline. Once dismissed, the iOS splash stays dismissed even if
|
|
377
|
+
OTA timing settings change. Branded-lite Android image splashes use translucent dark system-bar
|
|
378
|
+
scrims with light icons for legibility; color and gradient splashes remain full-bleed.
|
|
379
|
+
Web retains its current transitions and readiness.
|
|
380
|
+
The standalone branded-lite macOS shell currently does not mount a boot splash
|
|
381
|
+
overlay; `splash.enabled` does not enable one there. The shared SwiftUI background
|
|
382
|
+
renderer is available on macOS, but this host handoff integration covers Android
|
|
383
|
+
and iOS. macOS shell integration requires a separate change.
|
|
384
|
+
|
|
385
|
+
Branded-lite builds expose the launcher artwork as the regular iOS image asset
|
|
386
|
+
`branded_lite_app_icon`, so the same logo configuration works on Android and iOS.
|
|
387
|
+
|
|
388
|
+
Native iOS hosts that use `HimalayaScreenHost` can opt into
|
|
389
|
+
`.onHimalayaScreenContent { ... }` to observe the appearance of loaded content or
|
|
390
|
+
an error. The callback ignores the host loader and does not replace a WebView's
|
|
391
|
+
page-loaded readiness signal. Existing hosts behave as before unless they opt in.
|
|
392
|
+
|
|
393
|
+
If cached splash configuration references missing or invalid colors after a binary
|
|
394
|
+
update, native splash stops fall back to the flat background, then `accentPrimary`,
|
|
395
|
+
then opaque white. Branded-lite also shows a shell loader if `maxHoldMs` expires
|
|
396
|
+
before seed prefill completes; the deadline remains unchanged.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1501.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": [
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
"artifactId": "himalaya-cli"
|
|
72
72
|
}
|
|
73
73
|
},
|
|
74
|
-
"falconPackageHash": "
|
|
74
|
+
"falconPackageHash": "b4581cb1b19e25892ccdd324431e2a5db2facd8ae8c8759bcc8c69cc"
|
|
75
75
|
}
|
|
@@ -89216,24 +89216,65 @@ const SCREENS = runtimeSetting({
|
|
|
89216
89216
|
"itemsPath": "$item.articleActions",
|
|
89217
89217
|
"items": [
|
|
89218
89218
|
{
|
|
89219
|
-
"id": "himi_business_chat.
|
|
89219
|
+
"id": "himi_business_chat.article_action.slot.$item.id",
|
|
89220
89220
|
"body": {
|
|
89221
89221
|
"package": "himalaya",
|
|
89222
|
-
"type": "
|
|
89222
|
+
"type": "VStack",
|
|
89223
89223
|
"props": {
|
|
89224
|
-
"
|
|
89225
|
-
|
|
89226
|
-
|
|
89227
|
-
|
|
89228
|
-
|
|
89229
|
-
|
|
89230
|
-
|
|
89231
|
-
|
|
89224
|
+
"children": [
|
|
89225
|
+
{
|
|
89226
|
+
"id": "himi_business_chat.article_action.web.$item.id",
|
|
89227
|
+
"body": {
|
|
89228
|
+
"package": "himalaya",
|
|
89229
|
+
"type": "Button",
|
|
89230
|
+
"props": {
|
|
89231
|
+
"title": "$item.label",
|
|
89232
|
+
"style": "secondary",
|
|
89233
|
+
"size": "sm",
|
|
89234
|
+
"fullWidth": false,
|
|
89235
|
+
"action": {
|
|
89236
|
+
"actionId": "capability.open_url.open",
|
|
89237
|
+
"params": {
|
|
89238
|
+
"url": "$item.url"
|
|
89239
|
+
}
|
|
89240
|
+
}
|
|
89241
|
+
}
|
|
89242
|
+
},
|
|
89243
|
+
"modifiers": {
|
|
89244
|
+
"hiddenPath": "$item.inApp"
|
|
89245
|
+
}
|
|
89246
|
+
},
|
|
89247
|
+
{
|
|
89248
|
+
"id": "himi_business_chat.article_action.app.$item.id",
|
|
89249
|
+
"body": {
|
|
89250
|
+
"package": "himalaya",
|
|
89251
|
+
"type": "Button",
|
|
89252
|
+
"props": {
|
|
89253
|
+
"title": "$item.label",
|
|
89254
|
+
"style": "secondary",
|
|
89255
|
+
"size": "sm",
|
|
89256
|
+
"fullWidth": false,
|
|
89257
|
+
"action": {
|
|
89258
|
+
"actionId": "himi.open",
|
|
89259
|
+
"params": {
|
|
89260
|
+
"screenId": "$item.screenId",
|
|
89261
|
+
"id": "$item.targetId"
|
|
89262
|
+
}
|
|
89263
|
+
}
|
|
89264
|
+
}
|
|
89265
|
+
},
|
|
89266
|
+
"modifiers": {
|
|
89267
|
+
"hiddenPath": "$item.web"
|
|
89268
|
+
}
|
|
89232
89269
|
}
|
|
89233
|
-
|
|
89270
|
+
],
|
|
89271
|
+
"spacing": 0,
|
|
89272
|
+
"alignment": "leading"
|
|
89234
89273
|
}
|
|
89235
89274
|
},
|
|
89236
|
-
"modifiers": {
|
|
89275
|
+
"modifiers": {
|
|
89276
|
+
"fillMaxWidth": true
|
|
89277
|
+
}
|
|
89237
89278
|
}
|
|
89238
89279
|
],
|
|
89239
89280
|
"spacing": 6
|
|
@@ -89607,24 +89648,65 @@ const SCREENS = runtimeSetting({
|
|
|
89607
89648
|
"itemsPath": "$item.articleActions",
|
|
89608
89649
|
"items": [
|
|
89609
89650
|
{
|
|
89610
|
-
"id": "himi_business_chat.
|
|
89651
|
+
"id": "himi_business_chat.card_action.slot.$item.id",
|
|
89611
89652
|
"body": {
|
|
89612
89653
|
"package": "himalaya",
|
|
89613
|
-
"type": "
|
|
89654
|
+
"type": "VStack",
|
|
89614
89655
|
"props": {
|
|
89615
|
-
"
|
|
89616
|
-
|
|
89617
|
-
|
|
89618
|
-
|
|
89619
|
-
|
|
89620
|
-
|
|
89621
|
-
|
|
89622
|
-
|
|
89656
|
+
"children": [
|
|
89657
|
+
{
|
|
89658
|
+
"id": "himi_business_chat.card_action.web.$item.id",
|
|
89659
|
+
"body": {
|
|
89660
|
+
"package": "himalaya",
|
|
89661
|
+
"type": "Button",
|
|
89662
|
+
"props": {
|
|
89663
|
+
"title": "$item.label",
|
|
89664
|
+
"style": "secondary",
|
|
89665
|
+
"size": "md",
|
|
89666
|
+
"fullWidth": true,
|
|
89667
|
+
"action": {
|
|
89668
|
+
"actionId": "capability.open_url.open",
|
|
89669
|
+
"params": {
|
|
89670
|
+
"url": "$item.url"
|
|
89671
|
+
}
|
|
89672
|
+
}
|
|
89673
|
+
}
|
|
89674
|
+
},
|
|
89675
|
+
"modifiers": {
|
|
89676
|
+
"hiddenPath": "$item.inApp"
|
|
89677
|
+
}
|
|
89678
|
+
},
|
|
89679
|
+
{
|
|
89680
|
+
"id": "himi_business_chat.card_action.app.$item.id",
|
|
89681
|
+
"body": {
|
|
89682
|
+
"package": "himalaya",
|
|
89683
|
+
"type": "Button",
|
|
89684
|
+
"props": {
|
|
89685
|
+
"title": "$item.label",
|
|
89686
|
+
"style": "secondary",
|
|
89687
|
+
"size": "md",
|
|
89688
|
+
"fullWidth": true,
|
|
89689
|
+
"action": {
|
|
89690
|
+
"actionId": "himi.open",
|
|
89691
|
+
"params": {
|
|
89692
|
+
"screenId": "$item.screenId",
|
|
89693
|
+
"id": "$item.targetId"
|
|
89694
|
+
}
|
|
89695
|
+
}
|
|
89696
|
+
}
|
|
89697
|
+
},
|
|
89698
|
+
"modifiers": {
|
|
89699
|
+
"hiddenPath": "$item.web"
|
|
89700
|
+
}
|
|
89623
89701
|
}
|
|
89624
|
-
|
|
89702
|
+
],
|
|
89703
|
+
"spacing": 0,
|
|
89704
|
+
"alignment": "leading"
|
|
89625
89705
|
}
|
|
89626
89706
|
},
|
|
89627
|
-
"modifiers": {
|
|
89707
|
+
"modifiers": {
|
|
89708
|
+
"fillMaxWidth": true
|
|
89709
|
+
}
|
|
89628
89710
|
}
|
|
89629
89711
|
],
|
|
89630
89712
|
"spacing": 6
|
|
@@ -89990,7 +90072,12 @@ const SCREENS = runtimeSetting({
|
|
|
89990
90072
|
"token": "surfaceSecondary"
|
|
89991
90073
|
},
|
|
89992
90074
|
"onAppear": {
|
|
89993
|
-
"actionId": "tier5.businessChat.init"
|
|
90075
|
+
"actionId": "tier5.businessChat.init",
|
|
90076
|
+
"params": {
|
|
90077
|
+
"siteUrl": "__HIMI_MEMBER_SITE_URL__",
|
|
90078
|
+
"productScreen": "himi_product",
|
|
90079
|
+
"serviceScreen": "himi_service"
|
|
90080
|
+
}
|
|
89994
90081
|
}
|
|
89995
90082
|
}
|
|
89996
90083
|
},
|
|
@@ -14,7 +14,26 @@ export type BusinessMessagePart = {
|
|
|
14
14
|
|
|
15
15
|
export type BusinessTextRun = { text: string; marks?: string[] };
|
|
16
16
|
export type BusinessSuggestion = { id: string; messageId: string; label: string; kind: "postback" | "visitor_option"; appId?: string; interactionId?: string; enabled: boolean; disabled: boolean };
|
|
17
|
-
|
|
17
|
+
/** `inApp` buttons open `screenId` with `targetId` inside the app; the rest open `url` in the browser. Only a
|
|
18
|
+
* `routable` one (a link in the text or a template button, never a file) may be opened in the app. */
|
|
19
|
+
export type BusinessArticleAction = { id: string; label: string; url: string; style: "primary" | "secondary"; screenId: string; targetId: string; inApp: boolean; web: boolean; routable: boolean };
|
|
20
|
+
/** The app's own screen for a site link, named by the slug in the link's path. */
|
|
21
|
+
export type BusinessInAppRoute = { kind: "product" | "service"; slug: string };
|
|
22
|
+
|
|
23
|
+
/** A store product page or a bookings service (its page or its booking calendar) on this app's own site has a screen
|
|
24
|
+
* in the app; another site's page (even one on the same host, as Wix sites share one), a pay link or a file has
|
|
25
|
+
* none, and with no site configured nothing is routed. The slug only names the item: the worker still has to find it. */
|
|
26
|
+
export function businessInAppRoute(url: string, siteUrl: string): BusinessInAppRoute | undefined {
|
|
27
|
+
const site = /^https:\/\/[^/?#\s]+(?:\/[^?#\s]*)?/i.exec(siteUrl.trim())?.[0].replace(/\/+$/, "") ?? "";
|
|
28
|
+
if (!site || !url.toLowerCase().startsWith(`${site.toLowerCase()}/`)) return undefined;
|
|
29
|
+
const match = /^\/(product-page|service-page|booking-calendar)\/([^/?#]+)\/?(?:[?#].*)?$/i.exec(url.slice(site.length));
|
|
30
|
+
if (!match) return undefined;
|
|
31
|
+
let slug: string;
|
|
32
|
+
// A malformed escape ("50%-off") names nothing the app can look up: the link stays a web link.
|
|
33
|
+
try { slug = decodeURIComponent(match[2]!); } catch { return undefined; }
|
|
34
|
+
return slug ? { kind: match[1]!.toLowerCase() === "product-page" ? "product" : "service", slug } : undefined;
|
|
35
|
+
}
|
|
36
|
+
const webAction = { screenId: "", targetId: "", inApp: false, web: true, routable: true };
|
|
18
37
|
export type BusinessVisitorOptions = { answerTo: string; labels: string[] };
|
|
19
38
|
|
|
20
39
|
export type BusinessMessage = {
|
|
@@ -274,7 +293,7 @@ function articleActions(message: RecordValue, messageId: string): BusinessArticl
|
|
|
274
293
|
if (!label || !rawUrl || button.payload != null) return [];
|
|
275
294
|
// No `URL` global in a worker: accept only a plain https URL whose authority carries no credentials.
|
|
276
295
|
if (!isSafeLink(rawUrl)) return [];
|
|
277
|
-
return [{ id: `${messageId}:article-${index}`, label, url: rawUrl, style: "secondary" as const }];
|
|
296
|
+
return [{ id: `${messageId}:article-${index}`, label, url: rawUrl, style: "secondary" as const, ...webAction }];
|
|
278
297
|
});
|
|
279
298
|
}
|
|
280
299
|
|
|
@@ -471,7 +490,8 @@ export function presentBusinessMessages<T extends Pick<BusinessMessage, "id" | "
|
|
|
471
490
|
const productPage = cardLike && !isAiGenerated ? [...extras.links, ...articleActions(message, row.id)].map((link) => /^https:\/\/[^/?#]+(?:\/[^/?#]+)*?\/product-page\/([^/?#]+)/i.exec(link.url)?.[1]).find(Boolean) : undefined;
|
|
472
491
|
// A file, recording or video has no inline player here: it gets a button that opens it.
|
|
473
492
|
const attachmentLinks = row.parts.filter((part) => (part.kind === "file" || part.kind === "audio" || part.kind === "video") && !!part.url)
|
|
474
|
-
|
|
493
|
+
// A file, recording or video always opens as itself in the browser, wherever its URL lives.
|
|
494
|
+
.map((part, at) => ({ id: `${row.id}:attachment-${at}`, label: (part.fileName || part.caption || `Open ${part.kind}`).slice(0, 40), url: part.url as string, style: "secondary" as const, ...webAction, routable: false }));
|
|
475
495
|
// The card look (a framed box with a centred title) is for what an owner tool sends: a product, coupon, scheduling
|
|
476
496
|
// or pay link, an event, or a file. A coupon's title is its code, which the coupon block already shows.
|
|
477
497
|
// An AI answer is text with link pills, as on the site's Smart Chat, even when it is shaped like a card.
|
|
@@ -481,7 +501,7 @@ export function presentBusinessMessages<T extends Pick<BusinessMessage, "id" | "
|
|
|
481
501
|
// Inbox adds to the text is left out of it.
|
|
482
502
|
const cardLines = cardTitle ? lines.slice(1) : titled.split("\n");
|
|
483
503
|
const cardDetail = (productPage ? cardLines.filter((line) => !/^\s*\d+\s+variants?\b|\|\s*(?:in|out of)\s+stock\s*$/i.test(line)) : cardLines).join("\n");
|
|
484
|
-
const articles = [...articleActions(message, row.id), ...attachmentLinks, ...extras.links.map((link, at) => ({ id: `${row.id}:link-${at}`, label: link.label, url: link.url, style: /\b(view|buy|shop|book|pay|order|checkout|reserve|schedule)\b/i.test(link.label) ? "primary" as const : "secondary" as const }))]
|
|
504
|
+
const articles = [...articleActions(message, row.id), ...attachmentLinks, ...extras.links.map((link, at) => ({ id: `${row.id}:link-${at}`, label: link.label, url: link.url, style: /\b(view|buy|shop|book|pay|order|checkout|reserve|schedule)\b/i.test(link.label) ? "primary" as const : "secondary" as const, ...webAction }))]
|
|
485
505
|
.filter((action, at, all) => all.findIndex((other) => other.url === action.url) === at);
|
|
486
506
|
|
|
487
507
|
return {
|
|
@@ -4,16 +4,17 @@ import type { ChatIdentity } from '../_shared/business-chat-transport.js';
|
|
|
4
4
|
import { type MessageRow } from '../_shared/business-chat-message-model.js';
|
|
5
5
|
import { businessChatSendRejected, messageTimeLabel, sendAnchor, pendingIntentWasObserved, chronologicalMessages, newBusinessChatIntent, type BusinessChatIntent } from '../_shared/business-chat-model.js';
|
|
6
6
|
import { subscribeRealtime, unsubscribeRealtime, getRealtimeStatus, type RealtimeStatus, type RealtimeEventEnvelope } from '@himalaya/wix-chat';
|
|
7
|
-
import { dispatchBusinessSuggestion, businessRealtimeStatusLabel, businessVisitorOptionSuggestions, presentBusinessMessages, selectExistingBusinessRoom, shouldRefreshBusinessHistory, type BusinessSuggestion, type BusinessVisitorOptions, businessVisitorOptionRequest, businessVisitorOptionsFromAiMessages, newBusinessSelectionId} from '../_shared/business-chat-presenter.js';
|
|
7
|
+
import { businessInAppRoute, type BusinessArticleAction, dispatchBusinessSuggestion, businessRealtimeStatusLabel, businessVisitorOptionSuggestions, presentBusinessMessages, selectExistingBusinessRoom, shouldRefreshBusinessHistory, type BusinessSuggestion, type BusinessVisitorOptions, businessVisitorOptionRequest, businessVisitorOptionsFromAiMessages, newBusinessSelectionId} from '../_shared/business-chat-presenter.js';
|
|
8
8
|
import { listMessages, streamMessages } from '@himalaya/wix-ai-site-chat';
|
|
9
9
|
import { hostSiteFromInput } from '../_shared/branded-lite-hosted.js';
|
|
10
10
|
import { productImage, searchStoreProducts } from '../_shared/himi-store.js';
|
|
11
|
+
import { queryServices } from '@himalaya/wix-bookings';
|
|
11
12
|
|
|
12
13
|
type PendingIntent = BusinessChatIntent;
|
|
13
14
|
// Only what the screen reads. This state crosses into the worker on every keystroke, so a row carries no raw
|
|
14
15
|
// parts, plain text or text runs: they would be re-sent each time for nothing.
|
|
15
16
|
type BusinessMessageRow = Pick<MessageRow,'id'|'sender'|'when'|'createdDate'|'mine'> & {
|
|
16
|
-
senderAvatar:string; senderName:string; senderInitials:string; senderBadge:string; imageUrl:string; imageDescription:string; noImage:boolean; bodyText:string; bodyMarkdown:string; suggestions:BusinessSuggestion[]; articleActions:
|
|
17
|
+
senderAvatar:string; senderName:string; senderInitials:string; senderBadge:string; imageUrl:string; imageDescription:string; noImage:boolean; bodyText:string; bodyMarkdown:string; suggestions:BusinessSuggestion[]; articleActions:BusinessArticleAction[]; couponCode:string; noCoupon:boolean; notMine:boolean;
|
|
17
18
|
isCard:boolean; notCard:boolean; noSuggestions:boolean; noActions:boolean; cardTitle:string; cardDetail:string; noCardText:boolean;
|
|
18
19
|
dayLabel:string; dayHidden:boolean; startsDay:boolean; scrollAnchor:string;
|
|
19
20
|
/** Only the member's own row that the server has not returned yet. */
|
|
@@ -82,6 +83,7 @@ function safeLoadFailure(error:unknown):string{
|
|
|
82
83
|
return `${loadStage}:${/^(TypeError|SyntaxError|ProtocolError|Unsupported|Error)$/.test(name)?name:'OtherError'}${safeCode}`;
|
|
83
84
|
}
|
|
84
85
|
function value(arg:unknown):string{if(typeof arg==='string')return arg;const a=arg as Record<string,unknown>|null;return typeof a?.value==='string'?a.value:'';}
|
|
86
|
+
function hasParam(arg:unknown,key:string):boolean{const a=arg as Record<string,unknown>|null;const p=a?.params as Record<string,unknown>|undefined;return typeof a?.[key]==='string'||typeof p?.[key]==='string';}
|
|
85
87
|
function param(arg:unknown,key:string):string{const a=arg as Record<string,unknown>|null;const p=a?.params as Record<string,unknown>|undefined;return typeof a?.[key]==='string'?a[key] as string:typeof p?.[key]==='string'?p[key] as string:'';}
|
|
86
88
|
// A private attachment's download URL costs a round trip and stays valid for minutes, so a refresh reuses it.
|
|
87
89
|
const attachmentUrls=new Map<string,{url:string;at:number}>();
|
|
@@ -94,21 +96,26 @@ async function privateAttachmentUrl(part:{mediaId?:string;mediaProvider?:string;
|
|
|
94
96
|
if(url)attachmentUrls.set(key,{url,at:Date.now()});
|
|
95
97
|
return url;
|
|
96
98
|
}
|
|
97
|
-
// A product card's picture comes from the store: the message carries only the product page link. A found
|
|
98
|
-
// reused for ten minutes and a miss for two, so a refresh never repeats the lookup.
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
// A product card's picture comes from the store: the message carries only the product page link. A found product is
|
|
100
|
+
// reused for ten minutes and a miss for two, so a refresh never repeats the lookup. Its id opens it in the app.
|
|
101
|
+
/** `id` is the product the link names (same slug) and opens it in the app; the picture may also come from a product of
|
|
102
|
+
* the same name, which never stands in for the link's own product. */
|
|
103
|
+
type FoundProduct={url:string;id:string};
|
|
104
|
+
const productImages=new Map<string,FoundProduct&{at:number}>();
|
|
105
|
+
const productImageLookups=new Map<string,Promise<FoundProduct>>();
|
|
101
106
|
const PRODUCT_IMAGE_TTL_MS=10*60*1000;
|
|
102
107
|
const PRODUCT_IMAGE_MISS_TTL_MS=2*60*1000;
|
|
103
|
-
function productImageFor(slug:string,name:string):Promise<
|
|
108
|
+
function productImageFor(slug:string,name:string):Promise<FoundProduct>{
|
|
104
109
|
// Keyed by both: the search runs on the name, so a miss for one name must not hide a hit for another.
|
|
105
110
|
const key=JSON.stringify([slug,name]);
|
|
106
111
|
const hit=productImages.get(key);
|
|
107
|
-
if(hit&&Date.now()-hit.at<(hit.
|
|
112
|
+
if(hit&&Date.now()-hit.at<(hit.id?PRODUCT_IMAGE_TTL_MS:PRODUCT_IMAGE_MISS_TTL_MS))return Promise.resolve({url:hit.url,id:hit.id});
|
|
108
113
|
const running=productImageLookups.get(key);
|
|
109
114
|
if(running)return running;
|
|
110
|
-
|
|
111
|
-
|
|
115
|
+
// A reset (sign-out, another member or business) bumps `epoch`: a lookup it overtook must not fill the new cache.
|
|
116
|
+
const startEpoch=epoch;
|
|
117
|
+
const lookup:Promise<FoundProduct>=(async()=>{
|
|
118
|
+
let url='';let id='';
|
|
112
119
|
try{
|
|
113
120
|
// The name first; then the link's own words, for a product renamed since the message was written. The slug is the
|
|
114
121
|
// identity, so a same-named product with another slug is used only if neither search finds the slug.
|
|
@@ -123,13 +130,48 @@ function productImageFor(slug:string,name:string):Promise<string>{
|
|
|
123
130
|
}
|
|
124
131
|
const match=bySlug??sameName;
|
|
125
132
|
if(match)url=productImage(match);
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
133
|
+
if(bySlug)id=typeof bySlug.id==='string'?bySlug.id:'';
|
|
134
|
+
}catch{url='';id='';}
|
|
135
|
+
if(startEpoch===epoch)productImages.set(key,{url,id,at:Date.now()});
|
|
136
|
+
return {url,id};
|
|
137
|
+
})().finally(()=>{if(productImageLookups.get(key)===lookup)productImageLookups.delete(key);});
|
|
130
138
|
productImageLookups.set(key,lookup);
|
|
131
139
|
return lookup;
|
|
132
140
|
}
|
|
141
|
+
// A bookings service named by a link's slug, cached like a product (a miss for less time). The first history load
|
|
142
|
+
// routes every row at once, so links to the same service share one lookup while it is running.
|
|
143
|
+
const serviceIds=new Map<string,{id:string;at:number}>();
|
|
144
|
+
const serviceIdLookups=new Map<string,Promise<string>>();
|
|
145
|
+
function serviceIdFor(slug:string):Promise<string>{
|
|
146
|
+
const hit=serviceIds.get(slug);
|
|
147
|
+
if(hit&&Date.now()-hit.at<(hit.id?PRODUCT_IMAGE_TTL_MS:PRODUCT_IMAGE_MISS_TTL_MS))return Promise.resolve(hit.id);
|
|
148
|
+
const running=serviceIdLookups.get(slug);
|
|
149
|
+
if(running)return running;
|
|
150
|
+
const startEpoch=epoch;
|
|
151
|
+
const lookup:Promise<string>=(async()=>{
|
|
152
|
+
let id='';
|
|
153
|
+
try{
|
|
154
|
+
const found=(await queryServices({query:{filter:{'mainSlug.name':{$eq:slug}},paging:{limit:1}}})).services??[];
|
|
155
|
+
id=typeof found[0]?.id==='string'?found[0].id:'';
|
|
156
|
+
}catch{id='';}
|
|
157
|
+
if(startEpoch===epoch)serviceIds.set(slug,{id,at:Date.now()});
|
|
158
|
+
return id;
|
|
159
|
+
})().finally(()=>{if(serviceIdLookups.get(slug)===lookup)serviceIdLookups.delete(slug);});
|
|
160
|
+
serviceIdLookups.set(slug,lookup);
|
|
161
|
+
return lookup;
|
|
162
|
+
}
|
|
163
|
+
/** A button whose link the app has a screen for opens that screen; a link it cannot place stays a web link. */
|
|
164
|
+
// This app's own site and the screens it has for products and services, as the screen passes them to `init`: only
|
|
165
|
+
// its own site's pages, and only to a screen the app registers, are opened in the app.
|
|
166
|
+
let ownSiteUrl='';
|
|
167
|
+
const ownScreens={product:'',service:''};
|
|
168
|
+
async function routeAction(action:BusinessArticleAction,productName:string):Promise<BusinessArticleAction>{
|
|
169
|
+
const route=action.routable?businessInAppRoute(action.url,ownSiteUrl):undefined;
|
|
170
|
+
const screenId=route?ownScreens[route.kind]:'';
|
|
171
|
+
if(!route||!screenId)return action;
|
|
172
|
+
const id=route.kind==='product'?(await productImageFor(route.slug,productName)).id:await serviceIdFor(route.slug);
|
|
173
|
+
return id?{...action,screenId,targetId:id,inApp:true,web:false}:action;
|
|
174
|
+
}
|
|
133
175
|
function slimRow(row:Record<string,unknown>):BusinessMessageRow{
|
|
134
176
|
const pick=(...keys:string[])=>Object.fromEntries(keys.map(key=>[key,row[key]]));
|
|
135
177
|
return pick('id','sender','when','createdDate','mine','senderAvatar','senderName','senderInitials','senderBadge','imageUrl','imageDescription','noImage','bodyText','bodyMarkdown','suggestions','articleActions','couponCode','noCoupon','notMine','isCard','notCard','noSuggestions','noActions','cardTitle','cardDetail','noCardText','dayLabel','dayHidden','startsDay','scrollAnchor') as unknown as BusinessMessageRow;
|
|
@@ -149,9 +191,12 @@ async function presentMessages(existing:MessageRow[],raw:unknown[],memberId?:str
|
|
|
149
191
|
const presented=presentBusinessMessages(prepared as unknown as Parameters<typeof presentBusinessMessages>[0],raw,businessParticipantId) as unknown as Record<string,unknown>[];
|
|
150
192
|
await Promise.all(presented.map(async row=>{
|
|
151
193
|
const slug=typeof row.productSlug==='string'?row.productSlug:'';
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
194
|
+
const name=String(row.productName||'');
|
|
195
|
+
if(slug&&!row.imageUrl){
|
|
196
|
+
const {url}=await productImageFor(slug,name);
|
|
197
|
+
if(url)Object.assign(row,{imageUrl:url,noImage:false,imageDescription:name||'Product image'});
|
|
198
|
+
}
|
|
199
|
+
row.articleActions=await Promise.all((row.articleActions as BusinessArticleAction[]).map(action=>routeAction(action,name)));
|
|
155
200
|
}));
|
|
156
201
|
return presented.map(slimRow);
|
|
157
202
|
}
|
|
@@ -178,7 +223,7 @@ function safeError(error:unknown,operation:'load'|'send'|'init'):string{
|
|
|
178
223
|
}
|
|
179
224
|
async function endSubscription():Promise<void>{const id=subscriptionId;subscriptionId='';if(id)try{await unsubscribeRealtime({subscriptionId:id});}catch{}}
|
|
180
225
|
function clearPrivate(s:State,phase:'guest'|'error'='guest'):State{
|
|
181
|
-
attachmentUrls.clear();productImages.clear();currentIdentity=null;businessParticipantId='';epoch++;void endSubscription();
|
|
226
|
+
attachmentUrls.clear();productImages.clear();productImageLookups.clear();serviceIds.clear();serviceIdLookups.clear();currentIdentity=null;businessParticipantId='';epoch++;void endSubscription();
|
|
182
227
|
return shape({...initial,phase,error:phase==='guest'?'Sign in to send a message.':s.error});
|
|
183
228
|
}
|
|
184
229
|
let refreshTail:Promise<unknown>=Promise.resolve();
|
|
@@ -259,8 +304,11 @@ async function deliver(pending:BusinessChatIntent,draft:string):Promise<void>{
|
|
|
259
304
|
const svc=defineService<State,Record<string,(s:State,a?:unknown)=>State|undefined|Promise<State|undefined>>>('businessChat',{
|
|
260
305
|
state:shape(initial),notHydrated:Object.keys(initial) as (keyof State)[],
|
|
261
306
|
actions:{
|
|
262
|
-
init:async
|
|
307
|
+
init:async(s,a)=>{
|
|
263
308
|
if(initFlight)return s;initFlight=true;eventDuringInit=false;statusDuringInit=null;
|
|
309
|
+
// A retry passes no site: the one the screen gave first stays. A site the screen passes, even an empty one (a
|
|
310
|
+
// business with no site), replaces it, so an earlier business's links are not routed to this one's screens.
|
|
311
|
+
if(hasParam(a,'siteUrl')){ownSiteUrl=param(a,'siteUrl');ownScreens.product=param(a,'productScreen');ownScreens.service=param(a,'serviceScreen');}
|
|
264
312
|
const oldPrincipal=s.principal;
|
|
265
313
|
const initRevision=draftRevision;
|
|
266
314
|
// Text typed at any point of the load, subscribe step included, outlives the snapshot this started from. So does the
|
|
@@ -418,7 +466,7 @@ const svc=defineService<State,Record<string,(s:State,a?:unknown)=>State|undefine
|
|
|
418
466
|
}
|
|
419
467
|
catch(error){if(startEpoch!==epoch)return undefined;const lost=/member_sign_in_required|MemberAccessChanged|\b401\b|\b403\b/i.test(String(error));return lost?clearPrivate(next,'guest'):shape({...withLiveDraft(next),error:safeError(error,'load'),loadFailure:typeof (error as {businessLoadFailure?:unknown})?.businessLoadFailure==='string'?(error as {businessLoadFailure:string}).businessLoadFailure:safeLoadFailure(error)});}
|
|
420
468
|
},
|
|
421
|
-
dispose:async s=>{epoch++;attachmentUrls.clear();productImages.clear();currentIdentity=null;businessParticipantId='';await endSubscription();return shape({...initial,phase:'guest'});},
|
|
469
|
+
dispose:async s=>{epoch++;attachmentUrls.clear();productImages.clear();productImageLookups.clear();serviceIds.clear();serviceIdLookups.clear();currentIdentity=null;businessParticipantId='';await endSubscription();return shape({...initial,phase:'guest'});},
|
|
422
470
|
}
|
|
423
471
|
});
|
|
424
472
|
readServiceState=()=>svc.getState();
|