@ecomiq/storefront 2.1.4 → 3.0.1

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 (310) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +377 -76
  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 -76
  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/codegen.mjs +0 -801
  238. package/src/components/account/customer-addresses-panel.tsx +0 -678
  239. package/src/components/account/customer-order-detail-panel.tsx +0 -285
  240. package/src/components/account/customer-orders-panel.tsx +0 -192
  241. package/src/components/account/customer-profile-panel.tsx +0 -379
  242. package/src/components/checkout/cart-sync.ts +0 -143
  243. package/src/components/checkout/checkout-contact-section.tsx +0 -76
  244. package/src/components/checkout/checkout-external-update-banner.tsx +0 -15
  245. package/src/components/checkout/checkout-form-controls.tsx +0 -139
  246. package/src/components/checkout/checkout-line-items.tsx +0 -43
  247. package/src/components/checkout/checkout-order-summary.tsx +0 -165
  248. package/src/components/checkout/checkout-payment-section.tsx +0 -212
  249. package/src/components/checkout/checkout-session-view.tsx +0 -564
  250. package/src/components/checkout/checkout-shipping-address-section.tsx +0 -400
  251. package/src/components/checkout/checkout-shipping-section.tsx +0 -98
  252. package/src/components/checkout/checkout-states.tsx +0 -73
  253. package/src/components/checkout/checkout-step-card.tsx +0 -101
  254. package/src/components/checkout/checkout-steps.ts +0 -111
  255. package/src/components/checkout/form-schema.ts +0 -281
  256. package/src/components/checkout/format.ts +0 -15
  257. package/src/components/checkout/index.ts +0 -5
  258. package/src/components/checkout/map-customer-to-checkout.ts +0 -188
  259. package/src/components/checkout/types.ts +0 -41
  260. package/src/components/checkout/use-checkout-customer-prefill.ts +0 -409
  261. package/src/components/checkout/use-checkout-geo.ts +0 -50
  262. package/src/components/checkout/use-checkout-session.ts +0 -640
  263. package/src/components/hero.tsx +0 -291
  264. package/src/config.d.ts +0 -94
  265. package/src/config.mjs +0 -146
  266. package/src/format-money.ts +0 -31
  267. package/src/health.ts +0 -90
  268. package/src/hooks/index.ts +0 -9
  269. package/src/hooks/recently-viewed.ts +0 -125
  270. package/src/index.ts +0 -349
  271. package/src/link.tsx +0 -2
  272. package/src/pages/account/account-page-skeleton.tsx +0 -69
  273. package/src/pages/account/account-page-view.tsx +0 -270
  274. package/src/pages/account/account-shell.tsx +0 -101
  275. package/src/pages/account/parse-account-route.ts +0 -36
  276. package/src/pages/account.tsx +0 -16
  277. package/src/pages/api.$.ts +0 -20
  278. package/src/pages/api.auth.$.ts +0 -16
  279. package/src/pages/checkout.$checkoutId.tsx +0 -60
  280. package/src/pages/checkout.tsx +0 -31
  281. package/src/pages/pages.$pageSlug.tsx +0 -74
  282. package/src/pages/thank-you.tsx +0 -53
  283. package/src/providers/auth.tsx +0 -96
  284. package/src/providers/cart.tsx +0 -275
  285. package/src/providers/ecomiq.ts +0 -137
  286. package/src/providers/index.ts +0 -26
  287. package/src/proxy-api.ts +0 -20
  288. package/src/public-config.ts +0 -24
  289. package/src/review-submission.ts +0 -89
  290. package/src/runtime/context.ts +0 -2
  291. package/src/runtime/default-layout.tsx +0 -64
  292. package/src/runtime/head.ts +0 -149
  293. package/src/runtime/page.tsx +0 -143
  294. package/src/runtime/postcss-browser-stub.mjs +0 -5
  295. package/src/server-config-store.ts +0 -35
  296. package/src/server.ts +0 -286
  297. package/src/styles.css +0 -76
  298. package/src/ui/badge.tsx +0 -32
  299. package/src/ui/button.tsx +0 -31
  300. package/src/ui/card.tsx +0 -31
  301. package/src/ui/carousel.tsx +0 -218
  302. package/src/ui/cn.ts +0 -6
  303. package/src/ui/index.ts +0 -8
  304. package/src/ui/separator.tsx +0 -6
  305. package/src/ui/skeleton.tsx +0 -6
  306. package/src/ui/storefront-error.tsx +0 -49
  307. package/src/utils.ts +0 -36
  308. package/src/vite-inline.mjs +0 -263
  309. package/templates/__root.tsx +0 -83
  310. 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 {};