@shopify/hydrogen 2026.10.0-preview.2 → 2026.10.0-preview.4

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 (404) hide show
  1. package/README.md +34 -3
  2. package/dist/cli/index.mjs +578 -85
  3. package/dist/client/client.mjs +2 -2
  4. package/dist/client/errors.d.mts +19 -19
  5. package/dist/client/errors.mjs +19 -16
  6. package/dist/client/errors.mjs.map +1 -1
  7. package/dist/client/types.d.mts +91 -10
  8. package/dist/core/analytics/cart-tracker.d.mts +14 -0
  9. package/dist/core/analytics/cart-tracker.mjs +15 -1
  10. package/dist/core/analytics/cart-tracker.mjs.map +1 -1
  11. package/dist/core/analytics/custom-consent.mjs +12 -0
  12. package/dist/core/analytics/custom-consent.mjs.map +1 -0
  13. package/dist/core/analytics/events.d.mts +7 -0
  14. package/dist/core/analytics/events.mjs +7 -0
  15. package/dist/core/analytics/events.mjs.map +1 -1
  16. package/dist/core/analytics/index.d.mts +1 -1
  17. package/dist/core/analytics/types.d.mts +152 -16
  18. package/dist/core/cart/actions.d.mts +47 -3
  19. package/dist/core/cart/actions.mjs +29 -0
  20. package/dist/core/cart/actions.mjs.map +1 -1
  21. package/dist/core/cart/attach-quantity-input.d.mts +26 -0
  22. package/dist/core/cart/attach-quantity-input.mjs +26 -0
  23. package/dist/core/cart/attach-quantity-input.mjs.map +1 -1
  24. package/dist/core/cart/cart.d.mts +106 -6
  25. package/dist/core/cart/cart.mjs +57 -6
  26. package/dist/core/cart/cart.mjs.map +1 -1
  27. package/dist/core/cart/cookie.d.mts +15 -0
  28. package/dist/core/cart/cookie.mjs +15 -0
  29. package/dist/core/cart/cookie.mjs.map +1 -1
  30. package/dist/core/cart/form.d.mts +61 -0
  31. package/dist/core/cart/form.mjs +18 -0
  32. package/dist/core/cart/form.mjs.map +1 -1
  33. package/dist/core/cart/get-cart.d.mts +43 -2
  34. package/dist/core/cart/get-cart.mjs +33 -0
  35. package/dist/core/cart/get-cart.mjs.map +1 -1
  36. package/dist/core/cart/index.d.mts +1 -1
  37. package/dist/core/cart/quantity.d.mts +17 -0
  38. package/dist/core/cart/quantity.mjs +17 -0
  39. package/dist/core/cart/quantity.mjs.map +1 -1
  40. package/dist/core/cart/queries.d.mts +402 -369
  41. package/dist/core/cart/queries.mjs +2 -1
  42. package/dist/core/cart/queries.mjs.map +1 -1
  43. package/dist/core/cart/server-handlers.d.mts +69 -0
  44. package/dist/core/cart/server-handlers.mjs +2 -10
  45. package/dist/core/cart/server-handlers.mjs.map +1 -1
  46. package/dist/core/cart/state.d.mts +133 -0
  47. package/dist/core/cart/state.mjs +8 -0
  48. package/dist/core/cart/state.mjs.map +1 -1
  49. package/dist/core/collection/collection.d.mts +18 -2
  50. package/dist/core/collection/collection.mjs +11 -0
  51. package/dist/core/collection/collection.mjs.map +1 -1
  52. package/dist/core/collection/index.d.mts +1 -1
  53. package/dist/core/collection/reconciler.d.mts +13 -4
  54. package/dist/core/collection/reconciler.mjs.map +1 -1
  55. package/dist/core/collection/state.d.mts +7 -2
  56. package/dist/core/collection/state.mjs.map +1 -1
  57. package/dist/core/collection/url.d.mts +3 -0
  58. package/dist/core/collection/url.mjs.map +1 -1
  59. package/dist/core/constants.d.mts +1 -1
  60. package/dist/core/constants.mjs +2 -2
  61. package/dist/core/constants.mjs.map +1 -1
  62. package/dist/core/headers.mjs +2 -2
  63. package/dist/core/headers.mjs.map +1 -1
  64. package/dist/core/index.d.mts +5 -5
  65. package/dist/core/logging/logging.mjs.map +1 -1
  66. package/dist/core/money/format.mjs +6 -3
  67. package/dist/core/money/format.mjs.map +1 -1
  68. package/dist/core/observable.mjs +0 -3
  69. package/dist/core/observable.mjs.map +1 -1
  70. package/dist/core/predictive-search/form.d.mts +1 -0
  71. package/dist/core/predictive-search/form.mjs +1 -0
  72. package/dist/core/predictive-search/form.mjs.map +1 -1
  73. package/dist/core/predictive-search/index.d.mts +1 -1
  74. package/dist/core/predictive-search/queries.d.mts +40 -4
  75. package/dist/core/predictive-search/queries.mjs +7 -1
  76. package/dist/core/predictive-search/queries.mjs.map +1 -1
  77. package/dist/core/predictive-search/search.d.mts +43 -10
  78. package/dist/core/predictive-search/search.mjs +34 -0
  79. package/dist/core/predictive-search/search.mjs.map +1 -1
  80. package/dist/core/predictive-search/server-handlers.d.mts +31 -5
  81. package/dist/core/predictive-search/server-handlers.mjs +5 -3
  82. package/dist/core/predictive-search/server-handlers.mjs.map +1 -1
  83. package/dist/core/predictive-search/store.d.mts +3 -1
  84. package/dist/core/predictive-search/store.mjs.map +1 -1
  85. package/dist/core/predictive-search/url.d.mts +50 -8
  86. package/dist/core/predictive-search/url.mjs +9 -0
  87. package/dist/core/predictive-search/url.mjs.map +1 -1
  88. package/dist/core/product/form.d.mts +21 -2
  89. package/dist/core/product/form.mjs +13 -0
  90. package/dist/core/product/form.mjs.map +1 -1
  91. package/dist/core/product/index.d.mts +1 -1
  92. package/dist/core/product/options.d.mts +2 -2
  93. package/dist/core/product/options.mjs +2 -2
  94. package/dist/core/product/options.mjs.map +1 -1
  95. package/dist/core/product/product-form.d.mts +33 -1
  96. package/dist/core/product/product-form.mjs +30 -0
  97. package/dist/core/product/product-form.mjs.map +1 -1
  98. package/dist/core/product/state.d.mts +41 -0
  99. package/dist/core/product/url.d.mts +6 -0
  100. package/dist/core/product/url.mjs.map +1 -1
  101. package/dist/core/request-context.d.mts +8 -5
  102. package/dist/core/request-context.mjs +17 -39
  103. package/dist/core/request-context.mjs.map +1 -1
  104. package/dist/core/request-routing/handle-shopify-routes.mjs +4 -1
  105. package/dist/core/request-routing/handle-shopify-routes.mjs.map +1 -1
  106. package/dist/core/request-routing/interceptors/ajax-api.mjs +1 -1
  107. package/dist/core/request-routing/interceptors/api-proxy.mjs +1 -1
  108. package/dist/core/request-routing/interceptors/checkout.mjs +22 -6
  109. package/dist/core/request-routing/interceptors/checkout.mjs.map +1 -1
  110. package/dist/core/request-routing/interceptors/mcp-proxy.mjs +1 -1
  111. package/dist/core/request-routing/interceptors/proxy.mjs +36 -10
  112. package/dist/core/request-routing/interceptors/proxy.mjs.map +1 -1
  113. package/dist/core/request-routing/interceptors/query-param-redirect.mjs +5 -11
  114. package/dist/core/request-routing/interceptors/query-param-redirect.mjs.map +1 -1
  115. package/dist/core/request-routing/interceptors/sfapi-proxy.mjs +19 -1
  116. package/dist/core/request-routing/interceptors/sfapi-proxy.mjs.map +1 -1
  117. package/dist/core/request-routing/interceptors/ucp-mcp-proxy.mjs +35 -0
  118. package/dist/core/request-routing/interceptors/ucp-mcp-proxy.mjs.map +1 -0
  119. package/dist/core/request-routing/interceptors/well-known.mjs +1 -1
  120. package/dist/core/shopify-scripts/analytics.mjs +2 -2
  121. package/dist/core/shopify-scripts/analytics.mjs.map +1 -1
  122. package/dist/core/shopify-scripts/constants.mjs +4 -2
  123. package/dist/core/shopify-scripts/constants.mjs.map +1 -1
  124. package/dist/core/shopify-scripts/global.mjs +9 -4
  125. package/dist/core/shopify-scripts/global.mjs.map +1 -1
  126. package/dist/core/shopify-scripts/index.d.mts +1 -0
  127. package/dist/core/shopify-scripts/index.mjs +14 -12
  128. package/dist/core/shopify-scripts/index.mjs.map +1 -1
  129. package/dist/core/shopify-scripts/initialize.d.mts +1 -0
  130. package/dist/core/shopify-scripts/initialize.mjs +10 -3
  131. package/dist/core/shopify-scripts/initialize.mjs.map +1 -1
  132. package/dist/core/shopify-scripts/types.d.mts +6 -0
  133. package/dist/core/url.mjs +21 -2
  134. package/dist/core/url.mjs.map +1 -1
  135. package/dist/customer-account/client.d.mts +128 -4
  136. package/dist/customer-account/client.mjs +27 -1
  137. package/dist/customer-account/client.mjs.map +1 -1
  138. package/dist/customer-account/errors.d.mts +46 -0
  139. package/dist/customer-account/errors.mjs +46 -0
  140. package/dist/customer-account/errors.mjs.map +1 -1
  141. package/dist/customer-account/graphql.d.mts +68 -0
  142. package/dist/customer-account/graphql.mjs +47 -0
  143. package/dist/customer-account/graphql.mjs.map +1 -1
  144. package/dist/customer-account/session.d.mts +114 -23
  145. package/dist/customer-account/session.mjs +27 -12
  146. package/dist/customer-account/session.mjs.map +1 -1
  147. package/dist/customer-account/type-resolver.d.mts +23 -0
  148. package/dist/customer-account-api-types.d.ts +570 -374
  149. package/dist/customer-account.schema.json +2981 -1527
  150. package/dist/development/client/client.mjs +2 -2
  151. package/dist/development/client/errors.d.mts +19 -19
  152. package/dist/development/client/errors.mjs +20 -20
  153. package/dist/development/client/errors.mjs.map +1 -1
  154. package/dist/development/client/types.d.mts +91 -10
  155. package/dist/development/core/analytics/cart-tracker.d.mts +14 -0
  156. package/dist/development/core/analytics/cart-tracker.mjs +15 -1
  157. package/dist/development/core/analytics/cart-tracker.mjs.map +1 -1
  158. package/dist/development/core/analytics/custom-consent.mjs +12 -0
  159. package/dist/development/core/analytics/custom-consent.mjs.map +1 -0
  160. package/dist/development/core/analytics/events.d.mts +7 -0
  161. package/dist/development/core/analytics/events.mjs +7 -0
  162. package/dist/development/core/analytics/events.mjs.map +1 -1
  163. package/dist/development/core/analytics/index.d.mts +1 -1
  164. package/dist/development/core/analytics/types.d.mts +152 -16
  165. package/dist/development/core/cart/actions.d.mts +47 -3
  166. package/dist/development/core/cart/actions.mjs +29 -0
  167. package/dist/development/core/cart/actions.mjs.map +1 -1
  168. package/dist/development/core/cart/attach-quantity-input.d.mts +26 -0
  169. package/dist/development/core/cart/attach-quantity-input.mjs +26 -0
  170. package/dist/development/core/cart/attach-quantity-input.mjs.map +1 -1
  171. package/dist/development/core/cart/cart.d.mts +106 -6
  172. package/dist/development/core/cart/cart.mjs +57 -6
  173. package/dist/development/core/cart/cart.mjs.map +1 -1
  174. package/dist/development/core/cart/cookie.d.mts +15 -0
  175. package/dist/development/core/cart/cookie.mjs +15 -0
  176. package/dist/development/core/cart/cookie.mjs.map +1 -1
  177. package/dist/development/core/cart/form.d.mts +61 -0
  178. package/dist/development/core/cart/form.mjs +18 -0
  179. package/dist/development/core/cart/form.mjs.map +1 -1
  180. package/dist/development/core/cart/get-cart.d.mts +43 -2
  181. package/dist/development/core/cart/get-cart.mjs +33 -0
  182. package/dist/development/core/cart/get-cart.mjs.map +1 -1
  183. package/dist/development/core/cart/index.d.mts +1 -1
  184. package/dist/development/core/cart/quantity.d.mts +17 -0
  185. package/dist/development/core/cart/quantity.mjs +17 -0
  186. package/dist/development/core/cart/quantity.mjs.map +1 -1
  187. package/dist/development/core/cart/queries.d.mts +345 -312
  188. package/dist/development/core/cart/queries.mjs +2 -1
  189. package/dist/development/core/cart/queries.mjs.map +1 -1
  190. package/dist/development/core/cart/server-handlers.d.mts +69 -0
  191. package/dist/development/core/cart/server-handlers.mjs +2 -10
  192. package/dist/development/core/cart/server-handlers.mjs.map +1 -1
  193. package/dist/development/core/cart/state.d.mts +133 -0
  194. package/dist/development/core/cart/state.mjs +8 -0
  195. package/dist/development/core/cart/state.mjs.map +1 -1
  196. package/dist/development/core/collection/collection.d.mts +18 -2
  197. package/dist/development/core/collection/collection.mjs +11 -0
  198. package/dist/development/core/collection/collection.mjs.map +1 -1
  199. package/dist/development/core/collection/index.d.mts +1 -1
  200. package/dist/development/core/collection/reconciler.d.mts +13 -4
  201. package/dist/development/core/collection/reconciler.mjs.map +1 -1
  202. package/dist/development/core/collection/state.d.mts +7 -2
  203. package/dist/development/core/collection/state.mjs.map +1 -1
  204. package/dist/development/core/collection/url.d.mts +3 -0
  205. package/dist/development/core/collection/url.mjs.map +1 -1
  206. package/dist/development/core/constants.mjs +1 -1
  207. package/dist/development/core/constants.mjs.map +1 -1
  208. package/dist/development/core/development.d.mts +5 -5
  209. package/dist/development/core/headers.mjs +2 -2
  210. package/dist/development/core/headers.mjs.map +1 -1
  211. package/dist/development/core/index.d.mts +4 -4
  212. package/dist/development/core/logging/logging.mjs.map +1 -1
  213. package/dist/development/core/money/format.mjs +6 -3
  214. package/dist/development/core/money/format.mjs.map +1 -1
  215. package/dist/development/core/observable.mjs +0 -3
  216. package/dist/development/core/observable.mjs.map +1 -1
  217. package/dist/development/core/predictive-search/form.d.mts +1 -0
  218. package/dist/development/core/predictive-search/form.mjs +1 -0
  219. package/dist/development/core/predictive-search/form.mjs.map +1 -1
  220. package/dist/development/core/predictive-search/index.d.mts +1 -1
  221. package/dist/development/core/predictive-search/queries.d.mts +38 -2
  222. package/dist/development/core/predictive-search/queries.mjs +7 -1
  223. package/dist/development/core/predictive-search/queries.mjs.map +1 -1
  224. package/dist/development/core/predictive-search/search.d.mts +43 -10
  225. package/dist/development/core/predictive-search/search.mjs +34 -0
  226. package/dist/development/core/predictive-search/search.mjs.map +1 -1
  227. package/dist/development/core/predictive-search/server-handlers.d.mts +31 -5
  228. package/dist/development/core/predictive-search/server-handlers.mjs +5 -3
  229. package/dist/development/core/predictive-search/server-handlers.mjs.map +1 -1
  230. package/dist/development/core/predictive-search/store.d.mts +3 -1
  231. package/dist/development/core/predictive-search/store.mjs.map +1 -1
  232. package/dist/development/core/predictive-search/url.d.mts +50 -8
  233. package/dist/development/core/predictive-search/url.mjs +9 -0
  234. package/dist/development/core/predictive-search/url.mjs.map +1 -1
  235. package/dist/development/core/product/form.d.mts +21 -2
  236. package/dist/development/core/product/form.mjs +13 -0
  237. package/dist/development/core/product/form.mjs.map +1 -1
  238. package/dist/development/core/product/index.d.mts +1 -1
  239. package/dist/development/core/product/options.d.mts +2 -2
  240. package/dist/development/core/product/options.mjs +2 -2
  241. package/dist/development/core/product/options.mjs.map +1 -1
  242. package/dist/development/core/product/product-form.d.mts +33 -1
  243. package/dist/development/core/product/product-form.mjs +30 -0
  244. package/dist/development/core/product/product-form.mjs.map +1 -1
  245. package/dist/development/core/product/state.d.mts +41 -0
  246. package/dist/development/core/product/url.d.mts +6 -0
  247. package/dist/development/core/product/url.mjs.map +1 -1
  248. package/dist/development/core/request-context.d.mts +8 -5
  249. package/dist/development/core/request-context.mjs +17 -39
  250. package/dist/development/core/request-context.mjs.map +1 -1
  251. package/dist/development/core/request-routing/handle-shopify-routes.mjs +4 -1
  252. package/dist/development/core/request-routing/handle-shopify-routes.mjs.map +1 -1
  253. package/dist/development/core/request-routing/interceptors/ajax-api.mjs +1 -1
  254. package/dist/development/core/request-routing/interceptors/api-proxy.mjs +1 -1
  255. package/dist/development/core/request-routing/interceptors/checkout.mjs +22 -6
  256. package/dist/development/core/request-routing/interceptors/checkout.mjs.map +1 -1
  257. package/dist/development/core/request-routing/interceptors/mcp-proxy.mjs +1 -1
  258. package/dist/development/core/request-routing/interceptors/proxy.mjs +36 -10
  259. package/dist/development/core/request-routing/interceptors/proxy.mjs.map +1 -1
  260. package/dist/development/core/request-routing/interceptors/query-param-redirect.mjs +5 -11
  261. package/dist/development/core/request-routing/interceptors/query-param-redirect.mjs.map +1 -1
  262. package/dist/development/core/request-routing/interceptors/sfapi-proxy.mjs +19 -1
  263. package/dist/development/core/request-routing/interceptors/sfapi-proxy.mjs.map +1 -1
  264. package/dist/development/core/request-routing/interceptors/ucp-mcp-proxy.mjs +35 -0
  265. package/dist/development/core/request-routing/interceptors/ucp-mcp-proxy.mjs.map +1 -0
  266. package/dist/development/core/request-routing/interceptors/well-known.mjs +1 -1
  267. package/dist/development/core/shopify-scripts/analytics.mjs +2 -2
  268. package/dist/development/core/shopify-scripts/analytics.mjs.map +1 -1
  269. package/dist/development/core/shopify-scripts/constants.mjs +4 -2
  270. package/dist/development/core/shopify-scripts/constants.mjs.map +1 -1
  271. package/dist/development/core/shopify-scripts/global.mjs +9 -4
  272. package/dist/development/core/shopify-scripts/global.mjs.map +1 -1
  273. package/dist/development/core/shopify-scripts/index.d.mts +1 -0
  274. package/dist/development/core/shopify-scripts/index.mjs +14 -12
  275. package/dist/development/core/shopify-scripts/index.mjs.map +1 -1
  276. package/dist/development/core/shopify-scripts/initialize.d.mts +1 -0
  277. package/dist/development/core/shopify-scripts/initialize.mjs +10 -3
  278. package/dist/development/core/shopify-scripts/initialize.mjs.map +1 -1
  279. package/dist/development/core/shopify-scripts/types.d.mts +6 -0
  280. package/dist/development/core/url.mjs +21 -2
  281. package/dist/development/core/url.mjs.map +1 -1
  282. package/dist/development/customer-account/session.d.mts +69 -13
  283. package/dist/development/customer-account/session.mjs +4 -0
  284. package/dist/development/customer-account/session.mjs.map +1 -1
  285. package/dist/development/globals.d.mts +6 -5
  286. package/dist/development/graphql/generated/graphql-env.d.mts +459 -16
  287. package/dist/development/graphql/generated/storefront-api-types.d.mts +1 -1
  288. package/dist/development/graphql/graphql.d.mts +33 -0
  289. package/dist/development/graphql/graphql.mjs +30 -0
  290. package/dist/development/graphql/graphql.mjs.map +1 -1
  291. package/dist/development/graphql/type-resolver.d.mts +14 -0
  292. package/dist/development/react/cart.d.mts +85 -14
  293. package/dist/development/react/cart.mjs +123 -3
  294. package/dist/development/react/cart.mjs.map +1 -1
  295. package/dist/development/react/collection.d.mts +2 -4
  296. package/dist/development/react/collection.mjs.map +1 -1
  297. package/dist/development/react/index.d.mts +8 -6
  298. package/dist/development/react/index.mjs +2 -2
  299. package/dist/development/react/predictive-search.d.mts +68 -7
  300. package/dist/development/react/predictive-search.mjs +54 -12
  301. package/dist/development/react/predictive-search.mjs.map +1 -1
  302. package/dist/development/react/product.d.mts +1 -0
  303. package/dist/development/react/product.mjs +5 -2
  304. package/dist/development/react/product.mjs.map +1 -1
  305. package/dist/development/react/shopify-scripts.mjs +1 -0
  306. package/dist/development/react/shopify-scripts.mjs.map +1 -1
  307. package/dist/development/vue/cart.d.mts +85 -6
  308. package/dist/development/vue/cart.mjs +95 -0
  309. package/dist/development/vue/cart.mjs.map +1 -1
  310. package/dist/development/vue/collection.d.mts +83 -5
  311. package/dist/development/vue/collection.mjs +52 -0
  312. package/dist/development/vue/collection.mjs.map +1 -1
  313. package/dist/development/vue/index.d.mts +6 -4
  314. package/dist/development/vue/predictive-search.d.mts +53 -6
  315. package/dist/development/vue/predictive-search.mjs +33 -0
  316. package/dist/development/vue/predictive-search.mjs.map +1 -1
  317. package/dist/development/vue/product.d.mts +6 -2
  318. package/dist/development/vue/product.mjs.map +1 -1
  319. package/dist/development/vue/shopify-scripts.d.mts +30 -3
  320. package/dist/development/vue/shopify-scripts.mjs +6 -0
  321. package/dist/development/vue/shopify-scripts.mjs.map +1 -1
  322. package/dist/globals.d.mts +6 -5
  323. package/dist/graphql/generated/customer-account-graphql-env.d.mts +1717 -1090
  324. package/dist/graphql/generated/graphql-env.d.mts +459 -16
  325. package/dist/graphql/generated/storefront-api-types.d.mts +1 -1
  326. package/dist/graphql/graphql.d.mts +33 -0
  327. package/dist/graphql/graphql.mjs +30 -0
  328. package/dist/graphql/graphql.mjs.map +1 -1
  329. package/dist/graphql/type-resolver.d.mts +14 -0
  330. package/dist/react/cart.d.mts +85 -14
  331. package/dist/react/cart.mjs +123 -3
  332. package/dist/react/cart.mjs.map +1 -1
  333. package/dist/react/collection.d.mts +2 -4
  334. package/dist/react/collection.mjs.map +1 -1
  335. package/dist/react/index.d.mts +8 -6
  336. package/dist/react/index.mjs +2 -2
  337. package/dist/react/predictive-search.d.mts +68 -7
  338. package/dist/react/predictive-search.mjs +54 -12
  339. package/dist/react/predictive-search.mjs.map +1 -1
  340. package/dist/react/product.d.mts +1 -0
  341. package/dist/react/product.mjs +5 -2
  342. package/dist/react/product.mjs.map +1 -1
  343. package/dist/react/shopify-scripts.mjs +1 -0
  344. package/dist/react/shopify-scripts.mjs.map +1 -1
  345. package/dist/storefront-api-types.d.ts +165 -20
  346. package/dist/storefront.schema.json +782 -57
  347. package/dist/vite/customer-account.mjs +191 -0
  348. package/dist/vite/customer-account.mjs.map +1 -0
  349. package/dist/vite/local-https.mjs +13 -29
  350. package/dist/vite/local-https.mjs.map +1 -1
  351. package/dist/vite/mkcert.mjs +1 -1
  352. package/dist/vue/cart.d.mts +85 -6
  353. package/dist/vue/cart.mjs +95 -0
  354. package/dist/vue/cart.mjs.map +1 -1
  355. package/dist/vue/collection.d.mts +83 -5
  356. package/dist/vue/collection.mjs +52 -0
  357. package/dist/vue/collection.mjs.map +1 -1
  358. package/dist/vue/index.d.mts +6 -4
  359. package/dist/vue/predictive-search.d.mts +53 -6
  360. package/dist/vue/predictive-search.mjs +33 -0
  361. package/dist/vue/predictive-search.mjs.map +1 -1
  362. package/dist/vue/product.d.mts +6 -2
  363. package/dist/vue/product.mjs.map +1 -1
  364. package/dist/vue/shopify-scripts.d.mts +31 -4
  365. package/dist/vue/shopify-scripts.mjs +6 -0
  366. package/dist/vue/shopify-scripts.mjs.map +1 -1
  367. package/package.json +5 -2
  368. package/skills/hydrogen-analytics/SKILL.md +6 -5
  369. package/skills/hydrogen-analytics/references/custom-consent.md +52 -0
  370. package/skills/hydrogen-analytics/references/react.md +1 -1
  371. package/skills/hydrogen-cart-metafields/SKILL.md +133 -0
  372. package/skills/hydrogen-cart-ui/SKILL.md +2 -1
  373. package/skills/hydrogen-customer-account/SKILL.md +3 -3
  374. package/skills/hydrogen-local-https/SKILL.md +22 -7
  375. package/skills/hydrogen-request-handlers/SKILL.md +5 -5
  376. package/skills/hydrogen-request-handlers/references/nuxt.md +0 -6
  377. package/skills/hydrogen-setup/references/analytics.md +24 -23
  378. package/skills/hydrogen-setup/steps/1-inspect-app.md +1 -1
  379. package/skills/hydrogen-setup/steps/11-verify.md +1 -0
  380. package/skills/hydrogen-setup/steps/2-scaffold.md +22 -1
  381. package/skills/hydrogen-smoke-test/SKILL.md +2 -2
  382. package/skills/hydrogen-storefront-client/SKILL.md +4 -2
  383. package/skills/hydrogen-variant-form/SKILL.md +10 -4
  384. package/ts-plugin/package.json +5 -0
  385. package/dist/core/shopify-scripts/consent.mjs +0 -17
  386. package/dist/core/shopify-scripts/consent.mjs.map +0 -1
  387. package/dist/core/shopify-scripts/deprecated-cookies.mjs +0 -97
  388. package/dist/core/shopify-scripts/deprecated-cookies.mjs.map +0 -1
  389. package/dist/core/shopify-scripts/utils/cookie-domain.mjs +0 -43
  390. package/dist/core/shopify-scripts/utils/cookie-domain.mjs.map +0 -1
  391. package/dist/core/shopify-scripts/utils/tracking-values.mjs +0 -65
  392. package/dist/core/shopify-scripts/utils/tracking-values.mjs.map +0 -1
  393. package/dist/core/shopify-scripts/utils/uuid.mjs +0 -17
  394. package/dist/core/shopify-scripts/utils/uuid.mjs.map +0 -1
  395. package/dist/development/core/shopify-scripts/consent.mjs +0 -17
  396. package/dist/development/core/shopify-scripts/consent.mjs.map +0 -1
  397. package/dist/development/core/shopify-scripts/deprecated-cookies.mjs +0 -97
  398. package/dist/development/core/shopify-scripts/deprecated-cookies.mjs.map +0 -1
  399. package/dist/development/core/shopify-scripts/utils/cookie-domain.mjs +0 -43
  400. package/dist/development/core/shopify-scripts/utils/cookie-domain.mjs.map +0 -1
  401. package/dist/development/core/shopify-scripts/utils/tracking-values.mjs +0 -65
  402. package/dist/development/core/shopify-scripts/utils/tracking-values.mjs.map +0 -1
  403. package/dist/development/core/shopify-scripts/utils/uuid.mjs +0 -17
  404. package/dist/development/core/shopify-scripts/utils/uuid.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"checkout.mjs","names":[],"sources":["../../../../../src/core/request-routing/interceptors/checkout.ts"],"sourcesContent":["import type { StorefrontClient } from \"../../../client\";\nimport { getCart, getCartId } from \"../../cart/get-cart\";\nimport { getLogger } from \"../../logging\";\nimport { CHECKOUT_RE, isHydrogenServerHandoffPath } from \"../../url\";\nimport type { HydrogenRouteInterceptor } from \"../route-types\";\n\nconst log = getLogger(\"checkout\");\nconst MOCK_SHOP_CART_PERMALINK_ORIGIN = \"https://demostore.mock.shop\";\n\nexport const handleCheckoutRedirect: HydrogenRouteInterceptor = (\n url,\n { request, storefrontClient },\n) => {\n if (!isHydrogenServerHandoffPath(url.pathname)) {\n return null;\n }\n\n if (request.method !== \"GET\" && request.method !== \"HEAD\") {\n return Promise.resolve(new Response(\"Method Not Allowed\", { status: 405 }));\n }\n\n const redirectUrlPromise = CHECKOUT_RE.test(url.pathname)\n ? getCheckoutRedirectUrl(request, storefrontClient)\n : getCartRedirectUrl(request, storefrontClient);\n\n return redirectUrlPromise\n .then((redirectUrl) => {\n if (redirectUrl.pathname !== \"/\") {\n mergeSearchParams(redirectUrl, url.searchParams);\n redirectUrl.searchParams.set(\"payment\", url.searchParams.get(\"payment\") ?? \"shop_pay\");\n }\n\n return new Response(null, {\n status: 302,\n headers: { location: redirectUrl.toString() },\n });\n })\n .catch((error) => {\n log.error(\"checkout redirect request failed\", { error });\n const message = error instanceof Error ? error.message : \"Internal redirect error\";\n\n return new Response(JSON.stringify({ error: message }), {\n status: 502,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n};\n\nasync function getCheckoutRedirectUrl(\n request: Request,\n storefrontClient: StorefrontClient,\n): Promise<URL> {\n const cartId = getCartId(request);\n if (!cartId) return new URL(\"/\", request.url);\n\n const result = await getCart(cartId, storefrontClient);\n return result.cart?.checkoutUrl ? new URL(result.cart.checkoutUrl) : new URL(\"/\", request.url);\n}\n\nasync function getCartRedirectUrl(\n request: Request,\n storefrontClient: StorefrontClient,\n): Promise<URL> {\n const sourceUrl = new URL(request.url);\n const redirectUrl = new URL(\n sourceUrl.pathname,\n getCartPermalinkOrigin(storefrontClient.storeUrl),\n );\n\n const cartId = getCartId(request);\n if (!cartId) return redirectUrl;\n\n try {\n const result = await getCart(cartId, storefrontClient);\n if (result.cart?.checkoutUrl) {\n mergeSearchParams(redirectUrl, new URL(result.cart.checkoutUrl).searchParams);\n }\n } catch (error) {\n log.warn(\"checkout redirect could not load cart permalink tracking params\", { error });\n }\n\n return redirectUrl;\n}\n\nfunction getCartPermalinkOrigin(storeUrl: string): string {\n const url = new URL(storeUrl);\n return url.hostname === \"mock.shop\" ? MOCK_SHOP_CART_PERMALINK_ORIGIN : url.origin;\n}\n\nfunction mergeSearchParams(target: URL, source: URLSearchParams): void {\n for (const [key, value] of source) {\n if (!target.searchParams.has(key)) target.searchParams.append(key, value);\n }\n}\n"],"mappings":";;;;;AAMA,MAAM,MAAM,UAAU,WAAW;AACjC,MAAM,kCAAkC;AAExC,MAAa,0BACX,KACA,EAAE,SAAS,uBACR;AACH,KAAI,CAAC,4BAA4B,IAAI,SAAS,CAC5C,QAAO;AAGT,KAAI,QAAQ,WAAW,SAAS,QAAQ,WAAW,OACjD,QAAO,QAAQ,QAAQ,IAAI,SAAS,sBAAsB,EAAE,QAAQ,KAAK,CAAC,CAAC;AAO7E,SAJ2B,YAAY,KAAK,IAAI,SAAS,GACrD,uBAAuB,SAAS,iBAAiB,GACjD,mBAAmB,SAAS,iBAAiB,EAG9C,MAAM,gBAAgB;AACrB,MAAI,YAAY,aAAa,KAAK;AAChC,qBAAkB,aAAa,IAAI,aAAa;AAChD,eAAY,aAAa,IAAI,WAAW,IAAI,aAAa,IAAI,UAAU,IAAI,WAAW;;AAGxF,SAAO,IAAI,SAAS,MAAM;GACxB,QAAQ;GACR,SAAS,EAAE,UAAU,YAAY,UAAU,EAAE;GAC9C,CAAC;GACF,CACD,OAAO,UAAU;AAChB,MAAI,MAAM,oCAAoC,EAAE,OAAO,CAAC;EACxD,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AAEzD,SAAO,IAAI,SAAS,KAAK,UAAU,EAAE,OAAO,SAAS,CAAC,EAAE;GACtD,QAAQ;GACR,SAAS,EAAE,gBAAgB,oBAAoB;GAChD,CAAC;GACF;;AAGN,eAAe,uBACb,SACA,kBACc;CACd,MAAM,SAAS,UAAU,QAAQ;AACjC,KAAI,CAAC,OAAQ,QAAO,IAAI,IAAI,KAAK,QAAQ,IAAI;CAE7C,MAAM,SAAS,MAAM,QAAQ,QAAQ,iBAAiB;AACtD,QAAO,OAAO,MAAM,cAAc,IAAI,IAAI,OAAO,KAAK,YAAY,GAAG,IAAI,IAAI,KAAK,QAAQ,IAAI;;AAGhG,eAAe,mBACb,SACA,kBACc;CACd,MAAM,YAAY,IAAI,IAAI,QAAQ,IAAI;CACtC,MAAM,cAAc,IAAI,IACtB,UAAU,UACV,uBAAuB,iBAAiB,SAAS,CAClD;CAED,MAAM,SAAS,UAAU,QAAQ;AACjC,KAAI,CAAC,OAAQ,QAAO;AAEpB,KAAI;EACF,MAAM,SAAS,MAAM,QAAQ,QAAQ,iBAAiB;AACtD,MAAI,OAAO,MAAM,YACf,mBAAkB,aAAa,IAAI,IAAI,OAAO,KAAK,YAAY,CAAC,aAAa;UAExE,OAAO;AACd,MAAI,KAAK,mEAAmE,EAAE,OAAO,CAAC;;AAGxF,QAAO;;AAGT,SAAS,uBAAuB,UAA0B;CACxD,MAAM,MAAM,IAAI,IAAI,SAAS;AAC7B,QAAO,IAAI,aAAa,cAAc,kCAAkC,IAAI;;AAG9E,SAAS,kBAAkB,QAAa,QAA+B;AACrE,MAAK,MAAM,CAAC,KAAK,UAAU,OACzB,KAAI,CAAC,OAAO,aAAa,IAAI,IAAI,CAAE,QAAO,aAAa,OAAO,KAAK,MAAM"}
