@zenky/storefront-vue 0.9.47 → 0.10.3

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.
Files changed (98) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/LICENSE.md +2 -2
  3. package/README.md +213 -6
  4. package/dist/cart/index.d.ts +588 -0
  5. package/dist/cart/index.js +12 -0
  6. package/dist/cart/index.js.map +1 -0
  7. package/dist/catalog/index.d.ts +73 -0
  8. package/dist/catalog/index.js +4 -0
  9. package/dist/catalog/index.js.map +1 -0
  10. package/dist/chunk-57IOMDAM.js +38 -0
  11. package/dist/chunk-57IOMDAM.js.map +1 -0
  12. package/dist/chunk-5QCUH3FF.js +15 -0
  13. package/dist/chunk-5QCUH3FF.js.map +1 -0
  14. package/dist/chunk-7FRMMCR5.js +93 -0
  15. package/dist/chunk-7FRMMCR5.js.map +1 -0
  16. package/dist/chunk-BWUKMWHL.js +45 -0
  17. package/dist/chunk-BWUKMWHL.js.map +1 -0
  18. package/dist/chunk-E3G7NGCH.js +45 -0
  19. package/dist/chunk-E3G7NGCH.js.map +1 -0
  20. package/dist/chunk-EMGQXBU3.js +3 -0
  21. package/dist/chunk-EMGQXBU3.js.map +1 -0
  22. package/dist/chunk-FFBZKQRV.js +393 -0
  23. package/dist/chunk-FFBZKQRV.js.map +1 -0
  24. package/dist/chunk-G2X4SBCO.js +2011 -0
  25. package/dist/chunk-G2X4SBCO.js.map +1 -0
  26. package/dist/chunk-GLTOJTZO.js +41 -0
  27. package/dist/chunk-GLTOJTZO.js.map +1 -0
  28. package/dist/chunk-GW2QNTAD.js +327 -0
  29. package/dist/chunk-GW2QNTAD.js.map +1 -0
  30. package/dist/chunk-JLFBAAFT.js +566 -0
  31. package/dist/chunk-JLFBAAFT.js.map +1 -0
  32. package/dist/chunk-MZ66ARDL.js +244 -0
  33. package/dist/chunk-MZ66ARDL.js.map +1 -0
  34. package/dist/chunk-N3NOTJUC.js +111 -0
  35. package/dist/chunk-N3NOTJUC.js.map +1 -0
  36. package/dist/chunk-RO25KNM5.js +36 -0
  37. package/dist/chunk-RO25KNM5.js.map +1 -0
  38. package/dist/chunk-RYYY7MVP.js +102 -0
  39. package/dist/chunk-RYYY7MVP.js.map +1 -0
  40. package/dist/chunk-TEG7EL4N.js +106 -0
  41. package/dist/chunk-TEG7EL4N.js.map +1 -0
  42. package/dist/chunk-V3VVDQIR.js +27 -0
  43. package/dist/chunk-V3VVDQIR.js.map +1 -0
  44. package/dist/chunk-XUGXLJZB.js +14 -0
  45. package/dist/chunk-XUGXLJZB.js.map +1 -0
  46. package/dist/chunk-Z3IW4ODZ.js +36 -0
  47. package/dist/chunk-Z3IW4ODZ.js.map +1 -0
  48. package/dist/index.d.ts +26 -0
  49. package/dist/index.js +21 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/layout/index.d.ts +54 -0
  52. package/dist/layout/index.js +106 -0
  53. package/dist/layout/index.js.map +1 -0
  54. package/dist/money/index.d.ts +26 -0
  55. package/dist/money/index.js +3 -0
  56. package/dist/money/index.js.map +1 -0
  57. package/dist/order/index.d.ts +34 -0
  58. package/dist/order/index.js +209 -0
  59. package/dist/order/index.js.map +1 -0
  60. package/dist/pagination/index.d.ts +87 -0
  61. package/dist/pagination/index.js +97 -0
  62. package/dist/pagination/index.js.map +1 -0
  63. package/dist/ports/index.d.ts +124 -0
  64. package/dist/ports/index.js +3 -0
  65. package/dist/ports/index.js.map +1 -0
  66. package/dist/products/index.d.ts +105 -0
  67. package/dist/products/index.js +7 -0
  68. package/dist/products/index.js.map +1 -0
  69. package/dist/promotions/index.d.ts +10 -0
  70. package/dist/promotions/index.js +7 -0
  71. package/dist/promotions/index.js.map +1 -0
  72. package/dist/schedule-Dd3zwHEb.d.ts +27 -0
  73. package/dist/seo/index.d.ts +91 -0
  74. package/dist/seo/index.js +289 -0
  75. package/dist/seo/index.js.map +1 -0
  76. package/dist/snippets/index.d.ts +17 -0
  77. package/dist/snippets/index.js +3 -0
  78. package/dist/snippets/index.js.map +1 -0
  79. package/dist/snippets-BC5bkSjm.d.ts +23 -0
  80. package/dist/stores/index.d.ts +196 -0
  81. package/dist/stores/index.js +8 -0
  82. package/dist/stores/index.js.map +1 -0
  83. package/dist/theme/index.d.ts +60 -0
  84. package/dist/theme/index.js +3 -0
  85. package/dist/theme/index.js.map +1 -0
  86. package/dist/utils/index.d.ts +66 -0
  87. package/dist/utils/index.js +4 -0
  88. package/dist/utils/index.js.map +1 -0
  89. package/dist/website-settings/index.d.ts +38 -0
  90. package/dist/website-settings/index.js +3 -0
  91. package/dist/website-settings/index.js.map +1 -0
  92. package/docs/consumer-setup.md +275 -0
  93. package/docs/ports.md +144 -0
  94. package/docs/releasing.md +46 -0
  95. package/package.json +143 -47
  96. package/dist/cjs/index.cjs +0 -3742
  97. package/dist/esm/index.mjs +0 -3642
  98. package/dist/zenky.d.ts +0 -10377
