@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
@@ -1,64 +0,0 @@
1
- /**
2
- * Layout por defecto de Ecomiq.
3
- * Nav y footer salen de settings.cms.menus (main / footer).
4
- */
5
- import { Link } from '@tanstack/react-router'
6
- import { getMenuItems } from '@ecomiq/core'
7
- import type { LayoutProps } from '../index'
8
-
9
- export default function DefaultLayout({ children, settings }: LayoutProps) {
10
- const mainItems = getMenuItems(settings, 'main')
11
- const footerItems = getMenuItems(settings, 'footer')
12
- const nav =
13
- mainItems.length > 0
14
- ? mainItems.map((item) => ({ label: item.label, to: item.url, target: item.target }))
15
- : [{ label: 'Productos', to: '/', target: null as string | null }]
16
-
17
- const storeName = settings?.store.name ?? 'Tienda'
18
-
19
- return (
20
- <div className="flex min-h-dvh flex-col">
21
- <header className="sticky top-0 z-40 border-b bg-background/90 backdrop-blur supports-[backdrop-filter]:bg-background/75">
22
- <div className="mx-auto flex h-14 w-full max-w-6xl items-center justify-between px-4">
23
- <Link to="/" className="font-semibold tracking-tight text-lg">
24
- {storeName}
25
- </Link>
26
- <nav className="flex items-center gap-5 text-sm text-muted-foreground">
27
- {nav.map((item) =>
28
- item.target === '_blank' ? (
29
- <a
30
- key={item.to}
31
- href={item.to}
32
- target="_blank"
33
- rel="noreferrer"
34
- className="transition-colors hover:text-foreground"
35
- >
36
- {item.label}
37
- </a>
38
- ) : (
39
- <Link key={item.to} to={item.to} className="transition-colors hover:text-foreground">
40
- {item.label}
41
- </Link>
42
- ),
43
- )}
44
- </nav>
45
- </div>
46
- </header>
47
- <main className="mx-auto w-full max-w-6xl flex-1 px-4 py-8">{children}</main>
48
- <footer className="border-t">
49
- <div className="mx-auto flex w-full max-w-6xl flex-col gap-4 px-4 py-6 text-sm text-muted-foreground sm:flex-row sm:items-center sm:justify-between">
50
- <p>{settings?.store.description || `${storeName} — creado con Ecomiq`}</p>
51
- {footerItems.length > 0 && (
52
- <nav className="flex flex-wrap gap-4">
53
- {footerItems.map((item) => (
54
- <Link key={item.url} to={item.url} className="transition-colors hover:text-foreground">
55
- {item.label}
56
- </Link>
57
- ))}
58
- </nav>
59
- )}
60
- </div>
61
- </footer>
62
- </div>
63
- )
64
- }
@@ -1,149 +0,0 @@
1
- /**
2
- * Runtime interno: construcción del <head>.
3
- * Mezcla SEO/branding/tracking de `/v1/settings` con el `meta` de cada página
4
- * (la página siempre gana) y genera los scripts de analytics del CMS.
5
- */
6
- import type { StorefrontSettings } from '@ecomiq/core'
7
- import type { PageMeta } from '../index'
8
- import {
9
- cmsBranding,
10
- cmsSeo,
11
- storeDisplayName,
12
- storeSeoDescription,
13
- } from '../utils'
14
-
15
- type MetaTag = Record<string, string>
16
- type LinkTag = Record<string, string>
17
- type ScriptTag = Record<string, string | boolean> & { children?: string }
18
-
19
- interface HeadResult {
20
- meta?: MetaTag[]
21
- links?: LinkTag[]
22
- scripts?: ScriptTag[]
23
- }
24
-
25
- function serializeJsonLd(value: Record<string, unknown>) {
26
- return JSON.stringify(value)
27
- .replace(/</g, '\\u003c')
28
- .replace(/\u2028/g, '\\u2028')
29
- .replace(/\u2029/g, '\\u2029')
30
- }
31
-
32
- function siteName(settings: StorefrontSettings | null | undefined): string {
33
- return storeDisplayName(settings) ?? 'Tienda'
34
- }
35
-
36
- /** Aplica titleTemplate del CMS (`{page} | {site}` o `%s · Tienda`). */
37
- export function resolveTitle(
38
- pageTitle: string | undefined,
39
- settings: StorefrontSettings | null | undefined,
40
- ): string {
41
- const name = siteName(settings)
42
- const seo = cmsSeo(settings)
43
- if (!pageTitle) return seo?.metaTitle ?? name
44
-
45
- const template = seo?.titleTemplate?.trim()
46
- if (!template) return `${pageTitle} · ${name}`
47
-
48
- return template
49
- .replaceAll('{page}', pageTitle)
50
- .replaceAll('{site}', name)
51
- .replace('%s', pageTitle)
52
- }
53
-
54
- /** Head global: charset, viewport, favicon, tracking. Va en el root. */
55
- export function buildRootHead(
56
- settings: StorefrontSettings | null | undefined,
57
- ): HeadResult {
58
- const branding = cmsBranding(settings)
59
- const seo = cmsSeo(settings)
60
-
61
- const meta: MetaTag[] = [
62
- { charSet: 'utf-8' },
63
- { name: 'viewport', content: 'width=device-width, initial-scale=1' },
64
- ]
65
- if (seo?.robotsIndex === false) {
66
- meta.push({ name: 'robots', content: 'noindex, nofollow' })
67
- }
68
-
69
- const links: LinkTag[] = [
70
- { rel: 'icon', href: branding?.faviconUrl ?? '/favicon.ico' },
71
- ]
72
-
73
- return { meta, links, scripts: buildAnalyticsScripts(settings) }
74
- }
75
-
76
- /** Head por página: title (con plantilla), description, OG/Twitter, robots, metas extra y JSON-LD. */
77
- export function buildPageHead(
78
- pageMeta: PageMeta | undefined,
79
- settings: StorefrontSettings | null | undefined,
80
- ): HeadResult {
81
- const branding = cmsBranding(settings)
82
- const seo = cmsSeo(settings)
83
- const title = resolveTitle(pageMeta?.title, settings)
84
- const description = pageMeta?.description ?? storeSeoDescription(settings) ?? undefined
85
- const ogImage = pageMeta?.ogImage ?? branding?.socialImageUrl ?? undefined
86
- const name = siteName(settings)
87
-
88
- const meta: MetaTag[] = [{ title }]
89
- if (description) meta.push({ name: 'description', content: description })
90
- if (pageMeta?.noIndex || seo?.robotsIndex === false) {
91
- meta.push({ name: 'robots', content: 'noindex, nofollow' })
92
- }
93
-
94
- meta.push({ property: 'og:title', content: title })
95
- meta.push({ property: 'og:type', content: 'website' })
96
- meta.push({ property: 'og:site_name', content: name })
97
- if (description) meta.push({ property: 'og:description', content: description })
98
- if (ogImage) {
99
- meta.push({ property: 'og:image', content: ogImage })
100
- meta.push({ name: 'twitter:card', content: 'summary_large_image' })
101
- meta.push({ name: 'twitter:image', content: ogImage })
102
- }
103
-
104
- for (const extra of pageMeta?.meta ?? []) meta.push(extra as MetaTag)
105
-
106
- const scripts: ScriptTag[] = []
107
- if (pageMeta?.jsonLd) {
108
- scripts.push({ type: 'application/ld+json', children: serializeJsonLd(pageMeta.jsonLd) })
109
- }
110
-
111
- return { meta, ...(scripts.length ? { scripts } : {}) }
112
- }
113
-
114
- /** Traduce tracking + customScripts del CMS a etiquetas <script>. */
115
- export function buildAnalyticsScripts(
116
- settings: StorefrontSettings | null | undefined,
117
- ): ScriptTag[] {
118
- const tracking = settings?.cms?.settings?.tracking
119
- const custom = settings?.cms?.settings?.customScripts
120
- const scripts: ScriptTag[] = []
121
-
122
- if (tracking?.googleAnalyticsMeasurementId) {
123
- const id = tracking.googleAnalyticsMeasurementId
124
- scripts.push({ src: `https://www.googletagmanager.com/gtag/js?id=${id}`, async: true })
125
- scripts.push({
126
- children: `window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments)};gtag('js',new Date());gtag('config','${id}');`,
127
- })
128
- }
129
-
130
- if (tracking?.googleTagManagerContainerId) {
131
- const id = tracking.googleTagManagerContainerId
132
- scripts.push({
133
- children: `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','${id}');`,
134
- })
135
- }
136
-
137
- if (tracking?.metaPixelId) {
138
- const id = tracking.metaPixelId
139
- scripts.push({
140
- children: `!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,document,'script','https://connect.facebook.net/en_US/fbevents.js');fbq('init','${id}');fbq('track','PageView');`,
141
- })
142
- }
143
-
144
- if (custom?.enabled && custom.head) {
145
- scripts.push({ children: custom.head })
146
- }
147
-
148
- return scripts
149
- }
@@ -1,143 +0,0 @@
1
- /**
2
- * Runtime interno de Ecomiq (solo lo importa el código generado en `.ecomiq`).
3
- * Traduce el contrato público `definePage` a las opciones del router interno.
4
- */
5
- import { useContext } from 'react'
6
- import { useRouterState } from '@tanstack/react-router'
7
- import type { StorefrontSettings } from '@ecomiq/core'
8
- import type { EcomiqPage, PublicEcomiqConfig } from '../index'
9
- import { AppEcomiqContext } from '../providers/ecomiq'
10
- import { serverApi } from '../server'
11
- import { StorefrontError } from '../ui/storefront-error'
12
- import { buildPageHead } from './head'
13
-
14
- function isSettings(value: unknown): value is StorefrontSettings {
15
- return Boolean(
16
- value &&
17
- typeof value === 'object' &&
18
- value !== null &&
19
- 'store' in value,
20
- )
21
- }
22
-
23
- async function resolveSettingsForMeta(
24
- matches?: Array<{ loaderData?: unknown }>,
25
- ): Promise<StorefrontSettings | undefined> {
26
- // Preferir el loader del root si ya está en el match (hidratación cliente).
27
- // En SSR `matches` suele venir stale (updateMatch no muta el array), así que
28
- // caemos a serverApi: el cliente core cachea settings y no hay HTTP extra.
29
- const fromRoot = matches?.[0]?.loaderData
30
- if (isSettings(fromRoot)) {
31
- return fromRoot
32
- }
33
- try {
34
- return await serverApi.getSettings()
35
- } catch {
36
- return undefined
37
- }
38
- }
39
-
40
- function usePageSettings(): StorefrontSettings | undefined {
41
- // Mismo módulo que AppEcomiqProvider (no el barrel) para evitar contextos duplicados.
42
- const fromProvider = useContext(AppEcomiqContext)?.settings
43
- const fromRootLoader = useRouterState({
44
- select: (state) => {
45
- const data = state.matches[0]?.loaderData
46
- return isSettings(data) ? data : undefined
47
- },
48
- })
49
- return fromProvider ?? fromRootLoader
50
- }
51
-
52
- export function pageToRouteOptions<
53
- TData,
54
- TParams extends Record<string, string>,
55
- TSearch extends Record<string, unknown>,
56
- >(
57
- page: EcomiqPage<TData, TParams, TSearch>,
58
- config: PublicEcomiqConfig,
59
- ) {
60
- const readSearch = page.validateSearch ?? ((raw: Record<string, unknown>) => raw as TSearch)
61
- const reloadOnSearch = page.reloadOnSearch !== false
62
- const stableLoaderDeps: Record<string, never> = {}
63
-
64
- return {
65
- preload: page.preload,
66
- shouldReload: reloadOnSearch ? undefined : false,
67
- validateSearch: readSearch,
68
- loaderDeps: ({ search }: { search: TSearch }) => reloadOnSearch ? search : stableLoaderDeps,
69
- loader: page.loader
70
- ? ({ params, deps, location }: {
71
- params: TParams
72
- deps: TSearch | Record<string, never>
73
- location?: { search?: Record<string, unknown> }
74
- }) => {
75
- let search = readSearch(location?.search ?? {})
76
- if (reloadOnSearch) {
77
- search = deps as TSearch
78
- }
79
- return page.loader!({
80
- params,
81
- search,
82
- config,
83
- })
84
- }
85
- : undefined,
86
- head: async ({ loaderData, params, match, matches }: {
87
- loaderData: TData
88
- params: TParams
89
- match: { search: TSearch }
90
- matches?: Array<{ loaderData?: unknown }>
91
- }) => {
92
- // Con loader: si TanStack calcula head antes de tener datos, degrada al head global.
93
- // Sin loader: loaderData es siempre undefined — aún así hay que llamar meta.
94
- const waitingForLoader = Boolean(page.loader) && loaderData === undefined
95
- if (waitingForLoader) return buildPageHead(undefined, undefined)
96
-
97
- const settings = page.meta
98
- ? await resolveSettingsForMeta(matches)
99
- : undefined
100
-
101
- return buildPageHead(
102
- page.meta?.({
103
- data: loaderData,
104
- params,
105
- search: match.search,
106
- config,
107
- settings,
108
- }),
109
- settings,
110
- )
111
- },
112
- pendingComponent: page.loading,
113
- errorComponent: page.error
114
- ? ({ error, reset }: { error: Error; reset: () => void }) => page.error!({ error, reset })
115
- : ({ reset }: { error: Error; reset: () => void }) => <StorefrontError onRetry={reset} />,
116
- }
117
- }
118
-
119
- export function PageBoundary<
120
- TData,
121
- TParams extends Record<string, string>,
122
- TSearch extends Record<string, unknown>,
123
- >({
124
- page,
125
- data,
126
- params,
127
- search,
128
- }: {
129
- page: EcomiqPage<TData, TParams, TSearch>
130
- data: TData
131
- params: TParams
132
- search: TSearch
133
- }) {
134
- const settings = usePageSettings()
135
- // Concurrent render / contexto duplicado: no tumbar el root.
136
- // El re-render sync con provider o el loader del root suelen recuperar.
137
- if (!settings) {
138
- const Loading = page.loading
139
- return Loading ? <Loading /> : null
140
- }
141
- const Component = page.component
142
- return <Component data={data} params={params} search={search} settings={settings} />
143
- }
@@ -1,5 +0,0 @@
1
- export function parse() {
2
- throw new Error('El storefront no admite estilos inline en HTML enriquecido.')
3
- }
4
-
5
- export default { parse }
@@ -1,35 +0,0 @@
1
- import type { CreateApiOptions } from '@ecomiq/core'
2
- import { createServerOnlyFn } from '@tanstack/react-start'
3
-
4
- export interface ServerEcomiqCloudConfig {
5
- baseUrl?: string
6
- artifactBaseUrl?: string
7
- storeSlug?: string
8
- timeoutMs?: number
9
- cacheTtlMs?: number
10
- }
11
-
12
- export interface ServerEcomiqConfig {
13
- domain: string
14
- api?: CreateApiOptions
15
- cloud?: ServerEcomiqCloudConfig
16
- }
17
-
18
- const serverConfigKey = Symbol.for('@ecomiq/storefront/server-config')
19
- const serverGlobal = globalThis as typeof globalThis & {
20
- [key: symbol]: ServerEcomiqConfig | undefined
21
- }
22
-
23
- export const registerServerConfig = createServerOnlyFn((config: ServerEcomiqConfig): void => {
24
- serverGlobal[serverConfigKey] = config
25
- })
26
-
27
- export const getServerConfig = createServerOnlyFn((): ServerEcomiqConfig => {
28
- const registered = serverGlobal[serverConfigKey]
29
- if (!registered) {
30
- throw new Error(
31
- 'Config server de Ecomiq no disponible. Ejecuta la app mediante `ecomiq dev|build`.',
32
- )
33
- }
34
- return registered
35
- })
package/src/server.ts DELETED
@@ -1,286 +0,0 @@
1
- /**
2
- * API storefront que solo corre en el servidor (TanStack Start RPC).
3
- * En SSR ejecuta el handler localmente; en el cliente llama al Worker.
4
- *
5
- * ```ts
6
- * import { definePage, serverApi } from '@ecomiq/storefront'
7
- *
8
- * export default definePage({
9
- * loader: () => serverApi.getProducts({ page: 1, pageSize: 12 }),
10
- * component: ({ data }) => …,
11
- * })
12
- * ```
13
- *
14
- * Nota: cada `createServerFn` debe vivir en el top-level del módulo
15
- * (el compilador de Start asigna IDs estables por call-site).
16
- * El cliente storefront es singleton → el cache de settings se reutiliza.
17
- */
18
- import { createServerFn } from '@tanstack/react-start'
19
- import {
20
- AddCartItemParamsSchema,
21
- CartAddressesParamsSchema,
22
- CartBuyerParamsSchema,
23
- CartCheckoutParamsSchema,
24
- CartCheckoutReadParamsSchema,
25
- CartPromotionCodeParamsSchema,
26
- CreateProductReviewParamsSchema,
27
- GetCartParamsSchema,
28
- GetDepartmentsParamsSchema,
29
- GetDistrictsParamsSchema,
30
- GetProvincesParamsSchema,
31
- GetShippingOptionsParamsSchema,
32
- ListProductReviewsParamsSchema,
33
- ProductAutocompleteParamsSchema,
34
- ProductDetailParamsSchema,
35
- ProductsParamsSchema,
36
- PutShippingMethodParamsSchema,
37
- RelatedProductsParamsSchema,
38
- RemoveCartItemParamsSchema,
39
- UpdateCartItemQuantityParamsSchema,
40
- type AddCartItemParams,
41
- type CartAddressesParams,
42
- type CartBuyerParams,
43
- type CartCheckoutParams,
44
- type CartCheckoutReadParams,
45
- type CartPromotionCodeParams,
46
- type CreateProductReviewParams,
47
- type GetCartParams,
48
- type GetDepartmentsParams,
49
- type GetDistrictsParams,
50
- type GetProvincesParams,
51
- type GetShippingOptionsParams,
52
- type ListProductReviewsParams,
53
- type ProductAutocompleteParams,
54
- type ProductDetailParams,
55
- type ProductsParamsInput,
56
- type PutShippingMethodParams,
57
- type RelatedProductsParams,
58
- type RemoveCartItemParams,
59
- type UpdateCartItemQuantityParams,
60
- type UploadPaymentReceiptParams,
61
- CartTokenSchema,
62
- EntityIdSchema,
63
- } from '@ecomiq/core'
64
- import { z } from 'zod'
65
- import { getStorefrontClient } from './client'
66
- import {
67
- loadActiveCart,
68
- submitCartItemQuantity,
69
- submitCartItemRemoval,
70
- submitProductToCart,
71
- type AddProductToCartInput,
72
- } from './cart-session'
73
- import { submitProductReview } from './review-submission'
74
-
75
- const getSettingsFn = createServerFn({ method: 'GET' }).handler(() =>
76
- getStorefrontClient().getSettings(),
77
- )
78
-
79
- const getStoreIdFn = createServerFn({ method: 'GET' }).handler(() =>
80
- getStorefrontClient().getStoreId(),
81
- )
82
-
83
- const getCollectionsFn = createServerFn({ method: 'GET' }).handler(() =>
84
- getStorefrontClient().getCollections(),
85
- )
86
-
87
- const getCollectionBySlugFn = createServerFn({ method: 'GET' })
88
- .validator(z.object({ slug: z.string().min(1) }))
89
- .handler(({ data }) => getStorefrontClient().getCollectionBySlug(data.slug))
90
-
91
- const getPageBySlugFn = createServerFn({ method: 'GET' })
92
- .validator(z.object({ slug: z.string().min(1) }))
93
- .handler(({ data }) => getStorefrontClient().getPageBySlug(data.slug))
94
-
95
- const getProductsFn = createServerFn({ method: 'GET' })
96
- .validator(ProductsParamsSchema)
97
- .handler(({ data }) => getStorefrontClient().getProducts(data))
98
-
99
- const ProductBySlugServerParamsSchema = ProductDetailParamsSchema.extend({
100
- slug: z.string().min(1),
101
- })
102
-
103
- const getProductBySlugFn = createServerFn({ method: 'GET' })
104
- .validator(ProductBySlugServerParamsSchema)
105
- .handler(({ data }) =>
106
- getStorefrontClient().getProductBySlug(data.slug, { sellerId: data.sellerId }),
107
- )
108
-
109
- const getRelatedProductsFn = createServerFn({ method: 'GET' })
110
- .validator(RelatedProductsParamsSchema)
111
- .handler(({ data }) => getStorefrontClient().getRelatedProducts(data))
112
-
113
- const autocompleteProductsFn = createServerFn({ method: 'GET' })
114
- .validator(ProductAutocompleteParamsSchema)
115
- .handler(({ data }) => getStorefrontClient().autocompleteProducts(data))
116
-
117
- const listProductReviewsFn = createServerFn({ method: 'GET' })
118
- .validator(ListProductReviewsParamsSchema)
119
- .handler(({ data }) => getStorefrontClient().listProductReviews(data))
120
-
121
- const submitProductReviewFn = createServerFn({ method: 'POST' })
122
- .validator(CreateProductReviewParamsSchema)
123
- .handler(({ data }) => submitProductReview(getStorefrontClient(), data))
124
-
125
- const loadCartFn = createServerFn({ method: 'POST' })
126
- .validator(GetCartParamsSchema)
127
- .handler(({ data }) => loadActiveCart(getStorefrontClient(), data))
128
-
129
- const setCartItemQuantityFn = createServerFn({ method: 'POST' })
130
- .validator(UpdateCartItemQuantityParamsSchema)
131
- .handler(({ data }) => submitCartItemQuantity(getStorefrontClient(), data))
132
-
133
- const removeCartItemFn = createServerFn({ method: 'POST' })
134
- .validator(RemoveCartItemParamsSchema)
135
- .handler(({ data }) => submitCartItemRemoval(getStorefrontClient(), data))
136
-
137
- const AddProductToCartServerSchema = z.object({
138
- cartToken: CartTokenSchema.optional(),
139
- currencyCode: z.string().length(3),
140
- variantId: EntityIdSchema,
141
- quantity: z.number().int().positive(),
142
- })
143
-
144
- const addProductToCartFn = createServerFn({ method: 'POST' })
145
- .validator(AddProductToCartServerSchema)
146
- .handler(({ data }) => submitProductToCart(getStorefrontClient(), data))
147
-
148
- const addCartItemFn = createServerFn({ method: 'POST' })
149
- .validator(AddCartItemParamsSchema)
150
- .handler(({ data }) => getStorefrontClient().addCartItem(data))
151
-
152
- const getCartCheckoutFn = createServerFn({ method: 'GET' })
153
- .validator(CartCheckoutReadParamsSchema)
154
- .handler(({ data }) => getStorefrontClient().getCartCheckout(data))
155
-
156
- const getShippingOptionsFn = createServerFn({ method: 'GET' })
157
- .validator(GetShippingOptionsParamsSchema)
158
- .handler(({ data }) => getStorefrontClient().getShippingOptions(data))
159
-
160
- const putCartShippingMethodFn = createServerFn({ method: 'POST' })
161
- .validator(PutShippingMethodParamsSchema)
162
- .handler(({ data }) => getStorefrontClient().putCartShippingMethod(data))
163
-
164
- const patchCartBuyerFn = createServerFn({ method: 'POST' })
165
- .validator(CartBuyerParamsSchema)
166
- .handler(({ data }) => getStorefrontClient().patchCartBuyer(data))
167
-
168
- const patchCartAddressesFn = createServerFn({ method: 'POST' })
169
- .validator(CartAddressesParamsSchema)
170
- .handler(({ data }) => getStorefrontClient().patchCartAddresses(data))
171
-
172
- const checkoutCartFn = createServerFn({ method: 'POST' })
173
- .validator(CartCheckoutParamsSchema)
174
- .handler(({ data }) => getStorefrontClient().checkoutCart(data))
175
-
176
- const CartPaymentReceiptServerSchema = z.object({
177
- cartToken: CartTokenSchema,
178
- fileBase64: z.string().min(1),
179
- fileName: z.string().min(1),
180
- mimeType: z.string().min(1).optional(),
181
- })
182
-
183
- const uploadPaymentReceiptFn = createServerFn({ method: 'POST' })
184
- .validator(CartPaymentReceiptServerSchema)
185
- .handler(({ data }) => {
186
- const binary = Uint8Array.from(atob(data.fileBase64), (c) => c.charCodeAt(0))
187
- const file = new Blob([binary], { type: data.mimeType ?? 'application/octet-stream' })
188
- return getStorefrontClient().uploadPaymentReceipt({
189
- cartToken: data.cartToken,
190
- file,
191
- fileName: data.fileName,
192
- })
193
- })
194
-
195
- const addCartPromotionCodeFn = createServerFn({ method: 'POST' })
196
- .validator(CartPromotionCodeParamsSchema)
197
- .handler(({ data }) => getStorefrontClient().addCartPromotionCode(data))
198
-
199
- const removeCartPromotionCodeFn = createServerFn({ method: 'POST' })
200
- .validator(CartPromotionCodeParamsSchema)
201
- .handler(({ data }) => getStorefrontClient().removeCartPromotionCode(data))
202
-
203
- const getCountriesFn = createServerFn({ method: 'GET' }).handler(() =>
204
- getStorefrontClient().getCountries(),
205
- )
206
-
207
- const getDepartmentsFn = createServerFn({ method: 'GET' })
208
- .validator(GetDepartmentsParamsSchema)
209
- .handler(({ data }) => getStorefrontClient().getDepartments(data))
210
-
211
- const getProvincesFn = createServerFn({ method: 'GET' })
212
- .validator(GetProvincesParamsSchema)
213
- .handler(({ data }) => getStorefrontClient().getProvinces(data))
214
-
215
- const getDistrictsFn = createServerFn({ method: 'GET' })
216
- .validator(GetDistrictsParamsSchema)
217
- .handler(({ data }) => getStorefrontClient().getDistricts(data))
218
-
219
- /**
220
- * Cliente storefront server-only. Misma superficie útil que `createClient()`,
221
- * pero cada método es una server function reutilizable desde cualquier página.
222
- */
223
- export const serverApi = {
224
- getSettings: () => getSettingsFn(),
225
- getStoreId: () => getStoreIdFn(),
226
- getCollections: () => getCollectionsFn(),
227
- getCollectionBySlug: (slug: string) => getCollectionBySlugFn({ data: { slug } }),
228
- getPageBySlug: (slug: string) => getPageBySlugFn({ data: { slug } }),
229
- getProducts: (
230
- params: ProductsParamsInput = {},
231
- options: { signal?: AbortSignal } = {},
232
- ) => getProductsFn({ data: params, signal: options.signal }),
233
- getProductBySlug: (slug: string, params: ProductDetailParams = {}) =>
234
- getProductBySlugFn({ data: { slug, ...params } }),
235
- getRelatedProducts: (params: RelatedProductsParams) =>
236
- getRelatedProductsFn({ data: params }),
237
- autocompleteProducts: (params: ProductAutocompleteParams) =>
238
- autocompleteProductsFn({ data: params }),
239
- listProductReviews: (params: ListProductReviewsParams) =>
240
- listProductReviewsFn({ data: params }),
241
- submitProductReview: (params: CreateProductReviewParams) =>
242
- submitProductReviewFn({ data: params }),
243
- loadCart: (params: GetCartParams) => loadCartFn({ data: params }),
244
- setCartItemQuantity: (params: UpdateCartItemQuantityParams) =>
245
- setCartItemQuantityFn({ data: params }),
246
- removeCartItem: (params: RemoveCartItemParams) =>
247
- removeCartItemFn({ data: params }),
248
- addProductToCart: (params: AddProductToCartInput) =>
249
- addProductToCartFn({ data: params }),
250
- addCartItem: (params: AddCartItemParams) => addCartItemFn({ data: params }),
251
- getCartCheckout: (params: CartCheckoutReadParams) =>
252
- getCartCheckoutFn({ data: params }),
253
- getShippingOptions: (params: GetShippingOptionsParams) =>
254
- getShippingOptionsFn({ data: params }),
255
- putCartShippingMethod: (params: PutShippingMethodParams) =>
256
- putCartShippingMethodFn({ data: params }),
257
- patchCartBuyer: (params: CartBuyerParams) => patchCartBuyerFn({ data: params }),
258
- patchCartAddresses: (params: CartAddressesParams) =>
259
- patchCartAddressesFn({ data: params }),
260
- checkoutCart: (params: CartCheckoutParams) => checkoutCartFn({ data: params }),
261
- uploadPaymentReceipt: async (params: UploadPaymentReceiptParams) => {
262
- const buffer = await params.file.arrayBuffer()
263
- const bytes = new Uint8Array(buffer)
264
- let binary = ''
265
- for (const byte of bytes) binary += String.fromCharCode(byte)
266
- return uploadPaymentReceiptFn({
267
- data: {
268
- cartToken: params.cartToken,
269
- fileBase64: btoa(binary),
270
- fileName:
271
- params.fileName ??
272
- (params.file instanceof File ? params.file.name : 'receipt'),
273
- mimeType: params.file.type || undefined,
274
- },
275
- })
276
- },
277
- addCartPromotionCode: (params: CartPromotionCodeParams) =>
278
- addCartPromotionCodeFn({ data: params }),
279
- removeCartPromotionCode: (params: CartPromotionCodeParams) =>
280
- removeCartPromotionCodeFn({ data: params }),
281
- getCountries: () => getCountriesFn(),
282
- getDepartments: (params: GetDepartmentsParams) =>
283
- getDepartmentsFn({ data: params }),
284
- getProvinces: (params: GetProvincesParams) => getProvincesFn({ data: params }),
285
- getDistricts: (params: GetDistrictsParams) => getDistrictsFn({ data: params }),
286
- }