@vtex/faststore 0.0.4 → 0.0.6

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 (306) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/dist/actions.json +181 -0
  3. package/dist/catalog.json +1595 -481
  4. package/dist/client.d.ts +2 -1
  5. package/dist/client.js +2 -1
  6. package/dist/components.d.ts +31 -7
  7. package/dist/components.js +35 -13
  8. package/dist/content-types.json +73 -0
  9. package/dist/docs/access-code-sign-in.md +1 -1
  10. package/dist/docs/account-access-gate.md +153 -0
  11. package/dist/docs/account-entry-point.md +1 -2
  12. package/dist/docs/account-menu.md +164 -0
  13. package/dist/docs/address-summary.md +24 -3
  14. package/dist/docs/alert-dialog.md +204 -0
  15. package/dist/docs/billing-address.md +284 -0
  16. package/dist/docs/buy-button.md +1 -1
  17. package/dist/docs/card-entry.md +250 -0
  18. package/dist/docs/cardholder-document.md +142 -0
  19. package/dist/docs/cart.md +1 -1
  20. package/dist/docs/client-preferences-fieldset.md +148 -0
  21. package/dist/docs/client-preferences.md +2 -1
  22. package/dist/docs/client-profile-fieldset.md +184 -0
  23. package/dist/docs/client-profile.md +1 -1
  24. package/dist/docs/document-field.md +58 -4
  25. package/dist/docs/field.md +317 -0
  26. package/dist/docs/form.md +307 -0
  27. package/dist/docs/identity-edit.md +6 -6
  28. package/dist/docs/identity-summary.md +5 -5
  29. package/dist/docs/installments.md +248 -0
  30. package/dist/docs/my-account-profile.md +1 -0
  31. package/dist/docs/order-placed-payment-summary.md +138 -0
  32. package/dist/docs/payment-method-badges.md +232 -0
  33. package/dist/docs/payment-methods.md +1 -0
  34. package/dist/docs/payment.md +218 -0
  35. package/dist/docs/phone-field.md +58 -4
  36. package/dist/docs/place-order.md +157 -0
  37. package/dist/docs/save-card.md +186 -0
  38. package/dist/docs/saved-cards.md +218 -0
  39. package/dist/docs/select.md +465 -0
  40. package/dist/docs/session.md +1 -1
  41. package/dist/docs/shipping-address.md +110 -258
  42. package/dist/docs/sign-in-redirect.md +1 -1
  43. package/dist/index.d.ts +4 -1
  44. package/dist/internal/client.d.ts +3 -1
  45. package/dist/internal/client.js +3 -1
  46. package/dist/matter/access-code-sign-in/access-code-sign-in.js +9 -8
  47. package/dist/matter/access-code-sign-in/access-code-sign-in.js.map +1 -1
  48. package/dist/matter/account-access-gate/account-access-gate.d.ts +86 -0
  49. package/dist/matter/account-access-gate/account-access-gate.js +283 -0
  50. package/dist/matter/account-access-gate/account-access-gate.js.map +1 -0
  51. package/dist/matter/account-access-gate/sign-out-intent.d.ts +17 -0
  52. package/dist/matter/account-access-gate/sign-out-intent.js +62 -0
  53. package/dist/matter/account-access-gate/sign-out-intent.js.map +1 -0
  54. package/dist/matter/account-entry-point/account-entry-point.js +2 -2
  55. package/dist/matter/account-entry-point/account-entry-point.js.map +1 -1
  56. package/dist/matter/account-menu/account-menu.d.ts +88 -0
  57. package/dist/matter/account-menu/account-menu.js +246 -0
  58. package/dist/matter/account-menu/account-menu.js.map +1 -0
  59. package/dist/matter/billing-address/billing-address.d.ts +165 -0
  60. package/dist/matter/billing-address/billing-address.js +408 -0
  61. package/dist/matter/billing-address/billing-address.js.map +1 -0
  62. package/dist/matter/card-entry/card-capture.d.ts +25 -0
  63. package/dist/matter/card-entry/card-capture.js +25 -0
  64. package/dist/matter/card-entry/card-capture.js.map +1 -0
  65. package/dist/matter/card-entry/card-entry.d.ts +120 -0
  66. package/dist/matter/card-entry/card-entry.js +832 -0
  67. package/dist/matter/card-entry/card-entry.js.map +1 -0
  68. package/dist/matter/cardholder-document/cardholder-document.d.ts +45 -0
  69. package/dist/matter/cardholder-document/cardholder-document.js +70 -0
  70. package/dist/matter/cardholder-document/cardholder-document.js.map +1 -0
  71. package/dist/matter/cart/cart.d.ts +1 -1
  72. package/dist/matter/cart/cart.js +2 -2
  73. package/dist/matter/cart/cart.js.map +1 -1
  74. package/dist/matter/client-preferences/client-preferences-fieldset.d.ts +77 -0
  75. package/dist/matter/client-preferences/client-preferences-fieldset.js +299 -0
  76. package/dist/matter/client-preferences/client-preferences-fieldset.js.map +1 -0
  77. package/dist/matter/client-preferences/client-preferences.d.ts +3 -5
  78. package/dist/matter/client-preferences/client-preferences.js +6 -6
  79. package/dist/matter/client-preferences/client-preferences.js.map +1 -1
  80. package/dist/matter/client-profile/client-profile.d.ts +4 -6
  81. package/dist/matter/client-profile/client-profile.js +9 -6
  82. package/dist/matter/client-profile/client-profile.js.map +1 -1
  83. package/dist/matter/client-profile-form/client-profile-fieldset.d.ts +119 -0
  84. package/dist/matter/client-profile-form/client-profile-fieldset.js +488 -0
  85. package/dist/matter/client-profile-form/client-profile-fieldset.js.map +1 -0
  86. package/dist/matter/delivery-options/delivery-options.js.map +1 -1
  87. package/dist/matter/identity-edit/identity-edit.js +2 -2
  88. package/dist/matter/identity-edit/identity-edit.js.map +1 -1
  89. package/dist/matter/identity-summary/identity-summary.js +2 -2
  90. package/dist/matter/identity-summary/identity-summary.js.map +1 -1
  91. package/dist/matter/installments/installments-select.d.ts +42 -0
  92. package/dist/matter/installments/installments-select.js +167 -0
  93. package/dist/matter/installments/installments-select.js.map +1 -0
  94. package/dist/matter/installments/installments.d.ts +58 -0
  95. package/dist/matter/installments/installments.js +176 -0
  96. package/dist/matter/installments/installments.js.map +1 -0
  97. package/dist/matter/installments/use-installments-selection.d.ts +29 -0
  98. package/dist/matter/installments/use-installments-selection.js +95 -0
  99. package/dist/matter/installments/use-installments-selection.js.map +1 -0
  100. package/dist/matter/my-account-profile/my-account-profile.js +5 -5
  101. package/dist/matter/my-account-profile/my-account-profile.js.map +1 -1
  102. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.d.ts +63 -0
  103. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js +305 -0
  104. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js.map +1 -0
  105. package/dist/matter/payment/payment-card-capture.d.ts +19 -0
  106. package/dist/matter/payment/payment-card-capture.js +129 -0
  107. package/dist/matter/payment/payment-card-capture.js.map +1 -0
  108. package/dist/matter/payment/payment-controller.d.ts +24 -0
  109. package/dist/matter/payment/payment-controller.js +107 -0
  110. package/dist/matter/payment/payment-controller.js.map +1 -0
  111. package/dist/matter/payment/payment-method-badges.d.ts +57 -0
  112. package/dist/matter/payment/payment-method-badges.js +192 -0
  113. package/dist/matter/payment/payment-method-badges.js.map +1 -0
  114. package/dist/matter/payment/payment.d.ts +89 -0
  115. package/dist/matter/payment/payment.js +263 -0
  116. package/dist/matter/payment/payment.js.map +1 -0
  117. package/dist/matter/payment/use-payment-method-selection.d.ts +302 -0
  118. package/dist/matter/payment/use-payment-method-selection.js +458 -0
  119. package/dist/matter/payment/use-payment-method-selection.js.map +1 -0
  120. package/dist/matter/payment/use-payment-submit-gate.d.ts +111 -0
  121. package/dist/matter/payment/use-payment-submit-gate.js +144 -0
  122. package/dist/matter/payment/use-payment-submit-gate.js.map +1 -0
  123. package/dist/matter/place-order/place-order.d.ts +74 -0
  124. package/dist/matter/place-order/place-order.js +379 -0
  125. package/dist/matter/place-order/place-order.js.map +1 -0
  126. package/dist/matter/product-list/product-list.d.ts +1 -0
  127. package/dist/matter/product-list/product-list.js.map +1 -1
  128. package/dist/matter/product-shelf/product-shelf.d.ts +1 -0
  129. package/dist/matter/product-shelf/product-shelf.js +2 -0
  130. package/dist/matter/product-shelf/product-shelf.js.map +1 -1
  131. package/dist/matter/region/region.js +1 -1
  132. package/dist/matter/region/region.js.map +1 -1
  133. package/dist/matter/save-card/save-card.d.ts +49 -0
  134. package/dist/matter/save-card/save-card.js +188 -0
  135. package/dist/matter/save-card/save-card.js.map +1 -0
  136. package/dist/matter/saved-cards/saved-cards.d.ts +79 -0
  137. package/dist/matter/saved-cards/saved-cards.js +387 -0
  138. package/dist/matter/saved-cards/saved-cards.js.map +1 -0
  139. package/dist/matter/shipping-address/country-descriptors.js +20 -10
  140. package/dist/matter/shipping-address/country-descriptors.js.map +1 -1
  141. package/dist/matter/shipping-address/shipping-address.d.ts +113 -174
  142. package/dist/matter/shipping-address/shipping-address.js +481 -792
  143. package/dist/matter/shipping-address/shipping-address.js.map +1 -1
  144. package/dist/matter/shipping-simulator/shipping-simulator.js.map +1 -1
  145. package/dist/matter/variant-selector/variant-selector.js +1 -1
  146. package/dist/particles/address-summary/address-summary.d.ts +24 -0
  147. package/dist/particles/address-summary/address-summary.js +83 -2
  148. package/dist/particles/address-summary/address-summary.js.map +1 -1
  149. package/dist/particles/alert-dialog/alert-dialog.d.ts +68 -0
  150. package/dist/particles/alert-dialog/alert-dialog.js +187 -0
  151. package/dist/particles/alert-dialog/alert-dialog.js.map +1 -0
  152. package/dist/particles/checkbox/checkbox.d.ts +7 -3
  153. package/dist/particles/checkbox/checkbox.js +4 -1
  154. package/dist/particles/checkbox/checkbox.js.map +1 -1
  155. package/dist/particles/document-field/document-field.d.ts +48 -5
  156. package/dist/particles/document-field/document-field.js +189 -32
  157. package/dist/particles/document-field/document-field.js.map +1 -1
  158. package/dist/particles/field/bound-field-registry.js +52 -0
  159. package/dist/particles/field/bound-field-registry.js.map +1 -0
  160. package/dist/particles/field/field.d.ts +116 -0
  161. package/dist/particles/field/field.js +497 -6
  162. package/dist/particles/field/field.js.map +1 -1
  163. package/dist/particles/fieldset/fieldset.js +2 -2
  164. package/dist/particles/fieldset/fieldset.js.map +1 -1
  165. package/dist/particles/footer-social/footer-social.js +1 -1
  166. package/dist/particles/form/form.d.ts +104 -0
  167. package/dist/particles/form/form.js +485 -0
  168. package/dist/particles/form/form.js.map +1 -0
  169. package/dist/particles/incentives/incentives.js +1 -1
  170. package/dist/particles/phone-field/phone-field.d.ts +38 -10
  171. package/dist/particles/phone-field/phone-field.js +183 -39
  172. package/dist/particles/phone-field/phone-field.js.map +1 -1
  173. package/dist/particles/postal-code-field/postal-code-field.js +2 -2
  174. package/dist/particles/postal-code-field/postal-code-field.js.map +1 -1
  175. package/dist/particles/select/field-select.d.ts +43 -0
  176. package/dist/particles/select/field-select.js +150 -0
  177. package/dist/particles/select/field-select.js.map +1 -0
  178. package/dist/particles/select/select.d.ts +2 -0
  179. package/dist/particles/select/select.js.map +1 -1
  180. package/dist/particles/shared/compose-refs.js +21 -0
  181. package/dist/particles/shared/compose-refs.js.map +1 -0
  182. package/dist/schema.graphql +701 -2
  183. package/dist/sdk/actions/analytics-action-provider.d.ts +15 -0
  184. package/dist/sdk/actions/analytics-action-provider.js +19 -0
  185. package/dist/sdk/actions/analytics-action-provider.js.map +1 -0
  186. package/dist/sdk/actions/cart-action-provider.d.ts +1 -1
  187. package/dist/sdk/actions/cart-action-provider.js +1 -1
  188. package/dist/sdk/actions/cart-action-provider.js.map +1 -1
  189. package/dist/sdk/actions/index.d.ts +3 -1
  190. package/dist/sdk/actions/index.js +3 -1
  191. package/dist/sdk/actions/payment-action-provider.d.ts +22 -0
  192. package/dist/sdk/actions/payment-action-provider.js +26 -0
  193. package/dist/sdk/actions/payment-action-provider.js.map +1 -0
  194. package/dist/sdk/actions/session-action-provider.d.ts +1 -1
  195. package/dist/sdk/actions/session-action-provider.js +1 -1
  196. package/dist/sdk/actions/session-action-provider.js.map +1 -1
  197. package/dist/sdk/actions/shipping-action-provider.d.ts +1 -1
  198. package/dist/sdk/actions/shipping-action-provider.js +1 -1
  199. package/dist/sdk/actions/shipping-action-provider.js.map +1 -1
  200. package/dist/sdk/actions/types.d.ts +6 -2
  201. package/dist/sdk/analytics/analytics-destination.d.ts +43 -0
  202. package/dist/sdk/analytics/analytics-destination.js +90 -0
  203. package/dist/sdk/analytics/analytics-destination.js.map +1 -0
  204. package/dist/sdk/analytics/use-analytics-actions.d.ts +57 -0
  205. package/dist/sdk/analytics/use-analytics-actions.js +108 -0
  206. package/dist/sdk/analytics/use-analytics-actions.js.map +1 -0
  207. package/dist/sdk/cache/storefront-cache.js +1 -1
  208. package/dist/sdk/cache/storefront-cache.js.map +1 -1
  209. package/dist/sdk/cart/operations.d.ts +4 -4
  210. package/dist/sdk/cart/operations.js +1 -1
  211. package/dist/sdk/cart/operations.js.map +1 -1
  212. package/dist/sdk/cart/optimistic.js +1 -1
  213. package/dist/sdk/cart/optimistic.js.map +1 -1
  214. package/dist/sdk/cart/use-cart-actions.d.ts +1 -1
  215. package/dist/sdk/cart/use-cart-actions.js +4 -4
  216. package/dist/sdk/cart/use-cart-actions.js.map +1 -1
  217. package/dist/sdk/cart/use-cart-validate-on-open.js +1 -1
  218. package/dist/sdk/cart/use-cart-validate-on-open.js.map +1 -1
  219. package/dist/sdk/cart/write-gate.js +1 -1
  220. package/dist/sdk/cart/write-gate.js.map +1 -1
  221. package/dist/sdk/data/entity-resolution-context.js +31 -0
  222. package/dist/sdk/data/entity-resolution-context.js.map +1 -0
  223. package/dist/sdk/data/entity-subscriber.js +18 -8
  224. package/dist/sdk/data/entity-subscriber.js.map +1 -1
  225. package/dist/sdk/data/index.js +1 -0
  226. package/dist/sdk/data/page-reactive-data-root.d.ts +38 -2
  227. package/dist/sdk/data/page-reactive-data-root.js +4 -2
  228. package/dist/sdk/data/page-reactive-data-root.js.map +1 -1
  229. package/dist/sdk/data/reactive-data-provider.d.ts +1 -1
  230. package/dist/sdk/data/reactive-data-provider.js +8 -4
  231. package/dist/sdk/data/reactive-data-provider.js.map +1 -1
  232. package/dist/sdk/data/reactive-list-item-data-provider.d.ts +1 -1
  233. package/dist/sdk/data/reactive-list-item-data-provider.js +13 -5
  234. package/dist/sdk/data/reactive-list-item-data-provider.js.map +1 -1
  235. package/dist/sdk/data/use-reactive-data-settled.js +39 -0
  236. package/dist/sdk/data/use-reactive-data-settled.js.map +1 -0
  237. package/dist/sdk/data/use-reactive-entity.js +6 -2
  238. package/dist/sdk/data/use-reactive-entity.js.map +1 -1
  239. package/dist/sdk/generated/fragment-types.js +2 -0
  240. package/dist/sdk/generated/fragment-types.js.map +1 -1
  241. package/dist/sdk/generated/gql.js +2 -1
  242. package/dist/sdk/generated/gql.js.map +1 -1
  243. package/dist/sdk/generated/graphql.js +85 -1
  244. package/dist/sdk/generated/graphql.js.map +1 -1
  245. package/dist/sdk/i18n/messages/en-US.js +3 -0
  246. package/dist/sdk/i18n/messages/en-US.json +3 -0
  247. package/dist/sdk/i18n/messages/en-US.json.d.ts +3 -0
  248. package/dist/sdk/i18n/messages/es-ES.js +3 -0
  249. package/dist/sdk/i18n/messages/es-ES.json +3 -0
  250. package/dist/sdk/i18n/messages/pt-BR.js +3 -0
  251. package/dist/sdk/i18n/messages/pt-BR.json +3 -0
  252. package/dist/sdk/identity/operations.js.map +1 -1
  253. package/dist/sdk/identity/use-identity-actions.d.ts +1 -1
  254. package/dist/sdk/identity/use-identity-actions.js +3 -2
  255. package/dist/sdk/identity/use-identity-actions.js.map +1 -1
  256. package/dist/sdk/payment/gateway-origin.js +35 -0
  257. package/dist/sdk/payment/gateway-origin.js.map +1 -0
  258. package/dist/sdk/payment/gateway.d.ts +85 -0
  259. package/dist/sdk/payment/gateway.js +183 -0
  260. package/dist/sdk/payment/gateway.js.map +1 -0
  261. package/dist/sdk/payment/operations.d.ts +52 -0
  262. package/dist/sdk/payment/operations.js +223 -0
  263. package/dist/sdk/payment/operations.js.map +1 -0
  264. package/dist/sdk/payment/security-code-mask.js +71 -0
  265. package/dist/sdk/payment/security-code-mask.js.map +1 -0
  266. package/dist/sdk/payment/submission-registry.d.ts +33 -0
  267. package/dist/sdk/payment/submission-registry.js +58 -0
  268. package/dist/sdk/payment/submission-registry.js.map +1 -0
  269. package/dist/sdk/payment/use-payment-actions.d.ts +78 -0
  270. package/dist/sdk/payment/use-payment-actions.js +276 -0
  271. package/dist/sdk/payment/use-payment-actions.js.map +1 -0
  272. package/dist/sdk/payment/use-place-order.d.ts +65 -0
  273. package/dist/sdk/payment/use-place-order.js +640 -0
  274. package/dist/sdk/payment/use-place-order.js.map +1 -0
  275. package/dist/sdk/session/auth-operations.d.ts +1 -1
  276. package/dist/sdk/session/auth-operations.js.map +1 -1
  277. package/dist/sdk/session/use-session-actions.d.ts +1 -1
  278. package/dist/sdk/session/use-session-actions.js.map +1 -1
  279. package/dist/sdk/session/use-session-revalidation.js +65 -0
  280. package/dist/sdk/session/use-session-revalidation.js.map +1 -0
  281. package/dist/sdk/shipping/option-select-operations.d.ts +1 -1
  282. package/dist/sdk/shipping/option-select-operations.js.map +1 -1
  283. package/dist/sdk/shipping/request-timeout.js +1 -1
  284. package/dist/sdk/shipping/request-timeout.js.map +1 -1
  285. package/dist/sdk/shipping/shipping-operations.d.ts +1 -1
  286. package/dist/sdk/shipping/shipping-operations.js.map +1 -1
  287. package/dist/sdk/shipping/use-shipping-actions.d.ts +2 -2
  288. package/dist/sdk/shipping/use-shipping-actions.js +1 -1
  289. package/dist/sdk/shipping/use-shipping-actions.js.map +1 -1
  290. package/dist/sdk/state/cart.d.ts +3 -4
  291. package/dist/sdk/state/cart.js +6 -7
  292. package/dist/sdk/state/cart.js.map +1 -1
  293. package/dist/utils/loggable-error-name.js +49 -0
  294. package/dist/utils/loggable-error-name.js.map +1 -0
  295. package/dist/utils/resolve-authored-copy.js +18 -0
  296. package/dist/utils/resolve-authored-copy.js.map +1 -0
  297. package/dist/utils/safe-href.js +3 -3
  298. package/dist/utils/safe-href.js.map +1 -1
  299. package/dist/utils/substitute-template.js +33 -0
  300. package/dist/utils/substitute-template.js.map +1 -0
  301. package/package.json +2 -1
  302. package/src/styles/tailwind.css +34 -0
  303. package/dist/docs/client-profile-form.md +0 -192
  304. package/dist/matter/client-profile-form/client-profile-form.d.ts +0 -126
  305. package/dist/matter/client-profile-form/client-profile-form.js +0 -662
  306. package/dist/matter/client-profile-form/client-profile-form.js.map +0 -1
