@ecomiq/storefront 2.0.22 → 2.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -72,16 +72,14 @@ Ver el monorepo [ecomiq-storefront](https://github.com/ecomiq/ecomiq-storefront)
72
72
 
73
73
  ## Storefront declarativo
74
74
 
75
- `StorefrontDefinition v1` permite construir y versionar una tienda sin generar
76
- código React arbitrario. El contrato valida tema, navegación, footer y ocho
77
- tipos de sección: `hero`, `product-grid`, `collection-grid`, `promo-banner`,
78
- `image-text`, `rich-text`, `testimonials` y `newsletter`.
75
+ El contrato y el renderer viven fuera de este package:
76
+
77
+ - `@ecomiq/storefront-definition` — schema Zod, patches, migraciones
78
+ - `@ecomiq/storefront-definition/react` — `DefinitionRenderer`, loaders y hooks
79
79
 
80
80
  ```tsx
81
- import {
82
- StorefrontDefinitionRenderer,
83
- createDefaultStorefrontDefinition,
84
- } from '@ecomiq/storefront'
81
+ import { createDefaultStorefrontDefinition } from '@ecomiq/storefront-definition'
82
+ import { DefinitionRenderer } from '@ecomiq/storefront-definition/react'
85
83
 
86
84
  const definition = createDefaultStorefrontDefinition({
87
85
  storeName: 'Casa Lumbre',
@@ -90,7 +88,7 @@ const definition = createDefaultStorefrontDefinition({
90
88
 
91
89
  export function Home() {
92
90
  return (
93
- <StorefrontDefinitionRenderer
91
+ <DefinitionRenderer
94
92
  definition={definition}
95
93
  locale="es-PE"
96
94
  currency="PEN"
@@ -107,27 +105,9 @@ export function Home() {
107
105
  }
108
106
  ```
109
107
 
110
- Los sistemas que solo necesitan validar o modificar el contrato pueden importar
111
- el subpath sin cargar el renderer:
112
-
113
108
  ```ts
114
109
  import {
115
110
  StorefrontDefinitionSchema,
116
- StorefrontDefinitionPatchSchema,
117
111
  applyStorefrontDefinitionPatch,
118
- type StorefrontDefinitionInput,
119
- type StorefrontDefinitionPatchInput,
120
- } from '@ecomiq/storefront/definition'
112
+ } from '@ecomiq/storefront-definition'
121
113
  ```
122
-
123
- Cada definición lleva `version` y `revision`. Los patches son puros, exigen
124
- `expectedRevision` y conservan el ID de una sección al reemplazarla. Soportan
125
- `section.add`, `section.replace`, `section.remove`, `section.reorder`,
126
- `theme.replace`, `navigation.replace` y `footer.replace`.
127
-
128
- El template productivo consulta server-side
129
- `GET /v1/runtime/storefronts/:storeSlug`, revalida la publicación mediante
130
- ETag y resuelve los `product-grid.source` y `collection-grid.source` contra el
131
- API storefront. La publicación declarativa reemplaza solo el contenido de la
132
- home; el layout comercial y las rutas de catálogo, producto, carrito, checkout
133
- y cuenta siguen siendo las del framework.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ecomiq/storefront",
3
- "version": "2.0.22",
3
+ "version": "2.1.4",
4
4
  "description": "Micro framework SSR de Ecomiq para storefronts. Páginas, datos y deploy sin configurar nada.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -32,8 +32,6 @@
32
32
  "default": "./src/config.mjs"
33
33
  },
34
34
  "./ui": "./src/ui/index.ts",
35
- "./definition": "./src/storefront-definition/contract.ts",
36
- "./definition/react": "./src/storefront-definition/index.ts",
37
35
  "./styles.css": "./src/styles.css",
38
36
  "./internal/page": "./src/runtime/page.tsx",
39
37
  "./internal/context": "./src/runtime/context.ts",
@@ -84,8 +82,7 @@
84
82
  "vite": "^8.1.0",
