@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.
Files changed (33) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +63 -3
  3. package/dist/cart/index.js +4 -4
  4. package/dist/{chunk-YREGCQSB.js → chunk-5YD4AIY2.js} +5 -5
  5. package/dist/chunk-5YD4AIY2.js.map +1 -0
  6. package/dist/{chunk-YS5DXYYV.js → chunk-E4DUFN2M.js} +21 -28
  7. package/dist/chunk-E4DUFN2M.js.map +1 -0
  8. package/dist/{chunk-OTSAR32A.js → chunk-MOG6UMFM.js} +2 -2
  9. package/dist/{chunk-OTSAR32A.js.map → chunk-MOG6UMFM.js.map} +1 -1
  10. package/dist/{chunk-SS7B2NLF.js → chunk-PTMSPB34.js} +3 -3
  11. package/dist/{chunk-SS7B2NLF.js.map → chunk-PTMSPB34.js.map} +1 -1
  12. package/dist/{chunk-IVG4FQE5.js → chunk-RAJDWCJU.js} +3 -3
  13. package/dist/{chunk-IVG4FQE5.js.map → chunk-RAJDWCJU.js.map} +1 -1
  14. package/dist/{chunk-TB5TBJ4U.js → chunk-VFMVQR6Y.js} +8 -15
  15. package/dist/chunk-VFMVQR6Y.js.map +1 -0
  16. package/dist/{chunk-NIQFYJRP.js → chunk-Z247QRDJ.js} +4 -4
  17. package/dist/{chunk-NIQFYJRP.js.map → chunk-Z247QRDJ.js.map} +1 -1
  18. package/dist/index.js +7 -7
  19. package/dist/ports/index.d.ts +2 -1
  20. package/dist/ports/index.js +1 -1
  21. package/dist/products/index.js +2 -2
  22. package/dist/promotions/index.d.ts +13 -0
  23. package/dist/promotions/index.js +3 -3
  24. package/dist/seo/index.js +2 -2
  25. package/dist/stores/index.d.ts +2 -1
  26. package/dist/stores/index.js +3 -3
  27. package/docs/consumer-setup.md +10 -3
  28. package/docs/ports.md +1 -1
  29. package/docs/releasing.md +2 -1
  30. package/package.json +5 -4
  31. package/dist/chunk-TB5TBJ4U.js.map +0 -1
  32. package/dist/chunk-YREGCQSB.js.map +0 -1
  33. package/dist/chunk-YS5DXYYV.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,19 +1,19 @@
1
1
  export { normalizeSnippets } from './chunk-2CI4RW7V.js';
2
- export { useProductsStore, useStore, useStorefrontProfile } from './chunk-SS7B2NLF.js';
2
+ export { useProductsStore, useStore, useStorefrontProfile } from './chunk-PTMSPB34.js';
3
3
  export { buildCssVariableMap, generatePrimaryShades, generateShades, useTheme } from './chunk-4IFPVEO7.js';
4
4
  export { buildQrCodeUrl, createOperationChain, formatAddressCityLast, formatDate, formatDateTime, formatPhoneNational, formatPhoneSpaced, formatScheduleStatus, getApiErrorMessage, getApiFieldErrors, getEmailLink, getPhoneTelLink, getSocialLinks, getTodayInfo, getWebsiteLink, getWeeklySchedule, pluralize, toDateInputValue, todayInTimezone } from './chunk-MZ66ARDL.js';
5
5
  import './chunk-EMGQXBU3.js';
6
- 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-YS5DXYYV.js';
7
- export { useCartCredentials } from './chunk-YREGCQSB.js';
6
+ 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';
7
+ export { useCartCredentials } from './chunk-5YD4AIY2.js';
8
8
  export { useCatalogStore } from './chunk-Z3IW4ODZ.js';
