@zenky/storefront-vue 0.10.10 → 0.10.12

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 (55) hide show
  1. package/CHANGELOG.md +139 -0
  2. package/README.md +1 -1
  3. package/dist/auth/index.d.ts +14 -0
  4. package/dist/auth/index.js +5 -0
  5. package/dist/auth/index.js.map +1 -0
  6. package/dist/cart/index.d.ts +4 -28
  7. package/dist/cart/index.js +9 -6
  8. package/dist/chunk-5B2P5W3E.js +20 -0
  9. package/dist/chunk-5B2P5W3E.js.map +1 -0
  10. package/dist/{chunk-32SLDGE5.js → chunk-6FVXAF7L.js} +4 -3
  11. package/dist/chunk-6FVXAF7L.js.map +1 -0
  12. package/dist/{chunk-4UMDIBW5.js → chunk-EM6H5WFS.js} +19 -110
  13. package/dist/chunk-EM6H5WFS.js.map +1 -0
  14. package/dist/chunk-IOYYCA75.js +52 -0
  15. package/dist/chunk-IOYYCA75.js.map +1 -0
  16. package/dist/chunk-LUJSF6V7.js +530 -0
  17. package/dist/chunk-LUJSF6V7.js.map +1 -0
  18. package/dist/{chunk-GXDTRTUT.js → chunk-RURXGVWW.js} +35 -6
  19. package/dist/chunk-RURXGVWW.js.map +1 -0
  20. package/dist/{chunk-XULHV6SS.js → chunk-TE2QPH74.js} +3 -3
  21. package/dist/{chunk-XULHV6SS.js.map → chunk-TE2QPH74.js.map} +1 -1
  22. package/dist/chunk-TE42OCFK.js +102 -0
  23. package/dist/chunk-TE42OCFK.js.map +1 -0
  24. package/dist/chunk-TIQ7AJLY.js +52 -0
  25. package/dist/chunk-TIQ7AJLY.js.map +1 -0
  26. package/dist/{chunk-GILJFP55.js → chunk-VTZYJ6OZ.js} +2 -2
  27. package/dist/chunk-VTZYJ6OZ.js.map +1 -0
  28. package/dist/{chunk-46FNHMWC.js → chunk-W43D7JYV.js} +5 -4
  29. package/dist/chunk-W43D7JYV.js.map +1 -0
  30. package/dist/{chunk-QZ3S3NN3.js → chunk-WTZXTBF6.js} +3 -47
  31. package/dist/chunk-WTZXTBF6.js.map +1 -0
  32. package/dist/index.d.ts +5 -3
  33. package/dist/index.js +15 -11
  34. package/dist/ports/index.d.ts +1 -1
  35. package/dist/ports/index.js +1 -1
  36. package/dist/products/index.js +3 -2
  37. package/dist/promotions/index.js +4 -3
  38. package/dist/seo/index.js +5 -4
  39. package/dist/seo/index.js.map +1 -1
  40. package/dist/stores/index.d.ts +56 -1
  41. package/dist/stores/index.js +7 -3
  42. package/dist/types-CXm2F6Hz.d.ts +55 -0
  43. package/dist/useCheckoutSubmit-C934F26-.d.ts +34 -0
  44. package/dist/utils/index.d.ts +6 -1
  45. package/dist/utils/index.js +1 -1
  46. package/docs/architecture.md +79 -3
  47. package/package.json +7 -3
  48. package/dist/chunk-32SLDGE5.js.map +0 -1
  49. package/dist/chunk-46FNHMWC.js.map +0 -1
  50. package/dist/chunk-4UMDIBW5.js.map +0 -1
  51. package/dist/chunk-FXKG5TFQ.js +0 -38
  52. package/dist/chunk-FXKG5TFQ.js.map +0 -1
  53. package/dist/chunk-GILJFP55.js.map +0 -1
  54. package/dist/chunk-GXDTRTUT.js.map +0 -1
  55. package/dist/chunk-QZ3S3NN3.js.map +0 -1
