@wix/himalaya-cli 0.1308.0 → 0.1310.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 (106) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/builder.d.ts +7 -0
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/delivery-contract.d.ts +3 -3
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/delivery.d.ts +3 -0
  4. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/host-session.d.ts +31 -0
  5. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/index.d.ts +1 -0
  6. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/wix-payments-contract.d.ts +19 -14
  7. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/wix-payments-wire.d.ts +2 -4
  8. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/wix-payments.d.ts +11 -12
  9. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/schema.d.ts +32 -0
  10. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/validator.d.ts +60 -0
  11. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/apple-iap-contract.d.ts +17 -9
  12. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/iap-order-backend.d.ts +6 -1
  13. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/core.mjs +31 -0
  14. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/iap-checkout.mjs +119 -65
  15. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/iap.mjs +117 -35
  16. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdui.mjs +31 -0
  17. package/dist/cli.mjs +1305 -863
  18. package/dist/preview-assets.generated.bin +0 -0
  19. package/guides/app-config.md +2 -2
  20. package/guides/component-reference.json +2 -2
  21. package/guides/component-reference.md +10 -0
  22. package/guides/getting-started.md +40 -0
  23. package/guides/himi-skill.md +40 -0
  24. package/guides/qa-builds.md +16 -12
  25. package/guides/sdk-reference.json +61 -25
  26. package/package.json +3 -2
  27. package/templates/beauty-salon/himalaya.content.json +86 -0
  28. package/templates/beauty-salon-owner/dev/index.ts +574 -181
  29. package/templates/beauty-salon-owner/himalaya.content.json +179 -0
  30. package/templates/beauty-salon-owner/tier5-src/_shared/aria-chat.ts +136 -12
  31. package/templates/beauty-salon-owner/tier5-src/_shared/aria-client-tools.ts +57 -9
  32. package/templates/beauty-salon-owner/tier5-src/_shared/aria-row-id.ts +14 -0
  33. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-aria/index.ts +3 -0
  34. package/templates/branded-lite/himalaya.content.json +254 -0
  35. package/templates/brandy/himalaya.content.json +18 -1
  36. package/templates/community-club/himalaya.content.json +68 -0
  37. package/templates/community-club-owner/dev/index.ts +574 -181
  38. package/templates/community-club-owner/himalaya.content.json +173 -0
  39. package/templates/community-club-owner/tier5-src/_shared/aria-chat.ts +136 -12
  40. package/templates/community-club-owner/tier5-src/_shared/aria-client-tools.ts +57 -9
  41. package/templates/community-club-owner/tier5-src/_shared/aria-row-id.ts +14 -0
  42. package/templates/community-club-owner/tier5-src/himi-owner-lite-aria/index.ts +3 -0
  43. package/templates/events-meetups/himalaya.content.json +62 -0
  44. package/templates/events-meetups-owner/dev/index.ts +574 -181
  45. package/templates/events-meetups-owner/himalaya.content.json +155 -0
  46. package/templates/events-meetups-owner/tier5-src/_shared/aria-chat.ts +136 -12
  47. package/templates/events-meetups-owner/tier5-src/_shared/aria-client-tools.ts +57 -9
  48. package/templates/events-meetups-owner/tier5-src/_shared/aria-row-id.ts +14 -0
  49. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-aria/index.ts +3 -0
  50. package/templates/gym-fitness/himalaya.content.json +101 -0
  51. package/templates/gym-fitness-owner/dev/index.ts +574 -181
  52. package/templates/gym-fitness-owner/himalaya.content.json +188 -0
  53. package/templates/gym-fitness-owner/tier5-src/_shared/aria-chat.ts +136 -12
  54. package/templates/gym-fitness-owner/tier5-src/_shared/aria-client-tools.ts +57 -9
  55. package/templates/gym-fitness-owner/tier5-src/_shared/aria-row-id.ts +14 -0
  56. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-aria/index.ts +3 -0
  57. package/templates/himi-chat/himalaya.content.json +8 -0
  58. package/templates/nonprofit-cause/himalaya.content.json +74 -0
  59. package/templates/nonprofit-cause-owner/dev/index.ts +574 -181
  60. package/templates/nonprofit-cause-owner/himalaya.content.json +170 -0
  61. package/templates/nonprofit-cause-owner/tier5-src/_shared/aria-chat.ts +136 -12
  62. package/templates/nonprofit-cause-owner/tier5-src/_shared/aria-client-tools.ts +57 -9
  63. package/templates/nonprofit-cause-owner/tier5-src/_shared/aria-row-id.ts +14 -0
  64. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-aria/index.ts +3 -0
  65. package/templates/owner-lite/dev/index.ts +574 -181
  66. package/templates/owner-lite/himalaya.content.json +203 -0
  67. package/templates/owner-lite/tier5-src/_shared/aria-chat.ts +136 -12
  68. package/templates/owner-lite/tier5-src/_shared/aria-client-tools.ts +57 -9
  69. package/templates/owner-lite/tier5-src/_shared/aria-row-id.ts +14 -0
  70. package/templates/owner-lite/tier5-src/himi-owner-lite-aria/index.ts +3 -0
  71. package/templates/podcast-creator/himalaya.content.json +71 -0
  72. package/templates/podcast-creator-owner/dev/index.ts +574 -181
  73. package/templates/podcast-creator-owner/himalaya.content.json +173 -0
  74. package/templates/podcast-creator-owner/tier5-src/_shared/aria-chat.ts +136 -12
  75. package/templates/podcast-creator-owner/tier5-src/_shared/aria-client-tools.ts +57 -9
  76. package/templates/podcast-creator-owner/tier5-src/_shared/aria-row-id.ts +14 -0
  77. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-aria/index.ts +3 -0
  78. package/templates/portfolio-creative/himalaya.content.json +80 -0
  79. package/templates/portfolio-creative-owner/dev/index.ts +574 -181
  80. package/templates/portfolio-creative-owner/himalaya.content.json +179 -0
  81. package/templates/portfolio-creative-owner/tier5-src/_shared/aria-chat.ts +136 -12
  82. package/templates/portfolio-creative-owner/tier5-src/_shared/aria-client-tools.ts +57 -9
  83. package/templates/portfolio-creative-owner/tier5-src/_shared/aria-row-id.ts +14 -0
  84. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-aria/index.ts +3 -0
  85. package/templates/restaurant/himalaya.content.json +65 -0
  86. package/templates/restaurant-owner/dev/index.ts +574 -181
  87. package/templates/restaurant-owner/himalaya.content.json +188 -0
  88. package/templates/restaurant-owner/tier5-src/_shared/aria-chat.ts +136 -12
  89. package/templates/restaurant-owner/tier5-src/_shared/aria-client-tools.ts +57 -9
  90. package/templates/restaurant-owner/tier5-src/_shared/aria-row-id.ts +14 -0
  91. package/templates/restaurant-owner/tier5-src/himi-owner-lite-aria/index.ts +3 -0
  92. package/templates/retail-store/himalaya.content.json +62 -0
  93. package/templates/retail-store-owner/dev/index.ts +574 -181
  94. package/templates/retail-store-owner/himalaya.content.json +164 -0
  95. package/templates/retail-store-owner/tier5-src/_shared/aria-chat.ts +136 -12
  96. package/templates/retail-store-owner/tier5-src/_shared/aria-client-tools.ts +57 -9
  97. package/templates/retail-store-owner/tier5-src/_shared/aria-row-id.ts +14 -0
  98. package/templates/retail-store-owner/tier5-src/himi-owner-lite-aria/index.ts +3 -0
  99. package/templates/surface-showcase/himalaya.content.json +11 -0
  100. package/templates/yoga-studio/himalaya.content.json +80 -0
  101. package/templates/yoga-studio-owner/dev/index.ts +574 -181
  102. package/templates/yoga-studio-owner/himalaya.content.json +170 -0
  103. package/templates/yoga-studio-owner/tier5-src/_shared/aria-chat.ts +136 -12
  104. package/templates/yoga-studio-owner/tier5-src/_shared/aria-client-tools.ts +57 -9
  105. package/templates/yoga-studio-owner/tier5-src/_shared/aria-row-id.ts +14 -0
  106. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-aria/index.ts +3 -0