9
- export { useCartStore, useOrderSettingsStore, usePromotionsStore } from './chunk-NIQFYJRP.js';
9
+ export { useCartStore, useOrderSettingsStore, usePromotionsStore } from './chunk-Z247QRDJ.js';
10
10
  export { collectDescendantIds, findCategoryById, findCategoryByShortId, findRootAncestor, getCategoryPath, groupProductsBySubcategory, useCollections } from './chunk-NG7RUIWW.js';
11
11
  export { getCity, getRemoteCatalog, getStock } from './chunk-E3G7NGCH.js';
12
12
  export { asMajor, asMinor, formatPrice, majorToMinor, minorToMajor, minorToMajorString } from './chunk-RO25KNM5.js';
13
- export { KEY_MESSAGE_FORMATTER, NOOP_ACTIVITY_REPORTER, NOOP_NOTIFIER, NOOP_RUM, createMemoryStorage, err, ok } from './chunk-OTSAR32A.js';
14
- export { canAddDirectly, findProductInCatalog, formatWeight, getProductWeight, getVariantWeight, resolveVariantPrice, toGrams, usePriceRecalculation, useProductPricing, useProductVariant, useProductVariantModifiers, useProductVariantSelector, useProductsByCategory, useRelatedProducts } from './chunk-IVG4FQE5.js';
13
+ export { KEY_MESSAGE_FORMATTER, NOOP_ACTIVITY_REPORTER, NOOP_NOTIFIER, NOOP_RUM, createMemoryStorage, err, ok } from './chunk-MOG6UMFM.js';
14
+ export { canAddDirectly, findProductInCatalog, formatWeight, getProductWeight, getVariantWeight, resolveVariantPrice, toGrams, usePriceRecalculation, useProductPricing, useProductVariant, useProductVariantModifiers, useProductVariantSelector, useProductsByCategory, useRelatedProducts } from './chunk-RAJDWCJU.js';
15
15
  export { createDebounce } from './chunk-XUGXLJZB.js';
16
16
  import './chunk-5QCUH3FF.js';
17
- export { createStorefront, provideStorefront, useAuthStore, useRuntime, useStoreProfileStore } from './chunk-TB5TBJ4U.js';
17
+ export { createStorefront, provideStorefront, useAuthStore, useRuntime, useStoreProfileStore } from './chunk-VFMVQR6Y.js';
18
18
  //# sourceMappingURL=index.js.map
19
19
  //# sourceMappingURL=index.js.map
