@zenky/storefront-vue 0.10.9 → 0.10.11
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 +162 -0
- package/README.md +1 -1
- package/dist/auth/index.d.ts +14 -0
- package/dist/auth/index.js +4 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/cart/index.d.ts +3 -28
- package/dist/cart/index.js +9 -7
- package/dist/catalog/index.d.ts +5 -3
- package/dist/catalog/index.js +2 -2
- package/dist/catalogEntity-DgrPsJpf.d.ts +44 -0
- package/dist/{chunk-AVES4WJZ.js → chunk-5CNL24PI.js} +11 -108
- package/dist/chunk-5CNL24PI.js.map +1 -0
- package/dist/{chunk-RF4ML3Q3.js → chunk-6FVXAF7L.js} +5 -4
- package/dist/chunk-6FVXAF7L.js.map +1 -0
- package/dist/chunk-AK4276ND.js +67 -0
- package/dist/chunk-AK4276ND.js.map +1 -0
- package/dist/{chunk-KFCO46RB.js → chunk-FS2UNPTY.js} +2 -2
- package/dist/chunk-FS2UNPTY.js.map +1 -0
- package/dist/chunk-IOYYCA75.js +52 -0
- package/dist/chunk-IOYYCA75.js.map +1 -0
- package/dist/chunk-KX7KXN3W.js +529 -0
- package/dist/chunk-KX7KXN3W.js.map +1 -0
- package/dist/{chunk-6QCFHSLX.js → chunk-NSOIL7PW.js} +2 -2
- package/dist/chunk-NSOIL7PW.js.map +1 -0
- package/dist/{chunk-RK5CGOM7.js → chunk-OBNMXLJO.js} +19 -3
- package/dist/chunk-OBNMXLJO.js.map +1 -0
- package/dist/{chunk-GXDTRTUT.js → chunk-RURXGVWW.js} +35 -6
- package/dist/chunk-RURXGVWW.js.map +1 -0
- package/dist/{chunk-XULHV6SS.js → chunk-TE2QPH74.js} +3 -3
- package/dist/{chunk-XULHV6SS.js.map → chunk-TE2QPH74.js.map} +1 -1
- package/dist/chunk-TE42OCFK.js +102 -0
- package/dist/chunk-TE42OCFK.js.map +1 -0
- package/dist/{chunk-GILJFP55.js → chunk-VTZYJ6OZ.js} +2 -2
- package/dist/chunk-VTZYJ6OZ.js.map +1 -0
- package/dist/{chunk-46FNHMWC.js → chunk-W43D7JYV.js} +5 -4
- package/dist/chunk-W43D7JYV.js.map +1 -0
- package/dist/{chunk-QZ3S3NN3.js → chunk-WTZXTBF6.js} +3 -47
- package/dist/chunk-WTZXTBF6.js.map +1 -0
- package/dist/index.d.ts +6 -3
- package/dist/index.js +16 -13
- package/dist/ports/index.d.ts +1 -1
- package/dist/ports/index.js +1 -1
- package/dist/products/index.d.ts +4 -3
- package/dist/products/index.js +4 -3
- package/dist/promotions/index.js +4 -3
- package/dist/seo/index.d.ts +5 -7
- package/dist/seo/index.js +16 -9
- package/dist/seo/index.js.map +1 -1
- package/dist/stores/index.d.ts +60 -4
- package/dist/stores/index.js +7 -4
- package/dist/types-CXm2F6Hz.d.ts +55 -0
- package/dist/useCheckoutSubmit-Be-lQd60.d.ts +30 -0
- package/dist/utils/index.d.ts +6 -1
- package/dist/utils/index.js +1 -1
- package/docs/architecture.md +81 -4
- package/package.json +7 -3
- package/dist/chunk-46FNHMWC.js.map +0 -1
- package/dist/chunk-6QCFHSLX.js.map +0 -1
- package/dist/chunk-AVES4WJZ.js.map +0 -1
- package/dist/chunk-FXKG5TFQ.js +0 -38
- package/dist/chunk-FXKG5TFQ.js.map +0 -1
- package/dist/chunk-GILJFP55.js.map +0 -1
- package/dist/chunk-GXDTRTUT.js.map +0 -1
- package/dist/chunk-KFCO46RB.js.map +0 -1
- package/dist/chunk-QZ3S3NN3.js.map +0 -1
- package/dist/chunk-RF4ML3Q3.js.map +0 -1
- package/dist/chunk-RK5CGOM7.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,11 +8,173 @@ All notable changes to this project are documented in this file. The format foll
|
|
|
8
8
|
|
|
9
9
|
### Added
|
|
10
10
|
|
|
11
|
+
- `groupScheduleDays` (`/utils`) — collapses consecutive days that share the same hours
|
|
12
|
+
into one row, so a location prints "пн — пт: 10:00-19:00" instead of five identical
|
|
13
|
+
lines; a page listing a chain's pickup points would otherwise print seven day-rows per
|
|
14
|
+
location. Day abbreviations come from `Intl`, not from slicing the long name — Russian
|
|
15
|
+
"понедельник" abbreviates to "пн", not "по" — and are returned in the locale's own
|
|
16
|
+
casing, since capitalizing them here corrupts scripts such as Georgian. Intl formatters
|
|
17
|
+
are memoized: constructing one is the expensive part, and a seven-location page built
|
|
18
|
+
roughly a hundred of them.
|
|
19
|
+
- `catalogItemEntity` / `isRenderableCatalogItem` (`/catalog`) — resolve a static catalog
|
|
20
|
+
item to a discriminated `category | collection` entity, with `id` and `name` lifted out
|
|
21
|
+
so a consumer can key, title, and scroll-spy a section without branching. Manual
|
|
22
|
+
catalogs can now contain product collections, which ship a `products_collection` object
|
|
23
|
+
instead of `category`. The entity is resolved by which object is present rather than by
|
|
24
|
+
`type`, because the payload (`products_collection`) and `@zenky/storefront-api@1.0.2`
|
|
25
|
+
(`collection`) disagree on the discriminator; both spellings are read. Items whose
|
|
26
|
+
entity has no id are treated as malformed and resolve to `null`.
|
|
27
|
+
- `StaticCatalogItem` / `StaticRemoteCatalog` (`/catalog`) — the catalog shapes as the
|
|
28
|
+
payload actually ships them. The SDK types predate manual catalogs: they omit
|
|
29
|
+
`products_collection` and `catalog_id`, the latter already returned by the live store
|
|
30
|
+
profile (`null` for automatic catalogs, filled for manual ones).
|
|
31
|
+
- `buildCollectionSchemas` (`/seo`) — JSON-LD for a products collection page.
|
|
11
32
|
- `useProductList` — fetches a page of products for a category or collection, with the
|
|
12
33
|
include list that keeps per-stock pricing working (`variants.prices`). Three call sites
|
|
13
34
|
in the consuming app built this fetch by hand and had drifted apart; one of them was
|
|
14
35
|
missing `variants.prices` and silently showed every product's store-wide price instead
|
|
15
36
|
of the price of the stock the customer was actually browsing.
|
|
37
|
+
- `authFlow` store (`zenky-auth-flow`, new `/auth` subpath) — the registration/login/
|
|
38
|
+
password-reset step machine (`checkPhone`/`login`/`register`/`confirmRegistration`/
|
|
39
|
+
`resendCode`/`dispatchReset`/`resetPassword`), moved out of the consuming app, with
|
|
40
|
+
confirmation-channel selection added on top (SMS/Telegram/WhatsApp). `register`/
|
|
41
|
+
`resendCode`/`dispatchReset` gate on a channel picker when the store has 2+ channels
|
|
42
|
+
enabled (`store.settings.authentication`), retry on `auth.otp_request.failed` by
|
|
43
|
+
falling back to another enabled channel — the failed channel is exposed as
|
|
44
|
+
`lastFailedChannel` so the UI can hide/disable it on the retry. `SelectableConfirmationChannel`
|
|
45
|
+
(`ConfirmationChannel` minus the response-only `call`) types everything the user can
|
|
46
|
+
actually pick — `availableChannels`, `selectChannel`, `lastFailedChannel`. Requires
|
|
47
|
+
`@zenky/storefront-api@^1.1.0` for `ConfirmationMethod.Telegram/WhatsApp` and
|
|
48
|
+
`RequestedConfirmationMethod`. Recaptcha is a parameter on every action that dispatches
|
|
49
|
+
an OTP, including `checkPhone`/`login`'s internal auto-resend
|
|
50
|
+
(`RecaptchaPayloadProvider`, reused from `cart/useCheckoutSubmit` — not a new port,
|
|
51
|
+
same pattern as checkout submission). All user-facing error copy goes through the
|
|
52
|
+
`messages` port instead of hardcoded Russian strings — 8 new `StorefrontMessageKey`
|
|
53
|
+
entries (`auth.checkPhoneFailed`, `auth.invalidPassword`, `auth.registerFailed`,
|
|
54
|
+
`auth.invalidCode`, `auth.resendCodeFailed`, `auth.dispatchResetFailed`,
|
|
55
|
+
`auth.resetPasswordFailed`, `auth.otpUnavailable`). `handleAuthError` now takes a
|
|
56
|
+
`StorefrontMessageKey` fallback instead of a ready-made string, so the core makes no
|
|
57
|
+
assumption about locale — text and translation stay entirely on the consumer's side.
|
|
58
|
+
Every action is guarded against out-of-order responses with an operation-revision
|
|
59
|
+
counter: each top-level call (`checkPhone`, `login`, `register`, `confirmRegistration`,
|
|
60
|
+
`resendCode`, `dispatchReset`, `resetPassword`, `selectChannel`) opens a new revision
|
|
61
|
+
that a later call — a fresh attempt, `reset()`, any `goTo*` navigation including
|
|
62
|
+
`Back`, or `changeChannel()` — invalidates; after every `await` (recaptcha included)
|
|
63
|
+
the store checks its revision is still current before touching
|
|
64
|
+
`currentStep`/`error`/`loading`/etc., so a slow response from an abandoned attempt can
|
|
65
|
+
no longer land on top of a newer one. A nested call that's a continuation of the same
|
|
66
|
+
user attempt (`checkPhone`/`login`'s auto-resend, `register`'s 0-channel `login`
|
|
67
|
+
fallback, `selectChannel`'s dispatch) receives the parent's revision instead of
|
|
68
|
+
opening its own, so it isn't invalidated by its own caller. Invalidation isn't limited
|
|
69
|
+
to explicit actions: `phone`/`countryCode` invalidate on direct assignment too (a
|
|
70
|
+
`customRef`, transparent to `v-model`), since both are typically bound straight to an
|
|
71
|
+
input — a user can edit the field without re-submitting while a request for the old
|
|
72
|
+
value is still in flight. Every value read after an `await` (`phone`, `country`,
|
|
73
|
+
recaptcha action, the channel a failed OTP dispatch is attributed to) is a snapshot
|
|
74
|
+
taken before the first `await`, not a live read, so a value the user changes while a
|
|
75
|
+
request is in flight can't leak into how its response is handled. Both invalidating
|
|
76
|
+
helpers — `beginOperation()` for a fresh top-level attempt, `cancelPendingOperation()`
|
|
77
|
+
where nothing new replaces what's cancelled (`Back`, `reset()`, `changeChannel()`) —
|
|
78
|
+
clear `loading` themselves rather than assuming "the next line" will: for most actions
|
|
79
|
+
the next line isn't `loading.value = true` but a channel gate or a `storeId` check
|
|
80
|
+
that can `return` first, and the request's own `finally` has just lost the right to
|
|
81
|
+
clear `loading` by the same guard. An action that does reach its request sets
|
|
82
|
+
`loading` back to `true` a few lines later, in the same synchronous stretch, so this
|
|
83
|
+
reads as one transition, not a flicker.
|
|
84
|
+
|
|
85
|
+
Covered by 14 dedicated tests: a stale response losing to a newer one; a stale
|
|
86
|
+
`finally` not clearing a newer call's `loading`; the same class of bug in two more
|
|
87
|
+
shapes — every `goTo*`/`changeChannel()` invalidating the revision without clearing
|
|
88
|
+
`loading`, and a fresh action doing the same on its own early return, both leaving
|
|
89
|
+
`loading` stuck since the cancelled request's `finally` had already lost the right to
|
|
90
|
+
touch it; a stale recaptcha not overriding a channel picked after it; `Back` during a
|
|
91
|
+
dispatch neither landing the user back on `Code` nor leaving `loading` stuck; editing
|
|
92
|
+
`phone` without resubmitting neither applying a stale response nor letting a nested
|
|
93
|
+
auto-resend fire against the new number; a directly-assigned `confirmationMethod` (no
|
|
94
|
+
`customRef` on it — the legitimate paths already invalidate) not corrupting
|
|
95
|
+
`lastFailedChannel` on an OTP failure; and firing every remaining top-level action
|
|
96
|
+
twice to confirm the `loading` guard holds everywhere, not just where it was first
|
|
97
|
+
found broken.
|
|
98
|
+
|
|
99
|
+
### Changed
|
|
100
|
+
|
|
101
|
+
- `useCatalogStore` (`catalog`, `initCatalog`), `findProductInCatalog`, and the
|
|
102
|
+
`catalogItem` on `CatalogProductMatch` are typed `StaticCatalogItem` instead of the
|
|
103
|
+
SDK's `CatalogItem`, so the collection fields are visible on what the store holds.
|
|
104
|
+
`CatalogItem` values remain assignable, so passing catalog data in is unaffected; a
|
|
105
|
+
consumer that annotates a value read back out of the store as `CatalogItem[]` needs to
|
|
106
|
+
widen that annotation.
|
|
107
|
+
- `getRemoteCatalog` returns `StaticRemoteCatalog`, so `catalog_id` is typed.
|
|
108
|
+
|
|
109
|
+
### Fixed
|
|
110
|
+
|
|
111
|
+
- `authFlow.goToReset()` no longer confuses the resend timer between phone numbers.
|
|
112
|
+
`resendTimerEndsAt`/`codeContext` are shared, request-scoped refs, and were only
|
|
113
|
+
cleared by a full `reset()` — checking a second phone number after abandoning a
|
|
114
|
+
password-reset flow for a first one could land the second number straight on the
|
|
115
|
+
confirmation-code step for a code that was never actually sent to it. `checkPhone()`
|
|
116
|
+
now clears both at the start of every phone check, and `goToReset()` only trusts the
|
|
117
|
+
timer when `codeContext` is already `Reset`.
|
|
118
|
+
- `authFlow` error messages for non-`ZenkyError` failures (network drop, CORS, an
|
|
119
|
+
ad-blocker) no longer leak the raw `Error.message` to the user — they fall through to
|
|
120
|
+
the localized `fallback` string, same as `cart`'s error handling already did.
|
|
121
|
+
- `authFlow.selectChannel()` no longer clears `channelIntent` before the dispatch it
|
|
122
|
+
triggers actually succeeds. Any failure other than `auth.otp_request.failed`
|
|
123
|
+
(validation, network) left `currentStep` on `Channel` with `channelIntent` already
|
|
124
|
+
`null` — picking a channel again silently did nothing, and `goToChannelBack()` sent
|
|
125
|
+
the user to `Phone` instead of back to `Register`/`Code`/`Reset`. `channelIntent` is
|
|
126
|
+
now cleared by `register`/`resendCode`/`dispatchReset` themselves, only on real
|
|
127
|
+
success.
|
|
128
|
+
- `authFlow.resendCode()` now transitions to `AUTH_STEP.Code` itself when the dispatch it
|
|
129
|
+
just ran was reached via the channel picker — previously it never advanced past
|
|
130
|
+
`Channel` on that path (only `checkPhone`/`login`'s direct calls advanced the step),
|
|
131
|
+
so picking a channel for a resend silently left the user stuck on the picker after a
|
|
132
|
+
successful send.
|
|
133
|
+
- `authFlow.checkPhone()`/`login()`'s internal auto-resend (registered-but-unconfirmed,
|
|
134
|
+
and the `ConfirmationRequired` branch of `login`) no longer dispatches the OTP with a
|
|
135
|
+
no-op recaptcha provider. Both now take `getRecaptchaPayload` and forward it — for
|
|
136
|
+
stores with 2+ channels this was invisible (the real provider arrives later via
|
|
137
|
+
`selectChannel`), but for a single-channel store the request went out with no
|
|
138
|
+
recaptcha token at all.
|
|
139
|
+
- `authFlow.checkPhone()` now clears the full phone-scoped state (`confirmationMethod`,
|
|
140
|
+
`pendingPassword`, `channelIntent`, `resetCode`, `registerCode` — previously only
|
|
141
|
+
`codeContext`/`resendTimerEndsAt`) at the start of every check. Backing out of a flow
|
|
142
|
+
for one phone number and checking a different one could otherwise carry over the
|
|
143
|
+
first number's selected channel or pending password.
|
|
144
|
+
- `authFlow.channelIntent` is now part of the store's public `$state` (returned from
|
|
145
|
+
`defineStore`'s setup, per the dts rule) instead of a closure-local ref. Pinia setup
|
|
146
|
+
stores only serialize/hydrate what's returned — if the server happened to render with
|
|
147
|
+
`currentStep === 'channel'`, the client would hydrate that step with `channelIntent`
|
|
148
|
+
reset to `null`, making the picker a no-op and `goToChannelBack()` misroute.
|
|
149
|
+
- `handleOtpDispatchError()` no longer force-casts `confirmationMethod.value` into
|
|
150
|
+
`lastFailedChannel`. The cast assumed the value was always the channel *just
|
|
151
|
+
requested*, which holds right after an explicit `selectChannel()` pick but not when
|
|
152
|
+
`confirmationMethod` was inherited from an *earlier* successful dispatch whose
|
|
153
|
+
response (`AuthConfirmationStatus.method`, the SDK's full `ConfirmationMethod`, not
|
|
154
|
+
the request-only `RequestedConfirmationMethod`) came back as the legacy `Call` value —
|
|
155
|
+
a real backend fallback (dial in, code is the caller ID's last 4 digits), not a
|
|
156
|
+
hypothetical. A later failed attempt would then have silently stored `'call'` into a
|
|
157
|
+
field typed to exclude it, making the "hide the channel that just failed" UX a no-op
|
|
158
|
+
for that case. Now a runtime check keeps `Call` out instead of asserting it away.
|
|
159
|
+
- `authFlow.changeChannel()` now invalidates the pending operation revision. Without it,
|
|
160
|
+
a dispatch still in flight when the user resets their channel choice could resolve
|
|
161
|
+
afterward and resurrect the very channel they just backed out of (its success handler
|
|
162
|
+
writes `confirmationMethod` from the response, unconditionally).
|
|
163
|
+
|
|
164
|
+
### Security
|
|
165
|
+
|
|
166
|
+
- `authFlow.pendingPassword` is cleared immediately after a successful `register`
|
|
167
|
+
(0-channel edge case) or `confirmRegistration`, instead of lingering until the next
|
|
168
|
+
full `reset()`. It's a raw, publicly-exposed `Ref<string>` on the store — leaving a
|
|
169
|
+
plaintext password in reactive state after auth succeeds was an unnecessary window,
|
|
170
|
+
particularly for an SSR consumer where Pinia state can end up in the hydration
|
|
171
|
+
payload.
|
|
172
|
+
- `authFlow.register()`'s 0-channel edge case (`confirmation_required: false`) no longer
|
|
173
|
+
reports success while writing an empty string as the auth token.
|
|
174
|
+
`AuthConfirmationStatus` (register's response) never carries a token — `authStore`
|
|
175
|
+
treats an empty token as unauthenticated — so a caller that closed the auth UI on
|
|
176
|
+
`register()` returning `true` left the user believing they were signed in when they
|
|
177
|
+
weren't. This path now performs a real `login()` with the same password instead.
|
|
16
178
|
|
|
17
179
|
## 0.10.7 - 2026-08-02
|
|
18
180
|
|
package/README.md
CHANGED
|
@@ -181,7 +181,7 @@ import { buildProductSchema, buildOgTags } from '@zenky/storefront-vue/seo'
|
|
|
181
181
|
import { usePaginatedList } from '@zenky/storefront-vue/pagination'
|
|
182
182
|
```
|
|
183
183
|
|
|
184
|
-
Available subpaths: `ports`, `money`, `utils`, `theme`, `stores`, `products`, `catalog`, `cart`, `order`, `promotions`, `seo`, `pagination`, `snippets`, `website-settings`.
|
|
184
|
+
Available subpaths: `ports`, `money`, `utils`, `theme`, `stores`, `products`, `catalog`, `cart`, `order`, `promotions`, `seo`, `pagination`, `snippets`, `website-settings`, `auth`.
|
|
185
185
|
|
|
186
186
|
Routing, tenant theme presets, localized copy, header/footer composition, and conversion to
|
|
187
187
|
framework-specific head records belong to the consumer. Core SEO builders return plain
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { S as SelectableConfirmationChannel } from '../types-CXm2F6Hz.js';
|
|
2
|
+
export { A as AUTH_STEP, a as AuthStep, C as CHANNEL_INTENT, b as CODE_CONTEXT, c as CONFIRMATION_CHANNEL, d as CONFIRMATION_CHANNEL_ORDER, e as ChannelIntent, f as CodeContext, g as ConfirmationChannel, t as toConfirmationChannel, h as toRequestedMethod } from '../types-CXm2F6Hz.js';
|
|
3
|
+
import { ComputedRef } from 'vue';
|
|
4
|
+
import '@zenky/storefront-api';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Доступные каналы подтверждения для текущего магазина, в порядке показа
|
|
8
|
+
* (Telegram, WhatsApp, SMS). Источник — `store.settings.authentication`.
|
|
9
|
+
* Логика "≥2 → показать выбор, 1 → использовать сразу, 0 → method не передаём" —
|
|
10
|
+
* в вызывающем коде, эта функция отдаёт только список.
|
|
11
|
+
*/
|
|
12
|
+
declare function useAvailableConfirmationChannels(): ComputedRef<SelectableConfirmationChannel[]>;
|
|
13
|
+
|
|
14
|
+
export { SelectableConfirmationChannel, useAvailableConfirmationChannels };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { AUTH_STEP, CHANNEL_INTENT, CODE_CONTEXT, CONFIRMATION_CHANNEL, CONFIRMATION_CHANNEL_ORDER, toConfirmationChannel, toRequestedMethod, useAvailableConfirmationChannels } from '../chunk-AK4276ND.js';
|
|
2
|
+
import '../chunk-IOYYCA75.js';
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
package/dist/cart/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { ProductModifiersRequest, OrderProductVariant, PaymentMethod, OrderPaymentMethodRequest, OrderAuthenticationMethod, OrderCredentials, Order, OrderCheckoutTotal, OrderSettings, OrderPaymentMethod, OrderDeliveryMethod, InclusionRequest, ZenkyStorefront, SetOrderCustomerRequest, SetOrderDeliveryRequest, OrderPromocode, RecommendationsBlock,
|
|
1
|
+
import { ProductModifiersRequest, OrderProductVariant, PaymentMethod, OrderPaymentMethodRequest, OrderAuthenticationMethod, OrderCredentials, Order, OrderCheckoutTotal, OrderSettings, OrderPaymentMethod, OrderDeliveryMethod, InclusionRequest, ZenkyStorefront, SetOrderCustomerRequest, SetOrderDeliveryRequest, OrderPromocode, RecommendationsBlock, EvaluatedRestriction, Media, Product } from '@zenky/storefront-api';
|
|
2
2
|
import { ComputedRef, MaybeRefOrGetter, Ref } from 'vue';
|
|
3
3
|
import { ActivityReporter, Notifier, Result } from '../ports/index.js';
|
|
4
|
+
export { C as CheckoutSubmitComposable, R as RecaptchaPayloadProvider, u as useCheckoutSubmit } from '../useCheckoutSubmit-Be-lQd60.js';
|
|
4
5
|
import '@zenky/integrations-sdk';
|
|
5
6
|
|
|
6
7
|
/** WebSocket events for the order channel */
|
|
@@ -513,32 +514,6 @@ interface CartOperations {
|
|
|
513
514
|
}
|
|
514
515
|
declare function useCartOperations(credentials: CartCredentials, initialization: CartInitialization, sdk: ZenkyStorefront, deps: CartDependencies): CartOperations;
|
|
515
516
|
|
|
516
|
-
/** reCAPTCHA payload provider (implemented by the consumer app — Google reCAPTCHA v3). */
|
|
517
|
-
type RecaptchaPayloadProvider = (action: RecaptchaAction) => Promise<{
|
|
518
|
-
token: string;
|
|
519
|
-
} | undefined>;
|
|
520
|
-
interface CheckoutSubmitComposable {
|
|
521
|
-
/** Last `checkoutOrder` result — needed by the UI (ConfirmationModal / online redirect) */
|
|
522
|
-
result: Ref<OrderCheckoutResult | null>;
|
|
523
|
-
submitting: Ref<boolean>;
|
|
524
|
-
/**
|
|
525
|
-
* Collects `OrderCheckoutRequest` from `cartStore` (notes + persons_count).
|
|
526
|
-
* Returns `OrderCheckoutResult` with confirmation/online_payment flags.
|
|
527
|
-
*/
|
|
528
|
-
submit: () => Promise<OrderCheckoutResult | null>;
|
|
529
|
-
/** Confirm the SMS code (after checkoutOrder returned confirmation.required) */
|
|
530
|
-
confirm: (code: string) => Promise<boolean>;
|
|
531
|
-
/** Resend the code (with backoff — the UI is responsible for that) */
|
|
532
|
-
resendCode: () => Promise<boolean>;
|
|
533
|
-
cancel: () => Promise<boolean>;
|
|
534
|
-
}
|
|
535
|
-
/**
|
|
536
|
-
* Final order submit + SMS confirmation.
|
|
537
|
-
*
|
|
538
|
-
* @param getRecaptchaPayload reCAPTCHA token provider (app-specific, injected).
|
|
539
|
-
*/
|
|
540
|
-
declare function useCheckoutSubmit(getRecaptchaPayload: RecaptchaPayloadProvider): CheckoutSubmitComposable;
|
|
541
|
-
|
|
542
517
|
declare function useOrderChannel(): void;
|
|
543
518
|
|
|
544
519
|
interface StorefrontCart {
|
|
@@ -592,4 +567,4 @@ declare function useRestrictedAddToCart(): RestrictedAddToCart;
|
|
|
592
567
|
*/
|
|
593
568
|
declare function useVisibleCartVariants(): ComputedRef<OrderProductVariant[]>;
|
|
594
569
|
|
|
595
|
-
export { type AttachedCustomerCache, type BonusesReconciliation, type BonusesReconciliationDeps, CASH_DENOMINATIONS_MAJOR, type CachedCustomerView, type CartCredentials, type CartDependencies, type CartErrorScope, type CartInitialization, type CartItemRequest, type CartLineKeyParams, type CartMutationComposable, type CartOperations, type CartQuantities, type CartRecalculation, type CartRecalculationDeps, type CartStockWatcher, type CashChangePresetsOptions, type CheckoutFlowFlags, type
|
|
570
|
+
export { type AttachedCustomerCache, type BonusesReconciliation, type BonusesReconciliationDeps, CASH_DENOMINATIONS_MAJOR, type CachedCustomerView, type CartCredentials, type CartDependencies, type CartErrorScope, type CartInitialization, type CartItemRequest, type CartLineKeyParams, type CartMutationComposable, type CartOperations, type CartQuantities, type CartRecalculation, type CartRecalculationDeps, type CartStockWatcher, type CashChangePresetsOptions, type CheckoutFlowFlags, type CustomerAttachComposable, DEFAULT_ROUND_STEPS_MAJOR, type MainPaymentRequestParams, type MutationKind, type MutationOptions, ORDER_EVENTS, ORDER_WITH, type OrderBonusesComposable, type OrderBonusesDeps, type OrderCredentialsLike, type OrderDelivery, type OrderDeliveryDeps, type OrderPromocodeComposable, type OrderPromocodeDeps, type OrderSettingsComposable, type OrderTotal, type PaymentSelection, type PaymentSelectionComposable, type RestrictedAddToCart, type RestrictionGate, type RestrictionGateProduct, type RetryOptions, type StorefrontCart, buildCartLineKey, buildCashChangePresets, buildMainPaymentRequest, getCartErrorCode, getCartErrorHttpCode, getCartErrorMessage, getCashDenominationsMinor, getDefaultRoundStepsMinor, getValidationErrors, logCartError, normalizeAddress, useBonusesReconciliation, useCartAddressSync, useCartCredentials, useCartCustomerAttachment, useCartDeliveryAttachment, useCartInitialization, useCartMutation, useCartOperations, useCartQuantities, useCartRecalculation, useCartStockWatcher, useCheckoutFlow, useCustomerAttach, useOnlinePaymentRetry, useOrderBonuses, useOrderChannel, useOrderDelivery, useOrderPromocode, useOrderSettings, useOrderTotal, usePaymentSelection, useRestrictedAddToCart, useRestrictionGate, useStorefrontCart, useVisibleCartVariants, variantLineKey };
|
package/dist/cart/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
export { CASH_DENOMINATIONS_MAJOR, DEFAULT_ROUND_STEPS_MAJOR, ORDER_EVENTS, ORDER_WITH, buildCartLineKey, buildCashChangePresets, buildMainPaymentRequest,
|
|
2
|
-
export { useCartCredentials } from '../chunk-
|
|
3
|
-
import '../chunk-XULHV6SS.js';
|
|
4
|
-
import '../chunk-KFCO46RB.js';
|
|
5
|
-
import '../chunk-2Y6QTHXI.js';
|
|
1
|
+
export { CASH_DENOMINATIONS_MAJOR, DEFAULT_ROUND_STEPS_MAJOR, ORDER_EVENTS, ORDER_WITH, buildCartLineKey, buildCashChangePresets, buildMainPaymentRequest, getCashDenominationsMinor, getDefaultRoundStepsMinor, 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-5CNL24PI.js';
|
|
2
|
+
export { useCartCredentials } from '../chunk-W43D7JYV.js';
|
|
6
3
|
import '../chunk-5QCUH3FF.js';
|
|
7
|
-
|
|
8
|
-
import '../chunk-
|
|
4
|
+
export { getCartErrorCode, getCartErrorHttpCode, getCartErrorMessage, getValidationErrors, logCartError } from '../chunk-TE42OCFK.js';
|
|
5
|
+
import '../chunk-TE2QPH74.js';
|
|
6
|
+
import '../chunk-NSOIL7PW.js';
|
|
7
|
+
import '../chunk-WTZXTBF6.js';
|
|
8
|
+
import '../chunk-IOYYCA75.js';
|
|
9
|
+
import '../chunk-FS2UNPTY.js';
|
|
10
|
+
import '../chunk-2Y6QTHXI.js';
|
|
9
11
|
//# sourceMappingURL=index.js.map
|
|
10
12
|
//# sourceMappingURL=index.js.map
|
package/dist/catalog/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { NestedCategory, Product, Store, City, Stock,
|
|
1
|
+
import { NestedCategory, Product, Store, City, Stock, ZenkyStorefront, CollectionsListRequest, ProductsCollection } from '@zenky/storefront-api';
|
|
2
|
+
import { a as StaticRemoteCatalog } from '../catalogEntity-DgrPsJpf.js';
|
|
3
|
+
export { C as CatalogEntity, S as StaticCatalogItem, c as catalogItemEntity, i as isRenderableCatalogItem } from '../catalogEntity-DgrPsJpf.js';
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* Recursively searches the category tree by `short_id`.
|
|
@@ -44,7 +46,7 @@ declare function groupProductsBySubcategory(rootCategory: NestedCategory, produc
|
|
|
44
46
|
|
|
45
47
|
declare function getCity(store: Store, cityId?: string | null): City | null;
|
|
46
48
|
declare function getStock(city: City, stockId?: string | null): Stock | null;
|
|
47
|
-
declare function getRemoteCatalog(store: Store, city: City, stock: Stock | null):
|
|
49
|
+
declare function getRemoteCatalog(store: Store, city: City, stock: Stock | null): StaticRemoteCatalog | null;
|
|
48
50
|
|
|
49
51
|
/**
|
|
50
52
|
* Pure composable — the SDK is passed in as a parameter (DI), no Nuxt needed.
|
|
@@ -57,4 +59,4 @@ declare function useCollections(sdk: ZenkyStorefront): {
|
|
|
57
59
|
loadCollections: (storeId: string, request?: CollectionsListRequest) => Promise<ProductsCollection[]>;
|
|
58
60
|
};
|
|
59
61
|
|
|
60
|
-
export { type GroupedProducts, type SubcategoryGroup, collectDescendantIds, findCategoryById, findCategoryByShortId, findRootAncestor, getCategoryPath, getCity, getRemoteCatalog, getStock, groupProductsBySubcategory, useCollections };
|
|
62
|
+
export { type GroupedProducts, StaticRemoteCatalog, type SubcategoryGroup, collectDescendantIds, findCategoryById, findCategoryByShortId, findRootAncestor, getCategoryPath, getCity, getRemoteCatalog, getStock, groupProductsBySubcategory, useCollections };
|
package/dist/catalog/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { collectDescendantIds, findCategoryById, findCategoryByShortId, findRootAncestor, getCategoryPath, groupProductsBySubcategory, useCollections } from '../chunk-
|
|
2
|
-
export { getCity, getRemoteCatalog, getStock } from '../chunk-
|
|
1
|
+
export { catalogItemEntity, collectDescendantIds, findCategoryById, findCategoryByShortId, findRootAncestor, getCategoryPath, groupProductsBySubcategory, isRenderableCatalogItem, useCollections } from '../chunk-OBNMXLJO.js';
|
|
2
|
+
export { getCity, getRemoteCatalog, getStock } from '../chunk-FS2UNPTY.js';
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Category, ProductsCollection, CatalogItem, RemoteCatalog } from '@zenky/storefront-api';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Static catalog item. `@zenky/storefront-api@1.0.2` predates manual catalogs: it
|
|
5
|
+
* spells the collection `collection` and types `type` as `'category' | 'collection'`,
|
|
6
|
+
* while the payload uses `products_collection`. Both spellings are declared here, and
|
|
7
|
+
* the fields are re-declared rather than inherited so a later SDK release that adds
|
|
8
|
+
* them cannot conflict with this narrowing.
|
|
9
|
+
*/
|
|
10
|
+
interface StaticCatalogItem extends Omit<CatalogItem, 'type' | 'collection' | 'products_collection'> {
|
|
11
|
+
type: 'category' | 'collection' | 'products_collection';
|
|
12
|
+
collection?: ProductsCollection | null;
|
|
13
|
+
products_collection?: ProductsCollection | null;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Store profile catalog entry. `catalog_id` is filled for manual catalogs only, and
|
|
17
|
+
* is optional because the SDK type omits it — test it with `!= null`, since `undefined`
|
|
18
|
+
* means "SDK-typed value", not "automatic catalog".
|
|
19
|
+
*/
|
|
20
|
+
interface StaticRemoteCatalog extends Omit<RemoteCatalog, 'catalog_id'> {
|
|
21
|
+
catalog_id?: string | null;
|
|
22
|
+
}
|
|
23
|
+
/** What a catalog section represents; `id` and `name` are lifted so callers needn't branch. */
|
|
24
|
+
type CatalogEntity = {
|
|
25
|
+
kind: 'category';
|
|
26
|
+
id: string;
|
|
27
|
+
name: string;
|
|
28
|
+
category: Category;
|
|
29
|
+
} | {
|
|
30
|
+
kind: 'collection';
|
|
31
|
+
id: string;
|
|
32
|
+
name: string;
|
|
33
|
+
collection: ProductsCollection;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Resolve what a catalog section is about, or null for a malformed item. Keyed off
|
|
37
|
+
* which entity object is present, not off `type`: the payload and the SDK type
|
|
38
|
+
* disagree on the discriminator's value, but presence holds under both.
|
|
39
|
+
*/
|
|
40
|
+
declare function catalogItemEntity(item: StaticCatalogItem): CatalogEntity | null;
|
|
41
|
+
/** Sections worth rendering: a known entity and at least one product. */
|
|
42
|
+
declare function isRenderableCatalogItem(item: StaticCatalogItem): boolean;
|
|
43
|
+
|
|
44
|
+
export { type CatalogEntity as C, type StaticCatalogItem as S, type StaticRemoteCatalog as a, catalogItemEntity as c, isRenderableCatalogItem as i };
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { useCartCredentials, usePromotionsChecker } from './chunk-
|
|
2
|
-
import { useCartStore, useOrderSettingsStore, usePromotionsStore } from './chunk-XULHV6SS.js';
|
|
3
|
-
import { getRemoteCatalog } from './chunk-KFCO46RB.js';
|
|
4
|
-
import { minorToMajor, majorToMinor } from './chunk-2Y6QTHXI.js';
|
|
1
|
+
import { useCartCredentials, usePromotionsChecker } from './chunk-W43D7JYV.js';
|
|
5
2
|
import { createRuntimeState } from './chunk-5QCUH3FF.js';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
3
|
+
import { logCartError, getCartErrorCode, getCartErrorMessage } from './chunk-TE42OCFK.js';
|
|
4
|
+
import { useCartStore, useOrderSettingsStore, usePromotionsStore } from './chunk-TE2QPH74.js';
|
|
5
|
+
import { useCatalogStore } from './chunk-NSOIL7PW.js';
|
|
6
|
+
import { useRuntime, useAuthStore } from './chunk-WTZXTBF6.js';
|
|
7
|
+
import { useStoreProfileStore } from './chunk-IOYYCA75.js';
|
|
8
|
+
import { getRemoteCatalog } from './chunk-FS2UNPTY.js';
|
|
9
|
+
import { minorToMajor, majorToMinor } from './chunk-2Y6QTHXI.js';
|
|
8
10
|
import { PaymentMethod, OrderAuthenticationMethod, DeliveryMethod, OrderCartCheckerResultAction, RecaptchaAction } from '@zenky/storefront-api';
|
|
9
11
|
import { ref, computed, watch, watchEffect, getCurrentScope, onScopeDispose, toValue } from 'vue';
|
|
10
12
|
import { storeToRefs } from 'pinia';
|
|
@@ -92,105 +94,6 @@ function buildCashChangePresets({
|
|
|
92
94
|
return [...candidates].sort((a, b) => a - b);
|
|
93
95
|
}
|
|
94
96
|
|
|
95
|
-
// src/cart/logCartError.ts
|
|
96
|
-
var REDACTED = "[REDACTED]";
|
|
97
|
-
var MAX_LOG_DEPTH = 6;
|
|
98
|
-
var MAX_ARRAY_ITEMS = 25;
|
|
99
|
-
var MAX_OBJECT_KEYS = 50;
|
|
100
|
-
var SENSITIVE_KEY_PARTS = [
|
|
101
|
-
"address",
|
|
102
|
-
"authorization",
|
|
103
|
-
"checkouturl",
|
|
104
|
-
"cookie",
|
|
105
|
-
"credential",
|
|
106
|
-
"email",
|
|
107
|
-
"password",
|
|
108
|
-
"paymentlink",
|
|
109
|
-
"paymentpageurl",
|
|
110
|
-
"phone",
|
|
111
|
-
"recaptcha",
|
|
112
|
-
"redirecturl",
|
|
113
|
-
"secret",
|
|
114
|
-
"token"
|
|
115
|
-
];
|
|
116
|
-
var SENSITIVE_EXACT_KEYS = /* @__PURE__ */ new Set(["cvc", "cvv", "otp", "pan", "pin"]);
|
|
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;
|
|
119
|
-
var BEARER_TOKEN = /(bearer\s+)[a-z0-9._~+/=-]+/gi;
|
|
120
|
-
function isSensitiveKey(key) {
|
|
121
|
-
const normalized = key.replace(/[^a-z0-9]/gi, "").toLowerCase();
|
|
122
|
-
return SENSITIVE_EXACT_KEYS.has(normalized) || normalized.includes("confirmationcode") || normalized.includes("verificationcode") || SENSITIVE_KEY_PARTS.some((part) => normalized.includes(part));
|
|
123
|
-
}
|
|
124
|
-
function sanitizeString(value) {
|
|
125
|
-
return value.replace(BEARER_TOKEN, `$1${REDACTED}`).replace(SENSITIVE_QUERY_PARAM, `$1${REDACTED}`).replace(SENSITIVE_ASSIGNMENT, `$1${REDACTED}`);
|
|
126
|
-
}
|
|
127
|
-
function sanitizeLogValue(value, depth = 0, seen = /* @__PURE__ */ new WeakSet()) {
|
|
128
|
-
if (typeof value === "string") return sanitizeString(value);
|
|
129
|
-
if (value === null || typeof value !== "object") return value;
|
|
130
|
-
if (depth >= MAX_LOG_DEPTH) return "[TRUNCATED]";
|
|
131
|
-
if (seen.has(value)) return "[CIRCULAR]";
|
|
132
|
-
seen.add(value);
|
|
133
|
-
if (Array.isArray(value)) {
|
|
134
|
-
const sanitized = value.slice(0, MAX_ARRAY_ITEMS).map((item) => sanitizeLogValue(item, depth + 1, seen));
|
|
135
|
-
if (value.length > MAX_ARRAY_ITEMS) sanitized.push("[TRUNCATED]");
|
|
136
|
-
return sanitized;
|
|
137
|
-
}
|
|
138
|
-
const result = {};
|
|
139
|
-
if (value instanceof Error) {
|
|
140
|
-
result.name = sanitizeString(value.name);
|
|
141
|
-
result.message = sanitizeString(value.message);
|
|
142
|
-
}
|
|
143
|
-
let allEntries;
|
|
144
|
-
try {
|
|
145
|
-
allEntries = Object.entries(value);
|
|
146
|
-
} catch {
|
|
147
|
-
return "[UNSERIALIZABLE]";
|
|
148
|
-
}
|
|
149
|
-
const entries = allEntries.slice(0, MAX_OBJECT_KEYS);
|
|
150
|
-
for (const [key, nestedValue] of entries) {
|
|
151
|
-
if (key === "name" || key === "message") continue;
|
|
152
|
-
result[key] = isSensitiveKey(key) ? REDACTED : sanitizeLogValue(nestedValue, depth + 1, seen);
|
|
153
|
-
}
|
|
154
|
-
if (allEntries.length > MAX_OBJECT_KEYS) result.__truncated__ = true;
|
|
155
|
-
return result;
|
|
156
|
-
}
|
|
157
|
-
function logCartError({ scope, context }, e) {
|
|
158
|
-
const err = e?.err;
|
|
159
|
-
const safeContext = sanitizeLogValue(context);
|
|
160
|
-
console.error(`[${scope}] failed`, {
|
|
161
|
-
...safeContext ?? {},
|
|
162
|
-
httpCode: err?.http_code,
|
|
163
|
-
errorCode: err?.error_code,
|
|
164
|
-
message: sanitizeLogValue(err?.message),
|
|
165
|
-
meta: sanitizeLogValue(err?.meta),
|
|
166
|
-
error: sanitizeLogValue(e)
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
function getCartErrorCode(e) {
|
|
170
|
-
return e?.err?.error_code;
|
|
171
|
-
}
|
|
172
|
-
function getCartErrorHttpCode(e) {
|
|
173
|
-
return e?.err?.http_code;
|
|
174
|
-
}
|
|
175
|
-
function getValidationErrors(e) {
|
|
176
|
-
const err = e?.err;
|
|
177
|
-
if (err?.error_code !== "validation") return {};
|
|
178
|
-
const meta = err.meta;
|
|
179
|
-
return meta?.errors ?? {};
|
|
180
|
-
}
|
|
181
|
-
function getCartErrorMessage(e, fallback) {
|
|
182
|
-
const err = e?.err;
|
|
183
|
-
if (!err) return fallback;
|
|
184
|
-
if (err.error_code === "validation") {
|
|
185
|
-
const errors = err.meta?.errors;
|
|
186
|
-
if (errors) {
|
|
187
|
-
const messages = Object.values(errors).flat().filter(Boolean);
|
|
188
|
-
if (messages.length > 0) return messages.join(" ");
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
return err.message ?? fallback;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
97
|
// src/cart/useCartMutation.ts
|
|
195
98
|
var getMutationState = createRuntimeState(() => ({
|
|
196
99
|
versions: /* @__PURE__ */ new Map()
|
|
@@ -2010,6 +1913,6 @@ function useVisibleCartVariants() {
|
|
|
2010
1913
|
);
|
|
2011
1914
|
}
|
|
2012
1915
|
|
|
2013
|
-
export { CASH_DENOMINATIONS_MAJOR, DEFAULT_ROUND_STEPS_MAJOR, ORDER_EVENTS, ORDER_WITH, buildCartLineKey, buildCashChangePresets, buildMainPaymentRequest,
|
|
2014
|
-
//# sourceMappingURL=chunk-
|
|
2015
|
-
//# sourceMappingURL=chunk-
|
|
1916
|
+
export { CASH_DENOMINATIONS_MAJOR, DEFAULT_ROUND_STEPS_MAJOR, ORDER_EVENTS, ORDER_WITH, buildCartLineKey, buildCashChangePresets, buildMainPaymentRequest, getCashDenominationsMinor, getDefaultRoundStepsMinor, 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 };
|
|
1917
|
+
//# sourceMappingURL=chunk-5CNL24PI.js.map
|
|
1918
|
+
//# sourceMappingURL=chunk-5CNL24PI.js.map
|