@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.
- package/LICENSE +21 -0
- package/README.md +377 -76
- package/dist/account-Dx4e3syi.js +258 -0
- package/dist/account-forms-AVk71ko7.js +39 -0
- package/dist/account-forms.d.ts +13 -0
- package/dist/account.d.ts +240 -0
- package/dist/address-defaults-BqjRhS82.js +14 -0
- package/dist/address-defaults.d.ts +11 -0
- package/dist/analytics/analytics-CG1Qagwl.js +148 -0
- package/dist/analytics/analytics.d.ts +1 -0
- package/dist/analytics/config-DJr-GRhs.js +62 -0
- package/dist/analytics/config.d.ts +22 -0
- package/dist/analytics/consent-B13rBpBs.js +57 -0
- package/dist/analytics/consent-banner-9QvRRy8v.js +239 -0
- package/dist/analytics/consent-banner.d.ts +20 -0
- package/dist/analytics/cookies-pLozllyB.js +100 -0
- package/dist/analytics/cookies.d.ts +6 -0
- package/dist/analytics/destinations-iECrlLIr.js +144 -0
- package/dist/analytics/events-Dt81tIp1.js +102 -0
- package/dist/analytics/events.d.ts +51 -0
- package/dist/analytics/tracker-p4yaoOyk.js +51 -0
- package/dist/api-cache-DsuIn5hX.js +159 -0
- package/dist/bank-accounts-DlEczQQ5.js +81 -0
- package/dist/bank-accounts.d.ts +4 -0
- package/dist/captcha-DAqaIx8m.js +117 -0
- package/dist/captcha.d.ts +34 -0
- package/dist/cart-D7DxZ2lD.js +30 -0
- package/dist/cart-actions-Bsub_FFG.js +116 -0
- package/dist/cart-actions.d.ts +15 -0
- package/dist/cart-drawer-B7PPsR69.js +22 -0
- package/dist/cart-drawer.d.ts +9 -0
- package/dist/cart-form-y9P1r_EX.js +81 -0
- package/dist/cart-form.d.ts +24 -0
- package/dist/cart-summary-ur2VWKr-.js +89 -0
- package/dist/cart-summary.d.ts +31 -0
- package/dist/cart.d.ts +4 -0
- package/dist/catalog-7gJ-l5hW.js +67 -0
- package/dist/catalog-hooks-B7ZP4wYY.js +312 -0
- package/dist/catalog-hooks.d.ts +111 -0
- package/dist/catalog.d.ts +5 -0
- package/dist/checkout-DVWSXANi.js +474 -0
- package/dist/checkout-form-CbOIdENC.js +131 -0
- package/dist/checkout-form.d.ts +20 -0
- package/dist/checkout.d.ts +86 -0
- package/dist/complaint-book-BvwLvfx0.js +117 -0
- package/dist/complaint-book.d.ts +62 -0
- package/dist/culqi-authentication-BGr20vAJ.js +204 -0
- package/dist/culqi-authentication.d.ts +15 -0
- package/dist/culqi-checkout-CTXpKgp_.js +55 -0
- package/dist/culqi-three-ds-HP3mfrvV.js +33 -0
- package/dist/culqi-three-ds.d.ts +29 -0
- package/dist/customer-avatar-CJXSDroK.js +12 -0
- package/dist/customer-avatar.d.ts +5 -0
- package/dist/customer-cookies-DHOgFAMV.js +45 -0
- package/dist/customer-csrf-C1oDX-Py.js +17 -0
- package/dist/customer-csrf.d.ts +3 -0
- package/dist/customer-document-fields-C1K-_DAD.js +70 -0
- package/dist/customer-document-fields.d.ts +9 -0
- package/dist/customer-login-form-C7AC6vXd.js +144 -0
- package/dist/customer-login-form.d.ts +17 -0
- package/dist/customer-registration-form-BEm_NEfP.js +93 -0
- package/dist/customer-registration-form.d.ts +8 -0
- package/dist/document-url-CGsAl5Tf.js +9 -0
- package/dist/documents-T1mzc_j8.js +38 -0
- package/dist/documents.d.ts +16 -0
- package/dist/entries/account.d.ts +11 -0
- package/dist/entries/account.js +10 -0
- package/dist/entries/analytics.d.ts +6 -0
- package/dist/entries/analytics.js +5 -0
- package/dist/entries/cart.d.ts +8 -0
- package/dist/entries/cart.js +7 -0
- package/dist/entries/checkout.d.ts +12 -0
- package/dist/entries/checkout.js +11 -0
- package/dist/entries/order.d.ts +11 -0
- package/dist/entries/order.js +11 -0
- package/dist/favicon-YpyhVJ9H.js +28 -0
- package/dist/favicon.d.ts +4 -0
- package/dist/form-BtQcbXlJ.js +18 -0
- package/dist/form-contracts-BNpHaTGJ.js +166 -0
- package/dist/form-contracts.d.ts +42 -0
- package/dist/form.d.ts +3 -0
- package/dist/hidden-CCWtOWKR.js +3 -0
- package/dist/hidden.d.ts +4 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.js +50 -0
- package/dist/invoice-fields-BG0HjL6T.js +103 -0
- package/dist/invoice-fields.d.ts +39 -0
- package/dist/links-kFxBZfdb.js +96 -0
- package/dist/links.d.ts +21 -0
- package/dist/mercadopago-checkout-DC7RXa8k.js +27 -0
- package/dist/mercadopago-dialog-UTQev0MG.js +180 -0
- package/dist/mercadopago-dialog.d.ts +21 -0
- package/dist/money-DtGOtDri.js +32 -0
- package/dist/money.d.ts +1 -0
- package/dist/optimistic-cart-BveVOHuh.js +53 -0
- package/dist/optimistic-cart.d.ts +16 -0
- package/dist/order-display-DTt5WBbc.js +112 -0
- package/dist/order-display.d.ts +20 -0
- package/dist/order-draft-DxV1Uhm3.js +38 -0
- package/dist/order-draft.d.ts +16 -0
- package/dist/order-pages-Dm6l5m0m.js +38 -0
- package/dist/order-pages.d.ts +12 -0
- package/dist/order-payment-continuation-D_d5PGA4.js +212 -0
- package/dist/order-payment-continuation.d.ts +10 -0
- package/dist/order-payment-in-review-x4gdLFHZ.js +65 -0
- package/dist/order-payment-in-review.d.ts +5 -0
- package/dist/order-status-BJXLJwxq.js +162 -0
- package/dist/order-status.d.ts +89 -0
- package/dist/order-view-9IlBg5AF.js +62 -0
- package/dist/order-view.d.ts +12 -0
- package/dist/page-action-Ctkf4xC6.js +7 -0
- package/dist/page-seo-a5FJl8x5.js +262 -0
- package/dist/page-seo.d.ts +34 -0
- package/dist/pages-Ca_Gt6mq.js +150 -0
- package/dist/pages.d.ts +45 -0
- package/dist/payment-dialog-frame-B-Q_xQ94.js +57 -0
- package/dist/payment-logo-BoPaGJc_.js +46 -0
- package/dist/payment-logo-svgs-By9lDTLK.js +20 -0
- package/dist/payment-logo.d.ts +11 -0
- package/dist/payment-logos-BYvdwYyJ.js +23 -0
- package/dist/payment-methods-B8ocTgFZ.js +73 -0
- package/dist/payment-methods.d.ts +58 -0
- package/dist/payment-return-5cjypwIw.js +7 -0
- package/dist/place-CmW4hBWY.js +13 -0
- package/dist/place.d.ts +4 -0
- package/dist/preview-BiIBif3C.js +427 -0
- package/dist/preview-address-Cf0sJ-9p.js +21 -0
- package/dist/preview-cart-Dg2CVktS.js +376 -0
- package/dist/product-preview-BspMAecJ.js +51 -0
- package/dist/product-preview.d.ts +5 -0
- package/dist/product-variants-BNDHvs1y.js +46 -0
- package/dist/product-variants.d.ts +12 -0
- package/dist/public-pages-XtwlaLwt.js +194 -0
- package/dist/public-pages.d.ts +67 -0
- package/dist/registration-CpDcv8ql.js +91 -0
- package/dist/registration.d.ts +12 -0
- package/dist/request-security-CRsRMgwj.js +76 -0
- package/dist/rich-text-M-Ju8RL4.js +9 -0
- package/dist/rich-text.d.ts +5 -0
- package/dist/route-text-DcJw2SsK.js +9 -0
- package/dist/route-text.d.ts +4 -0
- package/dist/section-preview-CmsMl3yu.js +83 -0
- package/dist/section-preview.d.ts +12 -0
- package/dist/sections/account-addresses.d.ts +18 -0
- package/dist/sections/account-addresses.js +375 -0
- package/dist/sections/account-order.d.ts +12 -0
- package/dist/sections/account-order.js +592 -0
- package/dist/sections/account-orders.d.ts +8 -0
- package/dist/sections/account-orders.js +359 -0
- package/dist/sections/account-profile.d.ts +16 -0
- package/dist/sections/account-profile.js +123 -0
- package/dist/sections/checkout.d.ts +24 -0
- package/dist/sections/checkout.js +963 -0
- package/dist/sections/complaint-book.d.ts +8 -0
- package/dist/sections/complaint-book.js +538 -0
- package/dist/sections/design-system.d.ts +1 -0
- package/dist/sections/design-system.js +310 -0
- package/dist/sections/draft-invoice.d.ts +20 -0
- package/dist/sections/draft-invoice.js +158 -0
- package/dist/sections/order-tracking.d.ts +19 -0
- package/dist/sections/order-tracking.js +141 -0
- package/dist/sections-CNUMWTF_.js +77 -0
- package/dist/sections.d.ts +19 -0
- package/dist/seo-GpDRhAAA.js +78 -0
- package/dist/session-CKvmFJyg.js +379 -0
- package/dist/session.d.ts +24 -0
- package/dist/settings-B0NO2A6Y.js +78 -0
- package/dist/settings.d.ts +51 -0
- package/dist/source-marker-DhqSkW7n.js +4 -0
- package/dist/sources-B-3JFJfb.js +46 -0
- package/dist/sources.d.ts +7 -0
- package/dist/store-8Q-_LFrQ.js +152 -0
- package/dist/store-contact--hY6CoFb.js +19 -0
- package/dist/store-contact.d.ts +6 -0
- package/dist/store.d.ts +17 -0
- package/dist/storefront-language-DrMjVbmk.js +29 -0
- package/dist/storefront-language.d.ts +14 -0
- package/dist/storefront-text-D25ae1qf.js +11 -0
- package/dist/storefront-text-en-ljjjSS4q.js +1030 -0
- package/dist/storefront-text-pt-BtHaJLcp.js +1030 -0
- package/dist/storefront-text.d.ts +4 -0
- package/dist/stripe-dialog-Ev9s3Z62.js +396 -0
- package/dist/stripe-dialog.d.ts +30 -0
- package/dist/telemetry-HuZXWBPi.js +114 -0
- package/dist/telemetry.d.ts +10 -0
- package/dist/templates-CAqoNyTW.js +40 -0
- package/dist/templates.d.ts +15 -0
- package/dist/urls-CpGQPxvf.js +71 -0
- package/dist/urls.d.ts +18 -0
- package/dist/use-checkout-CZcxXJXi.js +42 -0
- package/dist/use-checkout-payment-9R-zacrJ.js +80 -0
- package/dist/use-checkout-payment.d.ts +18 -0
- package/dist/use-checkout.d.ts +36 -0
- package/dist/use-culqi-checkout-CrjLAipU.js +109 -0
- package/dist/use-order-payment-BKIz_IO0.js +45 -0
- package/dist/use-order-payment.d.ts +18 -0
- package/dist/use-payment-token-CErx-tN-.js +105 -0
- package/dist/vite-payment-logos-kziu7wKb.js +27 -0
- package/dist/vite-payment-logos.d.ts +24 -0
- package/dist/vite-public-assets-DW2fgtVb.js +209 -0
- package/dist/vite-public-assets.d.ts +29 -0
- package/dist/vite-sections-DTBr0-Kg.js +464 -0
- package/dist/vite-sections.d.ts +21 -0
- package/dist/vite-theme-ui-BMO-CDi3.js +41 -0
- package/dist/vite-theme-ui.d.ts +10 -0
- package/dist/vite.d.ts +36 -0
- package/dist/vite.js +127 -0
- package/dist/voucher-payment-CVFDZ1L8.js +66 -0
- package/dist/worker-CNi-gzCu.js +86 -0
- package/dist/worker.d.ts +27 -0
- package/package.json +100 -76
- package/src/sections/account-addresses.tsx +215 -0
- package/src/sections/account-order.tsx +424 -0
- package/src/sections/account-orders.tsx +259 -0
- package/src/sections/account-profile.tsx +70 -0
- package/src/sections/checkout.tsx +586 -0
- package/src/sections/complaint-book.tsx +325 -0
- package/src/sections/design-system.tsx +146 -0
- package/src/sections/draft-invoice.tsx +105 -0
- package/src/sections/order-tracking.tsx +81 -0
- package/src/vite-client.d.ts +4 -0
- package/bin/ecomiq.mjs +0 -179
- package/public/design-bridge.js +0 -318
- package/src/api-proxy.ts +0 -194
- package/src/auth/create-storefront-auth.ts +0 -94
- package/src/auth/ecomiq-oauth-password-client.ts +0 -26
- package/src/auth/ecomiq-oauth-password-constants.ts +0 -24
- package/src/auth/ecomiq-oauth-password-plugin.ts +0 -294
- package/src/auth/ecomiq-oauth-password-types.ts +0 -24
- package/src/auth/ecomiq-storefront-sign-in.ts +0 -44
- package/src/auth/env.ts +0 -7
- package/src/auth/secure-cookies.ts +0 -23
- package/src/auth/storefront-auth-base-url.ts +0 -117
- package/src/auth/storefront-auth.ts +0 -7
- package/src/cart-session.ts +0 -239
- package/src/client.ts +0 -48
- package/src/codegen.mjs +0 -801
- package/src/components/account/customer-addresses-panel.tsx +0 -678
- package/src/components/account/customer-order-detail-panel.tsx +0 -285
- package/src/components/account/customer-orders-panel.tsx +0 -192
- package/src/components/account/customer-profile-panel.tsx +0 -379
- package/src/components/checkout/cart-sync.ts +0 -143
- package/src/components/checkout/checkout-contact-section.tsx +0 -76
- package/src/components/checkout/checkout-external-update-banner.tsx +0 -15
- package/src/components/checkout/checkout-form-controls.tsx +0 -139
- package/src/components/checkout/checkout-line-items.tsx +0 -43
- package/src/components/checkout/checkout-order-summary.tsx +0 -165
- package/src/components/checkout/checkout-payment-section.tsx +0 -212
- package/src/components/checkout/checkout-session-view.tsx +0 -564
- package/src/components/checkout/checkout-shipping-address-section.tsx +0 -400
- package/src/components/checkout/checkout-shipping-section.tsx +0 -98
- package/src/components/checkout/checkout-states.tsx +0 -73
- package/src/components/checkout/checkout-step-card.tsx +0 -101
- package/src/components/checkout/checkout-steps.ts +0 -111
- package/src/components/checkout/form-schema.ts +0 -281
- package/src/components/checkout/format.ts +0 -15
- package/src/components/checkout/index.ts +0 -5
- package/src/components/checkout/map-customer-to-checkout.ts +0 -188
- package/src/components/checkout/types.ts +0 -41
- package/src/components/checkout/use-checkout-customer-prefill.ts +0 -409
- package/src/components/checkout/use-checkout-geo.ts +0 -50
- package/src/components/checkout/use-checkout-session.ts +0 -640
- package/src/components/hero.tsx +0 -291
- package/src/config.d.ts +0 -94
- package/src/config.mjs +0 -146
- package/src/format-money.ts +0 -31
- package/src/health.ts +0 -90
- package/src/hooks/index.ts +0 -9
- package/src/hooks/recently-viewed.ts +0 -125
- package/src/index.ts +0 -349
- package/src/link.tsx +0 -2
- package/src/pages/account/account-page-skeleton.tsx +0 -69
- package/src/pages/account/account-page-view.tsx +0 -270
- package/src/pages/account/account-shell.tsx +0 -101
- package/src/pages/account/parse-account-route.ts +0 -36
- package/src/pages/account.tsx +0 -16
- package/src/pages/api.$.ts +0 -20
- package/src/pages/api.auth.$.ts +0 -16
- package/src/pages/checkout.$checkoutId.tsx +0 -60
- package/src/pages/checkout.tsx +0 -31
- package/src/pages/pages.$pageSlug.tsx +0 -74
- package/src/pages/thank-you.tsx +0 -53
- package/src/providers/auth.tsx +0 -96
- package/src/providers/cart.tsx +0 -275
- package/src/providers/ecomiq.ts +0 -137
- package/src/providers/index.ts +0 -26
- package/src/proxy-api.ts +0 -20
- package/src/public-config.ts +0 -24
- package/src/review-submission.ts +0 -89
- package/src/runtime/context.ts +0 -2
- package/src/runtime/default-layout.tsx +0 -64
- package/src/runtime/head.ts +0 -149
- package/src/runtime/page.tsx +0 -143
- package/src/runtime/postcss-browser-stub.mjs +0 -5
- package/src/server-config-store.ts +0 -35
- package/src/server.ts +0 -286
- package/src/styles.css +0 -76
- package/src/ui/badge.tsx +0 -32
- package/src/ui/button.tsx +0 -31
- package/src/ui/card.tsx +0 -31
- package/src/ui/carousel.tsx +0 -218
- package/src/ui/cn.ts +0 -6
- package/src/ui/index.ts +0 -8
- package/src/ui/separator.tsx +0 -6
- package/src/ui/skeleton.tsx +0 -6
- package/src/ui/storefront-error.tsx +0 -49
- package/src/utils.ts +0 -36
- package/src/vite-inline.mjs +0 -263
- package/templates/__root.tsx +0 -83
- package/templates/router.tsx +0 -19
package/src/providers/auth.tsx
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Auth storefront: Better Auth client + sesión via context.
|
|
3
|
-
*
|
|
4
|
-
* El framework monta `<AuthProvider>` en `__root` (cliente por defecto).
|
|
5
|
-
* Puedes pasar un `client` propio si necesitas opciones custom.
|
|
6
|
-
*
|
|
7
|
-
* ```tsx
|
|
8
|
-
* const { session, signIn, signOut } = useAuth()
|
|
9
|
-
* ```
|
|
10
|
-
*/
|
|
11
|
-
import { createContext, useContext, type ReactNode } from 'react'
|
|
12
|
-
import { createAuthClient } from 'better-auth/react'
|
|
13
|
-
import { ecomiqOAuthPasswordClient } from '../auth/ecomiq-oauth-password-client'
|
|
14
|
-
import {
|
|
15
|
-
signInWithEcomiqCredentials,
|
|
16
|
-
type EcomiqSignInCredentials,
|
|
17
|
-
} from '../auth/ecomiq-storefront-sign-in'
|
|
18
|
-
import { AppEcomiqContext } from './ecomiq'
|
|
19
|
-
|
|
20
|
-
export type CreateStorefrontAuthClientOptions = {
|
|
21
|
-
baseURL?: string
|
|
22
|
-
basePath?: string
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function createStorefrontAuthClient(
|
|
26
|
-
options: CreateStorefrontAuthClientOptions = {},
|
|
27
|
-
) {
|
|
28
|
-
return createAuthClient({
|
|
29
|
-
...options,
|
|
30
|
-
plugins: [ecomiqOAuthPasswordClient()],
|
|
31
|
-
})
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export type StorefrontAuthClientInstance = ReturnType<typeof createStorefrontAuthClient>
|
|
35
|
-
/** Sesión tipada de Better Auth (`{ user, session }`). */
|
|
36
|
-
export type StorefrontSession = StorefrontAuthClientInstance['$Infer']['Session']
|
|
37
|
-
|
|
38
|
-
const AuthContext = createContext<StorefrontAuthClientInstance | null>(null)
|
|
39
|
-
|
|
40
|
-
/** Cliente por defecto del framework (una instancia por bundle). */
|
|
41
|
-
let defaultAuthClient: StorefrontAuthClientInstance | null = null
|
|
42
|
-
|
|
43
|
-
function getDefaultAuthClient(): StorefrontAuthClientInstance {
|
|
44
|
-
if (!defaultAuthClient) {
|
|
45
|
-
defaultAuthClient = createStorefrontAuthClient()
|
|
46
|
-
}
|
|
47
|
-
return defaultAuthClient
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function AuthProvider({
|
|
51
|
-
client,
|
|
52
|
-
children,
|
|
53
|
-
}: {
|
|
54
|
-
/** Si se omite, usa el cliente por defecto del storefront. */
|
|
55
|
-
client?: StorefrontAuthClientInstance
|
|
56
|
-
children: ReactNode
|
|
57
|
-
}) {
|
|
58
|
-
return (
|
|
59
|
-
<AuthContext.Provider value={client ?? getDefaultAuthClient()}>
|
|
60
|
-
{children}
|
|
61
|
-
</AuthContext.Provider>
|
|
62
|
-
)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** Acceso a sesión y acciones de auth. Requiere `<AuthProvider>` + `<AppEcomiqProvider>`. */
|
|
66
|
-
export function useAuth() {
|
|
67
|
-
const client = useContext(AuthContext)
|
|
68
|
-
if (!client) throw new Error('useAuth debe usarse dentro de AuthProvider')
|
|
69
|
-
|
|
70
|
-
const sessionQuery = client.useSession()
|
|
71
|
-
// Mismo módulo que AppEcomiqProvider (no useSettings del barrel) + soft read
|
|
72
|
-
// para no tumbar el árbol si hay re-render concurrente post-sesión.
|
|
73
|
-
const ecomiq = useContext(AppEcomiqContext)
|
|
74
|
-
|
|
75
|
-
return {
|
|
76
|
-
client,
|
|
77
|
-
session: sessionQuery.data,
|
|
78
|
-
isPending: sessionQuery.isPending,
|
|
79
|
-
error: sessionQuery.error,
|
|
80
|
-
signIn: async (credentials: EcomiqSignInCredentials) => {
|
|
81
|
-
if (!ecomiq) {
|
|
82
|
-
throw new Error('signIn requiere AppEcomiqProvider')
|
|
83
|
-
}
|
|
84
|
-
await signInWithEcomiqCredentials(client, ecomiq.settings, credentials)
|
|
85
|
-
const result = await client.getSession()
|
|
86
|
-
const session = (result as { data?: StorefrontSession | null })?.data ?? null
|
|
87
|
-
if (!session?.user) {
|
|
88
|
-
throw new Error(
|
|
89
|
-
'No se pudo establecer la sesión. Revisa cookies / certificado HTTPS e inténtalo de nuevo.',
|
|
90
|
-
)
|
|
91
|
-
}
|
|
92
|
-
return session
|
|
93
|
-
},
|
|
94
|
-
signOut: () => client.signOut(),
|
|
95
|
-
}
|
|
96
|
-
}
|
package/src/providers/cart.tsx
DELETED
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Estado de carrito storefront: sesión en localStorage + mutaciones vía serverApi.
|
|
3
|
-
*
|
|
4
|
-
* ```tsx
|
|
5
|
-
* <CartProvider storeId={settings.store.id} currencyCode={settings.store.currency}>
|
|
6
|
-
* <App />
|
|
7
|
-
* </CartProvider>
|
|
8
|
-
*
|
|
9
|
-
* const { cart, addItem } = useCart()
|
|
10
|
-
* ```
|
|
11
|
-
*/
|
|
12
|
-
import {
|
|
13
|
-
createContext,
|
|
14
|
-
useContext,
|
|
15
|
-
useEffect,
|
|
16
|
-
useRef,
|
|
17
|
-
useState,
|
|
18
|
-
type ReactNode,
|
|
19
|
-
} from 'react'
|
|
20
|
-
import { CartTokenSchema, type StorefrontCart } from '@ecomiq/core'
|
|
21
|
-
import { z } from 'zod'
|
|
22
|
-
import { serverApi } from '../server'
|
|
23
|
-
|
|
24
|
-
const CartSessionSchema = z.object({
|
|
25
|
-
version: z.literal(1),
|
|
26
|
-
storeId: z.string().min(1),
|
|
27
|
-
cartToken: CartTokenSchema,
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
export type CartLoadStatus = 'loading' | 'ready' | 'error'
|
|
31
|
-
|
|
32
|
-
export type CartMutation = {
|
|
33
|
-
kind: 'adding' | 'updating' | 'removing'
|
|
34
|
-
itemId?: string
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface CartContextValue {
|
|
38
|
-
cart: StorefrontCart | null
|
|
39
|
-
cartToken: string | undefined
|
|
40
|
-
itemCount: number
|
|
41
|
-
loadStatus: CartLoadStatus
|
|
42
|
-
mutation: CartMutation | null
|
|
43
|
-
error: string | undefined
|
|
44
|
-
addItem: (input: { variantId: string; quantity: number }) => Promise<StorefrontCart>
|
|
45
|
-
setItemQuantity: (itemId: string, quantity: number) => Promise<void>
|
|
46
|
-
removeItem: (itemId: string) => Promise<void>
|
|
47
|
-
reload: () => Promise<void>
|
|
48
|
-
clearCart: () => void
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const CartContext = createContext<CartContextValue | null>(null)
|
|
52
|
-
|
|
53
|
-
function sessionKey(storeId: string) {
|
|
54
|
-
return `ecomiq:cart:v1:${storeId}`
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function readCartSession(key: string) {
|
|
58
|
-
if (typeof localStorage === 'undefined') return undefined
|
|
59
|
-
const raw = localStorage.getItem(key)
|
|
60
|
-
if (!raw) return undefined
|
|
61
|
-
try {
|
|
62
|
-
const result = CartSessionSchema.safeParse(JSON.parse(raw))
|
|
63
|
-
return result.success ? result.data : undefined
|
|
64
|
-
} catch {
|
|
65
|
-
return undefined
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export function CartProvider({
|
|
70
|
-
storeId,
|
|
71
|
-
currencyCode,
|
|
72
|
-
children,
|
|
73
|
-
}: {
|
|
74
|
-
storeId: string
|
|
75
|
-
currencyCode: string
|
|
76
|
-
children: ReactNode
|
|
77
|
-
}) {
|
|
78
|
-
const key = sessionKey(storeId)
|
|
79
|
-
const [cart, setCart] = useState<StorefrontCart | null>(null)
|
|
80
|
-
const [cartToken, setCartToken] = useState<string>()
|
|
81
|
-
const [loadStatus, setLoadStatus] = useState<CartLoadStatus>('loading')
|
|
82
|
-
const [mutation, setMutation] = useState<CartMutation | null>(null)
|
|
83
|
-
const [error, setError] = useState<string>()
|
|
84
|
-
const mutationInFlight = useRef(false)
|
|
85
|
-
|
|
86
|
-
const persist = (nextCartToken: string) => {
|
|
87
|
-
setCartToken(nextCartToken)
|
|
88
|
-
localStorage.setItem(key, JSON.stringify({ version: 1, storeId, cartToken: nextCartToken }))
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const clear = () => {
|
|
92
|
-
setCart(null)
|
|
93
|
-
setCartToken(undefined)
|
|
94
|
-
localStorage.removeItem(key)
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const reload = async () => {
|
|
98
|
-
setLoadStatus('loading')
|
|
99
|
-
setError(undefined)
|
|
100
|
-
const stored = readCartSession(key)
|
|
101
|
-
if (!stored || stored.storeId !== storeId) {
|
|
102
|
-
clear()
|
|
103
|
-
setLoadStatus('ready')
|
|
104
|
-
return
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
setCartToken(stored.cartToken)
|
|
108
|
-
try {
|
|
109
|
-
const result = await serverApi.loadCart({ cartToken: stored.cartToken })
|
|
110
|
-
if (!result.ok) {
|
|
111
|
-
setError(result.error.message)
|
|
112
|
-
setLoadStatus('error')
|
|
113
|
-
return
|
|
114
|
-
}
|
|
115
|
-
if (!result.value) {
|
|
116
|
-
clear()
|
|
117
|
-
} else {
|
|
118
|
-
setCart(result.value)
|
|
119
|
-
}
|
|
120
|
-
setLoadStatus('ready')
|
|
121
|
-
} catch {
|
|
122
|
-
setError('No pudimos cargar el carrito. Inténtalo nuevamente.')
|
|
123
|
-
setLoadStatus('error')
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
useEffect(() => {
|
|
128
|
-
void reload()
|
|
129
|
-
const sync = (event: StorageEvent) => {
|
|
130
|
-
if (event.key === key) void reload()
|
|
131
|
-
}
|
|
132
|
-
window.addEventListener('storage', sync)
|
|
133
|
-
return () => window.removeEventListener('storage', sync)
|
|
134
|
-
}, [key])
|
|
135
|
-
|
|
136
|
-
const addItem = async (input: { variantId: string; quantity: number }) => {
|
|
137
|
-
if (mutationInFlight.current) {
|
|
138
|
-
const message = 'El carrito se está actualizando. Inténtalo nuevamente.'
|
|
139
|
-
setError(message)
|
|
140
|
-
throw new Error(message)
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
mutationInFlight.current = true
|
|
144
|
-
setMutation({ kind: 'adding' })
|
|
145
|
-
setError(undefined)
|
|
146
|
-
try {
|
|
147
|
-
let result
|
|
148
|
-
try {
|
|
149
|
-
result = await serverApi.addProductToCart({
|
|
150
|
-
cartToken,
|
|
151
|
-
currencyCode,
|
|
152
|
-
variantId: input.variantId,
|
|
153
|
-
quantity: input.quantity,
|
|
154
|
-
})
|
|
155
|
-
} catch {
|
|
156
|
-
const message = 'No pudimos actualizar el carrito. Inténtalo nuevamente.'
|
|
157
|
-
setError(message)
|
|
158
|
-
throw new Error(message)
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (!result.ok) {
|
|
162
|
-
setError(result.error.message)
|
|
163
|
-
throw new Error(result.error.message)
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
setError(undefined)
|
|
167
|
-
persist(result.value.cartToken)
|
|
168
|
-
setCart(result.value.cart)
|
|
169
|
-
return result.value.cart
|
|
170
|
-
} finally {
|
|
171
|
-
mutationInFlight.current = false
|
|
172
|
-
setMutation(null)
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const setItemQuantity = async (itemId: string, quantity: number) => {
|
|
177
|
-
if (!cartToken) {
|
|
178
|
-
setError('No hay un carrito activo.')
|
|
179
|
-
return
|
|
180
|
-
}
|
|
181
|
-
if (mutationInFlight.current) {
|
|
182
|
-
setError('El carrito se está actualizando. Inténtalo nuevamente.')
|
|
183
|
-
return
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
mutationInFlight.current = true
|
|
187
|
-
setMutation({ kind: 'updating', itemId })
|
|
188
|
-
setError(undefined)
|
|
189
|
-
try {
|
|
190
|
-
let result
|
|
191
|
-
try {
|
|
192
|
-
result = await serverApi.setCartItemQuantity({
|
|
193
|
-
cartToken,
|
|
194
|
-
cartItemId: itemId,
|
|
195
|
-
quantity,
|
|
196
|
-
})
|
|
197
|
-
} catch {
|
|
198
|
-
setError('No pudimos actualizar el carrito. Inténtalo nuevamente.')
|
|
199
|
-
return
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
if (!result.ok) {
|
|
203
|
-
if (result.error.kind === 'cart-unavailable') clear()
|
|
204
|
-
setError(result.error.message)
|
|
205
|
-
return
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
setCart(result.value)
|
|
209
|
-
} finally {
|
|
210
|
-
mutationInFlight.current = false
|
|
211
|
-
setMutation(null)
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
const removeItem = async (itemId: string) => {
|
|
216
|
-
if (!cartToken) {
|
|
217
|
-
setError('No hay un carrito activo.')
|
|
218
|
-
return
|
|
219
|
-
}
|
|
220
|
-
if (mutationInFlight.current) {
|
|
221
|
-
setError('El carrito se está actualizando. Inténtalo nuevamente.')
|
|
222
|
-
return
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
mutationInFlight.current = true
|
|
226
|
-
setMutation({ kind: 'removing', itemId })
|
|
227
|
-
setError(undefined)
|
|
228
|
-
try {
|
|
229
|
-
let result
|
|
230
|
-
try {
|
|
231
|
-
result = await serverApi.removeCartItem({
|
|
232
|
-
cartToken,
|
|
233
|
-
cartItemId: itemId,
|
|
234
|
-
})
|
|
235
|
-
} catch {
|
|
236
|
-
setError('No pudimos actualizar el carrito. Inténtalo nuevamente.')
|
|
237
|
-
return
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
if (!result.ok) {
|
|
241
|
-
if (result.error.kind === 'cart-unavailable') clear()
|
|
242
|
-
setError(result.error.message)
|
|
243
|
-
return
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
setCart(result.value)
|
|
247
|
-
} finally {
|
|
248
|
-
mutationInFlight.current = false
|
|
249
|
-
setMutation(null)
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
const value: CartContextValue = {
|
|
254
|
-
cart,
|
|
255
|
-
cartToken,
|
|
256
|
-
itemCount: cart?.items.reduce((sum, item) => sum + item.quantity, 0) ?? 0,
|
|
257
|
-
loadStatus,
|
|
258
|
-
mutation,
|
|
259
|
-
error,
|
|
260
|
-
addItem,
|
|
261
|
-
setItemQuantity,
|
|
262
|
-
removeItem,
|
|
263
|
-
reload,
|
|
264
|
-
clearCart: clear,
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
return <CartContext.Provider value={value}>{children}</CartContext.Provider>
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
/** Acceso al carrito. Requiere `<CartProvider>` en el layout. */
|
|
271
|
-
export function useCart() {
|
|
272
|
-
const value = useContext(CartContext)
|
|
273
|
-
if (!value) throw new Error('useCart debe usarse dentro de CartProvider')
|
|
274
|
-
return value
|
|
275
|
-
}
|
package/src/providers/ecomiq.ts
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Provider + hooks públicos de Ecomiq (settings, config, queries).
|
|
3
|
-
*/
|
|
4
|
-
import {
|
|
5
|
-
createContext,
|
|
6
|
-
createElement,
|
|
7
|
-
useContext,
|
|
8
|
-
type ReactNode,
|
|
9
|
-
} from 'react'
|
|
10
|
-
import { hashKey, keepPreviousData, useQuery } from '@tanstack/react-query'
|
|
11
|
-
import { useNavigate } from '@tanstack/react-router'
|
|
12
|
-
import {
|
|
13
|
-
getMenuItems,
|
|
14
|
-
type StorefrontMenuItem,
|
|
15
|
-
type StorefrontSettings,
|
|
16
|
-
} from '@ecomiq/core'
|
|
17
|
-
import type { PublicEcomiqConfig } from '../public-config'
|
|
18
|
-
|
|
19
|
-
export interface ApiQueryOptions<T> {
|
|
20
|
-
/** Datos iniciales (ej. los del loader SSR) para render inmediato. */
|
|
21
|
-
initialData?: T
|
|
22
|
-
/** Tiempo en ms que los datos se consideran frescos. Default 30s. */
|
|
23
|
-
freshForMs?: number
|
|
24
|
-
/** Habilita/deshabilita la consulta. */
|
|
25
|
-
enabled?: boolean
|
|
26
|
-
/** Reintentos ante error. Default 1. */
|
|
27
|
-
retry?: number
|
|
28
|
-
keepPreviousData?: boolean
|
|
29
|
-
seed?: { key: readonly unknown[]; data: T }
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export interface ApiQueryResult<T> {
|
|
33
|
-
data: T | undefined
|
|
34
|
-
isLoading: boolean
|
|
35
|
-
isRefreshing: boolean
|
|
36
|
-
error: Error | null
|
|
37
|
-
refresh: () => void
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Consulta datos en el cliente con caché y deduplicación automáticas.
|
|
42
|
-
*
|
|
43
|
-
* ```ts
|
|
44
|
-
* const { data, isLoading } = useApiQuery(['products'], () => api.get('/products', schema))
|
|
45
|
-
* ```
|
|
46
|
-
*/
|
|
47
|
-
export function useApiQuery<T>(
|
|
48
|
-
key: readonly unknown[],
|
|
49
|
-
fetcher: (context: { signal: AbortSignal }) => Promise<T>,
|
|
50
|
-
options: ApiQueryOptions<T> = {},
|
|
51
|
-
): ApiQueryResult<T> {
|
|
52
|
-
let initialData = options.initialData
|
|
53
|
-
if (options.seed && hashKey(options.seed.key) === hashKey(key)) {
|
|
54
|
-
initialData = options.seed.data
|
|
55
|
-
}
|
|
56
|
-
const query = useQuery({
|
|
57
|
-
queryKey: key,
|
|
58
|
-
queryFn: ({ signal }) => fetcher({ signal }),
|
|
59
|
-
initialData,
|
|
60
|
-
placeholderData: options.keepPreviousData ? keepPreviousData : undefined,
|
|
61
|
-
staleTime: options.freshForMs ?? 30_000,
|
|
62
|
-
enabled: options.enabled,
|
|
63
|
-
retry: options.retry ?? 1,
|
|
64
|
-
})
|
|
65
|
-
return {
|
|
66
|
-
data: query.data,
|
|
67
|
-
isLoading: query.isPending,
|
|
68
|
-
isRefreshing: query.isFetching && !query.isPending,
|
|
69
|
-
error: query.error,
|
|
70
|
-
refresh: () => void query.refetch(),
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/** Valor único del shell: config local + settings storefront. */
|
|
75
|
-
export interface AppEcomiqValue {
|
|
76
|
-
config: PublicEcomiqConfig
|
|
77
|
-
settings: StorefrontSettings
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/** Contexto único de la app Ecomiq (lo provee el root generado). */
|
|
81
|
-
export const AppEcomiqContext = createContext<AppEcomiqValue | null>(null)
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Provider del shell storefront (config + settings).
|
|
85
|
-
*
|
|
86
|
-
* ```tsx
|
|
87
|
-
* <AppEcomiqProvider config={publicConfig} settings={settings}>
|
|
88
|
-
* <App />
|
|
89
|
-
* </AppEcomiqProvider>
|
|
90
|
-
* ```
|
|
91
|
-
*/
|
|
92
|
-
export function AppEcomiqProvider({
|
|
93
|
-
config,
|
|
94
|
-
settings,
|
|
95
|
-
children,
|
|
96
|
-
}: AppEcomiqValue & { children: ReactNode }) {
|
|
97
|
-
return createElement(
|
|
98
|
-
AppEcomiqContext.Provider,
|
|
99
|
-
{ value: { config, settings } },
|
|
100
|
-
children,
|
|
101
|
-
)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function useAppEcomiq(): AppEcomiqValue {
|
|
105
|
-
const value = useContext(AppEcomiqContext)
|
|
106
|
-
if (!value) {
|
|
107
|
-
throw new Error('Hooks de Ecomiq deben usarse dentro de AppEcomiqProvider')
|
|
108
|
-
}
|
|
109
|
-
return value
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/** Acceso al ecomiq.config.js resuelto. */
|
|
113
|
-
export function useAppConfig(): PublicEcomiqConfig {
|
|
114
|
-
return useAppEcomiq().config
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/** Acceso a /v1/settings (CMS, store, menus). */
|
|
118
|
-
export function useSettings(): StorefrontSettings {
|
|
119
|
-
return useAppEcomiq().settings
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/** Items de un menú CMS (`main`, `footer`, `account`, …). */
|
|
123
|
-
export function useMenu(key: string): StorefrontMenuItem[] {
|
|
124
|
-
return getMenuItems(useSettings(), key)
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Navegación cliente a una ruta con query params (sin full page reload).
|
|
129
|
-
*
|
|
130
|
-
* ```ts
|
|
131
|
-
* const go = useSearchNavigate()
|
|
132
|
-
* go('/products', { sort: 'price_asc', page: 1 })
|
|
133
|
-
* ```
|
|
134
|
-
*/
|
|
135
|
-
export function useSearchNavigate() {
|
|
136
|
-
return useNavigate()
|
|
137
|
-
}
|
package/src/providers/index.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
export {
|
|
2
|
-
AppEcomiqContext,
|
|
3
|
-
AppEcomiqProvider,
|
|
4
|
-
useApiQuery,
|
|
5
|
-
useAppConfig,
|
|
6
|
-
useSettings,
|
|
7
|
-
useMenu,
|
|
8
|
-
useSearchNavigate,
|
|
9
|
-
type AppEcomiqValue,
|
|
10
|
-
type ApiQueryOptions,
|
|
11
|
-
type ApiQueryResult,
|
|
12
|
-
} from './ecomiq'
|
|
13
|
-
export {
|
|
14
|
-
CartProvider,
|
|
15
|
-
useCart,
|
|
16
|
-
type CartContextValue,
|
|
17
|
-
type CartLoadStatus,
|
|
18
|
-
type CartMutation,
|
|
19
|
-
} from './cart'
|
|
20
|
-
export {
|
|
21
|
-
AuthProvider,
|
|
22
|
-
createStorefrontAuthClient,
|
|
23
|
-
useAuth,
|
|
24
|
-
type StorefrontAuthClientInstance,
|
|
25
|
-
type StorefrontSession,
|
|
26
|
-
} from './auth'
|
package/src/proxy-api.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { createApi, type Api } from '@ecomiq/core'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Cliente HTTP hacia el BFF same-origin (`/api/*`).
|
|
5
|
-
* El proxy inyecta `x-Store-Id` y el Bearer desde la cookie OAuth
|
|
6
|
-
* (`ecomiq_sf_oauth_at`, path `/api`).
|
|
7
|
-
*
|
|
8
|
-
* Usar con los services de `@ecomiq/core` (p. ej. `getCustomerAddresses(api)`).
|
|
9
|
-
* `version` vacío: el path del proxy ya es `/api/...` (el upstream añade `/v1`).
|
|
10
|
-
*/
|
|
11
|
-
export function createStorefrontProxyApi(): Api {
|
|
12
|
-
const origin =
|
|
13
|
-
typeof window !== 'undefined' && window.location?.origin
|
|
14
|
-
? window.location.origin
|
|
15
|
-
: 'http://localhost'
|
|
16
|
-
return createApi({
|
|
17
|
-
baseUrl: `${origin}/api`,
|
|
18
|
-
version: '',
|
|
19
|
-
})
|
|
20
|
-
}
|
package/src/public-config.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export interface EcomiqThemeConfig {
|
|
2
|
-
primary?: string
|
|
3
|
-
primaryForeground?: string
|
|
4
|
-
background?: string
|
|
5
|
-
foreground?: string
|
|
6
|
-
accent?: string
|
|
7
|
-
radius?: string
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Proyección pública de ecomiq.config.js (seguro para el bundle cliente).
|
|
12
|
-
* Nombre, SEO, analytics y menús viven en `/v1/settings`.
|
|
13
|
-
*/
|
|
14
|
-
export interface PublicEcomiqConfig {
|
|
15
|
-
/**
|
|
16
|
-
* Identidad de tienda para `x-Store-Domain`.
|
|
17
|
-
* Acepta slug corto o dominio completo, p. ej. `marketplace`,
|
|
18
|
-
* `marketplace.ecomiq.app` o `marketplace.pe`.
|
|
19
|
-
*/
|
|
20
|
-
domain: string
|
|
21
|
-
theme?: EcomiqThemeConfig
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export type EcomiqConfig = PublicEcomiqConfig
|
package/src/review-submission.ts
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
CreateProductReviewParams,
|
|
3
|
-
StorefrontReview,
|
|
4
|
-
} from '@ecomiq/core'
|
|
5
|
-
import { ApiError } from '@ecomiq/core'
|
|
6
|
-
import { z } from 'zod'
|
|
7
|
-
|
|
8
|
-
const ReviewProblemSchema = z.object({
|
|
9
|
-
code: z.string().max(120).regex(/^[A-Za-z0-9._-]+$/).optional(),
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
interface ProductReviewClient {
|
|
13
|
-
createProductReview(
|
|
14
|
-
params: CreateProductReviewParams,
|
|
15
|
-
): Promise<StorefrontReview>
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface ProductReviewSubmissionError {
|
|
19
|
-
status: 400 | 409 | 429 | 500
|
|
20
|
-
code?: string
|
|
21
|
-
message: string
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export type ProductReviewSubmissionResult =
|
|
25
|
-
| {
|
|
26
|
-
ok: true
|
|
27
|
-
review: StorefrontReview
|
|
28
|
-
}
|
|
29
|
-
| {
|
|
30
|
-
ok: false
|
|
31
|
-
error: ProductReviewSubmissionError
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export async function submitProductReview(
|
|
35
|
-
client: ProductReviewClient,
|
|
36
|
-
input: CreateProductReviewParams,
|
|
37
|
-
): Promise<ProductReviewSubmissionResult> {
|
|
38
|
-
try {
|
|
39
|
-
const review = await client.createProductReview(input)
|
|
40
|
-
return { ok: true, review }
|
|
41
|
-
} catch (error) {
|
|
42
|
-
if (!(error instanceof ApiError)) throw error
|
|
43
|
-
|
|
44
|
-
let code: string | undefined
|
|
45
|
-
const problem = ReviewProblemSchema.safeParse(error.body)
|
|
46
|
-
if (problem.success) code = problem.data.code
|
|
47
|
-
|
|
48
|
-
if (error.status === 400) {
|
|
49
|
-
let message = 'Revisa los datos de la reseña e inténtalo nuevamente.'
|
|
50
|
-
if (
|
|
51
|
-
code === 'ProductReview.OrderInvalid' ||
|
|
52
|
-
code === 'ProductReview.OrderOwnerMismatch' ||
|
|
53
|
-
code === 'ProductReview.ProductNotPurchased'
|
|
54
|
-
) {
|
|
55
|
-
message = 'No pudimos verificar la compra con los datos ingresados.'
|
|
56
|
-
}
|
|
57
|
-
return { ok: false, error: { status: 400, code, message } }
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (error.status === 409) {
|
|
61
|
-
let message = 'No pudimos registrar esta reseña porque ya existe una similar.'
|
|
62
|
-
if (code === 'ProductReview.AlreadyExists') {
|
|
63
|
-
message = 'Ya enviaste una reseña para este producto.'
|
|
64
|
-
}
|
|
65
|
-
return { ok: false, error: { status: 409, code, message } }
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (error.status === 429) {
|
|
69
|
-
return {
|
|
70
|
-
ok: false,
|
|
71
|
-
error: {
|
|
72
|
-
status: 429,
|
|
73
|
-
code,
|
|
74
|
-
message:
|
|
75
|
-
'Enviaste varias reseñas en poco tiempo. Espera un momento e inténtalo nuevamente.',
|
|
76
|
-
},
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return {
|
|
81
|
-
ok: false,
|
|
82
|
-
error: {
|
|
83
|
-
status: 500,
|
|
84
|
-
code,
|
|
85
|
-
message: 'No pudimos enviar la reseña. Inténtalo nuevamente.',
|
|
86
|
-
},
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
package/src/runtime/context.ts
DELETED