@ecomiq/storefront 2.1.3 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (317) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -123
  3. package/dist/account-Dx4e3syi.js +258 -0
  4. package/dist/account-forms-AVk71ko7.js +39 -0
  5. package/dist/account-forms.d.ts +13 -0
  6. package/dist/account.d.ts +240 -0
  7. package/dist/address-defaults-BqjRhS82.js +14 -0
  8. package/dist/address-defaults.d.ts +11 -0
  9. package/dist/analytics/analytics-CG1Qagwl.js +148 -0
  10. package/dist/analytics/analytics.d.ts +1 -0
  11. package/dist/analytics/config-DJr-GRhs.js +62 -0
  12. package/dist/analytics/config.d.ts +22 -0
  13. package/dist/analytics/consent-B13rBpBs.js +57 -0
  14. package/dist/analytics/consent-banner-9QvRRy8v.js +239 -0
  15. package/dist/analytics/consent-banner.d.ts +20 -0
  16. package/dist/analytics/cookies-pLozllyB.js +100 -0
  17. package/dist/analytics/cookies.d.ts +6 -0
  18. package/dist/analytics/destinations-iECrlLIr.js +144 -0
  19. package/dist/analytics/events-Dt81tIp1.js +102 -0
  20. package/dist/analytics/events.d.ts +51 -0
  21. package/dist/analytics/tracker-p4yaoOyk.js +51 -0
  22. package/dist/api-cache-DsuIn5hX.js +159 -0
  23. package/dist/bank-accounts-DlEczQQ5.js +81 -0
  24. package/dist/bank-accounts.d.ts +4 -0
  25. package/dist/captcha-DAqaIx8m.js +117 -0
  26. package/dist/captcha.d.ts +34 -0
  27. package/dist/cart-D7DxZ2lD.js +30 -0
  28. package/dist/cart-actions-Bsub_FFG.js +116 -0
  29. package/dist/cart-actions.d.ts +15 -0
  30. package/dist/cart-drawer-B7PPsR69.js +22 -0
  31. package/dist/cart-drawer.d.ts +9 -0
  32. package/dist/cart-form-y9P1r_EX.js +81 -0
  33. package/dist/cart-form.d.ts +24 -0
  34. package/dist/cart-summary-ur2VWKr-.js +89 -0
  35. package/dist/cart-summary.d.ts +31 -0
  36. package/dist/cart.d.ts +4 -0
  37. package/dist/catalog-7gJ-l5hW.js +67 -0
  38. package/dist/catalog-hooks-B7ZP4wYY.js +312 -0
  39. package/dist/catalog-hooks.d.ts +111 -0
  40. package/dist/catalog.d.ts +5 -0
  41. package/dist/checkout-DVWSXANi.js +474 -0
  42. package/dist/checkout-form-CbOIdENC.js +131 -0
  43. package/dist/checkout-form.d.ts +20 -0
  44. package/dist/checkout.d.ts +86 -0
  45. package/dist/complaint-book-BvwLvfx0.js +117 -0
  46. package/dist/complaint-book.d.ts +62 -0
  47. package/dist/culqi-authentication-BGr20vAJ.js +204 -0
  48. package/dist/culqi-authentication.d.ts +15 -0
  49. package/dist/culqi-checkout-CTXpKgp_.js +55 -0
  50. package/dist/culqi-three-ds-HP3mfrvV.js +33 -0
  51. package/dist/culqi-three-ds.d.ts +29 -0
  52. package/dist/customer-avatar-CJXSDroK.js +12 -0
  53. package/dist/customer-avatar.d.ts +5 -0
  54. package/dist/customer-cookies-DHOgFAMV.js +45 -0
  55. package/dist/customer-csrf-C1oDX-Py.js +17 -0
  56. package/dist/customer-csrf.d.ts +3 -0
  57. package/dist/customer-document-fields-C1K-_DAD.js +70 -0
  58. package/dist/customer-document-fields.d.ts +9 -0
  59. package/dist/customer-login-form-C7AC6vXd.js +144 -0
  60. package/dist/customer-login-form.d.ts +17 -0
  61. package/dist/customer-registration-form-BEm_NEfP.js +93 -0
  62. package/dist/customer-registration-form.d.ts +8 -0
  63. package/dist/document-url-CGsAl5Tf.js +9 -0
  64. package/dist/documents-T1mzc_j8.js +38 -0
  65. package/dist/documents.d.ts +16 -0
  66. package/dist/entries/account.d.ts +11 -0
  67. package/dist/entries/account.js +10 -0
  68. package/dist/entries/analytics.d.ts +6 -0
  69. package/dist/entries/analytics.js +5 -0
  70. package/dist/entries/cart.d.ts +8 -0
  71. package/dist/entries/cart.js +7 -0
  72. package/dist/entries/checkout.d.ts +12 -0
  73. package/dist/entries/checkout.js +11 -0
  74. package/dist/entries/order.d.ts +11 -0
  75. package/dist/entries/order.js +11 -0
  76. package/dist/favicon-YpyhVJ9H.js +28 -0
  77. package/dist/favicon.d.ts +4 -0
  78. package/dist/form-BtQcbXlJ.js +18 -0
  79. package/dist/form-contracts-BNpHaTGJ.js +166 -0
  80. package/dist/form-contracts.d.ts +42 -0
  81. package/dist/form.d.ts +3 -0
  82. package/dist/hidden-CCWtOWKR.js +3 -0
  83. package/dist/hidden.d.ts +4 -0
  84. package/dist/index.d.ts +50 -0
  85. package/dist/index.js +50 -0
  86. package/dist/invoice-fields-BG0HjL6T.js +103 -0
  87. package/dist/invoice-fields.d.ts +39 -0
  88. package/dist/links-kFxBZfdb.js +96 -0
  89. package/dist/links.d.ts +21 -0
  90. package/dist/mercadopago-checkout-DC7RXa8k.js +27 -0
  91. package/dist/mercadopago-dialog-UTQev0MG.js +180 -0
  92. package/dist/mercadopago-dialog.d.ts +21 -0
  93. package/dist/money-DtGOtDri.js +32 -0
  94. package/dist/money.d.ts +1 -0
  95. package/dist/optimistic-cart-BveVOHuh.js +53 -0
  96. package/dist/optimistic-cart.d.ts +16 -0
  97. package/dist/order-display-DTt5WBbc.js +112 -0
  98. package/dist/order-display.d.ts +20 -0
  99. package/dist/order-draft-DxV1Uhm3.js +38 -0
  100. package/dist/order-draft.d.ts +16 -0
  101. package/dist/order-pages-Dm6l5m0m.js +38 -0
  102. package/dist/order-pages.d.ts +12 -0
  103. package/dist/order-payment-continuation-D_d5PGA4.js +212 -0
  104. package/dist/order-payment-continuation.d.ts +10 -0
  105. package/dist/order-payment-in-review-x4gdLFHZ.js +65 -0
  106. package/dist/order-payment-in-review.d.ts +5 -0
  107. package/dist/order-status-BJXLJwxq.js +162 -0
  108. package/dist/order-status.d.ts +89 -0
  109. package/dist/order-view-9IlBg5AF.js +62 -0
  110. package/dist/order-view.d.ts +12 -0
  111. package/dist/page-action-Ctkf4xC6.js +7 -0
  112. package/dist/page-seo-a5FJl8x5.js +262 -0
  113. package/dist/page-seo.d.ts +34 -0
  114. package/dist/pages-Ca_Gt6mq.js +150 -0
  115. package/dist/pages.d.ts +45 -0
  116. package/dist/payment-dialog-frame-B-Q_xQ94.js +57 -0
  117. package/dist/payment-logo-BoPaGJc_.js +46 -0
  118. package/dist/payment-logo-svgs-By9lDTLK.js +20 -0
  119. package/dist/payment-logo.d.ts +11 -0
  120. package/dist/payment-logos-BYvdwYyJ.js +23 -0
  121. package/dist/payment-methods-B8ocTgFZ.js +73 -0
  122. package/dist/payment-methods.d.ts +58 -0
  123. package/dist/payment-return-5cjypwIw.js +7 -0
  124. package/dist/place-CmW4hBWY.js +13 -0
  125. package/dist/place.d.ts +4 -0
  126. package/dist/preview-BiIBif3C.js +427 -0
  127. package/dist/preview-address-Cf0sJ-9p.js +21 -0
  128. package/dist/preview-cart-Dg2CVktS.js +376 -0
  129. package/dist/product-preview-BspMAecJ.js +51 -0
  130. package/dist/product-preview.d.ts +5 -0
  131. package/dist/product-variants-BNDHvs1y.js +46 -0
  132. package/dist/product-variants.d.ts +12 -0
  133. package/dist/public-pages-XtwlaLwt.js +194 -0
  134. package/dist/public-pages.d.ts +67 -0
  135. package/dist/registration-CpDcv8ql.js +91 -0
  136. package/dist/registration.d.ts +12 -0
  137. package/dist/request-security-CRsRMgwj.js +76 -0
  138. package/dist/rich-text-M-Ju8RL4.js +9 -0
  139. package/dist/rich-text.d.ts +5 -0
  140. package/dist/route-text-DcJw2SsK.js +9 -0
  141. package/dist/route-text.d.ts +4 -0
  142. package/dist/section-preview-CmsMl3yu.js +83 -0
  143. package/dist/section-preview.d.ts +12 -0
  144. package/dist/sections/account-addresses.d.ts +18 -0
  145. package/dist/sections/account-addresses.js +375 -0
  146. package/dist/sections/account-order.d.ts +12 -0
  147. package/dist/sections/account-order.js +592 -0
  148. package/dist/sections/account-orders.d.ts +8 -0
  149. package/dist/sections/account-orders.js +359 -0
  150. package/dist/sections/account-profile.d.ts +16 -0
  151. package/dist/sections/account-profile.js +123 -0
  152. package/dist/sections/checkout.d.ts +24 -0
  153. package/dist/sections/checkout.js +963 -0
  154. package/dist/sections/complaint-book.d.ts +8 -0
  155. package/dist/sections/complaint-book.js +538 -0
  156. package/dist/sections/design-system.d.ts +1 -0
  157. package/dist/sections/design-system.js +310 -0
  158. package/dist/sections/draft-invoice.d.ts +20 -0
  159. package/dist/sections/draft-invoice.js +158 -0
  160. package/dist/sections/order-tracking.d.ts +19 -0
  161. package/dist/sections/order-tracking.js +141 -0
  162. package/dist/sections-CNUMWTF_.js +77 -0
  163. package/dist/sections.d.ts +19 -0
  164. package/dist/seo-GpDRhAAA.js +78 -0
  165. package/dist/session-CKvmFJyg.js +379 -0
  166. package/dist/session.d.ts +24 -0
  167. package/dist/settings-B0NO2A6Y.js +78 -0
  168. package/dist/settings.d.ts +51 -0
  169. package/dist/source-marker-DhqSkW7n.js +4 -0
  170. package/dist/sources-B-3JFJfb.js +46 -0
  171. package/dist/sources.d.ts +7 -0
  172. package/dist/store-8Q-_LFrQ.js +152 -0
  173. package/dist/store-contact--hY6CoFb.js +19 -0
  174. package/dist/store-contact.d.ts +6 -0
  175. package/dist/store.d.ts +17 -0
  176. package/dist/storefront-language-DrMjVbmk.js +29 -0
  177. package/dist/storefront-language.d.ts +14 -0
  178. package/dist/storefront-text-D25ae1qf.js +11 -0
  179. package/dist/storefront-text-en-ljjjSS4q.js +1030 -0
  180. package/dist/storefront-text-pt-BtHaJLcp.js +1030 -0
  181. package/dist/storefront-text.d.ts +4 -0
  182. package/dist/stripe-dialog-Ev9s3Z62.js +396 -0
  183. package/dist/stripe-dialog.d.ts +30 -0
  184. package/dist/telemetry-HuZXWBPi.js +114 -0
  185. package/dist/telemetry.d.ts +10 -0
  186. package/dist/templates-CAqoNyTW.js +40 -0
  187. package/dist/templates.d.ts +15 -0
  188. package/dist/urls-CpGQPxvf.js +71 -0
  189. package/dist/urls.d.ts +18 -0
  190. package/dist/use-checkout-CZcxXJXi.js +42 -0
  191. package/dist/use-checkout-payment-9R-zacrJ.js +80 -0
  192. package/dist/use-checkout-payment.d.ts +18 -0
  193. package/dist/use-checkout.d.ts +36 -0
  194. package/dist/use-culqi-checkout-CrjLAipU.js +109 -0
  195. package/dist/use-order-payment-BKIz_IO0.js +45 -0
  196. package/dist/use-order-payment.d.ts +18 -0
  197. package/dist/use-payment-token-CErx-tN-.js +105 -0
  198. package/dist/vite-payment-logos-kziu7wKb.js +27 -0
  199. package/dist/vite-payment-logos.d.ts +24 -0
  200. package/dist/vite-public-assets-DW2fgtVb.js +209 -0
  201. package/dist/vite-public-assets.d.ts +29 -0
  202. package/dist/vite-sections-DTBr0-Kg.js +464 -0
  203. package/dist/vite-sections.d.ts +21 -0
  204. package/dist/vite-theme-ui-BMO-CDi3.js +41 -0
  205. package/dist/vite-theme-ui.d.ts +10 -0
  206. package/dist/vite.d.ts +36 -0
  207. package/dist/vite.js +127 -0
  208. package/dist/voucher-payment-CVFDZ1L8.js +66 -0
  209. package/dist/worker-CNi-gzCu.js +86 -0
  210. package/dist/worker.d.ts +27 -0
  211. package/package.json +100 -81
  212. package/src/sections/account-addresses.tsx +215 -0
  213. package/src/sections/account-order.tsx +424 -0
  214. package/src/sections/account-orders.tsx +259 -0
  215. package/src/sections/account-profile.tsx +70 -0
  216. package/src/sections/checkout.tsx +586 -0
  217. package/src/sections/complaint-book.tsx +325 -0
  218. package/src/sections/design-system.tsx +146 -0
  219. package/src/sections/draft-invoice.tsx +105 -0
  220. package/src/sections/order-tracking.tsx +81 -0
  221. package/src/vite-client.d.ts +4 -0
  222. package/bin/ecomiq.mjs +0 -179
  223. package/public/design-bridge.js +0 -318
  224. package/src/api-proxy.ts +0 -194
  225. package/src/auth/create-storefront-auth.ts +0 -94
  226. package/src/auth/ecomiq-oauth-password-client.ts +0 -26
  227. package/src/auth/ecomiq-oauth-password-constants.ts +0 -24
  228. package/src/auth/ecomiq-oauth-password-plugin.ts +0 -294
  229. package/src/auth/ecomiq-oauth-password-types.ts +0 -24
  230. package/src/auth/ecomiq-storefront-sign-in.ts +0 -44
  231. package/src/auth/env.ts +0 -7
  232. package/src/auth/secure-cookies.ts +0 -23
  233. package/src/auth/storefront-auth-base-url.ts +0 -117
  234. package/src/auth/storefront-auth.ts +0 -7
  235. package/src/cart-session.ts +0 -239
  236. package/src/client.ts +0 -48
  237. package/src/cloud-runtime-client.ts +0 -378
  238. package/src/codegen.mjs +0 -789
  239. package/src/components/account/customer-addresses-panel.tsx +0 -678
  240. package/src/components/account/customer-order-detail-panel.tsx +0 -285
  241. package/src/components/account/customer-orders-panel.tsx +0 -192
  242. package/src/components/account/customer-profile-panel.tsx +0 -379
  243. package/src/components/checkout/cart-sync.ts +0 -143
  244. package/src/components/checkout/checkout-contact-section.tsx +0 -76
  245. package/src/components/checkout/checkout-external-update-banner.tsx +0 -15
  246. package/src/components/checkout/checkout-form-controls.tsx +0 -139
  247. package/src/components/checkout/checkout-line-items.tsx +0 -43
  248. package/src/components/checkout/checkout-order-summary.tsx +0 -165
  249. package/src/components/checkout/checkout-payment-section.tsx +0 -212
  250. package/src/components/checkout/checkout-session-view.tsx +0 -564
  251. package/src/components/checkout/checkout-shipping-address-section.tsx +0 -400
  252. package/src/components/checkout/checkout-shipping-section.tsx +0 -98
  253. package/src/components/checkout/checkout-states.tsx +0 -73
  254. package/src/components/checkout/checkout-step-card.tsx +0 -101
  255. package/src/components/checkout/checkout-steps.ts +0 -111
  256. package/src/components/checkout/form-schema.ts +0 -281
  257. package/src/components/checkout/format.ts +0 -15
  258. package/src/components/checkout/index.ts +0 -5
  259. package/src/components/checkout/map-customer-to-checkout.ts +0 -188
  260. package/src/components/checkout/types.ts +0 -41
  261. package/src/components/checkout/use-checkout-customer-prefill.ts +0 -409
  262. package/src/components/checkout/use-checkout-geo.ts +0 -50
  263. package/src/components/checkout/use-checkout-session.ts +0 -640
  264. package/src/components/hero.tsx +0 -291
  265. package/src/config.d.ts +0 -94
  266. package/src/config.mjs +0 -146
  267. package/src/format-money.ts +0 -31
  268. package/src/health.ts +0 -90
  269. package/src/hooks/index.ts +0 -9
  270. package/src/hooks/recently-viewed.ts +0 -125
  271. package/src/index.ts +0 -354
  272. package/src/link.tsx +0 -2
  273. package/src/pages/account/account-page-skeleton.tsx +0 -69
  274. package/src/pages/account/account-page-view.tsx +0 -270
  275. package/src/pages/account/account-shell.tsx +0 -101
  276. package/src/pages/account/parse-account-route.ts +0 -36
  277. package/src/pages/account.tsx +0 -16
  278. package/src/pages/api.$.ts +0 -20
  279. package/src/pages/api.auth.$.ts +0 -16
  280. package/src/pages/checkout.$checkoutId.tsx +0 -60
  281. package/src/pages/checkout.tsx +0 -31
  282. package/src/pages/pages.$pageSlug.tsx +0 -111
  283. package/src/pages/thank-you.tsx +0 -53
  284. package/src/providers/auth.tsx +0 -96
  285. package/src/providers/cart.tsx +0 -275
  286. package/src/providers/ecomiq.ts +0 -137
  287. package/src/providers/index.ts +0 -26
  288. package/src/proxy-api.ts +0 -20
  289. package/src/public-config.ts +0 -24
  290. package/src/review-submission.ts +0 -89
  291. package/src/runtime/context.ts +0 -2
  292. package/src/runtime/default-layout.tsx +0 -64
  293. package/src/runtime/head.ts +0 -149
  294. package/src/runtime/page.tsx +0 -143
  295. package/src/runtime/postcss-browser-stub.mjs +0 -5
  296. package/src/server-config-store.ts +0 -35
  297. package/src/server.ts +0 -301
  298. package/src/storefront-definition/contract.ts +0 -1
  299. package/src/storefront-definition/data.ts +0 -188
  300. package/src/storefront-definition/index.ts +0 -2
  301. package/src/storefront-definition/renderer.tsx +0 -1481
  302. package/src/storefront-layout.ts +0 -59
  303. package/src/storefront-runtime.ts +0 -173
  304. package/src/styles.css +0 -97
  305. package/src/ui/badge.tsx +0 -32
  306. package/src/ui/button.tsx +0 -31
  307. package/src/ui/card.tsx +0 -31
  308. package/src/ui/carousel.tsx +0 -218
  309. package/src/ui/cn.ts +0 -6
  310. package/src/ui/index.ts +0 -8
  311. package/src/ui/separator.tsx +0 -6
  312. package/src/ui/skeleton.tsx +0 -6
  313. package/src/ui/storefront-error.tsx +0 -49
  314. package/src/utils.ts +0 -36
  315. package/src/vite-inline.mjs +0 -263
  316. package/templates/__root.tsx +0 -83
  317. package/templates/router.tsx +0 -19