1
+ {"version":3,"file":"checkout.mjs","names":[],"sources":["../../../../../src/core/request-routing/interceptors/checkout.ts"],"sourcesContent":["import type { StorefrontClient } from \"../../../client\";\nimport { getCart, getCartId } from \"../../cart/get-cart\";\nimport { getLogger } from \"../../logging\";\nimport { BUY_PERMALINK_RE, CHECKOUT_RE, isHydrogenServerHandoffPath } from \"../../url\";\nimport type { HydrogenRouteInterceptor } from \"../route-types\";\n\nconst log = getLogger(\"checkout\");\nconst MOCK_SHOP_PERMALINK_ORIGIN = \"https://demostore.mock.shop\";\n\nexport const handleCheckoutRedirect: HydrogenRouteInterceptor = (\n url,\n { request, storefrontClient },\n) => {\n if (!isHydrogenServerHandoffPath(url.pathname)) {\n return null;\n }\n\n if (request.method !== \"GET\" && request.method !== \"HEAD\") {\n return Promise.resolve(new Response(\"Method Not Allowed\", { status: 405 }));\n }\n\n const redirectUrlPromise = CHECKOUT_RE.test(url.pathname)\n ? getCheckoutRedirectUrl(request, storefrontClient)\n : getCartRedirectUrl(request, storefrontClient);\n\n return redirectUrlPromise\n .then((redirectUrl) => {\n if (redirectUrl.pathname !== \"/\") {\n mergeSearchParams(redirectUrl, url.searchParams);\n redirectUrl.searchParams.set(\"payment\", url.searchParams.get(\"payment\") ?? \"shop_pay\");\n }\n\n return new Response(null, {\n status: 302,\n headers: { location: redirectUrl.toString() },\n });\n })\n .catch((error) => {\n log.error(\"checkout redirect request failed\", { error });\n const message = error instanceof Error ? error.message : \"Internal redirect error\";\n\n return new Response(JSON.stringify({ error: message }), {\n status: 502,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n};\n\nexport const handleBuyPermalinkRedirect: HydrogenRouteInterceptor = (\n url,\n { request, storefrontClient },\n) => {\n if (!BUY_PERMALINK_RE.test(url.pathname)) {\n return null;\n }\n\n if (request.method !== \"GET\") {\n return Promise.resolve(new Response(\"Method Not Allowed\", { status: 405 }));\n }\n\n // UCP permalink response shape (303, no-store, no-referrer), forwarded verbatim since re-encoding would alter `continue_to`.\n // https://ucp.dev/2026-08-25/specification/permalink/#redirect-resolution\n const location = `${getPermalinkOrigin(storefrontClient.storeUrl)}${url.pathname}${url.search}`;\n return Promise.resolve(\n new Response(null, {\n status: 303,\n headers: { location, \"cache-control\": \"no-store\", \"referrer-policy\": \"no-referrer\" },\n }),\n );\n};\n\nasync function getCheckoutRedirectUrl(\n request: Request,\n storefrontClient: StorefrontClient,\n): Promise<URL> {\n const cartId = getCartId(request);\n if (!cartId) return new URL(\"/\", request.url);\n\n const result = await getCart(cartId, storefrontClient);\n return result.cart?.checkoutUrl ? new URL(result.cart.checkoutUrl) : new URL(\"/\", request.url);\n}\n\nasync function getCartRedirectUrl(\n request: Request,\n storefrontClient: StorefrontClient,\n): Promise<URL> {\n const sourceUrl = new URL(request.url);\n const redirectUrl = new URL(sourceUrl.pathname, getPermalinkOrigin(storefrontClient.storeUrl));\n\n const cartId = getCartId(request);\n if (!cartId) return redirectUrl;\n\n try {\n const result = await getCart(cartId, storefrontClient);\n if (result.cart?.checkoutUrl) {\n mergeSearchParams(redirectUrl, new URL(result.cart.checkoutUrl).searchParams);\n }\n } catch (error) {\n log.warn(\"checkout redirect could not load cart permalink tracking params\", { error });\n }\n\n return redirectUrl;\n}\n\nfunction getPermalinkOrigin(storeUrl: string): string {\n const url = new URL(storeUrl);\n return isMockShopHost(url.hostname) ? MOCK_SHOP_PERMALINK_ORIGIN : url.origin;\n}\n\n// mock.shop serves many stores, each on its own host (pets.mock.shop, ...), and\n// none of them renders cart or buy permalinks, so every mock host hands off to the demo store.\nfunction isMockShopHost(hostname: string): boolean {\n return hostname === \"mock.shop\" || hostname.endsWith(\".mock.shop\");\n}\n\nfunction mergeSearchParams(target: URL, source: URLSearchParams): void {\n for (const [key, value] of source) {\n if (!target.searchParams.has(key)) target.searchParams.append(key, value);\n }\n}\n"],"mappings":";;;;;AAMA,MAAM,MAAM,UAAU,WAAW;AACjC,MAAM,6BAA6B;AAEnC,MAAa,0BACX,KACA,EAAE,SAAS,uBACR;AACH,KAAI,CAAC,4BAA4B,IAAI,SAAS,CAC5C,QAAO;AAGT,KAAI,QAAQ,WAAW,SAAS,QAAQ,WAAW,OACjD,QAAO,QAAQ,QAAQ,IAAI,SAAS,sBAAsB,EAAE,QAAQ,KAAK,CAAC,CAAC;AAO7E,SAJ2B,YAAY,KAAK,IAAI,SAAS,GACrD,uBAAuB,SAAS,iBAAiB,GACjD,mBAAmB,SAAS,iBAAiB,EAG9C,MAAM,gBAAgB;AACrB,MAAI,YAAY,aAAa,KAAK;AAChC,qBAAkB,aAAa,IAAI,aAAa;AAChD,eAAY,aAAa,IAAI,WAAW,IAAI,aAAa,IAAI,UAAU,IAAI,WAAW;;AAGxF,SAAO,IAAI,SAAS,MAAM;GACxB,QAAQ;GACR,SAAS,EAAE,UAAU,YAAY,UAAU,EAAE;GAC9C,CAAC;GACF,CACD,OAAO,UAAU;AAChB,MAAI,MAAM,oCAAoC,EAAE,OAAO,CAAC;EACxD,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AAEzD,SAAO,IAAI,SAAS,KAAK,UAAU,EAAE,OAAO,SAAS,CAAC,EAAE;GACtD,QAAQ;GACR,SAAS,EAAE,gBAAgB,oBAAoB;GAChD,CAAC;GACF;;AAGN,MAAa,8BACX,KACA,EAAE,SAAS,uBACR;AACH,KAAI,CAAC,iBAAiB,KAAK,IAAI,SAAS,CACtC,QAAO;AAGT,KAAI,QAAQ,WAAW,MACrB,QAAO,QAAQ,QAAQ,IAAI,SAAS,sBAAsB,EAAE,QAAQ,KAAK,CAAC,CAAC;CAK7E,MAAM,WAAW,GAAG,mBAAmB,iBAAiB,SAAS,GAAG,IAAI,WAAW,IAAI;AACvF,QAAO,QAAQ,QACb,IAAI,SAAS,MAAM;EACjB,QAAQ;EACR,SAAS;GAAE;GAAU,iBAAiB;GAAY,mBAAmB;GAAe;EACrF,CAAC,CACH;;AAGH,eAAe,uBACb,SACA,kBACc;CACd,MAAM,SAAS,UAAU,QAAQ;AACjC,KAAI,CAAC,OAAQ,QAAO,IAAI,IAAI,KAAK,QAAQ,IAAI;CAE7C,MAAM,SAAS,MAAM,QAAQ,QAAQ,iBAAiB;AACtD,QAAO,OAAO,MAAM,cAAc,IAAI,IAAI,OAAO,KAAK,YAAY,GAAG,IAAI,IAAI,KAAK,QAAQ,IAAI;;AAGhG,eAAe,mBACb,SACA,kBACc;CACd,MAAM,YAAY,IAAI,IAAI,QAAQ,IAAI;CACtC,MAAM,cAAc,IAAI,IAAI,UAAU,UAAU,mBAAmB,iBAAiB,SAAS,CAAC;CAE9F,MAAM,SAAS,UAAU,QAAQ;AACjC,KAAI,CAAC,OAAQ,QAAO;AAEpB,KAAI;EACF,MAAM,SAAS,MAAM,QAAQ,QAAQ,iBAAiB;AACtD,MAAI,OAAO,MAAM,YACf,mBAAkB,aAAa,IAAI,IAAI,OAAO,KAAK,YAAY,CAAC,aAAa;UAExE,OAAO;AACd,MAAI,KAAK,mEAAmE,EAAE,OAAO,CAAC;;AAGxF,QAAO;;AAGT,SAAS,mBAAmB,UAA0B;CACpD,MAAM,MAAM,IAAI,IAAI,SAAS;AAC7B,QAAO,eAAe,IAAI,SAAS,GAAG,6BAA6B,IAAI;;AAKzE,SAAS,eAAe,UAA2B;AACjD,QAAO,aAAa,eAAe,SAAS,SAAS,aAAa;;AAGpE,SAAS,kBAAkB,QAAa,QAA+B;AACrE,MAAK,MAAM,CAAC,KAAK,UAAU,OACzB,KAAI,CAAC,OAAO,aAAa,IAAI,IAAI,CAAE,QAAO,aAAa,OAAO,KAAK,MAAM"}
@@ -1,5 +1,5 @@
1
- import { MCP_REQUEST_HEADER_ALLOWLIST } from "../../headers.mjs";
2
1
  import { MCP_RE } from "../../url.mjs";