@@ -108,7 +108,8 @@ interface StorefrontRuntime {
108
108
  /** SDK-клиент Zenky. Потребитель создаёт один инстанс и отдаёт сюда. */
109
109
  sdk: ZenkyStorefront;
110
110
  storage: StorageAdapter;
111
- config: StorefrontConfig;
111
+ /** Reserved consumer configuration. The current core does not read this port. */
112
+ config?: StorefrontConfig;
112
113
  notifier: Notifier;
113
114
  /** Localized user-facing copy. The core emits only stable message identifiers. */
114
115
  messages: MessageFormatter;
@@ -1,3 +1,3 @@
1
- export { KEY_MESSAGE_FORMATTER, NOOP_ACTIVITY_REPORTER, NOOP_NOTIFIER, NOOP_RUM, createMemoryStorage, err, ok } from '../chunk-OTSAR32A.js';
1
+ export { KEY_MESSAGE_FORMATTER, NOOP_ACTIVITY_REPORTER, NOOP_NOTIFIER, NOOP_RUM, createMemoryStorage, err, ok } from '../chunk-MOG6UMFM.js';
2
2
  //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,6 @@
1
- export { canAddDirectly, findProductInCatalog, formatWeight, getProductWeight, getVariantWeight, resolveVariantPrice, toGrams, usePriceRecalculation, useProductPricing, useProductVariant, useProductVariantModifiers, useProductVariantSelector, useProductsByCategory, useRelatedProducts } from '../chunk-IVG4FQE5.js';
1
+ export { canAddDirectly, findProductInCatalog, formatWeight, getProductWeight, getVariantWeight, resolveVariantPrice, toGrams, usePriceRecalculation, useProductPricing, useProductVariant, useProductVariantModifiers, useProductVariantSelector, useProductsByCategory, useRelatedProducts } from '../chunk-RAJDWCJU.js';
2
2
  import '../chunk-XUGXLJZB.js';
3
3
  import '../chunk-5QCUH3FF.js';
4
- import '../chunk-TB5TBJ4U.js';
4
+ import '../chunk-VFMVQR6Y.js';
5
5
  //# sourceMappingURL=index.js.map
6
6
  //# sourceMappingURL=index.js.map
@@ -4,6 +4,19 @@ interface PromotionsChecker {
4
4
  /**
5
5
  * Проверка промо-акций. Вызывает dispatchPromotionsChecker после изменения корзины.
6
6
  * Результат приходит через WebSocket (обрабатывается в useOrderChannel).
7
+ *
8
+ * Резолвить синхронно в setup, а после await вызывать только `dispatchCheck` — как и
9
+ * любой композабл ядра, см. раздел «Call composables and stores synchronously in setup»
10
+ * в README.
11
+ *
12
+ * ```ts
13
+ * const { dispatchCheck } = usePromotionsChecker()
14
+ *
15
+ * async function addGift() {
16
+ * await addVariantToOrder()
17
+ * dispatchCheck()
18
+ * }
19
+ * ```
7
20
  */
8
21
  declare function usePromotionsChecker(): PromotionsChecker;
9
22
 
@@ -1,5 +1,5 @@
1
- export { usePromotionsChecker } from '../chunk-YREGCQSB.js';
2
- import '../chunk-NIQFYJRP.js';
3
- import '../chunk-TB5TBJ4U.js';
1
+ export { usePromotionsChecker } from '../chunk-5YD4AIY2.js';
2
+ import '../chunk-Z247QRDJ.js';
3
+ import '../chunk-VFMVQR6Y.js';
4
4
  //# sourceMappingURL=index.js.map
5
5
  //# sourceMappingURL=index.js.map
package/dist/seo/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { getSocialLinks } from '../chunk-MZ66ARDL.js';
2
2
  import { minorToMajorString } from '../chunk-RO25KNM5.js';
3
- import { resolveVariantPrice } from '../chunk-IVG4FQE5.js';
3
+ import { resolveVariantPrice } from '../chunk-RAJDWCJU.js';
4
4
  import '../chunk-XUGXLJZB.js';
5
5
  import '../chunk-5QCUH3FF.js';
6
- import '../chunk-TB5TBJ4U.js';
6
+ import '../chunk-VFMVQR6Y.js';
7
7
  import { ContactType } from '@zenky/storefront-api';
8
8
 
9
9
  // src/seo/utils.ts
@@ -48,12 +48,13 @@ interface AuthStore {
48
48
  phone: Ref<string | null>;
49
49
  countryCode: Ref<string>;
50
50
  isAuthenticated: ComputedRef<boolean>;
51
+ apiToken: ComputedRef<string | undefined>;
51
52
  initials: ComputedRef<string>;
52
53
  setToken: (token: string, phone?: string, countryCode?: string) => void;
53
54
  clearToken: () => void;
54
55
  initFromCookie: () => void;
55
56
  }
56
- declare const useAuthStore: pinia.StoreDefinition<"zenky-auth", Pick<AuthStore, "token" | "phone" | "countryCode">, Pick<AuthStore, "isAuthenticated" | "initials">, Pick<AuthStore, "setToken" | "clearToken" | "initFromCookie">>;
57
+ declare const useAuthStore: pinia.StoreDefinition<"zenky-auth", Pick<AuthStore, "token" | "phone" | "countryCode">, Pick<AuthStore, "isAuthenticated" | "apiToken" | "initials">, Pick<AuthStore, "setToken" | "clearToken" | "initFromCookie">>;
57
58
 
58
59
  interface OrderSettingsStore {
59
60
  deliveryMethod: Ref<DeliveryMethod>;
@@ -1,6 +1,6 @@
1
- export { useProductsStore, useStore, useStorefrontProfile } from '../chunk-SS7B2NLF.js';
1
+ export { useProductsStore, useStore, useStorefrontProfile } from '../chunk-PTMSPB34.js';
2
2
  export { useCatalogStore } from '../chunk-Z3IW4ODZ.js';
3
- export { useCartStore, useOrderSettingsStore, usePromotionsStore } from '../chunk-NIQFYJRP.js';
4
- export { useAuthStore, useStoreProfileStore } from '../chunk-TB5TBJ4U.js';
3
+ export { useCartStore, useOrderSettingsStore, usePromotionsStore } from '../chunk-Z247QRDJ.js';
4
+ export { useAuthStore, useStoreProfileStore } from '../chunk-VFMVQR6Y.js';
5
5
  //# sourceMappingURL=index.js.map
6
6
  //# sourceMappingURL=index.js.map
@@ -11,7 +11,7 @@ Use an exact version while integrating or testing a prerelease. Upgrade delibera
11
11
  after the consumer quality gate is green.
12
12
 
13
13
  ```bash
14
- npm install --save-exact @zenky/storefront-vue@0.10.4
14
+ npm install --save-exact @zenky/storefront-vue@0.10.5
15
15
  ```
16
16
 
17
17
  The consumer must also provide compatible peer dependencies:
@@ -110,8 +110,13 @@ import type { StorefrontRuntime } from '@zenky/storefront-vue/ports'
110
110
  export default defineNuxtPlugin((nuxtApp) => {
111
111
  const config = useRuntimeConfig()
112
112
 
113
+ // One SDK client per request. The client is mutable — auth stores call
114
+ // `setApiToken()` on it — so a process-wide instance leaks one user's Bearer
115
+ // into other SSR requests. This plugin runs per request, so build it here.
116
+ const sdk = new ZenkyStorefront({ baseUrl, baseAuthUrl, client: 'web' })
117
+
113
118
  const runtime: StorefrontRuntime = {
114
- sdk: useStorefrontApi(),
119
+ sdk,
115
120
  config: {
116
121
  baseUrl: config.public.storefrontBaseUrl,
117
122
  baseAuthUrl: config.public.storefrontAuthUrl,
@@ -174,7 +179,9 @@ For every server request, create a new:
174
179
  1. Vue application;
175
180
  2. Pinia instance;
176
181
  3. `StorefrontRuntime`;
177
- 4. storage adapter.
182
+ 4. storage adapter;
183
+ 5. **SDK client** — it holds a mutable auth token, so sharing one across requests
184
+ leaks credentials between users.
178
185
 
179
186
  Do not keep runtime or Pinia instances in module-global server state. Runtime-owned
180
187
  mutation versions, request deduplication, restriction gates, and related-product state
package/docs/ports.md CHANGED
@@ -49,7 +49,6 @@ scope instead of installing the plugin globally.
49
49
  | Port | Contract | Responsibility |
50
50
  | --- | --- | --- |
51
51
  | `sdk` | `ZenkyStorefront` | Typed access to Zenky Storefront API resources. The consumer owns configuration and request transport. |
52
- | `config` | `StorefrontConfig` | Public storefront and auth base URLs plus an optional sales channel id. |
53
52
  | `storage` | `StorageAdapter` | Synchronous key/value persistence used for order/auth state and lightweight preferences. |
54
53
  | `notifier` | `Notifier` | User-facing `error`, `success`, `warning`, and generic message notifications. |
55
54
  | `messages` | `MessageFormatter` | Maps stable domain message keys and parameters to localized consumer copy. |
@@ -64,6 +63,7 @@ should provide a locale-aware formatter.
64
63
 
65
64
  | Port | Contract | Behavior when absent |
66
65
  | --- | --- | --- |
66
+ | `config` | `StorefrontConfig` | No behavior changes; the current core does not read this reserved consumer configuration. |
67
67
  | `events` | Lazy `EventsPort.get()` returning `ZenkyIntegrationsSDK` | Integration events are skipped. |
68
68
  | `realtime` | Lazy `RealtimePort.get()` returning `RealtimeAdapter` | Realtime order updates are skipped. |
69
69
  | `catalogReloader` | `CatalogReloader.reload()` | Stock changes do not trigger an external catalog reload. |
package/docs/releasing.md CHANGED
@@ -41,7 +41,8 @@ The npm package must have a trusted publisher configured for this GitHub reposit
41
41
 
42
42
  ## Verify
43
43
 
44
- - Confirm the workflow completed and the package has npm provenance.
44
+ - Confirm the workflow completed. This private repository intentionally publishes without
45
+ npm provenance; enable and verify provenance only after the source repository is public.
45
46
  - Inspect `npm view @zenky/storefront-vue@X.Y.Z` metadata and dist-tags.
46
47
  - Install the exact version into a clean consumer and import both the root and one subpath.
47
48
  - Confirm the GitHub release links to the correct tag and changelog section.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenky/storefront-vue",
3
- "version": "0.10.4",
3
+ "version": "0.10.6",
4
4
  "description": "Zenky Storefront SDK for Vue 3.",
5
5
  "keywords": [
6
6
  "zenky",
@@ -105,11 +105,12 @@
105
105
  "test:watch": "vitest",
106
106
  "check:exports": "publint --strict && attw --pack . --profile esm-only",
107
107
  "check:boundaries": "node scripts/check-boundaries.mjs",
108
+ "check:context": "node scripts/check-context.mjs",
108
109
  "check:runtime": "node scripts/check-runtime-compat.mjs",
109
110
  "check:size": "node scripts/check-bundle-size.mjs",
110
- "check": "npm run format:check && npm run lint && npm run typecheck && npm run test && npm run check:boundaries && npm run build && npm run check:exports && npm run check:runtime && npm run check:size",
111
- "check:ci": "npm run format:check && npm run lint && npm run typecheck && npm run test:coverage && npm run check:boundaries && npm run build && npm run check:exports && npm run check:runtime && npm run check:size",
112
- "check:release": "npm run typecheck && npm run test && npm run check:boundaries && npm run build && npm run check:exports && npm run check:runtime && npm run check:size",
111
+ "check": "npm run format:check && npm run lint && npm run typecheck && npm run test && npm run check:boundaries && npm run check:context && npm run build && npm run check:exports && npm run check:runtime && npm run check:size",
112
+ "check:ci": "npm run format:check && npm run lint && npm run typecheck && npm run test:coverage && npm run check:boundaries && npm run check:context && npm run build && npm run check:exports && npm run check:runtime && npm run check:size",
113
+ "check:release": "npm run typecheck && npm run test && npm run check:boundaries && npm run check:context && npm run build && npm run check:exports && npm run check:runtime && npm run check:size",
113
114
  "prepublishOnly": "npm run check:release"
114
115
  },
115
116
  "peerDependencies": {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/ports/runtime.ts","../src/stores/store-profile.ts","../src/stores/auth.ts"],"names":["defineStore","ref","computed"],"mappings":"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","file":"chunk-TB5TBJ4U.js","sourcesContent":["import { inject, provide, type App, type InjectionKey, type Plugin } from 'vue'\n\nimport type { StorefrontRuntime } from './index'\n\n// Composition root. Потребитель собирает рантайм (адаптеры) один раз и ставит плагин,\n// доменные composables берут его через useRuntime() вместо прямых Nuxt-вызовов.\n\nconst RUNTIME_KEY = Symbol.for('zenky.storefront.runtime') as InjectionKey<StorefrontRuntime>\n\ntype RequiredPort = {\n [K in keyof StorefrontRuntime]-?: undefined extends StorefrontRuntime[K] ? never : K\n}[keyof StorefrontRuntime]\n\nconst REQUIRED_PORTS = [\n 'sdk',\n 'config',\n 'storage',\n 'notifier',\n 'activity',\n 'messages',\n] as const satisfies readonly RequiredPort[]\n\ntype ListedPort = (typeof REQUIRED_PORTS)[number]\ntype UnlistedRequiredPort = Exclude<RequiredPort, ListedPort>\n\nconst _allRequiredPortsListed: UnlistedRequiredPort extends never ? true : never = true\nvoid _allRequiredPortsListed\n\nfunction assertRequiredPorts(runtime: StorefrontRuntime): void {\n const missing = REQUIRED_PORTS.filter((port) => runtime[port] == null)\n if (missing.length > 0) {\n throw new Error(\n `[@zenky/storefront-vue] Runtime is missing required ports: ${missing.join(', ')}. ` +\n 'See the Runtime Ports table in the README.'\n )\n }\n}\n\n/** Vue-плагин: app.use(createStorefront(runtime)). */\nexport function createStorefront(runtime: StorefrontRuntime): Plugin {\n assertRequiredPorts(runtime)\n\n return {\n install(app: App) {\n app.provide(RUNTIME_KEY, runtime)\n },\n }\n}\n\n/** Альтернатива плагину — provide внутри setup (напр. в изолированном виджете). */\nexport function provideStorefront(runtime: StorefrontRuntime): void {\n assertRequiredPorts(runtime)\n provide(RUNTIME_KEY, runtime)\n}\n\n/** Доступ к рантайму из любого composable/стора ядра. */\nexport function useRuntime(): StorefrontRuntime {\n const runtime = inject(RUNTIME_KEY)\n if (!runtime) {\n throw new Error(\n '[@zenky/storefront-vue] Runtime was not provided. ' +\n 'Install the plugin with app.use(createStorefront(runtime)).'\n )\n }\n return runtime\n}\n","import { defineStore } from 'pinia'\nimport { computed, ref, type ComputedRef, type Ref } from 'vue'\n\nimport type { City, NestedCategory, Stock, Store } from '@zenky/storefront-api'\n\nimport type { Website } from '../website-settings'\n\n// Именованный return-тип (правило dts) — иначе Pinia-инференс развернёт SDK-типы в .d.ts.\nexport interface StoreProfileStore {\n store: Ref<Store | null>\n city: Ref<City | null>\n stock: Ref<Stock | null>\n categories: Ref<NestedCategory[]>\n website: Ref<Website | null>\n initStore: (store: Store, city: City, stock: Stock | null) => void\n setStock: (stock: Stock | null) => void\n setCategories: (categories: NestedCategory[]) => void\n initWebsite: (website: Website | null) => void\n isReady: ComputedRef<boolean>\n hasStock: ComputedRef<boolean>\n currency: ComputedRef<string>\n squareLogoUrl: ComputedRef<string | null>\n}\n\nexport const useStoreProfileStore = defineStore('zenky-store-profile', (): StoreProfileStore => {\n const store = ref<Store | null>(null)\n const city = ref<City | null>(null)\n const stock = ref<Stock | null>(null)\n const categories = ref<NestedCategory[]>([])\n const website = ref<Website | null>(null)\n\n function initStore(newStore: Store, newCity: City, newStock: Stock | null): void {\n store.value = newStore\n city.value = newCity\n stock.value = newStock\n }\n\n function setStock(newStock: Stock | null): void {\n stock.value = newStock\n }\n\n function setCategories(newCategories: NestedCategory[]): void {\n categories.value = newCategories\n }\n\n function initWebsite(newWebsite: Website | null): void {\n website.value = newWebsite\n }\n\n const isReady = computed(() => store.value !== null && city.value !== null)\n const hasStock = computed(() => stock.value !== null)\n const currency = computed<string>(() => store.value?.settings?.currency ?? 'RUB')\n\n const squareLogoUrl = computed<string | null>(() => {\n const logo = store.value?.square_logo ?? store.value?.logo\n if (!logo) return null\n\n return (\n logo.hd?.url ??\n logo.xlarge?.url ??\n logo.large?.url ??\n logo.medium?.url ??\n logo.placeholder?.url ??\n null\n )\n })\n\n return {\n store,\n city,\n stock,\n categories,\n website,\n initStore,\n setStock,\n setCategories,\n initWebsite,\n isReady,\n hasStock,\n currency,\n squareLogoUrl,\n }\n})\n","import { defineStore } from 'pinia'\nimport { computed, ref, type ComputedRef, type Ref } from 'vue'\n\nimport { useRuntime } from '../ports/runtime'\n\n// Ключи совпадают с прежними CookieKey.AuthToken/AuthPhone — чтобы не разлогинить юзеров.\nconst AUTH_TOKEN_KEY = 'zenky_auth_token'\nconst AUTH_PHONE_KEY = 'zenky_auth_phone'\nconst YEAR_SECONDS = 60 * 60 * 24 * 365\n\n// Именованный return-тип (правило dts).\nexport interface AuthStore {\n token: Ref<string | null>\n phone: Ref<string | null>\n countryCode: Ref<string>\n isAuthenticated: ComputedRef<boolean>\n initials: ComputedRef<string>\n setToken: (token: string, phone?: string, countryCode?: string) => void\n clearToken: () => void\n initFromCookie: () => void\n}\n\nexport const useAuthStore = defineStore('zenky-auth', (): AuthStore => {\n // Рантайм захватываем на верхнем уровне setup (стор впервые создаётся в контексте\n // setup app.vue) — actions потом используют замыкание, не завися от inject после await.\n // SameSite/iframe-логика кук — целиком в cookie-адаптере приложения.\n const { storage, sdk } = useRuntime()\n\n const token = ref<string | null>(null)\n const phone = ref<string | null>(null)\n const countryCode = ref('RU')\n\n const isAuthenticated = computed(() => token.value !== null && token.value !== '')\n\n const initials = computed(() => {\n if (!phone.value) return '?'\n return phone.value.replace(/\\D/g, '').slice(-4)\n })\n\n function setToken(nextToken: string, nextPhone?: string, nextCountryCode?: string): void {\n token.value = nextToken\n storage.set(AUTH_TOKEN_KEY, nextToken, { maxAge: YEAR_SECONDS })\n sdk.setApiToken(nextToken)\n\n if (nextPhone) {\n phone.value = nextPhone\n storage.set(AUTH_PHONE_KEY, nextPhone, { maxAge: YEAR_SECONDS })\n }\n\n if (nextCountryCode) {\n countryCode.value = nextCountryCode\n }\n }\n\n function clearToken(): void {\n token.value = null\n phone.value = null\n storage.remove(AUTH_TOKEN_KEY)\n storage.remove(AUTH_PHONE_KEY)\n sdk.setApiToken(null)\n }\n\n function initFromCookie(): void {\n const savedToken = storage.get(AUTH_TOKEN_KEY)\n if (savedToken) {\n token.value = savedToken\n sdk.setApiToken(savedToken)\n }\n\n const savedPhone = storage.get(AUTH_PHONE_KEY)\n if (savedPhone) {\n phone.value = savedPhone\n }\n }\n\n return {\n token,\n phone,\n countryCode,\n isAuthenticated,\n initials,\n setToken,\n clearToken,\n initFromCookie,\n }\n})\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cart/useCartCredentials.ts","../src/promotions/usePromotionsChecker.ts"],"names":[],"mappings":"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","file":"chunk-YREGCQSB.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.isAuthenticated ? (authStore.token ?? undefined) : undefined\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 */\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"]}