@@ -0,0 +1,15 @@
1
+ import { ActionProviderProps } from "./inject-actions.js";
2
+ import { ReactNode } from "react";
3
+ //#region src/sdk/actions/analytics-action-provider.d.ts
4
+ export type AnalyticsActionProviderProps = ActionProviderProps;
5
+ /**
6
+ * Compiler-emitted runtime wrapper for the `analytics` action namespace. The compiler wraps every
7
+ * element whose definition declares `actions: { analytics: [...] }` with
8
+ * `<AnalyticsActionProvider methods={[...]}>`, calls `useAnalyticsActions` once, narrows the
9
+ * surface to the declared `methods`, and publishes it through `ActionsOverrideContext` (merging with
10
+ * any outer namespace provider, per `useInjectActions`) for `useActionsOverride` to read further
11
+ * down. A namespace a component does not declare is never wrapped, so its hook is never called.
12
+ */
13
+ export declare function AnalyticsActionProvider(props: AnalyticsActionProviderProps): ReactNode;
14
+ //#endregion
15
+ //# sourceMappingURL=analytics-action-provider.d.ts.map
@@ -0,0 +1,19 @@
1
+ "use client";
2
+ import { useAnalyticsActions } from "../analytics/use-analytics-actions.js";
3
+ import { useInjectActions } from "./inject-actions.js";
4
+ //#region src/sdk/actions/analytics-action-provider.tsx
5
+ /**
6
+ * Compiler-emitted runtime wrapper for the `analytics` action namespace. The compiler wraps every
7
+ * element whose definition declares `actions: { analytics: [...] }` with
8
+ * `<AnalyticsActionProvider methods={[...]}>`, calls `useAnalyticsActions` once, narrows the
9
+ * surface to the declared `methods`, and publishes it through `ActionsOverrideContext` (merging with
10
+ * any outer namespace provider, per `useInjectActions`) for `useActionsOverride` to read further
11
+ * down. A namespace a component does not declare is never wrapped, so its hook is never called.
12
+ */
13
+ function AnalyticsActionProvider(props) {
14
+ return useInjectActions("analytics", useAnalyticsActions(), props);
15
+ }
16
+ //#endregion
17
+ export { AnalyticsActionProvider };
18
+
19
+ //# sourceMappingURL=analytics-action-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics-action-provider.js","names":[],"sources":["../../../src/sdk/actions/analytics-action-provider.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactNode } from 'react';\nimport { useAnalyticsActions } from '../analytics/use-analytics-actions.js';\nimport { type ActionProviderProps, useInjectActions } from './inject-actions.js';\n\nexport type AnalyticsActionProviderProps = ActionProviderProps;\n\n/**\n * Compiler-emitted runtime wrapper for the `analytics` action namespace. The compiler wraps every\n * element whose definition declares `actions: { analytics: [...] }` with\n * `<AnalyticsActionProvider methods={[...]}>`, calls `useAnalyticsActions` once, narrows the\n * surface to the declared `methods`, and publishes it through `ActionsOverrideContext` (merging with\n * any outer namespace provider, per `useInjectActions`) for `useActionsOverride` to read further\n * down. A namespace a component does not declare is never wrapped, so its hook is never called.\n */\nexport function AnalyticsActionProvider(props: AnalyticsActionProviderProps): ReactNode {\n return useInjectActions('analytics', useAnalyticsActions(), props);\n}\n"],"mappings":";;;;;;;;;;;;AAgBA,SAAgB,wBAAwB,OAAgD;CACtF,OAAO,iBAAiB,aAAa,oBAAoB,GAAG,KAAK;AACnE"}
@@ -9,7 +9,7 @@ export type CartActionProviderProps = ActionProviderProps;
9
9
  * once, narrows the surface to the declared `methods`, and publishes it through