85
83
  "wrangler": "^4.100.0",
86
84
  "zod": "^3.25.0",
87
- "@ecomiq/core": "^0.1.8",
88
- "@ecomiq/storefront-definition": "^1.0.0"
85
+ "@ecomiq/core": "^0.1.9"
89
86
  },
90
87
  "peerDependencies": {
91
88
  "react": "^19.0.0",
@@ -1,6 +1,5 @@
1
1
  import {
2
2
  ApiError,
3
- cartVariantIdFromProduct,
4
3
  type RemoveCartItemParams,
5
4
  type StorefrontCart,
6
5
  type StorefrontClient,
@@ -11,7 +10,7 @@ import { z } from 'zod'
11
10
  type CartClient = Pick<StorefrontClient, 'getCart' | 'createCart' | 'addCartItem'>
12
11
 
13
12
  export interface LoadActiveCartInput {
14
- cartId: string
13
+ cartToken: string
15
14
  }
16
15
 
17
16
  export type ActiveCartLoadResult =
@@ -35,14 +34,14 @@ export type CartItemMutationResult =
35
34
  }
36
35
 
37
36
  export interface AddProductToCartInput {
38
- cartId?: string
37
+ cartToken?: string
39
38
  currencyCode: string
40
39
  variantId: string
41
40
  quantity: number
42
41
  }
43
42
 
44
43
  export interface AddProductToCartResult {
45
- cartId: string
44
+ cartToken: string
46
45
  cart: StorefrontCart
47
46
  created: boolean
48
47
  }
@@ -118,7 +117,7 @@ export async function loadActiveCart(
118
117
  input: LoadActiveCartInput,
119
118
  ): Promise<ActiveCartLoadResult> {
120
119
  try {
121
- const cart = await client.getCart({ cartId: input.cartId })
120
+ const cart = await client.getCart({ cartToken: input.cartToken })
122
121
  return { ok: true as const, value: cartIsActive(cart) ? cart : null }
123
122
  } catch (error) {
124
123
  if (cartIsUnavailable(error)) return { ok: true as const, value: null }
@@ -165,13 +164,12 @@ export async function addProductToCart(
165
164
  client: CartClient,
166
165
  input: AddProductToCartInput,
167
166
  ): Promise<AddProductToCartResult> {
168
- const variantId = cartVariantIdFromProduct(input.variantId)
169
167
  let current: StorefrontCart | undefined
170
168
  let created = false
171
169
 
172
- if (input.cartId) {
170
+ if (input.cartToken) {
173
171
  try {
174
- const persisted = await client.getCart({ cartId: input.cartId })
172
+ const persisted = await client.getCart({ cartToken: input.cartToken })
175
173
  if (cartIsActive(persisted)) current = persisted
176
174
  } catch (error) {
177
175
  if (!cartIsUnavailable(error)) throw error
@@ -183,20 +181,20 @@ export async function addProductToCart(
183
181
  created = true
184
182
  }
185
183
 
186
- const add = (cartId: string) => client.addCartItem({
187
- cartId,
188
- variantId,
184
+ const add = (cartToken: string) => client.addCartItem({
185
+ cartToken,
186
+ variantId: input.variantId,
189
187
  quantity: input.quantity,
190
188
  })
191
189
 
192
190
  try {
193
- const cart = await add(current.id)
194
- return { cartId: cart.id, cart, created }
191
+ const cart = await add(current.token)
192
+ return { cartToken: cart.token, cart, created }
195
193
  } catch (error) {
196
194
  if (!cartIsUnavailable(error)) throw error
197
195
  const replacement = await client.createCart({ currencyCode: input.currencyCode })
198
- const cart = await add(replacement.id)
199
- return { cartId: cart.id, cart, created: true }
196
+ const cart = await add(replacement.token)
197
+ return { cartToken: cart.token, cart, created: true }
200
198
  }
201
199
  }
202
200
 
package/src/client.ts CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  createClient as createCoreClient,
3
3
  type CreateApiOptions,
4
4
  type StorefrontClient,
5
- } from '@ecomiq/core'
5
+ } from '@ecomiq/core/client'
6
6
  import { getServerConfig } from './server-config-store'
7
7
 
8
8
  let sharedClient: StorefrontClient | null = null
package/src/codegen.mjs CHANGED
@@ -198,10 +198,22 @@ export async function generateApp({ cwd, appDir, frameworkRoot, config }) {
198
198
 
199
199
  // ── 5. styles.css: tokens del framework + fuentes de contenido del usuario ──
200
200
  const themeOverrides = buildThemeOverrides(config)
201
+ const projectPkgPath = resolve(cwd, 'package.json')
202
+ const projectPkg = existsSync(projectPkgPath)
203
+ ? JSON.parse(readFileSync(projectPkgPath, 'utf8'))
204
+ : {}
205
+ const hasStorefrontDefinition = Boolean(
206
+ projectPkg.dependencies?.['@ecomiq/storefront-definition'] ||
207
+ projectPkg.devDependencies?.['@ecomiq/storefront-definition'],
208
+ )
201
209
  writeGeneratedFile(
202
210
  join(srcDir, 'styles.css'),
203
211
  HEADER.replace('/*', '/*!') +
204
212
  `@import '@ecomiq/storefront/styles.css';\n` +
213
+ (hasStorefrontDefinition
214
+ ? `@import '@ecomiq/storefront-definition/react/styles.css';\n` +
215
+ `@source '../../../node_modules/@ecomiq/storefront-definition/src/react';\n`
216
+ : '') +
205
217
  `@source '../../pages';\n` +
206
218
  `@source '../../components';\n` +
207
219
  `@source '../../lib';\n` +
@@ -545,7 +557,6 @@ function assertNoFrameworkPageOverrides(pageEntries) {
545
557
  )
546
558
  // Overrides / alias legados
547
559
  reserved.set('/checkout', 'checkout.tsx')
548
- reserved.set('/checkout/$cartId', 'checkout.$cartId.tsx')
549
560
 
550
561
  for (const entry of pageEntries) {
551
562
  const routeId = fileToRouteId(entry.rel)
@@ -45,11 +45,11 @@ import { useCheckoutGeo } from './use-checkout-geo'
45
45
  import { useCheckoutCustomerPrefill } from './use-checkout-customer-prefill'
46
46
  import { useCheckoutSession } from './use-checkout-session'
47
47
 
48
- export function CheckoutSessionView({ cartId }: { cartId: string }) {
48
+ export function CheckoutSessionView({ cartToken }: { cartToken: string }) {
49
49
  const { store } = useSettings()
50
50
  const { session } = useAuth()
51
51
  const isAuthenticated = Boolean(session?.user)
52
- const checkout = useCheckoutSession(cartId)
52
+ const checkout = useCheckoutSession(cartToken)
53
53
  const [stepFlow, setStepFlow] = useState<CheckoutStepFlow>(() => createCheckoutStepFlow())
54
54
  const [fieldErrors, setFieldErrors] = useState<
55
55
  Partial<Record<CheckoutFieldId, string>>
@@ -72,7 +72,7 @@ export function CheckoutSessionView({ cartId }: { cartId: string }) {
72
72
 
73
73
  const customerPrefill = useCheckoutCustomerPrefill({
74
74
  enabled: isAuthenticated && checkout.loadStatus === 'ready',
75
- cartId,
75
+ cartToken,
76
76
  currency: store.currency,
77
77
  contact: checkout.contact,
78
78
  setContact: checkout.setContact,
@@ -298,7 +298,7 @@ export function CheckoutSessionView({ cartId }: { cartId: string }) {
298
298
  return
299
299
  }
300
300
  window.location.assign(
301
- thankYouUrl(cartId, result.payment?.transactionId ?? undefined),
301
+ thankYouUrl(cartToken, result.payment?.transactionId ?? undefined),
302
302
  )
303
303
  } catch {
304
304
  /* formError en sesión */
@@ -2,8 +2,8 @@ import type { CartCheckoutResponse } from '@ecomiq/core'
2
2
 
3
3
  export { formatMoney } from '../../format-money'
4
4
 
5
- export function thankYouUrl(cartId: string, transactionId?: string) {
6
- const q = new URLSearchParams({ cartId })
5
+ export function thankYouUrl(cartToken: string, transactionId?: string) {
6
+ const q = new URLSearchParams({ cartToken })
7
7
  if (transactionId) q.set('transactionId', transactionId)
8
8
  return `/thank-you?${q.toString()}`
9
9
  }
@@ -42,7 +42,7 @@ type ShippingFlatItem = { key: string }
42
42
 
43
43
  type UseCheckoutCustomerPrefillArgs = {
44
44
  enabled: boolean
45
- cartId: string
45
+ cartToken: string
46
46
  currency: string
47
47
  contact: CheckoutContactForm
48
48
  setContact: Dispatch<SetStateAction<CheckoutContactForm>>
@@ -66,7 +66,7 @@ type UseCheckoutCustomerPrefillArgs = {
66
66
 
67
67
  export function useCheckoutCustomerPrefill({
68
68
  enabled,
69
- cartId,
69
+ cartToken,
70
70
  currency,
71
71
  contact,
72
72
  setContact,
@@ -111,7 +111,7 @@ export function useCheckoutCustomerPrefill({
111
111
  setProfile(null)
112
112
  setSavedAddresses([])
113
113
  setSelectedSavedAddressId(null)
114
- }, [cartId])
114
+ }, [cartToken])
115
115
 
116
116
  useEffect(() => {
117
117
  if (!enabled) return
@@ -139,7 +139,7 @@ export function useCheckoutCustomerPrefill({
139
139
  setIsLoadingCustomer(false)
140
140
  }
141
141
  })()
142
- }, [enabled, cartId])
142
+ }, [enabled, cartToken])
143
143
 
144
144
  // Prefill perfil (campos vacíos).
145
145
  useEffect(() => {
@@ -13,7 +13,6 @@ import type {
13
13
  StorefrontCart,
14
14
  StorefrontOrderBump,
15
15
  } from '@ecomiq/core'
16
- import { cartVariantIdFromProduct } from '@ecomiq/core'
17
16
  import { useCart } from '../../providers'
18
17
  import { serverApi } from '../../server'
19
18
  import {
@@ -33,7 +32,7 @@ type ShippingFlat = {
33
32
  rate: ShippingRate
34
33
  }
35
34
 
36
- export function useCheckoutSession(cartId: string) {
35
+ export function useCheckoutSession(cartToken: string) {
37
36
  const { cart: providerCart, clearCart, reload: reloadProviderCart } = useCart()
38
37
 
39
38
  const [checkoutCart, setCheckoutCart] = useState<StorefrontCart | null>(null)
@@ -90,7 +89,7 @@ export function useCheckoutSession(cartId: string) {
90
89
  setLoadStatus('loading')
91
90
  setLoadError(undefined)
92
91
  try {
93
- const data = await serverApi.getCartCheckout({ cartId })
92
+ const data = await serverApi.getCartCheckout({ cartToken })
94
93
  if (isCheckoutCartAlreadyPurchased(data.cart)) {
95
94
  setCheckoutAlreadyPurchased(true)
96
95
  clearCart()
@@ -109,7 +108,7 @@ export function useCheckoutSession(cartId: string) {
109
108
  )
110
109
  setLoadStatus('error')
111
110
  }
112
- }, [cartId, clearCart])
111
+ }, [cartToken, clearCart])
113
112
 
114
113
  useEffect(() => {
115
114
  hydratedRef.current = false
@@ -124,7 +123,7 @@ export function useCheckoutSession(cartId: string) {
124
123
  setCheckoutPaymentMethodCode(null)
125
124
  setDeliveryPersisted(false)
126
125
  void loadCheckout()
127
- }, [cartId, loadCheckout])
126
+ }, [cartToken, loadCheckout])
128
127
 
129
128
  useEffect(() => {
130
129
  if (!checkoutCart || hydratedRef.current) return
@@ -150,7 +149,7 @@ export function useCheckoutSession(cartId: string) {
150
149
  // Cross-tab: sesión de carrito o ítems del provider cambian tras baseline.
151
150
  useEffect(() => {
152
151
  if (loadStatus !== 'ready' || isReconciling || checkoutAlreadyPurchased) return
153
- const sig = cartSessionSignature(cartId, localItems)
152
+ const sig = cartSessionSignature(cartToken, localItems)
154
153
  if (baselineSigRef.current === null) {
155
154
  baselineSigRef.current = sig
156
155
  return
@@ -158,7 +157,7 @@ export function useCheckoutSession(cartId: string) {
158
157
  if (sig !== baselineSigRef.current) {
159
158
  setCartChangedExternally(true)
160
159
  }
161
- }, [cartId, checkoutAlreadyPurchased, isReconciling, loadStatus, localItems])
160
+ }, [cartToken, checkoutAlreadyPurchased, isReconciling, loadStatus, localItems])
162
161
 
163
162
  useEffect(() => {
164
163
  const key = `ecomiq:cart:v1:`
@@ -174,14 +173,14 @@ export function useCheckoutSession(cartId: string) {
174
173
  useEffect(() => {
175
174
  if (loadStatus !== 'ready' || !checkoutCart || checkoutAlreadyPurchased) return
176
175
  if (isReconcilingRef.current) return
177
- if (providerCart && providerCart.id !== cartId) return
176
+ if (providerCart && providerCart.token !== cartToken) return
178
177
  if (localItems.length === 0 && apiItems.length === 0) return
179
178
  if (areCartSignaturesEqual(localItems, apiItems)) return
180
179
 
181
180
  const actions = findCartReconciliationActions(localItems, apiItems)
182
181
  if (actions.length === 0) return
183
182
 
184
- const attemptKey = `${cartId}::${cartItemsSignature(localItems)}::${cartItemsSignature(apiItems)}`
183
+ const attemptKey = `${cartToken}::${cartItemsSignature(localItems)}::${cartItemsSignature(apiItems)}`
185
184
  if (reconcileAttemptRef.current === attemptKey) return
186
185
 
187
186
  reconcileAttemptRef.current = attemptKey
@@ -194,7 +193,7 @@ export function useCheckoutSession(cartId: string) {
194
193
  if (action.action === 'remove') {
195
194
  try {
196
195
  const next = await serverApi.removeCartItem({
197
- cartId,
196
+ cartToken,
198
197
  cartItemId: action.itemId,
199
198
  })
200
199
  if (next.ok) setCheckoutCart(next.value)
@@ -204,7 +203,7 @@ export function useCheckoutSession(cartId: string) {
204
203
  } else if (action.action === 'update') {
205
204
  try {
206
205
  const next = await serverApi.setCartItemQuantity({
207
- cartId,
206
+ cartToken,
208
207
  cartItemId: action.itemId,
209
208
  quantity: action.quantity,
210
209
  })
@@ -218,8 +217,8 @@ export function useCheckoutSession(cartId: string) {
218
217
  if (action.action !== 'add') continue
219
218
  try {
220
219
  const next = await serverApi.addCartItem({
221
- cartId,
222
- variantId: cartVariantIdFromProduct(action.variantId),
220
+ cartToken,
221
+ variantId: action.variantId,
223
222
  quantity: action.quantity,
224
223
  })
225
224
  setCheckoutCart(next)
@@ -237,7 +236,7 @@ export function useCheckoutSession(cartId: string) {
237
236
  })()
238
237
  }, [
239
238
  apiItems,
240
- cartId,
239
+ cartToken,
241
240
  checkoutAlreadyPurchased,
242
241
  checkoutCart,
243
242
  loadCheckout,
@@ -257,7 +256,7 @@ export function useCheckoutSession(cartId: string) {
257
256
  setShippingLoading(true)
258
257
  setShippingError(null)
259
258
  void serverApi
260
- .getShippingOptions({ cartId, postalCode })
259
+ .getShippingOptions({ cartToken, postalCode })
261
260
  .then((res) => {
262
261
  if (!cancelled) setShippingGroups(res.groups)
263
262
  })
@@ -275,7 +274,7 @@ export function useCheckoutSession(cartId: string) {
275
274
  return () => {
276
275
  cancelled = true
277
276
  }
278
- }, [cartId, checkoutAlreadyPurchased, postalCode])
277
+ }, [cartToken, checkoutAlreadyPurchased, postalCode])
279
278
 
280
279
  const shippingFlat = useMemo(() => {
281
280
  const out: ShippingFlat[] = []
@@ -296,14 +295,14 @@ export function useCheckoutSession(cartId: string) {
296
295
  setSelectedShippingKey(shippingFlat[0]!.key)
297
296
  }, [shippingFlat, selectedShippingKey])
298
297
 
299
- const externalRef = `checkout-${cartId}`
298
+ const externalRef = `checkout-${cartToken}`
300
299
 
301
300
  const initProviderCheckout = useCallback(
302
301
  (paymentMethodCode: string) => {
303
302
  const method = paymentMethods.find((m) => m.code === paymentMethodCode)
304
303
  if (!method || !methodUsesProviderCheckoutUi(method)) return
305
304
 
306
- const dedupeKey = `${cartId}:${paymentMethodCode}`
305
+ const dedupeKey = `${cartToken}:${paymentMethodCode}`
307
306
  if (checkoutPaymentInitKeyRef.current === dedupeKey) return
308
307
  checkoutPaymentInitKeyRef.current = dedupeKey
309
308
 
@@ -311,7 +310,7 @@ export function useCheckoutSession(cartId: string) {
311
310
  setCheckoutPaymentError(null)
312
311
  setCheckoutPaymentMethodCode(paymentMethodCode)
313
312
  void serverApi
314
- .checkoutCart({ cartId, paymentMethodCode, externalRef })
313
+ .checkoutCart({ cartToken, paymentMethodCode, externalRef })
315
314
  .then((result) => {
316
315
  setCheckoutPaymentResponse(result)
317
316
  })
@@ -323,7 +322,7 @@ export function useCheckoutSession(cartId: string) {
323
322
  })
324
323
  .finally(() => setCheckoutPaymentLoading(false))
325
324
  },
326
- [cartId, externalRef, paymentMethods],
325
+ [cartToken, externalRef, paymentMethods],
327
326
  )
328
327
 
329
328
  const selectPaymentMethod = useCallback(
@@ -353,7 +352,7 @@ export function useCheckoutSession(cartId: string) {
353
352
 
354
353
  const saveBuyer = useCallback(async () => {
355
354
  const buyerCart = await serverApi.patchCartBuyer({
356
- cartId,
355
+ cartToken,
357
356
  email: contact.email.trim(),
358
357
  firstName: contact.firstName.trim(),
359
358
  lastName: contact.lastName.trim(),
@@ -361,7 +360,7 @@ export function useCheckoutSession(cartId: string) {
361
360
  })
362
361
  setCheckoutCart(buyerCart)
363
362
  return buyerCart
364
- }, [cartId, contact.email, contact.firstName, contact.lastName, contact.phone])
363
+ }, [cartToken, contact.email, contact.firstName, contact.lastName, contact.phone])
365
364
 
366
365
  const saveAddresses = useCallback(async () => {
367
366
  const countryCode = (contact.countryCode || 'PE').toUpperCase()
@@ -388,13 +387,13 @@ export function useCheckoutSession(cartId: string) {
388
387
  }
389
388
 
390
389
  const updated = await serverApi.patchCartAddresses({
391
- cartId,
390
+ cartToken,
392
391
  shippingAddress: baseAddress,
393
392
  billingAddress: baseAddress,
394
393
  })
395
394
  setCheckoutCart(updated)
396
395
  return updated
397
- }, [cartId, contact])
396
+ }, [cartToken, contact])
398
397
 
399
398
  const saveContactAndDelivery = useCallback(async () => {
400
399
  await saveBuyer()
@@ -404,7 +403,7 @@ export function useCheckoutSession(cartId: string) {
404
403
  const confirmShipping = useCallback(
405
404
  async (picked: ShippingFlat) => {
406
405
  const updated = await serverApi.putCartShippingMethod({
407
- cartId,
406
+ cartToken,
408
407
  rateId: picked.rate.rateId,
409
408
  shippingMethodId: picked.rate.shippingMethodId,
410
409
  serviceCode: picked.rate.serviceCode ?? null,
@@ -418,7 +417,7 @@ export function useCheckoutSession(cartId: string) {
418
417
  setCheckoutCart(updated)
419
418
  return updated
420
419
  },
421
- [cartId],
420
+ [cartToken],
422
421
  )
423
422
 
424
423
  /** Persiste buyer + dirección + envío al completar el paso Dirección. */
@@ -459,46 +458,46 @@ export function useCheckoutSession(cartId: string) {
459
458
  if (!code) return
460
459
  setCouponError(null)
461
460
  try {
462
- const next = await serverApi.addCartPromotionCode({ cartId, code })
461
+ const next = await serverApi.addCartPromotionCode({ cartToken, code })
463
462
  setCheckoutCart(next)
464
463
  setCouponCode('')
465
464
  } catch (error) {
466
465
  setCouponError(error instanceof Error ? error.message : 'No se pudo aplicar el cupón.')
467
466
  }
468
- }, [cartId, couponCode])
467
+ }, [cartToken, couponCode])
469
468
 
470
469
  const handleRemoveCoupon = useCallback(
471
470
  async (code: string) => {
472
471
  setCouponError(null)
473
472
  try {
474
- const next = await serverApi.removeCartPromotionCode({ cartId, code })
473
+ const next = await serverApi.removeCartPromotionCode({ cartToken, code })
475
474
  setCheckoutCart(next)
476
475
  } catch (error) {
477
476
  setCouponError(error instanceof Error ? error.message : 'No se pudo remover el cupón.')
478
477
  }
479
478
  },
480
- [cartId],
479
+ [cartToken],
481
480
  )
482
481
 
483
482
  const handleAddOrderBump = useCallback(
484
483
  async (orderBump: StorefrontOrderBump) => {
485
484
  const next = await serverApi.addCartItem({
486
- cartId,
487
- variantId: cartVariantIdFromProduct(orderBump.variantPublicId),
485
+ cartToken,
486
+ variantId: orderBump.variantId,
488
487
  quantity: 1,
489
488
  })
490
489
  setCheckoutCart(next)
491
490
  await loadCheckout()
492
491
  await reloadProviderCart()
493
492
  },
494
- [cartId, loadCheckout, reloadProviderCart],
493
+ [cartToken, loadCheckout, reloadProviderCart],
495
494
  )
496
495
 
497
496
  const uploadPaymentReceipt = useCallback(
498
497
  async (file: File) => {
499
- return serverApi.uploadPaymentReceipt({ cartId, file, fileName: file.name })
498
+ return serverApi.uploadPaymentReceipt({ cartToken, file, fileName: file.name })
500
499
  },
501
- [cartId],
500
+ [cartToken],
502
501
  )
503
502
 
504
503
  const payNow = useCallback(
@@ -539,7 +538,7 @@ export function useCheckoutSession(cartId: string) {
539
538
  }
540
539
 
541
540
  const result = await serverApi.checkoutCart({
542
- cartId,
541
+ cartToken,
543
542
  paymentMethodCode: code,
544
543
  externalRef,
545
544
  ...(options?.receiptUrl ? { receiptUrl: options.receiptUrl } : {}),
@@ -557,7 +556,7 @@ export function useCheckoutSession(cartId: string) {
557
556
  }
558
557
  },
559
558
  [
560
- cartId,
559
+ cartToken,
561
560
  checkoutPaymentMethodCode,
562
561
  checkoutPaymentResponse,
563
562
  confirmShipping,
@@ -589,7 +588,7 @@ export function useCheckoutSession(cartId: string) {
589
588
  : subtotal
590
589
 
591
590
  return {
592
- cartId,
591
+ cartToken,
593
592
  loadStatus,
594
593
  loadError,
595
594
  cartData: checkoutCart,
package/src/config.mjs CHANGED
@@ -57,6 +57,7 @@ const configSchema = z.object({
57
57
  cloud: z
58
58
  .object({
59
59
  baseUrl: z.string().url().optional(),
60
+ artifactBaseUrl: z.string().url().optional(),
60
61
  storeSlug: z
61
62
  .string()
62
63
  .trim()
@@ -61,7 +61,7 @@ export function trackRecentlyViewed(
61
61
  }
62
62
 
63
63
  export type TrackableProduct = {
64
- id: string | number
64
+ id: string
65
65
  name: string
66
66
  slug: string
67
67
  imageUrl?: string | null
@@ -72,7 +72,7 @@ export type TrackableProduct = {
72
72
 
73
73
  export function toRecentlyViewedItem(product: TrackableProduct): RecentlyViewedItem {
74
74
  return {
75
- id: String(product.id),
75
+ id: product.id,
76
76
  name: product.name,
77
77
  slug: product.slug,
78
78
  imageUrl: product.imageUrl || product.images?.[0]?.url || '',
package/src/index.ts CHANGED
@@ -31,6 +31,7 @@ export {
31
31
  DepartmentsSchema,
32
32
  DistrictSchema,
33
33
  DistrictsSchema,
34
+ CartTokenSchema,
34
35
  EntityIdSchema,
35
36
  NullableEntityIdSchema,
36
37
  OptionalEntityIdSchema,
@@ -46,7 +47,7 @@ export {
46
47
  StorefrontMenuItemSchema,
47
48
  getMenuItems,
48
49
  } from '@ecomiq/core'
49
- export type { EntityId } from '@ecomiq/core'
50
+ export type { CartToken, EntityId } from '@ecomiq/core'
50
51
  export { getCountries, getDepartments, getDistricts, getProvinces } from '@ecomiq/core'
51
52
  export {
52
53
  AddCartItemParamsSchema,
@@ -75,7 +76,6 @@ export {
75
76
  CartAddressesParamsSchema,
76
77
  CartPromotionCodeParamsSchema,
77
78
  UpdateCartItemQuantityParamsSchema,
78
- cartVariantIdFromProduct,
79
79
  sanitizeHtml,
80
80
  stripHtml,
81
81
  } from '@ecomiq/core'
@@ -147,9 +147,7 @@ export type {
147
147
  CustomerProfile,
148
148
  CustomerProfilePatch,
149
149
  CustomerOrderDetail,
150
- CustomerOrderDetailDto,
151
150
  CustomerOrderListItem,
152
- CustomerOrderListItemDto,
153
151
  } from '@ecomiq/core'
154
152
  export {
155
153
  CustomerAddressSchema,
@@ -248,11 +246,6 @@ export {
248
246
  type HeroProps,
249
247
  type HeroSlide,
250
248
  } from './components/hero'
251
- export * from './storefront-definition'
252
- export {
253
- definitionForRoute,
254
- useDefinition,
255
- } from './storefront-layout'
256
249
  export { z } from 'zod'
257
250
 
258
251
  /**
@@ -56,5 +56,5 @@ function CheckoutPage({ params }: { params: { checkoutId: string } }) {
56
56
  )
57
57
  }
58
58
 
59
- return <CheckoutSessionView cartId={checkoutId} />
59
+ return <CheckoutSessionView cartToken={checkoutId} />
60
60
  }