@ecomiq/storefront 2.1.3 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +150 -123
- 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 -81
- 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/cloud-runtime-client.ts +0 -378
- package/src/codegen.mjs +0 -789
- 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 -354
- 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 -111
- 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 -301
- package/src/storefront-definition/contract.ts +0 -1
- package/src/storefront-definition/data.ts +0 -188
- package/src/storefront-definition/index.ts +0 -2
- package/src/storefront-definition/renderer.tsx +0 -1481
- package/src/storefront-layout.ts +0 -59
- package/src/storefront-runtime.ts +0 -173
- package/src/styles.css +0 -97
- 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/cart-session.ts
DELETED
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ApiError,
|
|
3
|
-
type RemoveCartItemParams,
|
|
4
|
-
type StorefrontCart,
|
|
5
|
-
type StorefrontClient,
|
|
6
|
-
type UpdateCartItemQuantityParams,
|
|
7
|
-
} from '@ecomiq/core'
|
|
8
|
-
import { z } from 'zod'
|
|
9
|
-
|
|
10
|
-
type CartClient = Pick<StorefrontClient, 'getCart' | 'createCart' | 'addCartItem'>
|
|
11
|
-
|
|
12
|
-
export interface LoadActiveCartInput {
|
|
13
|
-
cartToken: string
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export type ActiveCartLoadResult =
|
|
17
|
-
| { ok: true; value: StorefrontCart | null }
|
|
18
|
-
| {
|
|
19
|
-
ok: false
|
|
20
|
-
error: {
|
|
21
|
-
kind: 'failed'
|
|
22
|
-
message: string
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export type CartItemMutationResult =
|
|
27
|
-
| { ok: true; value: StorefrontCart }
|
|
28
|
-
| {
|
|
29
|
-
ok: false
|
|
30
|
-
error: {
|
|
31
|
-
kind: 'cart-unavailable' | 'unavailable' | 'failed'
|
|
32
|
-
message: string
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export interface AddProductToCartInput {
|
|
37
|
-
cartToken?: string
|
|
38
|
-
currencyCode: string
|
|
39
|
-
variantId: string
|
|
40
|
-
quantity: number
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export interface AddProductToCartResult {
|
|
44
|
-
cartToken: string
|
|
45
|
-
cart: StorefrontCart
|
|
46
|
-
created: boolean
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export type ProductCartMutationResult =
|
|
50
|
-
| { ok: true; value: AddProductToCartResult }
|
|
51
|
-
| {
|
|
52
|
-
ok: false
|
|
53
|
-
error: {
|
|
54
|
-
kind: 'unavailable' | 'failed'
|
|
55
|
-
message: string
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const StorefrontProblemSchema = z.object({
|
|
60
|
-
code: z.string().optional(),
|
|
61
|
-
}).passthrough()
|
|
62
|
-
|
|
63
|
-
function cartIsUnavailable(error: unknown) {
|
|
64
|
-
if (!(error instanceof ApiError)) return false
|
|
65
|
-
const problem = StorefrontProblemSchema.safeParse(error.body)
|
|
66
|
-
if (!problem.success) return false
|
|
67
|
-
if (error.status === 404 && problem.data.code === 'Carts.NotFound') return true
|
|
68
|
-
return error.status === 400 && problem.data.code === 'Carts.NotActive'
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function cartIsActive(cart: StorefrontCart) {
|
|
72
|
-
return cart.status === 'inProgress' || cart.status === 'pending'
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function cartItemMutationFailure(error: ApiError): CartItemMutationResult {
|
|
76
|
-
if (cartIsUnavailable(error)) {
|
|
77
|
-
return {
|
|
78
|
-
ok: false,
|
|
79
|
-
error: {
|
|
80
|
-
kind: 'cart-unavailable',
|
|
81
|
-
message: 'Este carrito ya no está disponible.',
|
|
82
|
-
},
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const problem = StorefrontProblemSchema.safeParse(error.body)
|
|
87
|
-
if (problem.success && problem.data.code === 'Catalog.InsufficientStock') {
|
|
88
|
-
return {
|
|
89
|
-
ok: false,
|
|
90
|
-
error: {
|
|
91
|
-
kind: 'unavailable',
|
|
92
|
-
message: 'No hay stock suficiente para esa cantidad.',
|
|
93
|
-
},
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
if (problem.success && problem.data.code === 'Carts.ItemNotFound') {
|
|
97
|
-
return {
|
|
98
|
-
ok: false,
|
|
99
|
-
error: {
|
|
100
|
-
kind: 'unavailable',
|
|
101
|
-
message: 'Este producto ya no está en el carrito.',
|
|
102
|
-
},
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return {
|
|
107
|
-
ok: false,
|
|
108
|
-
error: {
|
|
109
|
-
kind: 'failed',
|
|
110
|
-
message: 'No pudimos actualizar el carrito. Inténtalo nuevamente.',
|
|
111
|
-
},
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export async function loadActiveCart(
|
|
116
|
-
client: Pick<StorefrontClient, 'getCart'>,
|
|
117
|
-
input: LoadActiveCartInput,
|
|
118
|
-
): Promise<ActiveCartLoadResult> {
|
|
119
|
-
try {
|
|
120
|
-
const cart = await client.getCart({ cartToken: input.cartToken })
|
|
121
|
-
return { ok: true as const, value: cartIsActive(cart) ? cart : null }
|
|
122
|
-
} catch (error) {
|
|
123
|
-
if (cartIsUnavailable(error)) return { ok: true as const, value: null }
|
|
124
|
-
if (error instanceof ApiError) {
|
|
125
|
-
return {
|
|
126
|
-
ok: false,
|
|
127
|
-
error: {
|
|
128
|
-
kind: 'failed',
|
|
129
|
-
message: 'No pudimos cargar el carrito. Inténtalo nuevamente.',
|
|
130
|
-
},
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
throw error
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export async function submitCartItemQuantity(
|
|
138
|
-
client: Pick<StorefrontClient, 'updateCartItemQuantity'>,
|
|
139
|
-
input: UpdateCartItemQuantityParams,
|
|
140
|
-
): Promise<CartItemMutationResult> {
|
|
141
|
-
try {
|
|
142
|
-
const cart = await client.updateCartItemQuantity(input)
|
|
143
|
-
return { ok: true, value: cart }
|
|
144
|
-
} catch (error) {
|
|
145
|
-
if (!(error instanceof ApiError)) throw error
|
|
146
|
-
return cartItemMutationFailure(error)
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
export async function submitCartItemRemoval(
|
|
151
|
-
client: Pick<StorefrontClient, 'updateCartItemQuantity'>,
|
|
152
|
-
input: RemoveCartItemParams,
|
|
153
|
-
): Promise<CartItemMutationResult> {
|
|
154
|
-
try {
|
|
155
|
-
const cart = await client.updateCartItemQuantity({ ...input, quantity: 0 })
|
|
156
|
-
return { ok: true, value: cart }
|
|
157
|
-
} catch (error) {
|
|
158
|
-
if (!(error instanceof ApiError)) throw error
|
|
159
|
-
return cartItemMutationFailure(error)
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
export async function addProductToCart(
|
|
164
|
-
client: CartClient,
|
|
165
|
-
input: AddProductToCartInput,
|
|
166
|
-
): Promise<AddProductToCartResult> {
|
|
167
|
-
let current: StorefrontCart | undefined
|
|
168
|
-
let created = false
|
|
169
|
-
|
|
170
|
-
if (input.cartToken) {
|
|
171
|
-
try {
|
|
172
|
-
const persisted = await client.getCart({ cartToken: input.cartToken })
|
|
173
|
-
if (cartIsActive(persisted)) current = persisted
|
|
174
|
-
} catch (error) {
|
|
175
|
-
if (!cartIsUnavailable(error)) throw error
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
if (!current) {
|
|
180
|
-
current = await client.createCart({ currencyCode: input.currencyCode })
|
|
181
|
-
created = true
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const add = (cartToken: string) => client.addCartItem({
|
|
185
|
-
cartToken,
|
|
186
|
-
variantId: input.variantId,
|
|
187
|
-
quantity: input.quantity,
|
|
188
|
-
})
|
|
189
|
-
|
|
190
|
-
try {
|
|
191
|
-
const cart = await add(current.token)
|
|
192
|
-
return { cartToken: cart.token, cart, created }
|
|
193
|
-
} catch (error) {
|
|
194
|
-
if (!cartIsUnavailable(error)) throw error
|
|
195
|
-
const replacement = await client.createCart({ currencyCode: input.currencyCode })
|
|
196
|
-
const cart = await add(replacement.token)
|
|
197
|
-
return { cartToken: cart.token, cart, created: true }
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
export async function submitProductToCart(
|
|
202
|
-
client: CartClient,
|
|
203
|
-
input: AddProductToCartInput,
|
|
204
|
-
): Promise<ProductCartMutationResult> {
|
|
205
|
-
try {
|
|
206
|
-
return { ok: true, value: await addProductToCart(client, input) }
|
|
207
|
-
} catch (error) {
|
|
208
|
-
if (!(error instanceof ApiError)) throw error
|
|
209
|
-
|
|
210
|
-
const problem = StorefrontProblemSchema.safeParse(error.body)
|
|
211
|
-
const code = problem.success ? problem.data.code : undefined
|
|
212
|
-
if (code === 'Catalog.InsufficientStock') {
|
|
213
|
-
return {
|
|
214
|
-
ok: false,
|
|
215
|
-
error: {
|
|
216
|
-
kind: 'unavailable',
|
|
217
|
-
message: 'No hay stock suficiente para esa cantidad.',
|
|
218
|
-
},
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
if (code === 'Catalog.VariantNotFound') {
|
|
222
|
-
return {
|
|
223
|
-
ok: false,
|
|
224
|
-
error: {
|
|
225
|
-
kind: 'unavailable',
|
|
226
|
-
message: 'Esta variante ya no está disponible.',
|
|
227
|
-
},
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
return {
|
|
232
|
-
ok: false,
|
|
233
|
-
error: {
|
|
234
|
-
kind: 'failed',
|
|
235
|
-
message: 'No pudimos actualizar el carrito. Inténtalo nuevamente.',
|
|
236
|
-
},
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
package/src/client.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createClient as createCoreClient,
|
|
3
|
-
type CreateApiOptions,
|
|
4
|
-
type StorefrontClient,
|
|
5
|
-
} from '@ecomiq/core/client'
|
|
6
|
-
import { getServerConfig } from './server-config-store'
|
|
7
|
-
|
|
8
|
-
let sharedClient: StorefrontClient | null = null
|
|
9
|
-
|
|
10
|
-
/** Cliente storefront compartido (cache de settings incluido). */
|
|
11
|
-
export function getStorefrontClient(options: CreateApiOptions = {}): StorefrontClient {
|
|
12
|
-
if (!sharedClient) {
|
|
13
|
-
const config = getServerConfig()
|
|
14
|
-
const headers = {
|
|
15
|
-
...config.api?.headers,
|
|
16
|
-
...options.headers,
|
|
17
|
-
}
|
|
18
|
-
for (const key of Object.keys(headers)) {
|
|
19
|
-
const lower = key.toLowerCase()
|
|
20
|
-
if (lower === 'x-store-id' || lower === 'x-store-domain') delete headers[key]
|
|
21
|
-
}
|
|
22
|
-
sharedClient = createCoreClient({
|
|
23
|
-
domain: config.domain,
|
|
24
|
-
...config.api,
|
|
25
|
-
...options,
|
|
26
|
-
headers,
|
|
27
|
-
})
|
|
28
|
-
}
|
|
29
|
-
return sharedClient
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/** Invalida el singleton (tests / hot reload). */
|
|
33
|
-
export function resetStorefrontClient(): void {
|
|
34
|
-
sharedClient?.clearCache()
|
|
35
|
-
sharedClient = null
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Cliente storefront. Domain y defaults de API salen del config de la tienda.
|
|
40
|
-
*
|
|
41
|
-
* ```ts
|
|
42
|
-
* export const api = createClient()
|
|
43
|
-
* const collections = await api.getCollections()
|
|
44
|
-
* ```
|
|
45
|
-
*/
|
|
46
|
-
export function createClient(_options: CreateApiOptions = {}): StorefrontClient {
|
|
47
|
-
return getStorefrontClient(_options)
|
|
48
|
-
}
|
|
@@ -1,378 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod'
|
|
2
|
-
import { StorefrontDefinitionSchema } from '@ecomiq/storefront-definition'
|
|
3
|
-
|
|
4
|
-
export const CloudRuntimeStoreSlugSchema = z
|
|
5
|
-
.string()
|
|
6
|
-
.trim()
|
|
7
|
-
.min(2)
|
|
8
|
-
.max(100)
|
|
9
|
-
.regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/)
|
|
10
|
-
|
|
11
|
-
export const ActiveStorefrontRuntimeSchema = z
|
|
12
|
-
.object({
|
|
13
|
-
schemaVersion: z.literal(1),
|
|
14
|
-
store: z
|
|
15
|
-
.object({
|
|
16
|
-
slug: CloudRuntimeStoreSlugSchema,
|
|
17
|
-
})
|
|
18
|
-
.strict(),
|
|
19
|
-
environment: z
|
|
20
|
-
.object({
|
|
21
|
-
name: z.literal('production'),
|
|
22
|
-
status: z.literal('ready'),
|
|
23
|
-
})
|
|
24
|
-
.strict(),
|
|
25
|
-
publication: z
|
|
26
|
-
.object({
|
|
27
|
-
sequence: z.number().int().nonnegative(),
|
|
28
|
-
releaseSequence: z.number().int().nonnegative(),
|
|
29
|
-
publishedAt: z.string().datetime({ offset: true }),
|
|
30
|
-
runtimeReleaseId: z.string().optional(),
|
|
31
|
-
artifactDigest: z.string().optional(),
|
|
32
|
-
})
|
|
33
|
-
.strict(),
|
|
34
|
-
definition: StorefrontDefinitionSchema,
|
|
35
|
-
})
|
|
36
|
-
.strict()
|
|
37
|
-
|
|
38
|
-
export type ActiveStorefrontRuntime = z.infer<
|
|
39
|
-
typeof ActiveStorefrontRuntimeSchema
|
|
40
|
-
>
|
|
41
|
-
|
|
42
|
-
export const EnvironmentPointerSchema = z
|
|
43
|
-
.object({
|
|
44
|
-
schemaVersion: z.literal(1),
|
|
45
|
-
storeSlug: CloudRuntimeStoreSlugSchema,
|
|
46
|
-
projectId: z.string().min(1),
|
|
47
|
-
environmentId: z.string().min(1),
|
|
48
|
-
generation: z.number().int().nonnegative(),
|
|
49
|
-
releaseSequence: z.number().int().nonnegative(),
|
|
50
|
-
deploymentSequence: z.number().int().nonnegative(),
|
|
51
|
-
artifactDigest: z.string().min(1),
|
|
52
|
-
artifactKey: z.string().min(1),
|
|
53
|
-
manifestDigest: z.string().min(1),
|
|
54
|
-
manifestKey: z.string().min(1),
|
|
55
|
-
runtimeReleaseId: z.string().min(1),
|
|
56
|
-
publishedAt: z.string().datetime({ offset: true }),
|
|
57
|
-
cachePolicy: z
|
|
58
|
-
.object({
|
|
59
|
-
pointerMaxAgeSeconds: z.number().int().nonnegative(),
|
|
60
|
-
staleIfErrorSeconds: z.number().int().nonnegative(),
|
|
61
|
-
})
|
|
62
|
-
.strict(),
|
|
63
|
-
})
|
|
64
|
-
.strict()
|
|
65
|
-
|
|
66
|
-
export type EnvironmentPointer = z.infer<typeof EnvironmentPointerSchema>
|
|
67
|
-
|
|
68
|
-
export type CloudRuntimeFetch = (
|
|
69
|
-
input: RequestInfo | URL,
|
|
70
|
-
init?: RequestInit,
|
|
71
|
-
) => Promise<Response>
|
|
72
|
-
|
|
73
|
-
export interface CloudRuntimeClientOptions {
|
|
74
|
-
baseUrl: string
|
|
75
|
-
artifactBaseUrl?: string
|
|
76
|
-
timeoutMs?: number
|
|
77
|
-
cacheTtlMs?: number
|
|
78
|
-
fetch?: CloudRuntimeFetch
|
|
79
|
-
now?: () => number
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
interface RuntimeCacheEntry {
|
|
83
|
-
value: ActiveStorefrontRuntime | null
|
|
84
|
-
etag?: string
|
|
85
|
-
expiresAt: number
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export class CloudRuntimeResponseError extends Error {
|
|
89
|
-
readonly status: number
|
|
90
|
-
|
|
91
|
-
constructor(status: number) {
|
|
92
|
-
super(`Cloud runtime respondió HTTP ${status}`)
|
|
93
|
-
this.name = 'CloudRuntimeResponseError'
|
|
94
|
-
this.status = status
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const DEFAULT_TIMEOUT_MS = 3_000
|
|
99
|
-
const DEFAULT_CACHE_TTL_MS = 15_000
|
|
100
|
-
const MAX_CACHE_ENTRIES = 100
|
|
101
|
-
|
|
102
|
-
interface LastKnownGood {
|
|
103
|
-
runtime: ActiveStorefrontRuntime
|
|
104
|
-
generation: number
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export class CloudRuntimeClient {
|
|
108
|
-
readonly baseUrl: string
|
|
109
|
-
readonly artifactBaseUrl: string | null
|
|
110
|
-
readonly timeoutMs: number
|
|
111
|
-
readonly cacheTtlMs: number
|
|
112
|
-
|
|
113
|
-
private readonly fetchRuntime: CloudRuntimeFetch
|
|
114
|
-
private readonly now: () => number
|
|
115
|
-
private readonly cache = new Map<string, RuntimeCacheEntry>()
|
|
116
|
-
private readonly lastKnownGood = new Map<string, LastKnownGood>()
|
|
117
|
-
private readonly artifactCache = new Map<string, ActiveStorefrontRuntime>()
|
|
118
|
-
private readonly inFlight = new Map<
|
|
119
|
-
string,
|
|
120
|
-
Promise<ActiveStorefrontRuntime | null>
|
|
121
|
-
>()
|
|
122
|
-
|
|
123
|
-
constructor(options: CloudRuntimeClientOptions) {
|
|
124
|
-
this.baseUrl = new URL(options.baseUrl).toString().replace(/\/$/, '')
|
|
125
|
-
this.artifactBaseUrl = options.artifactBaseUrl
|
|
126
|
-
? new URL(options.artifactBaseUrl).toString().replace(/\/$/, '')
|
|
127
|
-
: null
|
|
128
|
-
this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS
|
|
129
|
-
this.cacheTtlMs = options.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS
|
|
130
|
-
this.fetchRuntime = options.fetch ?? globalThis.fetch
|
|
131
|
-
this.now = options.now ?? Date.now
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
async resolveActiveStorefront(
|
|
135
|
-
storeSlugInput: string,
|
|
136
|
-
): Promise<ActiveStorefrontRuntime | null> {
|
|
137
|
-
const storeSlug = CloudRuntimeStoreSlugSchema.parse(storeSlugInput)
|
|
138
|
-
const cached = this.cache.get(storeSlug)
|
|
139
|
-
if (cached && cached.expiresAt > this.now()) {
|
|
140
|
-
return cached.value
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const activeRequest = this.inFlight.get(storeSlug)
|
|
144
|
-
if (activeRequest) return activeRequest
|
|
145
|
-
|
|
146
|
-
const request = (
|
|
147
|
-
this.artifactBaseUrl
|
|
148
|
-
? this.requestFromArtifactStore(storeSlug)
|
|
149
|
-
: this.requestActiveStorefront(storeSlug, cached)
|
|
150
|
-
).finally(() => {
|
|
151
|
-
this.inFlight.delete(storeSlug)
|
|
152
|
-
})
|
|
153
|
-
this.inFlight.set(storeSlug, request)
|
|
154
|
-
return request
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
clearCache(): void {
|
|
158
|
-
this.cache.clear()
|
|
159
|
-
this.lastKnownGood.clear()
|
|
160
|
-
this.artifactCache.clear()
|
|
161
|
-
this.inFlight.clear()
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
private async requestFromArtifactStore(
|
|
165
|
-
storeSlug: string,
|
|
166
|
-
): Promise<ActiveStorefrontRuntime | null> {
|
|
167
|
-
const survivor = this.lastKnownGood.get(storeSlug)
|
|
168
|
-
let pointer: EnvironmentPointer | null
|
|
169
|
-
try {
|
|
170
|
-
pointer = await this.fetchPointer(storeSlug)
|
|
171
|
-
} catch {
|
|
172
|
-
if (survivor) return survivor.runtime
|
|
173
|
-
throw new CloudRuntimeResponseError(503)
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (pointer === null) {
|
|
177
|
-
if (survivor) return survivor.runtime
|
|
178
|
-
this.setCache(storeSlug, {
|
|
179
|
-
value: null,
|
|
180
|
-
expiresAt: this.now() + this.cacheTtlMs,
|
|
181
|
-
})
|
|
182
|
-
return null
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if (survivor && pointer.generation < survivor.generation) {
|
|
186
|
-
this.setCache(storeSlug, {
|
|
187
|
-
value: survivor.runtime,
|
|
188
|
-
expiresAt: this.now() + this.cacheTtlMs,
|
|
189
|
-
})
|
|
190
|
-
return survivor.runtime
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
let runtime: ActiveStorefrontRuntime
|
|
194
|
-
try {
|
|
195
|
-
runtime = await this.fetchArtifactRuntime(pointer)
|
|
196
|
-
} catch {
|
|
197
|
-
if (survivor) return survivor.runtime
|
|
198
|
-
throw new CloudRuntimeResponseError(503)
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
if (runtime.store.slug !== storeSlug) {
|
|
202
|
-
throw new Error(
|
|
203
|
-
`El pointer de ${storeSlug} apunta a un artifact de ${runtime.store.slug}`,
|
|
204
|
-
)
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
const ttlMs = pointer.cachePolicy.pointerMaxAgeSeconds * 1_000
|
|
208
|
-
this.setCache(storeSlug, {
|
|
209
|
-
value: runtime,
|
|
210
|
-
expiresAt: this.now() + (ttlMs > 0 ? ttlMs : this.cacheTtlMs),
|
|
211
|
-
})
|
|
212
|
-
this.lastKnownGood.set(storeSlug, {
|
|
213
|
-
runtime,
|
|
214
|
-
generation: pointer.generation,
|
|
215
|
-
})
|
|
216
|
-
return runtime
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
private async fetchPointer(
|
|
220
|
-
storeSlug: string,
|
|
221
|
-
): Promise<EnvironmentPointer | null> {
|
|
222
|
-
const response = await this.fetchWithTimeout(
|
|
223
|
-
`${this.artifactBaseUrl}/stores/${encodeURIComponent(storeSlug)}/pointer.json`,
|
|
224
|
-
)
|
|
225
|
-
if (response.status === 404) return null
|
|
226
|
-
if (!response.ok) throw new CloudRuntimeResponseError(response.status)
|
|
227
|
-
return EnvironmentPointerSchema.parse(await response.json())
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
private async fetchArtifactRuntime(
|
|
231
|
-
pointer: EnvironmentPointer,
|
|
232
|
-
): Promise<ActiveStorefrontRuntime> {
|
|
233
|
-
const cached = this.artifactCache.get(pointer.artifactKey)
|
|
234
|
-
const base =
|
|
235
|
-
cached ?? (await this.requestArtifactBody(pointer.artifactKey))
|
|
236
|
-
if (!cached) {
|
|
237
|
-
if (this.artifactCache.size >= MAX_CACHE_ENTRIES) {
|
|
238
|
-
const oldestKey = this.artifactCache.keys().next().value
|
|
239
|
-
if (oldestKey !== undefined) this.artifactCache.delete(oldestKey)
|
|
240
|
-
}
|
|
241
|
-
this.artifactCache.set(pointer.artifactKey, base)
|
|
242
|
-
}
|
|
243
|
-
return {
|
|
244
|
-
...base,
|
|
245
|
-
publication: {
|
|
246
|
-
sequence: pointer.deploymentSequence,
|
|
247
|
-
releaseSequence: pointer.releaseSequence,
|
|
248
|
-
publishedAt: pointer.publishedAt,
|
|
249
|
-
runtimeReleaseId: pointer.runtimeReleaseId,
|
|
250
|
-
artifactDigest: pointer.artifactDigest,
|
|
251
|
-
},
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
private async requestArtifactBody(
|
|
256
|
-
artifactKey: string,
|
|
257
|
-
): Promise<ActiveStorefrontRuntime> {
|
|
258
|
-
const response = await this.fetchWithTimeout(
|
|
259
|
-
`${this.artifactBaseUrl}/${artifactKey}`,
|
|
260
|
-
)
|
|
261
|
-
if (!response.ok) throw new CloudRuntimeResponseError(response.status)
|
|
262
|
-
return ActiveStorefrontRuntimeSchema.parse(await response.json())
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
private async fetchWithTimeout(url: string): Promise<Response> {
|
|
266
|
-
const controller = new AbortController()
|
|
267
|
-
const timeout = setTimeout(() => controller.abort(), this.timeoutMs)
|
|
268
|
-
try {
|
|
269
|
-
return await this.fetchRuntime(url, {
|
|
270
|
-
method: 'GET',
|
|
271
|
-
headers: { accept: 'application/json' },
|
|
272
|
-
signal: controller.signal,
|
|
273
|
-
})
|
|
274
|
-
} finally {
|
|
275
|
-
clearTimeout(timeout)
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
private setCache(storeSlug: string, entry: RuntimeCacheEntry): void {
|
|
280
|
-
if (!this.cache.has(storeSlug) && this.cache.size >= MAX_CACHE_ENTRIES) {
|
|
281
|
-
const oldestKey = this.cache.keys().next().value
|
|
282
|
-
if (oldestKey !== undefined) this.cache.delete(oldestKey)
|
|
283
|
-
}
|
|
284
|
-
this.cache.set(storeSlug, entry)
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
private async requestActiveStorefront(
|
|
288
|
-
storeSlug: string,
|
|
289
|
-
cached?: RuntimeCacheEntry,
|
|
290
|
-
): Promise<ActiveStorefrontRuntime | null> {
|
|
291
|
-
const controller = new AbortController()
|
|
292
|
-
const timeout = setTimeout(() => controller.abort(), this.timeoutMs)
|
|
293
|
-
const headers = new Headers({ accept: 'application/json' })
|
|
294
|
-
if (cached?.etag) headers.set('if-none-match', cached.etag)
|
|
295
|
-
|
|
296
|
-
try {
|
|
297
|
-
const response = await this.fetchRuntime(
|
|
298
|
-
new URL(
|
|
299
|
-
`/v1/runtime/storefronts/${encodeURIComponent(storeSlug)}`,
|
|
300
|
-
this.baseUrl,
|
|
301
|
-
),
|
|
302
|
-
{
|
|
303
|
-
method: 'GET',
|
|
304
|
-
headers,
|
|
305
|
-
signal: controller.signal,
|
|
306
|
-
},
|
|
307
|
-
)
|
|
308
|
-
|
|
309
|
-
if (response.status === 304) {
|
|
310
|
-
if (!cached) throw new CloudRuntimeResponseError(304)
|
|
311
|
-
this.setCache(storeSlug, {
|
|
312
|
-
...cached,
|
|
313
|
-
expiresAt: this.now() + this.cacheTtlMs,
|
|
314
|
-
})
|
|
315
|
-
return cached.value
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
if (response.status === 404) {
|
|
319
|
-
this.setCache(storeSlug, {
|
|
320
|
-
value: null,
|
|
321
|
-
etag: response.headers.get('etag') ?? undefined,
|
|
322
|
-
expiresAt: this.now() + this.cacheTtlMs,
|
|
323
|
-
})
|
|
324
|
-
return null
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
if (!response.ok) {
|
|
328
|
-
throw new CloudRuntimeResponseError(response.status)
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
const runtime = ActiveStorefrontRuntimeSchema.parse(
|
|
332
|
-
await response.json(),
|
|
333
|
-
)
|
|
334
|
-
if (runtime.store.slug !== storeSlug) {
|
|
335
|
-
throw new Error(
|
|
336
|
-
`Cloud runtime devolvió el store slug ${runtime.store.slug} para ${storeSlug}`,
|
|
337
|
-
)
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
this.setCache(storeSlug, {
|
|
341
|
-
value: runtime,
|
|
342
|
-
etag: response.headers.get('etag') ?? undefined,
|
|
343
|
-
expiresAt: this.now() + this.cacheTtlMs,
|
|
344
|
-
})
|
|
345
|
-
return runtime
|
|
346
|
-
} finally {
|
|
347
|
-
clearTimeout(timeout)
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
const sharedClients = new Map<string, CloudRuntimeClient>()
|
|
353
|
-
|
|
354
|
-
export function getCloudRuntimeClient(
|
|
355
|
-
options: Omit<CloudRuntimeClientOptions, 'fetch' | 'now'>,
|
|
356
|
-
): CloudRuntimeClient {
|
|
357
|
-
const key = [
|
|
358
|
-
new URL(options.baseUrl).toString(),
|
|
359
|
-
options.artifactBaseUrl ? new URL(options.artifactBaseUrl).toString() : '',
|
|
360
|
-
options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
|
|
361
|
-
options.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS,
|
|
362
|
-
].join('|')
|
|
363
|
-
const current = sharedClients.get(key)
|
|
364
|
-
if (current) return current
|
|
365
|
-
|
|
366
|
-
const client = new CloudRuntimeClient(options)
|
|
367
|
-
if (sharedClients.size >= 8) {
|
|
368
|
-
const oldestKey = sharedClients.keys().next().value
|
|
369
|
-
if (oldestKey !== undefined) sharedClients.delete(oldestKey)
|
|
370
|
-
}
|
|
371
|
-
sharedClients.set(key, client)
|
|
372
|
-
return client
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
export function resetCloudRuntimeClients(): void {
|
|
376
|
-
for (const client of sharedClients.values()) client.clearCache()
|
|
377
|
-
sharedClients.clear()
|
|
378
|
-
}
|