@wix/himalaya-cli 0.1320.0 → 0.1322.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/app-config.d.ts +1 -0
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/app-module.d.ts +3 -0
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/biometrics/src/index.d.ts +11 -1
  4. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/catalog-pricing-contract.d.ts +4 -0
  5. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/host-session.d.ts +4 -0
  6. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/index.d.ts +13 -0
  7. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/mapping-source.d.ts +8 -3
  8. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/wix-payments.d.ts +5 -4
  9. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/sdk-types/src/capabilities.generated.d.ts +1 -1
  10. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/webview/src/index.d.ts +4 -0
  11. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/webview-page/src/index.d.ts +16 -1
  12. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/tokens.d.ts +9 -1
  13. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/apple-iap-contract.d.ts +5 -0
  14. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/apple-iap-core.d.ts +3 -1
  15. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/checkout-source.d.ts +4 -0
  16. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/commerce-contract.d.ts +83 -0
  17. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/commerce-core.d.ts +36 -0
  18. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/commerce.d.ts +8 -0
  19. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/index.d.ts +3 -0
  20. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/purchase-fields.d.ts +4 -0
  21. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/stores-v1/src/display.d.ts +21 -0
  22. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/audio-record.mjs +1 -1
  23. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/calendar.mjs +1 -1
  24. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/calls.mjs +1 -1
  25. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/contacts.mjs +1 -1
  26. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/iap-checkout.mjs +1205 -71
  27. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/iap.mjs +125 -13
  28. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/location.mjs +1 -1
  29. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/motion.mjs +1 -1
  30. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/photos.mjs +1 -1
  31. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdk-types.mjs +1 -1
  32. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdui.mjs +1 -0
  33. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/tasks.mjs +1 -1
  34. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/webview-page.mjs +78 -0
  35. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/webview.mjs +16 -0
  36. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-stores.mjs +13 -4
  37. package/dist/cli.mjs +87 -23
  38. package/dist/preview-assets.generated.bin +0 -0
  39. package/guides/getting-started.md +4 -2
  40. package/guides/himi-skill.md +4 -2
  41. package/guides/iap-pricing.md +33 -26
  42. package/guides/index.json +2 -1
  43. package/guides/sdk-reference.json +50 -8
  44. package/guides/tokens.md +22 -1
  45. package/guides/web-page-native-sdk.md +154 -33
  46. package/guides/webview-page-sdk.md +11 -0
  47. package/package.json +2 -2
  48. package/templates/beauty-salon/dev/index.ts +492 -0
  49. package/templates/beauty-salon/tier5-src/wix-spaces-collection-detail/index.ts +146 -30
  50. package/templates/branded-lite/dev/index.ts +533 -0
  51. package/templates/branded-lite/tier5-src/_shared/iap-worker.ts +21 -44
  52. package/templates/branded-lite/tier5-src/himi-branded-lite-program/index.ts +77 -47
  53. package/templates/branded-lite/tier5-src/himi-branded-lite-programs/index.ts +24 -38
  54. package/templates/branded-lite/tier5-src/wix-spaces-collection-detail/index.ts +146 -30
  55. package/templates/gym-fitness/dev/index.ts +492 -0
  56. package/templates/gym-fitness/tier5-src/wix-spaces-collection-detail/index.ts +146 -30
  57. package/templates/portfolio-creative/dev/index.ts +492 -0
  58. package/templates/portfolio-creative/tier5-src/wix-spaces-collection-detail/index.ts +146 -30
  59. package/templates/retail-store/dev/index.ts +492 -0
  60. package/templates/retail-store/tier5-src/wix-spaces-collection-detail/index.ts +146 -30
  61. package/templates/yoga-studio/dev/index.ts +41 -0
  62. package/templates/yoga-studio/tier5-src/_shared/iap-worker.ts +21 -44
  63. package/templates/yoga-studio/tier5-src/himi-branded-lite-program/index.ts +77 -47
  64. package/templates/yoga-studio/tier5-src/himi-branded-lite-programs/index.ts +24 -38
@@ -1,8 +1,3 @@
1
- // ../../stdlib/flows/iap-checkout/src/checkout-source.ts
2
- function appleIapCheckoutEnabled() {
3
- return false;
4
- }
5
-
6
1
  // ../../core/sdk/dispatch/src/index.ts