2
+ import { MCP_REQUEST_HEADER_ALLOWLIST } from "../../headers.mjs";
3
3
  import { createProxyInterceptor } from "./proxy.mjs";
4
4
 
5
5
  //#region src/core/request-routing/interceptors/mcp-proxy.ts
@@ -3,26 +3,41 @@ import { extractHeaders } from "../../headers.mjs";
3
3
 
4
4
  //#region src/core/request-routing/interceptors/proxy.ts
5
5
  const PROXY_TIMEOUT_MS = 3e4;
6
+ const PROXY_ERROR_CACHE_CONTROL = "no-store";
6
7
  function createProxyInterceptor(descriptor) {
7
8
  const log = getLogger(descriptor.scope);
8
9
  const formatError = descriptor.formatError ?? defaultFormatError;
9
10
  return (url, options) => {
10
11
  const { request, storefrontClient } = options;
11
12
  if (!descriptor.match.test(url.pathname)) return null;
12
- if (descriptor.methods && !descriptor.methods.includes(request.method)) return null;
13
+ if (url.searchParams.has("callback")) return Promise.resolve(new Response(JSON.stringify(formatError("JSONP requests are not supported")), {
14
+ status: 400,
15
+ headers: {
16
+ "content-type": "application/json",
17
+ "cache-control": PROXY_ERROR_CACHE_CONTROL
18
+ }
19
+ }));
20
+ if (descriptor.methods && !descriptor.methods.includes(request.method)) return Promise.resolve(new Response(JSON.stringify(formatError("Method Not Allowed")), {
21
+ status: 405,
22
+ headers: {
23
+ allow: descriptor.methods.join(", "),
24
+ "content-type": "application/json",
25
+ "cache-control": PROXY_ERROR_CACHE_CONTROL
26
+ }
27
+ }));
13
28
  let upstreamUrl;
14
29
  let init;
15
30
  try {
16
31
  const upstreamPathname = descriptor.rewritePathname?.(url.pathname) ?? url.pathname;
17
32
  upstreamUrl = new URL(upstreamPathname + url.search, storefrontClient.storeUrl);
18
- const forwardedHeaders = createProxyRequestHeaders(descriptor, request);
19
- options.requestContext.applyStorefrontRequestHeaders(forwardedHeaders);
20
- descriptor.requestHeaders.prepare?.(forwardedHeaders, options, url);
21
33
  init = {
22
34
  method: request.method,
23
35
  body: request.body,
24
- headers: forwardedHeaders,
25
- signal: AbortSignal.timeout(descriptor.timeoutMs ?? PROXY_TIMEOUT_MS),
36
+ headers: createProxyRequestHeaders(descriptor, {
37
+ ...options,
38
+ url
39
+ }),
40
+ signal: AbortSignal.timeout(PROXY_TIMEOUT_MS),
26
41
  redirect: descriptor.redirect ?? "manual"
27
42
  };
28
43
  if (request.body) init.duplex = "half";
@@ -32,7 +47,11 @@ function createProxyInterceptor(descriptor) {
32
47
  }
33
48
  return fetch(upstreamUrl, init).then((upstreamResponse) => {
34
49
  const headers = createProxyResponseHeaders(upstreamResponse.headers);
35
- descriptor.responseHeaders?.prepare?.(headers, options, url);
50
+ descriptor.responseHeaders?.prepare?.(headers, {
51
+ ...options,
52
+ url,
53
+ response: upstreamResponse
54
+ });
36
55
  options.requestContext.consumeStorefrontResponseHeaders(headers);
37
56
  return new Response(upstreamResponse.body, {
38
57
  status: upstreamResponse.status,
@@ -52,19 +71,26 @@ function createProxyErrorResponse(error, status, formatError) {
52
71
  const message = error instanceof Error ? error.message : "Internal proxy error";
53
72
  return new Response(JSON.stringify(formatError(message)), {
54
73
  status,
55
- headers: { "content-type": "application/json" }
74
+ headers: {
75
+ "content-type": "application/json",
76
+ "cache-control": PROXY_ERROR_CACHE_CONTROL
77
+ }
56
78
  });
57
79
  }
58
- function createProxyRequestHeaders(descriptor, request) {
59
- const { allow, deny } = descriptor.requestHeaders;
80
+ function createProxyRequestHeaders(descriptor, options) {
81
+ const { request, requestContext } = options;
82
+ const { allow, deny, prepare } = descriptor.requestHeaders;
60
83
  const headers = allow ? new Headers(extractHeaders((key) => request.headers.get(key), allow)) : new Headers(request.headers);
84
+ requestContext.applyStorefrontRequestHeaders(headers);
61
85
  for (const header of deny ?? []) headers.delete(header);
86
+ prepare?.(headers, options);
62
87
  return headers;
63
88
  }
64
89
  function createProxyResponseHeaders(upstreamHeaders) {
65
90
  const headers = new Headers(upstreamHeaders);
66
91
  headers.delete("content-encoding");
67
92
  headers.delete("content-length");
93
+ headers.delete("server-timing");
68
94
  return headers;
69
95
  }
70
96
 
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.mjs","names":[],"sources":["../../../../../src/core/request-routing/interceptors/proxy.ts"],"sourcesContent":["import { extractHeaders } from \"../../headers\";\nimport { getLogger } from \"../../logging\";\nimport type { HydrogenRouteInterceptor, HydrogenRoutesOptions } from \"../route-types\";\n\nconst PROXY_TIMEOUT_MS = 30_000;\n\ntype PrepareHeaders = (headers: Headers, options: HydrogenRoutesOptions, url: URL) => void;\n\ntype ProxyRequestHeaderOptions = (\n | { allow: readonly string[]; deny?: never }\n | { allow?: never; deny: readonly string[] }\n) & {\n prepare?: PrepareHeaders;\n};\n\ntype ProxyResponseHeaderOptions = {\n prepare?: PrepareHeaders;\n};\n\ntype ProxyDescriptor = {\n match: RegExp;\n methods?: readonly string[];\n formatError?: (message: string) => unknown;\n redirect?: RequestRedirect;\n scope: string;\n timeoutMs?: number;\n rewritePathname?: (pathname: string) => string;\n requestHeaders: ProxyRequestHeaderOptions;\n responseHeaders?: ProxyResponseHeaderOptions;\n};\n\nexport function createProxyInterceptor(descriptor: ProxyDescriptor): HydrogenRouteInterceptor {\n const log = getLogger(descriptor.scope);\n const formatError = descriptor.formatError ?? defaultFormatError;\n\n return (url, options) => {\n const { request, storefrontClient } = options;\n if (!descriptor.match.test(url.pathname)) return null;\n if (descriptor.methods && !descriptor.methods.includes(request.method)) return null;\n\n let upstreamUrl: URL;\n let init: RequestInit & { duplex?: \"half\" };\n try {\n const upstreamPathname = descriptor.rewritePathname?.(url.pathname) ?? url.pathname;\n upstreamUrl = new URL(upstreamPathname + url.search, storefrontClient.storeUrl);\n const forwardedHeaders = createProxyRequestHeaders(descriptor, request);\n options.requestContext.applyStorefrontRequestHeaders(forwardedHeaders);\n descriptor.requestHeaders.prepare?.(forwardedHeaders, options, url);\n\n init = {\n method: request.method,\n body: request.body,\n headers: forwardedHeaders,\n signal: AbortSignal.timeout(descriptor.timeoutMs ?? PROXY_TIMEOUT_MS),\n redirect: descriptor.redirect ?? \"manual\",\n };\n\n // Node's fetch requires this when forwarding a streaming request body.\n if (request.body) init.duplex = \"half\";\n } catch (error) {\n log.error(\"request failed\", { error });\n return Promise.resolve(createProxyErrorResponse(error, 500, formatError));\n }\n\n return fetch(upstreamUrl, init)\n .then((upstreamResponse) => {\n const headers = createProxyResponseHeaders(upstreamResponse.headers);\n descriptor.responseHeaders?.prepare?.(headers, options, url);\n options.requestContext.consumeStorefrontResponseHeaders(headers);\n\n return new Response(upstreamResponse.body, {\n status: upstreamResponse.status,\n statusText: upstreamResponse.statusText,\n headers,\n });\n })\n .catch((error) => {\n log.error(\"request failed\", { error });\n return createProxyErrorResponse(error, 502, formatError);\n });\n };\n}\n\nfunction defaultFormatError(message: string): { error: string } {\n return { error: message };\n}\n\nfunction createProxyErrorResponse(\n error: unknown,\n status: number,\n formatError: (message: string) => unknown,\n): Response {\n const message = error instanceof Error ? error.message : \"Internal proxy error\";\n return new Response(JSON.stringify(formatError(message)), {\n status,\n headers: { \"content-type\": \"application/json\" },\n });\n}\n\nfunction createProxyRequestHeaders(descriptor: ProxyDescriptor, request: Request): Headers {\n const { allow, deny } = descriptor.requestHeaders;\n const headers = allow\n ? new Headers(extractHeaders((key) => request.headers.get(key), allow))\n : new Headers(request.headers);\n for (const header of deny ?? []) headers.delete(header);\n return headers;\n}\n\nexport function createProxyResponseHeaders(upstreamHeaders: Headers): Headers {\n const headers = new Headers(upstreamHeaders);\n headers.delete(\"content-encoding\");\n headers.delete(\"content-length\");\n return headers;\n}\n"],"mappings":";;;;AAIA,MAAM,mBAAmB;AA2BzB,SAAgB,uBAAuB,YAAuD;CAC5F,MAAM,MAAM,UAAU,WAAW,MAAM;CACvC,MAAM,cAAc,WAAW,eAAe;AAE9C,SAAQ,KAAK,YAAY;EACvB,MAAM,EAAE,SAAS,qBAAqB;AACtC,MAAI,CAAC,WAAW,MAAM,KAAK,IAAI,SAAS,CAAE,QAAO;AACjD,MAAI,WAAW,WAAW,CAAC,WAAW,QAAQ,SAAS,QAAQ,OAAO,CAAE,QAAO;EAE/E,IAAI;EACJ,IAAI;AACJ,MAAI;GACF,MAAM,mBAAmB,WAAW,kBAAkB,IAAI,SAAS,IAAI,IAAI;AAC3E,iBAAc,IAAI,IAAI,mBAAmB,IAAI,QAAQ,iBAAiB,SAAS;GAC/E,MAAM,mBAAmB,0BAA0B,YAAY,QAAQ;AACvE,WAAQ,eAAe,8BAA8B,iBAAiB;AACtE,cAAW,eAAe,UAAU,kBAAkB,SAAS,IAAI;AAEnE,UAAO;IACL,QAAQ,QAAQ;IAChB,MAAM,QAAQ;IACd,SAAS;IACT,QAAQ,YAAY,QAAQ,WAAW,aAAa,iBAAiB;IACrE,UAAU,WAAW,YAAY;IAClC;AAGD,OAAI,QAAQ,KAAM,MAAK,SAAS;WACzB,OAAO;AACd,OAAI,MAAM,kBAAkB,EAAE,OAAO,CAAC;AACtC,UAAO,QAAQ,QAAQ,yBAAyB,OAAO,KAAK,YAAY,CAAC;;AAG3E,SAAO,MAAM,aAAa,KAAK,CAC5B,MAAM,qBAAqB;GAC1B,MAAM,UAAU,2BAA2B,iBAAiB,QAAQ;AACpE,cAAW,iBAAiB,UAAU,SAAS,SAAS,IAAI;AAC5D,WAAQ,eAAe,iCAAiC,QAAQ;AAEhE,UAAO,IAAI,SAAS,iBAAiB,MAAM;IACzC,QAAQ,iBAAiB;IACzB,YAAY,iBAAiB;IAC7B;IACD,CAAC;IACF,CACD,OAAO,UAAU;AAChB,OAAI,MAAM,kBAAkB,EAAE,OAAO,CAAC;AACtC,UAAO,yBAAyB,OAAO,KAAK,YAAY;IACxD;;;AAIR,SAAS,mBAAmB,SAAoC;AAC9D,QAAO,EAAE,OAAO,SAAS;;AAG3B,SAAS,yBACP,OACA,QACA,aACU;CACV,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,QAAO,IAAI,SAAS,KAAK,UAAU,YAAY,QAAQ,CAAC,EAAE;EACxD;EACA,SAAS,EAAE,gBAAgB,oBAAoB;EAChD,CAAC;;AAGJ,SAAS,0BAA0B,YAA6B,SAA2B;CACzF,MAAM,EAAE,OAAO,SAAS,WAAW;CACnC,MAAM,UAAU,QACZ,IAAI,QAAQ,gBAAgB,QAAQ,QAAQ,QAAQ,IAAI,IAAI,EAAE,MAAM,CAAC,GACrE,IAAI,QAAQ,QAAQ,QAAQ;AAChC,MAAK,MAAM,UAAU,QAAQ,EAAE,CAAE,SAAQ,OAAO,OAAO;AACvD,QAAO;;AAGT,SAAgB,2BAA2B,iBAAmC;CAC5E,MAAM,UAAU,IAAI,QAAQ,gBAAgB;AAC5C,SAAQ,OAAO,mBAAmB;AAClC,SAAQ,OAAO,iBAAiB;AAChC,QAAO"}
1
+ {"version":3,"file":"proxy.mjs","names":[],"sources":["../../../../../src/core/request-routing/interceptors/proxy.ts"],"sourcesContent":["import { extractHeaders } from \"../../headers\";\nimport { getLogger } from \"../../logging\";\nimport type { HydrogenRouteInterceptor, HydrogenRoutesOptions } from \"../route-types\";\n\nconst PROXY_TIMEOUT_MS = 30_000;\n\n// Proxy errors are transient and may be buyer-specific: never cache them.\nconst PROXY_ERROR_CACHE_CONTROL = \"no-store\";\n\ntype ProxyHeaderContext = HydrogenRoutesOptions & { url: URL };\n\ntype PrepareHeaders<ExtraContext extends object = object> = (\n headers: Headers,\n context: ProxyHeaderContext & ExtraContext,\n) => void;\n\ntype ProxyRequestHeaderOptions = (\n | { allow: readonly string[]; deny?: never }\n | { allow?: never; deny: readonly string[] }\n) & {\n prepare?: PrepareHeaders;\n};\n\ntype ProxyResponseHeaderOptions = {\n prepare?: PrepareHeaders<{ response: Response }>;\n};\n\ntype ProxyDescriptor = {\n match: RegExp;\n methods?: readonly string[];\n formatError?: (message: string) => unknown;\n redirect?: RequestRedirect;\n scope: string;\n rewritePathname?: (pathname: string) => string;\n requestHeaders: ProxyRequestHeaderOptions;\n responseHeaders?: ProxyResponseHeaderOptions;\n};\n\nexport function createProxyInterceptor(descriptor: ProxyDescriptor): HydrogenRouteInterceptor {\n const log = getLogger(descriptor.scope);\n const formatError = descriptor.formatError ?? defaultFormatError;\n\n return (url, options) => {\n const { request, storefrontClient } = options;\n if (!descriptor.match.test(url.pathname)) return null;\n\n // Disable JSONP requests for security:\n if (url.searchParams.has(\"callback\")) {\n return Promise.resolve(\n new Response(JSON.stringify(formatError(\"JSONP requests are not supported\")), {\n status: 400,\n headers: {\n \"content-type\": \"application/json\",\n \"cache-control\": PROXY_ERROR_CACHE_CONTROL,\n },\n }),\n );\n }\n\n if (descriptor.methods && !descriptor.methods.includes(request.method)) {\n // Method not allowed. Shape the body via formatError, like other errors.\n return Promise.resolve(\n new Response(JSON.stringify(formatError(\"Method Not Allowed\")), {\n status: 405,\n headers: {\n allow: descriptor.methods.join(\", \"),\n \"content-type\": \"application/json\",\n \"cache-control\": PROXY_ERROR_CACHE_CONTROL,\n },\n }),\n );\n }\n\n let upstreamUrl: URL;\n let init: RequestInit & { duplex?: \"half\" };\n try {\n const upstreamPathname = descriptor.rewritePathname?.(url.pathname) ?? url.pathname;\n upstreamUrl = new URL(upstreamPathname + url.search, storefrontClient.storeUrl);\n\n init = {\n method: request.method,\n body: request.body,\n headers: createProxyRequestHeaders(descriptor, { ...options, url }),\n signal: AbortSignal.timeout(PROXY_TIMEOUT_MS),\n redirect: descriptor.redirect ?? \"manual\",\n };\n\n // Node's fetch requires this when forwarding a streaming request body.\n if (request.body) init.duplex = \"half\";\n } catch (error) {\n log.error(\"request failed\", { error });\n return Promise.resolve(createProxyErrorResponse(error, 500, formatError));\n }\n\n return fetch(upstreamUrl, init)\n .then((upstreamResponse) => {\n const headers = createProxyResponseHeaders(upstreamResponse.headers);\n descriptor.responseHeaders?.prepare?.(headers, {\n ...options,\n url,\n response: upstreamResponse,\n });\n options.requestContext.consumeStorefrontResponseHeaders(headers);\n\n return new Response(upstreamResponse.body, {\n status: upstreamResponse.status,\n statusText: upstreamResponse.statusText,\n headers,\n });\n })\n .catch((error) => {\n log.error(\"request failed\", { error });\n return createProxyErrorResponse(error, 502, formatError);\n });\n };\n}\n\nfunction defaultFormatError(message: string): { error: string } {\n return { error: message };\n}\n\nfunction createProxyErrorResponse(\n error: unknown,\n status: number,\n formatError: (message: string) => unknown,\n): Response {\n const message = error instanceof Error ? error.message : \"Internal proxy error\";\n return new Response(JSON.stringify(formatError(message)), {\n status,\n headers: {\n \"content-type\": \"application/json\",\n \"cache-control\": PROXY_ERROR_CACHE_CONTROL,\n },\n });\n}\n\nfunction createProxyRequestHeaders(\n descriptor: ProxyDescriptor,\n options: ProxyHeaderContext,\n): Headers {\n const { request, requestContext } = options;\n const { allow, deny, prepare } = descriptor.requestHeaders;\n const headers = allow\n ? new Headers(extractHeaders((key) => request.headers.get(key), allow))\n : new Headers(request.headers);\n\n requestContext.applyStorefrontRequestHeaders(headers);\n\n for (const header of deny ?? []) headers.delete(header);\n prepare?.(headers, options);\n\n return headers;\n}\n\nexport function createProxyResponseHeaders(upstreamHeaders: Headers): Headers {\n const headers = new Headers(upstreamHeaders);\n headers.delete(\"content-encoding\");\n headers.delete(\"content-length\");\n headers.delete(\"server-timing\");\n return headers;\n}\n"],"mappings":";;;;AAIA,MAAM,mBAAmB;AAGzB,MAAM,4BAA4B;AA+BlC,SAAgB,uBAAuB,YAAuD;CAC5F,MAAM,MAAM,UAAU,WAAW,MAAM;CACvC,MAAM,cAAc,WAAW,eAAe;AAE9C,SAAQ,KAAK,YAAY;EACvB,MAAM,EAAE,SAAS,qBAAqB;AACtC,MAAI,CAAC,WAAW,MAAM,KAAK,IAAI,SAAS,CAAE,QAAO;AAGjD,MAAI,IAAI,aAAa,IAAI,WAAW,CAClC,QAAO,QAAQ,QACb,IAAI,SAAS,KAAK,UAAU,YAAY,mCAAmC,CAAC,EAAE;GAC5E,QAAQ;GACR,SAAS;IACP,gBAAgB;IAChB,iBAAiB;IAClB;GACF,CAAC,CACH;AAGH,MAAI,WAAW,WAAW,CAAC,WAAW,QAAQ,SAAS,QAAQ,OAAO,CAEpE,QAAO,QAAQ,QACb,IAAI,SAAS,KAAK,UAAU,YAAY,qBAAqB,CAAC,EAAE;GAC9D,QAAQ;GACR,SAAS;IACP,OAAO,WAAW,QAAQ,KAAK,KAAK;IACpC,gBAAgB;IAChB,iBAAiB;IAClB;GACF,CAAC,CACH;EAGH,IAAI;EACJ,IAAI;AACJ,MAAI;GACF,MAAM,mBAAmB,WAAW,kBAAkB,IAAI,SAAS,IAAI,IAAI;AAC3E,iBAAc,IAAI,IAAI,mBAAmB,IAAI,QAAQ,iBAAiB,SAAS;AAE/E,UAAO;IACL,QAAQ,QAAQ;IAChB,MAAM,QAAQ;IACd,SAAS,0BAA0B,YAAY;KAAE,GAAG;KAAS;KAAK,CAAC;IACnE,QAAQ,YAAY,QAAQ,iBAAiB;IAC7C,UAAU,WAAW,YAAY;IAClC;AAGD,OAAI,QAAQ,KAAM,MAAK,SAAS;WACzB,OAAO;AACd,OAAI,MAAM,kBAAkB,EAAE,OAAO,CAAC;AACtC,UAAO,QAAQ,QAAQ,yBAAyB,OAAO,KAAK,YAAY,CAAC;;AAG3E,SAAO,MAAM,aAAa,KAAK,CAC5B,MAAM,qBAAqB;GAC1B,MAAM,UAAU,2BAA2B,iBAAiB,QAAQ;AACpE,cAAW,iBAAiB,UAAU,SAAS;IAC7C,GAAG;IACH;IACA,UAAU;IACX,CAAC;AACF,WAAQ,eAAe,iCAAiC,QAAQ;AAEhE,UAAO,IAAI,SAAS,iBAAiB,MAAM;IACzC,QAAQ,iBAAiB;IACzB,YAAY,iBAAiB;IAC7B;IACD,CAAC;IACF,CACD,OAAO,UAAU;AAChB,OAAI,MAAM,kBAAkB,EAAE,OAAO,CAAC;AACtC,UAAO,yBAAyB,OAAO,KAAK,YAAY;IACxD;;;AAIR,SAAS,mBAAmB,SAAoC;AAC9D,QAAO,EAAE,OAAO,SAAS;;AAG3B,SAAS,yBACP,OACA,QACA,aACU;CACV,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,QAAO,IAAI,SAAS,KAAK,UAAU,YAAY,QAAQ,CAAC,EAAE;EACxD;EACA,SAAS;GACP,gBAAgB;GAChB,iBAAiB;GAClB;EACF,CAAC;;AAGJ,SAAS,0BACP,YACA,SACS;CACT,MAAM,EAAE,SAAS,mBAAmB;CACpC,MAAM,EAAE,OAAO,MAAM,YAAY,WAAW;CAC5C,MAAM,UAAU,QACZ,IAAI,QAAQ,gBAAgB,QAAQ,QAAQ,QAAQ,IAAI,IAAI,EAAE,MAAM,CAAC,GACrE,IAAI,QAAQ,QAAQ,QAAQ;AAEhC,gBAAe,8BAA8B,QAAQ;AAErD,MAAK,MAAM,UAAU,QAAQ,EAAE,CAAE,SAAQ,OAAO,OAAO;AACvD,WAAU,SAAS,QAAQ;AAE3B,QAAO;;AAGT,SAAgB,2BAA2B,iBAAmC;CAC5E,MAAM,UAAU,IAAI,QAAQ,gBAAgB;AAC5C,SAAQ,OAAO,mBAAmB;AAClC,SAAQ,OAAO,iBAAiB;AAChC,SAAQ,OAAO,gBAAgB;AAC/B,QAAO"}
@@ -1,21 +1,15 @@
1
+ import { getSameOriginPath } from "../../url.mjs";
2
+
1
3
  //#region src/core/request-routing/interceptors/query-param-redirect.ts
2
4
  function handleQueryParamRedirect(request) {
3
5
  const url = new URL(request.url);
4
- const redirectTo = url.searchParams.get("return_to") || url.searchParams.get("redirect");
5
- if (!redirectTo) return null;
6
- if (!isSameOrigin(request.url, redirectTo)) return null;
6
+ const location = getSameOriginPath(url.searchParams.get("return_to") || url.searchParams.get("redirect"), url.origin);
7
+ if (!location) return null;
7
8
  return new Response(null, {
8
9
  status: 301,
9
- headers: { location: redirectTo }
10
+ headers: { location }
10
11
  });
11
12
  }
12
- function isSameOrigin(requestUrl, redirectUrl) {
13
- try {
14
- return new URL(requestUrl).origin === new URL(redirectUrl, requestUrl).origin;
15
- } catch {
16
- return false;
17
- }
18
- }
19
13
 
20
14
  //#endregion
21
15
  export { handleQueryParamRedirect };
@@ -1 +1 @@
1
- {"version":3,"file":"query-param-redirect.mjs","names":[],"sources":["../../../../../src/core/request-routing/interceptors/query-param-redirect.ts"],"sourcesContent":["export function handleQueryParamRedirect(request: Request): Response | null {\n const url = new URL(request.url);\n const redirectTo = url.searchParams.get(\"return_to\") || url.searchParams.get(\"redirect\");\n\n if (!redirectTo) return null;\n if (!isSameOrigin(request.url, redirectTo)) return null;\n\n return new Response(null, {\n status: 301,\n headers: { location: redirectTo },\n });\n}\n\nfunction isSameOrigin(requestUrl: string, redirectUrl: string): boolean {\n try {\n return new URL(requestUrl).origin === new URL(redirectUrl, requestUrl).origin;\n } catch {\n return false;\n }\n}\n"],"mappings":";AAAA,SAAgB,yBAAyB,SAAmC;CAC1E,MAAM,MAAM,IAAI,IAAI,QAAQ,IAAI;CAChC,MAAM,aAAa,IAAI,aAAa,IAAI,YAAY,IAAI,IAAI,aAAa,IAAI,WAAW;AAExF,KAAI,CAAC,WAAY,QAAO;AACxB,KAAI,CAAC,aAAa,QAAQ,KAAK,WAAW,CAAE,QAAO;AAEnD,QAAO,IAAI,SAAS,MAAM;EACxB,QAAQ;EACR,SAAS,EAAE,UAAU,YAAY;EAClC,CAAC;;AAGJ,SAAS,aAAa,YAAoB,aAA8B;AACtE,KAAI;AACF,SAAO,IAAI,IAAI,WAAW,CAAC,WAAW,IAAI,IAAI,aAAa,WAAW,CAAC;SACjE;AACN,SAAO"}
1
+ {"version":3,"file":"query-param-redirect.mjs","names":[],"sources":["../../../../../src/core/request-routing/interceptors/query-param-redirect.ts"],"sourcesContent":["import { getSameOriginPath } from \"../../url\";\n\nexport function handleQueryParamRedirect(request: Request): Response | null {\n const url = new URL(request.url);\n const location = getSameOriginPath(\n url.searchParams.get(\"return_to\") || url.searchParams.get(\"redirect\"),\n url.origin,\n );\n\n if (!location) return null;\n\n return new Response(null, {\n status: 301,\n headers: { location },\n });\n}\n"],"mappings":";;;AAEA,SAAgB,yBAAyB,SAAmC;CAC1E,MAAM,MAAM,IAAI,IAAI,QAAQ,IAAI;CAChC,MAAM,WAAW,kBACf,IAAI,aAAa,IAAI,YAAY,IAAI,IAAI,aAAa,IAAI,WAAW,EACrE,IAAI,OACL;AAED,KAAI,CAAC,SAAU,QAAO;AAEtB,QAAO,IAAI,SAAS,MAAM;EACxB,QAAQ;EACR,SAAS,EAAE,UAAU;EACtB,CAAC"}
@@ -1,5 +1,5 @@
1
- import { SFAPI_REQUEST_HEADER_ALLOWLIST, STOREFRONT_BUYER_IP_HEADER, STOREFRONT_ID_HEADER } from "../../headers.mjs";
2
1
  import { SFAPI_RE } from "../../url.mjs";
2
+ import { CONSENT_MANAGEMENT_HEADER, SFAPI_REQUEST_HEADER_ALLOWLIST, STOREFRONT_BUYER_IP_HEADER, STOREFRONT_ID_HEADER } from "../../headers.mjs";
3
3
  import { createProxyInterceptor } from "./proxy.mjs";
4
4
 
5
5
  //#region src/core/request-routing/interceptors/sfapi-proxy.ts
@@ -19,8 +19,26 @@ const handleSfapiProxy = createProxyInterceptor({
19
19
  if (storefrontClient.type === "private") throw new Error("requestContext.buyerIp is required for private Storefront API proxy requests");
20
20
  }
21
21
  },
22
+ responseHeaders: { prepare(headers, { request, requestContext, url, response }) {
23
+ if (request.headers.has("Shopify-Storefront-Consent-Management") && response.ok) {
24
+ const cookies = (requestContext.cookie ?? "").split(";");
25
+ const legacyNames = ["_shopify_y", "_shopify_s"].filter((name) => cookies.some((cookie) => cookie.trim().startsWith(`${name}=`)));
26
+ if (legacyNames.length) expireLegacyCookies(headers, legacyNames, url.hostname);
27
+ }
28
+ } },
22
29
  scope: "sfapi-proxy"
23
30
  });
31
+ function expireLegacyCookies(headers, legacyNames, hostname) {
32
+ const domains = [""];
33
+ if (!hostname.includes(":") && !/^[\d.]+$/.test(hostname)) {
34
+ const labels = hostname.split(".");
35
+ while (labels.length > 1) {
36
+ domains.push(labels.join("."));
37
+ labels.shift();
38
+ }
39
+ }
40
+ for (const name of legacyNames) for (const domain of domains) headers.append("set-cookie", `${name}=; Path=/; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax${domain ? `; Domain=${domain}` : ""}`);
41
+ }
24
42
 
25
43
  //#endregion
26
44
  export { handleSfapiProxy };
@@ -1 +1 @@
1
- {"version":3,"file":"sfapi-proxy.mjs","names":[],"sources":["../../../../../src/core/request-routing/interceptors/sfapi-proxy.ts"],"sourcesContent":["import {\n SFAPI_REQUEST_HEADER_ALLOWLIST,\n STOREFRONT_BUYER_IP_HEADER,\n STOREFRONT_ID_HEADER,\n} from \"../../headers\";\nimport { SFAPI_RE } from \"../../url\";\nimport { createProxyInterceptor } from \"./proxy\";\n\nexport const handleSfapiProxy = createProxyInterceptor({\n match: SFAPI_RE,\n requestHeaders: {\n allow: SFAPI_REQUEST_HEADER_ALLOWLIST,\n prepare: (headers, { requestContext, storefrontClient }) => {\n headers.delete(STOREFRONT_ID_HEADER);\n if (storefrontClient.storefrontId) {\n headers.set(STOREFRONT_ID_HEADER, storefrontClient.storefrontId);\n }\n\n headers.delete(STOREFRONT_BUYER_IP_HEADER);\n const { buyerIp } = requestContext;\n if (buyerIp) {\n headers.set(STOREFRONT_BUYER_IP_HEADER, buyerIp);\n return;\n }\n if (storefrontClient.type === \"private\") {\n throw new Error(\n \"requestContext.buyerIp is required for private Storefront API proxy requests\",\n );\n }\n },\n },\n scope: \"sfapi-proxy\",\n});\n"],"mappings":";;;;;AAQA,MAAa,mBAAmB,uBAAuB;CACrD,OAAO;CACP,gBAAgB;EACd,OAAO;EACP,UAAU,SAAS,EAAE,gBAAgB,uBAAuB;AAC1D,WAAQ,OAAO,qBAAqB;AACpC,OAAI,iBAAiB,aACnB,SAAQ,IAAI,sBAAsB,iBAAiB,aAAa;AAGlE,WAAQ,OAAO,2BAA2B;GAC1C,MAAM,EAAE,YAAY;AACpB,OAAI,SAAS;AACX,YAAQ,IAAI,4BAA4B,QAAQ;AAChD;;AAEF,OAAI,iBAAiB,SAAS,UAC5B,OAAM,IAAI,MACR,+EACD;;EAGN;CACD,OAAO;CACR,CAAC"}
1
+ {"version":3,"file":"sfapi-proxy.mjs","names":[],"sources":["../../../../../src/core/request-routing/interceptors/sfapi-proxy.ts"],"sourcesContent":["import {\n CONSENT_MANAGEMENT_HEADER,\n SFAPI_REQUEST_HEADER_ALLOWLIST,\n STOREFRONT_BUYER_IP_HEADER,\n STOREFRONT_ID_HEADER,\n} from \"../../headers\";\nimport { SFAPI_RE } from \"../../url\";\nimport { createProxyInterceptor } from \"./proxy\";\n\nexport const handleSfapiProxy = createProxyInterceptor({\n match: SFAPI_RE,\n requestHeaders: {\n allow: SFAPI_REQUEST_HEADER_ALLOWLIST,\n prepare: (headers, { requestContext, storefrontClient }) => {\n headers.delete(STOREFRONT_ID_HEADER);\n if (storefrontClient.storefrontId) {\n headers.set(STOREFRONT_ID_HEADER, storefrontClient.storefrontId);\n }\n\n headers.delete(STOREFRONT_BUYER_IP_HEADER);\n const { buyerIp } = requestContext;\n if (buyerIp) {\n headers.set(STOREFRONT_BUYER_IP_HEADER, buyerIp);\n return;\n }\n if (storefrontClient.type === \"private\") {\n throw new Error(\n \"requestContext.buyerIp is required for private Storefront API proxy requests\",\n );\n }\n },\n },\n responseHeaders: {\n prepare(headers, { request, requestContext, url, response }) {\n if (request.headers.has(CONSENT_MANAGEMENT_HEADER) && response.ok) {\n const cookies = (requestContext.cookie ?? \"\").split(\";\");\n const legacyNames = [\"_shopify_y\", \"_shopify_s\"].filter((name) =>\n cookies.some((cookie) => cookie.trim().startsWith(`${name}=`)),\n );\n if (legacyNames.length) {\n expireLegacyCookies(headers, legacyNames, url.hostname);\n }\n }\n },\n },\n scope: \"sfapi-proxy\",\n});\n\nfunction expireLegacyCookies(headers: Headers, legacyNames: string[], hostname: string): void {\n // Cookie requests omit domain attributes. Expire host-only cookies and\n // each possible domain scope used by older storefronts. Browsers reject\n // public suffixes (such as co.uk), so no public suffix list is needed here.\n const domains = [\"\"];\n if (!hostname.includes(\":\") && !/^[\\d.]+$/.test(hostname)) {\n const labels = hostname.split(\".\");\n while (labels.length > 1) {\n domains.push(labels.join(\".\"));\n labels.shift();\n }\n }\n\n for (const name of legacyNames) {\n for (const domain of domains) {\n headers.append(\n \"set-cookie\",\n `${name}=; Path=/; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax${domain ? `; Domain=${domain}` : \"\"}`,\n );\n }\n }\n}\n"],"mappings":";;;;;AASA,MAAa,mBAAmB,uBAAuB;CACrD,OAAO;CACP,gBAAgB;EACd,OAAO;EACP,UAAU,SAAS,EAAE,gBAAgB,uBAAuB;AAC1D,WAAQ,OAAO,qBAAqB;AACpC,OAAI,iBAAiB,aACnB,SAAQ,IAAI,sBAAsB,iBAAiB,aAAa;AAGlE,WAAQ,OAAO,2BAA2B;GAC1C,MAAM,EAAE,YAAY;AACpB,OAAI,SAAS;AACX,YAAQ,IAAI,4BAA4B,QAAQ;AAChD;;AAEF,OAAI,iBAAiB,SAAS,UAC5B,OAAM,IAAI,MACR,+EACD;;EAGN;CACD,iBAAiB,EACf,QAAQ,SAAS,EAAE,SAAS,gBAAgB,KAAK,YAAY;AAC3D,MAAI,QAAQ,QAAQ,4CAA8B,IAAI,SAAS,IAAI;GACjE,MAAM,WAAW,eAAe,UAAU,IAAI,MAAM,IAAI;GACxD,MAAM,cAAc,CAAC,cAAc,aAAa,CAAC,QAAQ,SACvD,QAAQ,MAAM,WAAW,OAAO,MAAM,CAAC,WAAW,GAAG,KAAK,GAAG,CAAC,CAC/D;AACD,OAAI,YAAY,OACd,qBAAoB,SAAS,aAAa,IAAI,SAAS;;IAI9D;CACD,OAAO;CACR,CAAC;AAEF,SAAS,oBAAoB,SAAkB,aAAuB,UAAwB;CAI5F,MAAM,UAAU,CAAC,GAAG;AACpB,KAAI,CAAC,SAAS,SAAS,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE;EACzD,MAAM,SAAS,SAAS,MAAM,IAAI;AAClC,SAAO,OAAO,SAAS,GAAG;AACxB,WAAQ,KAAK,OAAO,KAAK,IAAI,CAAC;AAC9B,UAAO,OAAO;;;AAIlB,MAAK,MAAM,QAAQ,YACjB,MAAK,MAAM,UAAU,QACnB,SAAQ,OACN,cACA,GAAG,KAAK,2EAA2E,SAAS,YAAY,WAAW,KACpH"}
@@ -0,0 +1,35 @@
1
+ import { UCP_MCP_RE } from "../../url.mjs";
2
+ import { PROXY_REQUEST_HEADER_DENYLIST } from "../../headers.mjs";
3
+ import { createProxyInterceptor } from "./proxy.mjs";
4
+
5
+ //#region src/core/request-routing/interceptors/ucp-mcp-proxy.ts
6
+ const JSON_RPC_INTERNAL_ERROR = -32603;
7
+ const RESPONSE_STATE_REASON = "ucp request";
8
+ /**
9
+ * Caller-authenticated UCP pass-through. The caller owns both the
10
+ * Authorization header and the UCP agent profile in its request body.
11
+ */
12
+ const proxyUcpMcpRequest = createProxyInterceptor({
13
+ match: UCP_MCP_RE,
14
+ methods: ["POST"],
15
+ requestHeaders: { deny: PROXY_REQUEST_HEADER_DENYLIST },
16
+ formatError: (message) => ({
17
+ jsonrpc: "2.0",
18
+ error: {
19
+ code: JSON_RPC_INTERNAL_ERROR,
20
+ message
21
+ },
22
+ id: null
23
+ }),
24
+ scope: "ucp-mcp-proxy"
25
+ });
26
+ const handleUcpMcpProxy = (url, options) => {
27
+ if (!UCP_MCP_RE.test(url.pathname)) return null;
28
+ options.requestContext.markResponseAsPersonalized(RESPONSE_STATE_REASON);
29
+ options.requestContext.markResponseAsSessionEstablishing(RESPONSE_STATE_REASON);
30
+ return proxyUcpMcpRequest(url, options);
31
+ };
32
+
33
+ //#endregion
34
+ export { handleUcpMcpProxy };
35
+ //# sourceMappingURL=ucp-mcp-proxy.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ucp-mcp-proxy.mjs","names":[],"sources":["../../../../../src/core/request-routing/interceptors/ucp-mcp-proxy.ts"],"sourcesContent":["import { PROXY_REQUEST_HEADER_DENYLIST } from \"../../headers\";\nimport { UCP_MCP_RE } from \"../../url\";\nimport type { HydrogenRouteInterceptor } from \"../route-types\";\nimport { createProxyInterceptor } from \"./proxy\";\n\nconst JSON_RPC_INTERNAL_ERROR = -32603;\n\n// Traceability reason recorded when marking UCP MCP response state.\nconst RESPONSE_STATE_REASON = \"ucp request\";\n\n/**\n * Caller-authenticated UCP pass-through. The caller owns both the\n * Authorization header and the UCP agent profile in its request body.\n */\nconst proxyUcpMcpRequest = createProxyInterceptor({\n match: UCP_MCP_RE,\n methods: [\"POST\"],\n requestHeaders: { deny: PROXY_REQUEST_HEADER_DENYLIST },\n formatError: (message) => ({\n jsonrpc: \"2.0\",\n error: { code: JSON_RPC_INTERNAL_ERROR, message },\n id: null,\n }),\n scope: \"ucp-mcp-proxy\",\n});\n\nexport const handleUcpMcpProxy: HydrogenRouteInterceptor = (url, options) => {\n if (!UCP_MCP_RE.test(url.pathname)) return null;\n\n options.requestContext.markResponseAsPersonalized(RESPONSE_STATE_REASON);\n // UCP MCP is a sanctioned session-establishing endpoint: let the store's\n // session cookie return on a cold agent request, staying within the response\n // state gating rather than bypassing it.\n options.requestContext.markResponseAsSessionEstablishing(RESPONSE_STATE_REASON);\n return proxyUcpMcpRequest(url, options);\n};\n"],"mappings":";;;;;AAKA,MAAM,0BAA0B;AAGhC,MAAM,wBAAwB;;;;;AAM9B,MAAM,qBAAqB,uBAAuB;CAChD,OAAO;CACP,SAAS,CAAC,OAAO;CACjB,gBAAgB,EAAE,MAAM,+BAA+B;CACvD,cAAc,aAAa;EACzB,SAAS;EACT,OAAO;GAAE,MAAM;GAAyB;GAAS;EACjD,IAAI;EACL;CACD,OAAO;CACR,CAAC;AAEF,MAAa,qBAA+C,KAAK,YAAY;AAC3E,KAAI,CAAC,WAAW,KAAK,IAAI,SAAS,CAAE,QAAO;AAE3C,SAAQ,eAAe,2BAA2B,sBAAsB;AAIxE,SAAQ,eAAe,kCAAkC,sBAAsB;AAC/E,QAAO,mBAAmB,KAAK,QAAQ"}
@@ -1,5 +1,5 @@
1
- import { PROXY_REQUEST_HEADER_DENYLIST } from "../../headers.mjs";
2
1
  import { WELL_KNOWN_RE } from "../../url.mjs";
2
+ import { PROXY_REQUEST_HEADER_DENYLIST } from "../../headers.mjs";
3
3
  import { createProxyInterceptor } from "./proxy.mjs";
4
4
 
5
5
  //#region src/core/request-routing/interceptors/well-known.ts
@@ -1,7 +1,7 @@
1
1
  import { asInlineScript } from "./utils/inline-script.mjs";
2
2
 
3
3
  //#region src/core/shopify-scripts/analytics.ts
4
- const initializeShopifyAnalyticsBus = (scriptData) => decodeURIComponent("(function()%7Blet%20e%3D%7Btrace%3A%60debug%60%2Cdebug%3A%60debug%60%2Cinfo%3A%60info%60%2Cwarn%3A%60warn%60%2Cerror%3A%60error%60%2Cfatal%3A%60error%60%7D%3Bfunction%20t(e%2Ct)%7Breturn%60%5Bhydrogen%3A%24%7Be%7D%3A%24%7Bt%7D%5D%60%7Dfunction%20n(n%2Cr%2Ci)%7Blet%7Bscope%3Aa%2Cerror%3Ao%2C...s%7D%3Di%3F%3F%7B%7D%2Cc%3D%5Ba%3F%60%24%7Bt(n%2Ca)%7D%20%24%7Br%7D%60%3Ar%5D%3Bo!%3D%3Dvoid%200%26%26c.push(o)%2CObject.keys(s).length%3E0%26%26c.push(s)%2Cconsole%5Be%5Bn%5D%5D(...c)%7Dlet%20r%3D%7Btrace%3A(e%2Ct)%3D%3En(%60trace%60%2Ce%2Ct)%2Cdebug%3A(e%2Ct)%3D%3En(%60debug%60%2Ce%2Ct)%2Cinfo%3A(e%2Ct)%3D%3En(%60info%60%2Ce%2Ct)%2Cwarn%3A(e%2Ct)%3D%3En(%60warn%60%2Ce%2Ct)%2Cerror%3A(e%2Ct)%3D%3En(%60error%60%2Ce%2Ct)%2Cfatal%3A(e%2Ct)%3D%3En(%60fatal%60%2Ce%2Ct)%7D%2Ci%3D%60https%3A%2F%2Fcdn.shopify.com%60%3B%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%3Blet%20a%3D%60visitorConsentCollected%60%3Bfunction%20o()%7Bif(typeof%20window%3E%60u%60)return%3Blet%20e%3Dwindow%3Breturn%20e.Shopify%3F%3F%3D%7B%7D%7Dfunction%20s(e)%7Breturn%20typeof%20e%3D%3D%60object%60%26%26!!e%26%26!Array.isArray(e)%7Dfunction%20c(e%2Ct)%7Blet%20n%3De.subscriptions.get(t.event)%3Bif(!n%3F.size)%7Be.nextReplaySequence%3DMath.max(e.nextReplaySequence%2Ct.sequence%2B1)%3Breturn%7Dfor(let%20i%20of%20n)try%7Bi(t.payload)%7Dcatch(t)%7Br.error(%60error%20in%20analytics%20destination%20%22%24%7Be.name%7D%22%60%2C%7Bscope%3A%60analytics%60%2Cerror%3At%7D)%7De.nextReplaySequence%3DMath.max(e.nextReplaySequence%2Ct.sequence%2B1)%7Dfunction%20l(e)%7Blet%20t%3D0%2Cn%3D!0%2Ci%3D%5B%5D%2Ca%3Dnew%20Set%2Co%3Dnew%20Set%3Bfunction%20s(t%3D!1)%7Bif(!e.canTrack())%7Bt%26%26(i.length%3D0%2Cn%3D!1)%3Breturn%7Dn%3D!0%3Bfor(let%20e%20of%20a)for(let%20t%20of%20i)t.sequence%3Ce.nextReplaySequence%7C%7Cc(e%2Ct)%7Dfunction%20l(t)%7Bif(o.has(t.name))return%20r.warn(%60analytics%20destination%20%22%24%7Bt.name%7D%22%20is%20already%20registered%60%2C%7Bscope%3A%60analytics%60%7D)%2C()%3D%3E%7B%7D%3Bo.add(t.name)%3Blet%20n%3D%7Bname%3At.name%2Csubscriptions%3Anew%20Map%2CnextReplaySequence%3A0%7D%2Ci%3D!1%2Cc%3D(t%2Cr)%3D%3E%7Bif(i)return()%3D%3E%7B%7D%3Bif(e.isSupportedEvent%26%26!e.isSupportedEvent(t))return%20e.warnUnsupportedEvent%3F.(t)%2C()%3D%3E%7B%7D%3Blet%20a%3Dn.subscriptions.get(t)%3Breturn%20a%7C%7C(a%3Dnew%20Set%2Cn.subscriptions.set(t%2Ca))%2Ca.add(r)%2C()%3D%3E%7Blet%20e%3Dn.subscriptions.get(t)%3Be%3F.delete(r)%2Ce%3F.size%3D%3D%3D0%26%26n.subscriptions.delete(t)%7D%7D%2Cl%3D()%3D%3E%7Bi%7C%7C(i%3D!0%2Ca.delete(n)%2Co.delete(t.name)%2Cn.subscriptions.clear()%2Cn.cleanup%3F.())%7D%2Cu%3De%3D%3E%7Bif(i)%7Be%3F.()%3Breturn%7Dtypeof%20e%3D%3D%60function%60%26%26(n.cleanup%3De)%2Ca.add(n)%2Cs()%7D%3Btry%7Blet%20n%3Dt.setup(%7Bsubscribe%3Ac%2CgetConfig%3Ae.getConfig%7D)%3Bn%26%26typeof%20n.then%3D%3D%60function%60%3Fn.then(u).catch(e%3D%3E%7Br.error(%60error%20setting%20up%20analytics%20destination%20%22%24%7Bt.name%7D%22%60%2C%7Bscope%3A%60analytics%60%2Cerror%3Ae%7D)%2Cl()%7D)%3Au(n)%7Dcatch(e)%7Br.error(%60error%20setting%20up%20analytics%20destination%20%22%24%7Bt.name%7D%22%60%2C%7Bscope%3A%60analytics%60%2Cerror%3Ae%7D)%2Cl()%7Dreturn%20l%7Dfunction%20u(r%2Co)%7Blet%20s%3D%7Bsequence%3At%2B%2B%2Cevent%3Ar%2Cpayload%3Ao%7D%3Bif(n%26%26(i.push(s)%2Ci.length%3E500%26%26i.shift())%2Ce.canTrack())for(let%20e%20of%20a)c(e%2Cs)%7Dfunction%20d()%7Bi.length%3D0%3Bfor(let%20e%20of%20a)e.subscriptions.clear()%2Ce.cleanup%3F.()%3Ba.clear()%2Co.clear()%7Dreturn%7BaddDestination%3Al%2ConPublish%3Au%2Creplay%3As%2Cdestroy%3Ad%7D%7Dlet%20u%3D%7BPAGE_VIEWED%3A%60page_viewed%60%2CPRODUCT_VIEWED%3A%60product_viewed%60%2CCOLLECTION_VIEWED%3A%60collection_viewed%60%2CCART_VIEWED%3A%60cart_viewed%60%2CSEARCH_VIEWED%3A%60search_viewed%60%2CCART_UPDATED%3A%60cart_updated%60%2CPRODUCT_ADD_TO_CART%3A%60product_added_to_cart%60%2CPRODUCT_REMOVED_FROM_CART%3A%60product_removed_from_cart%60%7D%2Cd%3D%60gid%3A%2F%2Fshopify%2FShop%2F%60%3Bfunction%20f(e)%7Breturn%20e.startsWith(d)%3Fe%3A%60%24%7Bd%7D%24%7Be%7D%60%7Dfunction%20p(e)%7Breturn%20e%3F%7B...e%2CshopId%3Af(e.shopId)%7D%3Anull%7Dlet%20m%3Dnew%20Set(%5Bu.PAGE_VIEWED%2Cu.PRODUCT_VIEWED%2Cu.COLLECTION_VIEWED%2Cu.CART_VIEWED%2Cu.SEARCH_VIEWED%5D)%2Ch%3Dnew%20Set(Object.values(u))%3Bfunction%20g()%7Bif(!(typeof%20window%3E%60u%60))return%20window.location.href%7Dfunction%20_(e%2Ct)%7Breturn%20Object.prototype.hasOwnProperty.call(e%2Ct)%7Dfunction%20v(e%2Ct)%7Breturn%20s(e)%3F_(e%2C%60shop%60)%3F%7B...e%2Cshop%3Ap(e.shop)%7D%3A%7B...e%2Cshop%3At%7D%3Ae%7Dfunction%20y(e%2Ct)%7Bif(!m.has(e)%7C%7C!s(t)%7C%7Ctypeof%20t.url%3D%3D%60string%60%26%26t.url.length%3E0)return%20t%3Blet%20n%3Dg()%3Breturn%20n%3F%7B...t%2Curl%3An%7D%3At%7Dfunction%20b()%7Btry%7Blet%20e%3Dwindow.Shopify%3F.customerPrivacy%3Bif(e%3F.consentStatus!%3D%3D%60loaded%60)return!1%3Blet%20t%3De.currentVisitorConsent%3F.()%3Breturn%20s(t)%26%26t.analytics%3D%3D%3D%60no%60%3F!1%3Ae%3F.analyticsProcessingAllowed%3F.()%3F%3F!1%7Dcatch%7Breturn!1%7D%7Dfunction%20x(e)%7Breturn%20typeof%20e%3D%3D%60string%60%26%26h.has(e)%7Dfunction%20S(e)%7Br.warn(%60unsupported%20analytics%20event%20%22%24%7BString(e)%7D%22%60%2C%7Bscope%3A%60analytics%60%7D)%7Dfunction%20C(e)%7Breturn!s(e)%7C%7Ce.analytics%3D%3D%3D%60%60%26%26e.marketing%3D%3D%3D%60%60%26%26e.preferences%3D%3D%3D%60%60%7Dfunction%20w()%7Btry%7Bif(!s(window.privacyBanner))return!1%3Blet%20e%3Dwindow.Shopify%3F.customerPrivacy%2Ct%3De%3F.shouldShowBanner%3Breturn%20typeof%20t%3D%3D%60function%60%3Ft()%26%26C(e%3F.currentVisitorConsent%3F.())%3A!0%7Dcatch%7Breturn!0%7D%7Dfunction%20T(e)%7Breturn%20e%3D%3D%3Dvoid%200%3F%7B%7D%3Ae%7Dfunction%20E(e)%7Bif(typeof%20window%3C%60u%60%26%26window.Shopify%3F.analytics)throw%20Error(%60Analytics%20bus%20already%20initialized.%20Only%20one%20setupStorefrontAnalytics()%20instance%20is%20allowed.%20Call%20destroy()%20first%20to%20re-initialize.%60)%3Blet%7Bconsent%3At%2CcustomData%3An%7D%3De%2Ci%3Dp(e.shop)%2Cs%3D!1%2Cc%3D!1%2Cu%3Dnew%20Map%2Cd%3D0%3Bfunction%20f()%7Breturn%7Bshop%3Ai%2Cconsent%3At%2CcustomData%3An%7D%7Dlet%20m%3Dl(%7BcanTrack%3A()%3D%3E!c%26%26b()%2CgetConfig%3Af%2CisSupportedEvent%3Ax%2CwarnUnsupportedEvent%3AS%7D)%3Bfunction%20h(e%2C...t)%7Bif(s)return%3Bif(!x(e))%7BS(e)%3Breturn%7Dlet%20n%3Dy(e%2Cv(T(t%5B0%5D)%2Ci))%3B(u.get(e)%3F%3Fnew%20Map).forEach((e%2Ct)%3D%3E%7Btry%7Be(n)%7Dcatch(e)%7Br.error(%60analytics%20publish%20error%60%2C%7Bscope%3A%60analytics%60%2Cerror%3Ae%2CsubscriberId%3At%7D)%7D%7D)%2Cm.onPublish(e%2Cn)%7Dfunction%20g(e%2Ct)%7Bif(!x(e))return%20S(e)%2C()%3D%3E%7B%7D%3Blet%20n%3Du.get(e)%3Bn%7C%7C(n%3Dnew%20Map%2Cu.set(e%2Cn))%3Blet%20r%3DString(d%2B%2B)%3Breturn%20n.set(r%2Ct)%2C()%3D%3E%7Bu.get(e)%3F.delete(r)%7D%7Dlet%20_%3Bfunction%20C()%7Bif(typeof%20document%3E%60u%60)return%3Blet%20e%3De%3D%3E%7Bif(s)return%3Blet%20t%3De.detail%3F.source%2Cn%3Dt%3D%3D%3D%60initial%60%26%26w()%3Bif(c%3Dn%2Cn)return%3Blet%20r%3Dt!%3D%3D%60initial%60%3Bm.replay(r)%7D%3Bdocument.addEventListener(a%2Ce)%2C_%3D()%3D%3E%7Bdocument.removeEventListener(a%2Ce)%7D%7Dfunction%20E()%7Bif(typeof%20window%3E%60u%60)return%3Blet%20e%3DO%2Ct%3Do()%3Bt%26%26(t.analytics%3De)%7Dfunction%20D()%7Bs%3D!0%2Cu.clear()%2Cm.destroy()%2C_%3F.()%2Ctypeof%20window%3C%60u%60%26%26window.Shopify%3F.analytics%3D%3D%3DO%26%26delete%20window.Shopify.analytics%7Dlet%20O%3D%7Bpublish%3Ah%2Csubscribe%3Ag%2CaddDestination%3Am.addDestination%2Cdestroy%3AD%2CgetConfig%3Af%7D%3Breturn%20i%3F.shopId%26%26String(i.shopId).endsWith(%60%2F68817551382%60)%26%26r.warn(%60mock%20shop%20detected%3B%20analytics%20will%20not%20work%20properly%60%2C%7Bscope%3A%60analytics%60%7D)%2CC()%2CE()%2CO%7Dfunction%20D(e)%7Be%26%26E(e)%7DD(__SHOPIFY_SCRIPT_DATA__)%7D)()%3B").replace("__SHOPIFY_SCRIPT_DATA__", () => (JSON.stringify(scriptData) ?? "undefined").replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029"));
4
+ const initializeShopifyAnalyticsBus = (scriptData) => decodeURIComponent("(function()%7Blet%20e%3D%7Btrace%3A%60debug%60%2Cdebug%3A%60debug%60%2Cinfo%3A%60info%60%2Cwarn%3A%60warn%60%2Cerror%3A%60error%60%2Cfatal%3A%60error%60%7D%3Bfunction%20t(e%2Ct)%7Breturn%60%5Bhydrogen%3A%24%7Be%7D%3A%24%7Bt%7D%5D%60%7Dfunction%20n(n%2Cr%2Ci)%7Blet%7Bscope%3Aa%2Cerror%3Ao%2C...s%7D%3Di%3F%3F%7B%7D%2Cc%3D%5Ba%3F%60%24%7Bt(n%2Ca)%7D%20%24%7Br%7D%60%3Ar%5D%3Bo!%3D%3Dvoid%200%26%26c.push(o)%2CObject.keys(s).length%3E0%26%26c.push(s)%2Cconsole%5Be%5Bn%5D%5D(...c)%7Dlet%20r%3D%7Btrace%3A(e%2Ct)%3D%3En(%60trace%60%2Ce%2Ct)%2Cdebug%3A(e%2Ct)%3D%3En(%60debug%60%2Ce%2Ct)%2Cinfo%3A(e%2Ct)%3D%3En(%60info%60%2Ce%2Ct)%2Cwarn%3A(e%2Ct)%3D%3En(%60warn%60%2Ce%2Ct)%2Cerror%3A(e%2Ct)%3D%3En(%60error%60%2Ce%2Ct)%2Cfatal%3A(e%2Ct)%3D%3En(%60fatal%60%2Ce%2Ct)%7D%2Ci%3D%60https%3A%2F%2Fcdn.shopify.com%60%3B%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%2C%60%24%7Bi%7D%60%3Blet%20a%3D%60consentTrackingApiLoaded%60%2Co%3D%60visitorConsentCollected%60%3Bfunction%20s()%7Bif(typeof%20window%3E%60u%60)return%3Blet%20e%3Dwindow%3Breturn%20e.Shopify%3F%3F%3D%7B%7D%7Dfunction%20c(e)%7Breturn%20typeof%20e%3D%3D%60object%60%26%26!!e%26%26!Array.isArray(e)%7Dlet%20l%3DSymbol.for(%60shopify.hydrogen.custom-consent%60)%3Bfunction%20u(e)%7Blet%20t%3D(typeof%20window%3E%60u%60%3Fvoid%200%3Awindow.Shopify%3F.customerPrivacy)%3F.__internal%2Cn%3D%7BgenerateFallback%3A!0%2Ctag%3Ae%7D%3Breturn%7BuniqueToken%3At%3F.uniqueToken%3F.(n)%3F%3F%60%60%2CvisitToken%3At%3F.visitToken%3F.(n)%3F%3F%60%60%7D%7Dfunction%20d(e%2Ct)%7Blet%20n%3De.subscriptions.get(t.event)%3Bif(!n%3F.size)%7Be.nextReplaySequence%3DMath.max(e.nextReplaySequence%2Ct.sequence%2B1)%3Breturn%7Dfor(let%20i%20of%20n)try%7Bi(t.payload%2Ce.context)%7Dcatch(t)%7Br.error(%60error%20in%20analytics%20destination%20%22%24%7Be.name%7D%22%60%2C%7Bscope%3A%60analytics%60%2Cerror%3At%7D)%7De.nextReplaySequence%3DMath.max(e.nextReplaySequence%2Ct.sequence%2B1)%7Dfunction%20f(e)%7Blet%20t%3D0%2Cn%3D!0%2Ci%3D%5B%5D%2Ca%3Dnew%20Set%2Co%3Dnew%20Set%3Bfunction%20s(t%3D!1)%7Bif(!e.canTrack())%7Bt%26%26(i.length%3D0%2Cn%3D!1)%3Breturn%7Dn%3D!0%3Bfor(let%20e%20of%20a)for(let%20t%20of%20i)t.sequence%3Ce.nextReplaySequence%7C%7Cd(e%2Ct)%7Dfunction%20c(t)%7Bif(o.has(t.name))return%20r.warn(%60analytics%20destination%20%22%24%7Bt.name%7D%22%20is%20already%20registered%60%2C%7Bscope%3A%60analytics%60%7D)%2C()%3D%3E%7B%7D%3Bo.add(t.name)%3Blet%20n%3D%60hydrogen%3A%24%7Bt.name%7D%60%2Ci%3D%7Bname%3At.name%2Ccontext%3A%7BgetTrackingValues%3A()%3D%3Ee.canTrack()%3Fu(n)%3A%7BuniqueToken%3A%60%60%2CvisitToken%3A%60%60%7D%7D%2Csubscriptions%3Anew%20Map%2CnextReplaySequence%3A0%7D%2Cc%3D!1%2Cl%3D(t%2Cn)%3D%3E%7Bif(c)return()%3D%3E%7B%7D%3Bif(e.isSupportedEvent%26%26!e.isSupportedEvent(t))return%20e.warnUnsupportedEvent%3F.(t)%2C()%3D%3E%7B%7D%3Blet%20r%3Di.subscriptions.get(t)%3Breturn%20r%7C%7C(r%3Dnew%20Set%2Ci.subscriptions.set(t%2Cr))%2Cr.add(n)%2C()%3D%3E%7Blet%20e%3Di.subscriptions.get(t)%3Be%3F.delete(n)%2Ce%3F.size%3D%3D%3D0%26%26i.subscriptions.delete(t)%7D%7D%2Cd%3D()%3D%3E%7Bc%7C%7C(c%3D!0%2Ca.delete(i)%2Co.delete(t.name)%2Ci.subscriptions.clear()%2Ci.cleanup%3F.())%7D%2Cf%3De%3D%3E%7Bif(c)%7Be%3F.()%3Breturn%7Dtypeof%20e%3D%3D%60function%60%26%26(i.cleanup%3De)%2Ca.add(i)%2Cs()%7D%3Btry%7Blet%20n%3Dt.setup(%7Bsubscribe%3Al%2CgetConfig%3Ae.getConfig%7D)%3Bn%26%26typeof%20n.then%3D%3D%60function%60%3Fn.then(f).catch(e%3D%3E%7Br.error(%60error%20setting%20up%20analytics%20destination%20%22%24%7Bt.name%7D%22%60%2C%7Bscope%3A%60analytics%60%2Cerror%3Ae%7D)%2Cd()%7D)%3Af(n)%7Dcatch(e)%7Br.error(%60error%20setting%20up%20analytics%20destination%20%22%24%7Bt.name%7D%22%60%2C%7Bscope%3A%60analytics%60%2Cerror%3Ae%7D)%2Cd()%7Dreturn%20d%7Dfunction%20l(r%2Co)%7Blet%20s%3D%7Bsequence%3At%2B%2B%2Cevent%3Ar%2Cpayload%3Ao%7D%3Bif(n%26%26(i.push(s)%2Ci.length%3E500%26%26i.shift())%2Ce.canTrack())for(let%20e%20of%20a)d(e%2Cs)%7Dfunction%20f()%7Bi.length%3D0%3Bfor(let%20e%20of%20a)e.subscriptions.clear()%2Ce.cleanup%3F.()%3Ba.clear()%2Co.clear()%7Dreturn%7BaddDestination%3Ac%2ConPublish%3Al%2Creplay%3As%2Cdestroy%3Af%7D%7Dlet%20p%3D%7BPAGE_VIEWED%3A%60page_viewed%60%2CPRODUCT_VIEWED%3A%60product_viewed%60%2CCOLLECTION_VIEWED%3A%60collection_viewed%60%2CCART_VIEWED%3A%60cart_viewed%60%2CSEARCH_VIEWED%3A%60search_viewed%60%2CCART_UPDATED%3A%60cart_updated%60%2CPRODUCT_ADD_TO_CART%3A%60product_added_to_cart%60%2CPRODUCT_REMOVED_FROM_CART%3A%60product_removed_from_cart%60%7D%2Cm%3D%60gid%3A%2F%2Fshopify%2FShop%2F%60%3Bfunction%20h(e)%7Breturn%20e.startsWith(m)%3Fe%3A%60%24%7Bm%7D%24%7Be%7D%60%7Dfunction%20g(e)%7Breturn%20e%3F%7B...e%2CshopId%3Ah(e.shopId)%7D%3Anull%7Dlet%20_%3Dnew%20Set(%5Bp.PAGE_VIEWED%2Cp.PRODUCT_VIEWED%2Cp.COLLECTION_VIEWED%2Cp.CART_VIEWED%2Cp.SEARCH_VIEWED%5D)%2Cv%3Dnew%20Set(Object.values(p))%3Bfunction%20y()%7Bif(!(typeof%20window%3E%60u%60))return%20window.location.href%7Dfunction%20b(e%2Ct)%7Breturn%20Object.prototype.hasOwnProperty.call(e%2Ct)%7Dfunction%20x(e%2Ct)%7Breturn%20c(e)%3Fb(e%2C%60shop%60)%3F%7B...e%2Cshop%3Ag(e.shop)%7D%3A%7B...e%2Cshop%3At%7D%3Ae%7Dfunction%20S(e%2Ct)%7Bif(!_.has(e)%7C%7C!c(t)%7C%7Ctypeof%20t.url%3D%3D%60string%60%26%26t.url.length%3E0)return%20t%3Blet%20n%3Dy()%3Breturn%20n%3F%7B...t%2Curl%3An%7D%3At%7Dfunction%20C()%7Btry%7Blet%20e%3Dwindow.Shopify%3F.customerPrivacy%3Bif(e%3F.consentStatus!%3D%3D%60loaded%60)return!1%3Blet%20t%3De.currentVisitorConsent%3F.()%3Breturn%20c(t)%26%26t.analytics%3D%3D%3D%60no%60%3F!1%3Ae%3F.analyticsProcessingAllowed%3F.()%3F%3F!1%7Dcatch%7Breturn!1%7D%7Dfunction%20w(e)%7Breturn%20typeof%20e%3D%3D%60string%60%26%26v.has(e)%7Dfunction%20T(e)%7Br.warn(%60unsupported%20analytics%20event%20%22%24%7BString(e)%7D%22%60%2C%7Bscope%3A%60analytics%60%7D)%7Dfunction%20E()%7Btry%7Blet%20e%3Dwindow.Shopify%3F.customerPrivacy%3Breturn%20typeof%20e%3F.shouldShowGDPRBanner%3D%3D%60function%60%3Fe.shouldShowGDPRBanner()%3A!0%7Dcatch%7Breturn!0%7D%7Dfunction%20D(e)%7Breturn%20e%3D%3D%3Dvoid%200%3F%7B%7D%3Ae%7Dfunction%20O(e)%7Bif(typeof%20window%3C%60u%60%26%26window.Shopify%3F.analytics)throw%20Error(%60Analytics%20bus%20already%20initialized.%20Only%20one%20instance%20is%20allowed%20per%20page.%60)%3Blet%7Bconsent%3At%2CcustomData%3An%7D%3De%2Ci%3Dt%3F.mode%3D%3D%3D%60default-banner%60%2Cu%3Dt%3F.mode%3D%3D%3D%60custom-banner%60%2Cd%3D!u%26%26!i%2Cp%3Dg(e.shop)%2Cm%3D!1%3Bfunction%20h()%7Breturn%7Bshop%3Ap%2Cconsent%3At%2CcustomData%3An%7D%7Dlet%20_%3Df(%7BcanTrack%3A()%3D%3Ed%26%26C()%2CgetConfig%3Ah%2CisSupportedEvent%3Aw%2CwarnUnsupportedEvent%3AT%7D)%3Bfunction%20v(e%2C...t)%7Bif(m)return%3Bif(!w(e))%7BT(e)%3Breturn%7Dlet%20n%3DS(e%2Cx(D(t%5B0%5D)%2Cp))%3B_.onPublish(e%2Cn)%7Dlet%20y%3Bfunction%20b()%7Bif(typeof%20document%3E%60u%60)return%3Blet%20e%2Ct%3D!1%2Cn%3D()%3D%3E%7Bm%7C%7C(d%3D!0%2C_.replay(!0))%7D%2Cs%3Dasync()%3D%3E%7Bif(!(m%7C%7Cwindow.Shopify%3F.customerPrivacy%3F.consentStatus!%3D%3D%60loaded%60))%7Bif(u)%7Bif(!e%7C%7Ct)return%3Bt%3D!0%3Btry%7Bawait%20e()%2Cn()%7Dcatch(e)%7Br.error(%60custom%20consent%20setup%20failed%60%2C%7Bscope%3A%60consent%60%2Cerror%3Ae%7D)%7Dreturn%7Dif(i%7C%7Cc(window.privacyBanner))%7Bif(t)%7B_.replay()%3Breturn%7Dif(t%3D!0%2CE())%7Bd%3D!1%3Breturn%7Dn()%3Breturn%7D_.replay()%7D%7D%2Cf%3D()%3D%3E%7Bm%7C%7Cu%26%26(s()%2C!d)%7C%7C(t%3D!0%2Cn())%7D%3Bu%26%26Object.defineProperty(A%2Cl%2C%7Bvalue(t)%7Be%3F%3F%3Dt%2Cs()%7D%7D)%2Cdocument.addEventListener(a%2Cs)%2Cdocument.addEventListener(o%2Cf)%2Cs()%2Cy%3D()%3D%3E%7Bdocument.removeEventListener(a%2Cs)%2Cdocument.removeEventListener(o%2Cf)%7D%7Dfunction%20O()%7Bif(typeof%20window%3E%60u%60)return%3Blet%20e%3DA%2Ct%3Ds()%3Bt%26%26(t.analytics%3De)%7Dfunction%20k()%7Bm%3D!0%2C_.destroy()%2Cy%3F.()%2Ctypeof%20window%3C%60u%60%26%26window.Shopify%3F.analytics%3D%3D%3DA%26%26delete%20window.Shopify.analytics%7Dlet%20A%3D%7Bpublish%3Av%2CaddDestination%3A_.addDestination%2CgetConfig%3Ah%7D%3Breturn%20p%3F.shopId%26%26String(p.shopId).endsWith(%60%2F68817551382%60)%26%26r.warn(%60mock%20shop%20detected%3B%20analytics%20will%20not%20work%20properly%60%2C%7Bscope%3A%60analytics%60%7D)%2Cb()%2CO()%2C%7Bbus%3AA%2Cdestroy%3Ak%7D%7Dfunction%20k(e)%7Be%26%26O(e)%7Dk(__SHOPIFY_SCRIPT_DATA__)%7D)()%3B").replace("__SHOPIFY_SCRIPT_DATA__", () => (JSON.stringify(scriptData) ?? "undefined").replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029"));
5
5
  function getShopifyAnalyticsConfig({ analytics, consent, shop }) {
6
6
  const channel = analytics?.channel ?? "hydrogen";
7
7
  return {
@@ -13,7 +13,7 @@ function getShopifyAnalyticsConfig({ analytics, consent, shop }) {
13
13
  storefrontId: shop.storefrontId,
14
14
  channel
15
15
  },
16
- consent: consent ?? {},
16
+ consent: consent?.mode ? { mode: consent.mode } : {},
17
17
  customData: analytics?.customData
18
18
  };
19
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"analytics.mjs","names":[],"sources":["../../../../src/core/shopify-scripts/analytics.ts"],"sourcesContent":["import initializeShopifyAnalyticsBus from \"../analytics/cdn/bootstrap\" with { type: \"script\" };\nimport type { StorefrontAnalyticsConfig } from \"../analytics/types\";\nimport type { ShopifyScriptTagsOptions } from \"./types\";\nimport { asInlineScript } from \"./utils/inline-script\";\n\nexport function getShopifyAnalyticsConfig({\n analytics,\n consent,\n shop,\n}: Pick<ShopifyScriptTagsOptions, \"analytics\" | \"consent\" | \"shop\">): StorefrontAnalyticsConfig {\n const channel = analytics?.channel ?? \"hydrogen\";\n\n return {\n shop:\n channel === \"headless\"\n ? { shopId: shop.shopId, channel }\n : { shopId: shop.shopId, storefrontId: shop.storefrontId, channel },\n consent: consent ?? {},\n customData: analytics?.customData,\n };\n}\n\nexport function getShopifyAnalyticsBusScript(analytics: StorefrontAnalyticsConfig): string {\n return asInlineScript(initializeShopifyAnalyticsBus)(analytics);\n}\n"],"mappings":";;;AAAA,MAAM,iCAA+B,eAAkB,mBAAgB,mpPAAuB,CAAA,QAAA,kCAAA,KAAA,UAAA,WAAA,IAAA,aAAA,QAAA,MAAA,UAAA,CAAA,QAAA,WAAA,UAAA,CAAA,QAAA,WAAA,UAAA,CAAA;AAK9F,SAAgB,0BAA0B,EACxC,WACA,SACA,QAC8F;CAC9F,MAAM,UAAU,WAAW,WAAW;AAEtC,QAAO;EACL,MACE,YAAY,aACR;GAAE,QAAQ,KAAK;GAAQ;GAAQ,GAC/B;GAAE,QAAQ,KAAK;GAAQ,cAAc,KAAK;GAAc;GAAS;EACvE,SAAS,WAAW,EAAE;EACtB,YAAY,WAAW;EACxB;;AAGH,SAAgB,6BAA6B,WAA8C;AACzF,QAAO,eAAe,8BAA8B,CAAC,UAAU"}
1
+ {"version":3,"file":"analytics.mjs","names":[],"sources":["../../../../src/core/shopify-scripts/analytics.ts"],"sourcesContent":["import initializeShopifyAnalyticsBus from \"../analytics/cdn/bootstrap\" with { type: \"script\" };\nimport type { StorefrontAnalyticsConfig } from \"../analytics/types\";\nimport type { ShopifyScriptTagsOptions } from \"./types\";\nimport { asInlineScript } from \"./utils/inline-script\";\n\nexport function getShopifyAnalyticsConfig({\n analytics,\n consent,\n shop,\n}: Pick<ShopifyScriptTagsOptions, \"analytics\" | \"consent\" | \"shop\">): StorefrontAnalyticsConfig {\n const channel = analytics?.channel ?? \"hydrogen\";\n\n return {\n shop:\n channel === \"headless\"\n ? { shopId: shop.shopId, channel }\n : { shopId: shop.shopId, storefrontId: shop.storefrontId, channel },\n consent: consent?.mode ? { mode: consent.mode } : {},\n customData: analytics?.customData,\n };\n}\n\nexport function getShopifyAnalyticsBusScript(analytics: StorefrontAnalyticsConfig): string {\n return asInlineScript(initializeShopifyAnalyticsBus)(analytics);\n}\n"],"mappings":";;;AAAA,MAAM,iCAA+B,eAAkB,mBAAgB,ioQAAuB,CAAA,QAAA,kCAAA,KAAA,UAAA,WAAA,IAAA,aAAA,QAAA,MAAA,UAAA,CAAA,QAAA,WAAA,UAAA,CAAA,QAAA,WAAA,UAAA,CAAA;AAK9F,SAAgB,0BAA0B,EACxC,WACA,SACA,QAC8F;CAC9F,MAAM,UAAU,WAAW,WAAW;AAEtC,QAAO;EACL,MACE,YAAY,aACR;GAAE,QAAQ,KAAK;GAAQ;GAAQ,GAC/B;GAAE,QAAQ,KAAK;GAAQ,cAAc,KAAK;GAAc;GAAS;EACvE,SAAS,SAAS,OAAO,EAAE,MAAM,QAAQ,MAAM,GAAG,EAAE;EACpD,YAAY,WAAW;EACxB;;AAGH,SAAgB,6BAA6B,WAA8C;AACzF,QAAO,eAAe,8BAA8B,CAAC,UAAU"}
@@ -4,7 +4,8 @@ const SHOPIFY_SHOP_APP_ORIGIN = "https://shop.app";
4
4
  const SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/standard-actions.js`;
5
5
  const SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/standard-events.js`;
6
6
  const SHOPIFY_STOREFRONT_STANDARD_EVENTS_INSPECTOR_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/standard-events-inspector.js`;
7
- const SHOPIFY_STOREFRONT_WEBMCP_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/webmcp.js`;
7
+ const SHOPIFY_STOREFRONT_WEBMCP_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/storefront/webmcp/webmcp.js`;
8
+ const SHOPIFY_ACCOUNT_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/web-components/account.js`;
8
9
  const SHOPIFY_INBOX_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/web-components/agent.js`;
9
10
  const SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/analytics/shopify.js`;
10
11
  const SHOPIFY_PERF_KIT_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/perf-kit/shopify-perf-kit-spa.min.js?v2`;
@@ -12,8 +13,9 @@ const SHOPIFY_CONSENT_API_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/consent-t
12
13
  const SHOPIFY_PRIVACY_BANNER_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/privacy-banner/storefront-banner.js`;
13
14
  const SHOPIFY_CONSENT_SCRIPT_ID = "shopify-consent";
14
15
  const SHOPIFY_PERF_KIT_SCRIPT_ID = "shopify-perfkit";
16
+ const CONSENT_TRACKING_API_LOADED_EVENT = "consentTrackingApiLoaded";
15
17
  const VISITOR_CONSENT_COLLECTED_EVENT = "visitorConsentCollected";
16
18
 
17
19
  //#endregion
18
- export { SHOPIFY_CDN_ORIGIN, SHOPIFY_CONSENT_API_SCRIPT, SHOPIFY_CONSENT_SCRIPT_ID, SHOPIFY_INBOX_SCRIPT, SHOPIFY_PERF_KIT_SCRIPT, SHOPIFY_PERF_KIT_SCRIPT_ID, SHOPIFY_PRIVACY_BANNER_SCRIPT, SHOPIFY_SHOP_APP_ORIGIN, SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_EVENTS_INSPECTOR_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT, SHOPIFY_STOREFRONT_WEBMCP_SCRIPT, VISITOR_CONSENT_COLLECTED_EVENT };
20
+ export { CONSENT_TRACKING_API_LOADED_EVENT, SHOPIFY_ACCOUNT_SCRIPT, SHOPIFY_CDN_ORIGIN, SHOPIFY_CONSENT_API_SCRIPT, SHOPIFY_CONSENT_SCRIPT_ID, SHOPIFY_INBOX_SCRIPT, SHOPIFY_PERF_KIT_SCRIPT, SHOPIFY_PERF_KIT_SCRIPT_ID, SHOPIFY_PRIVACY_BANNER_SCRIPT, SHOPIFY_SHOP_APP_ORIGIN, SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_EVENTS_INSPECTOR_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT, SHOPIFY_STOREFRONT_WEBMCP_SCRIPT, VISITOR_CONSENT_COLLECTED_EVENT };
19
21
  //# sourceMappingURL=constants.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.mjs","names":[],"sources":["../../../../src/core/shopify-scripts/constants.ts"],"sourcesContent":["export const SHOPIFY_CDN_ORIGIN = \"https://cdn.shopify.com\";\nexport const SHOPIFY_SHOP_APP_ORIGIN = \"https://shop.app\";\nexport const SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/standard-actions.js`;\nexport const SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/standard-events.js`;\nexport const SHOPIFY_STOREFRONT_STANDARD_EVENTS_INSPECTOR_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/standard-events-inspector.js`;\nexport const SHOPIFY_STOREFRONT_WEBMCP_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/webmcp.js`;\nexport const SHOPIFY_INBOX_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/web-components/agent.js`;\n\nexport const SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/analytics/shopify.js`;\n\nexport const SHOPIFY_PERF_KIT_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/perf-kit/shopify-perf-kit-spa.min.js?v2`;\nexport const SHOPIFY_CONSENT_API_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/consent-tracking-api/v0.2/consent-tracking-api.js`;\nexport const SHOPIFY_PRIVACY_BANNER_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/privacy-banner/storefront-banner.js`;\n\nexport const SHOPIFY_CONSENT_SCRIPT_ID = \"shopify-consent\";\nexport const SHOPIFY_PERF_KIT_SCRIPT_ID = \"shopify-perfkit\";\n\nexport const VISITOR_CONSENT_COLLECTED_EVENT = \"visitorConsentCollected\";\n"],"mappings":";AAAA,MAAa,qBAAqB;AAClC,MAAa,0BAA0B;AACvC,MAAa,6CAA6C,GAAG,mBAAmB;AAChF,MAAa,4CAA4C,GAAG,mBAAmB;AAC/E,MAAa,sDAAsD,GAAG,mBAAmB;AACzF,MAAa,mCAAmC,GAAG,mBAAmB;AACtE,MAAa,uBAAuB,GAAG,mBAAmB;AAE1D,MAAa,sCAAsC,GAAG,mBAAmB;AAEzE,MAAa,0BAA0B,GAAG,mBAAmB;AAC7D,MAAa,6BAA6B,GAAG,mBAAmB;AAChE,MAAa,gCAAgC,GAAG,mBAAmB;AAEnE,MAAa,4BAA4B;AACzC,MAAa,6BAA6B;AAE1C,MAAa,kCAAkC"}
1
+ {"version":3,"file":"constants.mjs","names":[],"sources":["../../../../src/core/shopify-scripts/constants.ts"],"sourcesContent":["export const SHOPIFY_CDN_ORIGIN = \"https://cdn.shopify.com\";\nexport const SHOPIFY_SHOP_APP_ORIGIN = \"https://shop.app\";\nexport const SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/standard-actions.js`;\nexport const SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/standard-events.js`;\nexport const SHOPIFY_STOREFRONT_STANDARD_EVENTS_INSPECTOR_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/standard-events-inspector.js`;\nexport const SHOPIFY_STOREFRONT_WEBMCP_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/storefront/webmcp/webmcp.js`;\nexport const SHOPIFY_ACCOUNT_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/web-components/account.js`;\nexport const SHOPIFY_INBOX_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/web-components/agent.js`;\n\nexport const SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/storefront/analytics/shopify.js`;\n\nexport const SHOPIFY_PERF_KIT_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/perf-kit/shopify-perf-kit-spa.min.js?v2`;\nexport const SHOPIFY_CONSENT_API_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/consent-tracking-api/v0.2/consent-tracking-api.js`;\nexport const SHOPIFY_PRIVACY_BANNER_SCRIPT = `${SHOPIFY_CDN_ORIGIN}/shopifycloud/privacy-banner/storefront-banner.js`;\n\nexport const SHOPIFY_CONSENT_SCRIPT_ID = \"shopify-consent\";\nexport const SHOPIFY_PERF_KIT_SCRIPT_ID = \"shopify-perfkit\";\n\nexport const CONSENT_TRACKING_API_LOADED_EVENT = \"consentTrackingApiLoaded\";\nexport const VISITOR_CONSENT_COLLECTED_EVENT = \"visitorConsentCollected\";\n"],"mappings":";AAAA,MAAa,qBAAqB;AAClC,MAAa,0BAA0B;AACvC,MAAa,6CAA6C,GAAG,mBAAmB;AAChF,MAAa,4CAA4C,GAAG,mBAAmB;AAC/E,MAAa,sDAAsD,GAAG,mBAAmB;AACzF,MAAa,mCAAmC,GAAG,mBAAmB;AACtE,MAAa,yBAAyB,GAAG,mBAAmB;AAC5D,MAAa,uBAAuB,GAAG,mBAAmB;AAE1D,MAAa,sCAAsC,GAAG,mBAAmB;AAEzE,MAAa,0BAA0B,GAAG,mBAAmB;AAC7D,MAAa,6BAA6B,GAAG,mBAAmB;AAChE,MAAa,gCAAgC,GAAG,mBAAmB;AAEnE,MAAa,4BAA4B;AACzC,MAAa,6BAA6B;AAE1C,MAAa,oCAAoC;AACjD,MAAa,kCAAkC"}
@@ -73,10 +73,15 @@ function getShopifyGlobalBootstrapScript({ i18n, shop }) {
73
73
  apiProxyPrefix: SHOPIFY_API_PROXY_PREFIX
74
74
  },
75
75
  shop: normalizeMyshopifyDomain(shop.myshopifyDomain),
76
- customerPrivacy: {
77
- config: { isHeadless: true },
78
- consentStatus: "pending"
79
- }
76
+ customerPrivacy: { config: {
77
+ isHeadless: true,
78
+ asyncConsent: true,
79
+ asyncVisitorState: true,
80
+ debug: { hydrogen: {
81
+ generation: 3,
82
+ serverTiming: false
83
+ } }
84
+ } }
80
85
  };
81
86
  return asInlineScript(initializeShopifyGlobal)(config);
82
87
  }
@@ -1 +1 @@
1
- {"version":3,"file":"global.mjs","names":[],"sources":["../../../../src/core/shopify-scripts/global.ts"],"sourcesContent":["import type { ShopifyGlobal } from \"../../globals\";\nimport type { I18nConfig } from \"../request-context\";\nimport {\n matchStandardRouteUrl,\n resolveStandardRouteUrl,\n type ShopifyRouteTemplates,\n} from \"../standard-routes/index\";\nimport { SHOPIFY_API_PROXY_PREFIX, isHydrogenServerHandoffPath } from \"../url\";\nimport initializeShopifyGlobal from \"./global-script\" with { type: \"script\" };\nimport type { ShopifyScriptsI18n } from \"./types\";\nimport type { ShopifyScriptsShop } from \"./types\";\nimport { asInlineScript } from \"./utils/inline-script\";\n\nexport type ShopifyGlobalConfig = {\n country: I18nConfig[\"country\"];\n currency?: NonNullable<ShopifyGlobal[\"currency\"]>;\n locale: Lowercase<I18nConfig[\"language\"]>;\n customerPrivacy: {\n config: NonNullable<ShopifyGlobal[\"customerPrivacy\"][\"config\"]>;\n consentStatus: NonNullable<ShopifyGlobal[\"customerPrivacy\"][\"consentStatus\"]>;\n };\n routes: {\n root: string;\n apiProxyPrefix: string;\n };\n shop: string;\n};\n\nexport type IncompleteCustomerPrivacy = Partial<\n Omit<ShopifyGlobal[\"customerPrivacy\"], \"config\">\n> & {\n config?: Partial<NonNullable<ShopifyGlobal[\"customerPrivacy\"][\"config\"]>>;\n};\n\nexport type IncompleteShopifyGlobal = Partial<Omit<ShopifyGlobal, \"customerPrivacy\" | \"routes\">> & {\n customerPrivacy?: IncompleteCustomerPrivacy;\n routes?: Partial<ShopifyGlobal[\"routes\"]> & Record<string, unknown>;\n [key: string]: unknown;\n};\n\nconst DEFAULT_COUNTRY: ShopifyGlobalConfig[\"country\"] = \"US\";\nconst DEFAULT_LOCALE: ShopifyGlobalConfig[\"locale\"] = \"en\";\nconst DEFAULT_ROUTES_ROOT: ShopifyGlobalConfig[\"routes\"][\"root\"] = \"/\";\n\n/**\n * Returns the browser's `window.Shopify` object, creating it when needed.\n *\n * This is SSR-safe and returns `undefined` outside the browser.\n */\nexport function getShopifyGlobal(): IncompleteShopifyGlobal | undefined {\n if (typeof window === \"undefined\") return undefined;\n\n const shopifyWindow: { Shopify?: IncompleteShopifyGlobal } = window;\n return (shopifyWindow.Shopify ??= {});\n}\n\n/**\n * Configures Shopify runtime routing hooks used by storefront scripts.\n *\n * This is SSR-safe and no-ops outside the browser.\n */\nexport function configureShopifyRouting({\n navigate,\n routes,\n}: {\n navigate?: ShopifyGlobal[\"routes\"][\"navigate\"];\n routes?: ShopifyRouteTemplates;\n}) {\n const shopify = getShopifyGlobal();\n if (!shopify) return;\n\n const getRouteOptions = (url: string) => ({\n baseUrl: window.location.href,\n pathPrefix: shopify.routes?.root,\n routeTemplates: routes ?? {},\n url,\n });\n\n shopify.routes ??= {};\n shopify.routes.match = (url) => matchStandardRouteUrl(getRouteOptions(url));\n shopify.routes.resolve = (url) => resolveStandardRouteUrl(getRouteOptions(url));\n\n const navigateTo = navigate ?? documentNavigate;\n shopify.routes.navigate = (url) => {\n if (shouldHandoff(url)) {\n return documentNavigate(url);\n }\n\n return navigateTo(shopify.routes?.resolve?.(url) ?? url);\n };\n // Deprecated, kept for temporary backwards compat with WebMCP\n shopify.navigate = shopify.routes.navigate;\n}\n\nfunction documentNavigate(url: string): void {\n window.location.assign(url);\n}\n\nfunction shouldHandoff(url: string): boolean {\n try {\n const parsedUrl = new URL(url, window.location.href);\n\n return (\n parsedUrl.origin === window.location.origin && isHydrogenServerHandoffPath(parsedUrl.pathname)\n );\n } catch {\n return false;\n }\n}\n\nfunction getShopifyRoutesRoot(pathPrefix: I18nConfig[\"pathPrefix\"]): string {\n const normalizedPathPrefix = pathPrefix?.trim().replace(/^\\/+/, \"\").replace(/\\/+$/, \"\") ?? \"\";\n\n return normalizedPathPrefix ? `/${normalizedPathPrefix}/` : DEFAULT_ROUTES_ROOT;\n}\n\nfunction normalizeMyshopifyDomain(domain: string): string {\n return domain\n .trim()\n .replace(/^https?:\\/\\//i, \"\")\n .replace(/\\/+$/, \"\");\n}\n\n/**\n * Builds the inline bootstrap script that initializes `window.Shopify` for storefront scripts.\n */\nexport function getShopifyGlobalBootstrapScript({\n i18n,\n shop,\n}: {\n i18n?: ShopifyScriptsI18n;\n shop: ShopifyScriptsShop;\n}): string {\n const config: ShopifyGlobalConfig = {\n country: i18n?.country ?? DEFAULT_COUNTRY,\n ...(i18n?.currency !== undefined ? { currency: { active: i18n.currency.toUpperCase() } } : {}),\n // oxlint-disable-next-line typescript/consistent-type-assertions\n locale: (i18n?.language ?? DEFAULT_LOCALE).toLowerCase() as Lowercase<\n ShopifyGlobalConfig[\"locale\"]\n >,\n routes: {\n root: getShopifyRoutesRoot(i18n?.pathPrefix),\n apiProxyPrefix: SHOPIFY_API_PROXY_PREFIX,\n },\n shop: normalizeMyshopifyDomain(shop.myshopifyDomain),\n customerPrivacy: {\n config: {\n isHeadless: true,\n },\n consentStatus: \"pending\",\n },\n };\n\n return asInlineScript(initializeShopifyGlobal)(config);\n}\n"],"mappings":";;;;;;AAQA,MAAM,2BAAyB,eAAe,mBAAsB,sUAAS,CAAA,QAAA,kCAAA,KAAA,UAAA,WAAA,IAAA,aAAA,QAAA,MAAA,UAAA,CAAA,QAAA,WAAA,UAAA,CAAA,QAAA,WAAA,UAAA,CAAA;AAgC7E,MAAM,kBAAkD;AACxD,MAAM,iBAAgD;AACtD,MAAM,sBAA6D;;;;;;AAOnE,SAAgB,mBAAwD;AACtE,KAAI,OAAO,WAAW,YAAa,QAAO;CAE1C,MAAM,gBAAuD;AAC7D,QAAQ,cAAc,YAAY,EAAE;;;;;;;AAQtC,SAAgB,wBAAwB,EACtC,UACA,UAIC;CACD,MAAM,UAAU,kBAAkB;AAClC,KAAI,CAAC,QAAS;CAEd,MAAM,mBAAmB,SAAiB;EACxC,SAAS,OAAO,SAAS;EACzB,YAAY,QAAQ,QAAQ;EAC5B,gBAAgB,UAAU,EAAE;EAC5B;EACD;AAED,SAAQ,WAAW,EAAE;AACrB,SAAQ,OAAO,SAAS,QAAQ,sBAAsB,gBAAgB,IAAI,CAAC;AAC3E,SAAQ,OAAO,WAAW,QAAQ,wBAAwB,gBAAgB,IAAI,CAAC;CAE/E,MAAM,aAAa,YAAY;AAC/B,SAAQ,OAAO,YAAY,QAAQ;AACjC,MAAI,cAAc,IAAI,CACpB,QAAO,iBAAiB,IAAI;AAG9B,SAAO,WAAW,QAAQ,QAAQ,UAAU,IAAI,IAAI,IAAI;;AAG1D,SAAQ,WAAW,QAAQ,OAAO;;AAGpC,SAAS,iBAAiB,KAAmB;AAC3C,QAAO,SAAS,OAAO,IAAI;;AAG7B,SAAS,cAAc,KAAsB;AAC3C,KAAI;EACF,MAAM,YAAY,IAAI,IAAI,KAAK,OAAO,SAAS,KAAK;AAEpD,SACE,UAAU,WAAW,OAAO,SAAS,UAAU,4BAA4B,UAAU,SAAQ;SAEzF;AACN,SAAO;;;AAIX,SAAS,qBAAqB,YAA8C;CAC1E,MAAM,uBAAuB,YAAY,MAAM,CAAC,QAAQ,QAAQ,GAAG,CAAC,QAAQ,QAAQ,GAAG,IAAI;AAE3F,QAAO,uBAAuB,IAAI,qBAAqB,KAAK;;AAG9D,SAAS,yBAAyB,QAAwB;AACxD,QAAO,OACJ,MAAK,CACL,QAAQ,iBAAiB,GAAE,CAC3B,QAAQ,QAAQ,GAAG;;;;;AAMxB,SAAgB,gCAAgC,EAC9C,MACA,QAIS;CACT,MAAM,SAA8B;EAClC,SAAS,MAAM,WAAW;EAC1B,GAAI,MAAM,aAAa,SAAY,EAAE,UAAU,EAAE,QAAQ,KAAK,SAAS,aAAa,EAAE,EAAE,GAAG,EAAE;EAE7F,SAAS,MAAM,YAAY,gBAAgB,aAAa;EAGxD,QAAQ;GACN,MAAM,qBAAqB,MAAM,WAAW;GAC5C,gBAAgB;GACjB;EACD,MAAM,yBAAyB,KAAK,gBAAgB;EACpD,iBAAiB;GACf,QAAQ,EACN,YAAY,MACb;GACD,eAAe;GAChB;EACF;AAED,QAAO,eAAe,wBAAwB,CAAC,OAAO"}
1
+ {"version":3,"file":"global.mjs","names":[],"sources":["../../../../src/core/shopify-scripts/global.ts"],"sourcesContent":["import type { ShopifyGlobal } from \"../../globals\";\nimport type { I18nConfig } from \"../request-context\";\nimport {\n matchStandardRouteUrl,\n resolveStandardRouteUrl,\n type ShopifyRouteTemplates,\n} from \"../standard-routes/index\";\nimport { SHOPIFY_API_PROXY_PREFIX, isHydrogenServerHandoffPath } from \"../url\";\nimport initializeShopifyGlobal from \"./global-script\" with { type: \"script\" };\nimport type { ShopifyScriptsI18n } from \"./types\";\nimport type { ShopifyScriptsShop } from \"./types\";\nimport { asInlineScript } from \"./utils/inline-script\";\n\nexport type ShopifyGlobalConfig = {\n country: I18nConfig[\"country\"];\n currency?: NonNullable<ShopifyGlobal[\"currency\"]>;\n locale: Lowercase<I18nConfig[\"language\"]>;\n customerPrivacy: {\n config: NonNullable<ShopifyGlobal[\"customerPrivacy\"][\"config\"]> & {\n /** Temporary diagnostic metadata for instrumentation; does not change consent or token behavior. */\n debug: {\n hydrogen: {\n generation: number;\n serverTiming: boolean;\n };\n };\n };\n };\n routes: {\n root: string;\n apiProxyPrefix: string;\n };\n shop: string;\n};\n\nexport type IncompleteCustomerPrivacy = Partial<\n Omit<ShopifyGlobal[\"customerPrivacy\"], \"config\">\n> & {\n config?: Partial<NonNullable<ShopifyGlobal[\"customerPrivacy\"][\"config\"]>>;\n};\n\nexport type IncompleteShopifyGlobal = Partial<Omit<ShopifyGlobal, \"customerPrivacy\" | \"routes\">> & {\n customerPrivacy?: IncompleteCustomerPrivacy;\n routes?: Partial<ShopifyGlobal[\"routes\"]> & Record<string, unknown>;\n [key: string]: unknown;\n};\n\nconst DEFAULT_COUNTRY: ShopifyGlobalConfig[\"country\"] = \"US\";\nconst DEFAULT_LOCALE: ShopifyGlobalConfig[\"locale\"] = \"en\";\nconst DEFAULT_ROUTES_ROOT: ShopifyGlobalConfig[\"routes\"][\"root\"] = \"/\";\n\n/**\n * Returns the browser's `window.Shopify` object, creating it when needed.\n *\n * This is SSR-safe and returns `undefined` outside the browser.\n */\nexport function getShopifyGlobal(): IncompleteShopifyGlobal | undefined {\n if (typeof window === \"undefined\") return undefined;\n\n const shopifyWindow: { Shopify?: IncompleteShopifyGlobal } = window;\n return (shopifyWindow.Shopify ??= {});\n}\n\n/**\n * Configures Shopify runtime routing hooks used by storefront scripts.\n *\n * This is SSR-safe and no-ops outside the browser.\n */\nexport function configureShopifyRouting({\n navigate,\n routes,\n}: {\n navigate?: ShopifyGlobal[\"routes\"][\"navigate\"];\n routes?: ShopifyRouteTemplates;\n}) {\n const shopify = getShopifyGlobal();\n if (!shopify) return;\n\n const getRouteOptions = (url: string) => ({\n baseUrl: window.location.href,\n pathPrefix: shopify.routes?.root,\n routeTemplates: routes ?? {},\n url,\n });\n\n shopify.routes ??= {};\n shopify.routes.match = (url) => matchStandardRouteUrl(getRouteOptions(url));\n shopify.routes.resolve = (url) => resolveStandardRouteUrl(getRouteOptions(url));\n\n const navigateTo = navigate ?? documentNavigate;\n shopify.routes.navigate = (url) => {\n if (shouldHandoff(url)) {\n return documentNavigate(url);\n }\n\n return navigateTo(shopify.routes?.resolve?.(url) ?? url);\n };\n // Deprecated, kept for temporary backwards compat with WebMCP\n shopify.navigate = shopify.routes.navigate;\n}\n\nfunction documentNavigate(url: string): void {\n window.location.assign(url);\n}\n\nfunction shouldHandoff(url: string): boolean {\n try {\n const parsedUrl = new URL(url, window.location.href);\n\n return (\n parsedUrl.origin === window.location.origin && isHydrogenServerHandoffPath(parsedUrl.pathname)\n );\n } catch {\n return false;\n }\n}\n\nfunction getShopifyRoutesRoot(pathPrefix: I18nConfig[\"pathPrefix\"]): string {\n const normalizedPathPrefix = pathPrefix?.trim().replace(/^\\/+/, \"\").replace(/\\/+$/, \"\") ?? \"\";\n\n return normalizedPathPrefix ? `/${normalizedPathPrefix}/` : DEFAULT_ROUTES_ROOT;\n}\n\nfunction normalizeMyshopifyDomain(domain: string): string {\n return domain\n .trim()\n .replace(/^https?:\\/\\//i, \"\")\n .replace(/\\/+$/, \"\");\n}\n\n/**\n * Builds the inline bootstrap script that initializes `window.Shopify` for storefront scripts.\n */\nexport function getShopifyGlobalBootstrapScript({\n i18n,\n shop,\n}: {\n i18n?: ShopifyScriptsI18n;\n shop: ShopifyScriptsShop;\n}): string {\n const config: ShopifyGlobalConfig = {\n country: i18n?.country ?? DEFAULT_COUNTRY,\n ...(i18n?.currency !== undefined ? { currency: { active: i18n.currency.toUpperCase() } } : {}),\n // oxlint-disable-next-line typescript/consistent-type-assertions\n locale: (i18n?.language ?? DEFAULT_LOCALE).toLowerCase() as Lowercase<\n ShopifyGlobalConfig[\"locale\"]\n >,\n routes: {\n root: getShopifyRoutesRoot(i18n?.pathPrefix),\n apiProxyPrefix: SHOPIFY_API_PROXY_PREFIX,\n },\n shop: normalizeMyshopifyDomain(shop.myshopifyDomain),\n customerPrivacy: {\n config: {\n isHeadless: true,\n asyncConsent: true,\n asyncVisitorState: true,\n debug: {\n hydrogen: {\n generation: 3,\n serverTiming: false,\n },\n },\n },\n },\n };\n\n return asInlineScript(initializeShopifyGlobal)(config);\n}\n"],"mappings":";;;;;;AAQA,MAAM,2BAAyB,eAAe,mBAAsB,sUAAS,CAAA,QAAA,kCAAA,KAAA,UAAA,WAAA,IAAA,aAAA,QAAA,MAAA,UAAA,CAAA,QAAA,WAAA,UAAA,CAAA,QAAA,WAAA,UAAA,CAAA;AAuC7E,MAAM,kBAAkD;AACxD,MAAM,iBAAgD;AACtD,MAAM,sBAA6D;;;;;;AAOnE,SAAgB,mBAAwD;AACtE,KAAI,OAAO,WAAW,YAAa,QAAO;CAE1C,MAAM,gBAAuD;AAC7D,QAAQ,cAAc,YAAY,EAAE;;;;;;;AAQtC,SAAgB,wBAAwB,EACtC,UACA,UAIC;CACD,MAAM,UAAU,kBAAkB;AAClC,KAAI,CAAC,QAAS;CAEd,MAAM,mBAAmB,SAAiB;EACxC,SAAS,OAAO,SAAS;EACzB,YAAY,QAAQ,QAAQ;EAC5B,gBAAgB,UAAU,EAAE;EAC5B;EACD;AAED,SAAQ,WAAW,EAAE;AACrB,SAAQ,OAAO,SAAS,QAAQ,sBAAsB,gBAAgB,IAAI,CAAC;AAC3E,SAAQ,OAAO,WAAW,QAAQ,wBAAwB,gBAAgB,IAAI,CAAC;CAE/E,MAAM,aAAa,YAAY;AAC/B,SAAQ,OAAO,YAAY,QAAQ;AACjC,MAAI,cAAc,IAAI,CACpB,QAAO,iBAAiB,IAAI;AAG9B,SAAO,WAAW,QAAQ,QAAQ,UAAU,IAAI,IAAI,IAAI;;AAG1D,SAAQ,WAAW,QAAQ,OAAO;;AAGpC,SAAS,iBAAiB,KAAmB;AAC3C,QAAO,SAAS,OAAO,IAAI;;AAG7B,SAAS,cAAc,KAAsB;AAC3C,KAAI;EACF,MAAM,YAAY,IAAI,IAAI,KAAK,OAAO,SAAS,KAAK;AAEpD,SACE,UAAU,WAAW,OAAO,SAAS,UAAU,4BAA4B,UAAU,SAAQ;SAEzF;AACN,SAAO;;;AAIX,SAAS,qBAAqB,YAA8C;CAC1E,MAAM,uBAAuB,YAAY,MAAM,CAAC,QAAQ,QAAQ,GAAG,CAAC,QAAQ,QAAQ,GAAG,IAAI;AAE3F,QAAO,uBAAuB,IAAI,qBAAqB,KAAK;;AAG9D,SAAS,yBAAyB,QAAwB;AACxD,QAAO,OACJ,MAAK,CACL,QAAQ,iBAAiB,GAAE,CAC3B,QAAQ,QAAQ,GAAG;;;;;AAMxB,SAAgB,gCAAgC,EAC9C,MACA,QAIS;CACT,MAAM,SAA8B;EAClC,SAAS,MAAM,WAAW;EAC1B,GAAI,MAAM,aAAa,SAAY,EAAE,UAAU,EAAE,QAAQ,KAAK,SAAS,aAAa,EAAE,EAAE,GAAG,EAAE;EAE7F,SAAS,MAAM,YAAY,gBAAgB,aAAa;EAGxD,QAAQ;GACN,MAAM,qBAAqB,MAAM,WAAW;GAC5C,gBAAgB;GACjB;EACD,MAAM,yBAAyB,KAAK,gBAAgB;EACpD,iBAAiB,EACf,QAAQ;GACN,YAAY;GACZ,cAAc;GACd,mBAAmB;GACnB,OAAO,EACL,UAAU;IACR,YAAY;IACZ,cAAc;IACf,EACF;GACF,EACF;EACF;AAED,QAAO,eAAe,wBAAwB,CAAC,OAAO"}
@@ -9,6 +9,7 @@ import { initializeShopifyScripts } from "./initialize.mjs";
9
9
  * `initializeShopifyScripts()` during browser hydration.
10
10
  */
11
11
  declare function getShopifyScriptTags({
12
+ account,
12
13
  analytics,
13
14
  consent,
14
15
  debug,
@@ -1,6 +1,5 @@
1
1
  import { getShopifyAnalyticsBusScript, getShopifyAnalyticsConfig } from "./analytics.mjs";
2
- import { SHOPIFY_CDN_ORIGIN, SHOPIFY_CONSENT_API_SCRIPT, SHOPIFY_CONSENT_SCRIPT_ID, SHOPIFY_INBOX_SCRIPT, SHOPIFY_PERF_KIT_SCRIPT, SHOPIFY_PRIVACY_BANNER_SCRIPT, SHOPIFY_SHOP_APP_ORIGIN, SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_EVENTS_INSPECTOR_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT, SHOPIFY_STOREFRONT_WEBMCP_SCRIPT, VISITOR_CONSENT_COLLECTED_EVENT } from "./constants.mjs";
3
- import { getShopifyConsentTrackingScript } from "./consent.mjs";
2
+ import { CONSENT_TRACKING_API_LOADED_EVENT, SHOPIFY_ACCOUNT_SCRIPT, SHOPIFY_CDN_ORIGIN, SHOPIFY_CONSENT_API_SCRIPT, SHOPIFY_CONSENT_SCRIPT_ID, SHOPIFY_INBOX_SCRIPT, SHOPIFY_PERF_KIT_SCRIPT, SHOPIFY_PRIVACY_BANNER_SCRIPT, SHOPIFY_SHOP_APP_ORIGIN, SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_EVENTS_INSPECTOR_SCRIPT, SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT, SHOPIFY_STOREFRONT_WEBMCP_SCRIPT, VISITOR_CONSENT_COLLECTED_EVENT } from "./constants.mjs";
4
3
  import { getShopifyGlobal, getShopifyGlobalBootstrapScript } from "./global.mjs";
5
4
  import { getPerfKitScript } from "./perfkit.mjs";
6
5
  import { renderShopifyScriptTag } from "./render.mjs";
@@ -14,7 +13,7 @@ import { initializeShopifyScripts } from "./initialize.mjs";
14
13
  * component. Frameworks without a binding can render these descriptors during SSR and call
15
14
  * `initializeShopifyScripts()` during browser hydration.
16
15
  */
17
- function getShopifyScriptTags({ analytics, consent, debug, i18n, nonce, shop, shopifyAnalytics = true, inbox = false }) {
16
+ function getShopifyScriptTags({ account = false, analytics, consent, debug, i18n, nonce, shop, shopifyAnalytics = true, inbox = false }) {
18
17
  const nonceAttributes = nonce !== void 0 ? { nonce } : void 0;
19
18
  const analyticsConfig = getShopifyAnalyticsConfig({
20
19
  analytics,
@@ -87,31 +86,34 @@ function getShopifyScriptTags({ analytics, consent, debug, i18n, nonce, shop, sh
87
86
  src: SHOPIFY_INBOX_SCRIPT
88
87
  }
89
88
  });
90
- scripts.push({
89
+ if (account) scripts.push({
91
90
  tagName: "script",
92
91
  attributes: {
93
- id: SHOPIFY_CONSENT_SCRIPT_ID,
92
+ id: "shopify-account",
93
+ type: "module",
94
94
  async: true,
95
95
  crossorigin: "anonymous",
96
96
  ...nonceAttributes,
97
- src: consent?.mode === "default-banner" ? SHOPIFY_PRIVACY_BANNER_SCRIPT : SHOPIFY_CONSENT_API_SCRIPT
97
+ src: SHOPIFY_ACCOUNT_SCRIPT
98
98
  }
99
99
  });
100
100
  scripts.push({
101
101
  tagName: "script",
102
102
  attributes: {
103
- id: "shopify-consent-bootstrap",
103
+ id: "shopify-analytics-bus",
104
104
  ...nonceAttributes
105
105
  },
106
- innerHTML: getShopifyConsentTrackingScript(consent)
106
+ innerHTML: getShopifyAnalyticsBusScript(analyticsConfig)
107
107
  });
108
108
  scripts.push({
109
109
  tagName: "script",
110
110
  attributes: {
111
- id: "shopify-analytics-bus",
112
- ...nonceAttributes
113
- },
114
- innerHTML: getShopifyAnalyticsBusScript(analyticsConfig)
111
+ id: SHOPIFY_CONSENT_SCRIPT_ID,
112
+ async: true,
113
+ crossorigin: "anonymous",
114
+ ...nonceAttributes,
115
+ src: consent?.mode === "default-banner" ? SHOPIFY_PRIVACY_BANNER_SCRIPT : SHOPIFY_CONSENT_API_SCRIPT
116
+ }
115
117
  });
116
118
  if (shopifyAnalytics) scripts.push({
117
119
  tagName: "script",
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/core/shopify-scripts/index.ts"],"sourcesContent":["import { getShopifyAnalyticsBusScript, getShopifyAnalyticsConfig } from \"./analytics\";\nimport { getShopifyConsentTrackingScript } from \"./consent\";\nimport {\n SHOPIFY_CONSENT_API_SCRIPT,\n SHOPIFY_CDN_ORIGIN,\n SHOPIFY_CONSENT_SCRIPT_ID,\n SHOPIFY_PRIVACY_BANNER_SCRIPT,\n SHOPIFY_SHOP_APP_ORIGIN,\n SHOPIFY_INBOX_SCRIPT,\n SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT,\n SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT,\n SHOPIFY_STOREFRONT_STANDARD_EVENTS_INSPECTOR_SCRIPT,\n SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT,\n} from \"./constants\";\nimport { getShopifyGlobalBootstrapScript } from \"./global\";\nimport { getPerfKitScript } from \"./perfkit\";\nimport { renderShopifyScriptTag } from \"./render\";\nimport type {\n ShopifyLinkDescriptor,\n ShopifyScriptDescriptor,\n ShopifyScriptTagDescriptors,\n ShopifyScriptTagsOptions,\n} from \"./types\";\n\nexport {\n SHOPIFY_CDN_ORIGIN,\n SHOPIFY_CONSENT_API_SCRIPT,\n SHOPIFY_PERF_KIT_SCRIPT,\n SHOPIFY_PRIVACY_BANNER_SCRIPT,\n SHOPIFY_SHOP_APP_ORIGIN,\n SHOPIFY_INBOX_SCRIPT,\n SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT,\n SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT,\n SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT,\n SHOPIFY_STOREFRONT_WEBMCP_SCRIPT,\n VISITOR_CONSENT_COLLECTED_EVENT,\n} from \"./constants\";\nexport { getShopifyGlobal, getShopifyGlobalBootstrapScript } from \"./global\";\nexport { initializeShopifyScripts } from \"./initialize\";\nexport { renderShopifyScriptTag } from \"./render\";\nexport type {\n ShopifyScriptsAnalyticsConfig,\n ShopifyRoutesOptions,\n ShopifyScriptTagDescriptor,\n ShopifyScriptTagDescriptors,\n ShopifyScriptTagsOptions,\n ShopifyScriptsOptions,\n ShopifyScriptsI18n,\n ShopifyScriptsShop,\n} from \"./types\";\n\n/**\n * Returns grouped Shopify storefront script/link descriptors for SSR frameworks and bindings.\n *\n * Framework bindings wrap this with `initializeShopifyScripts()` to form their `ShopifyScripts`\n * component. Frameworks without a binding can render these descriptors during SSR and call\n * `initializeShopifyScripts()` during browser hydration.\n */\nexport function getShopifyScriptTags({\n analytics,\n consent,\n debug,\n i18n,\n nonce,\n shop,\n shopifyAnalytics = true,\n inbox = false,\n}: ShopifyScriptTagsOptions): ShopifyScriptTagDescriptors {\n const nonceAttributes = nonce !== undefined ? { nonce } : undefined;\n const analyticsConfig = getShopifyAnalyticsConfig({ analytics, consent, shop });\n\n const links: ShopifyLinkDescriptor[] = [\n {\n tagName: \"link\",\n attributes: {\n rel: \"preconnect\",\n href: SHOPIFY_CDN_ORIGIN,\n },\n },\n {\n tagName: \"link\",\n attributes: {\n rel: \"preconnect\",\n href: SHOPIFY_SHOP_APP_ORIGIN,\n },\n },\n {\n tagName: \"link\",\n attributes: {\n rel: \"prefetch\",\n as: \"script\",\n href: SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT,\n crossorigin: \"anonymous\",\n },\n },\n ];\n const scripts: ShopifyScriptDescriptor[] = [\n {\n tagName: \"script\",\n attributes: { id: \"shopify-global-bootstrap\", ...nonceAttributes },\n innerHTML: getShopifyGlobalBootstrapScript({ i18n, shop }),\n },\n {\n tagName: \"script\",\n attributes: {\n id: \"shopify-standard-actions\",\n type: \"module\",\n crossorigin: \"anonymous\",\n ...nonceAttributes,\n src: SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT,\n },\n },\n ];\n\n if (__DEV__ && debug?.standardEventsInspector) {\n scripts.push({\n tagName: \"script\",\n attributes: {\n id: \"shopify-standard-events-inspector\",\n defer: true,\n crossorigin: \"anonymous\",\n ...nonceAttributes,\n src: SHOPIFY_STOREFRONT_STANDARD_EVENTS_INSPECTOR_SCRIPT,\n },\n });\n }\n\n if (inbox) {\n scripts.push({\n tagName: \"script\",\n attributes: {\n id: \"shopify-inbox\",\n type: \"module\",\n async: true,\n crossorigin: \"anonymous\",\n ...nonceAttributes,\n src: SHOPIFY_INBOX_SCRIPT,\n },\n });\n }\n\n // Keep this async consent library immediately before the inline consent bootstrap.\n // Parser-inserted async scripts execute in a later task, so the following inline\n // script can attach a load listener before the library runs.\n scripts.push({\n tagName: \"script\",\n attributes: {\n id: SHOPIFY_CONSENT_SCRIPT_ID,\n async: true,\n crossorigin: \"anonymous\",\n ...nonceAttributes,\n src:\n consent?.mode === \"default-banner\"\n ? SHOPIFY_PRIVACY_BANNER_SCRIPT\n : SHOPIFY_CONSENT_API_SCRIPT,\n },\n });\n // This must run immediately after the consent library tag so it can find that\n // tag and attach its load listener before consent-tracking-api/privacy-banner executes.\n scripts.push({\n tagName: \"script\",\n attributes: { id: \"shopify-consent-bootstrap\", ...nonceAttributes },\n innerHTML: getShopifyConsentTrackingScript(consent),\n });\n\n // This must run after getShopifyConsentTrackingScript because that script\n // temporarily annotates visitorConsentCollected events for the analytics bus.\n scripts.push({\n tagName: \"script\",\n attributes: { id: \"shopify-analytics-bus\", ...nonceAttributes },\n innerHTML: getShopifyAnalyticsBusScript(analyticsConfig),\n });\n\n if (shopifyAnalytics) {\n scripts.push({\n tagName: \"script\",\n attributes: {\n id: \"shopify-storefront-analytics\",\n async: true,\n crossorigin: \"anonymous\",\n ...nonceAttributes,\n src: SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT,\n },\n });\n }\n\n const perfKitScript = getPerfKitScript(shop, nonceAttributes);\n if (perfKitScript) {\n scripts.push(perfKitScript);\n }\n\n return {\n links,\n scripts,\n get tags() {\n return [...links, ...scripts];\n },\n };\n}\n\n/**\n * Renders all Shopify storefront script/link descriptors to HTML strings.\n */\nexport function renderShopifyScriptTags(options: ShopifyScriptTagsOptions): string[] {\n return getShopifyScriptTags(options).tags.map(renderShopifyScriptTag);\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA0DA,SAAgB,qBAAqB,EACnC,WACA,SACA,OACA,MACA,OACA,MACA,mBAAmB,MACnB,QAAQ,SACgD;CACxD,MAAM,kBAAkB,UAAU,SAAY,EAAE,OAAO,GAAG;CAC1D,MAAM,kBAAkB,0BAA0B;EAAE;EAAW;EAAS;EAAM,CAAC;CAE/E,MAAM,QAAiC;EACrC;GACE,SAAS;GACT,YAAY;IACV,KAAK;IACL,MAAM;IACP;GACF;EACD;GACE,SAAS;GACT,YAAY;IACV,KAAK;IACL,MAAM;IACP;GACF;EACD;GACE,SAAS;GACT,YAAY;IACV,KAAK;IACL,IAAI;IACJ,MAAM;IACN,aAAa;IACd;GACF;EACF;CACD,MAAM,UAAqC,CACzC;EACE,SAAS;EACT,YAAY;GAAE,IAAI;GAA4B,GAAG;GAAiB;EAClE,WAAW,gCAAgC;GAAE;GAAM;GAAM,CAAC;EAC3D,EACD;EACE,SAAS;EACT,YAAY;GACV,IAAI;GACJ,MAAM;GACN,aAAa;GACb,GAAG;GACH,KAAK;GACN;EACF,CACF;AAED,KAAe,OAAO,wBACpB,SAAQ,KAAK;EACX,SAAS;EACT,YAAY;GACV,IAAI;GACJ,OAAO;GACP,aAAa;GACb,GAAG;GACH,KAAK;GACN;EACF,CAAC;AAGJ,KAAI,MACF,SAAQ,KAAK;EACX,SAAS;EACT,YAAY;GACV,IAAI;GACJ,MAAM;GACN,OAAO;GACP,aAAa;GACb,GAAG;GACH,KAAK;GACN;EACF,CAAC;AAMJ,SAAQ,KAAK;EACX,SAAS;EACT,YAAY;GACV,IAAI;GACJ,OAAO;GACP,aAAa;GACb,GAAG;GACH,KACE,SAAS,SAAS,mBACd,gCACA;GACP;EACF,CAAC;AAGF,SAAQ,KAAK;EACX,SAAS;EACT,YAAY;GAAE,IAAI;GAA6B,GAAG;GAAiB;EACnE,WAAW,gCAAgC,QAAQ;EACpD,CAAC;AAIF,SAAQ,KAAK;EACX,SAAS;EACT,YAAY;GAAE,IAAI;GAAyB,GAAG;GAAiB;EAC/D,WAAW,6BAA6B,gBAAgB;EACzD,CAAC;AAEF,KAAI,iBACF,SAAQ,KAAK;EACX,SAAS;EACT,YAAY;GACV,IAAI;GACJ,OAAO;GACP,aAAa;GACb,GAAG;GACH,KAAK;GACN;EACF,CAAC;CAGJ,MAAM,gBAAgB,iBAAiB,MAAM,gBAAgB;AAC7D,KAAI,cACF,SAAQ,KAAK,cAAc;AAG7B,QAAO;EACL;EACA;EACA,IAAI,OAAO;AACT,UAAO,CAAC,GAAG,OAAO,GAAG,QAAQ;;EAEhC;;;;;AAMH,SAAgB,wBAAwB,SAA6C;AACnF,QAAO,qBAAqB,QAAQ,CAAC,KAAK,IAAI,uBAAuB"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/core/shopify-scripts/index.ts"],"sourcesContent":["import { getShopifyAnalyticsBusScript, getShopifyAnalyticsConfig } from \"./analytics\";\nimport {\n SHOPIFY_ACCOUNT_SCRIPT,\n SHOPIFY_CONSENT_API_SCRIPT,\n SHOPIFY_CDN_ORIGIN,\n SHOPIFY_CONSENT_SCRIPT_ID,\n SHOPIFY_PRIVACY_BANNER_SCRIPT,\n SHOPIFY_SHOP_APP_ORIGIN,\n SHOPIFY_INBOX_SCRIPT,\n SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT,\n SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT,\n SHOPIFY_STOREFRONT_STANDARD_EVENTS_INSPECTOR_SCRIPT,\n SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT,\n} from \"./constants\";\nimport { getShopifyGlobalBootstrapScript } from \"./global\";\nimport { getPerfKitScript } from \"./perfkit\";\nimport { renderShopifyScriptTag } from \"./render\";\nimport type {\n ShopifyLinkDescriptor,\n ShopifyScriptDescriptor,\n ShopifyScriptTagDescriptors,\n ShopifyScriptTagsOptions,\n} from \"./types\";\n\nexport {\n CONSENT_TRACKING_API_LOADED_EVENT,\n SHOPIFY_ACCOUNT_SCRIPT,\n SHOPIFY_CDN_ORIGIN,\n SHOPIFY_CONSENT_API_SCRIPT,\n SHOPIFY_PERF_KIT_SCRIPT,\n SHOPIFY_PRIVACY_BANNER_SCRIPT,\n SHOPIFY_SHOP_APP_ORIGIN,\n SHOPIFY_INBOX_SCRIPT,\n SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT,\n SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT,\n SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT,\n SHOPIFY_STOREFRONT_WEBMCP_SCRIPT,\n VISITOR_CONSENT_COLLECTED_EVENT,\n} from \"./constants\";\nexport { getShopifyGlobal, getShopifyGlobalBootstrapScript } from \"./global\";\nexport { initializeShopifyScripts } from \"./initialize\";\nexport { renderShopifyScriptTag } from \"./render\";\nexport type {\n ShopifyScriptsAnalyticsConfig,\n ShopifyRoutesOptions,\n ShopifyScriptTagDescriptor,\n ShopifyScriptTagDescriptors,\n ShopifyScriptTagsOptions,\n ShopifyScriptsOptions,\n ShopifyScriptsI18n,\n ShopifyScriptsShop,\n} from \"./types\";\n\n/**\n * Returns grouped Shopify storefront script/link descriptors for SSR frameworks and bindings.\n *\n * Framework bindings wrap this with `initializeShopifyScripts()` to form their `ShopifyScripts`\n * component. Frameworks without a binding can render these descriptors during SSR and call\n * `initializeShopifyScripts()` during browser hydration.\n */\n// oxlint-disable-next-line complexity -- ordered assembly of optional Shopify script tags; each flag adds one branch and splitting would obscure the required load order\nexport function getShopifyScriptTags({\n account = false,\n analytics,\n consent,\n debug,\n i18n,\n nonce,\n shop,\n shopifyAnalytics = true,\n inbox = false,\n}: ShopifyScriptTagsOptions): ShopifyScriptTagDescriptors {\n const nonceAttributes = nonce !== undefined ? { nonce } : undefined;\n const analyticsConfig = getShopifyAnalyticsConfig({ analytics, consent, shop });\n\n const links: ShopifyLinkDescriptor[] = [\n {\n tagName: \"link\",\n attributes: {\n rel: \"preconnect\",\n href: SHOPIFY_CDN_ORIGIN,\n },\n },\n {\n tagName: \"link\",\n attributes: {\n rel: \"preconnect\",\n href: SHOPIFY_SHOP_APP_ORIGIN,\n },\n },\n {\n tagName: \"link\",\n attributes: {\n rel: \"prefetch\",\n as: \"script\",\n href: SHOPIFY_STOREFRONT_STANDARD_EVENTS_SCRIPT,\n crossorigin: \"anonymous\",\n },\n },\n ];\n const scripts: ShopifyScriptDescriptor[] = [\n {\n tagName: \"script\",\n attributes: { id: \"shopify-global-bootstrap\", ...nonceAttributes },\n innerHTML: getShopifyGlobalBootstrapScript({ i18n, shop }),\n },\n {\n tagName: \"script\",\n attributes: {\n id: \"shopify-standard-actions\",\n type: \"module\",\n crossorigin: \"anonymous\",\n ...nonceAttributes,\n src: SHOPIFY_STOREFRONT_STANDARD_ACTIONS_SCRIPT,\n },\n },\n ];\n\n if (__DEV__ && debug?.standardEventsInspector) {\n scripts.push({\n tagName: \"script\",\n attributes: {\n id: \"shopify-standard-events-inspector\",\n defer: true,\n crossorigin: \"anonymous\",\n ...nonceAttributes,\n src: SHOPIFY_STOREFRONT_STANDARD_EVENTS_INSPECTOR_SCRIPT,\n },\n });\n }\n\n if (inbox) {\n scripts.push({\n tagName: \"script\",\n attributes: {\n id: \"shopify-inbox\",\n type: \"module\",\n async: true,\n crossorigin: \"anonymous\",\n ...nonceAttributes,\n src: SHOPIFY_INBOX_SCRIPT,\n },\n });\n }\n\n if (account) {\n scripts.push({\n tagName: \"script\",\n attributes: {\n id: \"shopify-account\",\n type: \"module\",\n async: true,\n crossorigin: \"anonymous\",\n ...nonceAttributes,\n src: SHOPIFY_ACCOUNT_SCRIPT,\n },\n });\n }\n\n // Install readiness listeners before loading the async consent library so a\n // cached script cannot finish initialization before Hydrogen starts listening.\n scripts.push({\n tagName: \"script\",\n attributes: { id: \"shopify-analytics-bus\", ...nonceAttributes },\n innerHTML: getShopifyAnalyticsBusScript(analyticsConfig),\n });\n\n scripts.push({\n tagName: \"script\",\n attributes: {\n id: SHOPIFY_CONSENT_SCRIPT_ID,\n async: true,\n crossorigin: \"anonymous\",\n ...nonceAttributes,\n src:\n consent?.mode === \"default-banner\"\n ? SHOPIFY_PRIVACY_BANNER_SCRIPT\n : SHOPIFY_CONSENT_API_SCRIPT,\n },\n });\n\n if (shopifyAnalytics) {\n scripts.push({\n tagName: \"script\",\n attributes: {\n id: \"shopify-storefront-analytics\",\n async: true,\n crossorigin: \"anonymous\",\n ...nonceAttributes,\n src: SHOPIFY_STOREFRONT_ANALYTICS_SCRIPT,\n },\n });\n }\n\n const perfKitScript = getPerfKitScript(shop, nonceAttributes);\n if (perfKitScript) {\n scripts.push(perfKitScript);\n }\n\n return {\n links,\n scripts,\n get tags() {\n return [...links, ...scripts];\n },\n };\n}\n\n/**\n * Renders all Shopify storefront script/link descriptors to HTML strings.\n */\nexport function renderShopifyScriptTags(options: ShopifyScriptTagsOptions): string[] {\n return getShopifyScriptTags(options).tags.map(renderShopifyScriptTag);\n}\n"],"mappings":";;;;;;;;;;;;;;;AA6DA,SAAgB,qBAAqB,EACnC,UAAU,OACV,WACA,SACA,OACA,MACA,OACA,MACA,mBAAmB,MACnB,QAAQ,SACgD;CACxD,MAAM,kBAAkB,UAAU,SAAY,EAAE,OAAO,GAAG;CAC1D,MAAM,kBAAkB,0BAA0B;EAAE;EAAW;EAAS;EAAM,CAAC;CAE/E,MAAM,QAAiC;EACrC;GACE,SAAS;GACT,YAAY;IACV,KAAK;IACL,MAAM;IACP;GACF;EACD;GACE,SAAS;GACT,YAAY;IACV,KAAK;IACL,MAAM;IACP;GACF;EACD;GACE,SAAS;GACT,YAAY;IACV,KAAK;IACL,IAAI;IACJ,MAAM;IACN,aAAa;IACd;GACF;EACF;CACD,MAAM,UAAqC,CACzC;EACE,SAAS;EACT,YAAY;GAAE,IAAI;GAA4B,GAAG;GAAiB;EAClE,WAAW,gCAAgC;GAAE;GAAM;GAAM,CAAC;EAC3D,EACD;EACE,SAAS;EACT,YAAY;GACV,IAAI;GACJ,MAAM;GACN,aAAa;GACb,GAAG;GACH,KAAK;GACN;EACF,CACF;AAED,KAAe,OAAO,wBACpB,SAAQ,KAAK;EACX,SAAS;EACT,YAAY;GACV,IAAI;GACJ,OAAO;GACP,aAAa;GACb,GAAG;GACH,KAAK;GACN;EACF,CAAC;AAGJ,KAAI,MACF,SAAQ,KAAK;EACX,SAAS;EACT,YAAY;GACV,IAAI;GACJ,MAAM;GACN,OAAO;GACP,aAAa;GACb,GAAG;GACH,KAAK;GACN;EACF,CAAC;AAGJ,KAAI,QACF,SAAQ,KAAK;EACX,SAAS;EACT,YAAY;GACV,IAAI;GACJ,MAAM;GACN,OAAO;GACP,aAAa;GACb,GAAG;GACH,KAAK;GACN;EACF,CAAC;AAKJ,SAAQ,KAAK;EACX,SAAS;EACT,YAAY;GAAE,IAAI;GAAyB,GAAG;GAAiB;EAC/D,WAAW,6BAA6B,gBAAgB;EACzD,CAAC;AAEF,SAAQ,KAAK;EACX,SAAS;EACT,YAAY;GACV,IAAI;GACJ,OAAO;GACP,aAAa;GACb,GAAG;GACH,KACE,SAAS,SAAS,mBACd,gCACA;GACP;EACF,CAAC;AAEF,KAAI,iBACF,SAAQ,KAAK;EACX,SAAS;EACT,YAAY;GACV,IAAI;GACJ,OAAO;GACP,aAAa;GACb,GAAG;GACH,KAAK;GACN;EACF,CAAC;CAGJ,MAAM,gBAAgB,iBAAiB,MAAM,gBAAgB;AAC7D,KAAI,cACF,SAAQ,KAAK,cAAc;AAG7B,QAAO;EACL;EACA;EACA,IAAI,OAAO;AACT,UAAO,CAAC,GAAG,OAAO,GAAG,QAAQ;;EAEhC;;;;;AAMH,SAAgB,wBAAwB,SAA6C;AACnF,QAAO,qBAAqB,QAAQ,CAAC,KAAK,IAAI,uBAAuB"}
@@ -9,6 +9,7 @@ import { InitializeShopifyScriptsOptions } from "./types.mjs";
9
9
  * and call this helper from their browser lifecycle.
10
10
  */
11
11
  declare function initializeShopifyScripts({
12
+ consent,
12
13
  navigate,
13
14
  routes,
14
15
  webMcp