@zenky/storefront-vue 0.10.4 → 0.10.6
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/CHANGELOG.md +39 -0
- package/README.md +63 -3
- package/dist/cart/index.js +4 -4
- package/dist/{chunk-YREGCQSB.js → chunk-5YD4AIY2.js} +5 -5
- package/dist/chunk-5YD4AIY2.js.map +1 -0
- package/dist/{chunk-YS5DXYYV.js → chunk-E4DUFN2M.js} +21 -28
- package/dist/chunk-E4DUFN2M.js.map +1 -0
- package/dist/{chunk-OTSAR32A.js → chunk-MOG6UMFM.js} +2 -2
- package/dist/{chunk-OTSAR32A.js.map → chunk-MOG6UMFM.js.map} +1 -1
- package/dist/{chunk-SS7B2NLF.js → chunk-PTMSPB34.js} +3 -3
- package/dist/{chunk-SS7B2NLF.js.map → chunk-PTMSPB34.js.map} +1 -1
- package/dist/{chunk-IVG4FQE5.js → chunk-RAJDWCJU.js} +3 -3
- package/dist/{chunk-IVG4FQE5.js.map → chunk-RAJDWCJU.js.map} +1 -1
- package/dist/{chunk-TB5TBJ4U.js → chunk-VFMVQR6Y.js} +8 -15
- package/dist/chunk-VFMVQR6Y.js.map +1 -0
- package/dist/{chunk-NIQFYJRP.js → chunk-Z247QRDJ.js} +4 -4
- package/dist/{chunk-NIQFYJRP.js.map → chunk-Z247QRDJ.js.map} +1 -1
- package/dist/index.js +7 -7
- package/dist/ports/index.d.ts +2 -1
- package/dist/ports/index.js +1 -1
- package/dist/products/index.js +2 -2
- package/dist/promotions/index.d.ts +13 -0
- package/dist/promotions/index.js +3 -3
- package/dist/seo/index.js +2 -2
- package/dist/stores/index.d.ts +2 -1
- package/dist/stores/index.js +3 -3
- package/docs/consumer-setup.md +10 -3
- package/docs/ports.md +1 -1
- package/docs/releasing.md +2 -1
- package/package.json +5 -4
- package/dist/chunk-TB5TBJ4U.js.map +0 -1
- package/dist/chunk-YREGCQSB.js.map +0 -1
- package/dist/chunk-YS5DXYYV.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,45 @@ All notable changes to this project are documented in this file. The format foll
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and releases follow
|
|
5
5
|
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## Unreleased
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `authStore.apiToken` — the single answer to "which token goes into an SDK call". It is
|
|
12
|
+
`undefined` unless the store holds a non-empty token, so an empty string can never reach
|
|
13
|
+
an `Authorization` header. Consumers should read it instead of deriving the rule from
|
|
14
|
+
`token` and `isAuthenticated` at each call site.
|
|
15
|
+
|
|
16
|
+
## 0.10.5 - 2026-07-31
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- `config` is now an optional runtime port because the current core does not read it.
|
|
21
|
+
- The framework-boundary gate now parses TypeScript syntax, so URLs and comment-like
|
|
22
|
+
text inside strings no longer hide violations or create false positives.
|
|
23
|
+
- A runtime-context gate now rejects composable or Pinia-store resolution from deferred
|
|
24
|
+
helpers and store actions; those functions must use dependencies captured in setup.
|
|
25
|
+
- Product restriction and delivery-time operations use public
|
|
26
|
+
`@zenky/storefront-api` resource methods instead of reaching through `sdk.client`.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- `authStore.initFromCookie()` now clears stale in-memory SDK credentials when the
|
|
31
|
+
current request has no auth cookies.
|
|
32
|
+
- Payment selection reuses the setup-captured order total, so checkout with applied
|
|
33
|
+
bonuses no longer resolves a composable from a later event/checkout callback.
|
|
34
|
+
- Cart delivery-method validation resolves the order-settings store once in the store
|
|
35
|
+
setup. Pinia already activates the owning instance for the duration of an action, so
|
|
36
|
+
this is consistency rather than a leak fix.
|
|
37
|
+
- Runtime-context documentation now distinguishes Vue injection context, arbitrary
|
|
38
|
+
callbacks, `app.runWithContext()`, and Pinia's conditional global fallback.
|
|
39
|
+
|
|
40
|
+
### Security
|
|
41
|
+
|
|
42
|
+
- `logCartError` redaction now covers customer addresses, e-mail and phone numbers, and
|
|
43
|
+
checkout/payment/redirect URLs, in object keys, `key=value` assignments, and query
|
|
44
|
+
parameters alike. Cart and checkout failures previously logged these verbatim.
|
|
45
|
+
|
|
7
46
|
## 0.10.4 - 2026-07-29
|
|
8
47
|
|
|
9
48
|
> **Breaking.** This release changes the runtime port contract and removes public
|
package/README.md
CHANGED
|
@@ -73,14 +73,71 @@ cart.itemCount.value // reactive
|
|
|
73
73
|
cart.totalPrice.value
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
+
### Call composables and stores synchronously in setup
|
|
77
|
+
|
|
78
|
+
Composables read the runtime through `inject()`, which works while a component
|
|
79
|
+
instance is active or while the owning Vue app is executing `app.runWithContext()`.
|
|
80
|
+
The important cases behave differently:
|
|
81
|
+
|
|
82
|
+
- **Top-level `await` in `<script setup>` is safe.** The SFC compiler wraps it in
|
|
83
|
+
`withAsyncContext()`, which restores the instance afterwards — so composables called
|
|
84
|
+
after `await bootstrap()` at the top level still resolve correctly.
|
|
85
|
+
- **A lifecycle hook has context only in its synchronous prefix.** After its first
|
|
86
|
+
`await`, the component instance is no longer active.
|
|
87
|
+
- **Event handlers, `watch` callbacks, timers, and `.then()` callbacks do not inherit
|
|
88
|
+
component injection context.** Resolve dependencies before registering the callback,
|
|
89
|
+
or deliberately re-enter the owning app with `app.runWithContext()`.
|
|
90
|
+
- **A hand-written `async setup()` is not compiler-wrapped.** Resolve dependencies
|
|
91
|
+
before its first `await`.
|
|
92
|
+
|
|
93
|
+
Resolve the composable up front and call the returned functions later.
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
// ✅ resolve in setup, call after the await
|
|
97
|
+
const { dispatchCheck } = usePromotionsChecker()
|
|
98
|
+
|
|
99
|
+
onMounted(async () => {
|
|
100
|
+
await initializeOrder()
|
|
101
|
+
dispatchCheck()
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
// ❌ resolving after an await — inject() has no instance to read from
|
|
105
|
+
onMounted(async () => {
|
|
106
|
+
await initializeOrder()
|
|
107
|
+
const { dispatchCheck } = usePromotionsChecker()
|
|
108
|
+
})
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The same applies inside event handlers, `watch` callbacks, timers, and `.then()` blocks:
|
|
112
|
+
resolve in `setup()`, keep the reference, call it from the callback. Watch for this
|
|
113
|
+
inside `try` blocks in particular — the `catch` swallows the failure and reports it as
|
|
114
|
+
whatever the surrounding operation was supposed to do, so the real cause never surfaces.
|
|
115
|
+
|
|
116
|
+
**Stores fail differently, and worse.** The Pinia stores exported from
|
|
117
|
+
`@zenky/storefront-vue/stores` read the runtime too, but a missed context does not throw:
|
|
118
|
+
Pinia falls back to its module-level active instance. Under concurrent SSR that instance
|
|
119
|
+
belongs to whichever request touched it last, so the lookup succeeds with another user's
|
|
120
|
+
state instead of failing.
|
|
121
|
+
|
|
122
|
+
Two cases behave differently, and the distinction is verified rather than assumed:
|
|
123
|
+
|
|
124
|
+
- **Inside a store action — safe.** Pinia activates the action's own instance for the
|
|
125
|
+
duration of the call, so resolving another store there returns the right one.
|
|
126
|
+
- **In a plain function after an `await`, outside any action and outside
|
|
127
|
+
`runWithContext()` — leaks.** This is the shape to watch for: it is silent, and it
|
|
128
|
+
crosses requests.
|
|
129
|
+
|
|
130
|
+
Resolve core stores in `setup()` for the same reason you resolve composables there. A
|
|
131
|
+
silent leak is far harder to notice than an exception.
|
|
132
|
+
|
|
76
133
|
## Runtime Ports
|
|
77
134
|
|
|
78
|
-
`createStorefront(runtime)` takes one object.
|
|
135
|
+
`createStorefront(runtime)` takes one object. Five ports are required; the rest are optional — omit an optional port and the feature that needs it is simply skipped.
|
|
79
136
|
|
|
80
137
|
| Port | Required | What the consumer provides |
|
|
81
138
|
| --- | --- | --- |
|
|
82
139
|
| `sdk` | yes | A `ZenkyStorefront` instance (`@zenky/storefront-api`). |
|
|
83
|
-
| `config` |
|
|
140
|
+
| `config` | no | Reserved consumer configuration; the current core does not read it. |
|
|
84
141
|
| `storage` | yes | Key/value persistence — cookies, `localStorage`, memory. |
|
|
85
142
|
| `notifier` | yes | Toasts: `error` / `success` / `warning` / `message`. |
|
|
86
143
|
| `messages` | yes | Maps stable domain message keys to localized consumer copy. |
|
|
@@ -186,13 +243,15 @@ npm run test:coverage # vitest + V8 coverage report
|
|
|
186
243
|
npm run check # format + lint + types + tests + build + exports
|
|
187
244
|
npm run check:exports # publint + are-the-types-wrong (esm-only profile)
|
|
188
245
|
npm run check:boundaries # reject Nuxt/Unhead and consumer policy in src/
|
|
246
|
+
npm run check:context # reject ambient composables/stores in deferred helpers
|
|
189
247
|
npm run check:runtime # import all entries in SSR + reject Node-only output
|
|
190
248
|
npm run check:size # enforce gzip bundle budgets
|
|
191
249
|
```
|
|
192
250
|
|
|
193
251
|
### Local linking with yalc
|
|
194
252
|
|
|
195
|
-
|
|
253
|
+
To iterate on an unreleased change without cutting a version, link the package into a
|
|
254
|
+
consumer app with [yalc](https://github.com/wclr/yalc):
|
|
196
255
|
|
|
197
256
|
```bash
|
|
198
257
|
# in this package, after a build:
|
|
@@ -213,6 +272,7 @@ npm run build && npx yalc push
|
|
|
213
272
|
- `typecheck` — type-only compile.
|
|
214
273
|
- `check:exports` — validate the exports map and published types.
|
|
215
274
|
- `check:boundaries` — reject Nuxt/Unhead APIs, routes, and tenant presets in core source.
|
|
275
|
+
- `check:context` — reject deferred composable/store resolution outside composition setup.
|
|
216
276
|
- `check:runtime` — verify Node SSR imports and browser/edge-safe ESM output.
|
|
217
277
|
- `check:size` — enforce root/domain/all-output gzip budgets.
|
|
218
278
|
- `check:ci` — quality gate with the V8 coverage ratchet.
|
package/dist/cart/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export { CASH_DENOMINATIONS_MAJOR, DEFAULT_ROUND_STEPS_MAJOR, ORDER_EVENTS, ORDER_WITH, buildCartLineKey, buildCashChangePresets, buildMainPaymentRequest, getCartErrorCode, getCartErrorHttpCode, getCartErrorMessage, getCashDenominationsMinor, getDefaultRoundStepsMinor, getValidationErrors, logCartError, normalizeAddress, useBonusesReconciliation, useCartAddressSync, useCartCustomerAttachment, useCartDeliveryAttachment, useCartInitialization, useCartMutation, useCartOperations, useCartQuantities, useCartRecalculation, useCartStockWatcher, useCheckoutFlow, useCheckoutSubmit, useCustomerAttach, useOnlinePaymentRetry, useOrderBonuses, useOrderChannel, useOrderDelivery, useOrderPromocode, useOrderSettings, useOrderTotal, usePaymentSelection, useRestrictedAddToCart, useRestrictionGate, useStorefrontCart, useVisibleCartVariants, variantLineKey } from '../chunk-
|
|
2
|
-
export { useCartCredentials } from '../chunk-
|
|
1
|
+
export { CASH_DENOMINATIONS_MAJOR, DEFAULT_ROUND_STEPS_MAJOR, ORDER_EVENTS, ORDER_WITH, buildCartLineKey, buildCashChangePresets, buildMainPaymentRequest, getCartErrorCode, getCartErrorHttpCode, getCartErrorMessage, getCashDenominationsMinor, getDefaultRoundStepsMinor, getValidationErrors, logCartError, normalizeAddress, useBonusesReconciliation, useCartAddressSync, useCartCustomerAttachment, useCartDeliveryAttachment, useCartInitialization, useCartMutation, useCartOperations, useCartQuantities, useCartRecalculation, useCartStockWatcher, useCheckoutFlow, useCheckoutSubmit, useCustomerAttach, useOnlinePaymentRetry, useOrderBonuses, useOrderChannel, useOrderDelivery, useOrderPromocode, useOrderSettings, useOrderTotal, usePaymentSelection, useRestrictedAddToCart, useRestrictionGate, useStorefrontCart, useVisibleCartVariants, variantLineKey } from '../chunk-E4DUFN2M.js';
|
|
2
|
+
export { useCartCredentials } from '../chunk-5YD4AIY2.js';
|
|
3
3
|
import '../chunk-Z3IW4ODZ.js';
|
|
4
|
-
import '../chunk-
|
|
4
|
+
import '../chunk-Z247QRDJ.js';
|
|
5
5
|
import '../chunk-E3G7NGCH.js';
|
|
6
6
|
import '../chunk-RO25KNM5.js';
|
|
7
7
|
import '../chunk-5QCUH3FF.js';
|
|
8
|
-
import '../chunk-
|
|
8
|
+
import '../chunk-VFMVQR6Y.js';
|
|
9
9
|
//# sourceMappingURL=index.js.map
|
|
10
10
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useCartStore, usePromotionsStore } from './chunk-
|
|
2
|
-
import { useRuntime, useAuthStore, useStoreProfileStore } from './chunk-
|
|
1
|
+
import { useCartStore, usePromotionsStore } from './chunk-Z247QRDJ.js';
|
|
2
|
+
import { useRuntime, useAuthStore, useStoreProfileStore } from './chunk-VFMVQR6Y.js';
|
|
3
3
|
import { ref } from 'vue';
|
|
4
4
|
|
|
5
5
|
var KEY_ORDER_ID = "zenky_order_id";
|
|
@@ -26,7 +26,7 @@ function useCartCredentials() {
|
|
|
26
26
|
return profileStore.city.id;
|
|
27
27
|
}
|
|
28
28
|
function getApiToken() {
|
|
29
|
-
return authStore.
|
|
29
|
+
return authStore.apiToken;
|
|
30
30
|
}
|
|
31
31
|
function buildCredentials(orderId, orderToken) {
|
|
32
32
|
const credentials = {
|
|
@@ -105,5 +105,5 @@ function usePromotionsChecker() {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
export { useCartCredentials, usePromotionsChecker };
|
|
108
|
-
//# sourceMappingURL=chunk-
|
|
109
|
-
//# sourceMappingURL=chunk-
|
|
108
|
+
//# sourceMappingURL=chunk-5YD4AIY2.js.map
|
|
109
|
+
//# sourceMappingURL=chunk-5YD4AIY2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cart/useCartCredentials.ts","../src/promotions/usePromotionsChecker.ts"],"names":[],"mappings":"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","file":"chunk-5YD4AIY2.js","sourcesContent":["import { ref, type Ref } from 'vue'\n\nimport type { Order, OrderCredentials } from '@zenky/storefront-api'\n\nimport { useRuntime } from '../ports/runtime'\nimport { useAuthStore } from '../stores/auth'\nimport { useCartStore } from '../stores/cart'\nimport { useStoreProfileStore } from '../stores/store-profile'\n\nconst KEY_ORDER_ID = 'zenky_order_id'\nconst KEY_ORDER_TOKEN = 'zenky_order_token'\nconst WEEK_SECONDS = 60 * 60 * 24 * 7\n\n// app-энум OrderStatusKind.Pending = 'pending'.\nconst ORDER_STATUS_PENDING = 'pending'\n\nexport interface CartCredentials {\n orderIdCookie: Ref<string | null>\n orderTokenCookie: Ref<string | null>\n getStoreId: () => string\n getCityId: () => string\n getApiToken: () => string | undefined\n buildCredentials: (orderId: string, orderToken: string) => OrderCredentials\n getCredentials: () => OrderCredentials\n persistCredentials: (savedOrder: Order) => void\n clearPersistedCredentials: () => void\n isOrderActive: (order: Order) => boolean\n}\n\n/**\n * Управление credentials заказа. Персистенс order-id/token — через порт `storage`\n * (ядро не знает про useCookie). Рефы инициализируются из storage, persist пишет в оба.\n */\nexport function useCartCredentials(): CartCredentials {\n const { storage } = useRuntime()\n const cartStore = useCartStore()\n const authStore = useAuthStore()\n const profileStore = useStoreProfileStore()\n\n const orderIdRef = ref<string | null>(storage.get(KEY_ORDER_ID))\n const orderTokenRef = ref<string | null>(storage.get(KEY_ORDER_TOKEN))\n\n function getStoreId(): string {\n if (!profileStore.store) {\n throw new Error('Store is not initialized.')\n }\n\n return profileStore.store.id\n }\n\n function getCityId(): string {\n if (!profileStore.city) {\n throw new Error('City is not initialized.')\n }\n\n return profileStore.city.id\n }\n\n function getApiToken(): string | undefined {\n return authStore.apiToken\n }\n\n function buildCredentials(orderId: string, orderToken: string): OrderCredentials {\n const credentials: OrderCredentials = {\n id: orderId,\n token: orderToken,\n }\n\n const apiToken = getApiToken()\n\n if (apiToken) {\n credentials.api_token = apiToken\n }\n\n return credentials\n }\n\n function getCredentials(): OrderCredentials {\n if (!cartStore.credentials) {\n throw new Error('Cart has no credentials.')\n }\n\n return buildCredentials(cartStore.credentials.id, cartStore.credentials.token)\n }\n\n function persistCredentials(savedOrder: Order): void {\n orderIdRef.value = savedOrder.id\n orderTokenRef.value = savedOrder.token\n storage.set(KEY_ORDER_ID, savedOrder.id, { maxAge: WEEK_SECONDS })\n storage.set(KEY_ORDER_TOKEN, savedOrder.token, { maxAge: WEEK_SECONDS })\n }\n\n function clearPersistedCredentials(): void {\n orderIdRef.value = null\n orderTokenRef.value = null\n storage.remove(KEY_ORDER_ID)\n storage.remove(KEY_ORDER_TOKEN)\n }\n\n function isOrderActive(existingOrder: Order): boolean {\n if (!existingOrder.status) return true\n\n return String(existingOrder.status.kind) === ORDER_STATUS_PENDING\n }\n\n return {\n orderIdCookie: orderIdRef,\n orderTokenCookie: orderTokenRef,\n getStoreId,\n getCityId,\n getApiToken,\n buildCredentials,\n getCredentials,\n persistCredentials,\n clearPersistedCredentials,\n isOrderActive,\n }\n}\n","import { useRuntime } from '../ports/runtime'\nimport { useCartCredentials } from '../cart/useCartCredentials'\nimport { useCartStore } from '../stores/cart'\nimport { usePromotionsStore } from '../stores/promotions'\nimport { useStoreProfileStore } from '../stores/store-profile'\n\nexport interface PromotionsChecker {\n dispatchCheck: () => Promise<void>\n}\n\n/** Таймаут — если WS не ответил, сбросить флаг checking. */\nconst WS_RESPONSE_TIMEOUT_MS = 5000\n\n/**\n * Проверка промо-акций. Вызывает dispatchPromotionsChecker после изменения корзины.\n * Результат приходит через WebSocket (обрабатывается в useOrderChannel).\n *\n * Резолвить синхронно в setup, а после await вызывать только `dispatchCheck` — как и\n * любой композабл ядра, см. раздел «Call composables and stores synchronously in setup»\n * в README.\n *\n * ```ts\n * const { dispatchCheck } = usePromotionsChecker()\n *\n * async function addGift() {\n * await addVariantToOrder()\n * dispatchCheck()\n * }\n * ```\n */\nexport function usePromotionsChecker(): PromotionsChecker {\n const { sdk, events } = useRuntime()\n const cartStore = useCartStore()\n const profileStore = useStoreProfileStore()\n const promotionsStore = usePromotionsStore()\n const credentials = useCartCredentials()\n\n async function dispatchCheck(): Promise<void> {\n if (!cartStore.hasOrder || promotionsStore.checking) return\n\n const storeId = profileStore.store?.id\n if (!storeId) return\n\n promotionsStore.setChecking(true)\n promotionsStore.clearRewards() // Очистить старые — WS заново наполнит актуальные\n events?.get()?.promotionsCheckerStarted({ order: cartStore.order })\n\n try {\n const creds = credentials.getCredentials()\n await sdk.orders.dispatchPromotionsChecker(storeId, creds)\n\n setTimeout(() => {\n if (promotionsStore.checking) promotionsStore.setChecking(false)\n }, WS_RESPONSE_TIMEOUT_MS)\n } catch (e: unknown) {\n console.error('[promotions] check failed', e)\n promotionsStore.setChecking(false)\n }\n }\n\n return { dispatchCheck }\n}\n"]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { useCartCredentials, usePromotionsChecker } from './chunk-
|
|
1
|
+
import { useCartCredentials, usePromotionsChecker } from './chunk-5YD4AIY2.js';
|
|
2
2
|
import { useCatalogStore } from './chunk-Z3IW4ODZ.js';
|
|
3
|
-
import { useCartStore, useOrderSettingsStore, usePromotionsStore } from './chunk-
|
|
3
|
+
import { useCartStore, useOrderSettingsStore, usePromotionsStore } from './chunk-Z247QRDJ.js';
|
|
4
4
|
import { getRemoteCatalog } from './chunk-E3G7NGCH.js';
|
|
5
5
|
import { minorToMajor, majorToMinor } from './chunk-RO25KNM5.js';
|
|
6
6
|
import { createRuntimeState } from './chunk-5QCUH3FF.js';
|
|
7
|
-
import { useRuntime, useStoreProfileStore, useAuthStore } from './chunk-
|
|
7
|
+
import { useRuntime, useStoreProfileStore, useAuthStore } from './chunk-VFMVQR6Y.js';
|
|
8
8
|
import { PaymentMethod, OrderAuthenticationMethod, DeliveryMethod, OrderCartCheckerResultAction, RecaptchaAction } from '@zenky/storefront-api';
|
|
9
9
|
import { ref, computed, watch, watchEffect, getCurrentScope, onScopeDispose, toValue } from 'vue';
|
|
10
10
|
import { storeToRefs } from 'pinia';
|
|
@@ -98,17 +98,24 @@ var MAX_LOG_DEPTH = 6;
|
|
|
98
98
|
var MAX_ARRAY_ITEMS = 25;
|
|
99
99
|
var MAX_OBJECT_KEYS = 50;
|
|
100
100
|
var SENSITIVE_KEY_PARTS = [
|
|
101
|
+
"address",
|
|
101
102
|
"authorization",
|
|
103
|
+
"checkouturl",
|
|
102
104
|
"cookie",
|
|
103
105
|
"credential",
|
|
106
|
+
"email",
|
|
104
107
|
"password",
|
|
108
|
+
"paymentlink",
|
|
109
|
+
"paymentpageurl",
|
|
110
|
+
"phone",
|
|
105
111
|
"recaptcha",
|
|
112
|
+
"redirecturl",
|
|
106
113
|
"secret",
|
|
107
114
|
"token"
|
|
108
115
|
];
|
|
109
116
|
var SENSITIVE_EXACT_KEYS = /* @__PURE__ */ new Set(["cvc", "cvv", "otp", "pan", "pin"]);
|
|
110
|
-
var SENSITIVE_ASSIGNMENT = /((?:authorization|cookie|password|recaptcha|secret|(?:api|access|auth|card|order|refresh)[_-]?token|token)\s*[=:]\s*["']?)([^\s,"';&}\]]+)/gi;
|
|
111
|
-
var SENSITIVE_QUERY_PARAM = /([?&#](?:authorization|password|recaptcha|secret|(?:api|access|auth|card|order|refresh)[_-]?token|token)=)([^&#\s]+)/gi;
|
|
117
|
+
var SENSITIVE_ASSIGNMENT = /((?:address|authorization|cookie|email|password|phone|recaptcha|secret|(?:checkout|redirect)[_-]?url|payment(?:[_-]?page)?[_-]?(?:link|url)|(?:api|access|auth|card|order|refresh)[_-]?token|token)\s*[=:]\s*["']?)([^\s,"';&}\]]+)/gi;
|
|
118
|
+
var SENSITIVE_QUERY_PARAM = /([?&#](?:address|authorization|email|password|phone|recaptcha|secret|(?:checkout|redirect)[_-]?url|payment(?:[_-]?page)?[_-]?(?:link|url)|(?:api|access|auth|card|order|refresh)[_-]?token|token)=)([^&#\s]+)/gi;
|
|
112
119
|
var BEARER_TOKEN = /(bearer\s+)[a-z0-9._~+/=-]+/gi;
|
|
113
120
|
function isSensitiveKey(key) {
|
|
114
121
|
const normalized = key.replace(/[^a-z0-9]/gi, "").toLowerCase();
|
|
@@ -636,7 +643,7 @@ function usePaymentSelection() {
|
|
|
636
643
|
const credentials = useCartCredentials();
|
|
637
644
|
const cartStore = useCartStore();
|
|
638
645
|
const profileStore = useStoreProfileStore();
|
|
639
|
-
const { fetchTotal } = useOrderTotal();
|
|
646
|
+
const { fetchTotal, total } = useOrderTotal();
|
|
640
647
|
const { run: runMutation } = useCartMutation();
|
|
641
648
|
async function sendPayments(payments, debounce = PAYMENT_DEBOUNCE_MS) {
|
|
642
649
|
const storeId = profileStore.store?.id;
|
|
@@ -687,7 +694,6 @@ function usePaymentSelection() {
|
|
|
687
694
|
}
|
|
688
695
|
function getCurrentBonusesPayment() {
|
|
689
696
|
if (!cartStore.hasBonusesApplied) return null;
|
|
690
|
-
const { total } = useOrderTotal();
|
|
691
697
|
const bonusPayment = total.value?.payments?.find(
|
|
692
698
|
(p) => p.method === PaymentMethod.Bonuses
|
|
693
699
|
);
|
|
@@ -1154,20 +1160,9 @@ function useOrderDelivery(deps = {}) {
|
|
|
1154
1160
|
() => {
|
|
1155
1161
|
const storeId = credentials.getStoreId();
|
|
1156
1162
|
const orderCredentials = credentials.getCredentials();
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
}
|
|
1160
|
-
const path = sdk.client.getStoreUrl(
|
|
1161
|
-
storeId,
|
|
1162
|
-
`/orders/${orderCredentials.id}/checkout/delivery/time`,
|
|
1163
|
-
{ token: orderCredentials.token }
|
|
1164
|
-
);
|
|
1165
|
-
return sdk.client.request(
|
|
1166
|
-
"POST",
|
|
1167
|
-
path,
|
|
1168
|
-
{ deliver_at: deliverAt },
|
|
1169
|
-
orderCredentials.api_token ?? null
|
|
1170
|
-
);
|
|
1163
|
+
return sdk.orders.setOrderDeliveryTime(storeId, orderCredentials, {
|
|
1164
|
+
deliver_at: deliverAt
|
|
1165
|
+
});
|
|
1171
1166
|
},
|
|
1172
1167
|
{ deliverAt },
|
|
1173
1168
|
options.awaitSettle ?? false
|
|
@@ -1979,12 +1974,10 @@ function useRestrictedAddToCart() {
|
|
|
1979
1974
|
if (!storeId || !cityId) return true;
|
|
1980
1975
|
let blocking = [];
|
|
1981
1976
|
try {
|
|
1982
|
-
const
|
|
1983
|
-
city_id: cityId
|
|
1984
|
-
stock_id: profileStore.stock?.id ?? void 0
|
|
1977
|
+
const restrictions = await sdk.products.getProductRestrictions(storeId, product.id, {
|
|
1978
|
+
city_id: cityId
|
|
1985
1979
|
});
|
|
1986
|
-
|
|
1987
|
-
blocking = (response?.data ?? []).filter((item) => item.is_blocking);
|
|
1980
|
+
blocking = (restrictions ?? []).filter((item) => item.is_blocking);
|
|
1988
1981
|
} catch (error) {
|
|
1989
1982
|
logCartError({ scope: "restrictions-check", context: { productId: product.id } }, error);
|
|
1990
1983
|
return true;
|
|
@@ -2014,5 +2007,5 @@ function useVisibleCartVariants() {
|
|
|
2014
2007
|
}
|
|
2015
2008
|
|
|
2016
2009
|
export { CASH_DENOMINATIONS_MAJOR, DEFAULT_ROUND_STEPS_MAJOR, ORDER_EVENTS, ORDER_WITH, buildCartLineKey, buildCashChangePresets, buildMainPaymentRequest, getCartErrorCode, getCartErrorHttpCode, getCartErrorMessage, getCashDenominationsMinor, getDefaultRoundStepsMinor, getValidationErrors, logCartError, normalizeAddress, useBonusesReconciliation, useCartAddressSync, useCartCustomerAttachment, useCartDeliveryAttachment, useCartInitialization, useCartMutation, useCartOperations, useCartQuantities, useCartRecalculation, useCartStockWatcher, useCheckoutFlow, useCheckoutSubmit, useCustomerAttach, useOnlinePaymentRetry, useOrderBonuses, useOrderChannel, useOrderDelivery, useOrderPromocode, useOrderSettings, useOrderTotal, usePaymentSelection, useRestrictedAddToCart, useRestrictionGate, useStorefrontCart, useVisibleCartVariants, variantLineKey };
|
|
2017
|
-
//# sourceMappingURL=chunk-
|
|
2018
|
-
//# sourceMappingURL=chunk-
|
|
2010
|
+
//# sourceMappingURL=chunk-E4DUFN2M.js.map
|
|
2011
|
+
//# sourceMappingURL=chunk-E4DUFN2M.js.map
|