@wix/himalaya-cli 0.1496.0 → 0.1498.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 (138) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/attendance-classifier.d.ts +37 -0
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/catalog-pricing-contract.d.ts +1 -1
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/index.d.ts +2 -1
  4. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/wix-payments-contract.d.ts +11 -3
  5. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/apple-iap-contract.d.ts +27 -3
  6. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/commerce-contract.d.ts +1 -0
  7. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/iap-verticals/attendance.d.ts +10 -0
  8. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/iap-verticals/index.d.ts +1 -0
  9. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/index.d.ts +1 -1
  10. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/events/src/index.d.ts +33 -2
  11. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/iap-checkout.mjs +346 -26
  12. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/iap.mjs +132 -3
  13. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/screens.mjs +366 -48
  14. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-events.mjs +5 -0
  15. package/dist/cli.mjs +817 -666
  16. package/guides/iap-products.md +7 -1
  17. package/package.json +2 -2
  18. package/templates/beauty-salon/dev/index.ts +394 -0
  19. package/templates/beauty-salon/tier5-src/_shared/iap-attendance-form.ts +106 -0
  20. package/templates/beauty-salon/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
  21. package/templates/beauty-salon/tier5-src/_shared/iap-attendance.ts +38 -0
  22. package/templates/beauty-salon/tier5-src/himi-booking-time/index.ts +52 -7
  23. package/templates/beauty-salon-owner/dev/index.ts +571 -0
  24. package/templates/beauty-salon-owner/himalaya.content.json +6 -0
  25. package/templates/beauty-salon-owner/tier5-src/_shared/owner-today-rollup.ts +307 -0
  26. package/templates/beauty-salon-owner/tier5-src/_shared/owner-widget-reads.ts +23 -0
  27. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-today/index.ts +8 -20
  28. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-today-rollup/index.ts +121 -0
  29. package/templates/branded-lite/dev/index.ts +1429 -278
  30. package/templates/branded-lite/tier5-src/_shared/business-chat-presenter.ts +46 -8
  31. package/templates/branded-lite/tier5-src/_shared/iap-attendance-form.ts +106 -0
  32. package/templates/branded-lite/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
  33. package/templates/branded-lite/tier5-src/_shared/iap-attendance.ts +38 -0
  34. package/templates/branded-lite/tier5-src/business-chat/index.ts +3 -2
  35. package/templates/branded-lite/tier5-src/himi-booking-time/index.ts +52 -7
  36. package/templates/branded-lite/tier5-src/himi-events-detail/index.ts +112 -21
  37. package/templates/community-club/dev/index.ts +397 -2
  38. package/templates/community-club/tier5-src/_shared/iap-attendance-form.ts +106 -0
  39. package/templates/community-club/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
  40. package/templates/community-club/tier5-src/_shared/iap-attendance.ts +38 -0
  41. package/templates/community-club/tier5-src/himi-events-detail/index.ts +112 -21
  42. package/templates/community-club-owner/dev/index.ts +571 -0
  43. package/templates/community-club-owner/himalaya.content.json +6 -0
  44. package/templates/community-club-owner/tier5-src/_shared/owner-today-rollup.ts +307 -0
  45. package/templates/community-club-owner/tier5-src/_shared/owner-widget-reads.ts +23 -0
  46. package/templates/community-club-owner/tier5-src/himi-owner-lite-today/index.ts +8 -20
  47. package/templates/community-club-owner/tier5-src/himi-owner-lite-today-rollup/index.ts +121 -0
  48. package/templates/events-meetups/dev/index.ts +397 -2
  49. package/templates/events-meetups/tier5-src/_shared/iap-attendance-form.ts +106 -0
  50. package/templates/events-meetups/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
  51. package/templates/events-meetups/tier5-src/_shared/iap-attendance.ts +38 -0
  52. package/templates/events-meetups/tier5-src/himi-events-detail/index.ts +112 -21
  53. package/templates/events-meetups-owner/dev/index.ts +571 -0
  54. package/templates/events-meetups-owner/himalaya.content.json +6 -0
  55. package/templates/events-meetups-owner/tier5-src/_shared/owner-today-rollup.ts +307 -0
  56. package/templates/events-meetups-owner/tier5-src/_shared/owner-widget-reads.ts +23 -0
  57. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-today/index.ts +8 -20
  58. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-today-rollup/index.ts +121 -0
  59. package/templates/gym-fitness/dev/index.ts +828 -39
  60. package/templates/gym-fitness/tier5-src/_shared/iap-attendance-form.ts +106 -0
  61. package/templates/gym-fitness/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
  62. package/templates/gym-fitness/tier5-src/_shared/iap-attendance.ts +38 -0
  63. package/templates/gym-fitness/tier5-src/himi-booking-time/index.ts +52 -7
  64. package/templates/gym-fitness/tier5-src/himi-events-detail/index.ts +112 -21
  65. package/templates/gym-fitness-owner/dev/index.ts +571 -0
  66. package/templates/gym-fitness-owner/himalaya.content.json +6 -0
  67. package/templates/gym-fitness-owner/tier5-src/_shared/owner-today-rollup.ts +307 -0
  68. package/templates/gym-fitness-owner/tier5-src/_shared/owner-widget-reads.ts +23 -0
  69. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-today/index.ts +8 -20
  70. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-today-rollup/index.ts +121 -0
  71. package/templates/nonprofit-cause/dev/index.ts +397 -2
  72. package/templates/nonprofit-cause/tier5-src/_shared/iap-attendance-form.ts +106 -0
  73. package/templates/nonprofit-cause/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
  74. package/templates/nonprofit-cause/tier5-src/_shared/iap-attendance.ts +38 -0
  75. package/templates/nonprofit-cause/tier5-src/himi-events-detail/index.ts +112 -21
  76. package/templates/nonprofit-cause-owner/dev/index.ts +571 -0
  77. package/templates/nonprofit-cause-owner/himalaya.content.json +6 -0
  78. package/templates/nonprofit-cause-owner/tier5-src/_shared/owner-today-rollup.ts +307 -0
  79. package/templates/nonprofit-cause-owner/tier5-src/_shared/owner-widget-reads.ts +23 -0
  80. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-today/index.ts +8 -20
  81. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-today-rollup/index.ts +121 -0
  82. package/templates/owner-lite/dev/index.ts +571 -0
  83. package/templates/owner-lite/himalaya.content.json +6 -0
  84. package/templates/owner-lite/tier5-src/_shared/owner-today-rollup.ts +307 -0
  85. package/templates/owner-lite/tier5-src/_shared/owner-widget-reads.ts +23 -0
  86. package/templates/owner-lite/tier5-src/himi-owner-lite-today/index.ts +8 -20
  87. package/templates/owner-lite/tier5-src/himi-owner-lite-today-rollup/index.ts +121 -0
  88. package/templates/podcast-creator/dev/index.ts +397 -2
  89. package/templates/podcast-creator/tier5-src/_shared/iap-attendance-form.ts +106 -0
  90. package/templates/podcast-creator/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
  91. package/templates/podcast-creator/tier5-src/_shared/iap-attendance.ts +38 -0
  92. package/templates/podcast-creator/tier5-src/himi-events-detail/index.ts +112 -21
  93. package/templates/podcast-creator-owner/dev/index.ts +571 -0
  94. package/templates/podcast-creator-owner/himalaya.content.json +6 -0
  95. package/templates/podcast-creator-owner/tier5-src/_shared/owner-today-rollup.ts +307 -0
  96. package/templates/podcast-creator-owner/tier5-src/_shared/owner-widget-reads.ts +23 -0
  97. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-today/index.ts +8 -20
  98. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-today-rollup/index.ts +121 -0
  99. package/templates/portfolio-creative/dev/index.ts +397 -2
  100. package/templates/portfolio-creative/tier5-src/_shared/iap-attendance-form.ts +106 -0
  101. package/templates/portfolio-creative/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
  102. package/templates/portfolio-creative/tier5-src/_shared/iap-attendance.ts +38 -0
  103. package/templates/portfolio-creative/tier5-src/himi-events-detail/index.ts +112 -21
  104. package/templates/portfolio-creative-owner/dev/index.ts +571 -0
  105. package/templates/portfolio-creative-owner/himalaya.content.json +6 -0
  106. package/templates/portfolio-creative-owner/tier5-src/_shared/owner-today-rollup.ts +307 -0
  107. package/templates/portfolio-creative-owner/tier5-src/_shared/owner-widget-reads.ts +23 -0
  108. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-today/index.ts +8 -20
  109. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-today-rollup/index.ts +121 -0
  110. package/templates/restaurant/dev/index.ts +397 -2
  111. package/templates/restaurant/tier5-src/_shared/iap-attendance-form.ts +106 -0
  112. package/templates/restaurant/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
  113. package/templates/restaurant/tier5-src/_shared/iap-attendance.ts +38 -0
  114. package/templates/restaurant/tier5-src/himi-events-detail/index.ts +112 -21
  115. package/templates/restaurant-owner/dev/index.ts +571 -0
  116. package/templates/restaurant-owner/himalaya.content.json +6 -0
  117. package/templates/restaurant-owner/tier5-src/_shared/owner-today-rollup.ts +307 -0
  118. package/templates/restaurant-owner/tier5-src/_shared/owner-widget-reads.ts +23 -0
  119. package/templates/restaurant-owner/tier5-src/himi-owner-lite-today/index.ts +8 -20
  120. package/templates/restaurant-owner/tier5-src/himi-owner-lite-today-rollup/index.ts +121 -0
  121. package/templates/retail-store-owner/dev/index.ts +571 -0
  122. package/templates/retail-store-owner/himalaya.content.json +6 -0
  123. package/templates/retail-store-owner/tier5-src/_shared/owner-today-rollup.ts +307 -0
  124. package/templates/retail-store-owner/tier5-src/_shared/owner-widget-reads.ts +23 -0
  125. package/templates/retail-store-owner/tier5-src/himi-owner-lite-today/index.ts +8 -20
  126. package/templates/retail-store-owner/tier5-src/himi-owner-lite-today-rollup/index.ts +121 -0
  127. package/templates/yoga-studio/dev/index.ts +828 -39
  128. package/templates/yoga-studio/tier5-src/_shared/iap-attendance-form.ts +106 -0
  129. package/templates/yoga-studio/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
  130. package/templates/yoga-studio/tier5-src/_shared/iap-attendance.ts +38 -0
  131. package/templates/yoga-studio/tier5-src/himi-booking-time/index.ts +52 -7
  132. package/templates/yoga-studio/tier5-src/himi-events-detail/index.ts +112 -21
  133. package/templates/yoga-studio-owner/dev/index.ts +571 -0
  134. package/templates/yoga-studio-owner/himalaya.content.json +6 -0
  135. package/templates/yoga-studio-owner/tier5-src/_shared/owner-today-rollup.ts +307 -0
  136. package/templates/yoga-studio-owner/tier5-src/_shared/owner-widget-reads.ts +23 -0
  137. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-today/index.ts +8 -20
  138. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-today-rollup/index.ts +121 -0