7
2
  function dispatch(handlerId, params, _options) {
8
3
  const himalaya = globalThis.himalaya;
@@ -18,6 +13,31 @@ function dispatch(handlerId, params, _options) {
18
13
  return himalaya.dispatch(handlerId, stringParams);
19
14
  }
20
15
 
16
+ // ../../core/sdk/app-info/src/index.ts
17
+ var PLATFORMS = ["ios", "android", "macos", "web", "react-native"];
18
+ function str(v) {
19
+ return typeof v === "string" ? v.trim() : "";
20
+ }
21
+ async function get() {
22
+ const r = await dispatch("capability.app_info.get");
23
+ const platform = str(r?.platform);
24
+ const releaseId = str(r?.releaseId);
25
+ const serveBaseUrl = str(r?.serveBaseUrl);
26
+ return {
27
+ appId: str(r?.appId),
28
+ bundleId: str(r?.bundleId),
29
+ version: str(r?.version),
30
+ buildNumber: str(r?.buildNumber),
31
+ binaryVersion: str(r?.binaryVersion),
32
+ releaseId: releaseId || null,
33
+ releasePinned: r?.releasePinned === true,
34
+ // Trust the host's own answer; fall back to inferring from whether a serve origin is set.
35
+ environment: str(r?.environment) === "prod" ? "prod" : serveBaseUrl ? "prod" : "dev",
36
+ serveBaseUrl: serveBaseUrl || null,
37
+ platform: PLATFORMS.includes(platform) ? platform : "unknown"
38
+ };
39
+ }
40
+
21
41
  // ../../core/sdk/iap/src/delivery.ts
22
42
  var MAX_AUTOMATIC_ATTEMPTS = 5;
23
43
  var MAX_RETRY_DELAY_MS = 6e4;
@@ -30,7 +50,7 @@ function createPurchaseCoordinator(deps) {
30
50
  let outcome = "idle";
31
51
  let purchasing = false;
32
52
  let signInPrompt = false;
33
- let unavailable = null;
53
+ let unavailable2 = null;
34
54
  let pendingApproval = null;
35
55
  let errorCode = null;
36
56
  let errorFromReconcile = false;
@@ -66,7 +86,7 @@ function createPurchaseCoordinator(deps) {
66
86
  if (disposed || !sessionMatches()) return { phase: "idle", errorCode: null, items: [], unfinishedCount: null, nextWakeAt: null };
67
87
  const snapshot = [...items.values()].map((item) => ({ ...item.state }));
68
88
  const due = snapshot.map((item) => item.nextAttemptAt).filter((at) => at !== null);
69
- return { phase: currentPhase(), errorCode: errorCode ?? unavailable?.code ?? null, items: snapshot, unfinishedCount, nextWakeAt: due.length > 0 ? Math.min(...due) : null };
89
+ return { phase: currentPhase(), errorCode: errorCode ?? unavailable2?.code ?? null, items: snapshot, unfinishedCount, nextWakeAt: due.length > 0 ? Math.min(...due) : null };
70
90
  }
71
91
  function dispose() {
72
92
  disposed = true;
@@ -78,7 +98,7 @@ function createPurchaseCoordinator(deps) {
78
98
  setError(null, false);
79
99
  outcome = "idle";
80
100
  pendingApproval = null;
81
- unavailable = null;
101
+ unavailable2 = null;
82
102
  releaseSignIn();
83
103
  if (session.kind !== "member") {
84
104
  requireSignIn();
@@ -137,7 +157,7 @@ function createPurchaseCoordinator(deps) {
137
157
  }
138
158
  }
139
159
  function clearReconcileProblem() {
140
- if (unavailable?.from === "reconcile") unavailable = null;
160
+ if (unavailable2?.from === "reconcile") unavailable2 = null;
141
161
  if (errorFromReconcile) setError(null, false);
142
162
  }
143
163
  async function runRetry() {
@@ -304,7 +324,7 @@ function createPurchaseCoordinator(deps) {
304
324
  outcome = "idle";
305
325
  purchasing = false;
306
326
  signInPrompt = false;
307
- unavailable = null;
327
+ unavailable2 = null;
308
328
  pendingApproval = null;
309
329
  unfinishedCount = null;
310
330
  setError(null, false);
@@ -362,8 +382,8 @@ function createPurchaseCoordinator(deps) {
362
382
  }
363
383
  function failStore(code, fromReconcile) {
364
384
  setError(code, fromReconcile);
365
- if (UNAVAILABLE_CODES.has(code) && unavailable?.from !== "purchase") {
366
- unavailable = { from: fromReconcile ? "reconcile" : "purchase", code };
385
+ if (UNAVAILABLE_CODES.has(code) && unavailable2?.from !== "purchase") {
386
+ unavailable2 = { from: fromReconcile ? "reconcile" : "purchase", code };
367
387
  }
368
388
  publish();
369
389
  }
@@ -381,9 +401,9 @@ function createPurchaseCoordinator(deps) {
381
401
  }
382
402
  function currentPhase() {
383
403
  if (purchasing) return "purchasing";
384
- if (unavailable?.from === "purchase") return "unavailable";
404
+ if (unavailable2?.from === "purchase") return "unavailable";
385
405
  if (signInPrompt) return "signInRequired";
386
- if (unavailable?.from === "reconcile") return "unavailable";
406
+ if (unavailable2?.from === "reconcile") return "unavailable";
387
407
  return outcome;
388
408
  }
389
409
  function setError(code, fromReconcile) {
@@ -519,8 +539,8 @@ function createSerialQueue() {
519
539
  return {
520
540
  /** Callers joined onto a shared job all receive that job's result. */
521
541
  run(name, job, { joinRunning = false }) {
522
- const shared = waiting.get(name) ?? (joinRunning ? running.get(name) : void 0);
523
- if (shared) return shared;
542
+ const shared2 = waiting.get(name) ?? (joinRunning ? running.get(name) : void 0);
543
+ if (shared2) return shared2;
524
544
  const scheduled = tail.then(() => execute(name, scheduled, job));
525
545
  waiting.set(name, scheduled);
526
546
  tail = scheduled;
@@ -529,17 +549,741 @@ function createSerialQueue() {
529
549
  };
530
550
  }
531
551
 
552
+ // ../../core/sdk/iap/src/pricing.ts
553
+ function createPricingController(deps) {
554
+ let state = { revision: 0, scope: null, items: [] };
555
+ let lastInput;
556
+ let active;
557
+ let disposed = false;
558
+ function load(input) {
559
+ if (disposed) return Promise.resolve();
560
+ const captured = captureInput(input);
561
+ const key = JSON.stringify(captured);
562
+ if (active?.key === key) return active.promise;
563
+ lastInput = captured;
564
+ const revision = state.revision + 1;
565
+ let complete;
566
+ const promise = new Promise((resolve) => {
567
+ complete = resolve;
568
+ });
569
+ active = { key, promise };
570
+ publish({ revision, scope: captured.scope, items: captured.items.map((item) => ({ reference: item.reference, status: "loading" })) });
571
+ void run(captured, revision).finally(complete);
572
+ return promise;
573
+ }
574
+ async function run(input, revision) {
575
+ const current = () => !disposed && state.revision === revision;
576
+ if (!current()) return;
577
+ const items = await resolvePrices(input, deps, current);
578
+ if (!current()) return;
579
+ active = void 0;
580
+ publish({ revision, scope: input.scope, items });
581
+ }
582
+ function publish(next) {
583
+ state = next;
584
+ try {
585
+ deps.onState?.(getState());
586
+ } catch {
587
+ }
588
+ }
589
+ function getState() {
590
+ return {
591
+ ...state,
592
+ scope: state.scope ? { ...state.scope } : null,
593
+ items: state.items.map((item) => ({ ...item, reference: { ...item.reference } }))
594
+ };
595
+ }
596
+ function dispose() {
597
+ disposed = true;
598
+ active = void 0;
599
+ lastInput = void 0;
600
+ state = { revision: state.revision + 1, scope: null, items: [] };
601
+ }
602
+ return { load, refresh: () => lastInput ? load(lastInput) : Promise.resolve(), getState, dispose };
603
+ }
604
+ function captureInput(input) {
605
+ const scope = {
606
+ appId: input.scope.appId,
607
+ bundleId: input.scope.bundleId,
608
+ siteId: input.scope.siteId,
609
+ ...input.scope.contextRevision === void 0 ? {} : { contextRevision: input.scope.contextRevision }
610
+ };
611
+ const items = /* @__PURE__ */ new Map();
612
+ for (const item of input.items) {
613
+ const reference = { kind: item.reference.kind, id: item.reference.id };
614
+ const key = JSON.stringify([reference.kind, reference.id]);
615
+ if (!items.has(key)) items.set(key, { reference, ...item.commerceDisplayPrice === void 0 ? {} : { commerceDisplayPrice: item.commerceDisplayPrice } });
616
+ }
617
+ return { scope, platform: input.platform, items: [...items.values()] };
618
+ }
619
+ async function resolvePrices(input, deps, current) {
620
+ if (input.items.length === 0) return [];
621
+ if (![input.scope.appId, input.scope.bundleId, input.scope.siteId].every(nonempty)) {
622
+ return input.items.map((item) => unavailable(item.reference, "invalidInput"));
623
+ }
624
+ const mappings = await resolveMappings(input, deps);
625
+ if (!current()) return [];
626
+ if (mappings === null) return input.items.map((item) => unavailable(item.reference, "mappingUnavailable"));
627
+ const routes = input.items.map((item) => resolveRoute(item, mappings, input.platform));
628
+ const ids = [...new Set(routes.flatMap((route) => route.status === "loading" ? [route.mapping.productId] : []))];
629
+ const products = ids.length ? await lookupProducts(ids, deps) : [];
630
+ return routes.map((route) => route.status === "loading" ? applePrice(route.mapping, products) : route);
631
+ }
632
+ async function resolveMappings(input, deps) {
633
+ try {
634
+ const references = input.items.filter((item) => nonempty(item.reference.kind) && nonempty(item.reference.id)).map((item) => ({ ...item.reference }));
635
+ if (!references.length) return [];
636
+ const result = await deps.mapping.resolve({ scope: { ...input.scope }, references });
637
+ return Array.isArray(result) ? result : [];
638
+ } catch {
639
+ return null;
640
+ }
641
+ }
642
+ async function lookupProducts(ids, deps) {
643
+ try {
644
+ const products = await deps.getProducts(ids);
645
+ return Array.isArray(products) ? products : [];
646
+ } catch {
647
+ return [];
648
+ }
649
+ }
650
+ function resolveRoute(item, mappings, platform) {
651
+ if (!nonempty(item.reference.kind) || !nonempty(item.reference.id)) return unavailable(item.reference, "invalidInput");
652
+ const matches = mappings.filter((value) => isObject2(value) && sameReference(value.reference, item.reference));
653
+ if (matches.length !== 1) return unavailable(item.reference, "mappingUnresolved");
654
+ const mapping = matches[0];
655
+ if (mapping.route === "regular") return regularPrice(item);
656
+ if (mapping.route !== "appleIap" || !nonempty(mapping.productId) || mapping.productId.includes(",") || !nonempty(mapping.mappingRevision)) {
657
+ return unavailable(item.reference, "mappingUnresolved");
658
+ }
659
+ if (platform !== "ios") return unavailable(item.reference, "unsupportedPlatform");
660
+ return { status: "loading", mapping: { reference: item.reference, route: "appleIap", productId: mapping.productId, mappingRevision: mapping.mappingRevision } };
661
+ }
662
+ function regularPrice(item) {
663
+ return nonempty(item.commerceDisplayPrice) ? { reference: item.reference, status: "ready", source: "regular", displayPrice: item.commerceDisplayPrice } : unavailable(item.reference, "commercePriceUnavailable");
664
+ }
665
+ function applePrice(mapping, products) {
666
+ const matches = products.filter((value) => isObject2(value) && value.id === mapping.productId);
667
+ const product = matches[0];
668
+ if (matches.length !== 1 || !nonempty(product?.displayPrice)) return unavailable(mapping.reference, "priceUnavailable");
669
+ if (product?.type !== "nonConsumable") return unavailable(mapping.reference, "unsupportedProductType");
670
+ return {
671
+ reference: mapping.reference,
672
+ status: "ready",
673
+ source: "appleIap",
674
+ productId: mapping.productId,
675
+ mappingRevision: mapping.mappingRevision,
676
+ displayPrice: product.displayPrice
677
+ };
678
+ }
679
+ function unavailable(reference, reason) {
680
+ return { reference, status: "unavailable", reason, retryable: !["invalidInput", "unsupportedPlatform", "unsupportedProductType", "commercePriceUnavailable"].includes(reason) };
681
+ }
682
+ var isObject2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
683
+ var nonempty = (value) => typeof value === "string" && value.trim().length > 0;
684
+ var sameReference = (value, reference) => isObject2(value) && value.kind === reference.kind && value.id === reference.id;
685
+
686
+ // ../../core/sdk/iap/src/wix-payments-contract.ts
687
+ var HIMALAYA_SERVE_IAP_ROUTE = { prefix: "/himalaya-serve/v1/iap" };
688
+ var APPLE_SALE_RULES = {
689
+ onlineProgram: { appProductId: (id) => id, productType: "NON_CONSUMABLE" }
690
+ };
691
+
692
+ // ../../core/sdk/iap/src/mapping-source.ts
693
+ function iapMappingSource() {
694
+ return createWixIapMappingSource({ binding: sharedHostAppBindingSource(), call: hostWixCall });
695
+ }
696
+ function createWixIapMappingSource(deps) {
697
+ return {
698
+ // Only a binding the host actually returned: a read that failed is re-asked on the next load.
699
+ active: async () => await deps.binding.current() !== null,
700
+ mapping: {
701
+ resolve: async ({ scope, references }) => {
702
+ const binding = await deps.binding.current();
703
+ if (!binding) return references.map((reference) => ({ reference, route: "regular" }));
704
+ if (scope.siteId && !sameId(scope.siteId, binding.siteId)) return references.map((reference) => ({ reference, route: "unavailable" }));
705
+ const asked = [...new Set(references.flatMap((reference) => appProductIdOf(reference) ?? []))];
706
+ const mapped = await resolveAll(deps.call, binding, asked);
707
+ return references.map((reference) => decide(reference, binding, mapped));
708
+ }
709
+ }
710
+ };
711
+ }
712
+ function appProductIdOf(reference) {
713
+ return reference.id ? APPLE_SALE_RULES[reference.kind]?.appProductId(reference.id) : void 0;
714
+ }
715
+ var PATH = `${HIMALAYA_SERVE_IAP_ROUTE.prefix}/mappings`;
716
+ var BATCH = 100;
717
+ async function resolveAll(call, binding, ids) {
718
+ const mapped = /* @__PURE__ */ new Map();
719
+ const wanted = new Set(ids);
720
+ for (let at = 0; at < ids.length; at += BATCH) {
721
+ const batch = ids.slice(at, at + BATCH);
722
+ const reply = await call("POST", PATH, { appId: binding.purchasesAppId, appProductIds: batch }, { "wix-site-id": binding.siteId });
723
+ for (const [id, mapping] of decodeMappings(reply)) if (wanted.has(id)) mapped.set(id, mapping);
724
+ }
725
+ return mapped;
726
+ }
727
+ function decodeMappings(reply) {
728
+ const list = reply?.mappings;
729
+ if (!Array.isArray(list)) throw new Error("the mapping route answered without a mappings list");
730
+ return list.map((raw) => {
731
+ const m = raw;
732
+ if (typeof m?.appProductId !== "string" || typeof m.storeProductId !== "string" || !m.storeProductId) {
733
+ throw new Error("the mapping route answered a mapping without its ids");
734
+ }
735
+ return [m.appProductId, { storeProductId: m.storeProductId, type: String(m.type ?? ""), active: m.active === true }];
736
+ });
737
+ }
738
+ function decide(reference, binding, mapped) {
739
+ const id = appProductIdOf(reference);
740
+ const mapping = id ? mapped.get(id) : void 0;
741
+ if (!mapping) return { reference, route: "regular" };
742
+ if (!mapping.active || mapping.type !== APPLE_SALE_RULES[reference.kind]?.productType) return { reference, route: "unavailable" };
743
+ return { reference, route: "appleIap", productId: mapping.storeProductId, mappingRevision: `${binding.purchasesAppId}:${mapping.storeProductId}` };
744
+ }
745
+ function sameId(a, b) {
746
+ return a.toLowerCase() === b.toLowerCase();
747
+ }
748
+ function hostWixCall(method, path, body, headers) {
749
+ const bridge = globalThis.himalaya?.wixApi;
750
+ if (!bridge) return Promise.reject(new Error("the host did not install the wixApi bridge"));
751
+ return bridge.call(method, path, body, headers);
752
+ }
753
+
754
+ // ../../core/sdk/iap/src/catalog-pricing-core.ts
755
+ var POLL_ID = "iapCatalogPricing";
756
+ var POLL_INTERVAL_MS = 6e4;
757
+ function createIapCatalogPricingWith(deps) {
758
+ return deps.source ? enabledPricing(deps.source, deps) : disabledPricing();
759
+ }
760
+ function disabledPricing() {
761
+ return {
762
+ enabled: false,
763
+ load: () => Promise.resolve(),
764
+ refresh: () => Promise.resolve(),
765
+ view: disabledView,
766
+ checkoutGuard: (reference) => decisionOf(disabledView(reference)),
767
+ continueCheckoutGuard: (reference) => decisionOf(disabledView(reference)),
768
+ appleProduct: () => null,
769
+ pollDirective: () => void 0,
770
+ dispose: () => {
771
+ }
772
+ };
773
+ }
774
+ function enabledPricing(source, deps) {
775
+ let controller;
776
+ let disposed = false;
777
+ const settled = /* @__PURE__ */ new Map();
778
+ let settledScope = "";
779
+ const rememberSettled = (state) => {
780
+ const scopeKey = JSON.stringify(state.scope);
781
+ if (scopeKey !== settledScope) {
782
+ settled.clear();
783
+ settledScope = scopeKey;
784
+ }
785
+ for (const item of state.items) {
786
+ const answered = viewOf(item.reference, item);
787
+ if (!unanswered(answered)) settled.set(referenceKey(item.reference), answered);
788
+ }
789
+ };
790
+ let selling = "active";
791
+ let lookupRevision = 0;
792
+ let answeredRoutes;
793
+ const mapping = {
794
+ resolve: async (request) => {
795
+ const asked = lookupRevision;
796
+ const answer = await source.mapping.resolve(request);
797
+ if (asked === lookupRevision) answeredRoutes = routesAnswered(answer);
798
+ return answer;
799
+ }
800
+ };
801
+ const trackLookup = (state) => {
802
+ if (state.revision !== lookupRevision) {
803
+ lookupRevision = state.revision;
804
+ answeredRoutes = void 0;
805
+ }
806
+ };
807
+ const ensureController = () => controller ?? (controller = createPricingController({
808
+ mapping,
809
+ getProducts: deps.getProducts,
810
+ onState: (state) => {
811
+ trackLookup(state);
812
+ rememberSettled(state);
813
+ deps.onChange?.();
814
+ }
815
+ }));
816
+ const view = (reference) => disposed ? blockedView(reference, "unavailable") : selling === "inactive" ? disabledView(reference) : selling === "unknown" ? sellingUnknownView(reference) : viewOf(reference, controller && itemFor(controller.getState().items, reference));
817
+ const load = async (input) => {
818
+ if (disposed) return;
819
+ selling = source.active ? await source.active().then((active) => active ? "active" : "inactive", () => "unknown") : "active";
820
+ if (selling !== "active") {
821
+ deps.onChange?.();
822
+ return;
823
+ }
824
+ await ensureController().load(pricingInput(input, source));
825
+ };
826
+ const continueCheckoutGuard = (reference) => {
827
+ const current = view(reference);
828
+ if (!unanswered(current) || selling !== "active") return decisionOf(current);
829
+ if (answeredRoutes) return routeDecision(answeredRoutes.get(referenceKey(reference)) ?? "unavailable");
830
+ return decisionOf(settled.get(referenceKey(reference)) ?? current);
831
+ };
832
+ return {
833
+ enabled: true,
834
+ load,
835
+ refresh: () => controller?.refresh() ?? Promise.resolve(),
836
+ view,
837
+ checkoutGuard: (reference) => decisionOf(view(reference)),
838
+ continueCheckoutGuard,
839
+ appleProduct: (reference) => disposed || selling !== "active" ? null : appleProductOf(controller && itemFor(controller.getState().items, reference)),
840
+ pollDirective: (action2) => ({ id: POLL_ID, action: action2, intervalMs: POLL_INTERVAL_MS, immediate: true }),
841
+ dispose: () => {
842
+ disposed = true;
843
+ settled.clear();
844
+ controller?.dispose();
845
+ }
846
+ };
847
+ }
848
+ function pricingInput(input, source) {
849
+ return { scope: pricingScope(input.scope, source.siteId), platform: input.platform, items: input.items };
850
+ }
851
+ function pricingScope(scope, boundSiteId) {
852
+ return {
853
+ appId: scope.appId,
854
+ bundleId: scope.bundleId,
855
+ siteId: siteIdFor(scope.siteId, boundSiteId),
856
+ ...scope.contextRevision === void 0 ? {} : { contextRevision: scope.contextRevision }
857
+ };
858
+ }
859
+ function siteIdFor(callerSiteId, boundSiteId) {
860
+ if (callerSiteId && boundSiteId && callerSiteId !== boundSiteId) return "";
861
+ return callerSiteId || boundSiteId || "";
862
+ }
863
+ var referenceKey = (reference) => JSON.stringify([reference.kind, reference.id]);
864
+ function routesAnswered(answer) {
865
+ const routes = /* @__PURE__ */ new Map();
866
+ for (const entry of Array.isArray(answer) ? answer : []) {
867
+ const reference = entry?.reference;
868
+ if (typeof reference?.kind !== "string" || typeof reference.id !== "string") continue;
869
+ const key = referenceKey(reference);
870
+ const route = entry.route;
871
+ routes.set(key, routes.has(key) ? "unavailable" : route === "regular" || route === "appleIap" ? route : "unavailable");
872
+ }
873
+ return routes;
874
+ }
875
+ function routeDecision(route) {
876
+ return { allowed: route === "regular", route };
877
+ }
878
+ function unanswered(view) {
879
+ return view.route === "resolving" || view.reason === "mappingUnavailable";
880
+ }
881
+ function itemFor(items, reference) {
882
+ return items.find((item) => item.reference.kind === reference.kind && item.reference.id === reference.id);
883
+ }
884
+ function appleProductOf(item) {
885
+ if (item?.status !== "ready" || item.source !== "appleIap") return null;
886
+ return { productId: item.productId, mappingRevision: item.mappingRevision };
887
+ }
888
+ function viewOf(reference, item) {
889
+ if (!item || item.status === "loading") return blockedView(reference, "resolving");
890
+ if (item.status === "ready") return readyView(reference, item);
891
+ return unavailableView(reference, item);
892
+ }
893
+ function readyView(reference, item) {
894
+ return item.source === "appleIap" ? { ...blockedView(reference, "appleIap"), displayPrice: item.displayPrice } : { ...regularView(reference), displayPrice: item.displayPrice };
895
+ }
896
+ function unavailableView(reference, item) {
897
+ if (item.reason === "commercePriceUnavailable") return regularView(reference);
898
+ return { ...blockedView(reference, "unavailable"), reason: item.reason, retryable: item.retryable };
899
+ }
900
+ function blockedView(reference, route) {
901
+ return { reference: { kind: reference.kind, id: reference.id }, route, displayPrice: "", retryable: false, canStartRegularCheckout: false, purchasable: false };
902
+ }
903
+ function regularView(reference) {
904
+ return { ...blockedView(reference, "regular"), canStartRegularCheckout: true };
905
+ }
906
+ function sellingUnknownView(reference) {
907
+ return { ...blockedView(reference, "unavailable"), reason: "mappingUnavailable", retryable: true };
908
+ }
909
+ function disabledView(reference) {
910
+ return { ...blockedView(reference, "disabled"), canStartRegularCheckout: true };
911
+ }
912
+ function decisionOf(view) {
913
+ return { allowed: view.canStartRegularCheckout, route: view.route };
914
+ }
915
+
916
+ // ../../core/sdk/iap/src/catalog-pricing.ts
917
+ function createIapCatalogPricing(options = {}) {
918
+ return createIapCatalogPricingWith({ source: iapMappingSource(), getProducts, onChange: options.onChange });
919
+ }
920
+
532
921
  // ../../core/sdk/iap/src/host-session.ts
922
+ var SIGNED_OUT = {
923
+ generation: 0,
924
+ kind: "signedOut",
925
+ memberId: null,
926
+ siteId: null,
927
+ appId: null,
928
+ ready: false,
929
+ epoch: 0
930
+ };
931
+ var KINDS = /* @__PURE__ */ new Set(["member", "visitor", "owner", "signedOut"]);
932
+ function createHostSession(source) {
933
+ let seen = -1;
934
+ let latest = SIGNED_OUT;
935
+ const byGeneration = /* @__PURE__ */ new Map();
936
+ function pull() {
937
+ const snap = parseSession(source.current());
938
+ if (snap.generation < seen) return latest;
939
+ seen = snap.generation;
940
+ latest = snap;
941
+ const expectation = expectationOf(snap);
942
+ if (expectation && !byGeneration.has(snap.generation)) byGeneration.set(snap.generation, expectation);
943
+ return snap;
944
+ }
945
+ return {
946
+ identityBound: source.identityBound,
947
+ current() {
948
+ const snap = pull();
949
+ return { generation: snap.generation, kind: snap.kind };
950
+ },
951
+ identity(session) {
952
+ pull();
953
+ return byGeneration.get(session.generation) ?? null;
954
+ },
955
+ site() {
956
+ const snap = pull();
957
+ return snap.ready ? snap.siteId : null;
958
+ },
959
+ subscribe(listener) {
960
+ return source.subscribe(() => {
961
+ const before = seen;
962
+ pull();
963
+ if (latest.generation >= before) listener();
964
+ });
965
+ }
966
+ };
967
+ }
968
+ function hostSessionFromGlobal() {
969
+ const api = wixApiGlobal();
970
+ const session = api?.session;
971
+ if (!session || typeof session.current !== "function" || typeof session.subscribe !== "function") {
972
+ return createHostSession({ identityBound: false, current: () => SIGNED_OUT, subscribe: () => () => {
973
+ } });
974
+ }
975
+ return createHostSession({
976
+ identityBound: api?.identityBound === true,
977
+ current: () => session.current(),
978
+ subscribe: (listener) => session.subscribe(listener)
979
+ });
980
+ }
981
+ function memberIdentityOf(source) {
982
+ return { memberId: (session) => Promise.resolve(source.identity(session)?.memberId ?? null) };
983
+ }
533
984
  function readIdentityBound() {
534
985
  return wixApiGlobal()?.identityBound === true;
535
986
  }
987
+ function expectationOf(snap) {
988
+ if (!snap.ready || snap.kind !== "member" || !snap.memberId || !snap.siteId || !snap.appId) return null;
989
+ return { generation: snap.generation, kind: "member", memberId: snap.memberId, siteId: snap.siteId, appId: snap.appId };
990
+ }
991
+ function parseSession(raw) {
992
+ if (raw === null || typeof raw !== "object") return SIGNED_OUT;
993
+ const value = raw;
994
+ const kind = value.kind;
995
+ if (typeof value.generation !== "number" || !Number.isSafeInteger(value.generation)) return SIGNED_OUT;
996
+ if (typeof kind !== "string" || !KINDS.has(kind)) return SIGNED_OUT;
997
+ return {
998
+ generation: value.generation,
999
+ kind,
1000
+ memberId: typeof value.memberId === "string" && value.memberId.length > 0 ? value.memberId : null,
1001
+ siteId: typeof value.siteId === "string" && value.siteId.length > 0 ? value.siteId : null,
1002
+ appId: typeof value.appId === "string" && value.appId.length > 0 ? value.appId : null,
1003
+ ready: value.ready === true,
1004
+ epoch: typeof value.epoch === "number" ? value.epoch : 0
1005
+ };
1006
+ }
536
1007
  function wixApiGlobal() {
537
1008
  return globalThis.himalaya?.wixApi;
538
1009
  }
539
1010
 
1011
+ // ../../core/sdk/iap/src/wix-payments-wire.ts
1012
+ function startPaymentCall(scope, wixTransactionId) {
1013
+ return post(scope, "/payments/start", { appId: scope.binding.purchasesAppId, wixTransactionId });
1014
+ }
1015
+ function completePaymentCall(scope, signedTransaction) {
1016
+ return post(scope, "/payments/complete", { appId: scope.binding.purchasesAppId, apple: { signedTransaction } });
1017
+ }
1018
+ function paymentCall(scope, paymentId) {
1019
+ return get2(scope, `/payments/${encodeURIComponent(paymentId)}`);
1020
+ }
1021
+ function isRoutePrefix(prefix) {
1022
+ return /^\/[A-Za-z0-9._~\-/]*[A-Za-z0-9._~-]$/.test(prefix);
1023
+ }
1024
+ function decodeStarted(raw, expected) {
1025
+ if (!isObject3(raw) || !isStoreProductId(raw.storeProductId) || !isUUID(raw.appAccountToken)) return null;
1026
+ const payment = decodePayment(raw.payment, expected);
1027
+ return payment && { payment, storeProductId: raw.storeProductId, appAccountToken: raw.appAccountToken };
1028
+ }
1029
+ function decodePaymentAnswer(raw, expected) {
1030
+ return isObject3(raw) ? decodePayment(raw.payment, expected) : null;
1031
+ }
1032
+ function decodePayment(raw, expected) {
1033
+ if (!isObject3(raw) || !hasPaymentIds(raw) || !echoes(raw, expected) || !hasValidOptionals(raw)) return null;
1034
+ const status = ownValue(STATUSES, raw.status);
1035
+ return status ? toPayment(raw, status) : null;
1036
+ }
1037
+ function hasPaymentIds(raw) {
1038
+ return isUUID(raw.id) && isUUID(raw.appId) && isUUID(raw.memberId) && isUUID(raw.wixTransactionId);
1039
+ }
1040
+ function echoes(raw, expected) {
1041
+ return sameUUID(raw.appId, expected.appId) && (expected.memberId === null || sameUUID(raw.memberId, expected.memberId)) && (expected.paymentId === void 0 || sameUUID(raw.id, expected.paymentId)) && (expected.wixTransactionId === void 0 || sameUUID(raw.wixTransactionId, expected.wixTransactionId));
1042
+ }
1043
+ function hasValidOptionals(raw) {
1044
+ return (raw.appProductId === void 0 || isStoreProductId(raw.appProductId)) && (raw.purchaseTransactionId === void 0 || isUUID(raw.purchaseTransactionId)) && TIMESTAMPS.every((field) => raw[field] === void 0 || isTimestamp(raw[field]));
1045
+ }
1046
+ function toPayment(raw, status) {
1047
+ const optional = {
1048
+ appProductId: raw.appProductId,
1049
+ cancelReason: ownValue(CANCEL_REASONS, raw.cancelReason),
1050
+ purchaseTransactionId: raw.purchaseTransactionId,
1051
+ expiresDate: raw.expiresDate,
1052
+ approvedDate: raw.approvedDate,
1053
+ canceledDate: raw.canceledDate,
1054
+ refundedDate: raw.refundedDate
1055
+ };
1056
+ const ids = { paymentId: raw.id, appId: raw.appId, memberId: raw.memberId, wixTransactionId: raw.wixTransactionId };
1057
+ return { ...ids, status, ...withoutUndefined(optional) };
1058
+ }
1059
+ function classifyFailure(error, operation, codes) {
1060
+ const message = messageOf(error);
1061
+ if (BRIDGE_REFUSAL.test(message)) return failure(operation, "notEnabled");
1062
+ if (PRINCIPAL_CHANGED.test(message)) return failure(operation, "sessionChanged");
1063
+ const http = /^HTTP (\d{3})(?: \[([^\]]+)\])?:/.exec(message);
1064
+ if (!http) return failure(operation, "unavailable");
1065
+ return classifyHttp({ operation, codes, httpStatus: Number(http[1]), code: http[2] ?? "" });
1066
+ }
1067
+ function failure(operation, kind) {
1068
+ return { status: "failed", operation, kind };
1069
+ }
1070
+ function classifyHttp(refusal) {
1071
+ const { operation, codes, httpStatus, code } = refusal;
1072
+ if (code === "PRINCIPAL_CHANGED") return failure(operation, "sessionChanged");
1073
+ if (isOneOf(codes, code)) return { status: "failed", operation, kind: "application", code, httpStatus };
1074
+ return { status: "failed", operation, kind: kindForStatus(httpStatus, code), httpStatus };
1075
+ }
1076
+ function kindForStatus(httpStatus, code) {
1077
+ if (code === "UNAVAILABLE" || httpStatus === 408 || httpStatus === 429 || httpStatus >= 500) return "unavailable";
1078
+ if (httpStatus === 401 || code === "UNAUTHENTICATED") return "authRequired";
1079
+ if (httpStatus === 403 || code === "PERMISSION_DENIED") return "notPermitted";
1080
+ return "unrecognized";
1081
+ }
1082
+ function post(scope, route, body) {
1083
+ return { method: "POST", path: `${scope.prefix}${route}`, body, headers: siteHeaders(scope.binding) };
1084
+ }
1085
+ function get2(scope, route) {
1086
+ return { method: "GET", path: `${scope.prefix}${route}`, headers: siteHeaders(scope.binding) };
1087
+ }
1088
+ function siteHeaders(binding) {
1089
+ return { "wix-site-id": binding.siteId };
1090
+ }
1091
+ function messageOf(error) {
1092
+ const message = error?.message;
1093
+ return typeof message === "string" ? message : "";
1094
+ }
1095
+ function withoutUndefined(value) {
1096
+ const kept = {};
1097
+ for (const key of Object.keys(value)) {
1098
+ if (value[key] !== void 0) kept[key] = value[key];
1099
+ }
1100
+ return kept;
1101
+ }
1102
+ function isOneOf(codes, code) {
1103
+ return codes.includes(code);
1104
+ }
1105
+ function ownValue(table, key) {
1106
+ return typeof key === "string" && Object.prototype.hasOwnProperty.call(table, key) ? table[key] : void 0;
1107
+ }
1108
+ function isObject3(value) {
1109
+ return value !== null && typeof value === "object" && !Array.isArray(value);
1110
+ }
1111
+ function isUUID(value) {
1112
+ return typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
1113
+ }
1114
+ function sameUUID(value, expected) {
1115
+ return isUUID(value) && value.toLowerCase() === expected.toLowerCase();
1116
+ }
1117
+ function isStoreProductId(value) {
1118
+ return typeof value === "string" && value.length > 0 && value.length <= 255;
1119
+ }
1120
+ function isTimestamp(value) {
1121
+ return typeof value === "string" && !Number.isNaN(Date.parse(value));
1122
+ }
1123
+ var STATUSES = {
1124
+ PENDING: "pending",
1125
+ APPROVING: "approving",
1126
+ APPROVED: "approved",
1127
+ CANCELING: "canceling",
1128
+ CANCELED: "canceled",
1129
+ REFUNDING: "refunding",
1130
+ REFUNDED: "refunded"
1131
+ };
1132
+ var CANCEL_REASONS = { EXPIRED: "expired", REJECTED: "rejected" };
1133
+ var TIMESTAMPS = ["createdDate", "updatedDate", "expiresDate", "approvedDate", "canceledDate", "refundedDate"];
1134
+ var BRIDGE_REFUSAL = /^(wixApi not enabled|capability wix_api not allowed)\b|^NotInstalled\(\)$/;
1135
+ var PRINCIPAL_CHANGED = /^PRINCIPAL_CHANGED\b/;
1136
+
1137
+ // ../../core/sdk/iap/src/wix-payments.ts
1138
+ function createWixIapClient(deps) {
1139
+ function startPayment(input) {
1140
+ if (!isUUID(input.wixTransactionId)) return Promise.resolve(failure("startPayment", "invalidArgument"));
1141
+ return run({
1142
+ operation: "startPayment",
1143
+ codes: START_PAYMENT_CODES,
1144
+ request: (scope) => startPaymentCall(scope, input.wixTransactionId),
1145
+ decode: (raw, scope) => {
1146
+ const started = decodeStarted(raw, { ...expectationOf2(scope), wixTransactionId: input.wixTransactionId });
1147
+ return started && { status: "started", ...started };
1148
+ }
1149
+ });
1150
+ }
1151
+ function completePayment(transaction) {
1152
+ const refusal = refuseProof(transaction);
1153
+ if (refusal) return Promise.resolve(refusal);
1154
+ return run({
1155
+ operation: "completePayment",
1156
+ codes: COMPLETE_PAYMENT_CODES,
1157
+ request: (scope) => completePaymentCall(scope, transaction.signedTransaction),
1158
+ decode: (raw, scope) => {
1159
+ const payment = decodePaymentAnswer(raw, expectationOf2(scope));
1160
+ return payment && { status: "matched", payment };
1161
+ }
1162
+ });
1163
+ }
1164
+ function getPayment(input) {
1165
+ if (!isUUID(input.paymentId)) return Promise.resolve(failure("getPayment", "invalidArgument"));
1166
+ return run({
1167
+ operation: "getPayment",
1168
+ codes: GET_PAYMENT_CODES,
1169
+ request: (scope) => paymentCall(scope, input.paymentId),
1170
+ decode: (raw, scope) => {
1171
+ const payment = decodePaymentAnswer(raw, { ...expectationOf2(scope), paymentId: input.paymentId });
1172
+ return payment && { status: "found", payment };
1173
+ }
1174
+ });
1175
+ }
1176
+ async function run(spec) {
1177
+ const scope = await resolveScope(deps.session.current(), spec.operation);
1178
+ if ("failure" in scope) return scope.failure;
1179
+ const sent = await send(scope, spec);
1180
+ if ("failure" in sent) return sent.failure;
1181
+ return spec.decode(sent.answer, scope) ?? failure(spec.operation, "invalidResponse");
1182
+ }
1183
+ async function resolveScope(session, operation) {
1184
+ if (session.kind !== "member") return refused(operation, "authRequired");
1185
+ if (!isRoutePrefix(deps.route.prefix)) return refused(operation, "notProvisioned");
1186
+ const binding = await read(() => deps.binding.current(), operation);
1187
+ if ("failure" in binding) return binding;
1188
+ if (!binding.value || !isBindingFor(binding.value, deps.host)) return refused(operation, "notProvisioned");
1189
+ const member = await expectedMember(session, operation);
1190
+ if ("failure" in member) return member;
1191
+ return { session, binding: binding.value, prefix: deps.route.prefix, memberId: member.memberId };
1192
+ }
1193
+ async function expectedMember(session, operation) {
1194
+ const identity = deps.identity;
1195
+ if (!identity) return { memberId: null };
1196
+ const memberId = await read(() => identity.memberId(session), operation);
1197
+ if ("failure" in memberId) return memberId;
1198
+ return memberId.value ? { memberId: memberId.value } : refused(operation, "authRequired");
1199
+ }
1200
+ async function send(scope, spec) {
1201
+ const transport = deps.transport ?? bridgeTransport();
1202
+ if (!transport) return refused(spec.operation, "notEnabled");
1203
+ if (!isCurrent(scope.session)) return refused(spec.operation, "sessionChanged");
1204
+ const expectation = boundExpectation2(scope.session, deps.transport == null);
1205
+ if (expectation === "refuse") return refused(spec.operation, "notEnabled");
1206
+ const outcome = await attempt(transport, spec.request(scope), spec, expectation);
1207
+ return isCurrent(scope.session) ? outcome : refused(spec.operation, "sessionChanged");
1208
+ }
1209
+ function boundExpectation2(session, liveHost) {
1210
+ const source = deps.session;
1211
+ if (liveHost && (source.identityBound !== true || !readIdentityBound())) return "refuse";
1212
+ if (typeof source.identity !== "function") return liveHost ? "refuse" : void 0;
1213
+ return source.identity(session) ?? "refuse";
1214
+ }
1215
+ function isCurrent(session) {
1216
+ return deps.session.current().generation === session.generation;
1217
+ }
1218
+ return { startPayment, completePayment, getPayment };
1219
+ }
1220
+ async function attempt(transport, call, spec, expectation) {
1221
+ try {
1222
+ const answer = expectation ? await transport.call(call.method, call.path, call.body, call.headers, expectation) : await transport.call(call.method, call.path, call.body, call.headers);
1223
+ return { answer };
1224
+ } catch (error) {
1225
+ return { failure: classifyFailure(error, spec.operation, spec.codes) };
1226
+ }
1227
+ }
1228
+ async function read(call, operation) {
1229
+ try {
1230
+ return { value: await call() };
1231
+ } catch (error) {
1232
+ return { failure: classifyFailure(error, operation, []) };
1233
+ }
1234
+ }
1235
+ function refused(operation, kind) {
1236
+ return { failure: failure(operation, kind) };
1237
+ }
1238
+ function expectationOf2(scope) {
1239
+ return { appId: scope.binding.purchasesAppId, memberId: scope.memberId };
1240
+ }
1241
+ function refuseProof(transaction) {
1242
+ if (transaction.environment !== "production" && transaction.environment !== "sandbox") return failure("completePayment", "environmentUnsupported");
1243
+ const signed = transaction.signedTransaction;
1244
+ return typeof signed === "string" && signed.length > 0 && signed.length <= MAX_SIGNED_TRANSACTION ? null : failure("completePayment", "invalidArgument");
1245
+ }
1246
+ function isBindingFor(binding, host) {
1247
+ return binding.himalayaAppId === host.appId && binding.bundleId === host.bundleId && binding.siteId === host.siteId;
1248
+ }
1249
+ function bridgeTransport() {
1250
+ const himalaya = globalThis.himalaya;
1251
+ const bridge = himalaya ? himalaya.wixApi : void 0;
1252
+ return typeof bridge?.call === "function" ? bridge : void 0;
1253
+ }
1254
+ var MAX_SIGNED_TRANSACTION = 2e4;
1255
+ var START_PAYMENT_CODES = [
1256
+ "NOT_PENDING",
1257
+ "WRONG_PAYMENT_METHOD",
1258
+ "NOT_ORDER_BUYER",
1259
+ "UNSUPPORTED_ORDER",
1260
+ "PRODUCT_NOT_AVAILABLE",
1261
+ "ALREADY_OWNED"
1262
+ ];
1263
+ var COMPLETE_PAYMENT_CODES = [
1264
+ "INVALID_PURCHASE",
1265
+ "OWNED_BY_ANOTHER_CUSTOMER",
1266
+ "PURCHASE_REVOKED",
1267
+ "NOT_PURCHASED",
1268
+ "ZERO_PRICE",
1269
+ "NO_MATCHING_PAYMENT",
1270
+ "PAYMENT_NOT_PENDING",
1271
+ "APP_NOT_CONFIGURED"
1272
+ ];
1273
+ var GET_PAYMENT_CODES = ["NOT_FOUND"];
1274
+
540
1275
  // ../../core/sdk/iap/src/index.ts
1276
+ async function getProducts(productIds) {
1277
+ if (!productIds || productIds.length === 0) return [];
1278
+ const r = await dispatch("capability.iap.getProducts", {
1279
+ // Product ids are reverse-DNS-ish and never contain commas — comma-join
1280
+ // matches the @himalaya/push list-param convention.
1281
+ productIds: productIds.join(",")
1282
+ });
1283
+ return Array.isArray(r?.products) ? r.products : [];
1284
+ }
541
1285
  async function purchaseForVerification(input) {
542
- if (!nonempty(input?.productId) || !isUUID2(input?.appAccountToken)) return failure2("invalidArgument");
1286
+ if (!nonempty2(input?.productId) || !isUUID2(input?.appAccountToken)) return failure2("invalidArgument");
543
1287
  const result = await managedDispatch(() => dispatch("capability.iap.purchaseForVerification", input));
544
1288
  if (result?.status === "purchased" && isAppleTransaction(result.transaction)) {
545
1289
  return { status: "purchased", transaction: decodeTransaction(result.transaction) };
@@ -555,21 +1299,57 @@ async function getUnfinishedTransactions() {
555
1299
  return decodeFailure(result);
556
1300
  }
557
1301
  async function finishTransaction(input) {
558
- if (!nonempty(input?.transactionId)) return failure2("invalidArgument");
1302
+ if (!nonempty2(input?.transactionId)) return failure2("invalidArgument");
559
1303
  const result = await managedDispatch(() => dispatch("capability.iap.finishTransaction", input));
560
1304
  if (result?.status === "finished" || result?.status === "notFound") return { status: result.status };
561
1305
  return decodeFailure(result);
562
1306
  }
563
1307
  var appleManagedStore = { purchaseForVerification, getUnfinishedTransactions, finishTransaction };
1308
+ function hostAppBindingSource() {
1309
+ let read2;
1310
+ return {
1311
+ current: () => read2 ?? (read2 = readHostBinding().catch((error) => {
1312
+ read2 = void 0;
1313
+ throw error;
1314
+ }))
1315
+ };
1316
+ }
1317
+ async function readHostBinding() {
1318
+ let answer;
1319
+ try {
1320
+ answer = await dispatch("capability.iap.appBinding");
1321
+ } catch (error) {
1322
+ if (bindingNotOffered(error)) return null;
1323
+ throw new Error("the host could not read the app binding");
1324
+ }
1325
+ if (!isObject4(answer)) throw new Error("the host could not read the app binding");
1326
+ if (answer.status === "bound") return decodeBinding(answer.binding);
1327
+ if (answer.status === "unbound" || answer.status === "failed" && answer.code === "unsupported") return null;
1328
+ throw new Error("the host could not read the app binding");
1329
+ }
1330
+ function bindingNotOffered(error) {
1331
+ const message = error instanceof Error ? error.message : String(error);
1332
+ return /(unknown|no capability handler for|needs a fixture for)\W[^\n]{0,20}capability\.iap\.appBinding|capability iap not allowed/i.test(message);
1333
+ }
1334
+ var shared;
1335
+ function sharedHostAppBindingSource() {
1336
+ return shared ?? (shared = hostAppBindingSource());
1337
+ }
1338
+ function decodeBinding(raw) {
1339
+ if (!isObject4(raw)) return null;
1340
+ const { purchasesAppId, himalayaAppId, bundleId, siteId } = raw;
1341
+ if (!isUUID2(purchasesAppId) || !isUUID2(siteId) || !nonempty2(himalayaAppId) || !nonempty2(bundleId)) return null;
1342
+ return { purchasesAppId, himalayaAppId, bundleId, siteId };
1343
+ }
564
1344
  var transactionErrors = /* @__PURE__ */ new Set(["unsupported", "unavailable", "invalidArgument", "invalidResponse", "notEnabled", "unsupportedProductType", "unknownProduct", "verificationFailed", "persistenceFailed", "ownershipConflict", "storeError", "busy"]);
565
1345
  var failure2 = (code) => ({ status: "failed", code });
566
- var nonempty = (value) => typeof value === "string" && value.trim().length > 0;
1346
+ var nonempty2 = (value) => typeof value === "string" && value.trim().length > 0;
567
1347
  var isUUID2 = (value) => typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value) && value.length === 36;
568
- var isObject2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
1348
+ var isObject4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
569
1349
  async function managedDispatch(invoke) {
570
1350
  try {
571
1351
  const value = await invoke();
572
- return isObject2(value) ? value : null;
1352
+ return isObject4(value) ? value : null;
573
1353
  } catch {
574
1354
  return failure2("unavailable");
575
1355
  }
@@ -578,14 +1358,26 @@ function decodeFailure(value) {
578
1358
  return value?.status === "failed" && transactionErrors.has(value.code) ? failure2(value.code) : failure2("invalidResponse");
579
1359
  }
580
1360
  function isAppleTransaction(value) {
581
- if (!isObject2(value)) return false;
582
- return value.store === "apple" && typeof value.signedTransaction === "string" && /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(value.signedTransaction) && nonempty(value.transactionId) && nonempty(value.originalTransactionId) && nonempty(value.productId) && (value.appAccountToken === null || isUUID2(value.appAccountToken)) && ["production", "sandbox", "xcode", "unknown"].includes(value.environment);
1361
+ if (!isObject4(value)) return false;
1362
+ return value.store === "apple" && typeof value.signedTransaction === "string" && /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(value.signedTransaction) && nonempty2(value.transactionId) && nonempty2(value.originalTransactionId) && nonempty2(value.productId) && (value.appAccountToken === null || isUUID2(value.appAccountToken)) && ["production", "sandbox", "xcode", "unknown"].includes(value.environment);
583
1363
  }
584
1364
  function decodeTransaction(value) {
585
1365
  const { store, signedTransaction, transactionId, originalTransactionId, productId, appAccountToken, environment } = value;
586
1366
  return { store, signedTransaction, transactionId, originalTransactionId, productId, appAccountToken, environment };
587
1367
  }
588
1368
 
1369
+ // ../../stdlib/flows/iap-checkout/src/checkout-source.ts
1370
+ var HIMALAYA_SERVE_CHECKOUT_ROUTES = {
1371
+ wixIap: HIMALAYA_SERVE_IAP_ROUTE,
1372
+ cashier: { prefix: HIMALAYA_SERVE_IAP_ROUTE.prefix }
1373
+ };
1374
+ function appleIapCheckoutRoutes() {
1375
+ return HIMALAYA_SERVE_CHECKOUT_ROUTES;
1376
+ }
1377
+ function appleIapCheckoutEnabled() {
1378
+ return appleIapCheckoutRoutes() !== null;
1379
+ }
1380
+
589
1381
  // ../../stdlib/flows/iap-checkout/src/cashier-charges.ts
590
1382
  async function ensureAppleIapCharge(bridge, route, orderId) {
591
1383
  if (!isRoutePrefix2(route.prefix)) return { status: "notConfigured" };
@@ -622,22 +1414,22 @@ function decideFromCharges(charges) {
622
1414
  return isAwaitingApple(apple) ? { status: "pending", transactionId: apple.transactionId } : { status: "invalidResponse" };
623
1415
  }
624
1416
  function chargedFrom(body) {
625
- const charge = isObject3(body) ? decodeCharge(body.charge) : null;
1417
+ const charge = isObject5(body) ? decodeCharge(body.charge) : null;
626
1418
  return charge && isAwaitingApple(charge) ? { status: "pending", transactionId: charge.transactionId } : null;
627
1419
  }
628
1420
  function isAwaitingApple(charge) {
629
1421
  return charge.paymentMethod === APPLE_IAP && AWAITING_PAYMENT.has(charge.status);
630
1422
  }
631
1423
  function decodeCharges(body) {
632
- if (!isObject3(body)) return null;
1424
+ if (!isObject5(body)) return null;
633
1425
  const raw = body.charges ?? [];
634
1426
  if (!Array.isArray(raw)) return null;
635
1427
  const charges = raw.map(decodeCharge);
636
1428
  return charges.every((charge) => charge !== null) ? charges : null;
637
1429
  }
638
1430
  function decodeCharge(raw) {
639
- if (!isObject3(raw) || !isNonEmpty2(raw.chargeId) || !isNonEmpty2(raw.transactionId)) return null;
640
- const state = isObject3(raw.state) && isObject3(raw.state.transactionStatus) ? raw.state.transactionStatus : {};
1431
+ if (!isObject5(raw) || !isNonEmpty2(raw.chargeId) || !isNonEmpty2(raw.transactionId)) return null;
1432
+ const state = isObject5(raw.state) && isObject5(raw.state.transactionStatus) ? raw.state.transactionStatus : {};
641
1433
  const method = isNonEmpty2(raw.paymentMethodId) ? raw.paymentMethodId : isNonEmpty2(raw.paymentMethod) ? raw.paymentMethod : "";
642
1434
  return { chargeId: raw.chargeId, transactionId: raw.transactionId, status: isNonEmpty2(state.status) ? state.status : "UNDEFINED", paymentMethod: method };
643
1435
  }
@@ -650,7 +1442,7 @@ function chargesPath(route, orderId) {
650
1442
  function isRoutePrefix2(prefix) {
651
1443
  return /^\/[A-Za-z0-9._~\-/]*[A-Za-z0-9._~-]$/.test(prefix);
652
1444
  }
653
- function isObject3(value) {
1445
+ function isObject5(value) {
654
1446
  return value !== null && typeof value === "object" && !Array.isArray(value);
655
1447
  }
656
1448
  function isNonEmpty2(value) {
@@ -749,7 +1541,7 @@ function readVersioned(store, location) {
749
1541
  if (raw === void 0) return null;
750
1542
  if (raw === null || raw === "") return "empty";
751
1543
  const parsed = safely(() => JSON.parse(raw));
752
- return isObject4(parsed) && parsed.v === VERSION ? parsed : null;
1544
+ return isObject6(parsed) && parsed.v === VERSION ? parsed : null;
753
1545
  }
754
1546
  function writeVerified(store, location, value) {
755
1547
  if (!store) return false;
@@ -759,7 +1551,7 @@ function writeVerified(store, location, value) {
759
1551
  }) === true;
760
1552
  }
761
1553
  function isOrderRef(value) {
762
- if (!isObject4(value) || typeof value.key !== "string" || !STAGES.has(value.stage)) return false;
1554
+ if (!isObject6(value) || typeof value.key !== "string" || !STAGES.has(value.stage)) return false;
763
1555
  if (typeof value.updatedAt !== "number") return false;
764
1556
  const optional = ["kind", "cashierOrderId", "wixTransactionId", "paymentId", "storeProductId", "appProductId", "appleTransactionId", "appAccountToken"];
765
1557
  if (!optional.every((field) => value[field] === void 0 || typeof value[field] === "string")) return false;
@@ -794,9 +1586,9 @@ function hostStorage() {
794
1586
  const storage = globalThis.himalaya?.storage;
795
1587
  return typeof storage?.getItem === "function" && typeof storage.setItem === "function" ? storage : void 0;
796
1588
  }
797
- function safely(read) {
1589
+ function safely(read2) {
798
1590
  try {
799
- return read();
1591
+ return read2();
800
1592
  } catch {
801
1593
  return void 0;
802
1594
  }
@@ -805,9 +1597,9 @@ function serialize(value) {
805
1597
  return JSON.stringify(value);
806
1598
  }
807
1599
  function isStringMap(value) {
808
- return isObject4(value) && Object.values(value).every((entry) => typeof entry === "string");
1600
+ return isObject6(value) && Object.values(value).every((entry) => typeof entry === "string");
809
1601
  }
810
- function isObject4(value) {
1602
+ function isObject6(value) {
811
1603
  return value !== null && typeof value === "object" && !Array.isArray(value);
812
1604
  }
813
1605
  function isUUID3(value) {
@@ -826,7 +1618,7 @@ function bindBridge(session, provider, bridge) {
826
1618
  if (!isCurrent()) return SESSION_CHANGED;
827
1619
  const expectation = boundExpectation(session, provider, bridge);
828
1620
  if (expectation === "refuse") return { status: "notEnabled" };
829
- const outcome = await attempt(bridge, method, path, body, expectation);
1621
+ const outcome = await attempt2(bridge, method, path, body, expectation);
830
1622
  return isCurrent() ? outcome : SESSION_CHANGED;
831
1623
  }
832
1624
  return { call, isCurrent };
@@ -837,7 +1629,7 @@ function hostBridge() {
837
1629
  return typeof bridge?.call === "function" ? bridge : void 0;
838
1630
  }
839
1631
  var MISSING_BRIDGE = { call: () => Promise.reject(new Error("wixApi not enabled")) };
840
- async function attempt(bridge, method, path, body, expectation) {
1632
+ async function attempt2(bridge, method, path, body, expectation) {
841
1633
  try {
842
1634
  const answer = expectation ? await bridge.call(method, path, body, void 0, expectation) : await bridge.call(method, path, body);
843
1635
  return { status: "ok", body: answer };
@@ -859,8 +1651,8 @@ function isLiveHost(bridge) {
859
1651
  function refusalOf(error) {
860
1652
  const message = error?.message;
861
1653
  const text = typeof message === "string" ? message : "";
862
- if (BRIDGE_REFUSAL.test(text)) return { status: "notEnabled" };
863
- if (PRINCIPAL_CHANGED.test(text)) return SESSION_CHANGED;
1654
+ if (BRIDGE_REFUSAL2.test(text)) return { status: "notEnabled" };
1655
+ if (PRINCIPAL_CHANGED2.test(text)) return SESSION_CHANGED;
864
1656
  const http = /^HTTP (\d{3})(?: \[([^\]]+)\])?:/.exec(text);
865
1657
  if (!http) return { status: "unavailable" };
866
1658
  return httpRefusal(Number(http[1]), http[2] ?? "");
@@ -871,8 +1663,8 @@ function httpRefusal(httpStatus, code) {
871
1663
  return { status: "http", httpStatus, code };
872
1664
  }
873
1665
  var SESSION_CHANGED = { status: "sessionChanged" };
874
- var BRIDGE_REFUSAL = /^(wixApi not enabled|capability wix_api not allowed)\b|^NotInstalled\(\)$/;
875
- var PRINCIPAL_CHANGED = /^PRINCIPAL_CHANGED\b/;
1666
+ var BRIDGE_REFUSAL2 = /^(wixApi not enabled|capability wix_api not allowed)\b|^NotInstalled\(\)$/;
1667
+ var PRINCIPAL_CHANGED2 = /^PRINCIPAL_CHANGED\b/;
876
1668
 
877
1669
  // ../../stdlib/flows/iap-checkout/src/iap-order-backend.ts
878
1670
  function createWixOrderBackend(deps) {
@@ -934,26 +1726,26 @@ function createWixOrderBackend(deps) {
934
1726
  if (existing?.stage === "held") return stopWith("rejected", "paymentHeld");
935
1727
  if (existing?.stage === "needsSupport") return stopWith("rejected", "needsSupport");
936
1728
  if (deps.productBusy?.(sale.appleProduct.productId)) return stopWith("rejected", "paymentInProgress");
937
- const attempt2 = existing?.cashierOrderId && existing.verticalRef ? await reopenOrOpen(sale, { cashierOrderId: existing.cashierOrderId, verticalRef: existing.verticalRef }) : await sale.adapter.openOrder(sale.item, sale.bridge);
938
- return recordOrder(sale, existing, attempt2);
1729
+ const attempt3 = existing?.cashierOrderId && existing.verticalRef ? await reopenOrOpen(sale, { cashierOrderId: existing.cashierOrderId, verticalRef: existing.verticalRef }) : await sale.adapter.openOrder(sale.item, sale.bridge);
1730
+ return recordOrder(sale, existing, attempt3);
939
1731
  }
940
1732
  async function reopenOrOpen(sale, order) {
941
1733
  const reopened = await sale.adapter.reopenOrder(order, sale.bridge);
942
1734
  const closed = reopened.status === "refused" && reopened.reason === "orderClosed";
943
1735
  return closed ? sale.adapter.openOrder(sale.item, sale.bridge) : reopened;
944
1736
  }
945
- function recordOrder(sale, existing, attempt2) {
946
- if (attempt2.status === "granted") return alreadyOwned(sale);
947
- if (attempt2.status === "refused") return stopWith("rejected", attempt2.reason);
948
- if (attempt2.status !== "open") return attempt2.status === "sessionChanged" ? STALE2 : retry("unavailable");
949
- const kept = existing && existing.cashierOrderId === attempt2.cashierOrderId ? existing : { key: sale.catalogRef, updatedAt: 0 };
1737
+ function recordOrder(sale, existing, attempt3) {
1738
+ if (attempt3.status === "granted") return alreadyOwned(sale);
1739
+ if (attempt3.status === "refused") return stopWith("rejected", attempt3.reason);
1740
+ if (attempt3.status !== "open") return attempt3.status === "sessionChanged" ? STALE2 : retry("unavailable");
1741
+ const kept = existing && existing.cashierOrderId === attempt3.cashierOrderId ? existing : { key: sale.catalogRef, updatedAt: 0 };
950
1742
  return persist(sale, {
951
1743
  ...kept,
952
1744
  key: sale.catalogRef,
953
1745
  stage: "ordered",
954
1746
  kind: sale.adapter.kind,
955
- verticalRef: attempt2.verticalRef,
956
- cashierOrderId: attempt2.cashierOrderId,
1747
+ verticalRef: attempt3.verticalRef,
1748
+ cashierOrderId: attempt3.cashierOrderId,
957
1749
  updatedAt: now()
958
1750
  });
959
1751
  }
@@ -1194,6 +1986,8 @@ function enabledCheckout(deps) {
1194
1986
  const bridge = deps.bridge ?? hostBridge() ?? MISSING_BRIDGE;
1195
1987
  const sales = /* @__PURE__ */ new Map();
1196
1988
  const payments = /* @__PURE__ */ new Map();
1989
+ const readGrants = /* @__PURE__ */ new Set();
1990
+ const accessReads = /* @__PURE__ */ new Map();
1197
1991
  let current = { item: null, failure: null, buying: false };
1198
1992
  let generation = deps.session.current().generation;
1199
1993
  let disposed = false;
@@ -1229,6 +2023,28 @@ function enabledCheckout(deps) {
1229
2023
  await trackPayments({ dueOnly: false });
1230
2024
  return state();
1231
2025
  }
2026
+ async function checkAccess(items) {
2027
+ resetIfSessionChanged();
2028
+ const session = deps.session.current();
2029
+ if (session.kind !== "member") return state();
2030
+ for (const item of items) {
2031
+ const key = itemKey(item);
2032
+ const adapter = deps.adapters.find((candidate) => candidate.kind === item.reference.kind);
2033
+ if (!adapter?.currentAccess || payments.has(key) && payments.get(key).access !== "granted" && !readGrants.has(key)) continue;
2034
+ const seq = (accessReads.get(key) ?? 0) + 1;
2035
+ accessReads.set(key, seq);
2036
+ const access = await adapter.currentAccess(item, bindBridge(session, deps.session, bridge)).catch(() => "unavailable");
2037
+ if (deps.session.current().generation !== session.generation) break;
2038
+ if (accessReads.get(key) !== seq) continue;
2039
+ if (access === "granted") {
2040
+ setPayment(key, "granted");
2041
+ readGrants.add(key);
2042
+ } else if (access === "none" && readGrants.delete(key)) {
2043
+ payments.delete(key);
2044
+ }
2045
+ }
2046
+ return publishAndReturn();
2047
+ }
1232
2048
  async function buy(item) {
1233
2049
  resetIfSessionChanged();
1234
2050
  const key = itemKey(item);
@@ -1287,6 +2103,7 @@ function enabledCheckout(deps) {
1287
2103
  const access = owned ? "granted" : event.access;
1288
2104
  const failure3 = owned ? void 0 : event.failure;
1289
2105
  if (access) setPayment(event.key, access);
2106
+ if (owned) readGrants.add(event.key);
1290
2107
  if (labelOf(event.key) === current.item && (failure3 || access)) current.failure = failure3 ?? failureOfAccess(access);
1291
2108
  }
1292
2109
  function setPayment(key, access) {
@@ -1323,6 +2140,7 @@ function enabledCheckout(deps) {
1323
2140
  generation = next;
1324
2141
  sales.clear();
1325
2142
  payments.clear();
2143
+ readGrants.clear();
1326
2144
  awaitingApproval.clear();
1327
2145
  partitionRead = null;
1328
2146
  current = { item: null, failure: null, buying: false };
@@ -1392,10 +2210,10 @@ function enabledCheckout(deps) {
1392
2210
  return readDue || [...payments.values()].some((payment) => payment.access === "processing" && isDue(payment.key, true));
1393
2211
  }
1394
2212
  async function trackOne(session, partition, ref) {
1395
- const read = await deps.wixIap.getPayment({ paymentId: ref.paymentId ?? "" });
2213
+ const read2 = await deps.wixIap.getPayment({ paymentId: ref.paymentId ?? "" });
1396
2214
  if (!isCurrent(session)) return;
1397
- if (read.status !== "found") return read.kind === "application" ? markNeedsSupport(partition, ref) : backOff(partition, ref, false);
1398
- await settlePayment(session, partition, ref, read.payment);
2215
+ if (read2.status !== "found") return read2.kind === "application" ? markNeedsSupport(partition, ref) : backOff(partition, ref, false);
2216
+ await settlePayment(session, partition, ref, read2.payment);
1399
2217
  }
1400
2218
  async function settlePayment(session, partition, ref, payment) {
1401
2219
  if (isFinalRefusal(payment.status)) return markNeedsSupport(partition, ref);
@@ -1446,12 +2264,15 @@ function enabledCheckout(deps) {
1446
2264
  function isCurrent(session) {
1447
2265
  return !disposed && deps.session.current().generation === session.generation;
1448
2266
  }
1449
- return { start, buy, reconcile: reconcile2, retry: retry2, tick, state, dispose };
2267
+ return { start, buy, checkAccess, reconcile: reconcile2, retry: retry2, tick, state, dispose };
2268
+ }
2269
+ function notEnabledState() {
2270
+ return blankState(false);
1450
2271
  }
1451
2272
  function disabledCheckout() {
1452
2273
  const state = () => blankState(false);
1453
2274
  const resolved = () => Promise.resolve(state());
1454
- return { start: resolved, buy: resolved, reconcile: resolved, retry: resolved, tick: resolved, state, dispose: () => {
2275
+ return { start: resolved, buy: resolved, checkAccess: resolved, reconcile: resolved, retry: resolved, tick: resolved, state, dispose: () => {
1455
2276
  } };
1456
2277
  }
1457
2278
  function blankState(enabled) {
@@ -1499,6 +2320,307 @@ function failureOfAccess(access) {
1499
2320
  var BASE_DELAY_MS = 1e3;
1500
2321
  var OVERLAY_PHASES = /* @__PURE__ */ new Set(["purchasing", "awaitingApproval", "cancelled", "signInRequired", "unavailable"]);
1501
2322
 
2323
+ // ../../stdlib/flows/iap-checkout/src/purchase-fields.ts
2324
+ function iapPurchaseFields(view, state, readiness, copy) {
2325
+ const key = `${view.reference.kind}:${view.reference.id}`;
2326
+ if (view.route !== "appleIap" && !holdsSale(state, key)) return { ...action(copy, "enabled", ""), appleRoute: false };
2327
+ if (readiness.status !== "ready") return action(copy, "disabled", readiness.status === "checking" ? "" : copy.unavailable);
2328
+ const own = state.item === key;
2329
+ const payment = state.payments.find((tracked) => tracked.item === key)?.access;
2330
+ if (own && state.phase === "accessReady" || payment === "granted") return { ...action(copy, "disabled", ""), accessReady: true };
2331
+ if (IN_FLIGHT.has(state.phase)) return action(copy, "busy", own ? copy.processing : "");
2332
+ if (own) return outcomeAction(state, copy);
2333
+ if (payment === "processing") return action(copy, "busy", copy.processing);
2334
+ if (payment === "needsSupport") return action(copy, "disabled", copy.support);
2335
+ return action(copy, "enabled", "");
2336
+ }
2337
+ function holdsSale(state, key) {
2338
+ if (state.payments.some((tracked) => tracked.item === key)) return true;
2339
+ return state.item === key && (SALE_PHASES.has(state.phase) || state.purchase.phase === "awaitingApproval");
2340
+ }
2341
+ function outcomeAction(state, copy) {
2342
+ if (state.purchase.phase === "awaitingApproval") return action(copy, "disabled", copy.awaitingApproval);
2343
+ switch (state.phase) {
2344
+ case "awaitingApproval":
2345
+ return action(copy, "disabled", copy.awaitingApproval);
2346
+ case "signInRequired":
2347
+ return action(copy, "disabled", copy.signInRequired);
2348
+ case "unavailable":
2349
+ return action(copy, "enabled", copy.retry);
2350
+ case "refused":
2351
+ return refusalAction(state.failure, copy);
2352
+ case "notEnabled":
2353
+ return action(copy, "disabled", copy.unavailable);
2354
+ default:
2355
+ return action(copy, "enabled", "");
2356
+ }
2357
+ }
2358
+ function refusalAction(failure3, copy) {
2359
+ const [mode, note] = REFUSALS[failure3 ?? "unavailable"] ?? ["enabled", "retry"];
2360
+ return action(copy, mode, note ? copy[note] : "");
2361
+ }
2362
+ function action(copy, mode, note) {
2363
+ return { appleRoute: true, accessReady: false, buyLabel: copy.buy, buyDisabled: mode !== "enabled", buyBusy: mode === "busy", buyNote: note };
2364
+ }
2365
+ var IN_FLIGHT = /* @__PURE__ */ new Set(["preparing", "purchasing", "processing"]);
2366
+ var SALE_PHASES = /* @__PURE__ */ new Set([...IN_FLIGHT, "awaitingApproval", "accessReady"]);
2367
+ var REFUSALS = {
2368
+ productChanged: ["enabled", "priceChanged"],
2369
+ paymentHeld: ["disabled", "support"],
2370
+ needsSupport: ["disabled", "support"],
2371
+ invalidAssociation: ["disabled", "support"],
2372
+ // Nothing in the checkout clears this, so the action stays tappable: a tap re-reads the order
2373
+ // (never a second charge) and turns into access once the vertical grants it.
2374
+ paymentInProgress: ["enabled", "processing"],
2375
+ approvalRequired: ["disabled", "awaitingApproval"],
2376
+ signInRequired: ["disabled", "signInRequired"],
2377
+ notConfigured: ["disabled", "unavailable"],
2378
+ notEnabled: ["disabled", "unavailable"],
2379
+ storageUnavailable: ["disabled", "unavailable"],
2380
+ unsupportedItem: ["disabled", "unavailable"],
2381
+ // The action shows only on an App Store route, so a refusal for any other route is stale.
2382
+ notAppleRoute: ["enabled", null]
2383
+ };
2384
+
2385
+ // ../../stdlib/flows/iap-checkout/src/commerce-core.ts
2386
+ function createIapCommerceWith(deps) {
2387
+ let readiness = { status: "checking" };
2388
+ let checkout;
2389
+ let opening;
2390
+ let disposed = false;
2391
+ let armedInterval = null;
2392
+ let lastPollAt = null;
2393
+ let lastPricedAt = null;
2394
+ let pricedItems = null;
2395
+ let lastScopeComplete = true;
2396
+ let stopWatchingSession;
2397
+ let stopWatchingAccess;
2398
+ let checkoutStarted = false;
2399
+ let recheckAfterOpening = false;
2400
+ async function loadPrices(items) {
2401
+ if (!deps.pricing.enabled) return { scopeComplete: true };
2402
+ lastPricedAt = deps.clock.now();
2403
+ pricedItems = items;
2404
+ const [identity, read2] = await Promise.all([deps.host.identity(), deps.binding.current().then((binding) => ({ binding }), () => null)]);
2405
+ const scope = read2 ? catalogScope(identity, read2.binding) : { appId: "", bundleId: "" };
2406
+ await deps.pricing.load({ scope, platform: identity?.platform ?? "", items });
2407
+ lastScopeComplete = identity !== null && read2 !== null;
2408
+ if (checkout) await checkAccess(checkout);
2409
+ return { scopeComplete: lastScopeComplete };
2410
+ }
2411
+ function pollDirective(action2) {
2412
+ const interval = checkout?.state().nextWakeAt != null ? DUE_WORK_POLL_MS : deps.pricing.enabled || checkout ? PRICE_REFRESH_MS : null;
2413
+ if (interval === null || interval === armedInterval) return void 0;
2414
+ armedInterval = interval;
2415
+ lastPollAt ?? (lastPollAt = deps.clock.now());
2416
+ return { id: POLL_ID2, action: action2, intervalMs: interval, immediate: true };
2417
+ }
2418
+ async function poll() {
2419
+ const now = deps.clock.now();
2420
+ const suspended = lastPollAt !== null && now - lastPollAt > SUSPENDED_AFTER_MS;
2421
+ lastPollAt = now;
2422
+ await (suspended ? reconcile2() : checkout ? checkout.tick() : startedCheckout());
2423
+ if (pricedItems && lastPricedAt !== null && now - lastPricedAt >= PRICE_REFRESH_MS - PRICE_REFRESH_SLACK_MS) await loadPrices(pricedItems);
2424
+ }
2425
+ function reconcile2() {
2426
+ return recover((opened) => opened.reconcile());
2427
+ }
2428
+ function start() {
2429
+ return recover((opened) => opened.start());
2430
+ }
2431
+ async function buy(item) {
2432
+ if (unanswered2(deps.pricing.view(item.reference))) return state();
2433
+ const started = await startedCheckout();
2434
+ return started ? started.opened.buy(item) : state();
2435
+ }
2436
+ function purchaseFields(reference, copy) {
2437
+ const view = deps.pricing.view(reference);
2438
+ const fields = iapPurchaseFields({ ...view, route: deps.pricing.continueCheckoutGuard(reference).route }, state(), readiness, copy);
2439
+ if (!fields.appleRoute || fields.accessReady || fields.buyDisabled) return fields;
2440
+ if (deps.session.current().kind !== "member") return { ...fields, buyDisabled: true, buyNote: copy.signInRequired };
2441
+ if (!unanswered2(view)) return fields;
2442
+ return { ...fields, buyDisabled: true, buyNote: view.reason === "mappingUnavailable" ? copy.unavailable : fields.buyNote };
2443
+ }
2444
+ function catalogScope(identity, binding) {
2445
+ const siteId = binding?.siteId ?? (identity?.platform === "web" ? "" : deps.host.preferenceSite());
2446
+ return { appId: identity?.appId ?? "", bundleId: identity?.bundleId ?? "", ...siteId ? { siteId } : {} };
2447
+ }
2448
+ function open() {
2449
+ if (checkout || disposed) return Promise.resolve(checkout);
2450
+ return opening ?? (opening = openWhenReady().finally(() => {
2451
+ opening = void 0;
2452
+ if (!recheckAfterOpening) return;
2453
+ recheckAfterOpening = false;
2454
+ if (!checkout && !disposed) void startedCheckout();
2455
+ }));
2456
+ }
2457
+ async function openWhenReady() {
2458
+ const staticGaps = configurationGaps();
2459
+ if (staticGaps.length > 0) return settle({ status: "unavailable", gaps: staticGaps });
2460
+ const routes = deps.routes;
2461
+ const [identity, binding] = await Promise.all([deps.host.identity(), readBinding2()]);
2462
+ const host = identity && binding && hostFor(identity, binding);
2463
+ const gaps = await hostGaps(host, binding);
2464
+ if (!host || gaps.length > 0 || disposed) {
2465
+ watchSessionUntilReady();
2466
+ return settle({ status: "unavailable", gaps });
2467
+ }
2468
+ stopWatchingSession?.();
2469
+ stopWatchingSession = void 0;
2470
+ checkout = createAppleIapCheckoutWith({
2471
+ enabled: true,
2472
+ wixIap: deps.wixIapClient({ host, route: routes.wixIap }),
2473
+ binding: deps.binding,
2474
+ session: deps.session,
2475
+ identity: deps.identity,
2476
+ clock: deps.clock,
2477
+ cashier: routes.cashier,
2478
+ adapters: deps.adapters,
2479
+ pricing: deps.pricing,
2480
+ store: deps.store,
2481
+ refs: deps.refs,
2482
+ bridge: deps.bridge,
2483
+ jitter: deps.jitter,
2484
+ onState: () => deps.onChange?.()
2485
+ });
2486
+ return settle({ status: "ready" });
2487
+ }
2488
+ function watchSessionUntilReady() {
2489
+ stopWatchingSession ?? (stopWatchingSession = deps.session.subscribe(() => {
2490
+ if (checkout || disposed) return;
2491
+ if (opening) recheckAfterOpening = true;
2492
+ else void startedCheckout();
2493
+ }));
2494
+ }
2495
+ function configurationGaps() {
2496
+ return [...deps.routes ? [] : ["routes"], ...deps.pricing.enabled ? [] : ["mapping"]];
2497
+ }
2498
+ async function hostGaps(host, binding) {
2499
+ if (!host) return ["binding"];
2500
+ if (!fencedTo(binding)) return ["nativeIdentity"];
2501
+ const gaps = [];
2502
+ if (!await managedStoreEnabled()) gaps.push("managedStore");
2503
+ if (binding && deps.refs.hasRefs(binding) === null) gaps.push("storage");
2504
+ return gaps;
2505
+ }
2506
+ function fencedTo(binding) {
2507
+ const site = deps.session.site?.();
2508
+ return deps.session.identityBound === true && !!binding && !!site && site.toLowerCase() === binding.siteId.toLowerCase();
2509
+ }
2510
+ async function managedStoreEnabled() {
2511
+ const unfinished = await deps.store.getUnfinishedTransactions().catch(() => null);
2512
+ return unfinished?.status === "ok";
2513
+ }
2514
+ function settle(next) {
2515
+ const changed = JSON.stringify(next) !== JSON.stringify(readiness);
2516
+ readiness = next;
2517
+ if (changed) deps.onChange?.();
2518
+ return checkout;
2519
+ }
2520
+ function readBinding2() {
2521
+ return deps.binding.current().catch(() => null);
2522
+ }
2523
+ async function startedCheckout() {
2524
+ if (deps.adapters.length === 0) return void 0;
2525
+ const opened = await open();
2526
+ if (!opened) return void 0;
2527
+ if (checkoutStarted) return { opened, fresh: false };
2528
+ checkoutStarted = true;
2529
+ await opened.start();
2530
+ stopWatchingAccess = deps.session.subscribe(() => {
2531
+ if (!disposed) void checkAccess(opened);
2532
+ });
2533
+ await checkAccess(opened);
2534
+ return { opened, fresh: true };
2535
+ }
2536
+ async function recover(run) {
2537
+ const started = await startedCheckout();
2538
+ if (!started) return state();
2539
+ if (started.fresh) return state();
2540
+ await run(started.opened);
2541
+ return checkAccess(started.opened);
2542
+ }
2543
+ function checkAccess(opened) {
2544
+ const items = (pricedItems ?? []).filter((item) => deps.pricing.view(item.reference).route === "appleIap");
2545
+ return items.length ? opened.checkAccess(items.map((item) => ({ reference: item.reference }))) : Promise.resolve(state());
2546
+ }
2547
+ function state() {
2548
+ return checkout?.state() ?? notEnabledState();
2549
+ }
2550
+ return {
2551
+ pricing: deps.pricing,
2552
+ loadPrices,
2553
+ readiness: () => readiness,
2554
+ scopeComplete: () => lastScopeComplete,
2555
+ state,
2556
+ purchaseFields,
2557
+ start,
2558
+ buy,
2559
+ reconcile: reconcile2,
2560
+ tick: () => checkout ? checkout.tick() : Promise.resolve(state()),
2561
+ pollDirective,
2562
+ poll,
2563
+ dispose: () => {
2564
+ disposed = true;
2565
+ stopWatchingSession?.();
2566
+ stopWatchingAccess?.();
2567
+ deps.pricing.dispose();
2568
+ checkout?.dispose();
2569
+ }
2570
+ };
2571
+ }
2572
+ var POLL_ID2 = "iapCommerce";
2573
+ var PRICE_REFRESH_MS = 6e4;
2574
+ var PRICE_REFRESH_SLACK_MS = 1e4;
2575
+ var DUE_WORK_POLL_MS = 2e3;
2576
+ var SUSPENDED_AFTER_MS = 2 * PRICE_REFRESH_MS;
2577
+ function unanswered2(view) {
2578
+ return view.route === "resolving" || view.reason === "mappingUnavailable";
2579
+ }
2580
+ function hostFor(identity, binding) {
2581
+ if (binding.himalayaAppId !== identity.appId || binding.bundleId !== identity.bundleId) return null;
2582
+ return { appId: identity.appId, bundleId: identity.bundleId, siteId: binding.siteId };
2583
+ }
2584
+
2585
+ // ../../stdlib/flows/iap-checkout/src/commerce.ts
2586
+ function createIapCommerce(options = {}) {
2587
+ const session = hostSessionFromGlobal();
2588
+ const identity = memberIdentityOf(session);
2589
+ const binding = sharedHostAppBindingSource();
2590
+ return createIapCommerceWith({
2591
+ routes: appleIapCheckoutRoutes(),
2592
+ pricing: createIapCatalogPricing({ onChange: options.onChange }),
2593
+ binding,
2594
+ session,
2595
+ host: hostOfWorker(),
2596
+ store: appleManagedStore,
2597
+ refs: createWorkerOrderRefStore(),
2598
+ clock: { now: () => Date.now() },
2599
+ adapters: options.adapters ?? [],
2600
+ identity,
2601
+ wixIapClient: ({ host, route }) => createWixIapClient({ session, binding, identity, host, route }),
2602
+ onChange: options.onChange
2603
+ });
2604
+ }
2605
+ function hostOfWorker() {
2606
+ let read2;
2607
+ return {
2608
+ identity: () => read2 ?? (read2 = readIdentity().then((identity) => {
2609
+ if (!identity) read2 = void 0;
2610
+ return identity;
2611
+ })),
2612
+ preferenceSite
2613
+ };
2614
+ }
2615
+ async function readIdentity() {
2616
+ const info = await get().catch(() => void 0);
2617
+ return info?.appId && info.bundleId && info.platform ? { appId: info.appId, bundleId: info.bundleId, platform: info.platform } : null;
2618
+ }
2619
+ function preferenceSite() {
2620
+ const value = globalThis.himalaya?.input?.__himiPreferenceBusiness;
2621
+ return typeof value === "string" ? value.trim() : "";
2622
+ }
2623
+
1502
2624
  // ../../stdlib/flows/iap-checkout/src/apple-iap.ts
1503
2625
  function createAppleIapCheckout(deps) {
1504
2626
  return createAppleIapCheckoutWith({ ...deps, enabled: appleIapCheckoutEnabled() });
@@ -1527,9 +2649,9 @@ function isHttp(outcome, httpStatus) {
1527
2649
  }
1528
2650
  function bodyObject(outcome, name) {
1529
2651
  const body = outcome.body;
1530
- return isObject5(body) && isObject5(body[name]) ? body[name] : null;
2652
+ return isObject7(body) && isObject7(body[name]) ? body[name] : null;
1531
2653
  }
1532
- function isObject5(value) {
2654
+ function isObject7(value) {
1533
2655
  return value !== null && typeof value === "object" && !Array.isArray(value);
1534
2656
  }
1535
2657
  function isNonEmpty3(value) {
@@ -1548,20 +2670,21 @@ var onlineProgramOrders = {
1548
2670
  eligibility: (item) => singleUnitOf(KIND, item),
1549
2671
  openOrder,
1550
2672
  reopenOrder,
1551
- readAccess
2673
+ readAccess,
2674
+ currentAccess
1552
2675
  };
1553
2676
  async function openOrder(item, bridge) {
1554
2677
  const found = await currentApplication(item.reference.id, bridge);
1555
2678
  if ("attempt" in found) return found.attempt;
1556
- const read = found.application ? { application: found.application } : await createdApplication(item.reference.id, bridge);
1557
- if ("attempt" in read) return read.attempt;
1558
- return orderOf(read.application, bridge, { mayPrepare: true });
2679
+ const read2 = found.application ? { application: found.application } : await createdApplication(item.reference.id, bridge);
2680
+ if ("attempt" in read2) return read2.attempt;
2681
+ return orderOf(read2.application, bridge, { mayPrepare: true });
1559
2682
  }
1560
2683
  async function reopenOrder(order, bridge) {
1561
- const read = await applicationById(order.verticalRef.joinApplicationId, bridge);
1562
- if ("attempt" in read) return read.attempt;
1563
- const attempt2 = await orderOf(read.application, bridge, { mayPrepare: false });
1564
- return attempt2.status === "open" && attempt2.cashierOrderId !== order.cashierOrderId ? ORDER_CLOSED : attempt2;
2684
+ const read2 = await applicationById(order.verticalRef.joinApplicationId, bridge);
2685
+ if ("attempt" in read2) return read2.attempt;
2686
+ const attempt3 = await orderOf(read2.application, bridge, { mayPrepare: false });
2687
+ return attempt3.status === "open" && attempt3.cashierOrderId !== order.cashierOrderId ? ORDER_CLOSED : attempt3;
1565
2688
  }
1566
2689
  async function readAccess(verticalRef, bridge) {
1567
2690
  if (!isNonEmpty3(verticalRef.joinApplicationId)) return "unavailable";
@@ -1570,6 +2693,14 @@ async function readAccess(verticalRef, bridge) {
1570
2693
  const application = bodyObject(answer, "joinApplication");
1571
2694
  return application ? accessOf(application) : "unavailable";
1572
2695
  }
2696
+ async function currentAccess(item, bridge) {
2697
+ const answer = await bridge.call("GET", `${BASE}/current/${encodeURIComponent(item.reference.id)}`);
2698
+ if (isRefusal(answer)) return accessRefused(answer);
2699
+ const application = bodyObject(answer, "joinApplication");
2700
+ if (!application) return "unavailable";
2701
+ const access = accessOf(application);
2702
+ return access !== "granted" && ENDED_STATUS.has(String(application.status)) ? "none" : access;
2703
+ }
1573
2704
  function accessOf(application) {
1574
2705
  const paid = application.paymentStatus === "PAYMENT_SUCCESSFUL" || application.paymentStatus === "NO_PAYMENT_REQUIRED";
1575
2706
  if (application.status === "APPROVED" && paid && isNonEmpty3(application.participantId)) return "granted";
@@ -1602,8 +2733,8 @@ async function preparedOrder(application, bridge) {
1602
2733
  return prepared ? orderOf(prepared, bridge, { mayPrepare: false }) : ORDER_REFUSED;
1603
2734
  }
1604
2735
  async function reopenAfterRace(id, bridge) {
1605
- const read = await applicationById(id, bridge);
1606
- return "attempt" in read ? read.attempt : orderOf(read.application, bridge, { mayPrepare: false });
2736
+ const read2 = await applicationById(id, bridge);
2737
+ return "attempt" in read2 ? read2.attempt : orderOf(read2.application, bridge, { mayPrepare: false });
1607
2738
  }
1608
2739
  async function currentApplication(programId, bridge) {
1609
2740
  const answer = await bridge.call("GET", `${BASE}/current/${encodeURIComponent(programId)}`);
@@ -1636,6 +2767,7 @@ function applicationIn(answer) {
1636
2767
  var PREPARABLE = /* @__PURE__ */ new Set(["PAYMENT_PENDING", "PAYMENT_FAILED", "PAYMENT_CANCELED"]);
1637
2768
  var PAYMENT_UNDER_WAY = /* @__PURE__ */ new Set(["PAYMENT_PENDING", "PAYMENT_IN_PROGRESS", "PENDING_OWNER_APPROVAL"]);
1638
2769
  var NO_ACCESS_STATUS = /* @__PURE__ */ new Set(["CANCELLED", "DECLINED", "SUSPENDED", "INVITED", "APPROVAL_PENDING"]);
2770
+ var ENDED_STATUS = /* @__PURE__ */ new Set(["CANCELLED", "DECLINED", "SUSPENDED"]);
1639
2771
  var NO_ACCESS_PAYMENT = /* @__PURE__ */ new Set(["PAYMENT_FAILED", "PAYMENT_CANCELED"]);
1640
2772
 
1641
2773
  // ../../stdlib/flows/iap-checkout/src/iap-verticals/pricing-plans.ts
@@ -1659,10 +2791,10 @@ async function openOrder2(item, bridge) {
1659
2791
  return orderOf2(bodyObject(created, "order"), planId);
1660
2792
  }
1661
2793
  async function reopenOrder2(order, bridge) {
1662
- const read = await memberOrder(order.verticalRef.orderId, bridge);
1663
- if ("attempt" in read) return read.attempt;
1664
- const attempt2 = orderOf2(read.order, order.verticalRef.planId ?? "");
1665
- return attempt2.status === "open" && attempt2.cashierOrderId !== order.cashierOrderId ? ORDER_CLOSED : attempt2;
2794
+ const read2 = await memberOrder(order.verticalRef.orderId, bridge);
2795
+ if ("attempt" in read2) return read2.attempt;
2796
+ const attempt3 = orderOf2(read2.order, order.verticalRef.planId ?? "");
2797
+ return attempt3.status === "open" && attempt3.cashierOrderId !== order.cashierOrderId ? ORDER_CLOSED : attempt3;
1666
2798
  }
1667
2799
  async function readAccess2(verticalRef, bridge) {
1668
2800
  if (!isNonEmpty3(verticalRef.orderId)) return "unavailable";
@@ -1743,7 +2875,7 @@ async function readAccess3(verticalRef, bridge) {
1743
2875
  return NO_ACCESS2.has(status) ? "none" : "unavailable";
1744
2876
  }
1745
2877
  async function placedOrder(body, bridge) {
1746
- if (!isObject5(body) || !isNonEmpty3(body.orderId)) return ORDER_REFUSED;
2878
+ if (!isObject7(body) || !isNonEmpty3(body.orderId)) return ORDER_REFUSED;
1747
2879
  const verticalRef = { orderId: body.orderId };
1748
2880
  if (isNonEmpty3(body.paymentGatewayOrderId)) return { status: "open", cashierOrderId: body.paymentGatewayOrderId, verticalRef };
1749
2881
  const access = await readAccess3(verticalRef, bridge);
@@ -1755,7 +2887,9 @@ var NO_ACCESS2 = /* @__PURE__ */ new Set(["FULLY_REFUNDED", "PARTIALLY_REFUNDED"
1755
2887
  export {
1756
2888
  classifyCart,
1757
2889
  createAppleIapCheckout,
2890
+ createIapCommerce,
1758
2891
  createWorkerOrderRefStore,
2892
+ iapPurchaseFields,
1759
2893
  onlineProgramOrders,
1760
2894
  pricingPlanOrders,
1761
2895
  storesProductOrders