@wix/himalaya-cli 0.1523.0 → 0.1524.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 +1 -0
- package/package.json +2 -2
- package/templates/beauty-salon/tier5-src/himi-branded-lite-cart/index.ts +4 -63
- package/templates/branded-lite/tier5-src/himi-branded-lite-cart/index.ts +4 -63
- package/templates/gym-fitness/tier5-src/himi-branded-lite-cart/index.ts +4 -63
- package/templates/portfolio-creative/tier5-src/himi-branded-lite-cart/index.ts +4 -63
- package/templates/retail-store/tier5-src/himi-branded-lite-cart/index.ts +4 -63
package/dist/cli.mjs
CHANGED
|
@@ -22307,6 +22307,7 @@ function resolveIdiom(tokens2, ctx = {}) {
|
|
|
22307
22307
|
var IDIOM_CONTEXTS, UNSAFE_KEYS;
|
|
22308
22308
|
var init_idiom = __esm({
|
|
22309
22309
|
"../../core/ts/src/idiom.ts"() {
|
|
22310
|
+
"use strict";
|
|
22310
22311
|
IDIOM_CONTEXTS = {
|
|
22311
22312
|
ios: { native: ["ios"] },
|
|
22312
22313
|
android: { native: ["material"] },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1524.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": "037d302a249b672119cfc06ca2812967fd324fba0991df155e11cb97"
|
|
75
75
|
}
|
|
@@ -2,9 +2,8 @@ import { getStoreProduct } from "../_shared/himi-store.js";
|
|
|
2
2
|
import { iapPriceCopy } from "../_shared/iap-worker.js";
|
|
3
3
|
import { withIapPresentation } from "../_shared/iap-presentation.js";
|
|
4
4
|
import { type IapCommerce, classifyCart } from "@himalaya/iap-checkout";
|
|
5
|
-
import { addCouponToCurrentCart, calculateCurrentCart, createCheckoutFromCurrentCart,
|
|
5
|
+
import { addCouponToCurrentCart, calculateCurrentCart, createCheckoutFromCurrentCart, getCurrentCart, removeCouponFromCurrentCart, removeLineItemsFromCurrentCart, updateLineItemsQuantity, type WixCartDetail, type WixCartLineItemDetail } from "@himalaya/wix-ecom";
|
|
6
6
|
import { createRedirectSession } from "@himalaya/wix-redirects";
|
|
7
|
-
import { session as wixPlatformSession } from "@himalaya/wix-platform";
|
|
8
7
|
import { payCashierOrder } from "@himalaya/checkout";
|
|
9
8
|
import { hostedCheckoutOpener, isHostedWorker } from "../_shared/hosted-checkout.js";
|
|
10
9
|
import { formatCurrency } from "../_shared/engine-intl.js";
|
|
@@ -14,16 +13,6 @@ import { formatCurrency } from "../_shared/engine-intl.js";
|
|
|
14
13
|
const WIX_STORES_CATALOG_ID = "215238eb-22a5-4c36-9e7b-e7c08025e04e";
|
|
15
14
|
const WIX_STORES_APP_ID = "1380b703-ce81-ff05-f115-39571d94dfcd";
|
|
16
15
|
|
|
17
|
-
/** The site's metaSiteId for the cashier payment config. Best-effort — the native
|
|
18
|
-
* cashier can also resolve it from the app's signed Wix session, so "" is tolerated. */
|
|
19
|
-
async function resolveMsid(): Promise<string> {
|
|
20
|
-
try {
|
|
21
|
-
const st = await wixPlatformSession.signedInstanceStatus();
|
|
22
|
-
return st.msid ?? "";
|
|
23
|
-
} catch {
|
|
24
|
-
return "";
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
16
|
import { copyParam, copyTemplate, stashCopy } from "../_shared/himi-copy.js";
|
|
28
17
|
import { getAll, upsert, remove as dbRemove, type DbEntity } from "@himalaya/local-db";
|
|
29
18
|
import { isOfflineFailure, writeMayHaveLanded } from "../_shared/owner-load-error.js";
|
|
@@ -387,30 +376,6 @@ function couponDetails(result: unknown): { id: string; code: string } {
|
|
|
387
376
|
return { id: coupon?.coupon?.id ?? coupon?.id ?? "", code: coupon?.coupon?.code ?? coupon?.code ?? "" };
|
|
388
377
|
}
|
|
389
378
|
|
|
390
|
-
/** The state slice a SETTLED order leaves behind: the order consumed the cart, so the
|
|
391
|
-
* lines AND the subtotal go with it (`refresh` and the error path both clear the pair —
|
|
392
|
-
* leaving a stale subtotal in state is the class of defect #864 fixed on the render side).
|
|
393
|
-
*
|
|
394
|
-
* `emptyText` is cleared deliberately: the empty card would otherwise nudge "Your cart is
|
|
395
|
-
* empty." underneath the confirmation, which is noise at the moment of a successful
|
|
396
|
-
* payment. The next `load` restores it.
|
|
397
|
-
*
|
|
398
|
-
* This used to be written inline as `{ items: [], itemCount: 0, checkoutHint: ... }`.
|
|
399
|
-
* `itemCount` is not a field of `State` and never was — a write to nowhere, which is why
|
|
400
|
-
* the subtotal and emptyText resets were missing. It survived because nothing typechecks
|
|
401
|
-
* Tier-5 workers: esbuild erases types, and no tsconfig includes tier5-bundles-src.
|
|
402
|
-
*/
|
|
403
|
-
function cartConsumedByOrder(): Pick<State, "items" | "subtotal" | "emptyText" | "checkoutHint" | "showPaidToast" | "promoCode" | "appliedCode" | "couponId" | "discount"> {
|
|
404
|
-
return {
|
|
405
|
-
items: [],
|
|
406
|
-
subtotal: "",
|
|
407
|
-
emptyText: "",
|
|
408
|
-
checkoutHint: copyParam("cart.checkoutPaidMessage", "Order placed. Thanks!"),
|
|
409
|
-
showPaidToast: true,
|
|
410
|
-
promoCode: "", appliedCode: "", couponId: "", discount: "",
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
|
|
414
379
|
let cartPricing: IapCommerce;
|
|
415
380
|
const defineService = withIapPresentation<State>({
|
|
416
381
|
onCreate: commerce => { cartPricing = commerce; },
|
|
@@ -544,13 +509,7 @@ const svc = defineService<State, {
|
|
|
544
509
|
return derive({ ...state, checkoutHint: copyParam("cart.quantityFailedMessage", "Could not update the quantity.") });
|
|
545
510
|
}
|
|
546
511
|
},
|
|
547
|
-
//
|
|
548
|
-
// (@wix/himalaya/checkout) instead of always bouncing to the hosted checkout:
|
|
549
|
-
// createCheckoutFromCurrentCart → ecom.createOrder → payCashierOrder
|
|
550
|
-
// A wallet-equipped app settles with NO navigation at all; every other app hands
|
|
551
|
-
// off to the in-app Wix cashier (the previous behaviour), so nothing regresses.
|
|
552
|
-
// `createOrder` returning no paymentGatewayOrderId means there is nothing to
|
|
553
|
-
// charge (fully covered / zero total) — the order already stands.
|
|
512
|
+
// Physical checkout collects shipping before the site's checkout creates the order.
|
|
554
513
|
checkout: async (state) => {
|
|
555
514
|
let validatedLines: WixCartLineItemDetail[] = [];
|
|
556
515
|
const signature = (lines: WixCartLineItemDetail[]) => JSON.stringify(lines.map(line => [line.id, line.quantity, (line as WixCartLineItemDetail & { catalogReference?: Row["catalogReference"] }).catalogReference]));
|
|
@@ -577,21 +536,11 @@ const svc = defineService<State, {
|
|
|
577
536
|
if (!checkout.checkoutId) return derive({ ...state, checkoutHint: copyParam("cart.checkoutIdMissingMessage", "Wix did not return a checkout id.") });
|
|
578
537
|
const checkoutId = checkout.checkoutId;
|
|
579
538
|
|
|
580
|
-
// Hosted (Spaces): the site's own checkout page creates the order (RN's
|
|
581
|
-
// route) — creating it here first fails on a site with no payment method set up, before the
|
|
582
|
-
// member ever reaches the checkout. The host opens the checkout as the lent member.
|
|
583
539
|
const hosted = isHostedWorker();
|
|
584
|
-
const order = hosted ? { paymentGatewayOrderId: "" } : await createOrder(checkoutId);
|
|
585
|
-
const snapshotId = order.paymentGatewayOrderId ?? "";
|
|
586
|
-
if (!snapshotId && !hosted) {
|
|
587
|
-
await writeCachedItems([]);
|
|
588
|
-
return derive({ ...state, ...cartConsumedByOrder() });
|
|
589
|
-
}
|
|
590
|
-
|
|
591
540
|
const pay = await payCashierOrder({
|
|
592
541
|
appId: WIX_STORES_APP_ID,
|
|
593
|
-
snapshotId,
|
|
594
|
-
msid:
|
|
542
|
+
snapshotId: "",
|
|
543
|
+
msid: "",
|
|
595
544
|
mayCharge: async () => {
|
|
596
545
|
const latest = await getCurrentCart();
|
|
597
546
|
if (signature(latest.lineItems ?? []) !== signature(validatedLines)) return false;
|
|
@@ -611,19 +560,11 @@ const svc = defineService<State, {
|
|
|
611
560
|
return redirect.redirectSession?.fullUrl;
|
|
612
561
|
},
|
|
613
562
|
});
|
|
614
|
-
if (pay.kind === "paid") {
|
|
615
|
-
// Settled in place — the cart is consumed by the order.
|
|
616
|
-
await writeCachedItems([]);
|
|
617
|
-
return derive({ ...state, ...cartConsumedByOrder() });
|
|
618
|
-
}
|
|
619
563
|
if (pay.kind === "handoff") {
|
|
620
564
|
// Do NOT clear the cart: payment completes in the cashier and the order is
|
|
621
565
|
// only confirmed once it lands, so the cart must survive a bail-out.
|
|
622
566
|
return derive({ ...state, checkoutHint: copyParam("cart.checkoutOpenedMessage", "Checkout opened.") });
|
|
623
567
|
}
|
|
624
|
-
if (pay.kind === "cancelled") {
|
|
625
|
-
return derive({ ...state, checkoutHint: copyParam("cart.checkoutCancelledMessage", "Payment cancelled — your cart is still here.") });
|
|
626
|
-
}
|
|
627
568
|
return derive({ ...state, checkoutHint: copyParam("cart.checkoutFailedMessage", "Checkout could not start.") });
|
|
628
569
|
} catch {
|
|
629
570
|
return derive({ ...state, checkoutHint: copyParam("cart.checkoutFailedMessage", "Checkout could not start.") });
|
|
@@ -2,9 +2,8 @@ import { getStoreProduct } from "../_shared/himi-store.js";
|
|
|
2
2
|
import { iapPriceCopy } from "../_shared/iap-worker.js";
|
|
3
3
|
import { withIapPresentation } from "../_shared/iap-presentation.js";
|
|
4
4
|
import { type IapCommerce, classifyCart } from "@himalaya/iap-checkout";
|
|
5
|
-
import { addCouponToCurrentCart, calculateCurrentCart, createCheckoutFromCurrentCart,
|
|
5
|
+
import { addCouponToCurrentCart, calculateCurrentCart, createCheckoutFromCurrentCart, getCurrentCart, removeCouponFromCurrentCart, removeLineItemsFromCurrentCart, updateLineItemsQuantity, type WixCartDetail, type WixCartLineItemDetail } from "@himalaya/wix-ecom";
|
|
6
6
|
import { createRedirectSession } from "@himalaya/wix-redirects";
|
|
7
|
-
import { session as wixPlatformSession } from "@himalaya/wix-platform";
|
|
8
7
|
import { payCashierOrder } from "@himalaya/checkout";
|
|
9
8
|
import { hostedCheckoutOpener, isHostedWorker } from "../_shared/hosted-checkout.js";
|
|
10
9
|
import { formatCurrency } from "../_shared/engine-intl.js";
|
|
@@ -14,16 +13,6 @@ import { formatCurrency } from "../_shared/engine-intl.js";
|
|
|
14
13
|
const WIX_STORES_CATALOG_ID = "215238eb-22a5-4c36-9e7b-e7c08025e04e";
|
|
15
14
|
const WIX_STORES_APP_ID = "1380b703-ce81-ff05-f115-39571d94dfcd";
|
|
16
15
|
|
|
17
|
-
/** The site's metaSiteId for the cashier payment config. Best-effort — the native
|
|
18
|
-
* cashier can also resolve it from the app's signed Wix session, so "" is tolerated. */
|
|
19
|
-
async function resolveMsid(): Promise<string> {
|
|
20
|
-
try {
|
|
21
|
-
const st = await wixPlatformSession.signedInstanceStatus();
|
|
22
|
-
return st.msid ?? "";
|
|
23
|
-
} catch {
|
|
24
|
-
return "";
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
16
|
import { copyParam, copyTemplate, stashCopy } from "../_shared/himi-copy.js";
|
|
28
17
|
import { getAll, upsert, remove as dbRemove, type DbEntity } from "@himalaya/local-db";
|
|
29
18
|
import { isOfflineFailure, writeMayHaveLanded } from "../_shared/owner-load-error.js";
|
|
@@ -387,30 +376,6 @@ function couponDetails(result: unknown): { id: string; code: string } {
|
|
|
387
376
|
return { id: coupon?.coupon?.id ?? coupon?.id ?? "", code: coupon?.coupon?.code ?? coupon?.code ?? "" };
|
|
388
377
|
}
|
|
389
378
|
|
|
390
|
-
/** The state slice a SETTLED order leaves behind: the order consumed the cart, so the
|
|
391
|
-
* lines AND the subtotal go with it (`refresh` and the error path both clear the pair —
|
|
392
|
-
* leaving a stale subtotal in state is the class of defect #864 fixed on the render side).
|
|
393
|
-
*
|
|
394
|
-
* `emptyText` is cleared deliberately: the empty card would otherwise nudge "Your cart is
|
|
395
|
-
* empty." underneath the confirmation, which is noise at the moment of a successful
|
|
396
|
-
* payment. The next `load` restores it.
|
|
397
|
-
*
|
|
398
|
-
* This used to be written inline as `{ items: [], itemCount: 0, checkoutHint: ... }`.
|
|
399
|
-
* `itemCount` is not a field of `State` and never was — a write to nowhere, which is why
|
|
400
|
-
* the subtotal and emptyText resets were missing. It survived because nothing typechecks
|
|
401
|
-
* Tier-5 workers: esbuild erases types, and no tsconfig includes tier5-bundles-src.
|
|
402
|
-
*/
|
|
403
|
-
function cartConsumedByOrder(): Pick<State, "items" | "subtotal" | "emptyText" | "checkoutHint" | "showPaidToast" | "promoCode" | "appliedCode" | "couponId" | "discount"> {
|
|
404
|
-
return {
|
|
405
|
-
items: [],
|
|
406
|
-
subtotal: "",
|
|
407
|
-
emptyText: "",
|
|
408
|
-
checkoutHint: copyParam("cart.checkoutPaidMessage", "Order placed. Thanks!"),
|
|
409
|
-
showPaidToast: true,
|
|
410
|
-
promoCode: "", appliedCode: "", couponId: "", discount: "",
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
|
|
414
379
|
let cartPricing: IapCommerce;
|
|
415
380
|
const defineService = withIapPresentation<State>({
|
|
416
381
|
onCreate: commerce => { cartPricing = commerce; },
|
|
@@ -544,13 +509,7 @@ const svc = defineService<State, {
|
|
|
544
509
|
return derive({ ...state, checkoutHint: copyParam("cart.quantityFailedMessage", "Could not update the quantity.") });
|
|
545
510
|
}
|
|
546
511
|
},
|
|
547
|
-
//
|
|
548
|
-
// (@wix/himalaya/checkout) instead of always bouncing to the hosted checkout:
|
|
549
|
-
// createCheckoutFromCurrentCart → ecom.createOrder → payCashierOrder
|
|
550
|
-
// A wallet-equipped app settles with NO navigation at all; every other app hands
|
|
551
|
-
// off to the in-app Wix cashier (the previous behaviour), so nothing regresses.
|
|
552
|
-
// `createOrder` returning no paymentGatewayOrderId means there is nothing to
|
|
553
|
-
// charge (fully covered / zero total) — the order already stands.
|
|
512
|
+
// Physical checkout collects shipping before the site's checkout creates the order.
|
|
554
513
|
checkout: async (state) => {
|
|
555
514
|
let validatedLines: WixCartLineItemDetail[] = [];
|
|
556
515
|
const signature = (lines: WixCartLineItemDetail[]) => JSON.stringify(lines.map(line => [line.id, line.quantity, (line as WixCartLineItemDetail & { catalogReference?: Row["catalogReference"] }).catalogReference]));
|
|
@@ -577,21 +536,11 @@ const svc = defineService<State, {
|
|
|
577
536
|
if (!checkout.checkoutId) return derive({ ...state, checkoutHint: copyParam("cart.checkoutIdMissingMessage", "Wix did not return a checkout id.") });
|
|
578
537
|
const checkoutId = checkout.checkoutId;
|
|
579
538
|
|
|
580
|
-
// Hosted (Spaces): the site's own checkout page creates the order (RN's
|
|
581
|
-
// route) — creating it here first fails on a site with no payment method set up, before the
|
|
582
|
-
// member ever reaches the checkout. The host opens the checkout as the lent member.
|
|
583
539
|
const hosted = isHostedWorker();
|
|
584
|
-
const order = hosted ? { paymentGatewayOrderId: "" } : await createOrder(checkoutId);
|
|
585
|
-
const snapshotId = order.paymentGatewayOrderId ?? "";
|
|
586
|
-
if (!snapshotId && !hosted) {
|
|
587
|
-
await writeCachedItems([]);
|
|
588
|
-
return derive({ ...state, ...cartConsumedByOrder() });
|
|
589
|
-
}
|
|
590
|
-
|
|
591
540
|
const pay = await payCashierOrder({
|
|
592
541
|
appId: WIX_STORES_APP_ID,
|
|
593
|
-
snapshotId,
|
|
594
|
-
msid:
|
|
542
|
+
snapshotId: "",
|
|
543
|
+
msid: "",
|
|
595
544
|
mayCharge: async () => {
|
|
596
545
|
const latest = await getCurrentCart();
|
|
597
546
|
if (signature(latest.lineItems ?? []) !== signature(validatedLines)) return false;
|
|
@@ -611,19 +560,11 @@ const svc = defineService<State, {
|
|
|
611
560
|
return redirect.redirectSession?.fullUrl;
|
|
612
561
|
},
|
|
613
562
|
});
|
|
614
|
-
if (pay.kind === "paid") {
|
|
615
|
-
// Settled in place — the cart is consumed by the order.
|
|
616
|
-
await writeCachedItems([]);
|
|
617
|
-
return derive({ ...state, ...cartConsumedByOrder() });
|
|
618
|
-
}
|
|
619
563
|
if (pay.kind === "handoff") {
|
|
620
564
|
// Do NOT clear the cart: payment completes in the cashier and the order is
|
|
621
565
|
// only confirmed once it lands, so the cart must survive a bail-out.
|
|
622
566
|
return derive({ ...state, checkoutHint: copyParam("cart.checkoutOpenedMessage", "Checkout opened.") });
|
|
623
567
|
}
|
|
624
|
-
if (pay.kind === "cancelled") {
|
|
625
|
-
return derive({ ...state, checkoutHint: copyParam("cart.checkoutCancelledMessage", "Payment cancelled — your cart is still here.") });
|
|
626
|
-
}
|
|
627
568
|
return derive({ ...state, checkoutHint: copyParam("cart.checkoutFailedMessage", "Checkout could not start.") });
|
|
628
569
|
} catch {
|
|
629
570
|
return derive({ ...state, checkoutHint: copyParam("cart.checkoutFailedMessage", "Checkout could not start.") });
|
|
@@ -2,9 +2,8 @@ import { getStoreProduct } from "../_shared/himi-store.js";
|
|
|
2
2
|
import { iapPriceCopy } from "../_shared/iap-worker.js";
|
|
3
3
|
import { withIapPresentation } from "../_shared/iap-presentation.js";
|
|
4
4
|
import { type IapCommerce, classifyCart } from "@himalaya/iap-checkout";
|
|
5
|
-
import { addCouponToCurrentCart, calculateCurrentCart, createCheckoutFromCurrentCart,
|
|
5
|
+
import { addCouponToCurrentCart, calculateCurrentCart, createCheckoutFromCurrentCart, getCurrentCart, removeCouponFromCurrentCart, removeLineItemsFromCurrentCart, updateLineItemsQuantity, type WixCartDetail, type WixCartLineItemDetail } from "@himalaya/wix-ecom";
|
|
6
6
|
import { createRedirectSession } from "@himalaya/wix-redirects";
|
|
7
|
-
import { session as wixPlatformSession } from "@himalaya/wix-platform";
|
|
8
7
|
import { payCashierOrder } from "@himalaya/checkout";
|
|
9
8
|
import { hostedCheckoutOpener, isHostedWorker } from "../_shared/hosted-checkout.js";
|
|
10
9
|
import { formatCurrency } from "../_shared/engine-intl.js";
|
|
@@ -14,16 +13,6 @@ import { formatCurrency } from "../_shared/engine-intl.js";
|
|
|
14
13
|
const WIX_STORES_CATALOG_ID = "215238eb-22a5-4c36-9e7b-e7c08025e04e";
|
|
15
14
|
const WIX_STORES_APP_ID = "1380b703-ce81-ff05-f115-39571d94dfcd";
|
|
16
15
|
|
|
17
|
-
/** The site's metaSiteId for the cashier payment config. Best-effort — the native
|
|
18
|
-
* cashier can also resolve it from the app's signed Wix session, so "" is tolerated. */
|
|
19
|
-
async function resolveMsid(): Promise<string> {
|
|
20
|
-
try {
|
|
21
|
-
const st = await wixPlatformSession.signedInstanceStatus();
|
|
22
|
-
return st.msid ?? "";
|
|
23
|
-
} catch {
|
|
24
|
-
return "";
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
16
|
import { copyParam, copyTemplate, stashCopy } from "../_shared/himi-copy.js";
|
|
28
17
|
import { getAll, upsert, remove as dbRemove, type DbEntity } from "@himalaya/local-db";
|
|
29
18
|
import { isOfflineFailure, writeMayHaveLanded } from "../_shared/owner-load-error.js";
|
|
@@ -387,30 +376,6 @@ function couponDetails(result: unknown): { id: string; code: string } {
|
|
|
387
376
|
return { id: coupon?.coupon?.id ?? coupon?.id ?? "", code: coupon?.coupon?.code ?? coupon?.code ?? "" };
|
|
388
377
|
}
|
|
389
378
|
|
|
390
|
-
/** The state slice a SETTLED order leaves behind: the order consumed the cart, so the
|
|
391
|
-
* lines AND the subtotal go with it (`refresh` and the error path both clear the pair —
|
|
392
|
-
* leaving a stale subtotal in state is the class of defect #864 fixed on the render side).
|
|
393
|
-
*
|
|
394
|
-
* `emptyText` is cleared deliberately: the empty card would otherwise nudge "Your cart is
|
|
395
|
-
* empty." underneath the confirmation, which is noise at the moment of a successful
|
|
396
|
-
* payment. The next `load` restores it.
|
|
397
|
-
*
|
|
398
|
-
* This used to be written inline as `{ items: [], itemCount: 0, checkoutHint: ... }`.
|
|
399
|
-
* `itemCount` is not a field of `State` and never was — a write to nowhere, which is why
|
|
400
|
-
* the subtotal and emptyText resets were missing. It survived because nothing typechecks
|
|
401
|
-
* Tier-5 workers: esbuild erases types, and no tsconfig includes tier5-bundles-src.
|
|
402
|
-
*/
|
|
403
|
-
function cartConsumedByOrder(): Pick<State, "items" | "subtotal" | "emptyText" | "checkoutHint" | "showPaidToast" | "promoCode" | "appliedCode" | "couponId" | "discount"> {
|
|
404
|
-
return {
|
|
405
|
-
items: [],
|
|
406
|
-
subtotal: "",
|
|
407
|
-
emptyText: "",
|
|
408
|
-
checkoutHint: copyParam("cart.checkoutPaidMessage", "Order placed. Thanks!"),
|
|
409
|
-
showPaidToast: true,
|
|
410
|
-
promoCode: "", appliedCode: "", couponId: "", discount: "",
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
|
|
414
379
|
let cartPricing: IapCommerce;
|
|
415
380
|
const defineService = withIapPresentation<State>({
|
|
416
381
|
onCreate: commerce => { cartPricing = commerce; },
|
|
@@ -544,13 +509,7 @@ const svc = defineService<State, {
|
|
|
544
509
|
return derive({ ...state, checkoutHint: copyParam("cart.quantityFailedMessage", "Could not update the quantity.") });
|
|
545
510
|
}
|
|
546
511
|
},
|
|
547
|
-
//
|
|
548
|
-
// (@wix/himalaya/checkout) instead of always bouncing to the hosted checkout:
|
|
549
|
-
// createCheckoutFromCurrentCart → ecom.createOrder → payCashierOrder
|
|
550
|
-
// A wallet-equipped app settles with NO navigation at all; every other app hands
|
|
551
|
-
// off to the in-app Wix cashier (the previous behaviour), so nothing regresses.
|
|
552
|
-
// `createOrder` returning no paymentGatewayOrderId means there is nothing to
|
|
553
|
-
// charge (fully covered / zero total) — the order already stands.
|
|
512
|
+
// Physical checkout collects shipping before the site's checkout creates the order.
|
|
554
513
|
checkout: async (state) => {
|
|
555
514
|
let validatedLines: WixCartLineItemDetail[] = [];
|
|
556
515
|
const signature = (lines: WixCartLineItemDetail[]) => JSON.stringify(lines.map(line => [line.id, line.quantity, (line as WixCartLineItemDetail & { catalogReference?: Row["catalogReference"] }).catalogReference]));
|
|
@@ -577,21 +536,11 @@ const svc = defineService<State, {
|
|
|
577
536
|
if (!checkout.checkoutId) return derive({ ...state, checkoutHint: copyParam("cart.checkoutIdMissingMessage", "Wix did not return a checkout id.") });
|
|
578
537
|
const checkoutId = checkout.checkoutId;
|
|
579
538
|
|
|
580
|
-
// Hosted (Spaces): the site's own checkout page creates the order (RN's
|
|
581
|
-
// route) — creating it here first fails on a site with no payment method set up, before the
|
|
582
|
-
// member ever reaches the checkout. The host opens the checkout as the lent member.
|
|
583
539
|
const hosted = isHostedWorker();
|
|
584
|
-
const order = hosted ? { paymentGatewayOrderId: "" } : await createOrder(checkoutId);
|
|
585
|
-
const snapshotId = order.paymentGatewayOrderId ?? "";
|
|
586
|
-
if (!snapshotId && !hosted) {
|
|
587
|
-
await writeCachedItems([]);
|
|
588
|
-
return derive({ ...state, ...cartConsumedByOrder() });
|
|
589
|
-
}
|
|
590
|
-
|
|
591
540
|
const pay = await payCashierOrder({
|
|
592
541
|
appId: WIX_STORES_APP_ID,
|
|
593
|
-
snapshotId,
|
|
594
|
-
msid:
|
|
542
|
+
snapshotId: "",
|
|
543
|
+
msid: "",
|
|
595
544
|
mayCharge: async () => {
|
|
596
545
|
const latest = await getCurrentCart();
|
|
597
546
|
if (signature(latest.lineItems ?? []) !== signature(validatedLines)) return false;
|
|
@@ -611,19 +560,11 @@ const svc = defineService<State, {
|
|
|
611
560
|
return redirect.redirectSession?.fullUrl;
|
|
612
561
|
},
|
|
613
562
|
});
|
|
614
|
-
if (pay.kind === "paid") {
|
|
615
|
-
// Settled in place — the cart is consumed by the order.
|
|
616
|
-
await writeCachedItems([]);
|
|
617
|
-
return derive({ ...state, ...cartConsumedByOrder() });
|
|
618
|
-
}
|
|
619
563
|
if (pay.kind === "handoff") {
|
|
620
564
|
// Do NOT clear the cart: payment completes in the cashier and the order is
|
|
621
565
|
// only confirmed once it lands, so the cart must survive a bail-out.
|
|
622
566
|
return derive({ ...state, checkoutHint: copyParam("cart.checkoutOpenedMessage", "Checkout opened.") });
|
|
623
567
|
}
|
|
624
|
-
if (pay.kind === "cancelled") {
|
|
625
|
-
return derive({ ...state, checkoutHint: copyParam("cart.checkoutCancelledMessage", "Payment cancelled — your cart is still here.") });
|
|
626
|
-
}
|
|
627
568
|
return derive({ ...state, checkoutHint: copyParam("cart.checkoutFailedMessage", "Checkout could not start.") });
|
|
628
569
|
} catch {
|
|
629
570
|
return derive({ ...state, checkoutHint: copyParam("cart.checkoutFailedMessage", "Checkout could not start.") });
|
|
@@ -2,9 +2,8 @@ import { getStoreProduct } from "../_shared/himi-store.js";
|
|
|
2
2
|
import { iapPriceCopy } from "../_shared/iap-worker.js";
|
|
3
3
|
import { withIapPresentation } from "../_shared/iap-presentation.js";
|
|
4
4
|
import { type IapCommerce, classifyCart } from "@himalaya/iap-checkout";
|
|
5
|
-
import { addCouponToCurrentCart, calculateCurrentCart, createCheckoutFromCurrentCart,
|
|
5
|
+
import { addCouponToCurrentCart, calculateCurrentCart, createCheckoutFromCurrentCart, getCurrentCart, removeCouponFromCurrentCart, removeLineItemsFromCurrentCart, updateLineItemsQuantity, type WixCartDetail, type WixCartLineItemDetail } from "@himalaya/wix-ecom";
|
|
6
6
|
import { createRedirectSession } from "@himalaya/wix-redirects";
|
|
7
|
-
import { session as wixPlatformSession } from "@himalaya/wix-platform";
|
|
8
7
|
import { payCashierOrder } from "@himalaya/checkout";
|
|
9
8
|
import { hostedCheckoutOpener, isHostedWorker } from "../_shared/hosted-checkout.js";
|
|
10
9
|
import { formatCurrency } from "../_shared/engine-intl.js";
|
|
@@ -14,16 +13,6 @@ import { formatCurrency } from "../_shared/engine-intl.js";
|
|
|
14
13
|
const WIX_STORES_CATALOG_ID = "215238eb-22a5-4c36-9e7b-e7c08025e04e";
|
|
15
14
|
const WIX_STORES_APP_ID = "1380b703-ce81-ff05-f115-39571d94dfcd";
|
|
16
15
|
|
|
17
|
-
/** The site's metaSiteId for the cashier payment config. Best-effort — the native
|
|
18
|
-
* cashier can also resolve it from the app's signed Wix session, so "" is tolerated. */
|
|
19
|
-
async function resolveMsid(): Promise<string> {
|
|
20
|
-
try {
|
|
21
|
-
const st = await wixPlatformSession.signedInstanceStatus();
|
|
22
|
-
return st.msid ?? "";
|
|
23
|
-
} catch {
|
|
24
|
-
return "";
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
16
|
import { copyParam, copyTemplate, stashCopy } from "../_shared/himi-copy.js";
|
|
28
17
|
import { getAll, upsert, remove as dbRemove, type DbEntity } from "@himalaya/local-db";
|
|
29
18
|
import { isOfflineFailure, writeMayHaveLanded } from "../_shared/owner-load-error.js";
|
|
@@ -387,30 +376,6 @@ function couponDetails(result: unknown): { id: string; code: string } {
|
|
|
387
376
|
return { id: coupon?.coupon?.id ?? coupon?.id ?? "", code: coupon?.coupon?.code ?? coupon?.code ?? "" };
|
|
388
377
|
}
|
|
389
378
|
|
|
390
|
-
/** The state slice a SETTLED order leaves behind: the order consumed the cart, so the
|
|
391
|
-
* lines AND the subtotal go with it (`refresh` and the error path both clear the pair —
|
|
392
|
-
* leaving a stale subtotal in state is the class of defect #864 fixed on the render side).
|
|
393
|
-
*
|
|
394
|
-
* `emptyText` is cleared deliberately: the empty card would otherwise nudge "Your cart is
|
|
395
|
-
* empty." underneath the confirmation, which is noise at the moment of a successful
|
|
396
|
-
* payment. The next `load` restores it.
|
|
397
|
-
*
|
|
398
|
-
* This used to be written inline as `{ items: [], itemCount: 0, checkoutHint: ... }`.
|
|
399
|
-
* `itemCount` is not a field of `State` and never was — a write to nowhere, which is why
|
|
400
|
-
* the subtotal and emptyText resets were missing. It survived because nothing typechecks
|
|
401
|
-
* Tier-5 workers: esbuild erases types, and no tsconfig includes tier5-bundles-src.
|
|
402
|
-
*/
|
|
403
|
-
function cartConsumedByOrder(): Pick<State, "items" | "subtotal" | "emptyText" | "checkoutHint" | "showPaidToast" | "promoCode" | "appliedCode" | "couponId" | "discount"> {
|
|
404
|
-
return {
|
|
405
|
-
items: [],
|
|
406
|
-
subtotal: "",
|
|
407
|
-
emptyText: "",
|
|
408
|
-
checkoutHint: copyParam("cart.checkoutPaidMessage", "Order placed. Thanks!"),
|
|
409
|
-
showPaidToast: true,
|
|
410
|
-
promoCode: "", appliedCode: "", couponId: "", discount: "",
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
|
|
414
379
|
let cartPricing: IapCommerce;
|
|
415
380
|
const defineService = withIapPresentation<State>({
|
|
416
381
|
onCreate: commerce => { cartPricing = commerce; },
|
|
@@ -544,13 +509,7 @@ const svc = defineService<State, {
|
|
|
544
509
|
return derive({ ...state, checkoutHint: copyParam("cart.quantityFailedMessage", "Could not update the quantity.") });
|
|
545
510
|
}
|
|
546
511
|
},
|
|
547
|
-
//
|
|
548
|
-
// (@wix/himalaya/checkout) instead of always bouncing to the hosted checkout:
|
|
549
|
-
// createCheckoutFromCurrentCart → ecom.createOrder → payCashierOrder
|
|
550
|
-
// A wallet-equipped app settles with NO navigation at all; every other app hands
|
|
551
|
-
// off to the in-app Wix cashier (the previous behaviour), so nothing regresses.
|
|
552
|
-
// `createOrder` returning no paymentGatewayOrderId means there is nothing to
|
|
553
|
-
// charge (fully covered / zero total) — the order already stands.
|
|
512
|
+
// Physical checkout collects shipping before the site's checkout creates the order.
|
|
554
513
|
checkout: async (state) => {
|
|
555
514
|
let validatedLines: WixCartLineItemDetail[] = [];
|
|
556
515
|
const signature = (lines: WixCartLineItemDetail[]) => JSON.stringify(lines.map(line => [line.id, line.quantity, (line as WixCartLineItemDetail & { catalogReference?: Row["catalogReference"] }).catalogReference]));
|
|
@@ -577,21 +536,11 @@ const svc = defineService<State, {
|
|
|
577
536
|
if (!checkout.checkoutId) return derive({ ...state, checkoutHint: copyParam("cart.checkoutIdMissingMessage", "Wix did not return a checkout id.") });
|
|
578
537
|
const checkoutId = checkout.checkoutId;
|
|
579
538
|
|
|
580
|
-
// Hosted (Spaces): the site's own checkout page creates the order (RN's
|
|
581
|
-
// route) — creating it here first fails on a site with no payment method set up, before the
|
|
582
|
-
// member ever reaches the checkout. The host opens the checkout as the lent member.
|
|
583
539
|
const hosted = isHostedWorker();
|
|
584
|
-
const order = hosted ? { paymentGatewayOrderId: "" } : await createOrder(checkoutId);
|
|
585
|
-
const snapshotId = order.paymentGatewayOrderId ?? "";
|
|
586
|
-
if (!snapshotId && !hosted) {
|
|
587
|
-
await writeCachedItems([]);
|
|
588
|
-
return derive({ ...state, ...cartConsumedByOrder() });
|
|
589
|
-
}
|
|
590
|
-
|
|
591
540
|
const pay = await payCashierOrder({
|
|
592
541
|
appId: WIX_STORES_APP_ID,
|
|
593
|
-
snapshotId,
|
|
594
|
-
msid:
|
|
542
|
+
snapshotId: "",
|
|
543
|
+
msid: "",
|
|
595
544
|
mayCharge: async () => {
|
|
596
545
|
const latest = await getCurrentCart();
|
|
597
546
|
if (signature(latest.lineItems ?? []) !== signature(validatedLines)) return false;
|
|
@@ -611,19 +560,11 @@ const svc = defineService<State, {
|
|
|
611
560
|
return redirect.redirectSession?.fullUrl;
|
|
612
561
|
},
|
|
613
562
|
});
|
|
614
|
-
if (pay.kind === "paid") {
|
|
615
|
-
// Settled in place — the cart is consumed by the order.
|
|
616
|
-
await writeCachedItems([]);
|
|
617
|
-
return derive({ ...state, ...cartConsumedByOrder() });
|
|
618
|
-
}
|
|
619
563
|
if (pay.kind === "handoff") {
|
|
620
564
|
// Do NOT clear the cart: payment completes in the cashier and the order is
|
|
621
565
|
// only confirmed once it lands, so the cart must survive a bail-out.
|
|
622
566
|
return derive({ ...state, checkoutHint: copyParam("cart.checkoutOpenedMessage", "Checkout opened.") });
|
|
623
567
|
}
|
|
624
|
-
if (pay.kind === "cancelled") {
|
|
625
|
-
return derive({ ...state, checkoutHint: copyParam("cart.checkoutCancelledMessage", "Payment cancelled — your cart is still here.") });
|
|
626
|
-
}
|
|
627
568
|
return derive({ ...state, checkoutHint: copyParam("cart.checkoutFailedMessage", "Checkout could not start.") });
|
|
628
569
|
} catch {
|
|
629
570
|
return derive({ ...state, checkoutHint: copyParam("cart.checkoutFailedMessage", "Checkout could not start.") });
|
|
@@ -2,9 +2,8 @@ import { getStoreProduct } from "../_shared/himi-store.js";
|
|
|
2
2
|
import { iapPriceCopy } from "../_shared/iap-worker.js";
|
|
3
3
|
import { withIapPresentation } from "../_shared/iap-presentation.js";
|
|
4
4
|
import { type IapCommerce, classifyCart } from "@himalaya/iap-checkout";
|
|
5
|
-
import { addCouponToCurrentCart, calculateCurrentCart, createCheckoutFromCurrentCart,
|
|
5
|
+
import { addCouponToCurrentCart, calculateCurrentCart, createCheckoutFromCurrentCart, getCurrentCart, removeCouponFromCurrentCart, removeLineItemsFromCurrentCart, updateLineItemsQuantity, type WixCartDetail, type WixCartLineItemDetail } from "@himalaya/wix-ecom";
|
|
6
6
|
import { createRedirectSession } from "@himalaya/wix-redirects";
|
|
7
|
-
import { session as wixPlatformSession } from "@himalaya/wix-platform";
|
|
8
7
|
import { payCashierOrder } from "@himalaya/checkout";
|
|
9
8
|
import { hostedCheckoutOpener, isHostedWorker } from "../_shared/hosted-checkout.js";
|
|
10
9
|
import { formatCurrency } from "../_shared/engine-intl.js";
|
|
@@ -14,16 +13,6 @@ import { formatCurrency } from "../_shared/engine-intl.js";
|
|
|
14
13
|
const WIX_STORES_CATALOG_ID = "215238eb-22a5-4c36-9e7b-e7c08025e04e";
|
|
15
14
|
const WIX_STORES_APP_ID = "1380b703-ce81-ff05-f115-39571d94dfcd";
|
|
16
15
|
|
|
17
|
-
/** The site's metaSiteId for the cashier payment config. Best-effort — the native
|
|
18
|
-
* cashier can also resolve it from the app's signed Wix session, so "" is tolerated. */
|
|
19
|
-
async function resolveMsid(): Promise<string> {
|
|
20
|
-
try {
|
|
21
|
-
const st = await wixPlatformSession.signedInstanceStatus();
|
|
22
|
-
return st.msid ?? "";
|
|
23
|
-
} catch {
|
|
24
|
-
return "";
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
16
|
import { copyParam, copyTemplate, stashCopy } from "../_shared/himi-copy.js";
|
|
28
17
|
import { getAll, upsert, remove as dbRemove, type DbEntity } from "@himalaya/local-db";
|
|
29
18
|
import { isOfflineFailure, writeMayHaveLanded } from "../_shared/owner-load-error.js";
|
|
@@ -387,30 +376,6 @@ function couponDetails(result: unknown): { id: string; code: string } {
|
|
|
387
376
|
return { id: coupon?.coupon?.id ?? coupon?.id ?? "", code: coupon?.coupon?.code ?? coupon?.code ?? "" };
|
|
388
377
|
}
|
|
389
378
|
|
|
390
|
-
/** The state slice a SETTLED order leaves behind: the order consumed the cart, so the
|
|
391
|
-
* lines AND the subtotal go with it (`refresh` and the error path both clear the pair —
|
|
392
|
-
* leaving a stale subtotal in state is the class of defect #864 fixed on the render side).
|
|
393
|
-
*
|
|
394
|
-
* `emptyText` is cleared deliberately: the empty card would otherwise nudge "Your cart is
|
|
395
|
-
* empty." underneath the confirmation, which is noise at the moment of a successful
|
|
396
|
-
* payment. The next `load` restores it.
|
|
397
|
-
*
|
|
398
|
-
* This used to be written inline as `{ items: [], itemCount: 0, checkoutHint: ... }`.
|
|
399
|
-
* `itemCount` is not a field of `State` and never was — a write to nowhere, which is why
|
|
400
|
-
* the subtotal and emptyText resets were missing. It survived because nothing typechecks
|
|
401
|
-
* Tier-5 workers: esbuild erases types, and no tsconfig includes tier5-bundles-src.
|
|
402
|
-
*/
|
|
403
|
-
function cartConsumedByOrder(): Pick<State, "items" | "subtotal" | "emptyText" | "checkoutHint" | "showPaidToast" | "promoCode" | "appliedCode" | "couponId" | "discount"> {
|
|
404
|
-
return {
|
|
405
|
-
items: [],
|
|
406
|
-
subtotal: "",
|
|
407
|
-
emptyText: "",
|
|
408
|
-
checkoutHint: copyParam("cart.checkoutPaidMessage", "Order placed. Thanks!"),
|
|
409
|
-
showPaidToast: true,
|
|
410
|
-
promoCode: "", appliedCode: "", couponId: "", discount: "",
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
|
|
414
379
|
let cartPricing: IapCommerce;
|
|
415
380
|
const defineService = withIapPresentation<State>({
|
|
416
381
|
onCreate: commerce => { cartPricing = commerce; },
|
|
@@ -544,13 +509,7 @@ const svc = defineService<State, {
|
|
|
544
509
|
return derive({ ...state, checkoutHint: copyParam("cart.quantityFailedMessage", "Could not update the quantity.") });
|
|
545
510
|
}
|
|
546
511
|
},
|
|
547
|
-
//
|
|
548
|
-
// (@wix/himalaya/checkout) instead of always bouncing to the hosted checkout:
|
|
549
|
-
// createCheckoutFromCurrentCart → ecom.createOrder → payCashierOrder
|
|
550
|
-
// A wallet-equipped app settles with NO navigation at all; every other app hands
|
|
551
|
-
// off to the in-app Wix cashier (the previous behaviour), so nothing regresses.
|
|
552
|
-
// `createOrder` returning no paymentGatewayOrderId means there is nothing to
|
|
553
|
-
// charge (fully covered / zero total) — the order already stands.
|
|
512
|
+
// Physical checkout collects shipping before the site's checkout creates the order.
|
|
554
513
|
checkout: async (state) => {
|
|
555
514
|
let validatedLines: WixCartLineItemDetail[] = [];
|
|
556
515
|
const signature = (lines: WixCartLineItemDetail[]) => JSON.stringify(lines.map(line => [line.id, line.quantity, (line as WixCartLineItemDetail & { catalogReference?: Row["catalogReference"] }).catalogReference]));
|
|
@@ -577,21 +536,11 @@ const svc = defineService<State, {
|
|
|
577
536
|
if (!checkout.checkoutId) return derive({ ...state, checkoutHint: copyParam("cart.checkoutIdMissingMessage", "Wix did not return a checkout id.") });
|
|
578
537
|
const checkoutId = checkout.checkoutId;
|
|
579
538
|
|
|
580
|
-
// Hosted (Spaces): the site's own checkout page creates the order (RN's
|
|
581
|
-
// route) — creating it here first fails on a site with no payment method set up, before the
|
|
582
|
-
// member ever reaches the checkout. The host opens the checkout as the lent member.
|
|
583
539
|
const hosted = isHostedWorker();
|
|
584
|
-
const order = hosted ? { paymentGatewayOrderId: "" } : await createOrder(checkoutId);
|
|
585
|
-
const snapshotId = order.paymentGatewayOrderId ?? "";
|
|
586
|
-
if (!snapshotId && !hosted) {
|
|
587
|
-
await writeCachedItems([]);
|
|
588
|
-
return derive({ ...state, ...cartConsumedByOrder() });
|
|
589
|
-
}
|
|
590
|
-
|
|
591
540
|
const pay = await payCashierOrder({
|
|
592
541
|
appId: WIX_STORES_APP_ID,
|
|
593
|
-
snapshotId,
|
|
594
|
-
msid:
|
|
542
|
+
snapshotId: "",
|
|
543
|
+
msid: "",
|
|
595
544
|
mayCharge: async () => {
|
|
596
545
|
const latest = await getCurrentCart();
|
|
597
546
|
if (signature(latest.lineItems ?? []) !== signature(validatedLines)) return false;
|
|
@@ -611,19 +560,11 @@ const svc = defineService<State, {
|
|
|
611
560
|
return redirect.redirectSession?.fullUrl;
|
|
612
561
|
},
|
|
613
562
|
});
|
|
614
|
-
if (pay.kind === "paid") {
|
|
615
|
-
// Settled in place — the cart is consumed by the order.
|
|
616
|
-
await writeCachedItems([]);
|
|
617
|
-
return derive({ ...state, ...cartConsumedByOrder() });
|
|
618
|
-
}
|
|
619
563
|
if (pay.kind === "handoff") {
|
|
620
564
|
// Do NOT clear the cart: payment completes in the cashier and the order is
|
|
621
565
|
// only confirmed once it lands, so the cart must survive a bail-out.
|
|
622
566
|
return derive({ ...state, checkoutHint: copyParam("cart.checkoutOpenedMessage", "Checkout opened.") });
|
|
623
567
|
}
|
|
624
|
-
if (pay.kind === "cancelled") {
|
|
625
|
-
return derive({ ...state, checkoutHint: copyParam("cart.checkoutCancelledMessage", "Payment cancelled — your cart is still here.") });
|
|
626
|
-
}
|
|
627
568
|
return derive({ ...state, checkoutHint: copyParam("cart.checkoutFailedMessage", "Checkout could not start.") });
|
|
628
569
|
} catch {
|
|
629
570
|
return derive({ ...state, checkoutHint: copyParam("cart.checkoutFailedMessage", "Checkout could not start.") });
|