@@ -0,0 +1,67 @@
1
+ import { RouterContextProvider } from "react-router";
2
+ import { PublicOrderTracking } from "@ecomiq/core";
3
+ export type GeoPlace = {
4
+ code: string;
5
+ name: string;
6
+ };
7
+ export type ReviewActionData = {
8
+ ok: boolean;
9
+ error: string | null;
10
+ };
11
+ export declare function loadGeo(request: Request, context: Readonly<RouterContextProvider>): Promise<{
12
+ departments: GeoPlace[];
13
+ provinces: GeoPlace[];
14
+ districts: GeoPlace[];
15
+ }>;
16
+ export declare function loadSearchSuggestions(request: Request, context: Readonly<RouterContextProvider>): Promise<{
17
+ q: string;
18
+ products: never[] | {
19
+ id: string;
20
+ name: string;
21
+ slug: string;
22
+ url: string;
23
+ imageUrl: string;
24
+ }[];
25
+ }>;
26
+ export type TrackingData = {
27
+ code: string;
28
+ tracking: PublicOrderTracking | null;
29
+ missing: boolean;
30
+ language: string;
31
+ timeZone: string;
32
+ };
33
+ export declare function loadTracking(request: Request, context: Readonly<RouterContextProvider>, code: string | undefined): Promise<TrackingData>;
34
+ export declare function loadReview(context: Readonly<RouterContextProvider>, token: string): Promise<{
35
+ review: {
36
+ orderId: string;
37
+ orderNumber: string;
38
+ customerName: string | null;
39
+ email: string | null;
40
+ deliveredAt: string | null;
41
+ items: {
42
+ productId: string;
43
+ title: string;
44
+ variantTitle: string | null;
45
+ thumbnail: string | null;
46
+ }[];
47
+ };
48
+ }>;
49
+ export declare function reviewAction(request: Request, context: Readonly<RouterContextProvider>, token: string): Promise<import("react-router").UNSAFE_DataWithResponseInit<ReviewActionData> | {
50
+ ok: true;
51
+ error: null;
52
+ }>;
53
+ export declare function productReviewAction(request: Request, context: Readonly<RouterContextProvider>): Promise<import("react-router").UNSAFE_DataWithResponseInit<ReviewActionData> | {
54
+ ok: true;
55
+ error: null;
56
+ }>;
57
+ export type StorefrontPageData = {
58
+ title: string;
59
+ html: string;
60
+ layout: string;
61
+ seo: {
62
+ title: string;
63
+ description: string;
64
+ };
65
+ };
66
+ export declare function readPage(context: Readonly<RouterContextProvider>, handle: string): Promise<StorefrontPageData | null>;
67
+ export declare function loadPage(context: Readonly<RouterContextProvider>, handle: string): Promise<StorefrontPageData>;
@@ -0,0 +1,91 @@
1
+ import { safeNext, text } from "./form-BtQcbXlJ.js";
2
+ import { rejectCrossOriginAction, rejectCustomerCsrf } from "./request-security-CRsRMgwj.js";
3
+ import { customer, customerHeaders } from "./session-CKvmFJyg.js";
4
+ import { store } from "./store-8Q-_LFrQ.js";
5
+ import { worker } from "./worker-CNi-gzCu.js";
6
+ import { data, redirect } from "react-router";
7
+ import { ApiError, CustomerRegistrationInputSchema } from "@ecomiq/core";
8
+ // src/registration.ts
9
+ const PRIVATE_HEADERS = {
10
+ "Cache-Control": "private, no-store",
11
+ "Referrer-Policy": "no-referrer"
12
+ };
13
+ const FIELDS = [
14
+ "firstName",
15
+ "lastName",
16
+ "phone",
17
+ "dateOfBirth"
18
+ ];
19
+ async function registrationToday(context) {
20
+ const settings = await store(context).getSettings();
21
+ return new Intl.DateTimeFormat("en-CA", {
22
+ timeZone: settings.store.timeZone,
23
+ year: "numeric",
24
+ month: "2-digit",
25
+ day: "2-digit"
26
+ }).format(/* @__PURE__ */ new Date());
27
+ }
28
+ async function registrationData(registration, next, context, error = null, status = 200) {
29
+ const settings = await store(context).getSettings();
30
+ return data({
31
+ registration,
32
+ next,
33
+ storeName: settings.store.name,
34
+ error,
35
+ today: await registrationToday(context)
36
+ }, {
37
+ status,
38
+ headers: PRIVATE_HEADERS
39
+ });
40
+ }
41
+ /** The session exists at this stage; profile completion must not guard its own route. */
42
+ async function loadCustomerRegistration(request, context) {
43
+ const next = safeNext(new URL(request.url).searchParams.get("next"));
44
+ const current = await customer(request, context);
45
+ if (!current) return redirect(`/account/login?next=${encodeURIComponent(next)}`, { headers: PRIVATE_HEADERS });
46
+ const registration = await store(context).getCustomerRegistration(customerHeaders(current));
47
+ if (!registration.requiresCompletion) return redirect(next, { headers: PRIVATE_HEADERS });
48
+ return registrationData(registration, next, context);
49
+ }
50
+ async function submitCustomerRegistration(request, context) {
51
+ const rejected = rejectCrossOriginAction(request) ?? await rejectCustomerCsrf(request, context.get(worker).env);
52
+ if (rejected) return rejected;
53
+ const next = safeNext(new URL(request.url).searchParams.get("next"));
54
+ const current = await customer(request, context);
55
+ if (!current) return redirect(`/account/login?next=${encodeURIComponent(next)}`, {
56
+ status: 303,
57
+ headers: PRIVATE_HEADERS
58
+ });
59
+ const client = store(context);
60
+ const options = customerHeaders(current);
61
+ const registration = await client.getCustomerRegistration(options);
62
+ if (!registration.requiresCompletion) return redirect(next, {
63
+ status: 303,
64
+ headers: PRIVATE_HEADERS
65
+ });
66
+ const form = await request.formData();
67
+ const skip = text(form, "intent") === "skip";
68
+ const input = {};
69
+ for (const field of FIELDS) if (!skip && registration.fields[field] !== "hidden") input[field] = text(form, field) || null;
70
+ const submitted = {
71
+ ...registration,
72
+ ...input
73
+ };
74
+ const parsed = CustomerRegistrationInputSchema.safeParse(input);
75
+ if (!parsed.success) return registrationData(submitted, next, context, "Revisa los datos ingresados y vuelve a intentar.", 400);
76
+ for (const field of FIELDS) if (registration.fields[field] === "required" && !submitted[field]?.trim()) return registrationData(submitted, next, context, "Completa los datos obligatorios para continuar.", 400);
77
+ if (input.dateOfBirth && input.dateOfBirth > await registrationToday(context)) return registrationData(submitted, next, context, "La fecha de nacimiento no puede ser futura.", 400);
78
+ try {
79
+ const completed = await client.completeCustomerRegistration(parsed.data, options);
80
+ if (completed.requiresCompletion) return registrationData(completed, next, context, "Completa los datos obligatorios para continuar.", 400);
81
+ return redirect(next, {
82
+ status: 303,
83
+ headers: PRIVATE_HEADERS
84
+ });
85
+ } catch (error) {
86
+ let message = "No pudimos guardar tus datos. Intenta de nuevo.";
87
+ if (error instanceof ApiError && error.status === 400) message = error.message;
88
+ return registrationData(submitted, next, context, message, 400);
89
+ }
90
+ }
91
+ export { loadCustomerRegistration, submitCustomerRegistration };
@@ -0,0 +1,12 @@
1
+ import { RouterContextProvider, data } from "react-router";
2
+ import { CustomerRegistration } from "@ecomiq/core";
3
+ export type CustomerRegistrationData = {
4
+ registration: CustomerRegistration;
5
+ storeName: string;
6
+ next: string;
7
+ error: string | null;
8
+ today: string;
9
+ };
10
+ /** The session exists at this stage; profile completion must not guard its own route. */
11
+ export declare function loadCustomerRegistration(request: Request, context: Readonly<RouterContextProvider>): Promise<Response | ReturnType<typeof data<CustomerRegistrationData>>>;
12
+ export declare function submitCustomerRegistration(request: Request, context: Readonly<RouterContextProvider>): Promise<Response | ReturnType<typeof data<CustomerRegistrationData>>>;
@@ -0,0 +1,76 @@
1
+ import { base64Url, base64UrlBytes, customerSessionId, equalSecret } from "./customer-cookies-DHOgFAMV.js";
2
+ import { PRIVATE_STOREFRONT_SUBTREES } from "@ecomiq/core/redirects";
3
+ // src/request-security.ts
4
+ const SAFE_METHODS = /* @__PURE__ */ new Set([
5
+ "GET",
6
+ "HEAD",
7
+ "OPTIONS"
8
+ ]);
9
+ const PRIVATE_PATH = new RegExp(`^/(${PRIVATE_STOREFRONT_SUBTREES.join("|")})(/|$)`);
10
+ async function sessionCsrfToken(sessionId, env) {
11
+ const encoder = new TextEncoder();
12
+ const key = await crypto.subtle.importKey("raw", encoder.encode(env.SESSION_SECRET), {
13
+ name: "HMAC",
14
+ hash: "SHA-256"
15
+ }, false, ["sign"]);
16
+ const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(`customer-csrf\n${env.ECOMIQ_STORE}\n${sessionId}`));
17
+ return base64Url(new Uint8Array(signature));
18
+ }
19
+ async function customerCsrfTokenForRequest(request, env) {
20
+ const sessionId = await customerSessionId(request, env);
21
+ return sessionId ? sessionCsrfToken(sessionId, env) : "";
22
+ }
23
+ async function rejectCustomerCsrf(request, env) {
24
+ if (SAFE_METHODS.has(request.method)) return null;
25
+ const sessionId = await customerSessionId(request, env);
26
+ if (!sessionId) return null;
27
+ let submitted = request.headers.get("X-Customer-Csrf");
28
+ if (!submitted) try {
29
+ submitted = (await request.clone().formData()).get("__customer_csrf");
30
+ } catch {
31
+ submitted = null;
32
+ }
33
+ const expected = await sessionCsrfToken(sessionId, env);
34
+ if (typeof submitted === "string" && equalSecret(submitted, expected)) return null;
35
+ return new Response("La sesión cambió. Recarga la página antes de continuar.", {
36
+ status: 403,
37
+ headers: {
38
+ "Cache-Control": "private, no-store",
39
+ "Content-Type": "text/plain; charset=utf-8"
40
+ }
41
+ });
42
+ }
43
+ /** Browser actions must originate on the storefront that owns the cookies. */
44
+ function rejectCrossOriginAction(request) {
45
+ if (SAFE_METHODS.has(request.method)) return null;
46
+ if (request.headers.get("Origin") === new URL(request.url).origin && request.headers.get("Sec-Fetch-Site") !== "cross-site") return null;
47
+ return new Response("La solicitud debe enviarse desde esta tienda. Recarga la página e intenta de nuevo.", {
48
+ status: 403,
49
+ headers: {
50
+ "Cache-Control": "private, no-store",
51
+ "Content-Type": "text/plain; charset=utf-8"
52
+ }
53
+ });
54
+ }
55
+ function privateCustomerResponse(request) {
56
+ const path = new URL(request.url).pathname;
57
+ return !SAFE_METHODS.has(request.method) || PRIVATE_PATH.test(path) || /(?:^|;\s*)(?:__Host-ecomiq-customer|cart)=/.test(request.headers.get("Cookie") ?? "");
58
+ }
59
+ async function customerClientHeaders(request, env, target) {
60
+ const address = request.headers.get("CF-Connecting-IP");
61
+ const store = env.ECOMIQ_STORE_ID;
62
+ if (!address || !store || !env.CUSTOMER_IP_KEY) return {};
63
+ const timestamp = String(Math.floor(Date.now() / 1e3));
64
+ const key = await crypto.subtle.importKey("raw", base64UrlBytes(env.CUSTOMER_IP_KEY), {
65
+ name: "HMAC",
66
+ hash: "SHA-256"
67
+ }, false, ["sign"]);
68
+ const signature = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(`${timestamp}\n${store}\n${address}\nPOST\n${target.pathname}`));
69
+ return {
70
+ "X-Ecomiq-Client-Ip": address,
71
+ "X-Ecomiq-Client-Store": store,
72
+ "X-Ecomiq-Client-Timestamp": timestamp,
73
+ "X-Ecomiq-Client-Signature": base64Url(new Uint8Array(signature))
74
+ };
75
+ }
76
+ export { customerClientHeaders, customerCsrfTokenForRequest, privateCustomerResponse, rejectCrossOriginAction, rejectCustomerCsrf };
@@ -0,0 +1,9 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ // src/rich-text.tsx
3
+ function RichText({ html, className }) {
4
+ return /* @__PURE__ */ jsx("div", {
5
+ className,
6
+ dangerouslySetInnerHTML: { __html: html }
7
+ });
8
+ }
9
+ export { RichText };
@@ -0,0 +1,5 @@
1
+ import { ReactElement } from "react";
2
+ export declare function RichText({ html, className }: {
3
+ html: string;
4
+ className?: string;
5
+ }): ReactElement;
@@ -0,0 +1,9 @@
1
+ import { storefrontText } from "./storefront-text-D25ae1qf.js";
2
+ import { z } from "zod";
3
+ // src/route-text.ts
4
+ const RootLanguage = z.object({ shop: z.object({ translations: z.record(z.string(), z.string()).default({}) }) });
5
+ function storefrontRouteText(matches, source) {
6
+ const root = RootLanguage.safeParse(matches.find((match) => match?.id === "root")?.data);
7
+ return storefrontText(root.success ? root.data.shop.translations : {}, source);
8
+ }
9
+ export { storefrontRouteText };
@@ -0,0 +1,4 @@
1
+ export declare function storefrontRouteText(matches: readonly ({
2
+ id: string;
3
+ data?: unknown;
4
+ } | undefined)[], source: string): string;
@@ -0,0 +1,83 @@
1
+ import { loadSections, withSections } from "./sections-CNUMWTF_.js";
2
+ import { worker } from "./worker-CNi-gzCu.js";
3
+ import { data, useLoaderData } from "react-router";
4
+ import { createElement, useState } from "react";
5
+ import { jsx } from "react/jsx-runtime";
6
+ // src/section-preview.tsx
7
+ const COMPONENT = /^[A-Z][A-Za-z0-9]*$/;
8
+ const DESIGN = {
9
+ file: "@ecomiq/storefront/sections/design-system",
10
+ component: "DesignSystem"
11
+ };
12
+ const rendered = /* @__PURE__ */ new Map();
13
+ function notFound() {
14
+ throw data(null, { status: 404 });
15
+ }
16
+ function sectionFile(path) {
17
+ return `app/${path.replace(/^(?:\.\.\/)+/, "")}`;
18
+ }
19
+ function sectionEntries(module) {
20
+ const load = module.load;
21
+ if (typeof load !== "function") return [];
22
+ const section = load.section;
23
+ if (typeof section !== "string") return [];
24
+ return [{
25
+ section,
26
+ load,
27
+ props: {}
28
+ }];
29
+ }
30
+ async function sectionPreview(args, modules) {
31
+ const { env } = args.context.get(worker);
32
+ if (env.ECOMIQ_PREVIEW !== "1") notFound();
33
+ const url = new URL(args.request.url);
34
+ if (url.searchParams.get("design") === "1") {
35
+ const design = await import(
36
+ /* @vite-ignore */
37
+ DESIGN.file
38
+ );
39
+ rendered.set(DESIGN.file, design);
40
+ return DESIGN;
41
+ }
42
+ const file = url.searchParams.get("file") ?? "";
43
+ const component = url.searchParams.get("component") ?? "";
44
+ const path = Object.keys(modules).find((candidate) => sectionFile(candidate) === file);
45
+ const importer = path === void 0 ? void 0 : modules[path];
46
+ if (importer === void 0 || !COMPONENT.test(component)) notFound();
47
+ const module = await importer();
48
+ if (typeof module[component] !== "function") notFound();
49
+ rendered.set(file, module);
50
+ const pending = loadSections(args, sectionEntries(module));
51
+ const sections = Object.fromEntries(await Promise.all(Object.entries(pending).map(async ([key, value]) => [key, await value])));
52
+ return withSections({
53
+ file,
54
+ component
55
+ }, sections);
56
+ }
57
+ function sectionPreviewMeta() {
58
+ return [{
59
+ name: "robots",
60
+ content: "noindex"
61
+ }];
62
+ }
63
+ function serverHtml(component) {
64
+ if (typeof document === "undefined") return "";
65
+ return document.querySelector(`[data-ecomiq-preview="${CSS.escape(component)}"]`)?.innerHTML ?? "";
66
+ }
67
+ function SectionPreview() {
68
+ const { file, component } = useLoaderData();
69
+ const [html] = useState(() => serverHtml(component));
70
+ const Section = rendered.get(file)?.[component];
71
+ if (typeof Section !== "function") return /* @__PURE__ */ jsx("div", {
72
+ "data-ecomiq-preview": component,
73
+ style: { display: "flow-root" },
74
+ suppressHydrationWarning: true,
75
+ dangerouslySetInnerHTML: { __html: html }
76
+ });
77
+ return /* @__PURE__ */ jsx("div", {
78
+ "data-ecomiq-preview": component,
79
+ style: { display: "flow-root" },
80
+ children: createElement(Section)
81
+ });
82
+ }
83
+ export { SectionPreview, sectionPreview, sectionPreviewMeta };
@@ -0,0 +1,12 @@
1
+ import { LoaderFunctionArgs, MetaDescriptor } from "react-router";
2
+ import { ReactElement } from "react";
3
+ export type SectionModules = {
4
+ readonly [path: string]: () => Promise<unknown>;
5
+ };
6
+ export type SectionPreviewData = {
7
+ readonly file: string;
8
+ readonly component: string;
9
+ };
10
+ export declare function sectionPreview(args: LoaderFunctionArgs, modules: SectionModules): Promise<SectionPreviewData>;
11
+ export declare function sectionPreviewMeta(): MetaDescriptor[];
12
+ export declare function SectionPreview(): ReactElement;
@@ -0,0 +1,18 @@
1
+ import { AddressActionData } from "../account.js";
2
+ import "../index.js";
3
+ import { SectionCatalog } from "../settings.js";
4
+ import "../entries/account.js";
5
+ import { CustomerAddress } from "@ecomiq/core";
6
+ export declare const catalog: SectionCatalog;
7
+ type Country = {
8
+ code: string;
9
+ name: string;
10
+ };
11
+ export declare function AccountAddresses({ loaderData, actionData }: {
12
+ loaderData: {
13
+ addresses: CustomerAddress[];
14
+ countries: Country[];
15
+ };
16
+ actionData?: AddressActionData;
17
+ }): import("react").JSX.Element;
18
+ export {};