10
10
  * `ActionsOverrideContext` (merging with any outer namespace provider) for `useActionsOverride` to
11
11
  * read further down. A namespace a component does not declare is never wrapped, so its hook is never
12
- * called (specs/actions.md FR-6).
12
+ * called (docs/storefront-core/reference-free-particle-model.md § Write side — actions).
13
13
  *
14
14
  * It delivers `$actions` through context, not a `cloneElement` prop injection, matching `$data`
15
15
  * (`DataOverrideContext`/`useDataOverride`) — see `useInjectActions`. A component with no provider
@@ -9,7 +9,7 @@ import { useInjectActions } from "./inject-actions.js";
9
9
  * once, narrows the surface to the declared `methods`, and publishes it through
10
10
  * `ActionsOverrideContext` (merging with any outer namespace provider) for `useActionsOverride` to
11
11
  * read further down. A namespace a component does not declare is never wrapped, so its hook is never
12
- * called (specs/actions.md FR-6).
12
+ * called (docs/storefront-core/reference-free-particle-model.md § Write side — actions).
13
13
  *
14
14
  * It delivers `$actions` through context, not a `cloneElement` prop injection, matching `$data`
15
15
  * (`DataOverrideContext`/`useDataOverride`) — see `useInjectActions`. A component with no provider