@@ -677,9 +677,9 @@ function createPurchaseCoordinator(deps) {
677
677
  if (session.kind !== "member") return requireSignIn();
678
678
  if (listing === "listed") clearReconcileProblem();
679
679
  const now = deps.clock.now();
680
- const eligible = itemsWhere((item) => isAwaitingDelivery(item) && (item.state.nextAttemptAt === null || item.state.nextAttemptAt <= now));
681
- eligible.forEach(restartAttemptBudget);
682
- await settleDelivery(session, await deliver(session, eligible));
680
+ const eligible2 = itemsWhere((item) => isAwaitingDelivery(item) && (item.state.nextAttemptAt === null || item.state.nextAttemptAt <= now));
681
+ eligible2.forEach(restartAttemptBudget);
682
+ await settleDelivery(session, await deliver(session, eligible2));
683
683
  }
684
684
  async function settleDelivery(session, delivered) {
685
685
  applyDelivered(delivered);
@@ -1209,7 +1209,8 @@ function applePrice(mapping, products) {
1209
1209
  const matches = products.filter((value) => isObject2(value) && value.id === mapping.productId);
1210
1210
  const product = matches[0];
1211
1211
  if (matches.length !== 1 || !nonempty(product?.displayPrice)) return unavailable(mapping.reference, "priceUnavailable");
1212
- if (product?.type !== "nonConsumable") return unavailable(mapping.reference, "unsupportedProductType");
1212
+ const attendance = mapping.reference.kind === "bookingsService" || mapping.reference.kind === "eventsTicket";
1213
+ if (product?.type !== (attendance ? "consumable" : "nonConsumable")) return unavailable(mapping.reference, "unsupportedProductType");
1213
1214
  return {
1214
1215
  reference: mapping.reference,
1215
1216
  status: "ready",
@@ -1228,6 +1229,9 @@ var sameReference = (value, reference) => isObject2(value) && value.kind === ref
1228
1229
 
1229
1230
  // ../../core/sdk/iap/src/wix-payments-contract.ts
1230
1231
  var HIMALAYA_SERVE_IAP_ROUTE = { prefix: "/himalaya-serve/v1/iap" };
1232
+ var BOOKINGS_APPLE_SALES_ENABLED = false;
1233
+ var EVENTS_APPLE_SALES_ENABLED = false;
1234
+ var ATTENDANCE_SALE_RULE = { appProductId: (id2) => id2, productType: "CONSUMABLE" };
1231
1235
  var STORES_ITEM_PAYMENT_ENABLED = false;
1232
1236
  var STORES_APPLE_SALES_ENABLED = true;
1233
1237
  var STORES_PRODUCT_SALE_RULE = { appProductId: (id2) => id2, productType: "NON_CONSUMABLE" };
@@ -1238,10 +1242,17 @@ function appleSaleRules(options = {}) {
1238
1242
  return {
1239
1243
  onlineProgram: ONLINE_PROGRAM_SALE_RULE,
1240
1244
  ...(options.storesAppleSalesEnabled ?? STORES_APPLE_SALES_ENABLED) || (options.storesItemPaymentEnabled ?? STORES_ITEM_PAYMENT_ENABLED) ? { storesProduct: STORES_PRODUCT_SALE_RULE } : {},
1241
- ...options.pricingPlanAppleSalesEnabled ?? PRICING_PLAN_APPLE_SALES_ENABLED ? { pricingPlan: PRICING_PLAN_SALE_RULE } : {}
1245
+ ...options.pricingPlanAppleSalesEnabled ?? PRICING_PLAN_APPLE_SALES_ENABLED ? { pricingPlan: PRICING_PLAN_SALE_RULE } : {},
1246
+ ...options.bookingsAppleSalesEnabled ?? BOOKINGS_APPLE_SALES_ENABLED ? { bookingsService: ATTENDANCE_SALE_RULE } : {},
1247
+ ...options.eventsAppleSalesEnabled ?? EVENTS_APPLE_SALES_ENABLED ? { eventsTicket: ATTENDANCE_SALE_RULE } : {}
1242
1248
  };
1243
1249
  }
1244
1250
  var APPLE_SALE_RULES = appleSaleRules();
1251
+ var APPLE_PROVISIONING_RULES = {
1252
+ ...APPLE_SALE_RULES,
1253
+ bookingsService: ATTENDANCE_SALE_RULE,
1254
+ eventsTicket: ATTENDANCE_SALE_RULE
1255
+ };
1245
1256
 
1246
1257
  // ../../core/sdk/iap/src/mapping-source.ts
1247
1258
  function iapMappingSource() {
@@ -1904,6 +1915,109 @@ var COMPLETE_PAYMENT_CODES = [
1904
1915
  ];
1905
1916
  var GET_PAYMENT_CODES = ["NOT_FOUND"];
1906
1917
 
1918
+ // ../../core/sdk/iap/src/attendance-classifier.ts
1919
+ function classifyForApple(item, currency) {
1920
+ if (item.hidden !== false || item.attendance === "hybrid") return "decide";
1921
+ if (item.kind === "bookingsService") return bookingRoute(item, currency);
1922
+ return ticketRoute(item, currency);
1923
+ }
1924
+ function bookingRoute(item, currency) {
1925
+ if (item.onlineBooking !== true) return "decide";
1926
+ if (item.conferencing === false && item.locations?.length && item.locations.every((type) => type === "BUSINESS" || type === "CUSTOMER" || type === "CUSTOM")) {
1927
+ return item.attendance === "online" ? "decide" : "wixPayments";
1928
+ }
1929
+ if (item.conferencing !== true || item.attendance === "physical") return "decide";
1930
+ if (item.attendance !== "online" && (!item.locations || item.locations.length > 0)) return "decide";
1931
+ if (item.type === "APPOINTMENT") {
1932
+ return item.capacity === 1 && item.maxParticipantsPerBooking === 1 ? "wixPayments" : "decide";
1933
+ }
1934
+ if (item.type !== "CLASS" && item.type !== "COURSE" || !item.capacity || item.capacity <= 1) return "decide";
1935
+ if (item.priceType === "NO_FEE" || zeroPrice(item.amount)) return "wixPayments";
1936
+ if (item.onlinePayment !== true || item.deposit !== false || item.priceType !== "FIXED") return "decide";
1937
+ return fixedPriceRoute(item, currency);
1938
+ }
1939
+ function ticketRoute(item, currency) {
1940
+ if (item.location === "VENUE") return item.attendance === "online" ? "decide" : "wixPayments";
1941
+ if (item.location !== "ONLINE" || item.attendance === "physical" || item.registration !== "TICKETING") return "decide";
1942
+ if (item.eventStatus !== "UPCOMING" && item.eventStatus !== "STARTED") return "decide";
1943
+ if (item.saleStatus !== "SALE_STARTED") return "decide";
1944
+ if (zeroPrice(item.amount)) return "wixPayments";
1945
+ return item.priceType === "STANDARD" ? fixedPriceRoute(item, currency) : "decide";
1946
+ }
1947
+ function fixedPriceRoute(item, currency) {
1948
+ const amount = item.amount;
1949
+ return typeof amount === "string" && /^\d+(?:\.\d+)?$/.test(amount) && Number.isFinite(Number(amount)) && Number(amount) > 0 && /^[A-Z]{3}$/.test(currency) && item.currency === currency ? "appleIap" : "decide";
1950
+ }
1951
+ function bookingAttendanceOf(raw) {
1952
+ const s2 = object(raw);
1953
+ const payment = object(s2.payment);
1954
+ const fixed = object(payment.fixed);
1955
+ const price = object(fixed.price);
1956
+ const options = object(payment.options);
1957
+ const policy = object(object(s2.bookingPolicy).participantsPolicy);
1958
+ return {
1959
+ kind: "bookingsService",
1960
+ type: text(s2.type),
1961
+ capacity: numeric(s2.defaultCapacity),
1962
+ maxParticipantsPerBooking: policy.enabled === true ? numeric(policy.maxParticipantsPerBooking) : void 0,
1963
+ hidden: boolean(s2.hidden),
1964
+ conferencing: boolean(object(s2.conferencing).enabled),
1965
+ locations: Array.isArray(s2.locations) ? s2.locations.map((l) => text(object(l).type) ?? "UNKNOWN") : void 0,
1966
+ onlineBooking: boolean(object(s2.onlineBooking).enabled),
1967
+ onlinePayment: boolean(options.online),
1968
+ deposit: options.deposit === true || fixed.deposit !== void 0,
1969
+ priceType: text(payment.rateType),
1970
+ amount: text(price.value),
1971
+ currency: text(price.currency)
1972
+ };
1973
+ }
1974
+ function ticketAttendanceOf(event, definition) {
1975
+ const e = object(event);
1976
+ const t = object(definition);
1977
+ const pricing = object(t.pricingMethod);
1978
+ const price = object(pricing.fixedPrice);
1979
+ const registration = object(e.registration);
1980
+ const type = text(registration.type) ?? text(registration.initialType) ?? text(e.eventType);
1981
+ const status = text(e.status) ?? text(e.eventStatus);
1982
+ return {
1983
+ kind: "eventsTicket",
1984
+ location: text(object(e.location).type),
1985
+ registration: type === "TICKETS" || type === "RSVP_AND_TICKETS" ? "TICKETING" : type,
1986
+ eventStatus: status === "SCHEDULED" ? "UPCOMING" : status,
1987
+ saleStatus: text(t.saleStatus),
1988
+ hidden: boolean(t.hidden),
1989
+ priceType: text(pricing.pricingType),
1990
+ amount: text(price.value),
1991
+ currency: text(price.currency)
1992
+ };
1993
+ }
1994
+ function availableTicketAttendanceOf(event, ticket) {
1995
+ const e = object(event);
1996
+ const t = object(ticket);
1997
+ const pricing = object(t.pricing);
1998
+ const fixed = object(pricing.fixedPrice);
1999
+ const price = object(t.price);
2000
+ const visible = Array.isArray(t.state) && t.state.length === 0 && object(t.dashboard).hidden !== true && typeof t.id === "string" && t.id.length > 0 && typeof e.id === "string" && e.id.length > 0 && t.eventId === e.id;
2001
+ const fixedPrice = t.free === false && pricing.pricingType === "STANDARD" && sameTicketAmount(fixed.amount, price.amount) && fixed.currency === price.currency;
2002
+ return ticketAttendanceOf(e, {
2003
+ hidden: visible ? false : void 0,
2004
+ saleStatus: t.saleStatus,
2005
+ pricingMethod: { pricingType: fixedPrice ? "STANDARD" : void 0, fixedPrice: { value: fixed.amount, currency: fixed.currency } }
2006
+ });
2007
+ }
2008
+ function sameTicketAmount(left, right) {
2009
+ const valid = (value) => typeof value === "string" && /^\d+(?:\.\d+)?$/.test(value);
2010
+ const normalized = (value) => value.replace(/^0+(?=\d)/, "").replace(/(\.\d*?)0+$/, "$1").replace(/\.$/, "");
2011
+ return valid(left) && valid(right) && normalized(left) === normalized(right);
2012
+ }
2013
+ function object(value) {
2014
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
2015
+ }
2016
+ var text = (value) => typeof value === "string" ? value : void 0;
2017
+ var numeric = (value) => typeof value === "number" ? value : void 0;
2018
+ var boolean = (value) => typeof value === "boolean" ? value : void 0;
2019
+ var zeroPrice = (value) => typeof value === "string" && /^0+(?:\.0+)?$/.test(value);
2020
+
1907
2021
  // ../../core/sdk/iap/src/index.ts
1908
2022
  async function getProducts(productIds) {
1909
2023
  if (!productIds || productIds.length === 0) return [];
@@ -2201,11 +2315,11 @@ function partitionKey(key) {
2201
2315
  return `${PREFIX}.${key.purchasesAppId}.${key.siteId}.${memberKey(key.memberId)}`;
2202
2316
  }
2203
2317
  function memberKey(memberId) {
2204
- const text2 = memberId.toLowerCase();
2318
+ const text3 = memberId.toLowerCase();
2205
2319
  let h1 = 3735928559;
2206
2320
  let h2 = 1103547991;
2207
- for (let i = 0; i < text2.length; i++) {
2208
- const code = text2.charCodeAt(i);
2321
+ for (let i = 0; i < text3.length; i++) {
2322
+ const code = text3.charCodeAt(i);
2209
2323
  h1 = Math.imul(h1 ^ code, 2654435761);
2210
2324
  h2 = Math.imul(h2 ^ code, 1597334677);
2211
2325
  }
@@ -2244,9 +2358,9 @@ function isUUID3(value) {
2244
2358
  }
2245
2359
  var VERSION = 1;
2246
2360
  var PREFIX = "himi.iap.wix-checkout.v1";
2247
- var STAGES = /* @__PURE__ */ new Set(["startingItem", "ordered", "charged", "started", "submitted", "held", "needsSupport"]);
2361
+ var STAGES = /* @__PURE__ */ new Set(["startingItem", "openingOrder", "ordered", "charged", "started", "submitted", "fulfilled", "held", "needsSupport"]);
2248
2362
  var HOLD_MS = { held: NEEDS_SUPPORT_HOLD_MS, needsSupport: NEEDS_SUPPORT_HOLD_MS, startingItem: ITEM_START_HOLD_MS };
2249
- var EVICTABLE = /* @__PURE__ */ new Set(["ordered", "charged", "started"]);
2363
+ var EVICTABLE = /* @__PURE__ */ new Set(["fulfilled", "ordered", "charged", "started"]);
2250
2364
 
2251
2365
  // ../../stdlib/flows/iap-checkout/src/wix-bridge.ts
2252
2366
  function bindBridge(session, provider, bridge) {
@@ -2287,10 +2401,10 @@ function isLiveHost(bridge) {
2287
2401
  }
2288
2402
  function refusalOf(error) {
2289
2403
  const message = error?.message;
2290
- const text2 = typeof message === "string" ? message : "";
2291
- if (BRIDGE_REFUSAL2.test(text2)) return { status: "notEnabled" };
2292
- if (PRINCIPAL_CHANGED2.test(text2)) return SESSION_CHANGED;
2293
- const http = /^HTTP (\d{3})(?: \[([^\]]+)\])?:/.exec(text2);
2404
+ const text3 = typeof message === "string" ? message : "";
2405
+ if (BRIDGE_REFUSAL2.test(text3)) return { status: "notEnabled" };
2406
+ if (PRINCIPAL_CHANGED2.test(text3)) return SESSION_CHANGED;
2407
+ const http = /^HTTP (\d{3})(?: \[([^\]]+)\])?:/.exec(text3);
2294
2408
  if (!http) return { status: "unavailable" };
2295
2409
  return httpRefusal(Number(http[1]), http[2] ?? "");
2296
2410
  }
@@ -2346,12 +2460,19 @@ function createWixOrderBackend(deps) {
2346
2460
  const stage = refAt(sale.partition, sale.catalogRef)?.stage;
2347
2461
  const failure3 = stage && BLOCKING_STAGES[stage];
2348
2462
  if (failure3) return stopWith("rejected", failure3);
2463
+ if (sale.adapter.repeatable) {
2464
+ const prefix = `${sale.item.reference.kind}:${sale.item.reference.id}#`;
2465
+ const unresolved = sale.partition.refs().find((ref) => ref.key.startsWith(prefix) && ["openingOrder", "held", "needsSupport"].includes(ref.stage));
2466
+ if (unresolved) return stopWith("rejected", unresolved.stage === "openingOrder" ? "outcomeUnknown" : "needsSupport");
2467
+ }
2349
2468
  return deps.productBusy?.(sale.appleProduct.productId) ? stopWith("rejected", "paymentInProgress") : null;
2350
2469
  }
2351
2470
  async function saleFor(session, catalogRef) {
2352
2471
  const sold = deps.itemFor(catalogRef);
2353
2472
  const adapter = sold && adapterFor(sold.item.reference.kind);
2354
2473
  if (!sold || !adapter) return stopWith("rejected", "unsupportedItem");
2474
+ if (adapter.repeatable && !sold.item.attemptId) return stopWith("rejected", "unsupportedItem");
2475
+ if (!adapter.repeatable && sold.item.attemptId) return stopWith("rejected", "unsupportedItem");
2355
2476
  const eligibility = adapter.eligibility(sold.item);
2356
2477
  if (!eligibility.eligible) return stopWith("rejected", eligibility.reason);
2357
2478
  const member = await memberOf(session);
@@ -2371,15 +2492,37 @@ function createWixOrderBackend(deps) {
2371
2492
  }
2372
2493
  async function orderFor(sale) {
2373
2494
  const existing = refAt(sale.partition, sale.catalogRef);
2374
- const attempt4 = existing?.cashierOrderId && existing.verticalRef ? await reopenOrOpen(sale, { cashierOrderId: existing.cashierOrderId, verticalRef: existing.verticalRef }) : await sale.adapter.openOrder(sale.item, sale.bridge);
2375
- return recordOrder(sale, existing, attempt4);
2495
+ let prevented;
2496
+ const beforeCreate = () => {
2497
+ if (!sale.adapter.repeatable || existing) return true;
2498
+ if (!sale.bridge.isCurrent()) {
2499
+ prevented = STALE2;
2500
+ return false;
2501
+ }
2502
+ const blocked = saleBlocked(sale);
2503
+ if (blocked) {
2504
+ prevented = blocked;
2505
+ return false;
2506
+ }
2507
+ const opening = persist(sale, { key: sale.catalogRef, kind: sale.adapter.kind, stage: "openingOrder", updatedAt: now() });
2508
+ if (isStop(opening)) {
2509
+ prevented = opening;
2510
+ return false;
2511
+ }
2512
+ return true;
2513
+ };
2514
+ const attempt4 = existing?.cashierOrderId && existing.verticalRef ? await reopenOrOpen(sale, { cashierOrderId: existing.cashierOrderId, verticalRef: existing.verticalRef }) : await sale.adapter.openOrder(sale.item, sale.bridge, beforeCreate);
2515
+ return prevented ?? recordOrder(sale, existing, attempt4);
2376
2516
  }
2377
2517
  async function reopenOrOpen(sale, order) {
2378
2518
  const reopened = await sale.adapter.reopenOrder(order, sale.bridge);
2379
2519
  const closed = reopened.status === "refused" && reopened.reason === "orderClosed";
2380
- return closed ? sale.adapter.openOrder(sale.item, sale.bridge) : reopened;
2520
+ return closed && !sale.adapter.repeatable ? sale.adapter.openOrder(sale.item, sale.bridge) : reopened;
2381
2521
  }
2382
2522
  function recordOrder(sale, existing, attempt4) {
2523
+ if (attempt4.noOrderCreated && refAt(sale.partition, sale.catalogRef)?.stage === "openingOrder" && !sale.partition.remove(sale.catalogRef)) {
2524
+ return stopWith("rejected", "storageUnavailable");
2525
+ }
2383
2526
  if (attempt4.status === "granted") return alreadyOwned(sale);
2384
2527
  if (attempt4.status === "refused") return stopWith("rejected", attempt4.reason);
2385
2528
  if (attempt4.status !== "open") return attempt4.status === "sessionChanged" ? STALE2 : retry("unavailable");
@@ -2417,6 +2560,7 @@ function createWixOrderBackend(deps) {
2417
2560
  }
2418
2561
  }
2419
2562
  async function reorder(sale) {
2563
+ if (sale.adapter.repeatable) return stopWith("rejected", "orderClosed");
2420
2564
  if (!forget(sale, sale.catalogRef)) return stopWith("rejected", "storageUnavailable");
2421
2565
  const recorded = recordOrder(sale, void 0, await sale.adapter.openOrder(sale.item, sale.bridge));
2422
2566
  return isStop(recorded) ? recorded : chargeFor(sale, recorded, { reordered: true });
@@ -2493,7 +2637,7 @@ function createWixOrderBackend(deps) {
2493
2637
  return stopWith("rejected", failure3.code === "NOT_PENDING" ? "orderClosed" : "paymentRefused");
2494
2638
  }
2495
2639
  function alreadyOwned(sale) {
2496
- forget(sale, sale.catalogRef);
2640
+ if (!sale.adapter.repeatable) forget(sale, sale.catalogRef);
2497
2641
  return stopWith("rejected", "alreadyOwned");
2498
2642
  }
2499
2643
  function persist(sale, ref) {
@@ -2543,7 +2687,9 @@ function createWixOrderBackend(deps) {
2543
2687
  return access === "granted";
2544
2688
  }
2545
2689
  function processed(proof, ref) {
2546
- proof.member.partition?.remove(ref.key);
2690
+ if (adapterFor(ref.kind)?.repeatable) {
2691
+ if (!proof.member.partition?.put({ ...ref, stage: "fulfilled", updatedAt: now() })) return RETRYABLE;
2692
+ } else proof.member.partition?.remove(ref.key);
2547
2693
  deps.report({ key: ref.key, access: "granted" });
2548
2694
  return { status: "processed", acknowledgement: proof.acknowledgement };
2549
2695
  }
@@ -2610,6 +2756,7 @@ var UNAVAILABLE = { stop: true, result: "retryable", failure: "unavailable" };
2610
2756
  var OUTCOME_UNKNOWN = { stop: true, result: "rejected", failure: "outcomeUnknown" };
2611
2757
  var BLOCKING_STAGES = {
2612
2758
  startingItem: "outcomeUnknown",
2759
+ openingOrder: "outcomeUnknown",
2613
2760
  submitted: "paymentInProgress",
2614
2761
  held: "paymentHeld",
2615
2762
  needsSupport: "needsSupport"
@@ -2868,6 +3015,12 @@ function enabledCheckout(deps) {
2868
3015
  for (const ref of tracked.partition.refs()) {
2869
3016
  if (!isCurrent(session)) return;
2870
3017
  if (ref.stage === "needsSupport") setPayment(ref.key, "needsSupport");
3018
+ if (ref.stage === "fulfilled" && !options.dueOnly) {
3019
+ const access = await accessOf2(session, ref);
3020
+ if (!isCurrent(session)) return;
3021
+ if (access === "granted") setPayment(ref.key, "granted");
3022
+ else if (access === "none") payments.delete(ref.key);
3023
+ }
2871
3024
  if (ref.stage !== "submitted" || !ref.paymentId) continue;
2872
3025
  if (!options.dueOnly) restartBudget(ref.key);
2873
3026
  if (isDue(ref.key, options.dueOnly)) await trackOne(session, tracked.partition, ref);
@@ -2922,7 +3075,10 @@ function enabledCheckout(deps) {
2922
3075
  backOff(partition, ref, access === "none");
2923
3076
  }
2924
3077
  function grant(partition, ref) {
2925
- partition.remove(ref.key);
3078
+ const repeatable = deps.adapters.some((adapter) => adapter.kind === ref.kind && adapter.repeatable);
3079
+ if (repeatable) {
3080
+ if (!partition.put({ ...ref, stage: "fulfilled", updatedAt: deps.clock.now() })) return backOff(partition, ref, false);
3081
+ } else partition.remove(ref.key);
2926
3082
  setPayment(ref.key, "granted");
2927
3083
  }
2928
3084
  function settleUnassociated(partition, ref) {
@@ -2991,7 +3147,8 @@ function isInFlight(item) {
2991
3147
  return item.access === "processing" || item.access === "confirming" || item.access === "pending" || item.access === "waitingToRetry";
2992
3148
  }
2993
3149
  function itemKey(item) {
2994
- return `${item.reference.kind}:${item.reference.id}`;
3150
+ const key = `${item.reference.kind}:${item.reference.id}`;
3151
+ return item.attemptId ? `${key}#${encodeURIComponent(item.attemptId)}` : key;
2995
3152
  }
2996
3153
  function labelOf(key) {
2997
3154
  return key.startsWith("payment:") ? "payment" : key;
@@ -3020,10 +3177,20 @@ var OVERLAY_PHASES = /* @__PURE__ */ new Set(["purchasing", "awaitingApproval",
3020
3177
  // ../../stdlib/flows/iap-checkout/src/purchase-fields.ts
3021
3178
  function iapPurchaseFields(view, state, readiness, copy) {
3022
3179
  const key = `${view.reference.kind}:${view.reference.id}`;
3180
+ const repeatable = view.reference.kind === "bookingsService" || view.reference.kind === "eventsTicket";
3023
3181
  if (view.route !== "appleIap" && !holdsSale(state, key)) return { ...action(copy, "enabled", ""), appleRoute: false };
3024
3182
  if (readiness.status !== "ready") return action(copy, "disabled", readiness.status === "checking" ? "" : copy.unavailable);
3025
- const own = state.item === key;
3026
- const payment = state.payments.find((tracked) => tracked.item === key)?.access;
3183
+ const own = sameItem(state.item, key);
3184
+ const matching = state.payments.filter((tracked) => sameItem(tracked.item, key));
3185
+ const payment = matching.find((p) => p.access === "needsSupport")?.access ?? matching.find((p) => p.access === "processing")?.access ?? matching[matching.length - 1]?.access;
3186
+ if (repeatable && payment === "needsSupport") return action(copy, "disabled", copy.support);
3187
+ if (repeatable && IN_FLIGHT.has(state.phase)) return action(copy, "busy", own ? copy.processing : "");
3188
+ if (repeatable && payment === "processing") return action(copy, "busy", copy.processing);
3189
+ if (repeatable && own && state.phase !== "accessReady" && state.phase !== "idle") {
3190
+ if (state.failure === "orderClosed") return action(copy, "disabled", copy.support);
3191
+ return outcomeAction(state, copy);
3192
+ }
3193
+ if (repeatable && (own && state.phase === "accessReady" || payment === "granted")) return action({ ...copy, buy: copy.buyAnother ?? copy.buy }, "enabled", "");
3027
3194
  if (own && state.phase === "accessReady" || payment === "granted") return { ...action(copy, "disabled", ""), accessReady: true };
3028
3195
  if (IN_FLIGHT.has(state.phase)) return action(copy, "busy", own ? copy.processing : "");
3029
3196
  if (own) return outcomeAction(state, copy);
@@ -3032,8 +3199,11 @@ function iapPurchaseFields(view, state, readiness, copy) {
3032
3199
  return action(copy, "enabled", "");
3033
3200
  }
3034
3201
  function holdsSale(state, key) {
3035
- if (state.payments.some((tracked) => tracked.item === key)) return true;
3036
- return state.item === key && (SALE_PHASES.has(state.phase) || state.purchase.phase === "awaitingApproval");
3202
+ if (state.payments.some((tracked) => sameItem(tracked.item, key))) return true;
3203
+ return sameItem(state.item, key) && (SALE_PHASES.has(state.phase) || state.purchase.phase === "awaitingApproval");
3204
+ }
3205
+ function sameItem(item, key) {
3206
+ return item === key || item?.startsWith(`${key}#`) === true;
3037
3207
  }
3038
3208
  function outcomeAction(state, copy) {
3039
3209
  if (state.purchase.phase === "awaitingApproval") return action(copy, "disabled", copy.awaitingApproval);
@@ -3054,7 +3224,7 @@ function outcomeAction(state, copy) {
3054
3224
  }
3055
3225
  function refusalAction(failure3, copy) {
3056
3226
  const [mode, note] = REFUSALS[failure3 ?? "unavailable"] ?? ["enabled", "retry"];
3057
- return action(copy, mode, note ? copy[note] : "");
3227
+ return action(copy, mode, note ? copy[note] ?? "" : "");
3058
3228
  }
3059
3229
  function action(copy, mode, note) {
3060
3230
  return { appleRoute: true, accessReady: false, buyLabel: copy.buy, buyDisabled: mode !== "enabled", buyBusy: mode === "busy", buyNote: note };
@@ -3485,6 +3655,154 @@ function isOneTimeUnlimited(order) {
3485
3655
  return pricing?.singlePaymentUnlimited === true;
3486
3656
  }
3487
3657
 
3658
+ // ../../stdlib/flows/iap-checkout/src/iap-verticals/attendance.ts
3659
+ var BOOKING = "bookingsService";
3660
+ var TICKET = "eventsTicket";
3661
+ var NOT_ENABLED = { status: "refused", reason: "notEnabled" };
3662
+ var CHANGED = { status: "refused", reason: "productChanged" };
3663
+ function attendanceOrdersWith(options) {
3664
+ const now = options.now ?? Date.now;
3665
+ return {
3666
+ bookingOrders: {
3667
+ kind: BOOKING,
3668
+ repeatable: true,
3669
+ eligibility: (item) => eligible(item, BOOKING, options.bookingsEnabled),
3670
+ openOrder: (item, bridge, beforeCreate) => options.bookingsEnabled ? openBooking(item, bridge, beforeCreate) : Promise.resolve(NOT_ENABLED),
3671
+ readAccess: bookingAccess,
3672
+ reopenOrder: (order, bridge) => reopen(order, bridge, bookingAccess)
3673
+ },
3674
+ eventTicketOrders: {
3675
+ kind: TICKET,
3676
+ repeatable: true,
3677
+ eligibility: (item) => eligible(item, TICKET, options.eventsEnabled),
3678
+ openOrder: (item, bridge, beforeCreate) => options.eventsEnabled ? openTicket(item, bridge, now, beforeCreate) : Promise.resolve(NOT_ENABLED),
3679
+ readAccess: ticketAccess,
3680
+ reopenOrder: (order, bridge) => reopen(order, bridge, ticketAccess, now)
3681
+ }
3682
+ };
3683
+ }
3684
+ var { bookingOrders, eventTicketOrders } = /* @__PURE__ */ attendanceOrdersWith({ bookingsEnabled: BOOKINGS_APPLE_SALES_ENABLED, eventsEnabled: EVENTS_APPLE_SALES_ENABLED });
3685
+ function eligible(item, kind, enabled) {
3686
+ if (!enabled) return { eligible: false, reason: "notEnabled" };
3687
+ if (!singleUnitOf(kind, item).eligible || !isNonEmpty3(item.attemptId) || !item.attendance) return UNSUPPORTED;
3688
+ const selection = kind === BOOKING ? item.attendance.booking : item.attendance.ticket;
3689
+ return selection ? { eligible: true } : UNSUPPORTED;
3690
+ }
3691
+ async function openBooking(item, bridge, beforeCreate) {
3692
+ if (!eligible(item, BOOKING, true).eligible) return notCreated(ORDER_REFUSED);
3693
+ const selected = item.attendance.booking;
3694
+ if (selected.slot.serviceId !== item.reference.id || !isNonEmpty3(selected.slot.startDate) || !isNonEmpty3(selected.slot.endDate)) return notCreated(ORDER_REFUSED);
3695
+ const read2 = await bridge.call("GET", `/bookings/v2/services/${encodeURIComponent(item.reference.id)}`);
3696
+ if (isRefusal(read2)) return notCreated(attemptRefused(read2));
3697
+ const service = bodyObject(read2, "service");
3698
+ const metadata = bookingAttendanceOf(service);
3699
+ if (classifyForApple(metadata, item.attendance.currency) !== "appleIap" || !samePrice({ amount: metadata.amount, currency: metadata.currency }, item)) return notCreated(CHANGED);
3700
+ if (isObject7(service?.onlineBooking) && service.onlineBooking.requireManualApproval === true) return notCreated({ status: "refused", reason: "approvalRequired" });
3701
+ const availability = await bridge.call("POST", "/bookings/v1/availability/query", { query: { filter: { serviceId: [item.reference.id], startDate: selected.slot.startDate, endDate: selected.slot.endDate, bookable: true } } });
3702
+ if (isRefusal(availability)) return notCreated(attemptRefused(availability));
3703
+ const entries = isObject7(availability.body) ? availability.body.availabilityEntries : void 0;
3704
+ if (!Array.isArray(entries) || !entries.some((entry) => isObject7(entry) && entry.bookable === true && matchesSlot(entry.slot, selected.slot))) return notCreated(CHANGED);
3705
+ if (beforeCreate && !beforeCreate()) return notCreated({ status: "refused", reason: "storageUnavailable" });
3706
+ const created = await bridge.call("POST", "/bookings/v2/bookings", { booking: { bookedEntity: { slot: selected.slot }, contactDetails: selected.contactDetails, totalParticipants: 1, selectedPaymentOption: "ONLINE", ...selected.formInfo ? { formInfo: selected.formInfo } : {} } });
3707
+ if (isRefusal(created)) return creationRefused(created);
3708
+ const bookingId = bodyObject(created, "booking")?.id;
3709
+ return isNonEmpty3(bookingId) ? bookingCheckout(item, bookingId, bridge) : ORDER_REFUSED;
3710
+ }
3711
+ async function bookingCheckout(item, bookingId, bridge) {
3712
+ const checkout = await bridge.call("POST", "/ecom/v1/checkouts", { lineItems: [{ quantity: 1, catalogReference: { appId: "13d21c63-b5ec-5912-8397-c3a5ddb27a97", catalogItemId: bookingId } }], channelType: "OTHER_PLATFORM" });
3713
+ if (isRefusal(checkout)) return attemptRefused(checkout);
3714
+ const entity = bodyObject(checkout, "checkout");
3715
+ const total = isObject7(entity?.priceSummary) ? entity.priceSummary.total : void 0;
3716
+ if (!isObject7(total) || !samePrice({ amount: total.amount, currency: entity?.currency }, item)) return CHANGED;
3717
+ if (!isNonEmpty3(entity?.id)) return ORDER_REFUSED;
3718
+ const placed = await bridge.call("POST", `/ecom/v1/checkouts/${encodeURIComponent(entity.id)}/create-order`, {});
3719
+ if (isRefusal(placed)) return attemptRefused(placed);
3720
+ const body = placed.body;
3721
+ if (!isObject7(body) || !isNonEmpty3(body.orderId) || !isNonEmpty3(body.paymentGatewayOrderId)) return ORDER_REFUSED;
3722
+ return { status: "open", cashierOrderId: body.paymentGatewayOrderId, verticalRef: { serviceId: item.reference.id, bookingId, orderId: body.orderId } };
3723
+ }
3724
+ async function bookingAccess(ref, bridge) {
3725
+ if (!ref.bookingId || !ref.orderId) return "unavailable";
3726
+ const order = await bridge.call("GET", `/ecom/v1/orders/${encodeURIComponent(ref.orderId)}`);
3727
+ if (isRefusal(order)) return accessRefused(order);
3728
+ const payment = bodyObject(order, "order")?.paymentStatus;
3729
+ if (payment === "FULLY_REFUNDED" || payment === "PARTIALLY_REFUNDED") return "none";
3730
+ const read2 = await bridge.call("POST", "/bookings/v2/bookings/query", { query: { filter: { id: { $eq: ref.bookingId } } } });
3731
+ if (isRefusal(read2)) return accessRefused(read2);
3732
+ const rows = isObject7(read2.body) ? read2.body.bookings : void 0;
3733
+ const booking = Array.isArray(rows) ? rows.find((b) => isObject7(b) && b.id === ref.bookingId) : void 0;
3734
+ if (!isObject7(booking)) return "unavailable";
3735
+ if (booking.status === "CANCELED" || booking.status === "CANCELLED" || booking.status === "DECLINED") return "none";
3736
+ return payment === "PAID" && booking.status === "CONFIRMED" && booking.paymentStatus === "PAID" ? "granted" : "pending";
3737
+ }
3738
+ async function openTicket(item, bridge, now, beforeCreate) {
3739
+ if (!eligible(item, TICKET, true).eligible) return notCreated(ORDER_REFUSED);
3740
+ const selected = item.attendance.ticket;
3741
+ if (!isNonEmpty3(selected.eventId)) return notCreated(ORDER_REFUSED);
3742
+ const read2 = await bridge.call("GET", `/events/v3/events/${encodeURIComponent(selected.eventId)}?fields=REGISTRATION&fields=DETAILS&fields=FORM`);
3743
+ if (isRefusal(read2)) return notCreated(attemptRefused(read2));
3744
+ const available = await bridge.call("POST", "/events/v1/checkout/available-tickets/query", { filter: { eventId: selected.eventId }, limit: 100, offset: 0 });
3745
+ if (isRefusal(available)) return notCreated(attemptRefused(available));
3746
+ const definitions = isObject7(available.body) ? available.body.definitions : void 0;
3747
+ const live = Array.isArray(definitions) ? definitions.find((t) => isObject7(t) && t.id === item.reference.id && t.saleStatus === "SALE_STARTED") : void 0;
3748
+ if (!isObject7(live) || !samePrice(live.price, item)) return notCreated(CHANGED);
3749
+ if (live.eventId !== selected.eventId || classifyForApple(availableTicketAttendanceOf(bodyObject(read2, "event"), live), item.attendance.currency) !== "appleIap") return notCreated(ORDER_REFUSED);
3750
+ if (beforeCreate && !beforeCreate()) return notCreated({ status: "refused", reason: "storageUnavailable" });
3751
+ return reserveTicket(item, bridge, now);
3752
+ }
3753
+ async function reserveTicket(item, bridge, now) {
3754
+ const selected = item.attendance.ticket;
3755
+ const held = await bridge.call("POST", "/events/v1/checkout/reservations", { eventId: selected.eventId, ticketQuantities: [{ ticketDefinitionId: item.reference.id, quantity: 1 }], ignoreLimits: false, allowHiddenTickets: false });
3756
+ if (isRefusal(held)) return creationRefused(held);
3757
+ const reservation = held.body;
3758
+ if (!isObject7(reservation) || !isNonEmpty3(reservation.id) || !future(reservation.expires, now)) return ORDER_CLOSED;
3759
+ const invoice = isObject7(reservation.invoice) ? reservation.invoice : {};
3760
+ if (!samePrice(invoice.grandTotal ?? invoice.total, item)) return CHANGED;
3761
+ const placed = await bridge.call("POST", "/events/v1/checkout", { eventId: selected.eventId, reservationId: reservation.id, buyer: selected.buyer, ...selected.guests ? { guests: selected.guests } : {}, ...selected.buyerSubmission ? { buyerSubmission: selected.buyerSubmission } : {}, ...selected.guestSubmissions ? { guestSubmissions: selected.guestSubmissions } : {}, options: { silent: false, payInPerson: false, ignoreFormValidation: false, markAsPaid: false } });
3762
+ if (isRefusal(placed)) return attemptRefused(placed);
3763
+ const order = bodyObject(placed, "order");
3764
+ if (!samePrice(order?.totalPrice, item)) return CHANGED;
3765
+ const expires = isObject7(placed.body) && placed.body.expires || reservation.expires;
3766
+ if (!future(expires, now) || !isNonEmpty3(order?.snapshotId) || !isNonEmpty3(order?.orderNumber)) return ORDER_CLOSED;
3767
+ return { status: "open", cashierOrderId: order.snapshotId, verticalRef: { eventId: selected.eventId, ticketDefinitionId: item.reference.id, reservationId: reservation.id, orderNumber: order.orderNumber, expires: String(expires) } };
3768
+ }
3769
+ async function ticketAccess(ref, bridge) {
3770
+ if (!ref.eventId || !ref.orderNumber || !ref.ticketDefinitionId) return "unavailable";
3771
+ const read2 = await bridge.call("GET", `/events/v1/events/${encodeURIComponent(ref.eventId)}/orders/${encodeURIComponent(ref.orderNumber)}?fieldset=DETAILS&fieldset=TICKETS`);
3772
+ if (isRefusal(read2)) return accessRefused(read2);
3773
+ const order = bodyObject(read2, "order");
3774
+ if (order?.status === "CANCELED" || order?.status === "CANCELLED" || order?.status === "REFUNDED") return "none";
3775
+ const issued = Array.isArray(order?.tickets) && order.tickets.some((t) => isObject7(t) && isNonEmpty3(t.ticketNumber) && t.orderStatus === "PAID" && t.ticketDefinitionId === ref.ticketDefinitionId);
3776
+ return order?.status === "PAID" && issued ? "granted" : order ? "pending" : "unavailable";
3777
+ }
3778
+ async function reopen(order, bridge, accessOf2, now) {
3779
+ const access = await accessOf2(order.verticalRef, bridge);
3780
+ if (access === "granted") return GRANTED;
3781
+ if (access === "unavailable" || access === "sessionChanged") return { status: access };
3782
+ if (access === "none" || now && !future(order.verticalRef.expires, now)) return ORDER_CLOSED;
3783
+ return { status: "open", ...order };
3784
+ }
3785
+ function samePrice(value, item) {
3786
+ return isObject7(value) && value.currency === item.attendance?.currency && decimal(value.amount) !== null && decimal(value.amount) === decimal(item.attendance?.amount);
3787
+ }
3788
+ function decimal(value) {
3789
+ if (typeof value !== "string" || !/^\d+(?:\.\d+)?$/.test(value)) return null;
3790
+ return value.replace(/^0+(?=\d)/, "").replace(/(\.\d*?)0+$/, "$1").replace(/\.$/, "");
3791
+ }
3792
+ function future(value, now) {
3793
+ return typeof value === "string" && Number.isFinite(Date.parse(value)) && Date.parse(value) > now();
3794
+ }
3795
+ function matchesSlot(value, selected) {
3796
+ return isObject7(value) && ["serviceId", "sessionId"].every((key) => value[key] === selected[key]) && ["startDate", "endDate"].every((key) => typeof value[key] === "string" && Date.parse(value[key]) === Date.parse(String(selected[key])));
3797
+ }
3798
+ function creationRefused(refusal) {
3799
+ const attempt4 = attemptRefused(refusal);
3800
+ return refusal.status === "http" && [400, 401, 403, 404, 405, 409, 410, 415, 422].includes(refusal.httpStatus) ? notCreated(attempt4) : attempt4;
3801
+ }
3802
+ function notCreated(attempt4) {
3803
+ return { ...attempt4, noOrderCreated: true };
3804
+ }
3805
+
3488
3806
  // ../../stdlib/wix-sdk/redirects-v1/src/index.ts
3489
3807
  function wixCallHeaders(opts) {
3490
3808
  const site = opts?.site?.trim();
@@ -3521,7 +3839,7 @@ var hideWhen = (n, path) => ({
3521
3839
  ...n,
3522
3840
  modifiers: { ...n.modifiers ?? {}, hiddenPath: path }
3523
3841
  });
3524
- var text = (id2, value, style = "body") => node(id2, "Text", { text: value, style });
3842
+ var text2 = (id2, value, style = "body") => node(id2, "Text", { text: value, style });
3525
3843
  var vstack = (id2, children, spacing = 12, alignment = "leading") => node(id2, "VStack", { spacing, alignment, children });
3526
3844
  var button = (id2, title, action2, style = "primary") => node(id2, "Button", { title, style, fullWidth: true, action: action2 });
3527
3845
  var openScreen = (screenId) => ({ actionId: "himi.open", params: { screenId } });
@@ -3546,7 +3864,7 @@ function detailedHeader(opts) {
3546
3864
  spacing: 8,
3547
3865
  alignment: "center",
3548
3866
  children: [
3549
- text(`${id2}.location`, opts.locationLabel, "caption"),
3867
+ text2(`${id2}.location`, opts.locationLabel, "caption"),
3550
3868
  node(`${id2}.location.action`, "Button", {
3551
3869
  title: opts.locationAction.label,
3552
3870
  style: opts.locationAction.style ?? "plain",
@@ -3556,7 +3874,7 @@ function detailedHeader(opts) {
3556
3874
  ]
3557
3875
  }));
3558
3876
  } else {
3559
- identity.push(text(`${id2}.location`, opts.locationLabel, "caption"));
3877
+ identity.push(text2(`${id2}.location`, opts.locationLabel, "caption"));
3560
3878
  }
3561
3879
  }
3562
3880
  cardChildren.push(node(`${id2}.identity`, "HStack", { spacing: 12, alignment: "center", children: identity }));
@@ -3624,9 +3942,9 @@ function authScreen(opts) {
3624
3942
  ...extra
3625
3943
  });
3626
3944
  const children = [
3627
- text(`${s2}.headline`, `$service:${s2}.headline`, "title1"),
3628
- text(`${s2}.subhead`, `$service:${s2}.subhead`),
3629
- hideWhen(text(`${s2}.notice`, `$service:${s2}.notice`, "bodyEmphasis"), `$service:${s2}.noNotice`),
3945
+ text2(`${s2}.headline`, `$service:${s2}.headline`, "title1"),
3946
+ text2(`${s2}.subhead`, `$service:${s2}.subhead`),
3947
+ hideWhen(text2(`${s2}.notice`, `$service:${s2}.notice`, "bodyEmphasis"), `$service:${s2}.noNotice`),
3630
3948
  hideWhen(
3631
3949
  field("email", c.emailLabel ?? "Email", `tier5.${s2}.setEmail`, { keyboard: "email" }),
3632
3950
  `$service:${s2}.signedIn`
@@ -4109,18 +4427,18 @@ function checkoutScreen(opts) {
4109
4427
  const row = vstack(
4110
4428
  `${s2}.row`,
4111
4429
  [
4112
- hideWhen(text(`${s2}.row_badge`, "$item.badge", "caption1"), "$item.noBadge"),
4113
- text(`${s2}.row_name`, "$item.name", "title2"),
4114
- text(`${s2}.row_price`, "$item.priceLine", "title1"),
4115
- text(`${s2}.row_period`, "$item.periodLine", "caption1"),
4116
- text(`${s2}.row_desc`, "$item.description"),
4117
- text(`${s2}.row_note`, "$item.joinNote", "caption1"),
4118
- hideWhen(text(`${s2}.row_perk1`, "$item.perk1"), "$item.noPerk1"),
4119
- hideWhen(text(`${s2}.row_perk2`, "$item.perk2"), "$item.noPerk2"),
4120
- hideWhen(text(`${s2}.row_perk3`, "$item.perk3"), "$item.noPerk3"),
4430
+ hideWhen(text2(`${s2}.row_badge`, "$item.badge", "caption1"), "$item.noBadge"),
4431
+ text2(`${s2}.row_name`, "$item.name", "title2"),
4432
+ text2(`${s2}.row_price`, "$item.priceLine", "title1"),
4433
+ text2(`${s2}.row_period`, "$item.periodLine", "caption1"),
4434
+ text2(`${s2}.row_desc`, "$item.description"),
4435
+ text2(`${s2}.row_note`, "$item.joinNote", "caption1"),
4436
+ hideWhen(text2(`${s2}.row_perk1`, "$item.perk1"), "$item.noPerk1"),
4437
+ hideWhen(text2(`${s2}.row_perk2`, "$item.perk2"), "$item.noPerk2"),
4438
+ hideWhen(text2(`${s2}.row_perk3`, "$item.perk3"), "$item.noPerk3"),
4121
4439
  // The plan the member already holds shows a label, not a button. Selling
4122
4440
  // someone the thing they are currently paying for is the obvious next bug.
4123
- hideWhen(text(`${s2}.row_joined`, "$item.joinedLabel", "bodyEmphasis"), "$item.notJoined"),
4441
+ hideWhen(text2(`${s2}.row_joined`, "$item.joinedLabel", "bodyEmphasis"), "$item.notJoined"),
4124
4442
  hideWhen(
4125
4443
  node(`${s2}.row_join`, "Button", {
4126
4444
  title: "$item.cta",
@@ -4135,21 +4453,21 @@ function checkoutScreen(opts) {
4135
4453
  6
4136
4454
  );
4137
4455
  const children = [
4138
- text(`${s2}.headline`, `$service:${s2}.headline`, "title1"),
4139
- text(`${s2}.subhead`, `$service:${s2}.subhead`),
4140
- hideWhen(text(`${s2}.loading`, c.loadingText ?? "Loading plans\u2026"), `$service:${s2}.notLoading`),
4456
+ text2(`${s2}.headline`, `$service:${s2}.headline`, "title1"),
4457
+ text2(`${s2}.subhead`, `$service:${s2}.subhead`),
4458
+ hideWhen(text2(`${s2}.loading`, c.loadingText ?? "Loading plans\u2026"), `$service:${s2}.notLoading`),
4141
4459
  // A site with no plans is a real state, not an impossible one, and hiding the
4142
4460
  // list alone leaves a headline over blank space. Bound to a flag the SERVICE
4143
4461
  // computes: `hiddenPath` is a single path, so nesting two hideWhen calls to
4144
4462
  // mean "ready AND empty" just overwrites the inner one and shows this line
4145
4463
  // during the first load.
4146
4464
  hideWhen(
4147
- text(`${s2}.empty`, c.emptyText ?? "No plans are available right now."),
4465
+ text2(`${s2}.empty`, c.emptyText ?? "No plans are available right now."),
4148
4466
  `$service:${s2}.notEmptyCatalog`
4149
4467
  ),
4150
- hideWhen(text(`${s2}.error`, `$service:${s2}.error`), `$service:${s2}.noError`),
4468
+ hideWhen(text2(`${s2}.error`, `$service:${s2}.error`), `$service:${s2}.noError`),
4151
4469
  // Result of a join attempt — never a dead button.
4152
- hideWhen(text(`${s2}.notice`, `$service:${s2}.notice`, "bodyEmphasis"), `$service:${s2}.noNotice`)
4470
+ hideWhen(text2(`${s2}.notice`, `$service:${s2}.notice`, "bodyEmphasis"), `$service:${s2}.noNotice`)
4153
4471
  ];
4154
4472
  if (opts.signInScreenId) {
4155
4473
  children.push(
@@ -338,6 +338,10 @@ function getEventGuestList(eventId, opts = {}) {
338
338
  if (query) params.push(`query=${encodeURIComponent(query)}`);
339
339
  return wixCall("GET", `${BASE}/events/${encodeURIComponent(eventId)}/guest-list/v2?${params.join("&")}`);
340
340
  }
341
+ function getTicketDefinition(id) {
342
+ if (!id) throw new Error("getTicketDefinition: id is required");
343
+ return wixCall("GET", `/events/v3/ticket-definitions/${encodeURIComponent(id)}`);
344
+ }
341
345
  function queryAvailableTickets(eventId, limit = 100) {
342
346
  if (!eventId) throw new Error("queryAvailableTickets: eventId is required");
343
347
  return wixCall("POST", "/events/v1/checkout/available-tickets/query", {
@@ -402,6 +406,7 @@ export {
402
406
  getEvent,
403
407
  getEventGuestList,
404
408
  getEventsOrder,
409
+ getTicketDefinition,
405
410
  normalizeEvent,
406
411
  normalizeEventAt,
407
412
  queryAvailableTickets,