@vtex/faststore 0.0.8 → 0.0.11

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 (568) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/README.md +0 -1
  3. package/dist/actions.json +48 -1
  4. package/dist/catalog.json +1397 -1594
  5. package/dist/cli/index.d.ts +66 -28
  6. package/dist/cli/index.js +7371 -512
  7. package/dist/cli/index.js.map +1 -1
  8. package/dist/cli/server-runtime.js +41 -60
  9. package/dist/cli/server-runtime.js.map +1 -1
  10. package/dist/client.d.ts +3 -3
  11. package/dist/client.js +2 -2
  12. package/dist/components.d.ts +67 -56
  13. package/dist/components.js +64 -53
  14. package/dist/content-types.json +5886 -555
  15. package/dist/core/dist/define-component.d.ts +7 -2
  16. package/dist/core/dist/define-content-type.d.ts +50 -2
  17. package/dist/core/dist/define-content-type.js +107 -3
  18. package/dist/core/dist/define-content-type.js.map +1 -1
  19. package/dist/core/dist/index.d.ts +2 -2
  20. package/dist/docs/access-code-field.md +1 -1
  21. package/dist/docs/access-code-sign-in.md +126 -77
  22. package/dist/docs/account-address-book.md +210 -95
  23. package/dist/docs/account-entry-point.md +4 -4
  24. package/dist/docs/account-menu.md +16 -17
  25. package/dist/docs/account-saved-cards.md +306 -0
  26. package/dist/docs/alert-dialog.md +3 -1
  27. package/dist/docs/avatar.md +4 -2
  28. package/dist/docs/billing-address.md +99 -30
  29. package/dist/docs/binding-switcher.md +157 -0
  30. package/dist/docs/buy-button.md +7 -8
  31. package/dist/docs/card-entry.md +42 -29
  32. package/dist/docs/card-summary.md +185 -0
  33. package/dist/docs/cardholder-document.md +5 -3
  34. package/dist/docs/carousel.md +5 -4
  35. package/dist/docs/cart-destination.md +251 -0
  36. package/dist/docs/cart-item.md +48 -15
  37. package/dist/docs/cart-totalizer.md +8 -6
  38. package/dist/docs/cart.md +240 -39
  39. package/dist/docs/challenge-return.md +135 -0
  40. package/dist/docs/client-preferences-fieldset.md +10 -5
  41. package/dist/docs/client-preferences.md +31 -8
  42. package/dist/docs/client-profile-fieldset.md +20 -6
  43. package/dist/docs/client-profile.md +12 -3
  44. package/dist/docs/copy-text.md +9 -7
  45. package/dist/docs/document-field.md +1 -1
  46. package/dist/docs/email-field.md +2 -1
  47. package/dist/docs/email-identification.md +12 -2
  48. package/dist/docs/footer-copyright.md +4 -2
  49. package/dist/docs/footer-social.md +1 -1
  50. package/dist/docs/form.md +54 -18
  51. package/dist/docs/free-shipping-progress.md +18 -13
  52. package/dist/docs/identity-edit.md +8 -2
  53. package/dist/docs/identity-summary.md +18 -5
  54. package/dist/docs/incentives.md +2 -2
  55. package/dist/docs/installments.md +46 -32
  56. package/dist/docs/logo.md +1 -1
  57. package/dist/docs/my-account-profile.md +16 -11
  58. package/dist/docs/navigation-link.md +5 -3
  59. package/dist/docs/order-cancel.md +3 -1
  60. package/dist/docs/order-delivery-address.md +7 -5
  61. package/dist/docs/order-delivery-group.md +1 -3
  62. package/dist/docs/order-details-back.md +1 -1
  63. package/dist/docs/order-details-header.md +1 -4
  64. package/dist/docs/order-invoice-download.md +60 -0
  65. package/dist/docs/order-list-row.md +1 -1
  66. package/dist/docs/order-list-search.md +13 -20
  67. package/dist/docs/order-list-views.md +11 -17
  68. package/dist/docs/order-list.md +12 -5
  69. package/dist/docs/order-payment.md +9 -7
  70. package/dist/docs/order-placed-date.md +1 -1
  71. package/dist/docs/order-placed-payment-summary.md +28 -15
  72. package/dist/docs/order-placed.md +49 -14
  73. package/dist/docs/order-progress.md +1 -1
  74. package/dist/docs/order-status-badge.md +20 -9
  75. package/dist/docs/order-summary.md +2 -2
  76. package/dist/docs/order-tracking-link.md +58 -0
  77. package/dist/docs/payment-method-badges.md +32 -6
  78. package/dist/docs/payment-methods.md +2 -2
  79. package/dist/docs/payment.md +36 -17
  80. package/dist/docs/phone-field.md +4 -4
  81. package/dist/docs/place-order.md +84 -36
  82. package/dist/docs/postal-code-field.md +3 -1
  83. package/dist/docs/pricing.md +21 -23
  84. package/dist/docs/product-gallery.md +19 -20
  85. package/dist/docs/product-information.md +14 -10
  86. package/dist/docs/product-list.md +7 -6
  87. package/dist/docs/product-shelf.md +7 -1
  88. package/dist/docs/promotion.md +4 -2
  89. package/dist/docs/region.md +23 -15
  90. package/dist/docs/save-card.md +7 -6
  91. package/dist/docs/saved-cards.md +65 -36
  92. package/dist/docs/select.md +3 -4
  93. package/dist/docs/shipping-address.md +57 -21
  94. package/dist/docs/shipping-simulator.md +53 -15
  95. package/dist/docs/sign-in-disclosure.md +176 -0
  96. package/dist/docs/sign-in-form.md +78 -47
  97. package/dist/docs/sign-in-redirect.md +5 -3
  98. package/dist/docs/sign-in.md +173 -0
  99. package/dist/docs/toast.md +45 -16
  100. package/dist/docs/variant-selector.md +15 -11
  101. package/dist/graphql/types.d.ts +4 -14
  102. package/dist/index.d.ts +3 -2
  103. package/dist/internal/client.d.ts +4 -3
  104. package/dist/internal/client.js +5 -2
  105. package/dist/internal/server.d.ts +10 -5
  106. package/dist/internal/server.js +9 -4
  107. package/dist/matter/access-code-sign-in/access-code-sign-in.d.ts +250 -66
  108. package/dist/matter/access-code-sign-in/access-code-sign-in.js +459 -188
  109. package/dist/matter/access-code-sign-in/access-code-sign-in.js.map +1 -1
  110. package/dist/matter/account-address-book/account-address-book-delete.d.ts +78 -40
  111. package/dist/matter/account-address-book/account-address-book-delete.js +86 -50
  112. package/dist/matter/account-address-book/account-address-book-delete.js.map +1 -1
  113. package/dist/matter/account-address-book/account-address-book-deliverability.d.ts +21 -4
  114. package/dist/matter/account-address-book/account-address-book-deliverability.js +45 -17
  115. package/dist/matter/account-address-book/account-address-book-deliverability.js.map +1 -1
  116. package/dist/matter/account-address-book/account-address-book-form-parts.d.ts +74 -19
  117. package/dist/matter/account-address-book/account-address-book-form-parts.js +77 -26
  118. package/dist/matter/account-address-book/account-address-book-form-parts.js.map +1 -1
  119. package/dist/matter/account-address-book/account-address-book-profile-notice.d.ts +27 -6
  120. package/dist/matter/account-address-book/account-address-book-profile-notice.js +55 -28
  121. package/dist/matter/account-address-book/account-address-book-profile-notice.js.map +1 -1
  122. package/dist/matter/account-address-book/account-address-book.d.ts +67 -14
  123. package/dist/matter/account-address-book/account-address-book.js +74 -33
  124. package/dist/matter/account-address-book/account-address-book.js.map +1 -1
  125. package/dist/matter/account-address-book/account-address-country-switch.js +3 -3
  126. package/dist/matter/account-address-book/account-address-country-switch.js.map +1 -1
  127. package/dist/matter/account-address-book/account-address-country.d.ts +66 -20
  128. package/dist/matter/account-address-book/account-address-country.js +83 -49
  129. package/dist/matter/account-address-book/account-address-country.js.map +1 -1
  130. package/dist/matter/account-address-book/account-address-form-context.d.ts +8 -4
  131. package/dist/matter/account-address-book/account-address-form-context.js.map +1 -1
  132. package/dist/matter/account-address-book/account-address-form.d.ts +468 -45
  133. package/dist/matter/account-address-book/account-address-form.js +518 -155
  134. package/dist/matter/account-address-book/account-address-form.js.map +1 -1
  135. package/dist/matter/account-address-book/account-address-record.d.ts +27 -6
  136. package/dist/matter/account-address-book/account-address-record.js +32 -17
  137. package/dist/matter/account-address-book/account-address-record.js.map +1 -1
  138. package/dist/matter/account-menu/account-menu.d.ts +34 -17
  139. package/dist/matter/account-menu/account-menu.js +46 -54
  140. package/dist/matter/account-menu/account-menu.js.map +1 -1
  141. package/dist/matter/account-menu-identity/account-menu-identity.js +1 -1
  142. package/dist/matter/account-saved-cards/account-saved-cards.d.ts +463 -0
  143. package/dist/matter/account-saved-cards/account-saved-cards.js +1011 -0
  144. package/dist/matter/account-saved-cards/account-saved-cards.js.map +1 -0
  145. package/dist/matter/billing-address/billing-address.d.ts +156 -74
  146. package/dist/matter/billing-address/billing-address.js +227 -156
  147. package/dist/matter/billing-address/billing-address.js.map +1 -1
  148. package/dist/matter/breadcrumb/breadcrumb.d.ts +21 -3
  149. package/dist/matter/breadcrumb/breadcrumb.js +24 -9
  150. package/dist/matter/breadcrumb/breadcrumb.js.map +1 -1
  151. package/dist/matter/buy-button/buy-button.d.ts +8 -11
  152. package/dist/matter/buy-button/buy-button.js +10 -19
  153. package/dist/matter/buy-button/buy-button.js.map +1 -1
  154. package/dist/matter/card-entry/card-capture.js +12 -4
  155. package/dist/matter/card-entry/card-capture.js.map +1 -1
  156. package/dist/matter/card-entry/card-entry.d.ts +123 -32
  157. package/dist/matter/card-entry/card-entry.js +348 -221
  158. package/dist/matter/card-entry/card-entry.js.map +1 -1
  159. package/dist/matter/cart/cart-namespace.d.ts +11 -1
  160. package/dist/matter/cart/cart-namespace.js +11 -1
  161. package/dist/matter/cart/cart-namespace.js.map +1 -1
  162. package/dist/matter/cart/cart.d.ts +416 -45
  163. package/dist/matter/cart/cart.js +782 -101
  164. package/dist/matter/cart/cart.js.map +1 -1
  165. package/dist/matter/cart-destination/cart-destination.d.ts +233 -0
  166. package/dist/matter/cart-destination/cart-destination.js +703 -0
  167. package/dist/matter/cart-destination/cart-destination.js.map +1 -0
  168. package/dist/matter/cart-item/cart-item.d.ts +145 -16
  169. package/dist/matter/cart-item/cart-item.js +230 -54
  170. package/dist/matter/cart-item/cart-item.js.map +1 -1
  171. package/dist/matter/cart-item-compositions/cart-item-compositions.js +1 -1
  172. package/dist/matter/cart-item-compositions/cart-item-compositions.js.map +1 -1
  173. package/dist/matter/cart-item-customizations/cart-item-customizations.js +1 -1
  174. package/dist/matter/cart-item-customizations/cart-item-customizations.js.map +1 -1
  175. package/dist/matter/cart-item-discounts/cart-item-discounts.js +1 -1
  176. package/dist/matter/cart-item-discounts/cart-item-discounts.js.map +1 -1
  177. package/dist/matter/cart-item-seller-info/cart-item-seller-info.js +1 -1
  178. package/dist/matter/cart-item-seller-info/cart-item-seller-info.js.map +1 -1
  179. package/dist/matter/cart-item-variations/cart-item-variations.js +1 -1
  180. package/dist/matter/cart-item-variations/cart-item-variations.js.map +1 -1
  181. package/dist/matter/cart-totalizer/cart-totalizer.d.ts +43 -9
  182. package/dist/matter/cart-totalizer/cart-totalizer.js +49 -19
  183. package/dist/matter/cart-totalizer/cart-totalizer.js.map +1 -1
  184. package/dist/matter/challenge-return/challenge-return.d.ts +62 -0
  185. package/dist/matter/challenge-return/challenge-return.js +241 -0
  186. package/dist/matter/challenge-return/challenge-return.js.map +1 -0
  187. package/dist/matter/client-preferences/client-preferences-fieldset.d.ts +86 -17
  188. package/dist/matter/client-preferences/client-preferences-fieldset.js +126 -54
  189. package/dist/matter/client-preferences/client-preferences-fieldset.js.map +1 -1
  190. package/dist/matter/client-preferences/client-preferences.d.ts +50 -7
  191. package/dist/matter/client-preferences/client-preferences.js +84 -15
  192. package/dist/matter/client-preferences/client-preferences.js.map +1 -1
  193. package/dist/matter/client-profile/client-profile.d.ts +44 -9
  194. package/dist/matter/client-profile/client-profile.js +64 -24
  195. package/dist/matter/client-profile/client-profile.js.map +1 -1
  196. package/dist/matter/client-profile-form/client-profile-fieldset.d.ts +119 -22
  197. package/dist/matter/client-profile-form/client-profile-fieldset.js +161 -73
  198. package/dist/matter/client-profile-form/client-profile-fieldset.js.map +1 -1
  199. package/dist/matter/delivery-options/delivery-options-accordion.d.ts +49 -4
  200. package/dist/matter/delivery-options/delivery-options-accordion.js +67 -14
  201. package/dist/matter/delivery-options/delivery-options-accordion.js.map +1 -1
  202. package/dist/matter/delivery-options/delivery-options-controller.d.ts +69 -9
  203. package/dist/matter/delivery-options/delivery-options-controller.js +80 -14
  204. package/dist/matter/delivery-options/delivery-options-controller.js.map +1 -1
  205. package/dist/matter/delivery-options/delivery-options.d.ts +37 -2
  206. package/dist/matter/delivery-options/delivery-options.js +75 -12
  207. package/dist/matter/delivery-options/delivery-options.js.map +1 -1
  208. package/dist/matter/delivery-options/use-delivery-option-selection.d.ts +1 -0
  209. package/dist/matter/delivery-options/use-delivery-option-selection.js +1 -1
  210. package/dist/matter/delivery-options/use-delivery-option-selection.js.map +1 -1
  211. package/dist/matter/email-identification/email-identification.d.ts +25 -3
  212. package/dist/matter/email-identification/email-identification.js +49 -12
  213. package/dist/matter/email-identification/email-identification.js.map +1 -1
  214. package/dist/matter/free-shipping-progress/free-shipping-progress.d.ts +85 -10
  215. package/dist/matter/free-shipping-progress/free-shipping-progress.js +153 -53
  216. package/dist/matter/free-shipping-progress/free-shipping-progress.js.map +1 -1
  217. package/dist/matter/identity-edit/identity-edit.d.ts +52 -10
  218. package/dist/matter/identity-edit/identity-edit.js +47 -19
  219. package/dist/matter/identity-edit/identity-edit.js.map +1 -1
  220. package/dist/matter/identity-summary/identity-summary.d.ts +76 -22
  221. package/dist/matter/identity-summary/identity-summary.js +95 -45
  222. package/dist/matter/identity-summary/identity-summary.js.map +1 -1
  223. package/dist/matter/installments/installments-select.d.ts +98 -16
  224. package/dist/matter/installments/installments-select.js +156 -48
  225. package/dist/matter/installments/installments-select.js.map +1 -1
  226. package/dist/matter/installments/installments.d.ts +96 -16
  227. package/dist/matter/installments/installments.js +115 -40
  228. package/dist/matter/installments/installments.js.map +1 -1
  229. package/dist/matter/installments/use-installments-selection.d.ts +1 -0
  230. package/dist/matter/installments/use-installments-selection.js +8 -3
  231. package/dist/matter/installments/use-installments-selection.js.map +1 -1
  232. package/dist/matter/my-account-profile/my-account-profile.d.ts +358 -103
  233. package/dist/matter/my-account-profile/my-account-profile.js +370 -174
  234. package/dist/matter/my-account-profile/my-account-profile.js.map +1 -1
  235. package/dist/matter/order-cancel/order-cancel.d.ts +65 -19
  236. package/dist/matter/order-cancel/order-cancel.js +118 -51
  237. package/dist/matter/order-cancel/order-cancel.js.map +1 -1
  238. package/dist/matter/order-delivery-address/order-delivery-address.d.ts +8 -18
  239. package/dist/matter/order-delivery-address/order-delivery-address.js +14 -23
  240. package/dist/matter/order-delivery-address/order-delivery-address.js.map +1 -1
  241. package/dist/matter/order-delivery-group/order-delivery-group.d.ts +40 -24
  242. package/dist/matter/order-delivery-group/order-delivery-group.js +64 -74
  243. package/dist/matter/order-delivery-group/order-delivery-group.js.map +1 -1
  244. package/dist/matter/order-details-header/order-details-header.d.ts +32 -15
  245. package/dist/matter/order-details-header/order-details-header.js +66 -58
  246. package/dist/matter/order-details-header/order-details-header.js.map +1 -1
  247. package/dist/matter/order-invoice-download/order-invoice-download.d.ts +78 -0
  248. package/dist/matter/order-invoice-download/order-invoice-download.js +173 -0
  249. package/dist/matter/order-invoice-download/order-invoice-download.js.map +1 -0
  250. package/dist/matter/order-list/order-list.d.ts +164 -19
  251. package/dist/matter/order-list/order-list.js +229 -87
  252. package/dist/matter/order-list/order-list.js.map +1 -1
  253. package/dist/matter/order-list-row/order-list-row.d.ts +6 -1
  254. package/dist/matter/order-list-row/order-list-row.js +3 -2
  255. package/dist/matter/order-list-row/order-list-row.js.map +1 -1
  256. package/dist/matter/order-list-search/order-list-search.d.ts +18 -26
  257. package/dist/matter/order-list-search/order-list-search.js +30 -69
  258. package/dist/matter/order-list-search/order-list-search.js.map +1 -1
  259. package/dist/matter/order-list-views/order-list-views.d.ts +15 -22
  260. package/dist/matter/order-list-views/order-list-views.js +22 -68
  261. package/dist/matter/order-list-views/order-list-views.js.map +1 -1
  262. package/dist/matter/order-payment/order-payment.d.ts +33 -10
  263. package/dist/matter/order-payment/order-payment.js +44 -39
  264. package/dist/matter/order-payment/order-payment.js.map +1 -1
  265. package/dist/matter/order-placed/order-placed-deliveries.d.ts +144 -12
  266. package/dist/matter/order-placed/order-placed-deliveries.js +115 -40
  267. package/dist/matter/order-placed/order-placed-deliveries.js.map +1 -1
  268. package/dist/matter/order-placed/order-placed.d.ts +198 -31
  269. package/dist/matter/order-placed/order-placed.js +230 -139
  270. package/dist/matter/order-placed/order-placed.js.map +1 -1
  271. package/dist/matter/order-placed-date/order-placed-date.d.ts +5 -8
  272. package/dist/matter/order-placed-date/order-placed-date.js +7 -8
  273. package/dist/matter/order-placed-date/order-placed-date.js.map +1 -1
  274. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.d.ts +90 -17
  275. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js +93 -117
  276. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js.map +1 -1
  277. package/dist/matter/order-progress/order-progress.d.ts +19 -8
  278. package/dist/matter/order-progress/order-progress.js +37 -45
  279. package/dist/matter/order-progress/order-progress.js.map +1 -1
  280. package/dist/matter/order-summary/order-summary.d.ts +19 -9
  281. package/dist/matter/order-summary/order-summary.js +38 -44
  282. package/dist/matter/order-summary/order-summary.js.map +1 -1
  283. package/dist/matter/order-tracking-link/order-tracking-link.d.ts +43 -0
  284. package/dist/matter/order-tracking-link/order-tracking-link.js +107 -0
  285. package/dist/matter/order-tracking-link/order-tracking-link.js.map +1 -0
  286. package/dist/matter/payment/payment-card-capture.js +17 -10
  287. package/dist/matter/payment/payment-card-capture.js.map +1 -1
  288. package/dist/matter/payment/payment-controller.d.ts +4 -2
  289. package/dist/matter/payment/payment-controller.js +30 -9
  290. package/dist/matter/payment/payment-controller.js.map +1 -1
  291. package/dist/matter/payment/payment-method-badges.js +1 -1
  292. package/dist/matter/payment/payment.d.ts +69 -19
  293. package/dist/matter/payment/payment.js +101 -35
  294. package/dist/matter/payment/payment.js.map +1 -1
  295. package/dist/matter/payment/use-payment-method-selection.d.ts +25 -4
  296. package/dist/matter/payment/use-payment-method-selection.js +94 -32
  297. package/dist/matter/payment/use-payment-method-selection.js.map +1 -1
  298. package/dist/matter/payment/use-payment-submit-gate.d.ts +14 -3
  299. package/dist/matter/payment/use-payment-submit-gate.js +47 -8
  300. package/dist/matter/payment/use-payment-submit-gate.js.map +1 -1
  301. package/dist/matter/place-order/place-order.d.ts +171 -57
  302. package/dist/matter/place-order/place-order.js +376 -185
  303. package/dist/matter/place-order/place-order.js.map +1 -1
  304. package/dist/matter/pricing/pricing.d.ts +152 -13
  305. package/dist/matter/pricing/pricing.js +153 -52
  306. package/dist/matter/pricing/pricing.js.map +1 -1
  307. package/dist/matter/product-information/product-information.d.ts +27 -4
  308. package/dist/matter/product-information/product-information.js +32 -15
  309. package/dist/matter/product-information/product-information.js.map +1 -1
  310. package/dist/matter/product-list/product-list.d.ts +24 -6
  311. package/dist/matter/product-list/product-list.js +32 -26
  312. package/dist/matter/product-list/product-list.js.map +1 -1
  313. package/dist/matter/product-shelf/product-shelf.d.ts +8 -3
  314. package/dist/matter/product-shelf/product-shelf.js +111 -10
  315. package/dist/matter/product-shelf/product-shelf.js.map +1 -1
  316. package/dist/matter/region/region.d.ts +33 -16
  317. package/dist/matter/region/region.js +59 -52
  318. package/dist/matter/region/region.js.map +1 -1
  319. package/dist/matter/save-card/save-card.d.ts +43 -8
  320. package/dist/matter/save-card/save-card.js +61 -23
  321. package/dist/matter/save-card/save-card.js.map +1 -1
  322. package/dist/matter/saved-cards/saved-cards.d.ts +113 -21
  323. package/dist/matter/saved-cards/saved-cards.js +349 -77
  324. package/dist/matter/saved-cards/saved-cards.js.map +1 -1
  325. package/dist/matter/shipping-address/address-payload.js +25 -0
  326. package/dist/matter/shipping-address/address-payload.js.map +1 -0
  327. package/dist/matter/shipping-address/country-descriptors.js +71 -71
  328. package/dist/matter/shipping-address/country-descriptors.js.map +1 -1
  329. package/dist/matter/shipping-address/library-country-descriptors.js +136 -0
  330. package/dist/matter/shipping-address/library-country-descriptors.js.map +1 -0
  331. package/dist/matter/shipping-address/shipping-address.d.ts +312 -45
  332. package/dist/matter/shipping-address/shipping-address.js +443 -188
  333. package/dist/matter/shipping-address/shipping-address.js.map +1 -1
  334. package/dist/matter/shipping-simulator/shipping-simulator.d.ts +251 -25
  335. package/dist/matter/shipping-simulator/shipping-simulator.js +261 -51
  336. package/dist/matter/shipping-simulator/shipping-simulator.js.map +1 -1
  337. package/dist/matter/sign-in/sign-in.d.ts +108 -0
  338. package/dist/matter/sign-in/sign-in.js +285 -0
  339. package/dist/matter/sign-in/sign-in.js.map +1 -0
  340. package/dist/matter/sign-in-disclosure/sign-in-disclosure.d.ts +81 -0
  341. package/dist/matter/sign-in-disclosure/sign-in-disclosure.js +232 -0
  342. package/dist/matter/sign-in-disclosure/sign-in-disclosure.js.map +1 -0
  343. package/dist/matter/sign-in-form/sign-in-form.d.ts +93 -62
  344. package/dist/matter/sign-in-form/sign-in-form.js +134 -144
  345. package/dist/matter/sign-in-form/sign-in-form.js.map +1 -1
  346. package/dist/particles/binding-switcher/binding-switcher.d.ts +59 -0
  347. package/dist/particles/binding-switcher/binding-switcher.js +194 -0
  348. package/dist/particles/binding-switcher/binding-switcher.js.map +1 -0
  349. package/dist/particles/card-summary/card-network.d.ts +17 -0
  350. package/dist/particles/card-summary/card-network.js +25 -0
  351. package/dist/particles/card-summary/card-network.js.map +1 -0
  352. package/dist/particles/card-summary/card-summary.d.ts +113 -0
  353. package/dist/particles/card-summary/card-summary.js +221 -0
  354. package/dist/particles/card-summary/card-summary.js.map +1 -0
  355. package/dist/particles/carousel/carousel.d.ts +99 -11
  356. package/dist/particles/carousel/carousel.js +103 -35
  357. package/dist/particles/carousel/carousel.js.map +1 -1
  358. package/dist/particles/copy-text/copy-text.js +5 -15
  359. package/dist/particles/copy-text/copy-text.js.map +1 -1
  360. package/dist/particles/dialog/dialog.d.ts +14 -6
  361. package/dist/particles/dialog/dialog.js +6 -3
  362. package/dist/particles/dialog/dialog.js.map +1 -1
  363. package/dist/particles/drawer/drawer.js +1 -1
  364. package/dist/particles/drawer/drawer.js.map +1 -1
  365. package/dist/particles/email-field/email-field.d.ts +2 -1
  366. package/dist/particles/email-field/email-field.js +2 -1
  367. package/dist/particles/email-field/email-field.js.map +1 -1
  368. package/dist/particles/footer-link-group/footer-link-group.js +1 -0
  369. package/dist/particles/footer-link-group/footer-link-group.js.map +1 -1
  370. package/dist/particles/footer-social/footer-social.d.ts +1 -1
  371. package/dist/particles/footer-social/footer-social.js +1 -1
  372. package/dist/particles/footer-social/footer-social.js.map +1 -1
  373. package/dist/particles/form/form.d.ts +85 -13
  374. package/dist/particles/form/form.js +91 -42
  375. package/dist/particles/form/form.js.map +1 -1
  376. package/dist/particles/gallery/gallery.d.ts +129 -12
  377. package/dist/particles/gallery/gallery.js +121 -34
  378. package/dist/particles/gallery/gallery.js.map +1 -1
  379. package/dist/particles/incentives/incentives.d.ts +1 -1
  380. package/dist/particles/incentives/incentives.js +1 -1
  381. package/dist/particles/incentives/incentives.js.map +1 -1
  382. package/dist/particles/order-details-back/order-details-back.d.ts +5 -3
  383. package/dist/particles/order-details-back/order-details-back.js +8 -10
  384. package/dist/particles/order-details-back/order-details-back.js.map +1 -1
  385. package/dist/particles/order-status-badge/order-status-badge.d.ts +3 -3
  386. package/dist/particles/order-status-badge/order-status-badge.js +4 -20
  387. package/dist/particles/order-status-badge/order-status-badge.js.map +1 -1
  388. package/dist/particles/password-field/password-field.d.ts +1 -1
  389. package/dist/particles/password-field/password-field.js +2 -4
  390. package/dist/particles/password-field/password-field.js.map +1 -1
  391. package/dist/particles/payment-methods/payment-methods.d.ts +1 -1
  392. package/dist/particles/payment-methods/payment-methods.js +1 -1
  393. package/dist/particles/payment-methods/payment-methods.js.map +1 -1
  394. package/dist/particles/phone-field/phone-field.d.ts +4 -4
  395. package/dist/particles/phone-field/phone-field.js +8 -11
  396. package/dist/particles/phone-field/phone-field.js.map +1 -1
  397. package/dist/particles/spinner/spinner.d.ts +24 -4
  398. package/dist/particles/spinner/spinner.js +25 -9
  399. package/dist/particles/spinner/spinner.js.map +1 -1
  400. package/dist/particles/switch/switch.d.ts +4 -1
  401. package/dist/particles/switch/switch.js +3 -1
  402. package/dist/particles/switch/switch.js.map +1 -1
  403. package/dist/particles/toast/toast.d.ts +49 -9
  404. package/dist/particles/toast/toast.js +81 -15
  405. package/dist/particles/toast/toast.js.map +1 -1
  406. package/dist/schema.graphql +461 -89
  407. package/dist/sdk/actions/index.d.ts +3 -1
  408. package/dist/sdk/actions/index.js +3 -1
  409. package/dist/sdk/actions/locale-action-provider.d.ts +16 -0
  410. package/dist/sdk/actions/locale-action-provider.js +20 -0
  411. package/dist/sdk/actions/locale-action-provider.js.map +1 -0
  412. package/dist/sdk/actions/saved-card-action-provider.d.ts +12 -0
  413. package/dist/sdk/actions/saved-card-action-provider.js +16 -0
  414. package/dist/sdk/actions/saved-card-action-provider.js.map +1 -0
  415. package/dist/sdk/actions/types.d.ts +6 -2
  416. package/dist/sdk/address/address-fields.js +4 -4
  417. package/dist/sdk/address/address-fields.js.map +1 -1
  418. package/dist/sdk/address/constants.js +1 -6
  419. package/dist/sdk/address/constants.js.map +1 -1
  420. package/dist/sdk/address/messages.js +44 -44
  421. package/dist/sdk/address/messages.js.map +1 -1
  422. package/dist/sdk/address/postal-code.js +15 -2
  423. package/dist/sdk/address/postal-code.js.map +1 -1
  424. package/dist/sdk/address/types.d.ts +5 -3
  425. package/dist/sdk/address/validate-address.js +3 -3
  426. package/dist/sdk/address/validate-address.js.map +1 -1
  427. package/dist/sdk/analytics/use-analytics-actions.d.ts +1 -1
  428. package/dist/sdk/analytics/use-analytics-actions.js.map +1 -1
  429. package/dist/sdk/cache/storefront-cache.js +2 -1
  430. package/dist/sdk/cache/storefront-cache.js.map +1 -1
  431. package/dist/sdk/cart/operations.d.ts +2 -1
  432. package/dist/sdk/cart/operations.js +55 -1
  433. package/dist/sdk/cart/operations.js.map +1 -1
  434. package/dist/sdk/cart/optimistic.d.ts +30 -7
  435. package/dist/sdk/cart/optimistic.js +78 -41
  436. package/dist/sdk/cart/optimistic.js.map +1 -1
  437. package/dist/sdk/cart/use-cart-actions.d.ts +7 -0
  438. package/dist/sdk/cart/use-cart-actions.js +61 -15
  439. package/dist/sdk/cart/use-cart-actions.js.map +1 -1
  440. package/dist/sdk/cart/use-cart-sync-sales-channel.js +70 -0
  441. package/dist/sdk/cart/use-cart-sync-sales-channel.js.map +1 -0
  442. package/dist/sdk/data/index.js +2 -2
  443. package/dist/sdk/data/reactive-list-item-data-provider.js +2 -2
  444. package/dist/sdk/generated/gql.js +16 -12
  445. package/dist/sdk/generated/gql.js.map +1 -1
  446. package/dist/sdk/generated/graphql.d.ts +197 -51
  447. package/dist/sdk/generated/graphql.js +2318 -91
  448. package/dist/sdk/generated/graphql.js.map +1 -1
  449. package/dist/sdk/i18n/format-error-code.js +23 -0
  450. package/dist/sdk/i18n/format-error-code.js.map +1 -0
  451. package/dist/sdk/i18n/message-formatter.d.ts +22 -0
  452. package/dist/sdk/i18n/message-formatter.js +140 -0
  453. package/dist/sdk/i18n/message-formatter.js.map +1 -0
  454. package/dist/sdk/i18n/use-message-formatter.d.ts +8 -0
  455. package/dist/sdk/i18n/use-message-formatter.js +18 -0
  456. package/dist/sdk/i18n/use-message-formatter.js.map +1 -0
  457. package/dist/sdk/identity/use-identity-actions.js.map +1 -1
  458. package/dist/sdk/locale/binding-switch-provider.d.ts +13 -0
  459. package/dist/sdk/locale/binding-switch-provider.js +20 -0
  460. package/dist/sdk/locale/binding-switch-provider.js.map +1 -0
  461. package/dist/sdk/locale/use-locale-actions.d.ts +16 -0
  462. package/dist/sdk/locale/use-locale-actions.js +70 -0
  463. package/dist/sdk/locale/use-locale-actions.js.map +1 -0
  464. package/dist/sdk/navigation/binding-switch.d.ts +39 -0
  465. package/dist/sdk/navigation/binding-switch.js +129 -0
  466. package/dist/sdk/navigation/binding-switch.js.map +1 -0
  467. package/dist/sdk/navigation/decode-route-params.d.ts +11 -0
  468. package/dist/sdk/navigation/decode-route-params.js +32 -0
  469. package/dist/sdk/navigation/decode-route-params.js.map +1 -0
  470. package/dist/sdk/navigation/redirect.d.ts +2 -0
  471. package/dist/sdk/navigation/redirect.js +19 -1
  472. package/dist/sdk/navigation/redirect.js.map +1 -1
  473. package/dist/sdk/navigation/types.d.ts +13 -0
  474. package/dist/sdk/payment/bin-format.js +20 -0
  475. package/dist/sdk/payment/bin-format.js.map +1 -0
  476. package/dist/sdk/payment/challenge-return.js +37 -0
  477. package/dist/sdk/payment/challenge-return.js.map +1 -0
  478. package/dist/sdk/payment/confirmation-last-four.js +39 -0
  479. package/dist/sdk/payment/confirmation-last-four.js.map +1 -0
  480. package/dist/sdk/payment/gateway.d.ts +1 -1
  481. package/dist/sdk/payment/gateway.js +8 -2
  482. package/dist/sdk/payment/gateway.js.map +1 -1
  483. package/dist/sdk/payment/operations.d.ts +1 -0
  484. package/dist/sdk/payment/operations.js +28 -6
  485. package/dist/sdk/payment/operations.js.map +1 -1
  486. package/dist/sdk/payment/resumed-purchase.d.ts +1 -0
  487. package/dist/sdk/payment/resumed-purchase.js +119 -0
  488. package/dist/sdk/payment/resumed-purchase.js.map +1 -0
  489. package/dist/sdk/payment/security-code-mask.js +16 -23
  490. package/dist/sdk/payment/security-code-mask.js.map +1 -1
  491. package/dist/sdk/payment/submission-registry.js +6 -2
  492. package/dist/sdk/payment/submission-registry.js.map +1 -1
  493. package/dist/sdk/payment/use-payment-actions.d.ts +18 -3
  494. package/dist/sdk/payment/use-payment-actions.js +23 -3
  495. package/dist/sdk/payment/use-payment-actions.js.map +1 -1
  496. package/dist/sdk/payment/use-place-order.d.ts +10 -2
  497. package/dist/sdk/payment/use-place-order.js +138 -76
  498. package/dist/sdk/payment/use-place-order.js.map +1 -1
  499. package/dist/sdk/provider/storefront-provider.d.ts +1 -7
  500. package/dist/sdk/provider/storefront-provider.js +4 -11
  501. package/dist/sdk/provider/storefront-provider.js.map +1 -1
  502. package/dist/sdk/saved-cards/operations.d.ts +16 -0
  503. package/dist/sdk/saved-cards/operations.js +41 -0
  504. package/dist/sdk/saved-cards/operations.js.map +1 -0
  505. package/dist/sdk/saved-cards/use-saved-card-actions.d.ts +26 -0
  506. package/dist/sdk/saved-cards/use-saved-card-actions.js +86 -0
  507. package/dist/sdk/saved-cards/use-saved-card-actions.js.map +1 -0
  508. package/dist/sdk/seo/entity-landing.d.ts +24 -0
  509. package/dist/sdk/seo/entity-landing.js +30 -0
  510. package/dist/sdk/seo/entity-landing.js.map +1 -0
  511. package/dist/sdk/seo/page-alternates.d.ts +8 -5
  512. package/dist/sdk/seo/page-alternates.js +11 -14
  513. package/dist/sdk/seo/page-alternates.js.map +1 -1
  514. package/dist/sdk/seo/search-landing.d.ts +42 -0
  515. package/dist/sdk/seo/search-landing.js +85 -0
  516. package/dist/sdk/seo/search-landing.js.map +1 -0
  517. package/dist/sdk/session/mock-session.d.ts +9 -0
  518. package/dist/sdk/session/mock-session.js +31 -0
  519. package/dist/sdk/session/mock-session.js.map +1 -0
  520. package/dist/sdk/session/read-server-session.d.ts +3 -0
  521. package/dist/sdk/session/read-server-session.js +5 -0
  522. package/dist/sdk/session/read-server-session.js.map +1 -1
  523. package/dist/sdk/session/return-path-segment.d.ts +10 -0
  524. package/dist/sdk/session/return-path-segment.js +15 -0
  525. package/dist/sdk/session/return-path-segment.js.map +1 -0
  526. package/dist/sdk/session/use-session-actions.js.map +1 -1
  527. package/dist/sdk/shipping/shipping-operations.d.ts +1 -1
  528. package/dist/sdk/shipping/shipping-operations.js +13 -0
  529. package/dist/sdk/shipping/shipping-operations.js.map +1 -1
  530. package/dist/sdk/shipping/use-cart-shipping-simulation.js.map +1 -1
  531. package/dist/sdk/shipping/use-shipping-actions.js.map +1 -1
  532. package/dist/sdk/shipping/use-shipping-simulation.js.map +1 -1
  533. package/dist/sdk/state/cart.d.ts +9 -2
  534. package/dist/sdk/state/cart.js +9 -2
  535. package/dist/sdk/state/cart.js.map +1 -1
  536. package/dist/utils/safe-href.d.ts +2 -0
  537. package/package.json +4 -3
  538. package/skills/storefront-asset/SKILL.md +2 -2
  539. package/skills/storefront-asset/references/api-side.md +27 -14
  540. package/skills/storefront-asset/references/findings.md +5 -2
  541. package/src/styles/tailwind.css +9 -2
  542. package/dist/matter/shipping-address/country-descriptors.d.ts +0 -1
  543. package/dist/message-locales.json +0 -7
  544. package/dist/sdk/i18n/client.d.ts +0 -4
  545. package/dist/sdk/i18n/client.js +0 -4
  546. package/dist/sdk/i18n/locales.d.ts +0 -8
  547. package/dist/sdk/i18n/locales.js +0 -57
  548. package/dist/sdk/i18n/locales.js.map +0 -1
  549. package/dist/sdk/i18n/messages/en-US.js +0 -164
  550. package/dist/sdk/i18n/messages/en-US.js.map +0 -1
  551. package/dist/sdk/i18n/messages/en-US.json +0 -159
  552. package/dist/sdk/i18n/messages/en-US.json.d.ts +0 -163
  553. package/dist/sdk/i18n/messages/es-ES.js +0 -164
  554. package/dist/sdk/i18n/messages/es-ES.js.map +0 -1
  555. package/dist/sdk/i18n/messages/es-ES.json +0 -159
  556. package/dist/sdk/i18n/messages/pt-BR.js +0 -164
  557. package/dist/sdk/i18n/messages/pt-BR.js.map +0 -1
  558. package/dist/sdk/i18n/messages/pt-BR.json +0 -159
  559. package/dist/sdk/i18n/provider.d.ts +0 -1
  560. package/dist/sdk/i18n/provider.js +0 -30
  561. package/dist/sdk/i18n/provider.js.map +0 -1
  562. package/dist/sdk/i18n/server.d.ts +0 -28
  563. package/dist/sdk/i18n/server.js +0 -59
  564. package/dist/sdk/i18n/server.js.map +0 -1
  565. package/dist/utils/resolve-authored-copy.js +0 -18
  566. package/dist/utils/resolve-authored-copy.js.map +0 -1
  567. package/dist/utils/substitute-template.js +0 -33
  568. package/dist/utils/substitute-template.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binding-switch.js","names":[],"sources":["../../../src/sdk/navigation/binding-switch.ts"],"sourcesContent":["import type { ApolloClient } from '@apollo/client';\nimport {\n type AlternateBinding,\n CATALOG_ROUTE_ALTERNATES_QUERY,\n catalogClusterPaths,\n encodePath,\n} from '../seo/page-alternates.js';\nimport { decodeRouteParams } from './decode-route-params.js';\nimport { resolveStorefrontHref } from './resolve-storefront-href.js';\nimport type { RouteMap, RouteMapEntry, StandardName } from './types.js';\n\n/** Bounds the `catalogRoute` lookup: a slow API takes the no-equivalent fallback instead of stalling the switch. */\nconst BINDING_SWITCH_LOOKUP_TIMEOUT_MS = 3_000;\n\nconst CATALOG_STANDARDS: ReadonlySet<StandardName> = new Set(['product', 'category', 'brand', 'collection']);\n\nconst NO_EQUIVALENT_QUERY = '?fs_notice=no-equivalent';\n\nexport type BindingSwitchRequest = {\n /** Destination binding id. */\n bindingId: string;\n /** The binding the shopper is on. */\n currentBindingId: string;\n params: Record<string, string | string[]>;\n /** Decoded logical path of the current page. */\n path: string;\n /** `location.search`: `''` or `'?…'`. */\n search: string;\n /** `location.hash`: `''` or `'#…'`. */\n hash: string;\n};\n\nexport type BindingSwitchResult = { url: string | null };\n\nexport type ResolveBindingSwitchOptions = {\n request: BindingSwitchRequest;\n knownBindingId: (candidate: string | null | undefined) => string | null;\n bindings: readonly AlternateBinding[];\n routeMap: RouteMap;\n buildUrl: (bindingId: string, logicalPath: string) => string;\n clientFor: (bindingId: string) => ApolloClient;\n};\n\n/**\n * The equivalent URL of the current page in the destination binding, or the destination's home with\n * `fs_notice=no-equivalent` when none exists or the lookup fails. The page is the one route-map\n * entry whose href in the current binding equals the logical path; none or several take the\n * fallback. Every URL is built by `buildUrl` from an id `knownBindingId` accepted; an undeclared\n * destination resolves `{ url: null }`. The request comes off the wire, so each field is read as\n * unchecked. Never throws for an expected outcome, writes no cookie, and reads no request header.\n */\nexport async function resolveBindingSwitch({\n request,\n knownBindingId,\n bindings,\n routeMap,\n buildUrl,\n clientFor,\n}: ResolveBindingSwitchOptions): Promise<BindingSwitchResult> {\n const destination = knownBindingId(stringOr(request.bindingId, null));\n if (destination === null) {\n console.error('[locale.set] unknown binding');\n return { url: null };\n }\n\n const fallback = { url: `${buildUrl(destination, '/')}${NO_EQUIVALENT_QUERY}` };\n const path = stringOr(request.path, '');\n // `useParams()` hands the segments over percent-encoded; the route map fills patterns with decoded values.\n const params = decodeRouteParams(paramsOf(request.params));\n const page = pageMatchingPath(routeMap, stringOr(request.currentBindingId, ''), path, params);\n const entry = page === undefined ? undefined : ownEntry(routeMap, page);\n if (page === undefined || entry === undefined) return fallback;\n if (entry.bindings !== undefined && !entry.bindings.includes(destination)) return fallback;\n\n const tail = `${searchOf(request.search)}${hashOf(request.hash)}`;\n\n if (entry.standard !== undefined && CATALOG_STANDARDS.has(entry.standard)) {\n const current = knownBindingId(stringOr(request.currentBindingId, null));\n if (current === null || path === '' || path === '/') return fallback;\n\n const paths = await catalogClusterPaths(bindings, async () => {\n const { data, error } = await clientFor(current).query({\n query: CATALOG_ROUTE_ALTERNATES_QUERY,\n variables: { path },\n errorPolicy: 'all',\n fetchPolicy: 'no-cache',\n context: { fetchOptions: { signal: AbortSignal.timeout(BINDING_SWITCH_LOOKUP_TIMEOUT_MS) } },\n });\n return { data, error };\n });\n const variantPath = paths && Object.hasOwn(paths, destination) ? paths[destination] : undefined;\n if (variantPath === undefined) return fallback;\n return { url: `${buildUrl(destination, encodePath(variantPath))}${tail}` };\n }\n\n const { href } = resolveStorefrontHref({ bindingId: destination, basePath: '/' }, routeMap, { page, params });\n if (href === null) return fallback;\n return { url: `${buildUrl(destination, href)}${tail}` };\n}\n\nfunction stringOr<T extends string | null>(value: unknown, empty: T): string | T {\n return typeof value === 'string' ? value : empty;\n}\n\nfunction paramsOf(value: unknown): BindingSwitchRequest['params'] {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as BindingSwitchRequest['params'])\n : {};\n}\n\n/**\n * The single page whose href in the current binding is this logical path. A miss and a tie are both\n * no page: the switch falls back instead of guessing. An entry that cannot be resolved (a missing\n * param, a binding it does not serve) is skipped.\n */\nfunction pageMatchingPath(\n routeMap: RouteMap,\n bindingId: string,\n path: string,\n params: BindingSwitchRequest['params'],\n): string | undefined {\n const matches: string[] = [];\n for (const name of Object.keys(routeMap)) {\n const { href } = resolveStorefrontHref({ bindingId, basePath: '/' }, routeMap, { page: name, params });\n if (href === null || !sameDecodedPath(href, path)) continue;\n matches.push(name);\n }\n return matches.length === 1 ? matches[0] : undefined;\n}\n\n/**\n * `resolveStorefrontHref` percent-encodes params, so the href is decoded once. The request path is\n * compared as it arrived first, so a decoded slug like `100%-off` or `%41` is not decoded again; an\n * encoded path still matches through its decoded form.\n */\nfunction sameDecodedPath(href: string, path: string): boolean {\n const decodedHref = decodeOrNull(href);\n if (decodedHref === null) return false;\n return decodedHref === path || decodedHref === decodeOrNull(path);\n}\n\nfunction decodeOrNull(text: string): string | null {\n try {\n return decodeURIComponent(text);\n } catch {\n return null;\n }\n}\n\nfunction ownEntry(routeMap: RouteMap, page: string): RouteMapEntry | undefined {\n return Object.hasOwn(routeMap, page) ? routeMap[page] : undefined;\n}\n\n/** Kept verbatim when it is only a query: a leading `?`, no `#`, and no control character. */\nfunction searchOf(search: unknown): string {\n const text = stringOr(search, '');\n if (text.length < 2 || !text.startsWith('?')) return '';\n for (const char of text) {\n const code = char.codePointAt(0) ?? 0;\n if (char === '#' || code < 0x20 || code === 0x7f) return '';\n }\n return text;\n}\n\nfunction hashOf(hash: unknown): string {\n const text = stringOr(hash, '');\n return text.startsWith('#') && text.length > 1 ? text : '';\n}\n"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ //#region src/sdk/navigation/decode-route-params.d.ts
2
+ type RouteParamValue = string | string[] | undefined;
3
+ /**
4
+ * The route params a generated page receives, decoded: Next hands over a dynamic segment
5
+ * percent-encoded, so an id ending in `=` arrives as `%3D`. A value with a malformed sequence is kept
6
+ * as received, so a request can never turn into an exception. A list (catch-all) is decoded segment
7
+ * by segment, and the keys are unchanged.
8
+ */
9
+ export declare function decodeRouteParams<T extends Record<string, RouteParamValue>>(params: T): T;
10
+ //#endregion
11
+ //# sourceMappingURL=decode-route-params.d.ts.map
@@ -0,0 +1,32 @@
1
+ //#region src/sdk/navigation/decode-route-params.ts
2
+ function decodeSegment(segment) {
3
+ try {
4
+ return decodeURIComponent(segment);
5
+ } catch {
6
+ return segment;
7
+ }
8
+ }
9
+ function decodeValue(value) {
10
+ if (value === void 0) return void 0;
11
+ return Array.isArray(value) ? value.map(decodeSegment) : decodeSegment(value);
12
+ }
13
+ /**
14
+ * The route params a generated page receives, decoded: Next hands over a dynamic segment
15
+ * percent-encoded, so an id ending in `=` arrives as `%3D`. A value with a malformed sequence is kept
16
+ * as received, so a request can never turn into an exception. A list (catch-all) is decoded segment
17
+ * by segment, and the keys are unchanged.
18
+ */
19
+ function decodeRouteParams(params) {
20
+ const decoded = {};
21
+ for (const [key, value] of Object.entries(params)) Object.defineProperty(decoded, key, {
22
+ value: decodeValue(value),
23
+ enumerable: true,
24
+ writable: true,
25
+ configurable: true
26
+ });
27
+ return decoded;
28
+ }
29
+ //#endregion
30
+ export { decodeRouteParams };
31
+
32
+ //# sourceMappingURL=decode-route-params.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode-route-params.js","names":[],"sources":["../../../src/sdk/navigation/decode-route-params.ts"],"sourcesContent":["type RouteParamValue = string | string[] | undefined;\n\nfunction decodeSegment(segment: string): string {\n try {\n return decodeURIComponent(segment);\n } catch {\n return segment;\n }\n}\n\nfunction decodeValue(value: RouteParamValue): RouteParamValue {\n if (value === undefined) return undefined;\n return Array.isArray(value) ? value.map(decodeSegment) : decodeSegment(value);\n}\n\n/**\n * The route params a generated page receives, decoded: Next hands over a dynamic segment\n * percent-encoded, so an id ending in `=` arrives as `%3D`. A value with a malformed sequence is kept\n * as received, so a request can never turn into an exception. A list (catch-all) is decoded segment\n * by segment, and the keys are unchanged.\n */\nexport function decodeRouteParams<T extends Record<string, RouteParamValue>>(params: T): T {\n const decoded: Record<string, RouteParamValue> = {};\n for (const [key, value] of Object.entries(params)) {\n // defineProperty, not assignment: a param named `__proto__` must stay an own key.\n Object.defineProperty(decoded, key, {\n value: decodeValue(value),\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n return decoded as T;\n}\n"],"mappings":";AAEA,SAAS,cAAc,SAAyB;CAC9C,IAAI;EACF,OAAO,mBAAmB,OAAO;CACnC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,YAAY,OAAyC;CAC5D,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAChC,OAAO,MAAM,QAAQ,KAAK,IAAI,MAAM,IAAI,aAAa,IAAI,cAAc,KAAK;AAC9E;;;;;;;AAQA,SAAgB,kBAA6D,QAAc;CACzF,MAAM,UAA2C,CAAC;CAClD,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAE9C,OAAO,eAAe,SAAS,KAAK;EAClC,OAAO,YAAY,KAAK;EACxB,YAAY;EACZ,UAAU;EACV,cAAc;CAChB,CAAC;CAEH,OAAO;AACT"}
@@ -7,5 +7,7 @@ type BindingContext = Pick<StorefrontContext, 'bindingId' | 'basePath'>;
7
7
  export declare function redirectToStorefrontPage(context: BindingContext, routeMap: RouteMap, target: PageRef | string): never;
8
8
  /** Next's `permanentRedirect` to a page reference or a logical path, resolved for the binding. */
9
9
  export declare function permanentRedirectToStorefrontPage(context: BindingContext, routeMap: RouteMap, target: PageRef | string): never;
10
+ /** Next's `redirect` to `resolveSignInHref`: the session gate's answer to an anonymous request. */
11
+ export declare function redirectToSignIn(context: BindingContext, routeMap: RouteMap, returnPath: string): never;
10
12
  //#endregion
11
13
  //# sourceMappingURL=redirect.d.ts.map
@@ -1,5 +1,7 @@
1
+ import { RETURN_URL_PARAM, resolveSiteRelativeHref, signInTarget } from "../../utils/safe-href.js";
1
2
  import { resolveStorefrontHref } from "./resolve-storefront-href.js";
2
3
  import { reportUnresolved } from "./report.js";
4
+ import { MOCK_SESSION_ROUTE, mockSessionToken } from "../session/mock-session.js";
3
5
  import { permanentRedirect, redirect } from "next/navigation";
4
6
  //#region src/sdk/navigation/redirect.ts
5
7
  function resolveOrThrow(context, routeMap, target) {
@@ -16,7 +18,23 @@ function redirectToStorefrontPage(context, routeMap, target) {
16
18
  function permanentRedirectToStorefrontPage(context, routeMap, target) {
17
19
  return permanentRedirect(resolveOrThrow(context, routeMap, target));
18
20
  }
21
+ /**
22
+ * Where the session gate sends an anonymous request: the binding's sign-in page carrying `returnPath`, a
23
+ * logical path. With `FS_MOCK_SESSION` set it is the mock session handler instead, which lives outside
24
+ * every binding, so the return it carries is already the public path.
25
+ */
26
+ function resolveSignInHref(context, routeMap, returnPath) {
27
+ if (mockSessionToken() === null) return resolveOrThrow(context, routeMap, signInTarget(returnPath));
28
+ const back = resolveStorefrontHref(context, routeMap, returnPath).href;
29
+ const destination = back === null ? null : resolveSiteRelativeHref(back);
30
+ if (!destination?.safe) return MOCK_SESSION_ROUTE;
31
+ return `${MOCK_SESSION_ROUTE}?${new URLSearchParams({ [RETURN_URL_PARAM]: destination.href })}`;
32
+ }
33
+ /** Next's `redirect` to `resolveSignInHref`: the session gate's answer to an anonymous request. */
34
+ function redirectToSignIn(context, routeMap, returnPath) {
35
+ return redirect(resolveSignInHref(context, routeMap, returnPath));
36
+ }
19
37
  //#endregion
20
- export { permanentRedirectToStorefrontPage, redirectToStorefrontPage };
38
+ export { permanentRedirectToStorefrontPage, redirectToSignIn, redirectToStorefrontPage, resolveSignInHref };
21
39
 
22
40
  //# sourceMappingURL=redirect.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"redirect.js","names":[],"sources":["../../../src/sdk/navigation/redirect.ts"],"sourcesContent":["import type { StorefrontContext } from '@vtex/fs-core';\nimport { permanentRedirect, redirect } from 'next/navigation';\nimport { reportUnresolved } from './report.js';\nimport { resolveStorefrontHref } from './resolve-storefront-href.js';\nimport type { PageRef, RouteMap } from './types.js';\n\ntype BindingContext = Pick<StorefrontContext, 'bindingId' | 'basePath'>;\n\nfunction resolveOrThrow(context: BindingContext, routeMap: RouteMap, target: PageRef | string): string {\n const result = resolveStorefrontHref(context, routeMap, target);\n if (result.href !== null) return result.href;\n reportUnresolved(result.reason, target);\n throw new Error(\n `Cannot redirect: ${JSON.stringify(target)} resolved to no href (${result.reason}) on ` +\n `binding ${JSON.stringify(context.bindingId)}.`,\n );\n}\n\n/** Next's `redirect` to a page reference or a logical path, resolved for the binding. */\nexport function redirectToStorefrontPage(context: BindingContext, routeMap: RouteMap, target: PageRef | string): never {\n return redirect(resolveOrThrow(context, routeMap, target));\n}\n\n/** Next's `permanentRedirect` to a page reference or a logical path, resolved for the binding. */\nexport function permanentRedirectToStorefrontPage(\n context: BindingContext,\n routeMap: RouteMap,\n target: PageRef | string,\n): never {\n return permanentRedirect(resolveOrThrow(context, routeMap, target));\n}\n"],"mappings":";;;;AAQA,SAAS,eAAe,SAAyB,UAAoB,QAAkC;CACrG,MAAM,SAAS,sBAAsB,SAAS,UAAU,MAAM;CAC9D,IAAI,OAAO,SAAS,MAAM,OAAO,OAAO;CACxC,iBAAiB,OAAO,QAAQ,MAAM;CACtC,MAAM,IAAI,MACR,oBAAoB,KAAK,UAAU,MAAM,EAAE,wBAAwB,OAAO,OAAO,eACpE,KAAK,UAAU,QAAQ,SAAS,EAAE,EACjD;AACF;;AAGA,SAAgB,yBAAyB,SAAyB,UAAoB,QAAiC;CACrH,OAAO,SAAS,eAAe,SAAS,UAAU,MAAM,CAAC;AAC3D;;AAGA,SAAgB,kCACd,SACA,UACA,QACO;CACP,OAAO,kBAAkB,eAAe,SAAS,UAAU,MAAM,CAAC;AACpE"}
1
+ {"version":3,"file":"redirect.js","names":[],"sources":["../../../src/sdk/navigation/redirect.ts"],"sourcesContent":["import type { StorefrontContext } from '@vtex/fs-core';\nimport { permanentRedirect, redirect } from 'next/navigation';\nimport { RETURN_URL_PARAM, resolveSiteRelativeHref, signInTarget } from '../../utils/safe-href.js';\nimport { MOCK_SESSION_ROUTE, mockSessionToken } from '../session/mock-session.js';\nimport { reportUnresolved } from './report.js';\nimport { resolveStorefrontHref } from './resolve-storefront-href.js';\nimport type { PageRef, RouteMap } from './types.js';\n\ntype BindingContext = Pick<StorefrontContext, 'bindingId' | 'basePath'>;\n\nfunction resolveOrThrow(context: BindingContext, routeMap: RouteMap, target: PageRef | string): string {\n const result = resolveStorefrontHref(context, routeMap, target);\n if (result.href !== null) return result.href;\n reportUnresolved(result.reason, target);\n throw new Error(\n `Cannot redirect: ${JSON.stringify(target)} resolved to no href (${result.reason}) on ` +\n `binding ${JSON.stringify(context.bindingId)}.`,\n );\n}\n\n/** Next's `redirect` to a page reference or a logical path, resolved for the binding. */\nexport function redirectToStorefrontPage(context: BindingContext, routeMap: RouteMap, target: PageRef | string): never {\n return redirect(resolveOrThrow(context, routeMap, target));\n}\n\n/** Next's `permanentRedirect` to a page reference or a logical path, resolved for the binding. */\nexport function permanentRedirectToStorefrontPage(\n context: BindingContext,\n routeMap: RouteMap,\n target: PageRef | string,\n): never {\n return permanentRedirect(resolveOrThrow(context, routeMap, target));\n}\n\n/**\n * Where the session gate sends an anonymous request: the binding's sign-in page carrying `returnPath`, a\n * logical path. With `FS_MOCK_SESSION` set it is the mock session handler instead, which lives outside\n * every binding, so the return it carries is already the public path.\n */\nexport function resolveSignInHref(context: BindingContext, routeMap: RouteMap, returnPath: string): string {\n if (mockSessionToken() === null) {\n return resolveOrThrow(context, routeMap, signInTarget(returnPath));\n }\n const back = resolveStorefrontHref(context, routeMap, returnPath).href;\n const destination = back === null ? null : resolveSiteRelativeHref(back);\n if (!destination?.safe) return MOCK_SESSION_ROUTE;\n return `${MOCK_SESSION_ROUTE}?${new URLSearchParams({ [RETURN_URL_PARAM]: destination.href })}`;\n}\n\n/** Next's `redirect` to `resolveSignInHref`: the session gate's answer to an anonymous request. */\nexport function redirectToSignIn(context: BindingContext, routeMap: RouteMap, returnPath: string): never {\n return redirect(resolveSignInHref(context, routeMap, returnPath));\n}\n"],"mappings":";;;;;;AAUA,SAAS,eAAe,SAAyB,UAAoB,QAAkC;CACrG,MAAM,SAAS,sBAAsB,SAAS,UAAU,MAAM;CAC9D,IAAI,OAAO,SAAS,MAAM,OAAO,OAAO;CACxC,iBAAiB,OAAO,QAAQ,MAAM;CACtC,MAAM,IAAI,MACR,oBAAoB,KAAK,UAAU,MAAM,EAAE,wBAAwB,OAAO,OAAO,eACpE,KAAK,UAAU,QAAQ,SAAS,EAAE,EACjD;AACF;;AAGA,SAAgB,yBAAyB,SAAyB,UAAoB,QAAiC;CACrH,OAAO,SAAS,eAAe,SAAS,UAAU,MAAM,CAAC;AAC3D;;AAGA,SAAgB,kCACd,SACA,UACA,QACO;CACP,OAAO,kBAAkB,eAAe,SAAS,UAAU,MAAM,CAAC;AACpE;;;;;;AAOA,SAAgB,kBAAkB,SAAyB,UAAoB,YAA4B;CACzG,IAAI,iBAAiB,MAAM,MACzB,OAAO,eAAe,SAAS,UAAU,aAAa,UAAU,CAAC;CAEnE,MAAM,OAAO,sBAAsB,SAAS,UAAU,UAAU,CAAC,CAAC;CAClE,MAAM,cAAc,SAAS,OAAO,OAAO,wBAAwB,IAAI;CACvE,IAAI,CAAC,aAAa,MAAM,OAAO;CAC/B,OAAO,GAAG,mBAAmB,GAAG,IAAI,gBAAgB,GAAG,mBAAmB,YAAY,KAAK,CAAC;AAC9F;;AAGA,SAAgB,iBAAiB,SAAyB,UAAoB,YAA2B;CACvG,OAAO,SAAS,kBAAkB,SAAS,UAAU,UAAU,CAAC;AAClE"}
@@ -26,6 +26,19 @@ export type RouteMapEntry = {
26
26
  params?: string[];
27
27
  aliases?: Record<string, string>;
28
28
  bindings?: string[];
29
+ /**
30
+ * Set on a Search Landing Page: the term a singleton pins, as authored, or the content type and route
31
+ * parameter of the page over CMS term entries, whose item slug is the normalized term.
32
+ */
33
+ searchTerm?: string | {
34
+ contentType: string;
35
+ param: string;
36
+ };
37
+ /**
38
+ * Set on an Entity Landing Page: the Relay node ID of the collection, category, or brand whose standard
39
+ * listing points its canonical here, the ID `catalogRoute` returns for that listing.
40
+ */
41
+ canonicalFor?: string;
29
42
  };
30
43
  /** Keyed by page name. */
31
44
  export type RouteMap = Record<string, RouteMapEntry>;
@@ -0,0 +1,20 @@
1
+ import { isAcceptedCardBin } from "@vtex/fs-domain-logic/checkout/rules";
2
+ //#region src/sdk/payment/bin-format.ts
3
+ /**
4
+ * The browser-side use of the rule `paymentMethodSelect` applies to `bin`, so a malformed value never leaves
5
+ * through `payment.setMethod`. The rule itself lives in `@vtex/fs-domain-logic/checkout/rules`, shared with the
6
+ * server, so the two can no longer drift; the fixed refusal text lives there too. A new card (no `accountId`,
7
+ * or an empty one) carries nothing or exactly eight digits; a saved card carries nothing or one to eight,
8
+ * because the server compares it to the card's own stored BIN. `null` counts as nothing, like the server; any
9
+ * other value that is not a string is refused. Reads the value and returns a boolean: it never stores, logs or
10
+ * interpolates it.
11
+ */
12
+ function isAcceptedBin({ bin, accountId }) {
13
+ if (bin === void 0 || bin === null || bin === "") return true;
14
+ if (typeof bin !== "string") return false;
15
+ return isAcceptedCardBin(bin, Boolean(accountId));
16
+ }
17
+ //#endregion
18
+ export { isAcceptedBin };
19
+
20
+ //# sourceMappingURL=bin-format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin-format.js","names":[],"sources":["../../../src/sdk/payment/bin-format.ts"],"sourcesContent":["import { isAcceptedCardBin } from '@vtex/fs-domain-logic/checkout/rules';\n\n/**\n * The browser-side use of the rule `paymentMethodSelect` applies to `bin`, so a malformed value never leaves\n * through `payment.setMethod`. The rule itself lives in `@vtex/fs-domain-logic/checkout/rules`, shared with the\n * server, so the two can no longer drift; the fixed refusal text lives there too. A new card (no `accountId`,\n * or an empty one) carries nothing or exactly eight digits; a saved card carries nothing or one to eight,\n * because the server compares it to the card's own stored BIN. `null` counts as nothing, like the server; any\n * other value that is not a string is refused. Reads the value and returns a boolean: it never stores, logs or\n * interpolates it.\n */\nexport function isAcceptedBin({ bin, accountId }: Readonly<{ bin?: string | null; accountId?: string }>): boolean {\n if (bin === undefined || bin === null || bin === '') return true;\n if (typeof bin !== 'string') return false;\n return isAcceptedCardBin(bin, Boolean(accountId));\n}\n"],"mappings":";;;;;;;;;;;AAWA,SAAgB,cAAc,EAAE,KAAK,aAA6E;CAChH,IAAI,QAAQ,KAAA,KAAa,QAAQ,QAAQ,QAAQ,IAAI,OAAO;CAC5D,IAAI,OAAO,QAAQ,UAAU,OAAO;CACpC,OAAO,kBAAkB,KAAK,QAAQ,SAAS,CAAC;AAClD"}
@@ -0,0 +1,37 @@
1
+ //#region src/sdk/payment/challenge-return.ts
2
+ /**
3
+ * The contract between the two ends of the 3D Secure round trip (T208, Decision 2): `usePlaceOrder` builds
4
+ * the return URL's query before the card is posted, and the `ChallengeReturn` page reads it back when the
5
+ * bank sends the shopper home. Both ends live here so they cannot drift apart.
6
+ *
7
+ * The query is the order group and a literal flag, nothing else. The group is the only key the gateway
8
+ * callback needs and it exists before the card is posted. The reader is strict because the page it feeds
9
+ * issues a write: exactly one `orderGroup` that fits `ORDER_GROUP_PATTERN` (which excludes `.`, so a dot
10
+ * segment cannot arrive) and `redirect` equal to the string `true`. Anything else the gateway or the bank
11
+ * appends is ignored, and never returned.
12
+ */
13
+ const ORDER_GROUP_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
14
+ const GROUP_PARAM = "orderGroup";
15
+ const FLAG_PARAM = "redirect";
16
+ const FLAG_VALUE = "true";
17
+ /** The query for a group's return URL, or `null` when the group is not one a return page would accept. */
18
+ function buildChallengeReturnQuery(orderGroup) {
19
+ if (!ORDER_GROUP_PATTERN.test(orderGroup)) return null;
20
+ return {
21
+ [GROUP_PARAM]: orderGroup,
22
+ [FLAG_PARAM]: FLAG_VALUE
23
+ };
24
+ }
25
+ /** The order group a return URL's query names, or `null` for anything that is not exactly a return query. */
26
+ function readChallengeReturn(search) {
27
+ const params = new URLSearchParams(search);
28
+ const groups = params.getAll(GROUP_PARAM);
29
+ const [orderGroup] = groups;
30
+ if (groups.length !== 1 || orderGroup === void 0 || !ORDER_GROUP_PATTERN.test(orderGroup)) return null;
31
+ if (params.get(FLAG_PARAM) !== FLAG_VALUE) return null;
32
+ return { orderGroup };
33
+ }
34
+ //#endregion
35
+ export { buildChallengeReturnQuery, readChallengeReturn };
36
+
37
+ //# sourceMappingURL=challenge-return.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"challenge-return.js","names":[],"sources":["../../../src/sdk/payment/challenge-return.ts"],"sourcesContent":["/**\n * The contract between the two ends of the 3D Secure round trip (T208, Decision 2): `usePlaceOrder` builds\n * the return URL's query before the card is posted, and the `ChallengeReturn` page reads it back when the\n * bank sends the shopper home. Both ends live here so they cannot drift apart.\n *\n * The query is the order group and a literal flag, nothing else. The group is the only key the gateway\n * callback needs and it exists before the card is posted. The reader is strict because the page it feeds\n * issues a write: exactly one `orderGroup` that fits `ORDER_GROUP_PATTERN` (which excludes `.`, so a dot\n * segment cannot arrive) and `redirect` equal to the string `true`. Anything else the gateway or the bank\n * appends is ignored, and never returned.\n */\n\nconst ORDER_GROUP_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;\n\nconst GROUP_PARAM = 'orderGroup';\nconst FLAG_PARAM = 'redirect';\nconst FLAG_VALUE = 'true';\n\n/** The query for a group's return URL, or `null` when the group is not one a return page would accept. */\nexport function buildChallengeReturnQuery(orderGroup: string): Record<string, string> | null {\n if (!ORDER_GROUP_PATTERN.test(orderGroup)) return null;\n return { [GROUP_PARAM]: orderGroup, [FLAG_PARAM]: FLAG_VALUE };\n}\n\n/** The order group a return URL's query names, or `null` for anything that is not exactly a return query. */\nexport function readChallengeReturn(search: string): { orderGroup: string } | null {\n const params = new URLSearchParams(search);\n const groups = params.getAll(GROUP_PARAM);\n const [orderGroup] = groups;\n if (groups.length !== 1 || orderGroup === undefined || !ORDER_GROUP_PATTERN.test(orderGroup)) return null;\n if (params.get(FLAG_PARAM) !== FLAG_VALUE) return null;\n return { orderGroup };\n}\n"],"mappings":";;;;;;;;;;;;AAYA,MAAM,sBAAsB;AAE5B,MAAM,cAAc;AACpB,MAAM,aAAa;AACnB,MAAM,aAAa;;AAGnB,SAAgB,0BAA0B,YAAmD;CAC3F,IAAI,CAAC,oBAAoB,KAAK,UAAU,GAAG,OAAO;CAClD,OAAO;GAAG,cAAc;GAAa,aAAa;CAAW;AAC/D;;AAGA,SAAgB,oBAAoB,QAA+C;CACjF,MAAM,SAAS,IAAI,gBAAgB,MAAM;CACzC,MAAM,SAAS,OAAO,OAAO,WAAW;CACxC,MAAM,CAAC,cAAc;CACrB,IAAI,OAAO,WAAW,KAAK,eAAe,KAAA,KAAa,CAAC,oBAAoB,KAAK,UAAU,GAAG,OAAO;CACrG,IAAI,OAAO,IAAI,UAAU,MAAM,YAAY,OAAO;CAClD,OAAO,EAAE,WAAW;AACtB"}
@@ -0,0 +1,39 @@
1
+ import { useSyncExternalStore } from "react";
2
+ //#region src/sdk/payment/confirmation-last-four.ts
3
+ const FOUR_ASCII_DIGITS = /^\d{4}$/;
4
+ const NOT_AN_ASCII_DIGIT = /\D/g;
5
+ const SHORTEST_NUMBER_LENGTH = 8;
6
+ let record = null;
7
+ const listeners = /* @__PURE__ */ new Set();
8
+ function notify() {
9
+ for (const listener of listeners) listener();
10
+ }
11
+ function subscribe(listener) {
12
+ listeners.add(listener);
13
+ return () => {
14
+ listeners.delete(listener);
15
+ };
16
+ }
17
+ /** The last four ASCII digits of `rawDigits` once every non-digit is removed; null below 8 digits. */
18
+ function lastFourOf(rawDigits) {
19
+ const digits = rawDigits.replaceAll(NOT_AN_ASCII_DIGIT, "");
20
+ return digits.length >= SHORTEST_NUMBER_LENGTH ? digits.slice(-4) : null;
21
+ }
22
+ /** Stores one record. Refuses (no-op) unless `lastFour` is exactly four ASCII digits and `orderGroup` is non-empty. */
23
+ function rememberConfirmationLastFour(orderGroup, lastFour) {
24
+ if (typeof orderGroup !== "string" || orderGroup === "") return;
25
+ if (typeof lastFour !== "string" || !FOUR_ASCII_DIGITS.test(lastFour)) return;
26
+ record = {
27
+ orderGroup,
28
+ lastFour
29
+ };
30
+ notify();
31
+ }
32
+ /** The four digits for this order group, or null. The server snapshot is always null. */
33
+ function useConfirmationLastFour(orderGroup) {
34
+ return useSyncExternalStore(subscribe, () => record !== null && orderGroup != null && record.orderGroup === orderGroup ? record.lastFour : null, () => null);
35
+ }
36
+ //#endregion
37
+ export { lastFourOf, rememberConfirmationLastFour, useConfirmationLastFour };
38
+
39
+ //# sourceMappingURL=confirmation-last-four.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confirmation-last-four.js","names":[],"sources":["../../../src/sdk/payment/confirmation-last-four.ts"],"sourcesContent":["import { useSyncExternalStore } from 'react';\n\n/**\n * The masked last four of a newly typed payment instrument, carried in module memory from the place-order\n * step to the confirmation recap (T82, US-8). It holds one record: four ASCII digits and the order group\n * they belong to. It is never written to a storage API, a cookie, a URL, a header, a log, an analytics\n * event, a GraphQL variable or an error, and it is empty on the server and on first load.\n */\ntype ConfirmationLastFour = Readonly<{ orderGroup: string; lastFour: string }>;\n\nconst FOUR_ASCII_DIGITS = /^\\d{4}$/;\nconst NOT_AN_ASCII_DIGIT = /\\D/g;\nconst SHORTEST_NUMBER_LENGTH = 8;\n\nlet record: ConfirmationLastFour | null = null;\nconst listeners = new Set<() => void>();\n\nfunction notify(): void {\n for (const listener of listeners) listener();\n}\n\nfunction subscribe(listener: () => void): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\n/** The last four ASCII digits of `rawDigits` once every non-digit is removed; null below 8 digits. */\nexport function lastFourOf(rawDigits: string): string | null {\n const digits = rawDigits.replaceAll(NOT_AN_ASCII_DIGIT, '');\n return digits.length >= SHORTEST_NUMBER_LENGTH ? digits.slice(-4) : null;\n}\n\n/** Stores one record. Refuses (no-op) unless `lastFour` is exactly four ASCII digits and `orderGroup` is non-empty. */\nexport function rememberConfirmationLastFour(orderGroup: string, lastFour: string): void {\n if (typeof orderGroup !== 'string' || orderGroup === '') return;\n if (typeof lastFour !== 'string' || !FOUR_ASCII_DIGITS.test(lastFour)) return;\n record = { orderGroup, lastFour };\n notify();\n}\n\n/** The current record, or null. */\nexport function readConfirmationLastFour(): ConfirmationLastFour | null {\n return record;\n}\n\n/** The four digits for this order group, or null. The server snapshot is always null. */\nexport function useConfirmationLastFour(orderGroup: string | null | undefined): string | null {\n return useSyncExternalStore(\n subscribe,\n () => (record !== null && orderGroup != null && record.orderGroup === orderGroup ? record.lastFour : null),\n () => null,\n );\n}\n\n/** Test seam: empties the record. */\nexport function clearConfirmationLastFour(): void {\n record = null;\n notify();\n}\n"],"mappings":";;AAUA,MAAM,oBAAoB;AAC1B,MAAM,qBAAqB;AAC3B,MAAM,yBAAyB;AAE/B,IAAI,SAAsC;AAC1C,MAAM,4BAAY,IAAI,IAAgB;AAEtC,SAAS,SAAe;CACtB,KAAK,MAAM,YAAY,WAAW,SAAS;AAC7C;AAEA,SAAS,UAAU,UAAkC;CACnD,UAAU,IAAI,QAAQ;CACtB,aAAa;EACX,UAAU,OAAO,QAAQ;CAC3B;AACF;;AAGA,SAAgB,WAAW,WAAkC;CAC3D,MAAM,SAAS,UAAU,WAAW,oBAAoB,EAAE;CAC1D,OAAO,OAAO,UAAU,yBAAyB,OAAO,MAAM,EAAE,IAAI;AACtE;;AAGA,SAAgB,6BAA6B,YAAoB,UAAwB;CACvF,IAAI,OAAO,eAAe,YAAY,eAAe,IAAI;CACzD,IAAI,OAAO,aAAa,YAAY,CAAC,kBAAkB,KAAK,QAAQ,GAAG;CACvE,SAAS;EAAE;EAAY;CAAS;CAChC,OAAO;AACT;;AAQA,SAAgB,wBAAwB,YAAsD;CAC5F,OAAO,qBACL,iBACO,WAAW,QAAQ,cAAc,QAAQ,OAAO,eAAe,aAAa,OAAO,WAAW,YAC/F,IACR;AACF"}
@@ -38,7 +38,7 @@ export type PaymentGatewayTransaction = Readonly<{
38
38
  installmentsValueInCents: number;
39
39
  /** `PaymentInstallment.interestRate`; 0 for the interest-free 1x default. */
40
40
  interestRate: number;
41
- /** Absolute return URL. Phase-2 redirect mode only; omitted in v1's direct mode. */
41
+ /** Absolute return URL for the 3D Secure challenge. Omitted when the store authored no return page. */
42
42
  callbackUrl?: string;
43
43
  /**
44
44
  * Billing differs from the delivery address. Defaults to `false`, because `setBillingAddress` persists
@@ -23,7 +23,10 @@ import { isTrustedGatewayOrigin } from "./gateway-origin.js";
23
23
  */
24
24
  /** Client-synthesized code for a failed gateway leg — distinct from the BFF's `NETWORK_ERROR`. */
25
25
  const PAYMENT_GATEWAY_ERROR_CODE = "GATEWAY_ERROR";
26
- /** The single userError a rejected request, a non-2xx response and a request the builder refused all resolve to. */
26
+ /**
27
+ * The single userError a rejected request, a non-2xx response and a request the builder refused all resolve to.
28
+ * Its `message` is diagnostic; `PlaceOrder` words the code.
29
+ */
27
30
  const PAYMENT_GATEWAY_USER_ERROR = {
28
31
  code: PAYMENT_GATEWAY_ERROR_CODE,
29
32
  message: "Unable to complete the payment. Please try again."
@@ -85,7 +88,10 @@ function buildGatewayPaymentsRequest({ transaction, card }) {
85
88
  if (!isTrustedGatewayOrigin(transaction.gatewayUrl)) throw new Error("Refusing to post card data: the transaction carries no trusted https gateway origin.");
86
89
  const params = new URLSearchParams({ orderId: transaction.orderGroup });
87
90
  if (transaction.userProfileId !== null) params.append("userProfileId", transaction.userProfileId);
88
- if (transaction.callbackUrl !== void 0) params.append("callbackUrl", transaction.callbackUrl);
91
+ if (transaction.callbackUrl !== void 0) {
92
+ params.append("callbackUrl", transaction.callbackUrl);
93
+ params.append("redirect", "false");
94
+ }
89
95
  const transactionId = encodeURIComponent(transaction.transactionId);
90
96
  const url = `${transaction.gatewayUrl}/api/payments/transactions/${transactionId}/payments?${params}`;
91
97
  const { bin, fields } = toCardBody(card);
@@ -1 +1 @@
1
- {"version":3,"file":"gateway.js","names":[],"sources":["../../../src/sdk/payment/gateway.ts"],"sourcesContent":["/**\n * The direct-to-gateway card POST (specs/payment-action-namespace.md, US-6) — the PCI boundary of the\n * credit-card feature. A new card's number and CVV, or a saved card's CVV, go from the browser straight\n * to the VTEX payment gateway and never transit our GraphQL layer or the normalized Apollo cache\n * (RFC D13; ADR-0010's sanctioned façade flavor).\n *\n * This module imports no Apollo and no GraphQL symbol on purpose: the code that holds card data has no\n * route to the cache, and that property is checkable by reading the imports above. Card data arrives as\n * a runtime argument from the card-entry component's local state (T7) — it is never a declared action\n * payload, a fragment field, or a schema-bindable prop, so the AI Store Builder and the visual editor\n * have no name to map a value onto.\n *\n * Nothing on this path is ever logged, serialized, or stored anywhere but the request body: the caller\n * in `use-payment-actions.ts` logs a static message plus the error's `name` only.\n *\n * The request shape is behavior evidence from the legacy checkout\n * (`fastcheckout@cd09bec3`, `packages/apps/client/src/screens/Payment/components/CardForm/services/gateway.service.ts`)\n * — never a port. Where the legacy hardcoded a value under a `TODO` (installment count, interest rate,\n * reference value) this builder reads it off the transaction descriptor instead.\n */\n\nimport { loggableErrorName } from '../../utils/loggable-error-name.js';\nimport { isTrustedGatewayOrigin } from './gateway-origin.js';\nimport type { PaymentUserError } from './operations.js';\n\n/** Client-synthesized code for a failed gateway leg — distinct from the BFF's `NETWORK_ERROR`. */\nexport const PAYMENT_GATEWAY_ERROR_CODE = 'GATEWAY_ERROR';\n\n/** The single userError a rejected request, a non-2xx response and a request the builder refused all resolve to. */\nexport const PAYMENT_GATEWAY_USER_ERROR: PaymentUserError = {\n code: PAYMENT_GATEWAY_ERROR_CODE,\n message: 'Unable to complete the payment. Please try again.',\n};\n\n/**\n * Non-sensitive descriptor of the open transaction. Every field maps to a value the caller already\n * holds — `paymentStartTransaction`'s payload (T3) or the `Payment` read model (T1) — except\n * `gatewayUrl` and `merchantName`, which that payload does not carry today (Gaps 1 and 2 in the spec).\n * Amounts are in the currency's **minor units**; `PaymentStartTransactionPayload.value.amount` is a\n * decimal, so the caller converts once, visibly, rather than having this module assume an exponent.\n */\nexport type PaymentGatewayTransaction = Readonly<{\n /**\n * Gateway origin, e.g. `https://acme.vtexvault.com`. Server-resolved by T18 and read off\n * `paymentStartTransaction`'s payload; never derived here. It is nullable there and required here,\n * so the builder re-checks it (`isTrustedGatewayOrigin`) rather than trusting the type.\n */\n gatewayUrl: string;\n /** `PaymentStartTransactionPayload.transactionId`. */\n transactionId: string;\n /** VTEX merchant name for this transaction. Resolved server-side by T3 but not exposed on its payload. */\n merchantName: string;\n /** `PaymentStartTransactionPayload.orderGroup` — the gateway's `orderId` query parameter. */\n orderGroup: string;\n /** `PaymentStartTransactionPayload.userProfileId`; null for a guest order, so the query parameter is left out. */\n userProfileId: string | null;\n /** `Payment.selectedMethodId` — the VTEX payment-system id. */\n paymentSystem: string;\n /** `PaymentMethod.groupName`, e.g. `creditCardPaymentGroup`. */\n groupName: string;\n /** `PaymentStartTransactionPayload.value.currencyCode`. */\n currencyCode: string;\n /** Transaction total, in minor units. */\n valueInCents: number;\n /** Pre-interest base (`PaymentInstallmentOption.baseValue`), in minor units. */\n referenceValueInCents: number;\n /** `Payment.selectedInstallment.count`; 1 when the shopper never picked a plan. */\n installments: number;\n /** Per-installment amount (`PaymentInstallment.value`), in minor units. */\n installmentsValueInCents: number;\n /** `PaymentInstallment.interestRate`; 0 for the interest-free 1x default. */\n interestRate: number;\n /** Absolute return URL. Phase-2 redirect mode only; omitted in v1's direct mode. */\n callbackUrl?: string;\n /**\n * Billing differs from the delivery address. Defaults to `false`, because `setBillingAddress` persists\n * billing on the order form's `invoiceData` (T3) and the gateway reads it from there rather than from\n * this body. The call site that would override it is T13's `usePlaceOrder`, the one place the\n * descriptor is assembled; T11 owns the live verification of the assumption and publishes the flag to\n * T5's `draft` for T13 to read. Confirming it never reopens this module.\n */\n billingAddressDifferent?: boolean;\n}>;\n\n/** A newly entered card. Runtime argument only — never declared, never logged, never cached. */\nexport type PaymentGatewayNewCard = Readonly<{\n kind: 'new';\n /** Full card number. The builder strips whatever separators the method's `numberMask` inserted. */\n number: string;\n /** Security code (CVV). */\n securityCode: string;\n /** Expiry. Normalized to `MM/YY`, so a `MM/YYYY` mask is accepted. */\n expirationDate: string;\n holderName: string;\n /** Shopper document (a CPF). The builder strips its punctuation. */\n document?: string;\n /** Shopper-assigned label, when the save-card control collected one. */\n cardLabel?: string;\n /** The card-save flag itself — the other half of `payment.saveCard`'s consent write (RFC D5). */\n saveCard?: boolean;\n}>;\n\n/** A previously saved card: its account reference plus the CVV the shopper re-enters. */\nexport type PaymentGatewaySavedCard = Readonly<{\n kind: 'saved';\n /** `SavedCard.accountId`. */\n accountId: string;\n /** `SavedCard.bin` — not sensitive; the read model exposes it for installment lookup. */\n bin: string;\n /** Security code (CVV). */\n securityCode: string;\n}>;\n\nexport type PaymentGatewayCard = PaymentGatewayNewCard | PaymentGatewaySavedCard;\n\nexport type SendPaymentsRequest = Readonly<{\n transaction: PaymentGatewayTransaction;\n card: PaymentGatewayCard;\n}>;\n\n/** The assembled request. Exported so the body shape is unit-testable without issuing a POST. */\nexport type GatewayPaymentsRequest = Readonly<{ url: string; body: readonly unknown[] }>;\n\n/** VTEX bins the leading eight digits, not six — the legacy's own `sanitizedBin` slice. */\nconst BIN_LENGTH = 8;\n\n/**\n * Strips the separators a mask inserted. `PaymentMethodValidator.numberMask` is server-driven (T1) and the\n * card-entry component (T7) renders the input through it, so its local state holds `4111 1111 1111 1111`\n * rather than the digits. The legacy normalized here, in the builder, before its own BIN slice\n * (`card.cardNumber = card.cardNumber.replace(/ /g, '')`) — the boundary is the one place the obligation\n * cannot be forgotten, and a spaced BIN is a lookup the gateway fails with no diagnosable error.\n */\nfunction toDigits(value: string): string {\n return value.replace(/\\D/g, '');\n}\n\n/** `MM/YY` whatever the mask produced (`MM/YYYY`, `MMYY`) — the legacy's own two-slice normalization. */\nfunction toDueDate(expirationDate: string): string {\n const digits = toDigits(expirationDate);\n return `${digits.slice(0, 2)}/${digits.slice(-2)}`;\n}\n\n/** The card half of the body — the BIN and the `fields` map, both derived from one normalization pass. */\nfunction toCardBody(card: PaymentGatewayCard): { bin: string; fields: Record<string, unknown> } {\n if (card.kind === 'saved') {\n return { bin: card.bin, fields: { bin: card.bin, validationCode: card.securityCode } };\n }\n\n const number = toDigits(card.number);\n const bin = number.slice(0, BIN_LENGTH);\n\n return {\n bin,\n fields: {\n bin,\n cardNumber: number,\n // The legacy's own `\\W` strip, so a CPF typed `123.456.789-00` reaches the gateway unpunctuated.\n document: card.document === undefined ? null : card.document.replace(/\\W/g, ''),\n dueDate: toDueDate(card.expirationDate),\n holderName: card.holderName,\n validationCode: card.securityCode,\n cardLabel: card.cardLabel,\n savePaymentData: card.saveCard ?? false,\n },\n };\n}\n\n/**\n * Builds the gateway URL and body. Billing is deliberately absent from the body: `setBillingAddress`\n * already persisted it on the order form's `invoiceData` (T3), so the gateway reads it from there — hence\n * the `billingAddressDifferent: false` default the two billing flags derive from. `originalPaymentIndex`\n * is the legacy's own constant for a single-payment order.\n *\n * The origin check is the last line of defence, not the first: `usePlaceOrder` already refuses an\n * untrusted origin *before* asking a holder for the card (T13, Decision 4). A builder has no userError\n * channel, so it throws — `sendPayments` catches, collapses it to `GATEWAY_ERROR`, and logs the error's\n * name only, so nothing about the card reaches a log. The throw happens before the body is assembled.\n */\nexport function buildGatewayPaymentsRequest({ transaction, card }: SendPaymentsRequest): GatewayPaymentsRequest {\n if (!isTrustedGatewayOrigin(transaction.gatewayUrl)) {\n throw new Error('Refusing to post card data: the transaction carries no trusted https gateway origin.');\n }\n\n const params = new URLSearchParams({ orderId: transaction.orderGroup });\n if (transaction.userProfileId !== null) params.append('userProfileId', transaction.userProfileId);\n if (transaction.callbackUrl !== undefined) params.append('callbackUrl', transaction.callbackUrl);\n\n const transactionId = encodeURIComponent(transaction.transactionId);\n const url = `${transaction.gatewayUrl}/api/payments/transactions/${transactionId}/payments?${params}`;\n\n const { bin, fields } = toCardBody(card);\n const billingAddressDifferent = transaction.billingAddressDifferent ?? false;\n\n const payment = {\n accountId: card.kind === 'saved' ? card.accountId : null,\n bin,\n chooseToUseNewCard: card.kind === 'new',\n currencyCode: transaction.currencyCode,\n fields,\n groupName: transaction.groupName,\n hasDefaultBillingAddress: !billingAddressDifferent,\n id: transaction.merchantName,\n installmentValue: transaction.installmentsValueInCents,\n installments: transaction.installments,\n installmentsInterestRate: transaction.interestRate,\n installmentsValue: transaction.installmentsValueInCents,\n interestRate: transaction.interestRate,\n isBillingAddressDifferent: billingAddressDifferent,\n originalPaymentIndex: 1,\n paymentSystem: transaction.paymentSystem,\n referenceValue: transaction.referenceValueInCents,\n tokenId: null,\n transaction: { id: transaction.transactionId, merchantName: transaction.merchantName },\n value: transaction.valueInCents,\n };\n\n return { url, body: [payment] };\n}\n\n/**\n * T29 (FR-6, OQ-7): this leg's own abort budget. Before this task the direct-to-gateway POST carried no\n * `AbortSignal` and no timeout at all, so a gateway that never answered left `placing` true and the CTA\n * dead for the life of the mount (Route C, `place-order.md`'s Known limitations). The BFF's own default\n * is 10s (`apps/storefront-api-core/.../api-timeout.ts:9`), but a card authorization can legitimately\n * run longer than a GraphQL round trip, and this exact number is not confirmed with payments (spec\n * OQ-7) — a placeholder pending that answer, not a tuned production value.\n *\n * Exported so `gateway.test.ts`'s own abort-budget test can assert the abort fires at exactly this\n * duration, rather than against `vi.runAllTimersAsync()`, which fires any pending timer regardless of\n * duration and would stay green even if this were edited to `300_000`. That mechanism test alone is\n * still self-referential about this constant's own *value* — it advances the fake clock by whatever\n * `GATEWAY_REQUEST_TIMEOUT_MS` currently holds, so on its own it cannot catch an edit to the constant\n * either (fix round 2, verification finding V2). `gateway.test.ts` also asserts this constant against\n * the literal `30_000` directly, in its own dedicated test — that is what actually fails if this\n * constant's value ever changes.\n */\nexport const GATEWAY_REQUEST_TIMEOUT_MS = 30_000;\n\n/**\n * What a card POST resolves (T112). `reachedGateway` is `false` only when this module can show no request\n * was issued — the request builder refused before any `fetch`. Anything it cannot classify (a rejection, a\n * timeout, an abort, a malformed result) is `true`: a browser cannot tell whether a request that never\n * answered was processed, and a `false` frees the shopper to post the card again. Beside it, `userErrors`\n * keeps the `{ ..., userErrors }` payload shape (ADR-00005); it carries no card value.\n */\nexport type PaymentGatewayResult = Readonly<{\n /** false only when no request was issued to the gateway. Anything unclassified is true. */\n reachedGateway: boolean;\n userErrors: readonly PaymentUserError[];\n}>;\n\n/**\n * Posts the card straight to the gateway and resolves a `PaymentGatewayResult`. A non-2xx response\n * resolves `{ reachedGateway: true, userErrors: [GATEWAY_ERROR] }`; a request the builder refuses\n * (an untrusted origin, a malformed card) resolves `{ reachedGateway: false, userErrors: [GATEWAY_ERROR] }`\n * without issuing a `fetch` or arming a timer, logging only the error's name. A rejected request —\n * including this leg's own timeout firing, or `options.signal` aborting — propagates, and the handler in\n * `use-payment-actions.ts` collapses it to a `reachedGateway: true` result: nothing here can prove it\n * never left. Neither outcome reads the response body: it may echo the request, and it tells the shopper\n * nothing more actionable than \"try again\".\n *\n * `options.signal`, when given, aborts this request in *addition to* — never instead of — this module's\n * own timeout: a caller opts into an earlier or externally triggered abort, but cannot opt out of the\n * budget that keeps this leg from hanging forever (FR-6, US-3). Composed with a plain `AbortController`\n * rather than `AbortSignal.any`/`AbortSignal.timeout` so the timeout is driven by an ordinary\n * `setTimeout`, the one implementation a test can advance deterministically with fake timers.\n *\n * No caller in this package passes `options.signal` today — it exists to satisfy the spec's own\n * Technical Contract (`specs/make-an-order-attempt-survive-a.md`) ahead of a future integration. Fix\n * pass, Low finding: the listener this composes onto `externalSignal` is now removed in the `finally`\n * below on every exit path, not only when it fires — previously, a caller that supplied a long-lived\n * signal (as opposed to a fresh one per call) would accumulate one listener, and this function's own\n * dead `AbortController`, per call that resolved normally.\n */\nexport async function postPaymentsToGateway(\n request: SendPaymentsRequest,\n options?: { signal?: AbortSignal },\n): Promise<PaymentGatewayResult> {\n let built: GatewayPaymentsRequest;\n try {\n built = buildGatewayPaymentsRequest(request);\n } catch (error) {\n // Name only: the builder's message and the request it rejected can carry the card.\n console.error(\n '[payment.sendPayments] the gateway request was refused before it was sent',\n loggableErrorName(error),\n );\n return { reachedGateway: false, userErrors: [PAYMENT_GATEWAY_USER_ERROR] };\n }\n const { url, body } = built;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(\n () => controller.abort(new DOMException('The gateway request timed out.', 'TimeoutError')),\n GATEWAY_REQUEST_TIMEOUT_MS,\n );\n const externalSignal = options?.signal;\n const onExternalAbort = () => controller.abort(externalSignal?.reason);\n if (externalSignal) {\n if (externalSignal.aborted) {\n controller.abort(externalSignal.reason);\n } else {\n externalSignal.addEventListener('abort', onExternalAbort, { once: true });\n }\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n return { reachedGateway: true, userErrors: response.ok ? [] : [PAYMENT_GATEWAY_USER_ERROR] };\n } finally {\n clearTimeout(timeoutId);\n externalSignal?.removeEventListener('abort', onExternalAbort);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"gateway.js","names":[],"sources":["../../../src/sdk/payment/gateway.ts"],"sourcesContent":["/**\n * The direct-to-gateway card POST (specs/payment-action-namespace.md, US-6) — the PCI boundary of the\n * credit-card feature. A new card's number and CVV, or a saved card's CVV, go from the browser straight\n * to the VTEX payment gateway and never transit our GraphQL layer or the normalized Apollo cache\n * (RFC D13; ADR-0010's sanctioned façade flavor).\n *\n * This module imports no Apollo and no GraphQL symbol on purpose: the code that holds card data has no\n * route to the cache, and that property is checkable by reading the imports above. Card data arrives as\n * a runtime argument from the card-entry component's local state (T7) — it is never a declared action\n * payload, a fragment field, or a schema-bindable prop, so the AI Store Builder and the visual editor\n * have no name to map a value onto.\n *\n * Nothing on this path is ever logged, serialized, or stored anywhere but the request body: the caller\n * in `use-payment-actions.ts` logs a static message plus the error's `name` only.\n *\n * The request shape is behavior evidence from the legacy checkout\n * (`fastcheckout@cd09bec3`, `packages/apps/client/src/screens/Payment/components/CardForm/services/gateway.service.ts`)\n * — never a port. Where the legacy hardcoded a value under a `TODO` (installment count, interest rate,\n * reference value) this builder reads it off the transaction descriptor instead.\n */\n\nimport { loggableErrorName } from '../../utils/loggable-error-name.js';\nimport { isTrustedGatewayOrigin } from './gateway-origin.js';\nimport type { PaymentUserError } from './operations.js';\n\n/** Client-synthesized code for a failed gateway leg — distinct from the BFF's `NETWORK_ERROR`. */\nexport const PAYMENT_GATEWAY_ERROR_CODE = 'GATEWAY_ERROR';\n\n/**\n * The single userError a rejected request, a non-2xx response and a request the builder refused all resolve to.\n * Its `message` is diagnostic; `PlaceOrder` words the code.\n */\nexport const PAYMENT_GATEWAY_USER_ERROR: PaymentUserError = {\n code: PAYMENT_GATEWAY_ERROR_CODE,\n message: 'Unable to complete the payment. Please try again.',\n};\n\n/**\n * Non-sensitive descriptor of the open transaction. Every field maps to a value the caller already\n * holds — `paymentStartTransaction`'s payload (T3) or the `Payment` read model (T1) — except\n * `gatewayUrl` and `merchantName`, which that payload does not carry today (Gaps 1 and 2 in the spec).\n * Amounts are in the currency's **minor units**; `PaymentStartTransactionPayload.value.amount` is a\n * decimal, so the caller converts once, visibly, rather than having this module assume an exponent.\n */\nexport type PaymentGatewayTransaction = Readonly<{\n /**\n * Gateway origin, e.g. `https://acme.vtexvault.com`. Server-resolved by T18 and read off\n * `paymentStartTransaction`'s payload; never derived here. It is nullable there and required here,\n * so the builder re-checks it (`isTrustedGatewayOrigin`) rather than trusting the type.\n */\n gatewayUrl: string;\n /** `PaymentStartTransactionPayload.transactionId`. */\n transactionId: string;\n /** VTEX merchant name for this transaction. Resolved server-side by T3 but not exposed on its payload. */\n merchantName: string;\n /** `PaymentStartTransactionPayload.orderGroup` — the gateway's `orderId` query parameter. */\n orderGroup: string;\n /** `PaymentStartTransactionPayload.userProfileId`; null for a guest order, so the query parameter is left out. */\n userProfileId: string | null;\n /** `Payment.selectedMethodId` — the VTEX payment-system id. */\n paymentSystem: string;\n /** `PaymentMethod.groupName`, e.g. `creditCardPaymentGroup`. */\n groupName: string;\n /** `PaymentStartTransactionPayload.value.currencyCode`. */\n currencyCode: string;\n /** Transaction total, in minor units. */\n valueInCents: number;\n /** Pre-interest base (`PaymentInstallmentOption.baseValue`), in minor units. */\n referenceValueInCents: number;\n /** `Payment.selectedInstallment.count`; 1 when the shopper never picked a plan. */\n installments: number;\n /** Per-installment amount (`PaymentInstallment.value`), in minor units. */\n installmentsValueInCents: number;\n /** `PaymentInstallment.interestRate`; 0 for the interest-free 1x default. */\n interestRate: number;\n /** Absolute return URL for the 3D Secure challenge. Omitted when the store authored no return page. */\n callbackUrl?: string;\n /**\n * Billing differs from the delivery address. Defaults to `false`, because `setBillingAddress` persists\n * billing on the order form's `invoiceData` (T3) and the gateway reads it from there rather than from\n * this body. The call site that would override it is T13's `usePlaceOrder`, the one place the\n * descriptor is assembled; T11 owns the live verification of the assumption and publishes the flag to\n * T5's `draft` for T13 to read. Confirming it never reopens this module.\n */\n billingAddressDifferent?: boolean;\n}>;\n\n/** A newly entered card. Runtime argument only — never declared, never logged, never cached. */\nexport type PaymentGatewayNewCard = Readonly<{\n kind: 'new';\n /** Full card number. The builder strips whatever separators the method's `numberMask` inserted. */\n number: string;\n /** Security code (CVV). */\n securityCode: string;\n /** Expiry. Normalized to `MM/YY`, so a `MM/YYYY` mask is accepted. */\n expirationDate: string;\n holderName: string;\n /** Shopper document (a CPF). The builder strips its punctuation. */\n document?: string;\n /** Shopper-assigned label, when the save-card control collected one. */\n cardLabel?: string;\n /** The card-save flag itself — the other half of `payment.saveCard`'s consent write (RFC D5). */\n saveCard?: boolean;\n}>;\n\n/** A previously saved card: its account reference plus the CVV the shopper re-enters. */\nexport type PaymentGatewaySavedCard = Readonly<{\n kind: 'saved';\n /** `SavedCard.accountId`. */\n accountId: string;\n /** `SavedCard.bin` — not sensitive; the read model exposes it for installment lookup. */\n bin: string;\n /** Security code (CVV). */\n securityCode: string;\n}>;\n\nexport type PaymentGatewayCard = PaymentGatewayNewCard | PaymentGatewaySavedCard;\n\nexport type SendPaymentsRequest = Readonly<{\n transaction: PaymentGatewayTransaction;\n card: PaymentGatewayCard;\n}>;\n\n/** The assembled request. Exported so the body shape is unit-testable without issuing a POST. */\nexport type GatewayPaymentsRequest = Readonly<{ url: string; body: readonly unknown[] }>;\n\n/** VTEX bins the leading eight digits, not six — the legacy's own `sanitizedBin` slice. */\nconst BIN_LENGTH = 8;\n\n/**\n * Strips the separators a mask inserted. `PaymentMethodValidator.numberMask` is server-driven (T1) and the\n * card-entry component (T7) renders the input through it, so its local state holds `4111 1111 1111 1111`\n * rather than the digits. The legacy normalized here, in the builder, before its own BIN slice\n * (`card.cardNumber = card.cardNumber.replace(/ /g, '')`) — the boundary is the one place the obligation\n * cannot be forgotten, and a spaced BIN is a lookup the gateway fails with no diagnosable error.\n */\nfunction toDigits(value: string): string {\n return value.replace(/\\D/g, '');\n}\n\n/** `MM/YY` whatever the mask produced (`MM/YYYY`, `MMYY`) — the legacy's own two-slice normalization. */\nfunction toDueDate(expirationDate: string): string {\n const digits = toDigits(expirationDate);\n return `${digits.slice(0, 2)}/${digits.slice(-2)}`;\n}\n\n/** The card half of the body — the BIN and the `fields` map, both derived from one normalization pass. */\nfunction toCardBody(card: PaymentGatewayCard): { bin: string; fields: Record<string, unknown> } {\n if (card.kind === 'saved') {\n return { bin: card.bin, fields: { bin: card.bin, validationCode: card.securityCode } };\n }\n\n const number = toDigits(card.number);\n const bin = number.slice(0, BIN_LENGTH);\n\n return {\n bin,\n fields: {\n bin,\n cardNumber: number,\n // The legacy's own `\\W` strip, so a CPF typed `123.456.789-00` reaches the gateway unpunctuated.\n document: card.document === undefined ? null : card.document.replace(/\\W/g, ''),\n dueDate: toDueDate(card.expirationDate),\n holderName: card.holderName,\n validationCode: card.securityCode,\n cardLabel: card.cardLabel,\n savePaymentData: card.saveCard ?? false,\n },\n };\n}\n\n/**\n * Builds the gateway URL and body. Billing is deliberately absent from the body: `setBillingAddress`\n * already persisted it on the order form's `invoiceData` (T3), so the gateway reads it from there — hence\n * the `billingAddressDifferent: false` default the two billing flags derive from. `originalPaymentIndex`\n * is the legacy's own constant for a single-payment order.\n *\n * The origin check is the last line of defence, not the first: `usePlaceOrder` already refuses an\n * untrusted origin *before* asking a holder for the card (T13, Decision 4). A builder has no userError\n * channel, so it throws — `sendPayments` catches, collapses it to `GATEWAY_ERROR`, and logs the error's\n * name only, so nothing about the card reaches a log. The throw happens before the body is assembled.\n */\nexport function buildGatewayPaymentsRequest({ transaction, card }: SendPaymentsRequest): GatewayPaymentsRequest {\n if (!isTrustedGatewayOrigin(transaction.gatewayUrl)) {\n throw new Error('Refusing to post card data: the transaction carries no trusted https gateway origin.');\n }\n\n const params = new URLSearchParams({ orderId: transaction.orderGroup });\n if (transaction.userProfileId !== null) params.append('userProfileId', transaction.userProfileId);\n if (transaction.callbackUrl !== undefined) {\n params.append('callbackUrl', transaction.callbackUrl);\n params.append('redirect', 'false');\n }\n\n const transactionId = encodeURIComponent(transaction.transactionId);\n const url = `${transaction.gatewayUrl}/api/payments/transactions/${transactionId}/payments?${params}`;\n\n const { bin, fields } = toCardBody(card);\n const billingAddressDifferent = transaction.billingAddressDifferent ?? false;\n\n const payment = {\n accountId: card.kind === 'saved' ? card.accountId : null,\n bin,\n chooseToUseNewCard: card.kind === 'new',\n currencyCode: transaction.currencyCode,\n fields,\n groupName: transaction.groupName,\n hasDefaultBillingAddress: !billingAddressDifferent,\n id: transaction.merchantName,\n installmentValue: transaction.installmentsValueInCents,\n installments: transaction.installments,\n installmentsInterestRate: transaction.interestRate,\n installmentsValue: transaction.installmentsValueInCents,\n interestRate: transaction.interestRate,\n isBillingAddressDifferent: billingAddressDifferent,\n originalPaymentIndex: 1,\n paymentSystem: transaction.paymentSystem,\n referenceValue: transaction.referenceValueInCents,\n tokenId: null,\n transaction: { id: transaction.transactionId, merchantName: transaction.merchantName },\n value: transaction.valueInCents,\n };\n\n return { url, body: [payment] };\n}\n\n/**\n * T29 (FR-6, OQ-7): this leg's own abort budget. Before this task the direct-to-gateway POST carried no\n * `AbortSignal` and no timeout at all, so a gateway that never answered left `placing` true and the CTA\n * dead for the life of the mount (Route C, `place-order.md`'s Known limitations). The BFF's own default\n * is 10s (`apps/storefront-api-core/.../api-timeout.ts:9`), but a card authorization can legitimately\n * run longer than a GraphQL round trip, and this exact number is not confirmed with payments (spec\n * OQ-7) — a placeholder pending that answer, not a tuned production value.\n *\n * Exported so `gateway.test.ts`'s own abort-budget test can assert the abort fires at exactly this\n * duration, rather than against `vi.runAllTimersAsync()`, which fires any pending timer regardless of\n * duration and would stay green even if this were edited to `300_000`. That mechanism test alone is\n * still self-referential about this constant's own *value* — it advances the fake clock by whatever\n * `GATEWAY_REQUEST_TIMEOUT_MS` currently holds, so on its own it cannot catch an edit to the constant\n * either (fix round 2, verification finding V2). `gateway.test.ts` also asserts this constant against\n * the literal `30_000` directly, in its own dedicated test — that is what actually fails if this\n * constant's value ever changes.\n */\nexport const GATEWAY_REQUEST_TIMEOUT_MS = 30_000;\n\n/**\n * What a card POST resolves (T112). `reachedGateway` is `false` only when this module can show no request\n * was issued — the request builder refused before any `fetch`. Anything it cannot classify (a rejection, a\n * timeout, an abort, a malformed result) is `true`: a browser cannot tell whether a request that never\n * answered was processed, and a `false` frees the shopper to post the card again. Beside it, `userErrors`\n * keeps the `{ ..., userErrors }` payload shape (ADR-00005); it carries no card value.\n */\nexport type PaymentGatewayResult = Readonly<{\n /** false only when no request was issued to the gateway. Anything unclassified is true. */\n reachedGateway: boolean;\n userErrors: readonly PaymentUserError[];\n}>;\n\n/**\n * Posts the card straight to the gateway and resolves a `PaymentGatewayResult`. A non-2xx response\n * resolves `{ reachedGateway: true, userErrors: [GATEWAY_ERROR] }`; a request the builder refuses\n * (an untrusted origin, a malformed card) resolves `{ reachedGateway: false, userErrors: [GATEWAY_ERROR] }`\n * without issuing a `fetch` or arming a timer, logging only the error's name. A rejected request —\n * including this leg's own timeout firing, or `options.signal` aborting — propagates, and the handler in\n * `use-payment-actions.ts` collapses it to a `reachedGateway: true` result: nothing here can prove it\n * never left. Neither outcome reads the response body: it may echo the request, and it tells the shopper\n * nothing more actionable than \"try again\".\n *\n * `options.signal`, when given, aborts this request in *addition to* — never instead of — this module's\n * own timeout: a caller opts into an earlier or externally triggered abort, but cannot opt out of the\n * budget that keeps this leg from hanging forever (FR-6, US-3). Composed with a plain `AbortController`\n * rather than `AbortSignal.any`/`AbortSignal.timeout` so the timeout is driven by an ordinary\n * `setTimeout`, the one implementation a test can advance deterministically with fake timers.\n *\n * No caller in this package passes `options.signal` today — it exists to satisfy the spec's own\n * Technical Contract (`specs/make-an-order-attempt-survive-a.md`) ahead of a future integration. Fix\n * pass, Low finding: the listener this composes onto `externalSignal` is now removed in the `finally`\n * below on every exit path, not only when it fires — previously, a caller that supplied a long-lived\n * signal (as opposed to a fresh one per call) would accumulate one listener, and this function's own\n * dead `AbortController`, per call that resolved normally.\n */\nexport async function postPaymentsToGateway(\n request: SendPaymentsRequest,\n options?: { signal?: AbortSignal },\n): Promise<PaymentGatewayResult> {\n let built: GatewayPaymentsRequest;\n try {\n built = buildGatewayPaymentsRequest(request);\n } catch (error) {\n // Name only: the builder's message and the request it rejected can carry the card.\n console.error(\n '[payment.sendPayments] the gateway request was refused before it was sent',\n loggableErrorName(error),\n );\n return { reachedGateway: false, userErrors: [PAYMENT_GATEWAY_USER_ERROR] };\n }\n const { url, body } = built;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(\n () => controller.abort(new DOMException('The gateway request timed out.', 'TimeoutError')),\n GATEWAY_REQUEST_TIMEOUT_MS,\n );\n const externalSignal = options?.signal;\n const onExternalAbort = () => controller.abort(externalSignal?.reason);\n if (externalSignal) {\n if (externalSignal.aborted) {\n controller.abort(externalSignal.reason);\n } else {\n externalSignal.addEventListener('abort', onExternalAbort, { once: true });\n }\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n return { reachedGateway: true, userErrors: response.ok ? [] : [PAYMENT_GATEWAY_USER_ERROR] };\n } finally {\n clearTimeout(timeoutId);\n externalSignal?.removeEventListener('abort', onExternalAbort);\n }\n}\n"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import "../generated/graphql.js";
1
2
  import "../cart/operations.js";
2
3
  import { TypedDocumentNode } from "@apollo/client";
3
4
  //#region src/sdk/payment/operations.d.ts
@@ -40,11 +40,12 @@ const PaymentFragment = gql`
40
40
  amount
41
41
  currencyCode
42
42
  }
43
- total {
43
+ totalAmount {
44
44
  amount
45
45
  currencyCode
46
46
  }
47
47
  interestRate
48
+ interestFree
48
49
  }
49
50
  installmentOptions {
50
51
  __typename
@@ -61,17 +62,19 @@ const PaymentFragment = gql`
61
62
  amount
62
63
  currencyCode
63
64
  }
64
- total {
65
+ totalAmount {
65
66
  amount
66
67
  currencyCode
67
68
  }
68
69
  interestRate
70
+ interestFree
69
71
  }
70
72
  }
71
73
  methods {
72
74
  __typename
73
75
  id
74
76
  name
77
+ type
75
78
  groupName
76
79
  validator {
77
80
  __typename
@@ -137,9 +140,11 @@ const PAYMENT_METHOD_SELECT = gql`
137
140
  ${PaymentBillingAddressFragment}
138
141
  `;
139
142
  /**
140
- * Selects `cart { ...CartFragment }` alongside `payment` so the interest-inclusive order total lands
141
- * in the normalized cache in the same round trip (REQ-03) — the same reason `shippingOptionSelect`
142
- * selects the cart.
143
+ * Selects `cart { ...CartFragment }` alongside `payment` so the cart total the server returns lands in
144
+ * the normalized cache in the same round trip (REQ-03) — the same reason `shippingOptionSelect`
145
+ * selects the cart. That total is the server's: the greater of the order form's value and the selected
146
+ * payment's value (`mapOrderFormToGqlCart`), so it carries the picked tier's interest. Dropping `total`
147
+ * from the selection leaves the total on screen at its previous value.
143
148
  */
144
149
  const PAYMENT_INSTALLMENT_SELECT = gql`
145
150
  mutation PaymentInstallmentSelect($input: PaymentInstallmentSelectInput!) {
@@ -202,6 +207,7 @@ const PAYMENT_START_TRANSACTION = gql`
202
207
  merchantName
203
208
  gatewayUrl
204
209
  orderGroup
210
+ orderNodeId
205
211
  userProfileId
206
212
  value {
207
213
  amount
@@ -221,6 +227,8 @@ const PAYMENT_GATEWAY_CALLBACK = gql`
221
227
  paymentGatewayCallback(input: $input) {
222
228
  __typename
223
229
  orderId
230
+ orderNodeId
231
+ redirectUrl
224
232
  userErrors {
225
233
  code
226
234
  message
@@ -228,7 +236,21 @@ const PAYMENT_GATEWAY_CALLBACK = gql`
228
236
  }
229
237
  }
230
238
  `;
239
+ /** Only what `emitPurchaseForOrder` needs: the order's reference, its status, and what it costs. */
240
+ const SETTLED_ORDER_FACTS = gql`
241
+ query SettledOrderFacts($id: ID!) {
242
+ order(id: $id) {
243
+ id
244
+ reference
245
+ status
246
+ total {
247
+ amount
248
+ currencyCode
249
+ }
250
+ }
251
+ }
252
+ `;
231
253
  //#endregion
232
- export { PAYMENT_BILLING_ADDRESS_UPDATE, PAYMENT_GATEWAY_CALLBACK, PAYMENT_INSTALLMENT_SELECT, PAYMENT_METHOD_SELECT, PAYMENT_NETWORK_ERROR_CODE, PAYMENT_START_TRANSACTION, PaymentBillingAddressFragment, PaymentFragment };
254
+ export { PAYMENT_BILLING_ADDRESS_UPDATE, PAYMENT_GATEWAY_CALLBACK, PAYMENT_INSTALLMENT_SELECT, PAYMENT_METHOD_SELECT, PAYMENT_NETWORK_ERROR_CODE, PAYMENT_START_TRANSACTION, PaymentBillingAddressFragment, PaymentFragment, SETTLED_ORDER_FACTS };
233
255
 
234
256
  //# sourceMappingURL=operations.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"operations.js","names":[],"sources":["../../../src/sdk/payment/operations.ts"],"sourcesContent":["import type { TypedDocumentNode } from '@apollo/client';\nimport { type CartEntity, CartFragment } from '../cart/operations.js';\nimport { gql } from '../graphql-tag.js';\n\n/**\n * Payment write-model GraphQL operations (specs/payment-action-namespace.md, T4) — the five mutations\n * `api-module:PaymentWriteModel` shipped (T3, `checkout/schema.graphql` § 11). Nothing here is\n * invented: every mutation, input field, and payload field is pinned to that schema.\n *\n * Authored with the hand `gql` tag — the codegen `graphql()` factory is reserved for the reactive read\n * path — and excluded from the codegen `documents` glob (see `codegen.ts`): the `gql` tag alone is\n * still plucked by `graphql-codegen`, which would duplicate these hand-written types in\n * `sdk/generated/`. Mirrors `shipping/option-select-operations.ts` and `identity/operations.ts`.\n *\n * No field at any nesting depth carries a card number or CVV — the read model guarantees it (RFC D13),\n * and the one call that does carry them never touches GraphQL at all (see `gateway.ts`).\n *\n * Failures follow ADR-00007's two-path contract: domain outcomes arrive as payload `userErrors`;\n * transport and top-level GraphQL failures are infrastructure, collapsed by the handlers in\n * `use-payment-actions.ts` to the one client-synthesized code, `PAYMENT_NETWORK_ERROR_CODE`.\n */\n\n// ---------------------------------------------------------------------------\n// Domain types — mirror the shipped checkout schema\n// ---------------------------------------------------------------------------\n\n/** A payment domain error. Every mutation's error type is `{ code, message }`; codes stay strings. */\nexport type PaymentUserError = Readonly<{ code: string; message: string }>;\n\n/**\n * The one client-synthesized error code, carried by the userError every mutation-backed method\n * *resolves* (never throws) when its mutation fails at the transport or top-level-GraphQL layer.\n * `gateway.ts` owns the separate code for a failed gateway leg (Decision 7).\n */\nexport const PAYMENT_NETWORK_ERROR_CODE = 'NETWORK_ERROR';\n\nexport type PaymentMoney = Readonly<{ __typename?: 'Money'; amount: number; currencyCode: string }>;\n\ntype PaymentInstallmentEntity = Readonly<{\n __typename?: 'PaymentInstallment';\n count: number;\n value: PaymentMoney;\n total: PaymentMoney;\n interestRate: number;\n}>;\n\ntype PaymentMethodValidatorEntity = Readonly<{\n __typename?: 'PaymentMethodValidator';\n numberMask: string | null;\n numberRegex: string | null;\n cvvMask: string | null;\n cvvRegex: string | null;\n cvvRequired: boolean;\n expirationRequired: boolean;\n holderNameRequired: boolean;\n billingAddressRequired: boolean;\n documentDisplayable: boolean;\n documentRequired: boolean;\n}>;\n\ntype PaymentCountryDocumentEntity = Readonly<{\n __typename?: 'PaymentCountryDocument';\n type: string;\n displayable: boolean;\n required: boolean;\n}>;\n\ntype PaymentCountryEntity = Readonly<{\n __typename?: 'PaymentCountry';\n countryCode: string;\n documents: readonly PaymentCountryDocumentEntity[];\n}>;\n\ntype PaymentMethodEntity = Readonly<{\n __typename?: 'PaymentMethod';\n id: string;\n name: string;\n groupName: string;\n validator: PaymentMethodValidatorEntity;\n}>;\n\ntype PaymentInstallmentOptionEntity = Readonly<{\n __typename?: 'PaymentInstallmentOption';\n methodId: string;\n bin: string | null;\n baseValue: PaymentMoney;\n installments: readonly PaymentInstallmentEntity[];\n}>;\n\ntype SavedCardEntity = Readonly<{\n __typename?: 'SavedCard';\n id: string;\n accountId: string;\n methodId: string;\n network: string;\n lastFourDigits: string;\n bin: string;\n label: string | null;\n expired: boolean;\n cvvRequired: boolean;\n}>;\n\n/** The full `Payment` entity every selection mutation echoes back. Never carries a PAN or CVV. */\nexport type PaymentEntity = Readonly<{\n __typename?: 'Payment';\n id: string;\n methods: readonly PaymentMethodEntity[];\n selectedMethodId: string | null;\n selectedAccountId: string | null;\n selectedBin: string | null;\n storeCountryCode: string | null;\n countries: readonly PaymentCountryEntity[];\n selectedInstallment: PaymentInstallmentEntity | null;\n installmentOptions: readonly PaymentInstallmentOptionEntity[];\n savedCards: readonly SavedCardEntity[];\n}>;\n\n/** The billing-address echo on the selection payloads — the schema's shared `Address` type. */\nexport type PaymentBillingAddressEntity = Readonly<{\n __typename?: 'Address';\n id: string | null;\n recipientName: string | null;\n postalCode: string | null;\n country: string;\n street: string | null;\n number: string | null;\n complement: string | null;\n neighborhood: string | null;\n city: string | null;\n state: string | null;\n}>;\n\n// ---------------------------------------------------------------------------\n// Mutation inputs — mirror the schema's input types verbatim\n// ---------------------------------------------------------------------------\n\n/** A `bin` with an `accountId` is validated against the saved card's own BIN (MISMATCHED_BIN_FOR_SAVED_CARD). */\nexport type PaymentMethodSelectInput = Readonly<{ methodId: string; bin?: string; accountId?: string }>;\n\nexport type PaymentInstallmentSelectInput = Readonly<{ count: number }>;\n\n/** With `sameAsDelivery: true` every other field is ignored and the server performs no upstream write. */\nexport type PaymentBillingAddressUpdateInput = Readonly<{\n sameAsDelivery: boolean;\n addressType?: string;\n postalCode?: string;\n country?: string;\n street?: string;\n number?: string;\n complement?: string;\n neighborhood?: string;\n city?: string;\n state?: string;\n reference?: string;\n}>;\n\nexport type PaymentGatewayCallbackInput = Readonly<{ orderGroup: string }>;\n\n// ---------------------------------------------------------------------------\n// Shared fragment\n// ---------------------------------------------------------------------------\n\n/**\n * The canonical `Payment` selection set, spread by every selection mutation so one response\n * re-normalizes the whole entity and every reactive subscriber re-renders with no refetch — the\n * payload-completeness invariant writes must honor (ADR-0010). Selecting the entire entity mirrors\n * `CartFragment` and `SHIPPING_ADDRESS_UPDATE`'s full-`Shipping` selection: the method list (T5), the\n * validator config (T7), `installmentOptions` (T9), and the summary's selection fields (T6) are all\n * subscribed independently, and a partial selection would leave one of them incomplete.\n */\nexport const PaymentFragment = gql`\n fragment PaymentFragment on Payment {\n __typename\n id\n selectedMethodId\n selectedAccountId\n selectedBin\n storeCountryCode\n countries {\n __typename\n countryCode\n documents {\n __typename\n type\n displayable\n required\n }\n }\n selectedInstallment {\n __typename\n count\n value {\n amount\n currencyCode\n }\n total {\n amount\n currencyCode\n }\n interestRate\n }\n installmentOptions {\n __typename\n methodId\n bin\n baseValue {\n amount\n currencyCode\n }\n installments {\n __typename\n count\n value {\n amount\n currencyCode\n }\n total {\n amount\n currencyCode\n }\n interestRate\n }\n }\n methods {\n __typename\n id\n name\n groupName\n validator {\n __typename\n numberMask\n numberRegex\n cvvMask\n cvvRegex\n cvvRequired\n expirationRequired\n holderNameRequired\n billingAddressRequired\n documentDisplayable\n documentRequired\n }\n }\n savedCards {\n __typename\n id\n accountId\n methodId\n network\n lastFourDigits\n bin\n label\n expired\n cvvRequired\n }\n }\n`;\n\n/** The billing-address echo, spread by the three selection mutations that return one. */\nexport const PaymentBillingAddressFragment = gql`\n fragment PaymentBillingAddressFragment on Address {\n __typename\n id\n recipientName\n postalCode\n country\n street\n number\n complement\n neighborhood\n city\n state\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Mutation operations\n// ---------------------------------------------------------------------------\n\ntype PaymentMethodSelectMutation = Readonly<{\n paymentMethodSelect: Readonly<{\n __typename?: 'PaymentMethodSelectPayload';\n payment: PaymentEntity | null;\n billingAddress: PaymentBillingAddressEntity | null;\n userErrors: readonly PaymentUserError[];\n }>;\n}>;\n\nexport const PAYMENT_METHOD_SELECT: TypedDocumentNode<\n PaymentMethodSelectMutation,\n Readonly<{ input: PaymentMethodSelectInput }>\n> = gql`\n mutation PaymentMethodSelect($input: PaymentMethodSelectInput!) {\n paymentMethodSelect(input: $input) {\n __typename\n payment {\n ...PaymentFragment\n }\n billingAddress {\n ...PaymentBillingAddressFragment\n }\n userErrors {\n code\n message\n }\n }\n }\n ${PaymentFragment}\n ${PaymentBillingAddressFragment}\n`;\n\ntype PaymentInstallmentSelectMutation = Readonly<{\n paymentInstallmentSelect: Readonly<{\n __typename?: 'PaymentInstallmentSelectPayload';\n payment: PaymentEntity | null;\n cart: CartEntity | null;\n billingAddress: PaymentBillingAddressEntity | null;\n userErrors: readonly PaymentUserError[];\n }>;\n}>;\n\n/**\n * Selects `cart { ...CartFragment }` alongside `payment` so the interest-inclusive order total lands\n * in the normalized cache in the same round trip (REQ-03) — the same reason `shippingOptionSelect`\n * selects the cart.\n */\nexport const PAYMENT_INSTALLMENT_SELECT: TypedDocumentNode<\n PaymentInstallmentSelectMutation,\n Readonly<{ input: PaymentInstallmentSelectInput }>\n> = gql`\n mutation PaymentInstallmentSelect($input: PaymentInstallmentSelectInput!) {\n paymentInstallmentSelect(input: $input) {\n __typename\n payment {\n ...PaymentFragment\n }\n cart {\n ...CartFragment\n }\n billingAddress {\n ...PaymentBillingAddressFragment\n }\n userErrors {\n code\n message\n }\n }\n }\n ${PaymentFragment}\n ${PaymentBillingAddressFragment}\n ${CartFragment}\n`;\n\ntype PaymentBillingAddressUpdateMutation = Readonly<{\n paymentBillingAddressUpdate: Readonly<{\n __typename?: 'PaymentBillingAddressUpdatePayload';\n billingAddress: PaymentBillingAddressEntity | null;\n payment: PaymentEntity | null;\n userErrors: readonly PaymentUserError[];\n }>;\n}>;\n\nexport const PAYMENT_BILLING_ADDRESS_UPDATE: TypedDocumentNode<\n PaymentBillingAddressUpdateMutation,\n Readonly<{ input: PaymentBillingAddressUpdateInput }>\n> = gql`\n mutation PaymentBillingAddressUpdate($input: PaymentBillingAddressUpdateInput!) {\n paymentBillingAddressUpdate(input: $input) {\n __typename\n billingAddress {\n ...PaymentBillingAddressFragment\n }\n payment {\n ...PaymentFragment\n }\n userErrors {\n code\n message\n }\n }\n }\n ${PaymentFragment}\n ${PaymentBillingAddressFragment}\n`;\n\ntype PaymentStartTransactionMutation = Readonly<{\n paymentStartTransaction: Readonly<{\n __typename?: 'PaymentStartTransactionPayload';\n transactionId: string | null;\n merchantName: string | null;\n gatewayUrl: string | null;\n orderGroup: string | null;\n userProfileId: string | null;\n value: PaymentMoney | null;\n valueInCents: number | null;\n referenceValueInCents: number | null;\n userErrors: readonly PaymentUserError[];\n }>;\n}>;\n\n/**\n * Takes no input: every field VTEX's transaction endpoint needs is derived server-side from the\n * already-persisted selection (T3 Decision 9). The transaction cookies it mints ride on the HTTP\n * response, not on the payload.\n *\n * `merchantName`, `gatewayUrl`, `valueInCents`, and `referenceValueInCents` are T18's additions\n * (specs/payment-transaction-payload-gaps.md), selected here by T13: `PaymentGatewayTransaction`\n * requires all four, so the descriptor cannot be assembled without them. `value` stays selected\n * beside the minor-unit pair — it is the display decimal, and the `purchase` analytics event reports\n * it rather than a client-side division.\n */\nexport const PAYMENT_START_TRANSACTION: TypedDocumentNode<PaymentStartTransactionMutation, Record<string, never>> = gql`\n mutation PaymentStartTransaction {\n paymentStartTransaction {\n __typename\n transactionId\n merchantName\n gatewayUrl\n orderGroup\n userProfileId\n value {\n amount\n currencyCode\n }\n valueInCents\n referenceValueInCents\n userErrors {\n code\n message\n }\n }\n }\n`;\n\ntype PaymentGatewayCallbackMutation = Readonly<{\n paymentGatewayCallback: Readonly<{\n __typename?: 'PaymentGatewayCallbackPayload';\n orderId: string | null;\n userErrors: readonly PaymentUserError[];\n }>;\n}>;\n\nexport const PAYMENT_GATEWAY_CALLBACK: TypedDocumentNode<\n PaymentGatewayCallbackMutation,\n Readonly<{ input: PaymentGatewayCallbackInput }>\n> = gql`\n mutation PaymentGatewayCallback($input: PaymentGatewayCallbackInput!) {\n paymentGatewayCallback(input: $input) {\n __typename\n orderId\n userErrors {\n code\n message\n }\n }\n }\n`;\n"],"mappings":";;;;;;;;AAkCA,MAAa,6BAA6B;;;;;;;;;AAwI1C,MAAa,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwFlC,MAAa,gCAAgC,GAAG;;;;;;;;;;;;;;;AA6BhD,MAAa,wBAGT,GAAG;;;;;;;;;;;;;;;;IAgBH,gBAAgB;IAChB,8BAA8B;;;;;;;AAkBlC,MAAa,6BAGT,GAAG;;;;;;;;;;;;;;;;;;;IAmBH,gBAAgB;IAChB,8BAA8B;IAC9B,aAAa;;AAYjB,MAAa,iCAGT,GAAG;;;;;;;;;;;;;;;;IAgBH,gBAAgB;IAChB,8BAA8B;;;;;;;;;;;;;AA6BlC,MAAa,4BAAuG,GAAG;;;;;;;;;;;;;;;;;;;;;;AA+BvH,MAAa,2BAGT,GAAG"}
1
+ {"version":3,"file":"operations.js","names":[],"sources":["../../../src/sdk/payment/operations.ts"],"sourcesContent":["import type { TypedDocumentNode } from '@apollo/client';\nimport { type CartEntity, CartFragment } from '../cart/operations.js';\nimport type { PaymentType } from '../generated/graphql.js';\nimport { gql } from '../graphql-tag.js';\n\n/**\n * Payment write-model GraphQL operations (specs/payment-action-namespace.md, T4) — the five mutations\n * `api-module:PaymentWriteModel` shipped (T3, `checkout/schema.graphql` § 11). Nothing here is\n * invented: every mutation, input field, and payload field is pinned to that schema.\n *\n * Authored with the hand `gql` tag — the codegen `graphql()` factory is reserved for the reactive read\n * path — and excluded from the codegen `documents` glob (see `codegen.ts`): the `gql` tag alone is\n * still plucked by `graphql-codegen`, which would duplicate these hand-written types in\n * `sdk/generated/`. Mirrors `shipping/option-select-operations.ts` and `identity/operations.ts`.\n *\n * No field at any nesting depth carries a card number or CVV — the read model guarantees it (RFC D13),\n * and the one call that does carry them never touches GraphQL at all (see `gateway.ts`).\n *\n * Failures follow ADR-00007's two-path contract: domain outcomes arrive as payload `userErrors`;\n * transport and top-level GraphQL failures are infrastructure, collapsed by the handlers in\n * `use-payment-actions.ts` to the one client-synthesized code, `PAYMENT_NETWORK_ERROR_CODE`.\n */\n\n// ---------------------------------------------------------------------------\n// Domain types — mirror the shipped checkout schema\n// ---------------------------------------------------------------------------\n\n/** A payment domain error. Every mutation's error type is `{ code, message }`; codes stay strings. */\nexport type PaymentUserError = Readonly<{ code: string; message: string }>;\n\n/**\n * The one client-synthesized error code, carried by the userError every mutation-backed method\n * *resolves* (never throws) when its mutation fails at the transport or top-level-GraphQL layer.\n * `gateway.ts` owns the separate code for a failed gateway leg (Decision 7).\n */\nexport const PAYMENT_NETWORK_ERROR_CODE = 'NETWORK_ERROR';\n\nexport type PaymentMoney = Readonly<{ __typename?: 'Money'; amount: number; currencyCode: string }>;\n\ntype PaymentInstallmentEntity = Readonly<{\n __typename?: 'PaymentInstallment';\n count: number;\n value: PaymentMoney;\n /** The whole-plan amount, interest included. */\n totalAmount: PaymentMoney;\n /** Hundredths of a percent. `null` when the order form did not say what the rate is. */\n interestRate: number | null;\n /** `null` exactly when `interestRate` is `null`. */\n interestFree: boolean | null;\n}>;\n\ntype PaymentMethodValidatorEntity = Readonly<{\n __typename?: 'PaymentMethodValidator';\n numberMask: string | null;\n numberRegex: string | null;\n cvvMask: string | null;\n cvvRegex: string | null;\n cvvRequired: boolean;\n expirationRequired: boolean;\n holderNameRequired: boolean;\n billingAddressRequired: boolean;\n documentDisplayable: boolean;\n documentRequired: boolean;\n}>;\n\ntype PaymentCountryDocumentEntity = Readonly<{\n __typename?: 'PaymentCountryDocument';\n type: string;\n displayable: boolean;\n required: boolean;\n}>;\n\ntype PaymentCountryEntity = Readonly<{\n __typename?: 'PaymentCountry';\n countryCode: string;\n documents: readonly PaymentCountryDocumentEntity[];\n}>;\n\ntype PaymentMethodEntity = Readonly<{\n __typename?: 'PaymentMethod';\n id: string;\n name: string;\n /** The vendor-neutral kind. Classify a method with this; `groupName` is the gateway transport value. */\n type: PaymentType;\n groupName: string;\n validator: PaymentMethodValidatorEntity;\n}>;\n\ntype PaymentInstallmentOptionEntity = Readonly<{\n __typename?: 'PaymentInstallmentOption';\n methodId: string;\n bin: string | null;\n baseValue: PaymentMoney;\n installments: readonly PaymentInstallmentEntity[];\n}>;\n\ntype SavedCardEntity = Readonly<{\n __typename?: 'SavedCard';\n id: string;\n accountId: string;\n methodId: string;\n network: string;\n lastFourDigits: string;\n bin: string;\n label: string | null;\n expired: boolean;\n cvvRequired: boolean;\n}>;\n\n/** The full `Payment` entity every selection mutation echoes back. Never carries a PAN or CVV. */\nexport type PaymentEntity = Readonly<{\n __typename?: 'Payment';\n id: string;\n methods: readonly PaymentMethodEntity[];\n selectedMethodId: string | null;\n selectedAccountId: string | null;\n selectedBin: string | null;\n storeCountryCode: string | null;\n countries: readonly PaymentCountryEntity[];\n selectedInstallment: PaymentInstallmentEntity | null;\n installmentOptions: readonly PaymentInstallmentOptionEntity[];\n savedCards: readonly SavedCardEntity[];\n}>;\n\n/** The billing-address echo on the selection payloads — the schema's shared `Address` type. */\nexport type PaymentBillingAddressEntity = Readonly<{\n __typename?: 'Address';\n id: string | null;\n recipientName: string | null;\n postalCode: string | null;\n country: string;\n street: string | null;\n number: string | null;\n complement: string | null;\n neighborhood: string | null;\n city: string | null;\n state: string | null;\n}>;\n\n// ---------------------------------------------------------------------------\n// Mutation inputs — mirror the schema's input types verbatim\n// ---------------------------------------------------------------------------\n\n/** A `bin` with an `accountId` is validated against the saved card's own BIN (MISMATCHED_BIN_FOR_SAVED_CARD). */\nexport type PaymentMethodSelectInput = Readonly<{ methodId: string; bin?: string; accountId?: string }>;\n\nexport type PaymentInstallmentSelectInput = Readonly<{ count: number }>;\n\n/** With `sameAsDelivery: true` every other field is ignored and the server performs no upstream write. */\nexport type PaymentBillingAddressUpdateInput = Readonly<{\n sameAsDelivery: boolean;\n addressType?: string;\n postalCode?: string;\n country?: string;\n street?: string;\n number?: string;\n complement?: string;\n neighborhood?: string;\n city?: string;\n state?: string;\n reference?: string;\n}>;\n\nexport type PaymentGatewayCallbackInput = Readonly<{ orderGroup: string; acceptChallenges?: boolean }>;\n\n// ---------------------------------------------------------------------------\n// Shared fragment\n// ---------------------------------------------------------------------------\n\n/**\n * The canonical `Payment` selection set, spread by every selection mutation so one response\n * re-normalizes the whole entity and every reactive subscriber re-renders with no refetch — the\n * payload-completeness invariant writes must honor (ADR-0010). Selecting the entire entity mirrors\n * `CartFragment` and `SHIPPING_ADDRESS_UPDATE`'s full-`Shipping` selection: the method list (T5), the\n * validator config (T7), `installmentOptions` (T9), and the summary's selection fields (T6) are all\n * subscribed independently, and a partial selection would leave one of them incomplete.\n */\nexport const PaymentFragment = gql`\n fragment PaymentFragment on Payment {\n __typename\n id\n selectedMethodId\n selectedAccountId\n selectedBin\n storeCountryCode\n countries {\n __typename\n countryCode\n documents {\n __typename\n type\n displayable\n required\n }\n }\n selectedInstallment {\n __typename\n count\n value {\n amount\n currencyCode\n }\n totalAmount {\n amount\n currencyCode\n }\n interestRate\n interestFree\n }\n installmentOptions {\n __typename\n methodId\n bin\n baseValue {\n amount\n currencyCode\n }\n installments {\n __typename\n count\n value {\n amount\n currencyCode\n }\n totalAmount {\n amount\n currencyCode\n }\n interestRate\n interestFree\n }\n }\n methods {\n __typename\n id\n name\n type\n groupName\n validator {\n __typename\n numberMask\n numberRegex\n cvvMask\n cvvRegex\n cvvRequired\n expirationRequired\n holderNameRequired\n billingAddressRequired\n documentDisplayable\n documentRequired\n }\n }\n savedCards {\n __typename\n id\n accountId\n methodId\n network\n lastFourDigits\n bin\n label\n expired\n cvvRequired\n }\n }\n`;\n\n/** The billing-address echo, spread by the three selection mutations that return one. */\nexport const PaymentBillingAddressFragment = gql`\n fragment PaymentBillingAddressFragment on Address {\n __typename\n id\n recipientName\n postalCode\n country\n street\n number\n complement\n neighborhood\n city\n state\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Mutation operations\n// ---------------------------------------------------------------------------\n\ntype PaymentMethodSelectMutation = Readonly<{\n paymentMethodSelect: Readonly<{\n __typename?: 'PaymentMethodSelectPayload';\n payment: PaymentEntity | null;\n billingAddress: PaymentBillingAddressEntity | null;\n userErrors: readonly PaymentUserError[];\n }>;\n}>;\n\nexport const PAYMENT_METHOD_SELECT: TypedDocumentNode<\n PaymentMethodSelectMutation,\n Readonly<{ input: PaymentMethodSelectInput }>\n> = gql`\n mutation PaymentMethodSelect($input: PaymentMethodSelectInput!) {\n paymentMethodSelect(input: $input) {\n __typename\n payment {\n ...PaymentFragment\n }\n billingAddress {\n ...PaymentBillingAddressFragment\n }\n userErrors {\n code\n message\n }\n }\n }\n ${PaymentFragment}\n ${PaymentBillingAddressFragment}\n`;\n\ntype PaymentInstallmentSelectMutation = Readonly<{\n paymentInstallmentSelect: Readonly<{\n __typename?: 'PaymentInstallmentSelectPayload';\n payment: PaymentEntity | null;\n cart: CartEntity | null;\n billingAddress: PaymentBillingAddressEntity | null;\n userErrors: readonly PaymentUserError[];\n }>;\n}>;\n\n/**\n * Selects `cart { ...CartFragment }` alongside `payment` so the cart total the server returns lands in\n * the normalized cache in the same round trip (REQ-03) — the same reason `shippingOptionSelect`\n * selects the cart. That total is the server's: the greater of the order form's value and the selected\n * payment's value (`mapOrderFormToGqlCart`), so it carries the picked tier's interest. Dropping `total`\n * from the selection leaves the total on screen at its previous value.\n */\nexport const PAYMENT_INSTALLMENT_SELECT: TypedDocumentNode<\n PaymentInstallmentSelectMutation,\n Readonly<{ input: PaymentInstallmentSelectInput }>\n> = gql`\n mutation PaymentInstallmentSelect($input: PaymentInstallmentSelectInput!) {\n paymentInstallmentSelect(input: $input) {\n __typename\n payment {\n ...PaymentFragment\n }\n cart {\n ...CartFragment\n }\n billingAddress {\n ...PaymentBillingAddressFragment\n }\n userErrors {\n code\n message\n }\n }\n }\n ${PaymentFragment}\n ${PaymentBillingAddressFragment}\n ${CartFragment}\n`;\n\ntype PaymentBillingAddressUpdateMutation = Readonly<{\n paymentBillingAddressUpdate: Readonly<{\n __typename?: 'PaymentBillingAddressUpdatePayload';\n billingAddress: PaymentBillingAddressEntity | null;\n payment: PaymentEntity | null;\n userErrors: readonly PaymentUserError[];\n }>;\n}>;\n\nexport const PAYMENT_BILLING_ADDRESS_UPDATE: TypedDocumentNode<\n PaymentBillingAddressUpdateMutation,\n Readonly<{ input: PaymentBillingAddressUpdateInput }>\n> = gql`\n mutation PaymentBillingAddressUpdate($input: PaymentBillingAddressUpdateInput!) {\n paymentBillingAddressUpdate(input: $input) {\n __typename\n billingAddress {\n ...PaymentBillingAddressFragment\n }\n payment {\n ...PaymentFragment\n }\n userErrors {\n code\n message\n }\n }\n }\n ${PaymentFragment}\n ${PaymentBillingAddressFragment}\n`;\n\ntype PaymentStartTransactionMutation = Readonly<{\n paymentStartTransaction: Readonly<{\n __typename?: 'PaymentStartTransactionPayload';\n transactionId: string | null;\n merchantName: string | null;\n gatewayUrl: string | null;\n orderGroup: string | null;\n orderNodeId: string | null;\n userProfileId: string | null;\n value: PaymentMoney | null;\n valueInCents: number | null;\n referenceValueInCents: number | null;\n userErrors: readonly PaymentUserError[];\n }>;\n}>;\n\n/**\n * Takes no input: every field VTEX's transaction endpoint needs is derived server-side from the\n * already-persisted selection (T3 Decision 9). The transaction cookies it mints ride on the HTTP\n * response, not on the payload.\n *\n * `merchantName`, `gatewayUrl`, `valueInCents`, and `referenceValueInCents` are T18's additions\n * (specs/payment-transaction-payload-gaps.md), selected here by T13: `PaymentGatewayTransaction`\n * requires all four, so the descriptor cannot be assembled without them. `value` stays selected\n * beside the minor-unit pair — it is the display decimal, and the `purchase` analytics event reports\n * it rather than a client-side division.\n */\nexport const PAYMENT_START_TRANSACTION: TypedDocumentNode<PaymentStartTransactionMutation, Record<string, never>> = gql`\n mutation PaymentStartTransaction {\n paymentStartTransaction {\n __typename\n transactionId\n merchantName\n gatewayUrl\n orderGroup\n orderNodeId\n userProfileId\n value {\n amount\n currencyCode\n }\n valueInCents\n referenceValueInCents\n userErrors {\n code\n message\n }\n }\n }\n`;\n\ntype PaymentGatewayCallbackMutation = Readonly<{\n paymentGatewayCallback: Readonly<{\n __typename?: 'PaymentGatewayCallbackPayload';\n orderId: string | null;\n orderNodeId: string | null;\n redirectUrl: string | null;\n userErrors: readonly PaymentUserError[];\n }>;\n}>;\n\nexport const PAYMENT_GATEWAY_CALLBACK: TypedDocumentNode<\n PaymentGatewayCallbackMutation,\n Readonly<{ input: PaymentGatewayCallbackInput }>\n> = gql`\n mutation PaymentGatewayCallback($input: PaymentGatewayCallbackInput!) {\n paymentGatewayCallback(input: $input) {\n __typename\n orderId\n orderNodeId\n redirectUrl\n userErrors {\n code\n message\n }\n }\n }\n`;\n\n// ---------------------------------------------------------------------------\n// The settled-order read the resume paths report a purchase from (T208)\n// ---------------------------------------------------------------------------\n\ntype SettledOrderQuery = Readonly<{\n order: Readonly<{\n __typename?: 'Order';\n id: string;\n reference: string;\n status: 'APPROVED' | 'PENDING' | 'DENIED' | 'UNKNOWN';\n total: Readonly<{ __typename?: 'Money'; amount: string; currencyCode: string }> | null;\n }> | null;\n}>;\n\n/** Only what `emitPurchaseForOrder` needs: the order's reference, its status, and what it costs. */\nexport const SETTLED_ORDER_FACTS: TypedDocumentNode<SettledOrderQuery, Readonly<{ id: string }>> = gql`\n query SettledOrderFacts($id: ID!) {\n order(id: $id) {\n id\n reference\n status\n total {\n amount\n currencyCode\n }\n }\n }\n`;\n"],"mappings":";;;;;;;;AAmCA,MAAa,6BAA6B;;;;;;;;;AA8I1C,MAAa,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2FlC,MAAa,gCAAgC,GAAG;;;;;;;;;;;;;;;AA6BhD,MAAa,wBAGT,GAAG;;;;;;;;;;;;;;;;IAgBH,gBAAgB;IAChB,8BAA8B;;;;;;;;;AAoBlC,MAAa,6BAGT,GAAG;;;;;;;;;;;;;;;;;;;IAmBH,gBAAgB;IAChB,8BAA8B;IAC9B,aAAa;;AAYjB,MAAa,iCAGT,GAAG;;;;;;;;;;;;;;;;IAgBH,gBAAgB;IAChB,8BAA8B;;;;;;;;;;;;;AA8BlC,MAAa,4BAAuG,GAAG;;;;;;;;;;;;;;;;;;;;;;;AAkCvH,MAAa,2BAGT,GAAG;;;;;;;;;;;;;;;AA8BP,MAAa,sBAAsF,GAAG"}
@@ -0,0 +1 @@
1
+ import "../analytics/use-analytics-actions.js";