@@ -0,0 +1,196 @@
1
+ import * as pinia from 'pinia';
2
+ import * as vue from 'vue';
3
+ import { Ref, ComputedRef } from 'vue';
4
+ import * as _zenky_storefront_api from '@zenky/storefront-api';
5
+ import { CatalogItem, Product, Store, City, Stock, NestedCategory, DeliveryMethod, Order, OrderDeliveryMethod, OrderSettings, OrderCheckoutTotal, PaymentMethod, OrderPaymentTransaction, OrderProductVariant, OrderPaymentMethod } from '@zenky/storefront-api';
6
+ import { Website } from '../website-settings/index.js';
7
+ import '@zenky/integrations-sdk';
8
+ import '../snippets-BC5bkSjm.js';
9
+
10
+ interface CatalogStore {
11
+ catalog: Ref<CatalogItem[]>;
12
+ currentHash: Ref<string | null>;
13
+ reloading: Ref<boolean>;
14
+ loadError: Ref<boolean>;
15
+ initCatalog: (items: CatalogItem[], hash?: string | null) => void;
16
+ setLoadError: () => void;
17
+ setReloading: (value: boolean) => void;
18
+ hasCatalog: ComputedRef<boolean>;
19
+ }
20
+ declare const useCatalogStore: pinia.StoreDefinition<"zenky-catalog", Pick<CatalogStore, "catalog" | "currentHash" | "reloading" | "loadError">, Pick<CatalogStore, "hasCatalog">, Pick<CatalogStore, "initCatalog" | "setLoadError" | "setReloading">>;
21
+
22
+ interface ProductsStore {
23
+ products: Ref<Product[]>;
24
+ setProducts: (list: Product[]) => void;
25
+ hasProducts: ComputedRef<boolean>;
26
+ }
27
+ declare const useProductsStore: pinia.StoreDefinition<"zenky-products", Pick<ProductsStore, "products">, Pick<ProductsStore, "hasProducts">, Pick<ProductsStore, "setProducts">>;
28
+
29
+ interface StoreProfileStore {
30
+ store: Ref<Store | null>;
31
+ city: Ref<City | null>;
32
+ stock: Ref<Stock | null>;
33
+ categories: Ref<NestedCategory[]>;
34
+ website: Ref<Website | null>;
35
+ initStore: (store: Store, city: City, stock: Stock | null) => void;
36
+ setStock: (stock: Stock | null) => void;
37
+ setCategories: (categories: NestedCategory[]) => void;
38
+ initWebsite: (website: Website | null) => void;
39
+ isReady: ComputedRef<boolean>;
40
+ hasStock: ComputedRef<boolean>;
41
+ currency: ComputedRef<string>;
42
+ squareLogoUrl: ComputedRef<string | null>;
43
+ }
44
+ declare const useStoreProfileStore: pinia.StoreDefinition<"zenky-store-profile", Pick<StoreProfileStore, "store" | "city" | "stock" | "categories" | "website">, Pick<StoreProfileStore, "currency" | "isReady" | "hasStock" | "squareLogoUrl">, Pick<StoreProfileStore, "initStore" | "setStock" | "setCategories" | "initWebsite">>;
45
+
46
+ interface AuthStore {
47
+ token: Ref<string | null>;
48
+ phone: Ref<string | null>;
49
+ countryCode: Ref<string>;
50
+ isAuthenticated: ComputedRef<boolean>;
51
+ initials: ComputedRef<string>;
52
+ setToken: (token: string, phone?: string, countryCode?: string) => void;
53
+ clearToken: () => void;
54
+ initFromCookie: () => void;
55
+ }
56
+ declare const useAuthStore: pinia.StoreDefinition<"zenky-auth", Pick<AuthStore, "token" | "phone" | "countryCode">, Pick<AuthStore, "isAuthenticated" | "initials">, Pick<AuthStore, "setToken" | "clearToken" | "initFromCookie">>;
57
+
58
+ interface OrderSettingsStore {
59
+ deliveryMethod: Ref<DeliveryMethod>;
60
+ onPremiseTable: Ref<string | null>;
61
+ selectedStock: Ref<Stock | null>;
62
+ selectedAddress: Ref<string | null>;
63
+ selectedAddressId: Ref<string | null>;
64
+ selectedAddressName: Ref<string | null>;
65
+ setDeliveryMethod: (method: DeliveryMethod) => void;
66
+ setOnPremiseTable: (table: string | null) => void;
67
+ setSelectedStock: (stock: Stock | null) => void;
68
+ setSelectedAddress: (address: string | null, addressId?: string | null, addressName?: string | null) => void;
69
+ validateDeliveryMethod: (availableMethods: DeliveryMethod[]) => void;
70
+ restoreFromCookies: (city: City) => void;
71
+ isDelivery: ComputedRef<boolean>;
72
+ isPickup: ComputedRef<boolean>;
73
+ isOnPremise: ComputedRef<boolean>;
74
+ needsAddress: ComputedRef<boolean>;
75
+ needsStock: ComputedRef<boolean>;
76
+ needsTable: ComputedRef<boolean>;
77
+ }
78
+ declare const useOrderSettingsStore: pinia.StoreDefinition<"zenky-order-settings", Pick<OrderSettingsStore, "deliveryMethod" | "onPremiseTable" | "selectedStock" | "selectedAddress" | "selectedAddressId" | "selectedAddressName">, Pick<OrderSettingsStore, "isDelivery" | "isPickup" | "isOnPremise" | "needsAddress" | "needsStock" | "needsTable">, Pick<OrderSettingsStore, "setDeliveryMethod" | "setOnPremiseTable" | "setSelectedStock" | "setSelectedAddress" | "validateDeliveryMethod" | "restoreFromCookies">>;
79
+
80
+ interface CartCredentials {
81
+ id: string;
82
+ token: string;
83
+ }
84
+ /** Намерение по бонусам (business-state) — для headless-reconciliation. */
85
+ interface AppliedBonusesIntent {
86
+ enabled: boolean;
87
+ /** null = «списать максимум». */
88
+ desiredAmountMinor: number | null;
89
+ /** PIN-flow: бонусы сняты, нужно подтвердить заново. */
90
+ requiresConfirmation: boolean;
91
+ }
92
+ interface MinPriceViolation {
93
+ remaining: number;
94
+ progress: number;
95
+ minPrice: number;
96
+ }
97
+ interface CartStore {
98
+ order: Ref<Order | null>;
99
+ credentials: Ref<CartCredentials | null>;
100
+ loading: Ref<boolean>;
101
+ initializing: Ref<boolean>;
102
+ optimisticAdjustments: Ref<Record<string, number>>;
103
+ lineOptimistic: Ref<Record<string, number>>;
104
+ deliveryMethods: Ref<OrderDeliveryMethod[]>;
105
+ orderSettings: Ref<OrderSettings | null>;
106
+ comment: Ref<string>;
107
+ personsCount: Ref<number>;
108
+ checkoutTotal: Ref<OrderCheckoutTotal | null>;
109
+ selectedPaymentMethod: Ref<PaymentMethod | null>;
110
+ selectedPaymentBill: Ref<number | null>;
111
+ selectedCardTokenId: Ref<string | null>;
112
+ selectedSaveCard: Ref<boolean>;
113
+ bonusesIntent: Ref<AppliedBonusesIntent>;
114
+ deliveryTimeIntent: Ref<string | null>;
115
+ minPriceViolation: Ref<MinPriceViolation | null>;
116
+ setOrder: (order: Order) => void;
117
+ patchOrder: (partial: Order) => void;
118
+ setCredentials: (credentials: CartCredentials) => void;
119
+ setLoading: (value: boolean) => void;
120
+ setInitializing: (value: boolean) => void;
121
+ adjustOptimistic: (productId: string, delta: number) => void;
122
+ clearOptimistic: (productId: string) => void;
123
+ adjustLineOptimistic: (lineKey: string, delta: number) => void;
124
+ setDeliveryMethods: (methods: OrderDeliveryMethod[]) => void;
125
+ setOrderSettings: (settings: OrderSettings) => void;
126
+ setComment: (value: string) => void;
127
+ setPersonsCount: (value: number) => void;
128
+ setSelectedPaymentMethod: (method: PaymentMethod | null) => void;
129
+ setSelectedPaymentBill: (bill: number | null) => void;
130
+ setSelectedCardTokenId: (id: string | null) => void;
131
+ setSelectedSaveCard: (value: boolean) => void;
132
+ setBonusesIntentEnabled: (value: boolean) => void;
133
+ setDesiredBonusesAmount: (value: number | null) => void;
134
+ setBonusesRequiresConfirmation: (value: boolean) => void;
135
+ clearBonusesIntent: () => void;
136
+ setDeliveryTimeIntent: (value: string | null) => void;
137
+ restorePaymentSelection: (payments: OrderPaymentTransaction[]) => void;
138
+ validatePaymentSelection: () => void;
139
+ setOrderPaymentsState: (payments: OrderPaymentTransaction[]) => void;
140
+ setCheckoutTotal: (value: OrderCheckoutTotal) => void;
141
+ clearCart: () => void;
142
+ hasOrder: ComputedRef<boolean>;
143
+ hasCredentials: ComputedRef<boolean>;
144
+ variants: ComputedRef<OrderProductVariant[]>;
145
+ totalPrice: ComputedRef<number>;
146
+ itemCount: ComputedRef<number>;
147
+ availableDeliveryMethodIds: ComputedRef<DeliveryMethod[]>;
148
+ paymentMethods: ComputedRef<OrderPaymentMethod[]>;
149
+ hasBonusesApplied: ComputedRef<boolean>;
150
+ productQuantities: ComputedRef<Record<string, number>>;
151
+ }
152
+ declare const useCartStore: pinia.StoreDefinition<"zenky-cart", Pick<CartStore, "order" | "credentials" | "loading" | "initializing" | "optimisticAdjustments" | "lineOptimistic" | "deliveryMethods" | "orderSettings" | "comment" | "personsCount" | "checkoutTotal" | "selectedPaymentMethod" | "selectedPaymentBill" | "selectedCardTokenId" | "selectedSaveCard" | "bonusesIntent" | "deliveryTimeIntent" | "minPriceViolation">, Pick<CartStore, "hasOrder" | "hasCredentials" | "variants" | "totalPrice" | "itemCount" | "availableDeliveryMethodIds" | "paymentMethods" | "hasBonusesApplied" | "productQuantities">, Pick<CartStore, "setOrder" | "patchOrder" | "setCredentials" | "setLoading" | "setInitializing" | "adjustOptimistic" | "clearOptimistic" | "adjustLineOptimistic" | "setDeliveryMethods" | "setOrderSettings" | "setComment" | "setPersonsCount" | "setSelectedPaymentMethod" | "setSelectedPaymentBill" | "setSelectedCardTokenId" | "setSelectedSaveCard" | "setBonusesIntentEnabled" | "setDesiredBonusesAmount" | "setBonusesRequiresConfirmation" | "clearBonusesIntent" | "setDeliveryTimeIntent" | "restorePaymentSelection" | "validatePaymentSelection" | "setOrderPaymentsState" | "setCheckoutTotal" | "clearCart">>;
153
+
154
+ interface RewardSelectionContext {
155
+ type: string;
156
+ id: string;
157
+ }
158
+ interface RewardSelection {
159
+ offerId: string;
160
+ promotionId: string;
161
+ rewardId: string;
162
+ context: RewardSelectionContext | null;
163
+ limit: number;
164
+ }
165
+ interface PromotionsStore {
166
+ rewards: Ref<RewardSelection[]>;
167
+ checking: Ref<boolean>;
168
+ addOrUpdateReward: (selection: RewardSelection) => void;
169
+ removeRewardByPromotion: (promotionId: string) => void;
170
+ clearRewards: () => void;
171
+ setChecking: (value: boolean) => void;
172
+ hasRewards: ComputedRef<boolean>;
173
+ totalEmptySlots: ComputedRef<number>;
174
+ rewardSelection: ComputedRef<RewardSelection | null>;
175
+ needsSelection: ComputedRef<boolean>;
176
+ }
177
+ declare const usePromotionsStore: pinia.StoreDefinition<"zenky-promotions", Pick<PromotionsStore, "rewards" | "checking">, Pick<PromotionsStore, "hasRewards" | "totalEmptySlots" | "rewardSelection" | "needsSelection">, Pick<PromotionsStore, "addOrUpdateReward" | "removeRewardByPromotion" | "clearRewards" | "setChecking">>;
178
+
179
+ /** Аксессор загруженного стора/города/склада (store/city — гарантированно загружены). */
180
+ declare function useStore(): {
181
+ store: ComputedRef<Store>;
182
+ city: ComputedRef<City>;
183
+ stock: ComputedRef<Stock | null>;
184
+ };
185
+
186
+ /** Реактивный доступ к профилю (store/city/stock/categories + флаги готовности). */
187
+ declare function useStorefrontProfile(): {
188
+ store: vue.Ref<_zenky_storefront_api.Store | null, _zenky_storefront_api.Store | null>;
189
+ city: vue.Ref<_zenky_storefront_api.City | null, _zenky_storefront_api.City | null>;
190
+ stock: vue.Ref<_zenky_storefront_api.Stock | null, _zenky_storefront_api.Stock | null>;
191
+ categories: vue.Ref<_zenky_storefront_api.NestedCategory[], _zenky_storefront_api.NestedCategory[]>;
192
+ isReady: vue.ComputedRef<boolean>;
193
+ hasStock: vue.ComputedRef<boolean>;
194
+ };
195
+
196
+ export { type AppliedBonusesIntent, type AuthStore, type CartStore, type MinPriceViolation, type OrderSettingsStore, type PromotionsStore, type RewardSelection, type RewardSelectionContext, type StoreProfileStore, useAuthStore, useCartStore, useCatalogStore, useOrderSettingsStore, useProductsStore, usePromotionsStore, useStore, useStoreProfileStore, useStorefrontProfile };
@@ -0,0 +1,8 @@
1
+ export { useProductsStore, useStore, useStorefrontProfile } from '../chunk-57IOMDAM.js';
2
+ export { useCatalogStore } from '../chunk-Z3IW4ODZ.js';
3
+ export { usePromotionsStore } from '../chunk-BWUKMWHL.js';
4
+ export { useAuthStore, useStoreProfileStore } from '../chunk-TEG7EL4N.js';
5
+ export { useCartStore, useOrderSettingsStore } from '../chunk-FFBZKQRV.js';
6
+ import '../chunk-V3VVDQIR.js';
7
+ //# sourceMappingURL=index.js.map
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,60 @@
1
+ import { ComputedRef } from 'vue';
2
+
3
+ interface ThemeColorConfig {
4
+ primary: string;
5
+ secondary: string;
6
+ accent: string;
7
+ background: string;
8
+ text: string;
9
+ success?: string;
10
+ danger?: string;
11
+ warning?: string;
12
+ info?: string;
13
+ /** Цвет текста поверх primary-фона. Если не задан — рассчитывается автоматически. */
14
+ onPrimary?: string;
15
+ headerBg?: string;
16
+ footerBg?: string;
17
+ footerText?: string;
18
+ footerTextMuted?: string;
19
+ }
20
+ interface PrimaryShades {
21
+ lightest: string;
22
+ lighter: string;
23
+ light: string;
24
+ base: string;
25
+ dark: string;
26
+ darker: string;
27
+ darkest: string;
28
+ tint: string;
29
+ tintHover: string;
30
+ tintPressed: string;
31
+ ink: string;
32
+ }
33
+ /** Универсальный генератор 11-ступенчатой шкалы от одного hex. */
34
+ declare function generateShades(hex: string, bg?: string, text?: string): PrimaryShades;
35
+ declare function generatePrimaryShades(hex: string, bg?: string, text?: string): PrimaryShades;
36
+ declare function buildCssVariableMap(config: ThemeColorConfig): Record<string, string>;
37
+
38
+ interface FontConfig {
39
+ family: string;
40
+ url: string;
41
+ }
42
+ interface ThemeData {
43
+ cssVariables: ComputedRef<Record<string, string>>;
44
+ fontFamily: ComputedRef<string | null>;
45
+ fontUrl: ComputedRef<string | null>;
46
+ }
47
+ /** CSS-переменные темы + шрифт из цвето-/шрифто-конфига (инъекция в head — на стороне app). */
48
+ declare function useTheme(colorConfig: ThemeColorConfig, fontConfig: FontConfig): ThemeData;
49
+
50
+ interface ThemePreset {
51
+ id: string;
52
+ label: string;
53
+ description: string;
54
+ colors: ThemeColorConfig;
55
+ }
56
+ declare const THEME_PRESETS: ThemePreset[];
57
+ /** Тёмные версии пресетов — инвертированные background/text */
58
+ declare const DARK_THEME_PRESETS: ThemePreset[];
59
+
60
+ export { DARK_THEME_PRESETS, type FontConfig, type PrimaryShades, THEME_PRESETS, type ThemeColorConfig, type ThemeData, type ThemePreset, buildCssVariableMap, generatePrimaryShades, generateShades, useTheme };
@@ -0,0 +1,3 @@
1
+ export { DARK_THEME_PRESETS, THEME_PRESETS, buildCssVariableMap, generatePrimaryShades, generateShades, useTheme } from '../chunk-GW2QNTAD.js';
2
+ //# sourceMappingURL=index.js.map
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,66 @@
1
+ import { Phone } from '@zenky/storefront-api';
2
+ export { D as DayScheduleInfo, S as SocialLink, T as TodayScheduleInfo, f as formatScheduleStatus, g as getEmailLink, a as getSocialLinks, b as getTodayInfo, c as getWebsiteLink, d as getWeeklySchedule } from '../schedule-Dd3zwHEb.js';
3
+
4
+ declare function createDebounce(fn: () => void, delay: number): () => void;
5
+
6
+ interface OperationChain {
7
+ execute: (key: string, fn: () => Promise<void>) => Promise<void>;
8
+ readonly size: number;
9
+ }
10
+ declare function createOperationChain(): OperationChain;
11
+
12
+ declare function formatPhoneNational(phone: Phone | null | undefined): string | null;
13
+ declare function getPhoneTelLink(phone: Phone | null | undefined): string | null;
14
+ /**
15
+ * «Воздушный» формат номера: `+7 (999) 999-99-99` → `+7 999 999 99 99`.
16
+ * Скобки и дефисы заменяются на пробелы, лишние пробелы схлопываются.
17
+ */
18
+ declare function formatPhoneSpaced(formatted: string | null | undefined): string;
19
+
20
+ /**
21
+ * Генерирует URL картинки QR-кода через Zenky media API.
22
+ *
23
+ * Контент кодируется в base64 и передаётся в query `content`.
24
+ * Реализация не зависит от `window`, `btoa` или Node.js `Buffer`, поэтому один
25
+ * и тот же код работает в браузере, Node SSR и edge runtimes.
26
+ */
27
+ declare function buildQrCodeUrl(target: string, apiBaseUrl: string, size?: number): string;
28
+
29
+ declare function formatDate(date: string): string;
30
+ declare function formatDateTime(date: string): string;
31
+ /**
32
+ * Извлекает YYYY-MM-DD из ISO-строки (например "1998-06-02T03:00:00+03:00" → "1998-06-02").
33
+ * Для использования в <input type="date">.
34
+ */
35
+ declare function toDateInputValue(value: string | null): string;
36
+ /**
37
+ * Сегодняшняя дата в указанном часовом поясе в формате YYYY-MM-DD.
38
+ * Если TZ невалидный или не передан — возвращает дату в локальном TZ браузера.
39
+ *
40
+ * Используется, когда нужно сопоставить «сегодня» с датой из бэка, которая
41
+ * приходит относительно TZ магазина (а не TZ пользователя).
42
+ */
43
+ declare function todayInTimezone(timezone?: string | null): string;
44
+
45
+ /**
46
+ * Склонение существительных по числу (русский язык).
47
+ *
48
+ * @example
49
+ * pluralize(1, 'позиция', 'позиции', 'позиций') // 'позиция'
50
+ * pluralize(3, 'позиция', 'позиции', 'позиций') // 'позиции'
51
+ * pluralize(5, 'позиция', 'позиции', 'позиций') // 'позиций'
52
+ */
53
+ declare function pluralize(count: number, one: string, few: string, many: string): string;
54
+
55
+ /** Сообщение из ZenkyError (или fallback). */
56
+ declare function getApiErrorMessage(e: unknown, fallback: string): string;
57
+ /** Field-level ошибки из `meta.errors` ответа API (422 validation). */
58
+ declare function getApiFieldErrors(e: unknown): Record<string, string[]> | null;
59
+
60
+ /**
61
+ * Переносит город в конец строки адреса.
62
+ * "г Улан-Удэ, ул Ленина, д 29" → "ул Ленина, д 29, г Улан-Удэ"
63
+ */
64
+ declare function formatAddressCityLast(raw: string): string;
65
+
66
+ export { type OperationChain, buildQrCodeUrl, createDebounce, createOperationChain, formatAddressCityLast, formatDate, formatDateTime, formatPhoneNational, formatPhoneSpaced, getApiErrorMessage, getApiFieldErrors, getPhoneTelLink, pluralize, toDateInputValue, todayInTimezone };
@@ -0,0 +1,4 @@
1
+ export { buildQrCodeUrl, createOperationChain, formatAddressCityLast, formatDate, formatDateTime, formatPhoneNational, formatPhoneSpaced, formatScheduleStatus, getApiErrorMessage, getApiFieldErrors, getEmailLink, getPhoneTelLink, getSocialLinks, getTodayInfo, getWebsiteLink, getWeeklySchedule, pluralize, toDateInputValue, todayInTimezone } from '../chunk-MZ66ARDL.js';
2
+ export { createDebounce } from '../chunk-XUGXLJZB.js';
3
+ //# sourceMappingURL=index.js.map
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,38 @@
1
+ import { Media } from '@zenky/storefront-api';
2
+ import { ZenkyIntegration } from '@zenky/integrations-sdk';
3
+ import { a as SnippetGroup } from '../snippets-BC5bkSjm.js';
4
+
5
+ type SettingValue = string | number | boolean | null;
6
+ interface WebsiteSettingsValues {
7
+ [key: string]: SettingValue | {
8
+ [key: string]: SettingValue | {
9
+ [key: string]: SettingValue;
10
+ };
11
+ };
12
+ }
13
+ type WebsitePageType = 'about_us' | 'delivery_and_payments' | 'contacts' | 'custom';
14
+ interface WebsitePageSeo {
15
+ title?: string | null;
16
+ description?: string | null;
17
+ og_image?: string | null;
18
+ }
19
+ interface WebsitePageListItem {
20
+ id: string;
21
+ type: WebsitePageType;
22
+ path: string | null;
23
+ title?: string;
24
+ }
25
+ interface WebsitePage extends WebsitePageListItem {
26
+ content: string | null;
27
+ cover: Media | null;
28
+ seo: WebsitePageSeo | null;
29
+ }
30
+ interface Website {
31
+ id: string;
32
+ settings: WebsiteSettingsValues;
33
+ pages?: WebsitePageListItem[];
34
+ snippets?: SnippetGroup[];
35
+ integrations?: ZenkyIntegration[];
36
+ }
37
+
38
+ export type { SettingValue, Website, WebsitePage, WebsitePageListItem, WebsitePageSeo, WebsitePageType, WebsiteSettingsValues };
@@ -0,0 +1,3 @@
1
+ import '../chunk-EMGQXBU3.js';
2
+ //# sourceMappingURL=index.js.map
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,275 @@
1
+ # Consumer Setup
2
+
3
+ This guide is for teams integrating `@zenky/storefront-vue` into a Vue or Nuxt
4
+ storefront. The package owns reusable storefront state and business flows. The consumer
5
+ owns framework glue, visual components, routing, server endpoints, and environment
6
+ configuration.
7
+
8
+ ## 1. Install an exact version
9
+
10
+ Use an exact version while integrating or testing a prerelease. Upgrade deliberately
11
+ after the consumer quality gate is green.
12
+
13
+ ```bash
14
+ npm install --save-exact @zenky/storefront-vue@0.10.0
15
+ ```
16
+
17
+ The consumer must also provide compatible peer dependencies:
18
+
19
+ ```bash
20
+ npm install vue@^3.5 pinia@^3 @zenky/storefront-api@^1
21
+ ```
22
+
23
+ Install `@zenky/integrations-sdk` when the consumer sends Zenky integration events.
24
+
25
+ Do not commit a `file:.yalc/...` dependency. `yalc` is only for local development; CI
26
+ and deployed environments must install a published package version.
27
+
28
+ ## 2. Decide which domains the consumer needs
29
+
30
+ Import public subpaths instead of application source files:
31
+
32
+ ```ts
33
+ import { createStorefront } from '@zenky/storefront-vue'
34
+ import { getRemoteCatalog } from '@zenky/storefront-vue/catalog'
35
+ import { useProductPricing } from '@zenky/storefront-vue/products'
36
+ import { useCartStore } from '@zenky/storefront-vue/stores'
37
+ ```
38
+
39
+ A read-only menu normally needs `catalog`, `products`, `theme`, `utils`, and selected
40
+ stores. It does not need cart, checkout, auth, delivery, or payment modules.
41
+
42
+ A full storefront can additionally use `cart`, `order`, `promotions`, `seo`, `layout`,
43
+ `pagination`, `snippets`, and `website-settings`.
44
+
45
+ Never import from `@zenky/storefront-vue/dist/*` or from this repository's `src/*`.
46
+ Only documented package exports are public API.
47
+
48
+ ## 3. Create one composition root
49
+
50
+ The consumer creates external adapters once and installs the storefront plugin after
51
+ Pinia.
52
+
53
+ ```ts
54
+ import { createApp } from 'vue'
55
+ import { createPinia } from 'pinia'
56
+ import { createStorefront } from '@zenky/storefront-vue'
57
+ import type { StorefrontRuntime } from '@zenky/storefront-vue/ports'
58
+
59
+ import App from './App.vue'
60
+ import { sdk } from './services/zenky'
61
+
62
+ const app = createApp(App)
63
+ const pinia = createPinia()
64
+
65
+ const runtime: StorefrontRuntime = {
66
+ sdk,
67
+ config: {
68
+ baseUrl: import.meta.env.VITE_STOREFRONT_URL,
69
+ baseAuthUrl: import.meta.env.VITE_AUTH_URL,
70
+ salesChannelId: import.meta.env.VITE_SALES_CHANNEL_ID || undefined,
71
+ },
72
+ storage: {
73
+ get: (key) => localStorage.getItem(key),
74
+ set: (key, value) => localStorage.setItem(key, value),
75
+ remove: (key) => localStorage.removeItem(key),
76
+ },
77
+ notifier: {
78
+ error: (message) => notifications.error(message),
79
+ success: (message) => notifications.success(message),
80
+ warning: (message) => notifications.warning(message),
81
+ message: (title, options) => notifications.message(title, options),
82
+ },
83
+ activity: {
84
+ begin: (kind) => busy.begin(kind),
85
+ end: (kind) => busy.end(kind),
86
+ },
87
+ }
88
+
89
+ app.use(pinia)
90
+ app.use(createStorefront(runtime))
91
+ app.mount('#app')
92
+ ```
93
+
94
+ Use `NOOP_NOTIFIER` and `NOOP_ACTIVITY_REPORTER` from the `ports` subpath when a
95
+ read-only consumer intentionally has no notifications or busy UI. Keep that decision
96
+ explicit.
97
+
98
+ ## 4. Nuxt adapter
99
+
100
+ Nuxt consumers should install the runtime in one plugin and keep Nuxt APIs in that
101
+ plugin, not in the package.
102
+
103
+ ```ts
104
+ import { createStorefront } from '@zenky/storefront-vue'
105
+ import type { StorefrontRuntime } from '@zenky/storefront-vue/ports'
106
+
107
+ export default defineNuxtPlugin((nuxtApp) => {
108
+ const config = useRuntimeConfig()
109
+
110
+ const runtime: StorefrontRuntime = {
111
+ sdk: useStorefrontApi(),
112
+ config: {
113
+ baseUrl: config.public.storefrontBaseUrl,
114
+ baseAuthUrl: config.public.storefrontAuthUrl,
115
+ },
116
+ storage: {
117
+ get: (key) => useCookie<string | null>(key).value ?? null,
118
+ set: (key, value, options) => {
119
+ useCookie<string>(key, options).value = value
120
+ },
121
+ remove: (key, options) => {
122
+ useCookie(key, options).value = null
123
+ },
124
+ },
125
+ notifier: createNotifierAdapter(),
126
+ activity: createActivityAdapter(),
127
+ }
128
+
129
+ nuxtApp.vueApp.use(createStorefront(runtime))
130
+ })
131
+ ```
132
+
133
+ Resolve optional integrations lazily when their initialization order is later than the
134
+ storefront plugin:
135
+
136
+ ```ts
137
+ runtime.events = {
138
+ get: () => useZenkyIntegrations(),
139
+ }
140
+
141
+ runtime.realtime = {
142
+ get: () => useRealtimeAdapter(),
143
+ }
144
+ ```
145
+
146
+ Do not capture an initial `null` integration instance during plugin setup.
147
+
148
+ ## 5. Storage and sensitive data
149
+
150
+ The storage adapter is synchronous because order and auth credentials are read while
151
+ composables are created.
152
+
153
+ For browser-only applications, `localStorage` or cookies are acceptable according to
154
+ the consumer's security model. For SSR, use request-scoped cookies.
155
+
156
+ Never:
157
+
158
+ - share in-memory storage between users;
159
+ - log storage values, order tokens, API tokens, cookies, confirmation codes, payment
160
+ tokens, phone numbers, addresses, or order comments;
161
+ - expose secret server configuration through public runtime config;
162
+ - persist real credentials in test fixtures.
163
+
164
+ See [Runtime Ports](ports.md) for the complete security boundary.
165
+
166
+ ## 6. SSR isolation
167
+
168
+ For every server request, create a new:
169
+
170
+ 1. Vue application;
171
+ 2. Pinia instance;
172
+ 3. `StorefrontRuntime`;
173
+ 4. storage adapter.
174
+
175
+ Do not keep runtime or Pinia instances in module-global server state. Runtime-owned
176
+ mutation versions, request deduplication, restriction gates, and related-product state
177
+ must not cross request or application boundaries.
178
+
179
+ ## 7. Local package development with yalc
180
+
181
+ Use `yalc` only when changing the package and consumer together.
182
+
183
+ In this repository:
184
+
185
+ ```bash
186
+ npm run build
187
+ npx yalc publish
188
+ ```
189
+
190
+ In the consumer:
191
+
192
+ ```bash
193
+ npx yalc add @zenky/storefront-vue
194
+ ```
195
+
196
+ After another package change:
197
+
198
+ ```bash
199
+ npm run build
200
+ npx yalc push
201
+ ```
202
+
203
+ Before committing the consumer:
204
+
205
+ ```bash
206
+ npx yalc remove @zenky/storefront-vue
207
+ npm install --save-exact @zenky/storefront-vue@<published-version>
208
+ ```
209
+
210
+ Verify that `package.json` and `package-lock.json` no longer reference `.yalc`.
211
+
212
+ ## 8. Consumer quality gate
213
+
214
+ Before requesting review:
215
+
216
+ ```bash
217
+ npm ci
218
+ npm run lint
219
+ npm run test
220
+ npm run build
221
+ ```
222
+
223
+ For Nuxt consumers, also verify:
224
+
225
+ - the first SSR request returns HTML without a storefront-runtime or Pinia error;
226
+ - hydration completes without mismatch warnings;
227
+ - a new browser session creates or restores the expected order;
228
+ - a second app or SSR request does not see the first user's state;
229
+ - optional integrations initialized after the runtime still receive events.
230
+
231
+ For cart or checkout changes, cover:
232
+
233
+ - add, increment, decrement, and clear;
234
+ - API failures and stale responses;
235
+ - delivery and payment selection;
236
+ - minimum-order behavior;
237
+ - product restrictions;
238
+ - cleanup of busy state.
239
+
240
+ ## 9. Upgrade checklist
241
+
242
+ 1. Read the package changelog and migration notes.
243
+ 2. Install the exact target version.
244
+ 3. Review changed ports and exported types.
245
+ 4. Run the package consumer's unit tests and production build.
246
+ 5. Run smoke tests against a dedicated development store.
247
+ 6. Deploy to development.
248
+ 7. Run the same smoke suite against the deployed URL.
249
+ 8. Only then widen the version range or promote a prerelease.
250
+
251
+ ## 10. Common failures
252
+
253
+ ### `createStorefront() is not installed`
254
+
255
+ The runtime plugin was not installed, was installed after a component used the package,
256
+ or a second Vue application did not receive its own runtime.
257
+
258
+ ### `getActivePinia()` or `No active Pinia`
259
+
260
+ Install Pinia before `createStorefront(runtime)` and before calling package stores.
261
+
262
+ ### The app builds locally but CI cannot install the package
263
+
264
+ Check `package.json` and the lockfile for `file:.yalc`, local paths, or an unpublished
265
+ version.
266
+
267
+ ### SSR users share cart or restriction state
268
+
269
+ A runtime, Pinia instance, or storage adapter is being reused between requests. Make all
270
+ three request-scoped.
271
+
272
+ ### An optional integration never receives events
273
+
274
+ Provide a lazy `{ get() }` adapter instead of capturing the integration instance before
275
+ it is initialized.