@@ -1 +1 @@
1
- {"version":3,"file":"cart-action-provider.js","names":[],"sources":["../../../src/sdk/actions/cart-action-provider.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactNode } from 'react';\nimport { useCartActions } from '../cart/use-cart-actions.js';\nimport { type ActionProviderProps, useInjectActions } from './inject-actions.js';\n\nexport type CartActionProviderProps = ActionProviderProps;\n\n/**\n * Compiler-emitted runtime wrapper for the `cart` action namespace — the write-side mirror of\n * `ReactiveDataProvider`. The compiler wraps every element whose definition declares\n * `actions: { cart: [...] }` with `<CartActionProvider methods={[...]}>`, calls `useCartActions`\n * once, narrows the surface to the declared `methods`, and publishes it through\n * `ActionsOverrideContext` (merging with any outer namespace provider) for `useActionsOverride` to\n * read further down. A namespace a component does not declare is never wrapped, so its hook is never\n * called (specs/actions.md FR-6).\n *\n * It delivers `$actions` through context, not a `cloneElement` prop injection, matching `$data`\n * (`DataOverrideContext`/`useDataOverride`) — see `useInjectActions`. A component with no provider\n * above it (`mockAction` in a test or story) still works: `useActionsOverride` falls back to\n * whatever `$actions` prop the component was directly given.\n */\nexport function CartActionProvider(props: CartActionProviderProps): ReactNode {\n return useInjectActions('cart', useCartActions(), props);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAsBA,SAAgB,mBAAmB,OAA2C;CAC5E,OAAO,iBAAiB,QAAQ,eAAe,GAAG,KAAK;AACzD"}
1
+ {"version":3,"file":"cart-action-provider.js","names":[],"sources":["../../../src/sdk/actions/cart-action-provider.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactNode } from 'react';\nimport { useCartActions } from '../cart/use-cart-actions.js';\nimport { type ActionProviderProps, useInjectActions } from './inject-actions.js';\n\nexport type CartActionProviderProps = ActionProviderProps;\n\n/**\n * Compiler-emitted runtime wrapper for the `cart` action namespace — the write-side mirror of\n * `ReactiveDataProvider`. The compiler wraps every element whose definition declares\n * `actions: { cart: [...] }` with `<CartActionProvider methods={[...]}>`, calls `useCartActions`\n * once, narrows the surface to the declared `methods`, and publishes it through\n * `ActionsOverrideContext` (merging with any outer namespace provider) for `useActionsOverride` to\n * read further down. A namespace a component does not declare is never wrapped, so its hook is never\n * called (docs/storefront-core/reference-free-particle-model.md § Write side — actions).\n *\n * It delivers `$actions` through context, not a `cloneElement` prop injection, matching `$data`\n * (`DataOverrideContext`/`useDataOverride`) — see `useInjectActions`. A component with no provider\n * above it (`mockAction` in a test or story) still works: `useActionsOverride` falls back to\n * whatever `$actions` prop the component was directly given.\n */\nexport function CartActionProvider(props: CartActionProviderProps): ReactNode {\n return useInjectActions('cart', useCartActions(), props);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAsBA,SAAgB,mBAAmB,OAA2C;CAC5E,OAAO,iBAAiB,QAAQ,eAAe,GAAG,KAAK;AACzD"}
@@ -1,7 +1,9 @@
1
1
  import { ComponentActions } from "./types.js";
2
+ import { AnalyticsActionProvider, AnalyticsActionProviderProps } from "./analytics-action-provider.js";
2
3
  import { CartActionProvider, CartActionProviderProps } from "./cart-action-provider.js";
3
4
  import { IdentityActionProvider, IdentityActionProviderProps } from "./identity-action-provider.js";
5
+ import { PaymentActionProvider, PaymentActionProviderProps } from "./payment-action-provider.js";
4
6
  import { RegionActionProvider, RegionActionProviderProps } from "./region-action-provider.js";
5
7
  import { SessionActionProvider, SessionActionProviderProps } from "./session-action-provider.js";
6
8
  import { ShippingActionProvider, ShippingActionProviderProps } from "./shipping-action-provider.js";
7
- export { CartActionProvider, type CartActionProviderProps, IdentityActionProvider, type IdentityActionProviderProps, RegionActionProvider, type RegionActionProviderProps, SessionActionProvider, type SessionActionProviderProps, ShippingActionProvider, type ShippingActionProviderProps };
9
+ export { AnalyticsActionProvider, type AnalyticsActionProviderProps, CartActionProvider, type CartActionProviderProps, IdentityActionProvider, type IdentityActionProviderProps, PaymentActionProvider, type PaymentActionProviderProps, RegionActionProvider, type RegionActionProviderProps, SessionActionProvider, type SessionActionProviderProps, ShippingActionProvider, type ShippingActionProviderProps };
@@ -1,6 +1,8 @@
1
+ import { AnalyticsActionProvider } from "./analytics-action-provider.js";
1
2
  import { CartActionProvider } from "./cart-action-provider.js";
2
3
  import { IdentityActionProvider } from "./identity-action-provider.js";
4
+ import { PaymentActionProvider } from "./payment-action-provider.js";
3
5
  import { RegionActionProvider } from "./region-action-provider.js";
4
6
  import { SessionActionProvider } from "./session-action-provider.js";
5
7
  import { ShippingActionProvider } from "./shipping-action-provider.js";
6
- export { CartActionProvider, IdentityActionProvider, RegionActionProvider, SessionActionProvider, ShippingActionProvider };
8
+ export { AnalyticsActionProvider, CartActionProvider, IdentityActionProvider, PaymentActionProvider, RegionActionProvider, SessionActionProvider, ShippingActionProvider };
@@ -0,0 +1,22 @@
1
+ import { ActionProviderProps } from "./inject-actions.js";
2
+ import { ReactNode } from "react";
3
+ //#region src/sdk/actions/payment-action-provider.d.ts
4
+ export type PaymentActionProviderProps = ActionProviderProps;
5
+ /**
6
+ * Compiler-emitted runtime wrapper for the `payment` action namespace. The compiler wraps every
7
+ * element whose definition declares `actions: { payment: [...] }` with
8
+ * `<PaymentActionProvider methods={[...]}>`, calls `usePaymentActions` once, narrows the surface to
9
+ * the declared `methods`, and publishes it through `ActionsOverrideContext` (merging with any outer
10
+ * namespace provider, per `useInjectActions`) for `useActionsOverride` to read further down. A
11
+ * namespace a component does not declare is never wrapped, so its hook is never called
12
+ * (specs/actions.md FR-6).
13
+ *
14
+ * Narrowing matters more here than elsewhere: a component that declares only `setMethod` never receives
15
+ * `sendPayments`, because its own provider replaces the whole `payment` namespace an outer provider
16
+ * published (specs/payment-action-namespace.md, Decision 5). Context does not narrow a component that
17
+ * declares no `payment` method at all: rendered inside one that does, it can read the outer set
18
+ * (specs/sfs-3395-action-provider-context-delivery.md, Decision 2).
19
+ */
20
+ export declare function PaymentActionProvider(props: PaymentActionProviderProps): ReactNode;
21
+ //#endregion
22
+ //# sourceMappingURL=payment-action-provider.d.ts.map
@@ -0,0 +1,26 @@
1
+ "use client";
2
+ import { useInjectActions } from "./inject-actions.js";
3
+ import { usePaymentActions } from "../payment/use-payment-actions.js";
4
+ //#region src/sdk/actions/payment-action-provider.tsx
5
+ /**
6
+ * Compiler-emitted runtime wrapper for the `payment` action namespace. The compiler wraps every
7
+ * element whose definition declares `actions: { payment: [...] }` with
8
+ * `<PaymentActionProvider methods={[...]}>`, calls `usePaymentActions` once, narrows the surface to
9
+ * the declared `methods`, and publishes it through `ActionsOverrideContext` (merging with any outer
10
+ * namespace provider, per `useInjectActions`) for `useActionsOverride` to read further down. A
11
+ * namespace a component does not declare is never wrapped, so its hook is never called
12
+ * (specs/actions.md FR-6).
13
+ *
14
+ * Narrowing matters more here than elsewhere: a component that declares only `setMethod` never receives
15
+ * `sendPayments`, because its own provider replaces the whole `payment` namespace an outer provider
16
+ * published (specs/payment-action-namespace.md, Decision 5). Context does not narrow a component that
17
+ * declares no `payment` method at all: rendered inside one that does, it can read the outer set
18
+ * (specs/sfs-3395-action-provider-context-delivery.md, Decision 2).
19
+ */
20
+ function PaymentActionProvider(props) {
21
+ return useInjectActions("payment", usePaymentActions(), props);
22
+ }
23
+ //#endregion
24
+ export { PaymentActionProvider };
25
+
26
+ //# sourceMappingURL=payment-action-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payment-action-provider.js","names":[],"sources":["../../../src/sdk/actions/payment-action-provider.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactNode } from 'react';\nimport { usePaymentActions } from '../payment/use-payment-actions.js';\nimport { type ActionProviderProps, useInjectActions } from './inject-actions.js';\n\nexport type PaymentActionProviderProps = ActionProviderProps;\n\n/**\n * Compiler-emitted runtime wrapper for the `payment` action namespace. The compiler wraps every\n * element whose definition declares `actions: { payment: [...] }` with\n * `<PaymentActionProvider methods={[...]}>`, calls `usePaymentActions` once, narrows the surface to\n * the declared `methods`, and publishes it through `ActionsOverrideContext` (merging with any outer\n * namespace provider, per `useInjectActions`) for `useActionsOverride` to read further down. A\n * namespace a component does not declare is never wrapped, so its hook is never called\n * (specs/actions.md FR-6).\n *\n * Narrowing matters more here than elsewhere: a component that declares only `setMethod` never receives\n * `sendPayments`, because its own provider replaces the whole `payment` namespace an outer provider\n * published (specs/payment-action-namespace.md, Decision 5). Context does not narrow a component that\n * declares no `payment` method at all: rendered inside one that does, it can read the outer set\n * (specs/sfs-3395-action-provider-context-delivery.md, Decision 2).\n */\nexport function PaymentActionProvider(props: PaymentActionProviderProps): ReactNode {\n return useInjectActions('payment', usePaymentActions(), props);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,sBAAsB,OAA8C;CAClF,OAAO,iBAAiB,WAAW,kBAAkB,GAAG,KAAK;AAC/D"}
@@ -9,7 +9,7 @@ export type SessionActionProviderProps = ActionProviderProps;
9
9
  * `useSessionActions` once, narrows the surface to the declared `methods`, and publishes it through
10
10
  * `ActionsOverrideContext` (merging with any outer namespace provider) for `useActionsOverride` to
11
11
  * read further down. A namespace a component does not declare is never wrapped, so its hook is
12
- * never called (specs/actions.md FR-6).
12
+ * never called (docs/storefront-core/reference-free-particle-model.md § Write side — actions).
13
13
  */
14
14
  export declare function SessionActionProvider(props: SessionActionProviderProps): ReactNode;
15
15
  //#endregion
@@ -9,7 +9,7 @@ import { useSessionActions } from "../session/use-session-actions.js";
9
9
  * `useSessionActions` once, narrows the surface to the declared `methods`, and publishes it through
10
10
  * `ActionsOverrideContext` (merging with any outer namespace provider) for `useActionsOverride` to
11
11
  * read further down. A namespace a component does not declare is never wrapped, so its hook is
12
- * never called (specs/actions.md FR-6).
12
+ * never called (docs/storefront-core/reference-free-particle-model.md § Write side — actions).
13
13
  */
14
14
  function SessionActionProvider(props) {
15
15
  return useInjectActions("session", useSessionActions(), props);
@@ -1 +1 @@
1
- {"version":3,"file":"session-action-provider.js","names":[],"sources":["../../../src/sdk/actions/session-action-provider.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactNode } from 'react';\nimport { useSessionActions } from '../session/use-session-actions.js';\nimport { type ActionProviderProps, useInjectActions } from './inject-actions.js';\n\nexport type SessionActionProviderProps = ActionProviderProps;\n\n/**\n * Compiler-emitted runtime wrapper for the `session` action namespace — a line-for-line mirror of\n * `CartActionProvider`. The compiler wraps every element whose definition declares\n * `actions: { session: [...] }` with `<SessionActionProvider methods={[...]}>`, calls\n * `useSessionActions` once, narrows the surface to the declared `methods`, and publishes it through\n * `ActionsOverrideContext` (merging with any outer namespace provider) for `useActionsOverride` to\n * read further down. A namespace a component does not declare is never wrapped, so its hook is\n * never called (specs/actions.md FR-6).\n */\nexport function SessionActionProvider(props: SessionActionProviderProps): ReactNode {\n return useInjectActions('session', useSessionActions(), props);\n}\n"],"mappings":";;;;;;;;;;;;;AAiBA,SAAgB,sBAAsB,OAA8C;CAClF,OAAO,iBAAiB,WAAW,kBAAkB,GAAG,KAAK;AAC/D"}
1
+ {"version":3,"file":"session-action-provider.js","names":[],"sources":["../../../src/sdk/actions/session-action-provider.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactNode } from 'react';\nimport { useSessionActions } from '../session/use-session-actions.js';\nimport { type ActionProviderProps, useInjectActions } from './inject-actions.js';\n\nexport type SessionActionProviderProps = ActionProviderProps;\n\n/**\n * Compiler-emitted runtime wrapper for the `session` action namespace — a line-for-line mirror of\n * `CartActionProvider`. The compiler wraps every element whose definition declares\n * `actions: { session: [...] }` with `<SessionActionProvider methods={[...]}>`, calls\n * `useSessionActions` once, narrows the surface to the declared `methods`, and publishes it through\n * `ActionsOverrideContext` (merging with any outer namespace provider) for `useActionsOverride` to\n * read further down. A namespace a component does not declare is never wrapped, so its hook is\n * never called (docs/storefront-core/reference-free-particle-model.md § Write side — actions).\n */\nexport function SessionActionProvider(props: SessionActionProviderProps): ReactNode {\n return useInjectActions('session', useSessionActions(), props);\n}\n"],"mappings":";;;;;;;;;;;;;AAiBA,SAAgB,sBAAsB,OAA8C;CAClF,OAAO,iBAAiB,WAAW,kBAAkB,GAAG,KAAK;AAC/D"}
@@ -9,7 +9,7 @@ export type ShippingActionProviderProps = ActionProviderProps;
9
9
  * `useShippingActions` once, narrows the surface to the declared `methods`, and publishes it through
10
10
  * `ActionsOverrideContext` (merging with any outer namespace provider) for `useActionsOverride` to
11
11
  * read further down. A namespace a component does not declare is never wrapped, so its hook is
12
- * never called (specs/actions.md FR-6).
12
+ * never called (docs/storefront-core/reference-free-particle-model.md § Write side — actions).
13
13
  */
14
14
  export declare function ShippingActionProvider(props: ShippingActionProviderProps): ReactNode;
15
15
  //#endregion
@@ -9,7 +9,7 @@ import { useShippingActions } from "../shipping/use-shipping-actions.js";
9
9
  * `useShippingActions` once, narrows the surface to the declared `methods`, and publishes it through
10
10
  * `ActionsOverrideContext` (merging with any outer namespace provider) for `useActionsOverride` to
11
11
  * read further down. A namespace a component does not declare is never wrapped, so its hook is
12
- * never called (specs/actions.md FR-6).
12
+ * never called (docs/storefront-core/reference-free-particle-model.md § Write side — actions).
13
13
  */
14
14
  function ShippingActionProvider(props) {
15
15
  return useInjectActions("shipping", useShippingActions(), props);
@@ -1 +1 @@
1
- {"version":3,"file":"shipping-action-provider.js","names":[],"sources":["../../../src/sdk/actions/shipping-action-provider.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactNode } from 'react';\nimport { useShippingActions } from '../shipping/use-shipping-actions.js';\nimport { type ActionProviderProps, useInjectActions } from './inject-actions.js';\n\nexport type ShippingActionProviderProps = ActionProviderProps;\n\n/**\n * Compiler-emitted runtime wrapper for the `shipping` action namespace — a line-for-line mirror of\n * `SessionActionProvider`. The compiler wraps every element whose definition declares\n * `actions: { shipping: [...] }` with `<ShippingActionProvider methods={[...]}>`, calls\n * `useShippingActions` once, narrows the surface to the declared `methods`, and publishes it through\n * `ActionsOverrideContext` (merging with any outer namespace provider) for `useActionsOverride` to\n * read further down. A namespace a component does not declare is never wrapped, so its hook is\n * never called (specs/actions.md FR-6).\n */\nexport function ShippingActionProvider(props: ShippingActionProviderProps): ReactNode {\n return useInjectActions('shipping', useShippingActions(), props);\n}\n"],"mappings":";;;;;;;;;;;;;AAiBA,SAAgB,uBAAuB,OAA+C;CACpF,OAAO,iBAAiB,YAAY,mBAAmB,GAAG,KAAK;AACjE"}
1
+ {"version":3,"file":"shipping-action-provider.js","names":[],"sources":["../../../src/sdk/actions/shipping-action-provider.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactNode } from 'react';\nimport { useShippingActions } from '../shipping/use-shipping-actions.js';\nimport { type ActionProviderProps, useInjectActions } from './inject-actions.js';\n\nexport type ShippingActionProviderProps = ActionProviderProps;\n\n/**\n * Compiler-emitted runtime wrapper for the `shipping` action namespace — a line-for-line mirror of\n * `SessionActionProvider`. The compiler wraps every element whose definition declares\n * `actions: { shipping: [...] }` with `<ShippingActionProvider methods={[...]}>`, calls\n * `useShippingActions` once, narrows the surface to the declared `methods`, and publishes it through\n * `ActionsOverrideContext` (merging with any outer namespace provider) for `useActionsOverride` to\n * read further down. A namespace a component does not declare is never wrapped, so its hook is\n * never called (docs/storefront-core/reference-free-particle-model.md § Write side — actions).\n */\nexport function ShippingActionProvider(props: ShippingActionProviderProps): ReactNode {\n return useInjectActions('shipping', useShippingActions(), props);\n}\n"],"mappings":";;;;;;;;;;;;;AAiBA,SAAgB,uBAAuB,OAA+C;CACpF,OAAO,iBAAiB,YAAY,mBAAmB,GAAG,KAAK;AACjE"}
@@ -1,5 +1,7 @@
1
+ import { AnalyticsActions } from "../analytics/use-analytics-actions.js";
1
2
  import { CartActions } from "../cart/use-cart-actions.js";
2
3
  import { IdentityActions } from "../identity/use-identity-actions.js";
4
+ import { PaymentActions } from "../payment/use-payment-actions.js";
3
5
  import { RegionActions } from "../region/use-region-actions.js";
4
6
  import { SessionActions } from "../session/use-session-actions.js";
5
7
  import { ShippingActions } from "../shipping/use-shipping-actions.js";
@@ -7,12 +9,14 @@ import { ShippingActions } from "../shipping/use-shipping-actions.js";
7
9
  /**
8
10
  * The `$actions` prop the compiler injects (and `mockAction` builds for tests). Each namespace is
9
11
  * optional and each method is optional within it, because a component only receives the methods it
10
- * declared under `actions: { ... }`. Ships the `cart`, `identity`, `region`, `session`, and
11
- * `shipping` namespaces.
12
+ * declared under `actions: { ... }`. Ships the `analytics`, `cart`, `identity`, `payment`, `region`,
13
+ * `session`, and `shipping` namespaces.
12
14
  */
13
15
  export type ComponentActions = {
16
+ analytics?: Partial<AnalyticsActions>;
14
17
  cart?: Partial<CartActions>;
15
18
  identity?: Partial<IdentityActions>;
19
+ payment?: Partial<PaymentActions>;
16
20
  region?: Partial<RegionActions>;
17
21
  session?: Partial<SessionActions>;
18
22
  shipping?: Partial<ShippingActions>;
@@ -0,0 +1,43 @@
1
+ import { ReactNode } from "react";
2
+ //#region src/sdk/analytics/analytics-destination.d.ts
3
+ /**
4
+ * Configurable analytics destination (specs/make-the-analytics-destination-configurable-for.md;
5
+ * credit-card epic T120; RFC `docs/features/credit-card/rfc.md` § D14 — Analytics events
6
+ * (cross-cutting)). `use-analytics-actions.ts`'s `pushToDataLayer` used to hardcode
7
+ * `window.dataLayer`. This module narrows "configurable destination" to the *name* of the
8
+ * `window` array the two standard payment events (`add_payment_info`, `purchase`) are pushed to —
9
+ * not a vendor id, not a transport, not a fan-out list. The payload and its GA4 shape are
10
+ * unchanged; only the array it lands in differs.
11
+ *
12
+ * Resolution precedence: the nearest `AnalyticsDestinationProvider` -> the build-inlined
13
+ * `process.env.NEXT_PUBLIC_ANALYTICS_DESTINATION` -> `DEFAULT_ANALYTICS_DESTINATION`. Resolution
14
+ * happens at call time, inside `track` (see `use-analytics-actions.ts`) — never once at module
15
+ * scope — so a build-time env change and a test's `vi.stubEnv` are both observed without a remount.
16
+ *
17
+ * A destination that is not a plain identifier, or that names `__proto__` / `constructor` /
18
+ * `prototype`, is never written to `window`: it is rejected, logged once, and resolution falls
19
+ * back to the default instead. A misconfiguration can only cost an analytics event — it can never
20
+ * block payment submission or order placement, the same invariant `use-analytics-actions.ts`
21
+ * already holds.
22
+ */
23
+ /** The name of the `window` property the standard analytics events are pushed to. */
24
+ export type AnalyticsDestination = string;
25
+ export type AnalyticsDestinationProviderProps = Readonly<{
26
+ /**
27
+ * The `window` property name events are pushed to. Must be a build-time or merchant-authored
28
+ * constant — never wire this from user input. The identifier pattern and denylist block the
29
+ * known prototype-pollution keys, but a value that passes validation could still name a live,
30
+ * load-bearing global (`__NEXT_P`, `_gaq`, or a merchant queue with a hijacked `push`).
31
+ */
32
+ destination: AnalyticsDestination;
33
+ children: ReactNode;
34
+ }>;
35
+ /**
36
+ * Publishes a destination to the subtree — for a host that renders the components by hand (an
37
+ * embedder, a Storybook story, a test) and wants to supply or override the destination in React
38
+ * rather than through the build. Optional: an unprovided tree is the normal case, and the nearest
39
+ * provider wins over any outer one.
40
+ */
41
+ export declare function AnalyticsDestinationProvider({ destination, children }: AnalyticsDestinationProviderProps): ReactNode;
42
+ //#endregion
43
+ //# sourceMappingURL=analytics-destination.d.ts.map
@@ -0,0 +1,90 @@
1
+ "use client";
2
+ import { createContext, useContext } from "react";
3
+ import { jsx } from "react/jsx-runtime";
4
+ //#region src/sdk/analytics/analytics-destination.tsx
5
+ /** The sink every store used before this task, and the fallback for anything invalid. */
6
+ const DEFAULT_ANALYTICS_DESTINATION = "dataLayer";
7
+ /** A plain property name: no dots, no dashes, no spaces, no leading digit. */
8
+ const DESTINATION_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
9
+ /** Never written to `window`, whatever the build says. */
10
+ const UNSAFE_DESTINATION_KEYS = [
11
+ "__proto__",
12
+ "constructor",
13
+ "prototype"
14
+ ];
15
+ /**
16
+ * A plain, safe `window` property name: matches the identifier pattern and is absent from the
17
+ * unsafe-key denylist. Operates on the value exactly as given — trimming, and treating
18
+ * empty-after-trim as unset, are `resolveAnalyticsDestination`'s job, not this predicate's.
19
+ */
20
+ function isValidAnalyticsDestination(value) {
21
+ return DESTINATION_PATTERN.test(value) && !UNSAFE_DESTINATION_KEYS.some((unsafeKey) => unsafeKey === value);
22
+ }
23
+ /**
24
+ * Returns the first non-empty-after-trim candidate in precedence order — `override`, then the
25
+ * build-inlined env var — together with whether that candidate is valid. Resolution never walks
26
+ * past that first configured candidate: an invalid `override` is never rescued by a valid env
27
+ * var, it falls straight through to `resolveAnalyticsDestination`'s default, exactly like an
28
+ * invalid env var with no override does. Validation itself is `isValidAnalyticsDestination`'s
29
+ * job — this function only picks which single candidate gets validated.
30
+ */
31
+ function firstConfiguredCandidate(override) {
32
+ const envValue = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_ANALYTICS_DESTINATION : void 0;
33
+ for (const candidate of [override, envValue]) {
34
+ if (candidate === void 0) continue;
35
+ const trimmed = candidate.trim();
36
+ if (trimmed.length === 0) continue;
37
+ return {
38
+ value: trimmed,
39
+ valid: isValidAnalyticsDestination(trimmed)
40
+ };
41
+ }
42
+ }
43
+ /**
44
+ * Precedence: `override` (context) -> NEXT_PUBLIC_ANALYTICS_DESTINATION -> DEFAULT.
45
+ * Trims; treats empty-after-trim as unset. A present-but-invalid value logs once via
46
+ * console.error and resolves to DEFAULT. Never throws.
47
+ *
48
+ * `hasLoggedRejection`, when passed, is a mutable latch: the first rejection while it is `false`
49
+ * logs and flips it to `true`; every later rejection while it stays `true` is silent. Omit it —
50
+ * every direct/unit-test call does — to log every rejection. `useAnalyticsActions` is the only
51
+ * caller that owns one, scoped to its own hook instance via `useRef`, so "logs once" means once
52
+ * per mounted `useAnalyticsActions()`, not once for the whole page.
53
+ */
54
+ function resolveAnalyticsDestination(options) {
55
+ const outcome = firstConfiguredCandidate(options?.override);
56
+ if (outcome === void 0) return DEFAULT_ANALYTICS_DESTINATION;
57
+ if (outcome.valid) return outcome.value;
58
+ const hasLoggedRejection = options?.hasLoggedRejection;
59
+ if (!hasLoggedRejection?.current) {
60
+ const message = `[analytics.track] ${JSON.stringify(outcome.value)} is not a valid analytics destination; falling back to ${JSON.stringify(DEFAULT_ANALYTICS_DESTINATION)}`;
61
+ console.error(message);
62
+ if (hasLoggedRejection) hasLoggedRejection.current = true;
63
+ }
64
+ return DEFAULT_ANALYTICS_DESTINATION;
65
+ }
66
+ /**
67
+ * Private, so the only read is `useAnalyticsDestination` — which, unlike `useStorefrontContext`,
68
+ * never throws when unprovided: an unprovided tree is the normal case here, not a bug.
69
+ */
70
+ const AnalyticsDestinationContext = createContext(void 0);
71
+ /**
72
+ * Publishes a destination to the subtree — for a host that renders the components by hand (an
73
+ * embedder, a Storybook story, a test) and wants to supply or override the destination in React
74
+ * rather than through the build. Optional: an unprovided tree is the normal case, and the nearest
75
+ * provider wins over any outer one.
76
+ */
77
+ function AnalyticsDestinationProvider({ destination, children }) {
78
+ return /* @__PURE__ */ jsx(AnalyticsDestinationContext.Provider, {
79
+ value: destination,
80
+ children
81
+ });
82
+ }
83
+ /** The nearest provided destination, or `undefined` when no provider is in the tree. Never throws. */
84
+ function useAnalyticsDestination() {
85
+ return useContext(AnalyticsDestinationContext);
86
+ }
87
+ //#endregion
88
+ export { AnalyticsDestinationProvider, DEFAULT_ANALYTICS_DESTINATION, isValidAnalyticsDestination, resolveAnalyticsDestination, useAnalyticsDestination };
89
+
90
+ //# sourceMappingURL=analytics-destination.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics-destination.js","names":[],"sources":["../../../src/sdk/analytics/analytics-destination.tsx"],"sourcesContent":["'use client';\n\nimport { createContext, type ReactNode, useContext } from 'react';\n\n/**\n * Configurable analytics destination (specs/make-the-analytics-destination-configurable-for.md;\n * credit-card epic T120; RFC `docs/features/credit-card/rfc.md` § D14 — Analytics events\n * (cross-cutting)). `use-analytics-actions.ts`'s `pushToDataLayer` used to hardcode\n * `window.dataLayer`. This module narrows \"configurable destination\" to the *name* of the\n * `window` array the two standard payment events (`add_payment_info`, `purchase`) are pushed to —\n * not a vendor id, not a transport, not a fan-out list. The payload and its GA4 shape are\n * unchanged; only the array it lands in differs.\n *\n * Resolution precedence: the nearest `AnalyticsDestinationProvider` -> the build-inlined\n * `process.env.NEXT_PUBLIC_ANALYTICS_DESTINATION` -> `DEFAULT_ANALYTICS_DESTINATION`. Resolution\n * happens at call time, inside `track` (see `use-analytics-actions.ts`) — never once at module\n * scope — so a build-time env change and a test's `vi.stubEnv` are both observed without a remount.\n *\n * A destination that is not a plain identifier, or that names `__proto__` / `constructor` /\n * `prototype`, is never written to `window`: it is rejected, logged once, and resolution falls\n * back to the default instead. A misconfiguration can only cost an analytics event — it can never\n * block payment submission or order placement, the same invariant `use-analytics-actions.ts`\n * already holds.\n */\n\n/** The name of the `window` property the standard analytics events are pushed to. */\nexport type AnalyticsDestination = string;\n\n/** The sink every store used before this task, and the fallback for anything invalid. */\nexport const DEFAULT_ANALYTICS_DESTINATION = 'dataLayer';\n\n/** A plain property name: no dots, no dashes, no spaces, no leading digit. */\nconst DESTINATION_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$]*$/;\n\n/** Never written to `window`, whatever the build says. */\nconst UNSAFE_DESTINATION_KEYS = ['__proto__', 'constructor', 'prototype'] as const;\n\n/**\n * A plain, safe `window` property name: matches the identifier pattern and is absent from the\n * unsafe-key denylist. Operates on the value exactly as given — trimming, and treating\n * empty-after-trim as unset, are `resolveAnalyticsDestination`'s job, not this predicate's.\n */\nexport function isValidAnalyticsDestination(value: string): boolean {\n return DESTINATION_PATTERN.test(value) && !UNSAFE_DESTINATION_KEYS.some((unsafeKey) => unsafeKey === value);\n}\n\n/** The first configured candidate in precedence order, paired with whether it is valid. */\ntype CandidateOutcome = Readonly<{ value: string; valid: boolean }>;\n\n/**\n * Returns the first non-empty-after-trim candidate in precedence order — `override`, then the\n * build-inlined env var — together with whether that candidate is valid. Resolution never walks\n * past that first configured candidate: an invalid `override` is never rescued by a valid env\n * var, it falls straight through to `resolveAnalyticsDestination`'s default, exactly like an\n * invalid env var with no override does. Validation itself is `isValidAnalyticsDestination`'s\n * job — this function only picks which single candidate gets validated.\n */\nfunction firstConfiguredCandidate(override: string | undefined): CandidateOutcome | undefined {\n // `typeof process !== 'undefined'` guards a client bundle with no `process` shim at all (a\n // Vite/Rollup/esbuild embedder, US-2's stated host) — unlike a direct read, `typeof` never\n // throws when the identifier doesn't exist at all. The member expression itself stays literal\n // so Next's build-time inlining can still statically replace it (Decision 5).\n const envValue = typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_ANALYTICS_DESTINATION : undefined;\n\n for (const candidate of [override, envValue]) {\n if (candidate === undefined) continue;\n const trimmed = candidate.trim();\n if (trimmed.length === 0) continue;\n return { value: trimmed, valid: isValidAnalyticsDestination(trimmed) };\n }\n return undefined;\n}\n\n/**\n * Precedence: `override` (context) -> NEXT_PUBLIC_ANALYTICS_DESTINATION -> DEFAULT.\n * Trims; treats empty-after-trim as unset. A present-but-invalid value logs once via\n * console.error and resolves to DEFAULT. Never throws.\n *\n * `hasLoggedRejection`, when passed, is a mutable latch: the first rejection while it is `false`\n * logs and flips it to `true`; every later rejection while it stays `true` is silent. Omit it —\n * every direct/unit-test call does — to log every rejection. `useAnalyticsActions` is the only\n * caller that owns one, scoped to its own hook instance via `useRef`, so \"logs once\" means once\n * per mounted `useAnalyticsActions()`, not once for the whole page.\n */\nexport function resolveAnalyticsDestination(options?: {\n override?: string;\n hasLoggedRejection?: { current: boolean };\n}): AnalyticsDestination {\n const outcome = firstConfiguredCandidate(options?.override);\n if (outcome === undefined) return DEFAULT_ANALYTICS_DESTINATION;\n if (outcome.valid) return outcome.value;\n\n const hasLoggedRejection = options?.hasLoggedRejection;\n if (!hasLoggedRejection?.current) {\n const message =\n `[analytics.track] ${JSON.stringify(outcome.value)} is not a valid analytics destination; ` +\n `falling back to ${JSON.stringify(DEFAULT_ANALYTICS_DESTINATION)}`;\n console.error(message);\n if (hasLoggedRejection) hasLoggedRejection.current = true;\n }\n return DEFAULT_ANALYTICS_DESTINATION;\n}\n\nexport type AnalyticsDestinationProviderProps = Readonly<{\n /**\n * The `window` property name events are pushed to. Must be a build-time or merchant-authored\n * constant — never wire this from user input. The identifier pattern and denylist block the\n * known prototype-pollution keys, but a value that passes validation could still name a live,\n * load-bearing global (`__NEXT_P`, `_gaq`, or a merchant queue with a hijacked `push`).\n */\n destination: AnalyticsDestination;\n children: ReactNode;\n}>;\n\n/**\n * Private, so the only read is `useAnalyticsDestination` — which, unlike `useStorefrontContext`,\n * never throws when unprovided: an unprovided tree is the normal case here, not a bug.\n */\nconst AnalyticsDestinationContext = createContext<AnalyticsDestination | undefined>(undefined);\n\n/**\n * Publishes a destination to the subtree — for a host that renders the components by hand (an\n * embedder, a Storybook story, a test) and wants to supply or override the destination in React\n * rather than through the build. Optional: an unprovided tree is the normal case, and the nearest\n * provider wins over any outer one.\n */\nexport function AnalyticsDestinationProvider({ destination, children }: AnalyticsDestinationProviderProps): ReactNode {\n return <AnalyticsDestinationContext.Provider value={destination}>{children}</AnalyticsDestinationContext.Provider>;\n}\n\n/** The nearest provided destination, or `undefined` when no provider is in the tree. Never throws. */\nexport function useAnalyticsDestination(): AnalyticsDestination | undefined {\n return useContext(AnalyticsDestinationContext);\n}\n"],"mappings":";;;;;AA6BA,MAAa,gCAAgC;;AAG7C,MAAM,sBAAsB;;AAG5B,MAAM,0BAA0B;CAAC;CAAa;CAAe;AAAW;;;;;;AAOxE,SAAgB,4BAA4B,OAAwB;CAClE,OAAO,oBAAoB,KAAK,KAAK,KAAK,CAAC,wBAAwB,MAAM,cAAc,cAAc,KAAK;AAC5G;;;;;;;;;AAaA,SAAS,yBAAyB,UAA4D;CAK5F,MAAM,WAAW,OAAO,YAAY,cAAc,QAAQ,IAAI,oCAAoC,KAAA;CAElG,KAAK,MAAM,aAAa,CAAC,UAAU,QAAQ,GAAG;EAC5C,IAAI,cAAc,KAAA,GAAW;EAC7B,MAAM,UAAU,UAAU,KAAK;EAC/B,IAAI,QAAQ,WAAW,GAAG;EAC1B,OAAO;GAAE,OAAO;GAAS,OAAO,4BAA4B,OAAO;EAAE;CACvE;AAEF;;;;;;;;;;;;AAaA,SAAgB,4BAA4B,SAGnB;CACvB,MAAM,UAAU,yBAAyB,SAAS,QAAQ;CAC1D,IAAI,YAAY,KAAA,GAAW,OAAO;CAClC,IAAI,QAAQ,OAAO,OAAO,QAAQ;CAElC,MAAM,qBAAqB,SAAS;CACpC,IAAI,CAAC,oBAAoB,SAAS;EAChC,MAAM,UACJ,qBAAqB,KAAK,UAAU,QAAQ,KAAK,EAAE,yDAChC,KAAK,UAAU,6BAA6B;EACjE,QAAQ,MAAM,OAAO;EACrB,IAAI,oBAAoB,mBAAmB,UAAU;CACvD;CACA,OAAO;AACT;;;;;AAiBA,MAAM,8BAA8B,cAAgD,KAAA,CAAS;;;;;;;AAQ7F,SAAgB,6BAA6B,EAAE,aAAa,YAA0D;CACpH,OAAO,oBAAC,4BAA4B,UAA7B;EAAsC,OAAO;EAAc;CAA+C,CAAA;AACnH;;AAGA,SAAgB,0BAA4D;CAC1E,OAAO,WAAW,2BAA2B;AAC/C"}
@@ -0,0 +1,57 @@
1
+ import "../../core/dist/index.js";
2
+ //#region src/sdk/analytics/use-analytics-actions.d.ts
3
+ /**
4
+ * The `analytics` action namespace (specs/analytics-events.md) — a dispatcher-flavor namespace
5
+ * (docs/storefront-core/adr-0010-actions-own-the-write-side.md; docs/storefront-core/rfc-actions.md
6
+ * § "Three binding flavors") that pushes the two standard payment analytics events,
7
+ * `add_payment_info` and `purchase`, to a `window` array — `window.dataLayer` by default, the
8
+ * GTM/GA4-recognizable event convention. It never touches the Apollo cache, never issues a GraphQL
9
+ * operation, and never throws: a broken tag-manager script can never block payment submission or
10
+ * order placement.
11
+ *
12
+ * The destination array is configurable at build time
13
+ * (specs/make-the-analytics-destination-configurable-for.md; T120) — see
14
+ * `./analytics-destination.js` for the resolution precedence, validation, and the
15
+ * `AnalyticsDestinationProvider`. The pushed entry's shape is a data *contract* (a well-known
16
+ * browser-global array shape), not a *provider* — no vendor SDK, no server call. A future
17
+ * platform/foundation epic may replace this sink with a real `AnalyticsContext`; the
18
+ * `track(event: AnalyticsEvent): void` signature and `AnalyticsActions` type are the stable public
19
+ * contract every call site depends on until then (US-4).
20
+ */
21
+ export type AnalyticsMoney = Readonly<{
22
+ amount: number;
23
+ currencyCode: string;
24
+ }>;
25
+ export type AnalyticsLineItem = Readonly<{
26
+ sku: string;
27
+ name: string;
28
+ price: AnalyticsMoney;
29
+ quantity: number;
30
+ }>;
31
+ /** Dispatched by T7's CardEntry, before opening the transaction. */
32
+ export type AddPaymentInfoEvent = Readonly<{
33
+ name: 'add_payment_info';
34
+ value: AnalyticsMoney;
35
+ /**
36
+ * Derived from the selected method's `groupName` at the moment this fires (T140, Decision 5).
37
+ * Optional because the event fires on the cart total, before a method is necessarily selected —
38
+ * omitted rather than a guessed literal, so a downstream consumer never reads a false payment kind.
39
+ * `toEcommercePayload` below drops the corresponding key entirely when this is absent.
40
+ */
41
+ paymentType?: 'Credit Card' | 'Debit Card';
42
+ items?: readonly AnalyticsLineItem[];
43
+ }>;
44
+ /** Dispatched by T13's usePlaceOrder, after a successful gateway callback. */
45
+ export type PurchaseEvent = Readonly<{
46
+ name: 'purchase';
47
+ transactionId: string;
48
+ value: AnalyticsMoney;
49
+ items?: readonly AnalyticsLineItem[];
50
+ }>;
51
+ export type AnalyticsEvent = AddPaymentInfoEvent | PurchaseEvent;
52
+ export type AnalyticsActions = Readonly<{
53
+ /** Push a standard analytics event to window.dataLayer. Fire-and-forget; never throws. */
54
+ track: (event: AnalyticsEvent) => void;
55
+ }>;
56
+ //#endregion
57
+ //# sourceMappingURL=use-analytics-actions.d.ts.map
@@ -0,0 +1,108 @@
1
+ "use client";
2
+ import { defineActions } from "../../core/dist/actions/registry.js";
3
+ import "../../core/dist/index.js";
4
+ import { DEFAULT_ANALYTICS_DESTINATION, resolveAnalyticsDestination, useAnalyticsDestination } from "./analytics-destination.js";
5
+ import { useCallback, useMemo, useRef } from "react";
6
+ //#region src/sdk/analytics/use-analytics-actions.ts
7
+ function toEcommerceItems(items) {
8
+ return (items ?? []).map((item) => ({
9
+ item_id: item.sku,
10
+ item_name: item.name,
11
+ price: item.price.amount,
12
+ quantity: item.quantity
13
+ }));
14
+ }
15
+ function toEcommercePayload(event) {
16
+ if (event.name === "add_payment_info") return {
17
+ currency: event.value.currencyCode,
18
+ value: event.value.amount,
19
+ ...event.paymentType !== void 0 ? { payment_type: event.paymentType } : {},
20
+ items: toEcommerceItems(event.items)
21
+ };
22
+ return {
23
+ transaction_id: event.transactionId,
24
+ currency: event.value.currencyCode,
25
+ value: event.value.amount,
26
+ items: toEcommerceItems(event.items)
27
+ };
28
+ }
29
+ function pushToDataLayer(event, destination) {
30
+ if (typeof window === "undefined") return;
31
+ let layer = Reflect.get(window, destination);
32
+ if (layer === void 0) {
33
+ layer = [];
34
+ Reflect.set(window, destination, layer);
35
+ } else if (!Array.isArray(layer)) {
36
+ console.error(`[analytics.track] window.${destination} already exists and is not an array; the event was dropped`);
37
+ return;
38
+ }
39
+ layer.push({
40
+ event: event.name,
41
+ ecommerce: toEcommercePayload(event)
42
+ });
43
+ }
44
+ /**
45
+ * The `analytics` namespace hook. Registered with the first-party action registry via
46
+ * `analyticsActions` below; the compiler-emitted `AnalyticsActionProvider` calls it and threads
47
+ * the narrowed methods into each consumer's `$actions.analytics`. Dispatcher flavor: no
48
+ * `useMutation`, no cache read or write (ADR-0010). Fire-and-forget — `track` never throws, so a
49
+ * broken tag-manager script can never block payment submission or order placement.
50
+ */
51
+ function useAnalyticsActions() {
52
+ const override = useAnalyticsDestination();
53
+ const hasLoggedRejectionRef = useRef(false);
54
+ const track = useCallback((event) => {
55
+ if (typeof window === "undefined") return;
56
+ let destination = DEFAULT_ANALYTICS_DESTINATION;
57
+ try {
58
+ destination = resolveAnalyticsDestination({
59
+ override,
60
+ hasLoggedRejection: hasLoggedRejectionRef
61
+ });
62
+ pushToDataLayer(event, destination);
63
+ } catch (error) {
64
+ console.error(`[analytics.track] window.${destination} push failed`, error);
65
+ }
66
+ }, [override]);
67
+ return useMemo(() => ({ track }), [track]);
68
+ }
69
+ defineActions({
70
+ namespace: "analytics",
71
+ description: "Dispatcher-flavor namespace that pushes standard add_payment_info / purchase events to window.dataLayer. Never touches the Apollo cache.",
72
+ provider: {
73
+ name: "AnalyticsActionProvider",
74
+ importPath: "@vtex/faststore/internal/client"
75
+ },
76
+ methods: { track: {
77
+ description: "Push a standard analytics event (add_payment_info | purchase) to window.dataLayer. Fire-and-forget; never throws.",
78
+ payload: [
79
+ {
80
+ name: "name",
81
+ type: "string"
82
+ },
83
+ {
84
+ name: "currencyCode",
85
+ type: "string"
86
+ },
87
+ {
88
+ name: "amount",
89
+ type: "number"
90
+ },
91
+ {
92
+ name: "paymentType",
93
+ type: "string",
94
+ optional: true
95
+ },
96
+ {
97
+ name: "transactionId",
98
+ type: "string",
99
+ optional: true
100
+ }
101
+ ]
102
+ } },
103
+ use: useAnalyticsActions
104
+ });
105
+ //#endregion
106
+ export { useAnalyticsActions };
107
+
108
+ //# sourceMappingURL=use-analytics-actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-analytics-actions.js","names":[],"sources":["../../../src/sdk/analytics/use-analytics-actions.ts"],"sourcesContent":["'use client';\n\nimport { defineActions } from '@vtex/fs-core';\nimport { useCallback, useMemo, useRef } from 'react';\nimport {\n type AnalyticsDestination,\n DEFAULT_ANALYTICS_DESTINATION,\n resolveAnalyticsDestination,\n useAnalyticsDestination,\n} from './analytics-destination.js';\n\n/**\n * The `analytics` action namespace (specs/analytics-events.md) — a dispatcher-flavor namespace\n * (docs/storefront-core/adr-0010-actions-own-the-write-side.md; docs/storefront-core/rfc-actions.md\n * § \"Three binding flavors\") that pushes the two standard payment analytics events,\n * `add_payment_info` and `purchase`, to a `window` array — `window.dataLayer` by default, the\n * GTM/GA4-recognizable event convention. It never touches the Apollo cache, never issues a GraphQL\n * operation, and never throws: a broken tag-manager script can never block payment submission or\n * order placement.\n *\n * The destination array is configurable at build time\n * (specs/make-the-analytics-destination-configurable-for.md; T120) — see\n * `./analytics-destination.js` for the resolution precedence, validation, and the\n * `AnalyticsDestinationProvider`. The pushed entry's shape is a data *contract* (a well-known\n * browser-global array shape), not a *provider* — no vendor SDK, no server call. A future\n * platform/foundation epic may replace this sink with a real `AnalyticsContext`; the\n * `track(event: AnalyticsEvent): void` signature and `AnalyticsActions` type are the stable public\n * contract every call site depends on until then (US-4).\n */\n\nexport type AnalyticsMoney = Readonly<{\n amount: number;\n currencyCode: string;\n}>;\n\nexport type AnalyticsLineItem = Readonly<{\n sku: string;\n name: string;\n price: AnalyticsMoney;\n quantity: number;\n}>;\n\n/** Dispatched by T7's CardEntry, before opening the transaction. */\nexport type AddPaymentInfoEvent = Readonly<{\n name: 'add_payment_info';\n value: AnalyticsMoney;\n /**\n * Derived from the selected method's `groupName` at the moment this fires (T140, Decision 5).\n * Optional because the event fires on the cart total, before a method is necessarily selected —\n * omitted rather than a guessed literal, so a downstream consumer never reads a false payment kind.\n * `toEcommercePayload` below drops the corresponding key entirely when this is absent.\n */\n paymentType?: 'Credit Card' | 'Debit Card';\n items?: readonly AnalyticsLineItem[];\n}>;\n\n/** Dispatched by T13's usePlaceOrder, after a successful gateway callback. */\nexport type PurchaseEvent = Readonly<{\n name: 'purchase';\n transactionId: string;\n value: AnalyticsMoney;\n items?: readonly AnalyticsLineItem[];\n}>;\n\nexport type AnalyticsEvent = AddPaymentInfoEvent | PurchaseEvent;\n\nexport type AnalyticsActions = Readonly<{\n /** Push a standard analytics event to window.dataLayer. Fire-and-forget; never throws. */\n track: (event: AnalyticsEvent) => void;\n}>;\n\n/** The shape pushed onto window.dataLayer — GTM/GA4's own event convention. */\nexport type AnalyticsDataLayerEvent = Readonly<{\n event: 'add_payment_info' | 'purchase';\n ecommerce: Record<string, unknown>;\n}>;\n\nfunction toEcommerceItems(items: readonly AnalyticsLineItem[] | undefined) {\n return (items ?? []).map((item) => ({\n item_id: item.sku,\n item_name: item.name,\n price: item.price.amount,\n quantity: item.quantity,\n }));\n}\n\nfunction toEcommercePayload(event: AnalyticsEvent): Record<string, unknown> {\n if (event.name === 'add_payment_info') {\n return {\n currency: event.value.currencyCode,\n value: event.value.amount,\n // T140, Decision 5: the key itself must be absent when `paymentType` is, not merely `undefined`\n // — `pushToDataLayer` pushes this object as-is with no serialization step to strip it, and\n // `'payment_type' in ecommerce` would otherwise still report true.\n ...(event.paymentType !== undefined ? { payment_type: event.paymentType } : {}),\n items: toEcommerceItems(event.items),\n };\n }\n return {\n transaction_id: event.transactionId,\n currency: event.value.currencyCode,\n value: event.value.amount,\n items: toEcommerceItems(event.items),\n };\n}\n\n// `Reflect.get`/`Reflect.set` below match `storefront-provider.tsx`'s existing pattern for a\n// dynamic `window` key — they are not a security mechanism. `Reflect.set(target, k, v)` invokes\n// an inherited setter and creates no own property, exactly like `window[k] = v` would; it adds no\n// hardening on its own. What actually blocks prototype pollution is\n// `isValidAnalyticsDestination`'s denylist and identifier pattern, checked by the caller before\n// `destination` ever reaches this function, plus the non-array guard immediately below.\n//\n// The cast below, not a `declare global` augmentation of `Window`, is what keeps this typed: a\n// global augmentation here would ship inside this package's own `.d.ts` output and hand every\n// consumer's `window.dataLayer` this package's narrow event union, wrong for a store that also\n// pushes its own GTM events (packages/components/scripts/dist-type-boundary.test.ts). `destination`\n// is a runtime string anyway — `Window` has nothing to look up a dynamic key against — so the local\n// cast is also the only type-safe option, not merely the non-leaking one.\nfunction pushToDataLayer(event: AnalyticsEvent, destination: AnalyticsDestination): void {\n if (typeof window === 'undefined') return;\n\n let layer = Reflect.get(window, destination) as AnalyticsDataLayerEvent[] | undefined;\n if (layer === undefined) {\n layer = [];\n Reflect.set(window, destination, layer);\n } else if (!Array.isArray(layer)) {\n console.error(`[analytics.track] window.${destination} already exists and is not an array; the event was dropped`);\n return;\n }\n\n layer.push({ event: event.name, ecommerce: toEcommercePayload(event) });\n}\n\n/**\n * The `analytics` namespace hook. Registered with the first-party action registry via\n * `analyticsActions` below; the compiler-emitted `AnalyticsActionProvider` calls it and threads\n * the narrowed methods into each consumer's `$actions.analytics`. Dispatcher flavor: no\n * `useMutation`, no cache read or write (ADR-0010). Fire-and-forget — `track` never throws, so a\n * broken tag-manager script can never block payment submission or order placement.\n */\nexport function useAnalyticsActions(): AnalyticsActions {\n const override = useAnalyticsDestination();\n // Scoped to this hook instance, not the module: \"logs once\" means once per mounted\n // `useAnalyticsActions()`, so two independent call sites each still get their own first warning.\n const hasLoggedRejectionRef = useRef(false);\n\n const track = useCallback<AnalyticsActions['track']>(\n (event) => {\n // The SSR guard runs before any destination resolution is attempted — not just before the\n // write. Preserved from the pre-T120 behaviour (US-3, \"SSR — no destination resolution\n // attempted at all\").\n if (typeof window === 'undefined') return;\n let destination: AnalyticsDestination = DEFAULT_ANALYTICS_DESTINATION;\n try {\n destination = resolveAnalyticsDestination({\n override,\n hasLoggedRejection: hasLoggedRejectionRef,\n });\n pushToDataLayer(event, destination);\n } catch (error) {\n console.error(`[analytics.track] window.${destination} push failed`, error);\n }\n },\n [override],\n );\n\n return useMemo(() => ({ track }), [track]);\n}\n\n/**\n * Declares the `analytics` action namespace — the single source of truth for its method/payload\n * metadata, runtime provider, and `use` hook (mirrors `cartActions`, `shippingActions`). The\n * native catalog builder (`scripts/build-catalog.mjs`) statically reads this call to emit\n * `actions.json`; at runtime `AnalyticsActionProvider` calls `useAnalyticsActions` directly.\n *\n * The `payload` below is a flattened, best-effort scalar approximation of `AnalyticsEvent` for\n * catalog/docs tooling: `ActionPayloadField.type` supports only scalar primitives and cannot\n * express a discriminated union or a nested `items` array. The TS `AnalyticsEvent` union above is\n * the source of truth for the real call shape.\n */\nexport const analyticsActions = defineActions({\n namespace: 'analytics',\n description:\n 'Dispatcher-flavor namespace that pushes standard add_payment_info / purchase events to window.dataLayer. Never touches the Apollo cache.',\n provider: { name: 'AnalyticsActionProvider', importPath: '@vtex/faststore/internal/client' },\n methods: {\n track: {\n description:\n 'Push a standard analytics event (add_payment_info | purchase) to window.dataLayer. Fire-and-forget; never throws.',\n payload: [\n { name: 'name', type: 'string' },\n { name: 'currencyCode', type: 'string' },\n { name: 'amount', type: 'number' },\n { name: 'paymentType', type: 'string', optional: true },\n { name: 'transactionId', type: 'string', optional: true },\n ],\n },\n },\n use: useAnalyticsActions,\n});\n"],"mappings":";;;;;;AA6EA,SAAS,iBAAiB,OAAiD;CACzE,QAAQ,SAAS,CAAC,EAAA,CAAG,KAAK,UAAU;EAClC,SAAS,KAAK;EACd,WAAW,KAAK;EAChB,OAAO,KAAK,MAAM;EAClB,UAAU,KAAK;CACjB,EAAE;AACJ;AAEA,SAAS,mBAAmB,OAAgD;CAC1E,IAAI,MAAM,SAAS,oBACjB,OAAO;EACL,UAAU,MAAM,MAAM;EACtB,OAAO,MAAM,MAAM;EAInB,GAAI,MAAM,gBAAgB,KAAA,IAAY,EAAE,cAAc,MAAM,YAAY,IAAI,CAAC;EAC7E,OAAO,iBAAiB,MAAM,KAAK;CACrC;CAEF,OAAO;EACL,gBAAgB,MAAM;EACtB,UAAU,MAAM,MAAM;EACtB,OAAO,MAAM,MAAM;EACnB,OAAO,iBAAiB,MAAM,KAAK;CACrC;AACF;AAeA,SAAS,gBAAgB,OAAuB,aAAyC;CACvF,IAAI,OAAO,WAAW,aAAa;CAEnC,IAAI,QAAQ,QAAQ,IAAI,QAAQ,WAAW;CAC3C,IAAI,UAAU,KAAA,GAAW;EACvB,QAAQ,CAAC;EACT,QAAQ,IAAI,QAAQ,aAAa,KAAK;CACxC,OAAO,IAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;EAChC,QAAQ,MAAM,4BAA4B,YAAY,2DAA2D;EACjH;CACF;CAEA,MAAM,KAAK;EAAE,OAAO,MAAM;EAAM,WAAW,mBAAmB,KAAK;CAAE,CAAC;AACxE;;;;;;;;AASA,SAAgB,sBAAwC;CACtD,MAAM,WAAW,wBAAwB;CAGzC,MAAM,wBAAwB,OAAO,KAAK;CAE1C,MAAM,QAAQ,aACX,UAAU;EAIT,IAAI,OAAO,WAAW,aAAa;EACnC,IAAI,cAAoC;EACxC,IAAI;GACF,cAAc,4BAA4B;IACxC;IACA,oBAAoB;GACtB,CAAC;GACD,gBAAgB,OAAO,WAAW;EACpC,SAAS,OAAO;GACd,QAAQ,MAAM,4BAA4B,YAAY,eAAe,KAAK;EAC5E;CACF,GACA,CAAC,QAAQ,CACX;CAEA,OAAO,eAAe,EAAE,MAAM,IAAI,CAAC,KAAK,CAAC;AAC3C;AAagC,cAAc;CAC5C,WAAW;CACX,aACE;CACF,UAAU;EAAE,MAAM;EAA2B,YAAY;CAAkC;CAC3F,SAAS,EACP,OAAO;EACL,aACE;EACF,SAAS;GACP;IAAE,MAAM;IAAQ,MAAM;GAAS;GAC/B;IAAE,MAAM;IAAgB,MAAM;GAAS;GACvC;IAAE,MAAM;IAAU,MAAM;GAAS;GACjC;IAAE,MAAM;IAAe,MAAM;IAAU,UAAU;GAAK;GACtD;IAAE,MAAM;IAAiB,MAAM;IAAU,UAAU;GAAK;EAC1D;CACF,EACF;CACA,KAAK;AACP,CAAC"}
@@ -5,7 +5,7 @@ import { InMemoryCache } from "@apollo/client";
5
5
  * Per-entity normalization and field-merge rules for the Storefront cache.
6
6
  *
7
7
  * Empty in T1. Domain entries (Product, Cart, OrderForm, …) arrive with the
8
- * particles that need them — see specs/shared-apollo-sdk-surface.md,
8
+ * particles that need them — see docs/storefront-core/reference-free-particle-model.md § Typed documents and the shared cache,
9
9
  * "Out of Scope".
10
10
  */
11
11
  const typePolicies = {};
@@ -1 +1 @@
1
- {"version":3,"file":"storefront-cache.js","names":[],"sources":["../../../src/sdk/cache/storefront-cache.ts"],"sourcesContent":["import { InMemoryCache, type InMemoryCacheConfig, type TypePolicies } from '@apollo/client';\nimport { possibleTypes } from '../generated/fragment-types.js';\n\n/**\n * Per-entity normalization and field-merge rules for the Storefront cache.\n *\n * Empty in T1. Domain entries (Product, Cart, OrderForm, …) arrive with the\n * particles that need them — see specs/shared-apollo-sdk-surface.md,\n * \"Out of Scope\".\n */\nexport const typePolicies: TypePolicies = {};\n\nexport { possibleTypes };\n\n/**\n * The single source of truth for InMemoryCache configuration. Both the\n * server-side `createClient` and the client-side `StorefrontProvider`\n * consume this so SSR and CSR normalize entities identically.\n */\nexport function getCacheConfig(): InMemoryCacheConfig {\n return {\n typePolicies,\n possibleTypes,\n };\n}\n\n/**\n * The only place an `InMemoryCache` is constructed on the server path.\n * The client-side provider builds its cache from `getCacheConfig()` so the\n * config is shared verbatim without coupling to a specific InMemoryCache\n * subclass (the Next.js integration ships its own SSR-aware variant).\n */\nexport function buildCache(): InMemoryCache {\n return new InMemoryCache(getCacheConfig());\n}\n"],"mappings":";;;;;;;;;;AAUA,MAAa,eAA6B,CAAC;;;;;;AAS3C,SAAgB,iBAAsC;CACpD,OAAO;EACL;EACA;CACF;AACF;;;;;;;AAQA,SAAgB,aAA4B;CAC1C,OAAO,IAAI,cAAc,eAAe,CAAC;AAC3C"}
1
+ {"version":3,"file":"storefront-cache.js","names":[],"sources":["../../../src/sdk/cache/storefront-cache.ts"],"sourcesContent":["import { InMemoryCache, type InMemoryCacheConfig, type TypePolicies } from '@apollo/client';\nimport { possibleTypes } from '../generated/fragment-types.js';\n\n/**\n * Per-entity normalization and field-merge rules for the Storefront cache.\n *\n * Empty in T1. Domain entries (Product, Cart, OrderForm, …) arrive with the\n * particles that need them — see docs/storefront-core/reference-free-particle-model.md § Typed documents and the shared cache,\n * \"Out of Scope\".\n */\nexport const typePolicies: TypePolicies = {};\n\nexport { possibleTypes };\n\n/**\n * The single source of truth for InMemoryCache configuration. Both the\n * server-side `createClient` and the client-side `StorefrontProvider`\n * consume this so SSR and CSR normalize entities identically.\n */\nexport function getCacheConfig(): InMemoryCacheConfig {\n return {\n typePolicies,\n possibleTypes,\n };\n}\n\n/**\n * The only place an `InMemoryCache` is constructed on the server path.\n * The client-side provider builds its cache from `getCacheConfig()` so the\n * config is shared verbatim without coupling to a specific InMemoryCache\n * subclass (the Next.js integration ships its own SSR-aware variant).\n */\nexport function buildCache(): InMemoryCache {\n return new InMemoryCache(getCacheConfig());\n}\n"],"mappings":";;;;;;;;;;AAUA,MAAa,eAA6B,CAAC;;;;;;AAS3C,SAAgB,iBAAsC;CACpD,OAAO;EACL;EACA;CACF;AACF;;;;;;;AAQA,SAAgB,aAA4B;CAC1C,OAAO,IAAI,cAAc,eAAe,CAAC;AAC3C"}