@@ -161,7 +161,7 @@ function createPurchaseCoordinator(deps) {
161
161
  if (!isCurrent(session)) return noDelivery();
162
162
  const wasAllowed = item.finishAllowed;
163
163
  if (delivered.signInLost && !wasAllowed) {
164
- blockWithoutSession(item, context);
164
+ blockWithoutSession(item);
165
165
  continue;
166
166
  }
167
167
  if (await deliverItem(session, item, context)) delivered.finished = true;
@@ -170,9 +170,8 @@ function createPurchaseCoordinator(deps) {
170
170
  }
171
171
  return delivered;
172
172
  }
173
- function blockWithoutSession(item, context) {
174
- const foreign = context !== void 0 && !sameAccount(item.transaction.appAccountToken, context.appAccountToken);
175
- block(item.state, foreign ? "ownershipConflict" : "signInRequired", null);
173
+ function blockWithoutSession(item) {
174
+ block(item.state, item.transaction.appAccountToken === null ? "ownershipConflict" : "signInRequired", null);
176
175
  }
177
176
  async function deliverItem(session, item, context) {
178
177
  if (!item.finishAllowed) {
@@ -181,7 +180,7 @@ function createPurchaseCoordinator(deps) {
181
180
  return complete(session, item);
182
181
  }
183
182
  async function confirmAccess(session, item, context) {
184
- if (!sameAccount(item.transaction.appAccountToken, context.appAccountToken)) {
183
+ if (item.transaction.appAccountToken === null) {
185
184
  block(item.state, "ownershipConflict", null);
186
185
  return false;
187
186
  }
@@ -373,6 +372,7 @@ function createPurchaseCoordinator(deps) {
373
372
  const known = new Set([...items.keys()].filter((key) => items.get(key).state.productId === context.productId));
374
373
  pendingApproval = { productId: context.productId, token: context.appAccountToken, known };
375
374
  setOutcome("awaitingApproval");
375
+ deps.onAwaitingApproval?.(context.productId);
376
376
  return true;
377
377
  }
378
378
  function setOutcome(next) {
@@ -464,10 +464,10 @@ function decodeContext(settled, isContext) {
464
464
  return { kind: "unavailable", retryAfterMs: retryAfter(raw.retryAfterMs) };
465
465
  }
466
466
  function isPurchaseContext(value) {
467
- return isMemberContext(value) && isObject(value) && isNonEmpty(value.productId);
467
+ return isMemberContext(value) && isObject(value) && isNonEmpty(value.productId) && isNonEmpty(value.appAccountToken);
468
468
  }
469
469
  function isMemberContext(value) {
470
- return isObject(value) && isNonEmpty(value.appAccountToken) && isNonEmpty(value.scopeKey);
470
+ return isObject(value) && isNonEmpty(value.scopeKey);
471
471
  }
472
472
  function retryAfter(value) {
473
473
  return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
@@ -529,6 +529,14 @@ function createSerialQueue() {
529
529
  };
530
530
  }
531
531
 
532
+ // ../../core/sdk/iap/src/host-session.ts
533
+ function readIdentityBound() {
534
+ return wixApiGlobal()?.identityBound === true;
535
+ }
536
+ function wixApiGlobal() {
537
+ return globalThis.himalaya?.wixApi;
538
+ }
539
+
532
540
  // ../../core/sdk/iap/src/index.ts
533
541
  async function purchaseForVerification(input) {
534
542
  if (!nonempty(input?.productId) || !isUUID2(input?.appAccountToken)) return failure2("invalidArgument");
@@ -661,6 +669,7 @@ var COMPLETE_PAYMENT_REFUSALS = {
661
669
  PURCHASE_REVOKED: "refusedFinal",
662
670
  ZERO_PRICE: "refusedFinal",
663
671
  NO_MATCHING_PAYMENT: "refusedFinal",
672
+ PAYMENT_NOT_PENDING: "refusedFinal",
664
673
  // Before recordPurchase: nothing is recorded. Held pending owner confirmation.
665
674
  INVALID_PURCHASE: "hold",
666
675
  APP_NOT_CONFIGURED: "hold",
@@ -702,8 +711,8 @@ function createWorkerOrderRefStore(storage) {
702
711
  }
703
712
  function hasRefs(app) {
704
713
  if (!isUUID3(app.purchasesAppId) || !isUUID3(app.siteId)) return null;
705
- const customers = readIndex(kv(), indexKey(app));
706
- return customers && customers.length > 0;
714
+ const members = readIndex(kv(), indexKey(app));
715
+ return members && members.length > 0;
707
716
  }
708
717
  return { open, hasRefs };
709
718
  }
@@ -715,12 +724,12 @@ function upsert(refs, ref) {
715
724
  }
716
725
  function updateIndex(store, key, holdsRefs) {
717
726
  const location = indexKey(key);
718
- const customers = readIndex(store, location);
719
- if (customers === null) return false;
720
- const customer = customerKey(key.customerId);
721
- const others = customers.filter((stored) => stored !== customer);
722
- const next = holdsRefs ? [...others, customer] : others;
723
- return next.length === customers.length && next.every((c, i) => c === customers[i]) || writeVerified(store, location, serialize({ v: VERSION, customers: next }));
727
+ const members = readIndex(store, location);
728
+ if (members === null) return false;
729
+ const member = memberKey(key.memberId);
730
+ const others = members.filter((stored) => stored !== member);
731
+ const next = holdsRefs ? [...others, member] : others;
732
+ return next.length === members.length && next.every((m, i) => m === members[i]) || writeVerified(store, location, serialize({ v: VERSION, members: next }));
724
733
  }
725
734
  function readRefs(store, location) {
726
735
  const parsed = readVersioned(store, location);
@@ -731,8 +740,8 @@ function readRefs(store, location) {
731
740
  function readIndex(store, location) {
732
741
  const parsed = readVersioned(store, location);
733
742
  if (parsed === "empty") return [];
734
- if (!parsed || !Array.isArray(parsed.customers) || !parsed.customers.every(isCustomerKey)) return null;
735
- return parsed.customers;
743
+ if (!parsed || !Array.isArray(parsed.members) || !parsed.members.every(isMemberKey)) return null;
744
+ return parsed.members;
736
745
  }
737
746
  function readVersioned(store, location) {
738
747
  if (!store) return null;
@@ -752,18 +761,18 @@ function writeVerified(store, location, value) {
752
761
  function isOrderRef(value) {
753
762
  if (!isObject4(value) || typeof value.key !== "string" || !STAGES.has(value.stage)) return false;
754
763
  if (typeof value.updatedAt !== "number") return false;
755
- const optional = ["kind", "cashierOrderId", "wixTransactionId", "paymentId", "storeProductId", "appProductId", "appleTransactionId"];
764
+ const optional = ["kind", "cashierOrderId", "wixTransactionId", "paymentId", "storeProductId", "appProductId", "appleTransactionId", "appAccountToken"];
756
765
  if (!optional.every((field) => value[field] === void 0 || typeof value[field] === "string")) return false;
757
766
  return value.verticalRef === void 0 || isStringMap(value.verticalRef);
758
767
  }
759
768
  function isPartitionKey(key) {
760
- return isUUID3(key.purchasesAppId) && isUUID3(key.siteId) && isUUID3(key.customerId);
769
+ return isUUID3(key.purchasesAppId) && isUUID3(key.siteId) && isUUID3(key.memberId);
761
770
  }
762
771
  function partitionKey(key) {
763
- return `${PREFIX}.${key.purchasesAppId}.${key.siteId}.${customerKey(key.customerId)}`;
772
+ return `${PREFIX}.${key.purchasesAppId}.${key.siteId}.${memberKey(key.memberId)}`;
764
773
  }
765
- function customerKey(customerId) {
766
- const text = customerId.toLowerCase();
774
+ function memberKey(memberId) {
775
+ const text = memberId.toLowerCase();
767
776
  let h1 = 3735928559;
768
777
  let h2 = 1103547991;
769
778
  for (let i = 0; i < text.length; i++) {
@@ -773,13 +782,13 @@ function customerKey(customerId) {
773
782
  }
774
783
  h1 = Math.imul(h1 ^ h1 >>> 16, 2246822507) ^ Math.imul(h2 ^ h2 >>> 13, 3266489909);
775
784
  h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507) ^ Math.imul(h1 ^ h1 >>> 13, 3266489909);
776
- return `c${(4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(16).padStart(14, "0")}`;
785
+ return `m${(4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(16).padStart(14, "0")}`;
777
786
  }
778
- function isCustomerKey(value) {
779
- return typeof value === "string" && /^c[0-9a-f]{14}$/.test(value);
787
+ function isMemberKey(value) {
788
+ return typeof value === "string" && /^m[0-9a-f]{14}$/.test(value);
780
789
  }
781
790
  function indexKey(app) {
782
- return `${PREFIX}.${app.purchasesAppId}.${app.siteId}.customers`;
791
+ return `${PREFIX}.${app.purchasesAppId}.${app.siteId}.members`;
783
792
  }
784
793
  function hostStorage() {
785
794
  const storage = globalThis.himalaya?.storage;
@@ -815,7 +824,9 @@ function bindBridge(session, provider, bridge) {
815
824
  const isCurrent = () => session.kind === "member" && provider.current().generation === session.generation;
816
825
  async function call(method, path, body) {
817
826
  if (!isCurrent()) return SESSION_CHANGED;
818
- const outcome = await attempt(bridge, method, path, body);
827
+ const expectation = boundExpectation(session, provider, bridge);
828
+ if (expectation === "refuse") return { status: "notEnabled" };
829
+ const outcome = await attempt(bridge, method, path, body, expectation);
819
830
  return isCurrent() ? outcome : SESSION_CHANGED;
820
831
  }
821
832
  return { call, isCurrent };
@@ -826,13 +837,25 @@ function hostBridge() {
826
837
  return typeof bridge?.call === "function" ? bridge : void 0;
827
838
  }
828
839
  var MISSING_BRIDGE = { call: () => Promise.reject(new Error("wixApi not enabled")) };
829
- async function attempt(bridge, method, path, body) {
840
+ async function attempt(bridge, method, path, body, expectation) {
830
841
  try {
831
- return { status: "ok", body: await bridge.call(method, path, body) };
842
+ const answer = expectation ? await bridge.call(method, path, body, void 0, expectation) : await bridge.call(method, path, body);
843
+ return { status: "ok", body: answer };
832
844
  } catch (error) {
833
845
  return refusalOf(error);
834
846
  }
835
847
  }
848
+ function boundExpectation(session, provider, bridge) {
849
+ const source = provider;
850
+ const live = isLiveHost(bridge);
851
+ if (live && (source.identityBound !== true || !readIdentityBound())) return "refuse";
852
+ if (typeof source.identity !== "function") return live ? "refuse" : void 0;
853
+ return source.identity(session) ?? "refuse";
854
+ }
855
+ function isLiveHost(bridge) {
856
+ const api = globalThis.himalaya?.wixApi;
857
+ return api != null && (bridge === api || bridge.call === api.call);
858
+ }
836
859
  function refusalOf(error) {
837
860
  const message = error?.message;
838
861
  const text = typeof message === "string" ? message : "";
@@ -863,16 +886,17 @@ function createWixOrderBackend(deps) {
863
886
  if (!isCurrent(session)) return STALE2;
864
887
  if (binding === void 0) return retry("unavailable");
865
888
  if (!binding) return stopWith("rejected", "notConfigured");
866
- const customer = await deps.wixIap.getCustomerId();
889
+ const memberId = await readMemberId(deps.identity, session);
867
890
  if (!isCurrent(session)) return STALE2;
868
- if (customer.status !== "found") return failureStop(customer);
869
- const member = memberFor(binding, customer.customerId);
891
+ if (memberId === void 0) return retry("unavailable");
892
+ if (!memberId) return SIGN_IN;
893
+ const member = memberFor(binding, memberId);
870
894
  cached = { generation: session.generation, member };
871
895
  return member;
872
896
  }
873
- function memberFor(binding, customerId) {
874
- const partition = deps.refs.open({ purchasesAppId: binding.purchasesAppId, siteId: binding.siteId, customerId });
875
- return { customerId, scopeKey: `${binding.purchasesAppId}:${customerId}`, partition };
897
+ function memberFor(binding, memberId) {
898
+ const partition = deps.refs.open({ purchasesAppId: binding.purchasesAppId, siteId: binding.siteId, memberId });
899
+ return { memberId, scopeKey: `${binding.purchasesAppId}:${memberId.toLowerCase()}`, partition };
876
900
  }
877
901
  async function getPurchaseContext(session, catalogRef) {
878
902
  const sale = await saleFor(session, catalogRef);
@@ -909,6 +933,7 @@ function createWixOrderBackend(deps) {
909
933
  if (existing?.stage === "submitted") return stopWith("rejected", "paymentInProgress");
910
934
  if (existing?.stage === "held") return stopWith("rejected", "paymentHeld");
911
935
  if (existing?.stage === "needsSupport") return stopWith("rejected", "needsSupport");
936
+ if (deps.productBusy?.(sale.appleProduct.productId)) return stopWith("rejected", "paymentInProgress");
912
937
  const attempt2 = existing?.cashierOrderId && existing.verticalRef ? await reopenOrOpen(sale, { cashierOrderId: existing.cashierOrderId, verticalRef: existing.verticalRef }) : await sale.adapter.openOrder(sale.item, sale.bridge);
913
938
  return recordOrder(sale, existing, attempt2);
914
939
  }
@@ -977,14 +1002,14 @@ function createWixOrderBackend(deps) {
977
1002
  stage: "started",
978
1003
  paymentId: started.payment.paymentId,
979
1004
  storeProductId: started.storeProductId,
1005
+ appAccountToken: started.appAccountToken.toLowerCase(),
980
1006
  ...started.payment.appProductId ? { appProductId: started.payment.appProductId } : {},
981
1007
  updatedAt: now()
982
1008
  });
983
1009
  if (isStop(recorded)) return contextResult(sale.catalogRef, recorded);
984
- return { status: "ok", context: { productId: started.storeProductId, appAccountToken: sale.member.customerId, scopeKey: sale.member.scopeKey } };
1010
+ return { status: "ok", context: { productId: started.storeProductId, appAccountToken: started.appAccountToken, scopeKey: sale.member.scopeKey } };
985
1011
  }
986
1012
  function startedMismatch(sale, started) {
987
- if (!sameUUID(started.customerId, sale.member.customerId)) return "invalidAssociation";
988
1013
  return sale.appleProduct.productId === started.storeProductId ? null : "productChanged";
989
1014
  }
990
1015
  async function startRefusal(sale, ref, failure3) {
@@ -1019,9 +1044,8 @@ function createWixOrderBackend(deps) {
1019
1044
  }
1020
1045
  async function matchedProof(proof, payment) {
1021
1046
  const refs = proof.member.partition?.refs() ?? [];
1022
- const ref = refs.find((stored) => stored.paymentId === payment.paymentId) ?? refs.find((stored) => stored.wixTransactionId === payment.wixTransactionId);
1047
+ const ref = refs.find((stored) => stored.paymentId === payment.paymentId) ?? refs.find((stored) => stored.wixTransactionId === payment.wixTransactionId) ?? refByToken(refs, proof.transaction);
1023
1048
  if (ref?.storeProductId && ref.storeProductId !== proof.transaction.productId) return holdAssociation(ref);
1024
- reportOtherOrders(refs, ref, payment, proof.transaction);
1025
1049
  const tracking = trackingRef(ref, payment, proof.transaction, now());
1026
1050
  if (isFinalRefusal(payment.status)) return finalRefusal(proof, tracking);
1027
1051
  if (payment.status === "pending") return RETRYABLE;
@@ -1036,12 +1060,6 @@ function createWixOrderBackend(deps) {
1036
1060
  deps.report({ key: ref.key, failure: "invalidAssociation" });
1037
1061
  return { status: "rejected" };
1038
1062
  }
1039
- function reportOtherOrders(refs, matched, payment, transaction) {
1040
- for (const other of refs) {
1041
- if (other.key === matched?.key || other.stage !== "started" || other.storeProductId !== transaction.productId) continue;
1042
- if (other.paymentId !== payment.paymentId) deps.report({ key: other.key, failure: "matchedOtherOrder" });
1043
- }
1044
- }
1045
1063
  async function accessGranted(proof, ref) {
1046
1064
  const adapter = adapterFor(ref.kind);
1047
1065
  if (!adapter || !ref.verticalRef) return false;
@@ -1064,7 +1082,8 @@ function createWixOrderBackend(deps) {
1064
1082
  function finalRefusal(proof, ref) {
1065
1083
  const hold = ref ?? unassociatedHold(proof.transaction, now());
1066
1084
  const partition = proof.member.partition;
1067
- if (!partition || !isCurrent(proof.session) || !partition.put({ ...hold, stage: "needsSupport", updatedAt: now() })) return RETRYABLE;
1085
+ const stored = { ...hold, stage: "needsSupport", appleTransactionId: proof.transaction.transactionId, updatedAt: now() };
1086
+ if (!partition || !isCurrent(proof.session) || !partition.put(stored)) return RETRYABLE;
1068
1087
  deps.report({ key: hold.key, access: "needsSupport" });
1069
1088
  return { status: "refusedFinal", acknowledgement: proof.acknowledgement };
1070
1089
  }
@@ -1083,12 +1102,16 @@ function createWixOrderBackend(deps) {
1083
1102
  }
1084
1103
  function startedRefFor(proof) {
1085
1104
  const refs = proof.member.partition?.refs() ?? [];
1086
- return refs.find((ref) => (ref.stage === "started" || ref.stage === "held") && ref.storeProductId === proof.transaction.productId);
1105
+ const { productId, transactionId } = proof.transaction;
1106
+ const holding = refs.find((ref) => (ref.stage === "held" || ref.stage === "needsSupport") && ref.appleTransactionId === transactionId);
1107
+ if (holding) return holding;
1108
+ if (proof.transaction.appAccountToken) return refByToken(refs, proof.transaction);
1109
+ return refs.filter((ref) => ref.stage === "started" && ref.storeProductId === productId).reduce((newest, ref) => !newest || ref.updatedAt >= newest.updatedAt ? ref : newest, void 0);
1087
1110
  }
1088
1111
  async function getMemberContext(session) {
1089
1112
  const member = await memberOf(session);
1090
1113
  if (isStop(member)) return { status: member.result };
1091
- return { status: "ok", context: { appAccountToken: member.customerId, scopeKey: member.scopeKey } };
1114
+ return { status: "ok", context: { scopeKey: member.scopeKey } };
1092
1115
  }
1093
1116
  return { getPurchaseContext, getMemberContext, submitProof };
1094
1117
  }
@@ -1142,6 +1165,17 @@ function acknowledgementOf(transaction, scopeKey) {
1142
1165
  function refAt(partition, key) {
1143
1166
  return partition.refs().find((ref) => ref.key === key);
1144
1167
  }
1168
+ async function readMemberId(identity, session) {
1169
+ try {
1170
+ return await identity.memberId(session);
1171
+ } catch {
1172
+ return void 0;
1173
+ }
1174
+ }
1175
+ function refByToken(refs, transaction) {
1176
+ const token = transaction.appAccountToken?.toLowerCase();
1177
+ return token ? refs.find((ref) => ref.appAccountToken === token) : void 0;
1178
+ }
1145
1179
  async function readBinding(source) {
1146
1180
  try {
1147
1181
  return await source.current();
@@ -1149,14 +1183,12 @@ async function readBinding(source) {
1149
1183
  return void 0;
1150
1184
  }
1151
1185
  }
1152
- function sameUUID(a, b) {
1153
- return a.toLowerCase() === b.toLowerCase();
1154
- }
1155
1186
 
1156
1187
  // ../../stdlib/flows/iap-checkout/src/apple-iap-core.ts
1157
1188
  function createAppleIapCheckoutWith(deps) {
1158
1189
  return deps.enabled ? enabledCheckout(deps) : disabledCheckout();
1159
1190
  }
1191
+ var ASK_TO_BUY_HOLD_MS = 60 * 6e4;
1160
1192
  function enabledCheckout(deps) {
1161
1193
  const refs = deps.refs ?? createWorkerOrderRefStore();
1162
1194
  const bridge = deps.bridge ?? hostBridge() ?? MISSING_BRIDGE;
@@ -1166,10 +1198,11 @@ function enabledCheckout(deps) {
1166
1198
  let generation = deps.session.current().generation;
1167
1199
  let disposed = false;
1168
1200
  let tracking = Promise.resolve();
1169
- let trackedCustomer = null;
1170
1201
  let partitionRead = null;
1202
+ const awaitingApproval = /* @__PURE__ */ new Map();
1171
1203
  const backend = createWixOrderBackend({
1172
1204
  wixIap: deps.wixIap,
1205
+ identity: deps.identity,
1173
1206
  binding: deps.binding,
1174
1207
  session: deps.session,
1175
1208
  clock: deps.clock,
@@ -1178,6 +1211,7 @@ function enabledCheckout(deps) {
1178
1211
  refs,
1179
1212
  bridge,
1180
1213
  itemFor: (key) => sales.get(key),
1214
+ productBusy,
1181
1215
  report: onEvent
1182
1216
  });
1183
1217
  const coordinator = createPurchaseCoordinator({
@@ -1186,7 +1220,8 @@ function enabledCheckout(deps) {
1186
1220
  session: deps.session,
1187
1221
  clock: deps.clock,
1188
1222
  jitter: deps.jitter,
1189
- onState: publish
1223
+ onState: publish,
1224
+ onAwaitingApproval: reserveAskToBuy
1190
1225
  });
1191
1226
  async function start() {
1192
1227
  resetIfSessionChanged();
@@ -1264,16 +1299,31 @@ function enabledCheckout(deps) {
1264
1299
  if (current.failure) return "refused";
1265
1300
  if (OVERLAY_PHASES.has(purchase.phase)) return purchase.phase;
1266
1301
  if (current.buying) return "preparing";
1267
- if (mine?.access === "processing" || purchase.items.some(isProcessing)) return "processing";
1302
+ if (mine?.access === "processing" || purchase.items.some(isInFlight)) return "processing";
1303
+ if (!current.item && progress.some((payment) => payment.access === "processing")) return "processing";
1268
1304
  return "idle";
1269
1305
  }
1306
+ function reserveAskToBuy(productId) {
1307
+ awaitingApproval.set(productId, { items: itemsFor(productId).length, since: deps.clock.now() });
1308
+ }
1309
+ function productBusy(productId) {
1310
+ const items = itemsFor(productId);
1311
+ const pending = awaitingApproval.get(productId);
1312
+ if (pending && (items.length > pending.items || deps.clock.now() - pending.since >= ASK_TO_BUY_HOLD_MS)) {
1313
+ awaitingApproval.delete(productId);
1314
+ }
1315
+ return awaitingApproval.has(productId) || items.some(isUnfinished);
1316
+ }
1317
+ function itemsFor(productId) {
1318
+ return coordinator.getState().items.filter((held) => held.productId === productId);
1319
+ }
1270
1320
  function resetIfSessionChanged() {
1271
1321
  const next = deps.session.current().generation;
1272
1322
  if (next === generation) return;
1273
1323
  generation = next;
1274
1324
  sales.clear();
1275
1325
  payments.clear();
1276
- trackedCustomer = null;
1326
+ awaitingApproval.clear();
1277
1327
  partitionRead = null;
1278
1328
  current = { item: null, failure: null, buying: false };
1279
1329
  }
@@ -1314,17 +1364,17 @@ function enabledCheckout(deps) {
1314
1364
  if (!binding || !isCurrent(session)) return binding === null ? "none" : null;
1315
1365
  const stored = refs.hasRefs(binding);
1316
1366
  if (stored !== true) return stored === false ? "none" : null;
1317
- const customerId = await customerIdFor(session);
1318
- if (!customerId || !isCurrent(session)) return null;
1319
- const partition = refs.open({ purchasesAppId: binding.purchasesAppId, siteId: binding.siteId, customerId });
1367
+ const memberId = await memberIdOf(session);
1368
+ if (!memberId || !isCurrent(session)) return null;
1369
+ const partition = refs.open({ purchasesAppId: binding.purchasesAppId, siteId: binding.siteId, memberId });
1320
1370
  return partition && { partition };
1321
1371
  }
1322
- async function customerIdFor(session) {
1323
- if (trackedCustomer?.generation === session.generation) return trackedCustomer.customerId;
1324
- const customer = await deps.wixIap.getCustomerId();
1325
- if (customer.status !== "found" || !isCurrent(session)) return null;
1326
- trackedCustomer = { generation: session.generation, customerId: customer.customerId };
1327
- return customer.customerId;
1372
+ async function memberIdOf(session) {
1373
+ try {
1374
+ return await deps.identity.memberId(session);
1375
+ } catch {
1376
+ return null;
1377
+ }
1328
1378
  }
1329
1379
  function backOffDue() {
1330
1380
  const attempts = (partitionRead?.attempts ?? 0) + 1;
@@ -1415,7 +1465,11 @@ function blankState(enabled) {
1415
1465
  purchase: { phase: "idle", errorCode: null, items: [], unfinishedCount: null, nextWakeAt: null }
1416
1466
  };
1417
1467
  }
1418
- function isProcessing(item) {
1468
+ function isUnfinished(item) {
1469
+ return item.completion === "pending" || item.completion === "retryRequired";
1470
+ }
1471
+ function isInFlight(item) {
1472
+ if (item.completion === "finished") return false;
1419
1473
  return item.access === "processing" || item.access === "confirming" || item.access === "pending" || item.access === "waitingToRetry";
1420
1474
  }
1421
1475
  function itemKey(item) {