@@ -0,0 +1,52 @@
1
+ import { defineStore } from 'pinia';
2
+ import { ref, computed } from 'vue';
3
+
4
+ // src/stores/store-profile.ts
5
+ var useStoreProfileStore = defineStore("zenky-store-profile", () => {
6
+ const store = ref(null);
7
+ const city = ref(null);
8
+ const stock = ref(null);
9
+ const categories = ref([]);
10
+ const website = ref(null);
11
+ function initStore(newStore, newCity, newStock) {
12
+ store.value = newStore;
13
+ city.value = newCity;
14
+ stock.value = newStock;
15
+ }
16
+ function setStock(newStock) {
17
+ stock.value = newStock;
18
+ }
19
+ function setCategories(newCategories) {
20
+ categories.value = newCategories;
21
+ }
22
+ function initWebsite(newWebsite) {
23
+ website.value = newWebsite;
24
+ }
25
+ const isReady = computed(() => store.value !== null && city.value !== null);
26
+ const hasStock = computed(() => stock.value !== null);
27
+ const currency = computed(() => store.value?.settings?.currency ?? "RUB");
28
+ const squareLogoUrl = computed(() => {
29
+ const logo = store.value?.square_logo ?? store.value?.logo;
30
+ if (!logo) return null;
31
+ return logo.hd?.url ?? logo.xlarge?.url ?? logo.large?.url ?? logo.medium?.url ?? logo.placeholder?.url ?? null;
32
+ });
33
+ return {
34
+ store,
35
+ city,
36
+ stock,
37
+ categories,
38
+ website,
39
+ initStore,
40
+ setStock,
41
+ setCategories,
42
+ initWebsite,
43
+ isReady,
44
+ hasStock,
45
+ currency,
46
+ squareLogoUrl
47
+ };
48
+ });
49
+
50
+ export { useStoreProfileStore };
51
+ //# sourceMappingURL=chunk-IOYYCA75.js.map
52
+ //# sourceMappingURL=chunk-IOYYCA75.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/stores/store-profile.ts"],"names":[],"mappings":";;;;AAwBO,IAAM,oBAAA,GAAuB,WAAA,CAAY,qBAAA,EAAuB,MAAyB;AAC5F,EAAA,MAAM,KAAA,GAAQ,IAAkB,IAAI,CAAA;AACpC,EAAA,MAAM,IAAA,GAAO,IAAiB,IAAI,CAAA;AAClC,EAAA,MAAM,KAAA,GAAQ,IAAkB,IAAI,CAAA;AACpC,EAAA,MAAM,UAAA,GAAa,GAAA,CAAsB,EAAE,CAAA;AAC3C,EAAA,MAAM,OAAA,GAAU,IAAoB,IAAI,CAAA;AAExC,EAAA,SAAS,SAAA,CAAU,QAAA,EAAiB,OAAA,EAAe,QAAA,EAA8B;AAC7E,IAAA,KAAA,CAAM,KAAA,GAAQ,QAAA;AACd,IAAA,IAAA,CAAK,KAAA,GAAQ,OAAA;AACb,IAAA,KAAA,CAAM,KAAA,GAAQ,QAAA;AAAA,EAClB;AAEA,EAAA,SAAS,SAAS,QAAA,EAA8B;AAC5C,IAAA,KAAA,CAAM,KAAA,GAAQ,QAAA;AAAA,EAClB;AAEA,EAAA,SAAS,cAAc,aAAA,EAAuC;AAC1D,IAAA,UAAA,CAAW,KAAA,GAAQ,aAAA;AAAA,EACvB;AAEA,EAAA,SAAS,YAAY,UAAA,EAAkC;AACnD,IAAA,OAAA,CAAQ,KAAA,GAAQ,UAAA;AAAA,EACpB;AAEA,EAAA,MAAM,OAAA,GAAU,SAAS,MAAM,KAAA,CAAM,UAAU,IAAA,IAAQ,IAAA,CAAK,UAAU,IAAI,CAAA;AAC1E,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,MAAM,KAAA,CAAM,UAAU,IAAI,CAAA;AACpD,EAAA,MAAM,WAAW,QAAA,CAAiB,MAAM,MAAM,KAAA,EAAO,QAAA,EAAU,YAAY,KAAK,CAAA;AAEhF,EAAA,MAAM,aAAA,GAAgB,SAAwB,MAAM;AAChD,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,KAAA,EAAO,WAAA,IAAe,MAAM,KAAA,EAAO,IAAA;AACtD,IAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAElB,IAAA,OACI,IAAA,CAAK,EAAA,EAAI,GAAA,IACT,IAAA,CAAK,QAAQ,GAAA,IACb,IAAA,CAAK,KAAA,EAAO,GAAA,IACZ,IAAA,CAAK,MAAA,EAAQ,GAAA,IACb,IAAA,CAAK,aAAa,GAAA,IAClB,IAAA;AAAA,EAER,CAAC,CAAA;AAED,EAAA,OAAO;AAAA,IACH,KAAA;AAAA,IACA,IAAA;AAAA,IACA,KAAA;AAAA,IACA,UAAA;AAAA,IACA,OAAA;AAAA,IACA,SAAA;AAAA,IACA,QAAA;AAAA,IACA,aAAA;AAAA,IACA,WAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAA;AAAA,IACA,QAAA;AAAA,IACA;AAAA,GACJ;AACJ,CAAC","file":"chunk-IOYYCA75.js","sourcesContent":["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// Named return type (the dts rule) — otherwise Pinia's inference would expand the SDK types in the .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"]}
@@ -0,0 +1,530 @@
1
+ import { useAvailableConfirmationChannels } from './chunk-5B2P5W3E.js';
2
+ import { getCartErrorCode, logCartError, getValidationErrors, getCartErrorMessage } from './chunk-TE42OCFK.js';
3
+ import { useRuntime, useAuthStore } from './chunk-WTZXTBF6.js';
4
+ import { AUTH_STEP, CODE_CONTEXT, CHANNEL_INTENT, toConfirmationChannel, toRequestedMethod, CONFIRMATION_CHANNEL } from './chunk-TIQ7AJLY.js';
5
+ import { useStoreProfileStore } from './chunk-IOYYCA75.js';
6
+ import { defineStore, storeToRefs } from 'pinia';
7
+ import { ref, computed, customRef } from 'vue';
8
+ import { RecaptchaAction } from '@zenky/storefront-api';
9
+
10
+ var useProductsStore = defineStore("zenky-products", () => {
11
+ const products = ref([]);
12
+ function setProducts(list) {
13
+ products.value = list;
14
+ }
15
+ const hasProducts = computed(() => products.value.length > 0);
16
+ return { products, setProducts, hasProducts };
17
+ });
18
+ var RESEND_TIMER_SECONDS = 60;
19
+ var AUTH_ERROR_CODE = {
20
+ ConfirmationRequired: "auth.registration.confirmation_required",
21
+ InvalidCode: "auth.confirmation.invalid_code",
22
+ InvalidRegistrationCode: "auth.registration.invalid_confirmation_code",
23
+ InvalidResetCode: "auth.password_reset.invalid_code",
24
+ ExpiredCode: "auth.confirmation.expired_code",
25
+ OtpRequestFailed: "auth.otp_request.failed"
26
+ };
27
+ var useAuthFlowStore = defineStore("zenky-auth-flow", () => {
28
+ const { sdk, notifier, messages } = useRuntime();
29
+ const authStore = useAuthStore();
30
+ const profileStore = useStoreProfileStore();
31
+ const currentStep = ref(AUTH_STEP.Phone);
32
+ const phone = invalidatingRef("");
33
+ const countryCode = invalidatingRef("RU");
34
+ const loading = ref(false);
35
+ const error = ref(null);
36
+ const codeContext = ref(CODE_CONTEXT.Register);
37
+ const confirmationMethod = ref(null);
38
+ const resetCode = ref("");
39
+ const registerCode = ref("");
40
+ const resendTimerEndsAt = ref(0);
41
+ const fieldErrors = ref({});
42
+ const pendingPassword = ref("");
43
+ const channelIntent = ref(null);
44
+ const lastFailedChannel = ref(null);
45
+ const operationRevision = ref(0);
46
+ function invalidatePendingOperation() {
47
+ operationRevision.value += 1;
48
+ }
49
+ function beginOperation() {
50
+ invalidatePendingOperation();
51
+ loading.value = false;
52
+ return operationRevision.value;
53
+ }
54
+ function cancelPendingOperation() {
55
+ beginOperation();
56
+ }
57
+ function isStale(revision) {
58
+ return revision !== operationRevision.value;
59
+ }
60
+ function invalidatingRef(initial) {
61
+ let value = initial;
62
+ return customRef((track, trigger) => ({
63
+ get() {
64
+ track();
65
+ return value;
66
+ },
67
+ set(newValue) {
68
+ if (newValue === value) return;
69
+ value = newValue;
70
+ cancelPendingOperation();
71
+ trigger();
72
+ }
73
+ }));
74
+ }
75
+ const availableChannels = useAvailableConfirmationChannels();
76
+ function resolveOutgoingMethod() {
77
+ const channel = confirmationMethod.value ?? (availableChannels.value.length === 1 ? availableChannels.value[0] : void 0);
78
+ return toRequestedMethod(channel);
79
+ }
80
+ function getStoreId() {
81
+ return profileStore.store?.id ?? null;
82
+ }
83
+ function phoneRequest() {
84
+ return { number: phone.value, country: countryCode.value };
85
+ }
86
+ function clearError() {
87
+ error.value = null;
88
+ fieldErrors.value = {};
89
+ }
90
+ function handleAuthError(e, fallbackKey, scope) {
91
+ logCartError({ scope: `auth-${scope}`, context: { step: currentStep.value } }, e);
92
+ const fallback = messages.format(fallbackKey);
93
+ const validationErrors = getValidationErrors(e);
94
+ if (Object.keys(validationErrors).length > 0) {
95
+ notifier.error(getCartErrorMessage(e, fallback));
96
+ fieldErrors.value = validationErrors;
97
+ return;
98
+ }
99
+ error.value = getCartErrorMessage(e, fallback);
100
+ }
101
+ function handleOtpDispatchError(e, intent, scope, attemptedChannel) {
102
+ if (getCartErrorCode(e) === AUTH_ERROR_CODE.OtpRequestFailed && availableChannels.value.length >= 2) {
103
+ logCartError({ scope: `auth-${scope}`, context: { step: currentStep.value } }, e);
104
+ lastFailedChannel.value = attemptedChannel && attemptedChannel !== CONFIRMATION_CHANNEL.Call ? attemptedChannel : null;
105
+ confirmationMethod.value = null;
106
+ error.value = messages.format("auth.otpUnavailable");
107
+ channelIntent.value = intent;
108
+ currentStep.value = AUTH_STEP.Channel;
109
+ return true;
110
+ }
111
+ return false;
112
+ }
113
+ function changeChannel() {
114
+ cancelPendingOperation();
115
+ confirmationMethod.value = null;
116
+ lastFailedChannel.value = null;
117
+ }
118
+ function reset() {
119
+ cancelPendingOperation();
120
+ currentStep.value = AUTH_STEP.Phone;
121
+ phone.value = "";
122
+ countryCode.value = "RU";
123
+ error.value = null;
124
+ fieldErrors.value = {};
125
+ codeContext.value = CODE_CONTEXT.Register;
126
+ confirmationMethod.value = null;
127
+ resetCode.value = "";
128
+ registerCode.value = "";
129
+ resendTimerEndsAt.value = 0;
130
+ pendingPassword.value = "";
131
+ channelIntent.value = null;
132
+ lastFailedChannel.value = null;
133
+ }
134
+ async function checkPhone(getRecaptchaPayload) {
135
+ const revision = beginOperation();
136
+ clearError();
137
+ codeContext.value = CODE_CONTEXT.Register;
138
+ resendTimerEndsAt.value = 0;
139
+ confirmationMethod.value = null;
140
+ lastFailedChannel.value = null;
141
+ pendingPassword.value = "";
142
+ channelIntent.value = null;
143
+ resetCode.value = "";
144
+ registerCode.value = "";
145
+ const storeId = getStoreId();
146
+ if (!storeId) return;
147
+ const phoneSnapshot = phoneRequest();
148
+ loading.value = true;
149
+ try {
150
+ const result = await sdk.auth.checkPhone(storeId, { phone: phoneSnapshot });
151
+ if (isStale(revision)) return;
152
+ if (result.registered && result.confirmed) {
153
+ currentStep.value = AUTH_STEP.Login;
154
+ } else if (result.registered && !result.confirmed) {
155
+ codeContext.value = CODE_CONTEXT.Register;
156
+ await resendCode(getRecaptchaPayload, revision);
157
+ if (isStale(revision)) return;
158
+ if (currentStep.value !== AUTH_STEP.Channel) currentStep.value = AUTH_STEP.Code;
159
+ } else {
160
+ currentStep.value = AUTH_STEP.Register;
161
+ }
162
+ } catch (e) {
163
+ if (!isStale(revision)) handleAuthError(e, "auth.checkPhoneFailed", "check-phone");
164
+ } finally {
165
+ if (!isStale(revision)) loading.value = false;
166
+ }
167
+ }
168
+ async function login(password, getRecaptchaPayload, parentRevision) {
169
+ const revision = parentRevision ?? beginOperation();
170
+ clearError();
171
+ const storeId = getStoreId();
172
+ if (!storeId) return false;
173
+ const phoneSnapshot = phoneRequest();
174
+ loading.value = true;
175
+ try {
176
+ const result = await sdk.auth.login(storeId, { phone: phoneSnapshot, password });
177
+ if (isStale(revision)) return false;
178
+ authStore.setToken(result.token, phoneSnapshot.number, phoneSnapshot.country);
179
+ pendingPassword.value = "";
180
+ return true;
181
+ } catch (e) {
182
+ if (isStale(revision)) return false;
183
+ if (getCartErrorCode(e) === AUTH_ERROR_CODE.ConfirmationRequired) {
184
+ pendingPassword.value = password;
185
+ codeContext.value = CODE_CONTEXT.Register;
186
+ loading.value = false;
187
+ await resendCode(getRecaptchaPayload, revision);
188
+ if (isStale(revision)) return false;
189
+ if (currentStep.value !== AUTH_STEP.Channel) currentStep.value = AUTH_STEP.Code;
190
+ return false;
191
+ }
192
+ handleAuthError(e, "auth.invalidPassword", "login");
193
+ return false;
194
+ } finally {
195
+ if (!isStale(revision)) loading.value = false;
196
+ }
197
+ }
198
+ async function register(password, getRecaptchaPayload, parentRevision) {
199
+ const revision = parentRevision ?? beginOperation();
200
+ clearError();
201
+ pendingPassword.value = password;
202
+ if (confirmationMethod.value === null && availableChannels.value.length >= 2) {
203
+ channelIntent.value = CHANNEL_INTENT.Register;
204
+ currentStep.value = AUTH_STEP.Channel;
205
+ return false;
206
+ }
207
+ const storeId = getStoreId();
208
+ if (!storeId) return false;
209
+ const phoneSnapshot = phoneRequest();
210
+ const method = resolveOutgoingMethod();
211
+ const attemptedChannel = confirmationMethod.value;
212
+ loading.value = true;
213
+ try {
214
+ const recaptcha = await getRecaptchaPayload(RecaptchaAction.Registration);
215
+ if (isStale(revision)) return false;
216
+ const result = await sdk.auth.register(storeId, {
217
+ phone: phoneSnapshot,
218
+ password,
219
+ recaptcha,
220
+ method
221
+ });
222
+ if (isStale(revision)) return false;
223
+ if (result.confirmation_required) {
224
+ codeContext.value = CODE_CONTEXT.Register;
225
+ confirmationMethod.value = toConfirmationChannel(result.method);
226
+ resendTimerEndsAt.value = Date.now() + RESEND_TIMER_SECONDS * 1e3;
227
+ currentStep.value = AUTH_STEP.Code;
228
+ channelIntent.value = null;
229
+ lastFailedChannel.value = null;
230
+ return false;
231
+ }
232
+ channelIntent.value = null;
233
+ lastFailedChannel.value = null;
234
+ return await login(password, getRecaptchaPayload, revision);
235
+ } catch (e) {
236
+ if (isStale(revision)) return false;
237
+ if (!handleOtpDispatchError(e, CHANNEL_INTENT.Register, "register", attemptedChannel)) {
238
+ handleAuthError(e, "auth.registerFailed", "register");
239
+ }
240
+ return false;
241
+ } finally {
242
+ if (!isStale(revision)) loading.value = false;
243
+ }
244
+ }
245
+ async function confirmRegistration(code, password) {
246
+ const revision = beginOperation();
247
+ clearError();
248
+ const storeId = getStoreId();
249
+ if (!storeId) return false;
250
+ const phoneSnapshot = phoneRequest();
251
+ const passwordSnapshot = password || pendingPassword.value || void 0;
252
+ loading.value = true;
253
+ try {
254
+ const result = await sdk.auth.confirmRegistration(storeId, {
255
+ phone: phoneSnapshot,
256
+ code,
257
+ password: passwordSnapshot
258
+ });
259
+ if (isStale(revision)) return false;
260
+ authStore.setToken(result.token, phoneSnapshot.number, phoneSnapshot.country);
261
+ pendingPassword.value = "";
262
+ return true;
263
+ } catch (e) {
264
+ if (isStale(revision)) return false;
265
+ handleAuthError(e, "auth.invalidCode", "confirm-registration");
266
+ return false;
267
+ } finally {
268
+ if (!isStale(revision)) loading.value = false;
269
+ }
270
+ }
271
+ async function resendCode(getRecaptchaPayload, parentRevision) {
272
+ const revision = parentRevision ?? beginOperation();
273
+ clearError();
274
+ if (confirmationMethod.value === null && availableChannels.value.length >= 2) {
275
+ channelIntent.value = CHANNEL_INTENT.Resend;
276
+ currentStep.value = AUTH_STEP.Channel;
277
+ return 0;
278
+ }
279
+ const storeId = getStoreId();
280
+ if (!storeId) return 0;
281
+ const phoneSnapshot = phoneRequest();
282
+ const method = resolveOutgoingMethod();
283
+ const context = codeContext.value;
284
+ const attemptedChannel = confirmationMethod.value;
285
+ loading.value = true;
286
+ try {
287
+ const recaptcha = await getRecaptchaPayload(
288
+ context === CODE_CONTEXT.Reset ? RecaptchaAction.ResetPassword : RecaptchaAction.ResendRegistrationCode
289
+ );
290
+ if (isStale(revision)) return 0;
291
+ const result = context === CODE_CONTEXT.Reset ? await sdk.auth.dispatchPasswordReset(storeId, {
292
+ phone: phoneSnapshot,
293
+ recaptcha,
294
+ method
295
+ }) : await sdk.auth.resendRegistrationConfirmation(storeId, {
296
+ phone: phoneSnapshot,
297
+ recaptcha,
298
+ method
299
+ });
300
+ if (isStale(revision)) return 0;
301
+ confirmationMethod.value = toConfirmationChannel(result.method);
302
+ resendTimerEndsAt.value = Date.now() + RESEND_TIMER_SECONDS * 1e3;
303
+ lastFailedChannel.value = null;
304
+ if (currentStep.value === AUTH_STEP.Channel) {
305
+ channelIntent.value = null;
306
+ currentStep.value = AUTH_STEP.Code;
307
+ }
308
+ return RESEND_TIMER_SECONDS;
309
+ } catch (e) {
310
+ if (isStale(revision)) return 0;
311
+ if (!handleOtpDispatchError(e, CHANNEL_INTENT.Resend, "resend-code", attemptedChannel)) {
312
+ handleAuthError(e, "auth.resendCodeFailed", "resend-code");
313
+ }
314
+ return 0;
315
+ } finally {
316
+ if (!isStale(revision)) loading.value = false;
317
+ }
318
+ }
319
+ async function dispatchReset(getRecaptchaPayload, parentRevision) {
320
+ const revision = parentRevision ?? beginOperation();
321
+ clearError();
322
+ if (confirmationMethod.value === null && availableChannels.value.length >= 2) {
323
+ channelIntent.value = CHANNEL_INTENT.DispatchReset;
324
+ currentStep.value = AUTH_STEP.Channel;
325
+ return;
326
+ }
327
+ const storeId = getStoreId();
328
+ if (!storeId) return;
329
+ const phoneSnapshot = phoneRequest();
330
+ const method = resolveOutgoingMethod();
331
+ const attemptedChannel = confirmationMethod.value;
332
+ loading.value = true;
333
+ try {
334
+ const recaptcha = await getRecaptchaPayload(RecaptchaAction.ResetPassword);
335
+ if (isStale(revision)) return;
336
+ const result = await sdk.auth.dispatchPasswordReset(storeId, {
337
+ phone: phoneSnapshot,
338
+ recaptcha,
339
+ method
340
+ });
341
+ if (isStale(revision)) return;
342
+ codeContext.value = CODE_CONTEXT.Reset;
343
+ confirmationMethod.value = toConfirmationChannel(result.method);
344
+ resendTimerEndsAt.value = Date.now() + RESEND_TIMER_SECONDS * 1e3;
345
+ currentStep.value = AUTH_STEP.Code;
346
+ channelIntent.value = null;
347
+ lastFailedChannel.value = null;
348
+ } catch (e) {
349
+ if (isStale(revision)) return;
350
+ if (!handleOtpDispatchError(
351
+ e,
352
+ CHANNEL_INTENT.DispatchReset,
353
+ "dispatch-reset",
354
+ attemptedChannel
355
+ )) {
356
+ handleAuthError(e, "auth.dispatchResetFailed", "dispatch-reset");
357
+ }
358
+ } finally {
359
+ if (!isStale(revision)) loading.value = false;
360
+ }
361
+ }
362
+ async function resetPassword(code, password) {
363
+ const revision = beginOperation();
364
+ clearError();
365
+ const storeId = getStoreId();
366
+ if (!storeId) return false;
367
+ const phoneSnapshot = phoneRequest();
368
+ loading.value = true;
369
+ try {
370
+ const result = await sdk.auth.resetPassword(storeId, {
371
+ phone: phoneSnapshot,
372
+ code,
373
+ password
374
+ });
375
+ if (isStale(revision)) return false;
376
+ authStore.setToken(result.token, phoneSnapshot.number, phoneSnapshot.country);
377
+ return true;
378
+ } catch (e) {
379
+ if (isStale(revision)) return false;
380
+ const errorCode = getCartErrorCode(e);
381
+ if (errorCode === AUTH_ERROR_CODE.InvalidCode || errorCode === AUTH_ERROR_CODE.InvalidRegistrationCode || errorCode === AUTH_ERROR_CODE.InvalidResetCode || errorCode === AUTH_ERROR_CODE.ExpiredCode) {
382
+ handleAuthError(e, "auth.invalidCode", "reset-password");
383
+ resetCode.value = "";
384
+ currentStep.value = AUTH_STEP.Code;
385
+ return false;
386
+ }
387
+ handleAuthError(e, "auth.resetPasswordFailed", "reset-password");
388
+ return false;
389
+ } finally {
390
+ if (!isStale(revision)) loading.value = false;
391
+ }
392
+ }
393
+ async function selectChannel(channel, getRecaptchaPayload) {
394
+ if (!availableChannels.value.includes(channel)) return false;
395
+ const revision = beginOperation();
396
+ confirmationMethod.value = channel;
397
+ const intent = channelIntent.value;
398
+ if (intent === CHANNEL_INTENT.Register)
399
+ return register(pendingPassword.value, getRecaptchaPayload, revision);
400
+ if (intent === CHANNEL_INTENT.Resend) {
401
+ await resendCode(getRecaptchaPayload, revision);
402
+ return false;
403
+ }
404
+ if (intent === CHANNEL_INTENT.DispatchReset) {
405
+ await dispatchReset(getRecaptchaPayload, revision);
406
+ return false;
407
+ }
408
+ return false;
409
+ }
410
+ function goToChannelBack() {
411
+ cancelPendingOperation();
412
+ clearError();
413
+ const intent = channelIntent.value;
414
+ channelIntent.value = null;
415
+ if (intent === CHANNEL_INTENT.Register) currentStep.value = AUTH_STEP.Register;
416
+ else if (intent === CHANNEL_INTENT.Resend) currentStep.value = AUTH_STEP.Code;
417
+ else if (intent === CHANNEL_INTENT.DispatchReset) currentStep.value = AUTH_STEP.Reset;
418
+ else currentStep.value = AUTH_STEP.Phone;
419
+ }
420
+ function goToReset() {
421
+ cancelPendingOperation();
422
+ clearError();
423
+ if (codeContext.value === CODE_CONTEXT.Reset && resendTimerEndsAt.value > Date.now()) {
424
+ currentStep.value = AUTH_STEP.Code;
425
+ } else {
426
+ currentStep.value = AUTH_STEP.Reset;
427
+ }
428
+ }
429
+ function goToPhone() {
430
+ cancelPendingOperation();
431
+ clearError();
432
+ currentStep.value = AUTH_STEP.Phone;
433
+ }
434
+ function goToMethod() {
435
+ cancelPendingOperation();
436
+ clearError();
437
+ currentStep.value = AUTH_STEP.Method;
438
+ }
439
+ function goToLogin() {
440
+ cancelPendingOperation();
441
+ clearError();
442
+ currentStep.value = AUTH_STEP.Login;
443
+ }
444
+ function goToNewPassword(code) {
445
+ cancelPendingOperation();
446
+ clearError();
447
+ resetCode.value = code;
448
+ currentStep.value = AUTH_STEP.NewPassword;
449
+ }
450
+ function goToResetCode() {
451
+ cancelPendingOperation();
452
+ clearError();
453
+ resetCode.value = "";
454
+ currentStep.value = AUTH_STEP.Code;
455
+ }
456
+ function goToRegisterPassword(code) {
457
+ cancelPendingOperation();
458
+ clearError();
459
+ registerCode.value = code;
460
+ currentStep.value = AUTH_STEP.RegisterPassword;
461
+ }
462
+ function goToRegisterCode() {
463
+ cancelPendingOperation();
464
+ clearError();
465
+ registerCode.value = "";
466
+ currentStep.value = AUTH_STEP.Code;
467
+ }
468
+ return {
469
+ currentStep,
470
+ phone,
471
+ countryCode,
472
+ loading,
473
+ error,
474
+ fieldErrors,
475
+ codeContext,
476
+ confirmationMethod,
477
+ channelIntent,
478
+ lastFailedChannel,
479
+ resetCode,
480
+ registerCode,
481
+ resendTimerEndsAt,
482
+ pendingPassword,
483
+ availableChannels,
484
+ checkPhone,
485
+ login,
486
+ register,
487
+ confirmRegistration,
488
+ resendCode,
489
+ dispatchReset,
490
+ resetPassword,
491
+ selectChannel,
492
+ changeChannel,
493
+ goToChannelBack,
494
+ goToReset,
495
+ goToPhone,
496
+ goToMethod,
497
+ goToLogin,
498
+ goToNewPassword,
499
+ goToResetCode,
500
+ goToRegisterPassword,
501
+ goToRegisterCode,
502
+ reset
503
+ };
504
+ });
505
+ function useStore() {
506
+ const profileStore = useStoreProfileStore();
507
+ return {
508
+ store: computed(() => profileStore.store),
509
+ city: computed(() => profileStore.city),
510
+ stock: computed(() => profileStore.stock)
511
+ };
512
+ }
513
+ function useStorefrontProfile() {
514
+ const profileStore = useStoreProfileStore();
515
+ const { store, city, stock, categories } = storeToRefs(profileStore);
516
+ const isReady = computed(() => profileStore.isReady);
517
+ const hasStock = computed(() => profileStore.hasStock);
518
+ return {
519
+ store,
520
+ city,
521
+ stock,
522
+ categories,
523
+ isReady,
524
+ hasStock
525
+ };
526
+ }
527
+
528
+ export { RESEND_TIMER_SECONDS, useAuthFlowStore, useProductsStore, useStore, useStorefrontProfile };
529
+ //# sourceMappingURL=chunk-LUJSF6V7.js.map
530
+ //# sourceMappingURL=chunk-LUJSF6V7.js.map