@foxford/sdk 5.0.0

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/index.js ADDED
@@ -0,0 +1,1748 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var __async = (__this, __arguments, generator) => {
21
+ return new Promise((resolve, reject) => {
22
+ var fulfilled = (value) => {
23
+ try {
24
+ step(generator.next(value));
25
+ } catch (e) {
26
+ reject(e);
27
+ }
28
+ };
29
+ var rejected = (value) => {
30
+ try {
31
+ step(generator.throw(value));
32
+ } catch (e) {
33
+ reject(e);
34
+ }
35
+ };
36
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
37
+ step((generator = generator.apply(__this, __arguments)).next());
38
+ });
39
+ };
40
+
41
+ // src/foxford.ts
42
+ import { ApiService, CaptchaService as CaptchaService2 } from "@foxford/services";
43
+
44
+ // src/antibot/index.ts
45
+ if (window.antibotInitialized === void 0) window.antibotInitialized = false;
46
+ var _FoxfordAntibot = class _FoxfordAntibot {
47
+ constructor(config = _FoxfordAntibot.DEFAULT_CONFIG) {
48
+ this.createAntibotFrame = (params) => {
49
+ if (window.location.hostname.endsWith("foxford.ru") || window.location.hostname.endsWith("netology-group.services") || this.config.debug) {
50
+ const frame = _FoxfordAntibot.createFrame(params.src, params == null ? void 0 : params.onload, params == null ? void 0 : params.onerror);
51
+ document.body.appendChild(frame);
52
+ window.antibotInitialized = true;
53
+ }
54
+ };
55
+ this.config = __spreadValues(__spreadValues({}, _FoxfordAntibot.DEFAULT_CONFIG), config);
56
+ if (!document.body) throw new Error("Body element not found");
57
+ if (window.onCaptureReady !== void 0) {
58
+ console.debug("Seo4Ajax crawler injects own callback. FoxfordAntibot initialization will be ignored.");
59
+ return;
60
+ }
61
+ if (_FoxfordAntibot.antibotIsInitialized()) {
62
+ console.debug("FoxfordAntibot is already mounted");
63
+ return;
64
+ }
65
+ if (process.env.NODE_ENV === "production") {
66
+ this.createAntibotFrame({
67
+ onerror: this.config.antibotOnerror,
68
+ onload: this.config.antibotOnload,
69
+ src: this.config.antibotFrameSrc
70
+ });
71
+ }
72
+ }
73
+ static antibotIsInitialized() {
74
+ if (window.antibotInitialized || document.querySelectorAll(`iframe.${_FoxfordAntibot.FRAME_CLASSNAME}`).length > 0) {
75
+ return true;
76
+ }
77
+ try {
78
+ return window.top ? window.self !== window.top && Boolean(window.top.antibotInitialized) : false;
79
+ } catch (e) {
80
+ return false;
81
+ }
82
+ }
83
+ };
84
+ _FoxfordAntibot.FOXFORD_ANTIBOT_URL = "https://foxford.ru/antibot/ping";
85
+ _FoxfordAntibot.DEFAULT_CONFIG = {
86
+ antibotFrameSrc: _FoxfordAntibot.FOXFORD_ANTIBOT_URL
87
+ };
88
+ _FoxfordAntibot.FRAME_CLASSNAME = "antibot";
89
+ _FoxfordAntibot.createFrame = (src, onload, onerror) => {
90
+ const frame = document.createElement("iframe");
91
+ frame.classList.add(_FoxfordAntibot.FRAME_CLASSNAME);
92
+ frame.style.width = "1px";
93
+ frame.style.height = "1px";
94
+ frame.style.position = "fixed";
95
+ frame.style.zIndex = "-1";
96
+ frame.style.top = "0";
97
+ frame.style.left = "0";
98
+ frame.style.border = "0";
99
+ frame.referrerPolicy = "origin";
100
+ frame.src = src;
101
+ frame.onload = (e) => {
102
+ if (typeof onload === "function") onload(e);
103
+ };
104
+ frame.onerror = () => {
105
+ if (typeof onerror === "function") onerror();
106
+ };
107
+ return frame;
108
+ };
109
+ var FoxfordAntibot = _FoxfordAntibot;
110
+
111
+ // src/constants.ts
112
+ var CSRF_COOKIE_NAME = "_csrf_token";
113
+ var FOXFORD_HOST = "https://foxford.ru";
114
+
115
+ // src/api/config.ts
116
+ var apiBaseConfig = {
117
+ headers: { "X-Requested-With": "XMLHttpRequest" },
118
+ withXSRFToken: true,
119
+ xsrfCookieName: CSRF_COOKIE_NAME,
120
+ xsrfHeaderName: "X-CSRF-Token"
121
+ };
122
+ var apiConfig = __spreadProps(__spreadValues({}, apiBaseConfig), {
123
+ withCredentials: true
124
+ });
125
+
126
+ // src/utils/camelize.ts
127
+ import camelcaseKeys from "camelcase-keys-deep";
128
+ import decamelizeKeys from "decamelize-keys-deep";
129
+ var camelize = (obj) => camelcaseKeys(obj);
130
+ var decamelize = (obj) => decamelizeKeys(obj);
131
+
132
+ // src/api/plugins/CamelizeRequestPlugin.ts
133
+ var CamelizeRequestPlugin = class {
134
+ constructor() {
135
+ this.pluginType = "request";
136
+ this.pluginName = "camelizeRequestPlugin";
137
+ }
138
+ // требуется публичный метод, а для внутренней реализации может понадобиться this
139
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
140
+ execute(config, instance) {
141
+ return new Promise((resolve) => {
142
+ const convert = typeof config.camelize === "boolean" ? config.camelize : true;
143
+ if (convert) {
144
+ const defaultTransform = instance.defaults.transformResponse;
145
+ const camelizeResponse = (data) => {
146
+ return camelize(data);
147
+ };
148
+ if (defaultTransform) {
149
+ config.transformResponse = Array.isArray(defaultTransform) ? [...defaultTransform, camelizeResponse] : [defaultTransform, camelizeResponse];
150
+ }
151
+ }
152
+ resolve(config);
153
+ });
154
+ }
155
+ // требуется публичный метод, а для внутренней реализации может понадобиться this
156
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
157
+ isApplicable(config) {
158
+ return typeof config.camelize === "boolean" ? config.camelize : true;
159
+ }
160
+ };
161
+
162
+ // src/api/plugins/DataLayerEventDispatcherPlugin.ts
163
+ var DataLayerEventDispatcherPlugin = class {
164
+ constructor() {
165
+ this.pluginType = "responseSuccess";
166
+ this.pluginName = "dataLayerEventDispatcherPlugin";
167
+ }
168
+ // требуется публичный метод, а для внутренней реализации может понадобиться this
169
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
170
+ execute(response) {
171
+ return new Promise((resolve) => {
172
+ try {
173
+ const rawResponse = JSON.parse(response.request.response);
174
+ if (Array.isArray(rawResponse["data_layer_events"])) {
175
+ if (!Array.isArray(window.dataLayer)) {
176
+ window.dataLayer = [];
177
+ }
178
+ window.dataLayer.push(...rawResponse["data_layer_events"]);
179
+ }
180
+ } catch (e) {
181
+ }
182
+ resolve(response);
183
+ });
184
+ }
185
+ // требуется публичный метод, а для внутренней реализации может понадобиться this
186
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
187
+ isApplicable() {
188
+ return true;
189
+ }
190
+ };
191
+
192
+ // src/utils/pathToRegexp.ts
193
+ function lexer(str) {
194
+ const tokens = [];
195
+ let i = 0;
196
+ while (i < str.length) {
197
+ const char = str[i];
198
+ if (char === "*" || char === "+" || char === "?") {
199
+ tokens.push({ index: i, type: "MODIFIER", value: str[i++] });
200
+ continue;
201
+ }
202
+ if (char === "\\") {
203
+ tokens.push({ index: i++, type: "ESCAPED_CHAR", value: str[i++] });
204
+ continue;
205
+ }
206
+ if (char === "{") {
207
+ tokens.push({ index: i, type: "OPEN", value: str[i++] });
208
+ continue;
209
+ }
210
+ if (char === "}") {
211
+ tokens.push({ index: i, type: "CLOSE", value: str[i++] });
212
+ continue;
213
+ }
214
+ if (char === ":") {
215
+ let name = "";
216
+ let j = i + 1;
217
+ while (j < str.length) {
218
+ const code = str.charCodeAt(j);
219
+ if (
220
+ // `0-9`
221
+ code >= 48 && code <= 57 || // `A-Z`
222
+ code >= 65 && code <= 90 || // `a-z`
223
+ code >= 97 && code <= 122 || // `_`
224
+ code === 95
225
+ ) {
226
+ name += str[j++];
227
+ continue;
228
+ }
229
+ break;
230
+ }
231
+ if (!name) throw new TypeError(`Missing parameter name at ${i}`);
232
+ tokens.push({ index: i, type: "NAME", value: name });
233
+ i = j;
234
+ continue;
235
+ }
236
+ if (char === "(") {
237
+ let count = 1;
238
+ let pattern = "";
239
+ let j = i + 1;
240
+ if (str[j] === "?") {
241
+ throw new TypeError(`Pattern cannot start with "?" at ${j}`);
242
+ }
243
+ while (j < str.length) {
244
+ if (str[j] === "\\") {
245
+ pattern += str[j++] + str[j++];
246
+ continue;
247
+ }
248
+ if (str[j] === ")") {
249
+ count--;
250
+ if (count === 0) {
251
+ j++;
252
+ break;
253
+ }
254
+ } else if (str[j] === "(") {
255
+ count++;
256
+ if (str[j + 1] !== "?") {
257
+ throw new TypeError(`Capturing groups are not allowed at ${j}`);
258
+ }
259
+ }
260
+ pattern += str[j++];
261
+ }
262
+ if (count) throw new TypeError(`Unbalanced pattern at ${i}`);
263
+ if (!pattern) throw new TypeError(`Missing pattern at ${i}`);
264
+ tokens.push({ index: i, type: "PATTERN", value: pattern });
265
+ i = j;
266
+ continue;
267
+ }
268
+ tokens.push({ index: i, type: "CHAR", value: str[i++] });
269
+ }
270
+ tokens.push({ index: i, type: "END", value: "" });
271
+ return tokens;
272
+ }
273
+ function parse(str, options = {}) {
274
+ const tokens = lexer(str);
275
+ const { prefixes = "./" } = options;
276
+ const defaultPattern = `[^${escapeString(options.delimiter || "/#?")}]+?`;
277
+ const result = [];
278
+ let key = 0;
279
+ let i = 0;
280
+ let path = "";
281
+ const tryConsume = (type) => {
282
+ var _a, _b;
283
+ if (i < tokens.length && ((_a = tokens[i]) == null ? void 0 : _a.type) === type) return (_b = tokens[i++]) == null ? void 0 : _b.value;
284
+ return void 0;
285
+ };
286
+ const mustConsume = (type) => {
287
+ var _a, _b;
288
+ const value = tryConsume(type);
289
+ if (value !== void 0) return value;
290
+ throw new TypeError(`Unexpected ${(_a = tokens[i]) == null ? void 0 : _a.type} at ${(_b = tokens[i]) == null ? void 0 : _b.index}, expected ${type}`);
291
+ };
292
+ const consumeText = () => {
293
+ let result2 = "";
294
+ let value;
295
+ while (value = tryConsume("CHAR") || tryConsume("ESCAPED_CHAR")) {
296
+ result2 += value;
297
+ }
298
+ return result2;
299
+ };
300
+ while (i < tokens.length) {
301
+ const char = tryConsume("CHAR");
302
+ const name = tryConsume("NAME");
303
+ const pattern = tryConsume("PATTERN");
304
+ if (name || pattern) {
305
+ let prefix = char || "";
306
+ if (prefixes.indexOf(prefix) === -1) {
307
+ path += prefix;
308
+ prefix = "";
309
+ }
310
+ if (path) {
311
+ result.push(path);
312
+ path = "";
313
+ }
314
+ result.push({
315
+ modifier: tryConsume("MODIFIER") || "",
316
+ name: name || key++,
317
+ pattern: pattern || defaultPattern,
318
+ prefix,
319
+ suffix: ""
320
+ });
321
+ continue;
322
+ }
323
+ const value = char || tryConsume("ESCAPED_CHAR");
324
+ if (value) {
325
+ path += value;
326
+ continue;
327
+ }
328
+ if (path) {
329
+ result.push(path);
330
+ path = "";
331
+ }
332
+ const open = tryConsume("OPEN");
333
+ if (open) {
334
+ const prefix = consumeText();
335
+ const name2 = tryConsume("NAME") || "";
336
+ const pattern2 = tryConsume("PATTERN") || "";
337
+ const suffix = consumeText();
338
+ mustConsume("CLOSE");
339
+ result.push({
340
+ modifier: tryConsume("MODIFIER") || "",
341
+ name: name2 || (pattern2 ? key++ : ""),
342
+ pattern: name2 && !pattern2 ? defaultPattern : pattern2,
343
+ prefix,
344
+ suffix
345
+ });
346
+ continue;
347
+ }
348
+ mustConsume("END");
349
+ }
350
+ return result;
351
+ }
352
+ function escapeString(str) {
353
+ return str.replace(/([.+*?=^!:${}()[\]|/\\])/g, "\\$1");
354
+ }
355
+ function flags(options) {
356
+ return options && options.sensitive ? "" : "i";
357
+ }
358
+ function regexpToRegexp(path, keys) {
359
+ if (!keys) return path;
360
+ const groupsRegex = /\((?:\?<(.*?)>)?(?!\?)/g;
361
+ let index = 0;
362
+ let execResult = groupsRegex.exec(path.source);
363
+ while (execResult) {
364
+ keys.push({
365
+ modifier: "",
366
+ // Use parenthesized substring match if available, index otherwise
367
+ name: execResult[1] || index++,
368
+ pattern: "",
369
+ prefix: "",
370
+ suffix: ""
371
+ });
372
+ execResult = groupsRegex.exec(path.source);
373
+ }
374
+ return path;
375
+ }
376
+ function arrayToRegexp(paths, keys, options) {
377
+ const parts = paths.map((path) => pathToRegexp(path, keys, options).source);
378
+ return new RegExp(`(?:${parts.join("|")})`, flags(options));
379
+ }
380
+ function stringToRegexp(path, keys, options) {
381
+ return tokensToRegexp(parse(path, options), keys, options);
382
+ }
383
+ function tokensToRegexp(tokens, keys, options = {}) {
384
+ const {
385
+ strict = false,
386
+ start = true,
387
+ end = true,
388
+ encode = (x) => x,
389
+ delimiter = "/#?",
390
+ endsWith = ""
391
+ } = options;
392
+ const endsWithRe = `[${escapeString(endsWith)}]|$`;
393
+ const delimiterRe = `[${escapeString(delimiter)}]`;
394
+ let route = start ? "^" : "";
395
+ for (const token of tokens) {
396
+ if (typeof token === "string") {
397
+ route += escapeString(encode(token));
398
+ } else {
399
+ const prefix = escapeString(encode(token.prefix));
400
+ const suffix = escapeString(encode(token.suffix));
401
+ if (token.pattern) {
402
+ if (keys) keys.push(token);
403
+ if (prefix || suffix) {
404
+ if (token.modifier === "+" || token.modifier === "*") {
405
+ const mod = token.modifier === "*" ? "?" : "";
406
+ route += `(?:${prefix}((?:${token.pattern})(?:${suffix}${prefix}(?:${token.pattern}))*)${suffix})${mod}`;
407
+ } else {
408
+ route += `(?:${prefix}(${token.pattern})${suffix})${token.modifier}`;
409
+ }
410
+ } else {
411
+ if (token.modifier === "+" || token.modifier === "*") {
412
+ route += `((?:${token.pattern})${token.modifier})`;
413
+ } else {
414
+ route += `(${token.pattern})${token.modifier}`;
415
+ }
416
+ }
417
+ } else {
418
+ route += `(?:${prefix}${suffix})${token.modifier}`;
419
+ }
420
+ }
421
+ }
422
+ if (end) {
423
+ if (!strict) route += `${delimiterRe}?`;
424
+ route += !options.endsWith ? "$" : `(?=${endsWithRe})`;
425
+ } else {
426
+ const endToken = tokens[tokens.length - 1];
427
+ const isEndDelimited = typeof endToken === "string" ? delimiterRe.indexOf(endToken[endToken.length - 1]) > -1 : endToken === void 0;
428
+ if (!strict) {
429
+ route += `(?:${delimiterRe}(?=${endsWithRe}))?`;
430
+ }
431
+ if (!isEndDelimited) {
432
+ route += `(?=${delimiterRe}|${endsWithRe})`;
433
+ }
434
+ }
435
+ return new RegExp(route, flags(options));
436
+ }
437
+ function pathToRegexp(path, keys, options) {
438
+ if (path instanceof RegExp) return regexpToRegexp(path, keys);
439
+ if (Array.isArray(path)) return arrayToRegexp(path, keys, options);
440
+ return stringToRegexp(path, keys, options);
441
+ }
442
+
443
+ // src/utils/matchPath.ts
444
+ var cache = {};
445
+ var cacheLimit = 1e4;
446
+ var cacheCount = 0;
447
+ function compilePath(path, options) {
448
+ const { end = false, strict = false, sensitive = false } = options;
449
+ const cacheKey = `${path}/${end.toString()}/${strict.toString()}/${sensitive.toString()}`;
450
+ const pathCache = cache[cacheKey] || (cache[cacheKey] = {});
451
+ if (pathCache[path]) return pathCache[path];
452
+ const keys = [];
453
+ const regexp = pathToRegexp(path, keys, options);
454
+ const result = { keys, regexp };
455
+ if (cacheCount < cacheLimit) {
456
+ pathCache[path] = result;
457
+ cacheCount += 1;
458
+ }
459
+ return result;
460
+ }
461
+ var matchPath = (pathname, options) => {
462
+ if (options === void 0) {
463
+ options = {};
464
+ }
465
+ if (typeof options === "string" || Array.isArray(options)) {
466
+ options = {
467
+ path: options
468
+ };
469
+ }
470
+ const _options = options, path = _options.path, _options$exact = _options.exact, exact = _options$exact === void 0 ? false : _options$exact, _options$strict = _options.strict, strict = _options$strict === void 0 ? false : _options$strict, _options$sensitive = _options.sensitive, sensitive = _options$sensitive === void 0 ? false : _options$sensitive;
471
+ const paths = [].concat(path);
472
+ return paths.reduce(function(matched, path2) {
473
+ if (!path2 && path2 !== "") return null;
474
+ if (matched) return matched;
475
+ const _compilePath = compilePath(path2, {
476
+ end: exact,
477
+ sensitive,
478
+ strict
479
+ }), regexp = _compilePath.regexp, keys = _compilePath.keys;
480
+ const match = regexp.exec(pathname);
481
+ if (!match) return null;
482
+ const url = match[0], values = match.slice(1);
483
+ const isExact = pathname === url;
484
+ if (exact && !isExact) return null;
485
+ return {
486
+ // the matched portion of the URL
487
+ isExact,
488
+ // whether or not we matched exactly
489
+ params: keys.reduce(function(memo, key, index) {
490
+ memo[key.name] = values[index];
491
+ return memo;
492
+ }, {}),
493
+ path: path2,
494
+ // the path used to match
495
+ url: path2 === "/" && url === "" ? "/" : url
496
+ };
497
+ }, null);
498
+ };
499
+
500
+ // src/api/plugins/ReferrerRequestPlugin.ts
501
+ var REFERRER_PAYLOAD_NAME = "referrer";
502
+ var REFERRER_ENDPOINTS = {
503
+ delete: [],
504
+ get: [],
505
+ patch: [],
506
+ post: ["/api/email_registration", "/api/phone_registration", "/api/auth/registration"],
507
+ put: []
508
+ };
509
+ var ReferrerRequestPlugin = class {
510
+ constructor() {
511
+ this.pluginType = "request";
512
+ this.pluginName = "referrerRequestPlugin";
513
+ }
514
+ // требуется публичный метод, а для внутренней реализации может понадобиться this
515
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
516
+ execute(config) {
517
+ return new Promise((resolve) => {
518
+ const referrer = String(window.__fox_referrer__);
519
+ if (!referrer) {
520
+ resolve(config);
521
+ }
522
+ config.params = __spreadProps(__spreadValues({}, config.params), {
523
+ [REFERRER_PAYLOAD_NAME]: referrer
524
+ });
525
+ resolve(config);
526
+ });
527
+ }
528
+ // требуется публичный метод, а для внутренней реализации может понадобиться this
529
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
530
+ getEndpoints() {
531
+ return REFERRER_ENDPOINTS;
532
+ }
533
+ isApplicable(config) {
534
+ var _a;
535
+ const { method, url: pathUrl = "" } = config;
536
+ const endpointMethod = method ? method : "post";
537
+ const endpoints = this.getEndpoints();
538
+ const referrerURLs = (_a = endpoints[endpointMethod]) != null ? _a : [];
539
+ return referrerURLs.some((url) => url === pathUrl || pathUrl && matchPath(pathUrl, { exact: true, path: url })) || config.withReferrer === true;
540
+ }
541
+ };
542
+
543
+ // src/api/index.ts
544
+ var referrerRequestPlugin = new ReferrerRequestPlugin();
545
+ var camelizeRequestPlugin = new CamelizeRequestPlugin();
546
+ var dataLayerEventDispatcherPlugin = new DataLayerEventDispatcherPlugin();
547
+ var defaultPlugins = [
548
+ camelizeRequestPlugin,
549
+ referrerRequestPlugin,
550
+ dataLayerEventDispatcherPlugin
551
+ ];
552
+
553
+ // src/api/plugins/CaptchaPlugin.ts
554
+ import { CaptchaService } from "@foxford/services";
555
+ var CaptchaPlugin = class {
556
+ constructor(captchaConfig) {
557
+ this.pluginType = "responseFail";
558
+ this.pluginName = "captchaPlugin";
559
+ this.captchaConfig = captchaConfig;
560
+ }
561
+ // требуется публичный метод, а для внутренней реализации может понадобиться this
562
+ // eslint-disable-next-line complexity
563
+ execute(error) {
564
+ return __async(this, null, function* () {
565
+ var _a, _b;
566
+ try {
567
+ const captchaConfig = typeof this.captchaConfig === "function" ? this.captchaConfig() : this.captchaConfig;
568
+ if (!captchaConfig) return error;
569
+ const { settings = {} } = (_b = (_a = error.response) == null ? void 0 : _a.data) != null ? _b : {};
570
+ const { provider } = settings;
571
+ const siteKey = settings.siteKey || settings.site_key || void 0;
572
+ if (!settings || !provider || !siteKey) return error;
573
+ this.captcha = new CaptchaService(__spreadProps(__spreadValues({}, captchaConfig), {
574
+ provider,
575
+ sitekey: siteKey
576
+ }));
577
+ const { config } = error;
578
+ const captchaAnswer = yield this.captcha.execute({
579
+ location: config.url,
580
+ method: config.method
581
+ });
582
+ if (captchaAnswer === null || captchaAnswer === void 0 || typeof (captchaAnswer == null ? void 0 : captchaAnswer.captcha_token) !== "string") {
583
+ return config;
584
+ }
585
+ const captchaPayload = {
586
+ verification: {
587
+ settings: {
588
+ token: captchaAnswer.captcha_token
589
+ },
590
+ type: "captcha"
591
+ }
592
+ };
593
+ if (config.method === "get") {
594
+ config.params = __spreadValues(__spreadValues({}, config.params), captchaPayload);
595
+ }
596
+ if (typeof config.data === "string") {
597
+ try {
598
+ let data = JSON.parse(config.data);
599
+ data = __spreadValues(__spreadValues({}, data), captchaPayload);
600
+ config.data = JSON.stringify(data);
601
+ } catch (err) {
602
+ console.error(err);
603
+ }
604
+ } else if (config.data instanceof FormData) {
605
+ const formData = config.data;
606
+ formData.append("verification[settings][token]", captchaPayload.verification.settings.token);
607
+ formData.append("verification[type]", captchaPayload.verification.type);
608
+ config.data = formData;
609
+ } else if (typeof config.data === "object") {
610
+ config.data = __spreadValues(__spreadValues({}, config.data), captchaPayload);
611
+ }
612
+ return config;
613
+ } catch (error2) {
614
+ return error2;
615
+ }
616
+ });
617
+ }
618
+ // требуется публичный метод, а для внутренней реализации может понадобиться this
619
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
620
+ isApplicable(error) {
621
+ var _a;
622
+ return ((_a = error.response) == null ? void 0 : _a.status) === 449;
623
+ }
624
+ };
625
+
626
+ // src/api-plugins.ts
627
+ var getPlugins = (config, captchaConfig) => {
628
+ const apiPlugins = config.plugins || [];
629
+ const addedPlugins = [];
630
+ const resultPlugins = [];
631
+ apiPlugins.forEach((plugin) => {
632
+ if (!addedPlugins.includes(plugin.pluginName)) {
633
+ resultPlugins.push(plugin);
634
+ addedPlugins.push(plugin.pluginName);
635
+ }
636
+ });
637
+ defaultPlugins.forEach((plugin) => {
638
+ if (!addedPlugins.includes(plugin.pluginName)) {
639
+ resultPlugins.push(plugin);
640
+ addedPlugins.push(plugin.pluginName);
641
+ }
642
+ });
643
+ if (captchaConfig) {
644
+ const captchaRequestPlugin = new CaptchaPlugin(captchaConfig);
645
+ if (!addedPlugins.includes(captchaRequestPlugin.pluginName)) {
646
+ resultPlugins.push(captchaRequestPlugin);
647
+ addedPlugins.push(captchaRequestPlugin.pluginName);
648
+ }
649
+ }
650
+ return resultPlugins;
651
+ };
652
+
653
+ // src/services/app-options.ts
654
+ var AppOptionsService = class {
655
+ constructor(apiInstance, eventName) {
656
+ this.appOptions = null;
657
+ this.api = apiInstance;
658
+ this.eventName = eventName;
659
+ }
660
+ getCurrentAppOptions() {
661
+ return __async(this, null, function* () {
662
+ if (this.appOptions) return this.appOptions;
663
+ const data = yield this.getAppOptions();
664
+ return data;
665
+ });
666
+ }
667
+ /**
668
+ * Get app options data from api
669
+ */
670
+ getAppOptions() {
671
+ return __async(this, null, function* () {
672
+ const result = yield this.api.get(`/api/app_options`);
673
+ this.appOptions = result.data;
674
+ if (window) window.dispatchEvent(new CustomEvent(this.eventName, { detail: result.data }));
675
+ return result.data;
676
+ });
677
+ }
678
+ };
679
+
680
+ // src/services/cart.ts
681
+ var CartService = class {
682
+ constructor(apiInstance) {
683
+ this.api = apiInstance;
684
+ }
685
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
686
+ createCartItem(id, type) {
687
+ return {
688
+ cart_item_type: type,
689
+ resource_id: id
690
+ };
691
+ }
692
+ addCartItemToCart(cartItem) {
693
+ return __async(this, null, function* () {
694
+ const { data } = yield this.api.post(`/api/cart_items`, {
695
+ cart_item: cartItem
696
+ });
697
+ return data;
698
+ });
699
+ }
700
+ };
701
+
702
+ // src/services/course.ts
703
+ var CourseService = class {
704
+ constructor(apiInstance) {
705
+ this.api = apiInstance;
706
+ }
707
+ getCourse(id) {
708
+ return __async(this, null, function* () {
709
+ if (typeof id !== "number") throw new TypeError("id is wrong");
710
+ const { data } = yield this.api.get(`/api/courses/${id}`);
711
+ return data;
712
+ });
713
+ }
714
+ enrollCourse(id) {
715
+ return __async(this, null, function* () {
716
+ if (typeof id !== "number") throw new TypeError("id is wrong");
717
+ yield this.api.post(`/api/courses/${id}/users_courses`);
718
+ });
719
+ }
720
+ };
721
+
722
+ // src/services/lead-request.ts
723
+ var LR_REGISTRATION_SET = "LeadRequest.registration.set";
724
+ var LeadRequestType = /* @__PURE__ */ ((LeadRequestType2) => {
725
+ LeadRequestType2["Algorithmics"] = "LeadRequests::Algorithmics";
726
+ LeadRequestType2["External"] = "LeadRequests::External";
727
+ LeadRequestType2["Callback"] = "LeadRequests::Callback";
728
+ LeadRequestType2["Basic"] = "LeadRequests::Basic";
729
+ LeadRequestType2["Main"] = "LeadRequests::Main";
730
+ LeadRequestType2["Coach"] = "LeadRequests::Coach";
731
+ LeadRequestType2["Media"] = "LeadRequests::Media";
732
+ LeadRequestType2["MiniGroup"] = "LeadRequests::MiniGroup";
733
+ LeadRequestType2["Externship"] = "LeadRequests::Externship";
734
+ LeadRequestType2["CoachUserCoursePlanUpgradeCallback"] = "LeadRequests::CoachUserCoursePlanUpgradeCallback";
735
+ LeadRequestType2["ParentCallback"] = "LeadRequests::ParentCallback";
736
+ LeadRequestType2["TeacherCallback"] = "LeadRequests::TeacherCallback";
737
+ LeadRequestType2["Email"] = "LeadRequests::EmailSubscription";
738
+ LeadRequestType2["IThubLead"] = "LeadRequests::IThubLead";
739
+ return LeadRequestType2;
740
+ })(LeadRequestType || {});
741
+ var LeadRequestService = class {
742
+ constructor(apiInstance) {
743
+ this.types = LeadRequestType;
744
+ this.api = apiInstance;
745
+ }
746
+ /**
747
+ * Create lead request
748
+ * @param {LeadRequestType} type
749
+ * @param {LeadRequest['context']} context
750
+ * @param {LeadRequestPayload} data
751
+ */
752
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
753
+ createLeadRequest(type, context, data = {}) {
754
+ const payload = data;
755
+ return __spreadProps(__spreadValues({}, payload), {
756
+ agreement: true,
757
+ context,
758
+ type
759
+ });
760
+ }
761
+ /**
762
+ * Send lead request with specific data
763
+ * @param {LeadRequest} leadRequest
764
+ */
765
+ send(leadRequest) {
766
+ return __async(this, null, function* () {
767
+ const { data } = yield this.api.post(`/api/lead_requests`, {
768
+ lead_request: leadRequest
769
+ });
770
+ if (data.newUser) {
771
+ window.dispatchEvent(new CustomEvent(LR_REGISTRATION_SET));
772
+ }
773
+ return { leadRequest, response: data };
774
+ });
775
+ }
776
+ /**
777
+ * Update lead request with specific data
778
+ * @param {string} id
779
+ * @param {LeadRequestPayload} lrData
780
+ */
781
+ update(_0) {
782
+ return __async(this, arguments, function* (id, lrData = {}) {
783
+ const { data } = yield this.api.put(`/api/lead_requests/${id}`, {
784
+ lead_request: lrData
785
+ });
786
+ return data;
787
+ });
788
+ }
789
+ };
790
+
791
+ // src/services/product-pack.ts
792
+ var ProductPackService = class {
793
+ constructor(apiInstance) {
794
+ this.api = apiInstance;
795
+ }
796
+ getProductPack(id) {
797
+ return __async(this, null, function* () {
798
+ if (typeof id !== "number") throw new TypeError("id is wrong");
799
+ const { data } = yield this.api.get(`/api/product_packs/${id}`);
800
+ return data;
801
+ });
802
+ }
803
+ };
804
+
805
+ // src/services/promo.ts
806
+ var PromoService = class {
807
+ constructor(apiInstance) {
808
+ this.api = apiInstance;
809
+ }
810
+ checkPromocode(code) {
811
+ return __async(this, null, function* () {
812
+ const { data } = yield this.api.get(`/api/promo_codes/invite/${code}`);
813
+ return data;
814
+ });
815
+ }
816
+ /**
817
+ * Send data if user saw the promo code
818
+ * @param {string} promoCode
819
+ * @returns {Promise}
820
+ */
821
+ trackCodeCampaign(promoCode) {
822
+ return __async(this, null, function* () {
823
+ yield this.api.post(`/api/tracking/promo_code`, { promo_code: promoCode });
824
+ });
825
+ }
826
+ };
827
+
828
+ // src/services/tag.ts
829
+ var TagService = class {
830
+ constructor(apiInstance) {
831
+ this.api = apiInstance;
832
+ }
833
+ addTag(id) {
834
+ return __async(this, null, function* () {
835
+ const { data } = yield this.api.post(`/api/user/tag?id=${id}`);
836
+ return data;
837
+ });
838
+ }
839
+ };
840
+
841
+ // src/entities/user/constants.ts
842
+ var GRADE_MAP = {
843
+ 1: "1 \u043A\u043B\u0430\u0441\u0441",
844
+ 2: "2 \u043A\u043B\u0430\u0441\u0441",
845
+ 3: "3 \u043A\u043B\u0430\u0441\u0441",
846
+ 4: "4 \u043A\u043B\u0430\u0441\u0441",
847
+ 5: "5 \u043A\u043B\u0430\u0441\u0441",
848
+ 6: "6 \u043A\u043B\u0430\u0441\u0441",
849
+ 7: "7 \u043A\u043B\u0430\u0441\u0441",
850
+ 8: "8 \u043A\u043B\u0430\u0441\u0441",
851
+ 9: "9 \u043A\u043B\u0430\u0441\u0441",
852
+ 10: "10 \u043A\u043B\u0430\u0441\u0441",
853
+ 11: "11 \u043A\u043B\u0430\u0441\u0441"
854
+ };
855
+ var DEFAULT_USER = {
856
+ address: {
857
+ building: null,
858
+ cityId: null,
859
+ cityName: null,
860
+ countryId: null,
861
+ countryName: null,
862
+ house: null,
863
+ index: null,
864
+ regionId: null,
865
+ regionName: null,
866
+ room: null,
867
+ street: null
868
+ },
869
+ avatarUrl: "",
870
+ bonus: {
871
+ giftAmount: 0,
872
+ realMoneyAmount: 0
873
+ },
874
+ bonusAmount: 0,
875
+ cartItemsCount: 0,
876
+ cartTemplateId: null,
877
+ createdAt: null,
878
+ disciplineIds: [],
879
+ email: "",
880
+ emailConfirmed: false,
881
+ externshipUser: false,
882
+ fakeEmail: false,
883
+ fakeUser: false,
884
+ firstName: "",
885
+ freeAccessFinishesAt: null,
886
+ fullName: "",
887
+ grade: {
888
+ id: null,
889
+ index: null,
890
+ name: "",
891
+ translit: ""
892
+ },
893
+ gradeChecked: false,
894
+ hasAccessToAttestationSheets: false,
895
+ hasAccessToMultiDaysStreaks: false,
896
+ hasActivePurchases: false,
897
+ hasAttemptsSolveExamRehearsals: false,
898
+ hasBookmarks: false,
899
+ hasExternshipAttestationAccess: false,
900
+ hasPurchasedExternshipContracts: false,
901
+ id: null,
902
+ isAgent: false,
903
+ isCoach: false,
904
+ isCustomer: null,
905
+ isElementaryPupil: false,
906
+ isExternshipCoach: false,
907
+ isGraduated: false,
908
+ isMiniGroupTeacher: false,
909
+ isParent: false,
910
+ lastName: "",
911
+ locale: null,
912
+ methodist: false,
913
+ middleName: "",
914
+ onboardingFinished: false,
915
+ onboardingFinishedAt: null,
916
+ parentPhone: null,
917
+ parentPhoneConfirmed: false,
918
+ phone: null,
919
+ phoneConfirmed: false,
920
+ privacy: {
921
+ publicProfile: false
922
+ },
923
+ profileEnriched: false,
924
+ purchaseAnyExternshipContracts: false,
925
+ recapUuid: null,
926
+ shortName: "",
927
+ skype: null,
928
+ socialNets: [],
929
+ socializationProfile: null,
930
+ tags: null,
931
+ timezone: null,
932
+ type: null,
933
+ webSocketNotificationsJwt: null
934
+ };
935
+
936
+ // src/entities/user/index.ts
937
+ var _User = class _User {
938
+ constructor(props, isDefault = false) {
939
+ this.props = props;
940
+ this.isDefault = isDefault;
941
+ /**
942
+ * Возвращает роль пользователя
943
+ * @returns {UserRole} роль как строка
944
+ */
945
+ this.getRole = () => {
946
+ if (this.isCoach) return "\u0420\u0435\u043F\u0435\u0442\u0438\u0442\u043E\u0440";
947
+ if (this.isAgent) return "\u0423\u0447\u0438\u0442\u0435\u043B\u044C";
948
+ if (this.isParent) return "\u0420\u043E\u0434\u0438\u0442\u0435\u043B\u044C";
949
+ switch (this.type) {
950
+ case "pupil":
951
+ return this.getPupilRole();
952
+ case "agent":
953
+ return "\u0423\u0447\u0438\u0442\u0435\u043B\u044C";
954
+ default:
955
+ return "\u0423\u0447\u0435\u043D\u0438\u043A";
956
+ }
957
+ };
958
+ /**
959
+ * Возвращает фамилию и инициалы юзера
960
+ * @param {User} user
961
+ * @return {string} 'Пупкин В.'
962
+ */
963
+ this.getInitials = () => {
964
+ var _a, _b;
965
+ return `${this.lastName}${this.firstName ? ` ${(_a = this.firstName[0]) == null ? void 0 : _a.toUpperCase()}.` : ""}${this.middleName !== "" && this.middleName !== null ? ` ${(_b = this.middleName[0]) == null ? void 0 : _b.toUpperCase()}.` : ""}`;
966
+ };
967
+ }
968
+ get id() {
969
+ return this.props.id;
970
+ }
971
+ get email() {
972
+ return this.props.email;
973
+ }
974
+ get firstName() {
975
+ return this.props.firstName;
976
+ }
977
+ get middleName() {
978
+ return this.props.middleName;
979
+ }
980
+ get lastName() {
981
+ return this.props.lastName;
982
+ }
983
+ get fullName() {
984
+ return this.props.fullName;
985
+ }
986
+ get shortName() {
987
+ return this.props.shortName;
988
+ }
989
+ get createdAt() {
990
+ return this.props.createdAt;
991
+ }
992
+ get timezone() {
993
+ return this.props.timezone;
994
+ }
995
+ get locale() {
996
+ return this.props.locale;
997
+ }
998
+ get grade() {
999
+ return this.props.grade;
1000
+ }
1001
+ get phone() {
1002
+ return this.props.phone;
1003
+ }
1004
+ get avatarUrl() {
1005
+ return this.props.avatarUrl;
1006
+ }
1007
+ get isParent() {
1008
+ return this.props.isParent;
1009
+ }
1010
+ get isGraduated() {
1011
+ return this.props.isGraduated;
1012
+ }
1013
+ get gradeChecked() {
1014
+ return this.props.gradeChecked;
1015
+ }
1016
+ get type() {
1017
+ return this.props.type;
1018
+ }
1019
+ get isCoach() {
1020
+ return this.props.isCoach;
1021
+ }
1022
+ get isMiniGroupTeacher() {
1023
+ return this.props.isMiniGroupTeacher;
1024
+ }
1025
+ get isExternshipCoach() {
1026
+ return this.props.isExternshipCoach;
1027
+ }
1028
+ get isAgent() {
1029
+ return this.props.isAgent;
1030
+ }
1031
+ get methodist() {
1032
+ return this.props.methodist;
1033
+ }
1034
+ get address() {
1035
+ return this.props.address;
1036
+ }
1037
+ get socialNets() {
1038
+ return this.props.socialNets;
1039
+ }
1040
+ get skype() {
1041
+ return this.props.skype;
1042
+ }
1043
+ get settings() {
1044
+ return this.props.settings;
1045
+ }
1046
+ get bonus() {
1047
+ return this.props.bonus;
1048
+ }
1049
+ get bonusAmount() {
1050
+ return this.props.bonusAmount;
1051
+ }
1052
+ get hasActivePurchases() {
1053
+ return this.props.hasActivePurchases;
1054
+ }
1055
+ get hasAttemptsSolveExamRehearsals() {
1056
+ return this.props.hasAttemptsSolveExamRehearsals;
1057
+ }
1058
+ get hasBookmarks() {
1059
+ return this.props.hasBookmarks;
1060
+ }
1061
+ get tags() {
1062
+ return this.props.tags;
1063
+ }
1064
+ get cartTemplateId() {
1065
+ return this.props.cartTemplateId;
1066
+ }
1067
+ get cartItemsCount() {
1068
+ return this.props.cartItemsCount;
1069
+ }
1070
+ get onboardingFinished() {
1071
+ return this.props.onboardingFinished;
1072
+ }
1073
+ get onboardingFinishedAt() {
1074
+ return this.props.onboardingFinishedAt;
1075
+ }
1076
+ get emailConfirmed() {
1077
+ return this.props.emailConfirmed;
1078
+ }
1079
+ get phoneConfirmed() {
1080
+ return this.props.phoneConfirmed;
1081
+ }
1082
+ get fakeEmail() {
1083
+ return this.props.fakeEmail;
1084
+ }
1085
+ get fakeUser() {
1086
+ return this.props.fakeUser;
1087
+ }
1088
+ get profileEnriched() {
1089
+ return this.props.profileEnriched;
1090
+ }
1091
+ get recapUuid() {
1092
+ return this.props.recapUuid;
1093
+ }
1094
+ get disciplineIds() {
1095
+ return this.props.disciplineIds;
1096
+ }
1097
+ get privacy() {
1098
+ return this.props.privacy;
1099
+ }
1100
+ get parentPhone() {
1101
+ return this.props.parentPhone;
1102
+ }
1103
+ get parentPhoneConfirmed() {
1104
+ return this.props.parentPhoneConfirmed;
1105
+ }
1106
+ get isCustomer() {
1107
+ return this.props.isCustomer;
1108
+ }
1109
+ get hasAccessToMultiDaysStreaks() {
1110
+ return this.props.hasAccessToMultiDaysStreaks;
1111
+ }
1112
+ get isElementaryPupil() {
1113
+ return this.props.isElementaryPupil;
1114
+ }
1115
+ get webSocketNotificationsJwt() {
1116
+ return this.props.webSocketNotificationsJwt;
1117
+ }
1118
+ get hasAccessToAttestationSheets() {
1119
+ return this.props.hasAccessToAttestationSheets;
1120
+ }
1121
+ get externshipUser() {
1122
+ return this.props.externshipUser;
1123
+ }
1124
+ get hasPurchasedExternshipContracts() {
1125
+ return this.props.hasPurchasedExternshipContracts;
1126
+ }
1127
+ get hasExternshipAttestationAccess() {
1128
+ return this.props.hasExternshipAttestationAccess;
1129
+ }
1130
+ get socializationProfile() {
1131
+ return this.props.socializationProfile;
1132
+ }
1133
+ get freeAccessFinishesAt() {
1134
+ return this.props.freeAccessFinishesAt;
1135
+ }
1136
+ get hasUnseenRoomFeatures() {
1137
+ return this.props.hasUnseenRoomFeatures;
1138
+ }
1139
+ get purchaseAnyExternshipContracts() {
1140
+ return this.props.purchaseAnyExternshipContracts;
1141
+ }
1142
+ /**
1143
+ * Глубокое клонирование объекта с защитой от циклических ссылок
1144
+ * @private
1145
+ * @param obj - объект для клонирования
1146
+ * @param hash - WeakMap для отслеживания уже клонированных объектов
1147
+ * @returns клонированный объект
1148
+ */
1149
+ static deepClone(obj, hash = /* @__PURE__ */ new WeakMap()) {
1150
+ if (obj === null || typeof obj !== "object") {
1151
+ return obj;
1152
+ }
1153
+ if (hash.has(obj)) {
1154
+ return hash.get(obj);
1155
+ }
1156
+ if (obj instanceof Date) {
1157
+ return new Date(obj.getTime());
1158
+ }
1159
+ if (obj instanceof RegExp) {
1160
+ return new RegExp(obj.source, obj.flags);
1161
+ }
1162
+ if (Array.isArray(obj)) {
1163
+ const clonedArr = [];
1164
+ hash.set(obj, clonedArr);
1165
+ obj.forEach((item, index) => {
1166
+ clonedArr[index] = this.deepClone(item, hash);
1167
+ });
1168
+ return clonedArr;
1169
+ }
1170
+ const clonedObj = Object.create(Object.getPrototypeOf(obj));
1171
+ hash.set(obj, clonedObj);
1172
+ Object.keys(obj).forEach((key) => {
1173
+ clonedObj[key] = this.deepClone(obj[key], hash);
1174
+ });
1175
+ return clonedObj;
1176
+ }
1177
+ static createDefault() {
1178
+ return new _User(this.deepClone(DEFAULT_USER), true);
1179
+ }
1180
+ /**
1181
+ * Санитизирует строку: удаляет null-байты и обрезает пробелы
1182
+ * @private
1183
+ * @param str - исходная строка
1184
+ * @returns санитизированная строка
1185
+ */
1186
+ static sanitizeString(str) {
1187
+ if (typeof str !== "string") {
1188
+ console.warn("[User] Invalid string type:", typeof str);
1189
+ return String(str);
1190
+ }
1191
+ return str.replace(/\x00/g, "").trim();
1192
+ }
1193
+ static fromApi(input) {
1194
+ const sanitizedData = this.sanitizeUserData(this.deepClone(input));
1195
+ return new _User(sanitizedData);
1196
+ }
1197
+ /**
1198
+ * Санитизирует данные пользователя
1199
+ * @private
1200
+ * @param data - исходные данные
1201
+ * @returns санитизированные данные
1202
+ */
1203
+ static sanitizeUserData(data) {
1204
+ return __spreadProps(__spreadValues({}, data), {
1205
+ email: this.sanitizeString(data.email),
1206
+ firstName: this.sanitizeString(data.firstName),
1207
+ fullName: this.sanitizeString(data.fullName),
1208
+ lastName: this.sanitizeString(data.lastName),
1209
+ middleName: data.middleName ? this.sanitizeString(data.middleName) : data.middleName,
1210
+ shortName: this.sanitizeString(data.shortName)
1211
+ });
1212
+ }
1213
+ isDefaultUser() {
1214
+ return this.isDefault;
1215
+ }
1216
+ isLoggedIn() {
1217
+ return this.id && this.id > 0 ? true : false;
1218
+ }
1219
+ /**
1220
+ * Возвращает тектовое представление роли / класса пользователя
1221
+ *
1222
+ * @returns {UserRole}
1223
+ */
1224
+ getPupilRole() {
1225
+ if (this.grade.index === 0) {
1226
+ return "\u0414\u043E\u0448\u043A\u043E\u043B\u044C\u043D\u0438\u043A";
1227
+ }
1228
+ if (this.grade.index == null) return "\u0412\u044B\u043F\u0443\u0441\u043A\u043D\u0438\u043A";
1229
+ return _User.getGradeString(this.grade.index);
1230
+ }
1231
+ toJson() {
1232
+ return JSON.stringify(this.props);
1233
+ }
1234
+ };
1235
+ _User.getGradeString = (index) => GRADE_MAP[index] || GRADE_MAP[1];
1236
+ var User = _User;
1237
+
1238
+ // src/errors/login-error.ts
1239
+ var LogginError = class extends Error {
1240
+ constructor(message, options) {
1241
+ super(message);
1242
+ this.name = "LogginError";
1243
+ this.cause = options == null ? void 0 : options.cause;
1244
+ }
1245
+ };
1246
+
1247
+ // src/errors/confirmation-code-error.ts
1248
+ var ConfirmationCodeRequestError = class extends Error {
1249
+ constructor(message, options) {
1250
+ super(message);
1251
+ this.name = "ConfirmationCodeRequestError";
1252
+ this.cause = options == null ? void 0 : options.cause;
1253
+ }
1254
+ };
1255
+
1256
+ // src/services/user.ts
1257
+ var UserService = class {
1258
+ constructor(apiInstance, appOptionsService) {
1259
+ this.api = apiInstance;
1260
+ this.appOptionsService = appOptionsService;
1261
+ }
1262
+ /**
1263
+ * Create user instance
1264
+ * @param {UserDTO} data data of user
1265
+ */
1266
+ static createUser(data) {
1267
+ return User.fromApi(data);
1268
+ }
1269
+ /**
1270
+ * Create default user
1271
+ * @returns {User}
1272
+ */
1273
+ static createDefaultUser() {
1274
+ return User.createDefault();
1275
+ }
1276
+ /**
1277
+ * Get current user data
1278
+ * @return {Promise} Server response with user data
1279
+ */
1280
+ getUser() {
1281
+ return __async(this, null, function* () {
1282
+ try {
1283
+ const data = yield this.api.get("/api/user/me").then(({ data: data2 }) => data2);
1284
+ const user = User.fromApi(data);
1285
+ return user;
1286
+ } catch (e) {
1287
+ return User.createDefault();
1288
+ }
1289
+ });
1290
+ }
1291
+ /**
1292
+ * Логин или регистрация юзера по email
1293
+ * @param email email юзера
1294
+ * @param password пароль
1295
+ * @returns {Promise<{ user: User; result: LoginOrRegistrationResponse }>}
1296
+ */
1297
+ loginByEmail(email, password) {
1298
+ return __async(this, null, function* () {
1299
+ const data = yield this.api.post("/api/email_registration", {
1300
+ email,
1301
+ password
1302
+ }).then(({ data: data2 }) => data2);
1303
+ const user = yield this.getUser();
1304
+ return { result: data, user };
1305
+ });
1306
+ }
1307
+ /**
1308
+ * Запрос кода на подтвеждение телефона
1309
+ */
1310
+ getConfirmationCode(phone) {
1311
+ return __async(this, null, function* () {
1312
+ const appOptions = yield this.appOptionsService.getCurrentAppOptions();
1313
+ try {
1314
+ const payload = {
1315
+ phone,
1316
+ type: appOptions.phoneConfirmationType
1317
+ };
1318
+ const confirm = yield this.api.post("/api/phone_confirmation_codes", payload);
1319
+ return confirm;
1320
+ } catch (error) {
1321
+ throw new ConfirmationCodeRequestError("\u041E\u0448\u0438\u0431\u043A\u0430 \u043F\u043E\u043B\u0443\u0447\u0435\u043D\u0438\u044F \u043A\u043E\u0434\u0430 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0438\u044F", { cause: error });
1322
+ }
1323
+ });
1324
+ }
1325
+ /**
1326
+ * Логин или регистрация юзера по телефону
1327
+ * @param phone номер телефона
1328
+ * @param params
1329
+ * @returns {Promise<{ user: User; result: LoginOrRegistrationResponse }>}
1330
+ */
1331
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1332
+ loginByPhone(phone, params) {
1333
+ return __async(this, null, function* () {
1334
+ const appOptions = yield this.appOptionsService.getCurrentAppOptions();
1335
+ const phoneCheck = yield this.api.post("/api/phone_check", { phone });
1336
+ if (phoneCheck.data.state === "not_confirmed") {
1337
+ if (phoneCheck.data.fakeEmail === false) {
1338
+ let checkMethod = "email";
1339
+ const email = yield params.onEmailRequest(phoneCheck.data);
1340
+ try {
1341
+ yield this.api.post("/api/phone_check/verification", {
1342
+ check_method: checkMethod,
1343
+ email,
1344
+ phone,
1345
+ type: appOptions.phoneConfirmationType
1346
+ });
1347
+ } catch (e) {
1348
+ checkMethod = "name";
1349
+ }
1350
+ try {
1351
+ if (checkMethod === "name") {
1352
+ const { first_name, last_name } = yield params.onNameRequest();
1353
+ yield this.api.post("/api/phone_check/verification", {
1354
+ check_method: "name",
1355
+ first_name,
1356
+ last_name,
1357
+ phone,
1358
+ type: appOptions.phoneConfirmationType
1359
+ });
1360
+ }
1361
+ } catch (error) {
1362
+ throw new LogginError("\u041E\u0448\u0438\u0431\u043A\u0430 \u0430\u0432\u0442\u043E\u0440\u0438\u0437\u0430\u0446\u0438\u0438", { cause: error });
1363
+ }
1364
+ }
1365
+ }
1366
+ let confirm;
1367
+ try {
1368
+ confirm = yield this.getConfirmationCode(phone);
1369
+ params.onConfirmationCodeResponse(confirm.data);
1370
+ } catch (error) {
1371
+ throw new LogginError("\u041E\u0448\u0438\u0431\u043A\u0430 \u0430\u0432\u0442\u043E\u0440\u0438\u0437\u0430\u0446\u0438\u0438", { cause: error });
1372
+ }
1373
+ if (!confirm) return void 0;
1374
+ const code = yield params.onCodeRequest();
1375
+ let token;
1376
+ try {
1377
+ const resultConfirmation = yield this.api.post("/api/phone_confirmations", {
1378
+ code,
1379
+ phone
1380
+ });
1381
+ token = resultConfirmation.data.verificationToken;
1382
+ } catch (error) {
1383
+ params.onConfirmationCodeError(error);
1384
+ }
1385
+ const data = yield this.api.post("/api/phone_registration", {
1386
+ phone,
1387
+ phone_verification_token: token
1388
+ }).then(({ data: data2 }) => data2);
1389
+ const user = yield this.getUser();
1390
+ return { result: data, user };
1391
+ });
1392
+ }
1393
+ /**
1394
+ * Получение покупок текущего пользователя
1395
+ * @param {Number} params.resourceId Resource ID
1396
+ * @param {String} params.resourceType Resource type
1397
+ * @return {Promise} Server response with user purchases
1398
+ */
1399
+ purchases(_0) {
1400
+ return __async(this, arguments, function* ({ resourceId, resourceType }) {
1401
+ if (resourceId && typeof resourceId !== "number") {
1402
+ throw new Error("resourceId must be a number");
1403
+ }
1404
+ if (resourceType && typeof resourceType !== "string") {
1405
+ throw new Error("resourceType must be a string");
1406
+ }
1407
+ const params = [];
1408
+ if (resourceId) params.push(`resource_id=${encodeURIComponent(resourceId)}`);
1409
+ if (resourceType) params.push(`resource_type=${encodeURIComponent(resourceType)}`);
1410
+ const query = params.length ? `?${params.join("&")}` : "";
1411
+ const { data } = yield this.api.get(`/api/user/purchases${query}`);
1412
+ return data;
1413
+ });
1414
+ }
1415
+ /**
1416
+ * Навигация на страницу входа и перенаправление на указанный путь после успешного входа.
1417
+ * @param {String} options.redirectUrl URL для редиректа.
1418
+ */
1419
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
1420
+ signIn({ redirectUrl = void 0 }) {
1421
+ if (redirectUrl && typeof redirectUrl !== "string") {
1422
+ throw new Error("redirectUrl must be a string");
1423
+ }
1424
+ let url = `${FOXFORD_HOST}/user/registration?redirect_url=`;
1425
+ if (redirectUrl) url += encodeURIComponent(document.location.href);
1426
+ document.location.href = url;
1427
+ }
1428
+ /**
1429
+ * Выход из аккаунта с перезагрузкой страницы
1430
+ */
1431
+ signOut(reloadAfter = true) {
1432
+ return __async(this, null, function* () {
1433
+ const data = yield this.api.delete(`/user/log_out`);
1434
+ if (reloadAfter) window.location.reload();
1435
+ return data;
1436
+ });
1437
+ }
1438
+ pushEvent(event) {
1439
+ return __async(this, null, function* () {
1440
+ yield this.api.post(`/api/user/event`, {
1441
+ event
1442
+ });
1443
+ });
1444
+ }
1445
+ /**
1446
+ * Установить подписку пользователю
1447
+ * @param {CommunicationSubscriptions} subscriptions пользовательские подписки
1448
+ */
1449
+ setSubscriptions(subscriptions) {
1450
+ return __async(this, null, function* () {
1451
+ yield this.api.put(`/api/user/communication_subscriptions`, {
1452
+ communication_subscriptions: subscriptions
1453
+ });
1454
+ });
1455
+ }
1456
+ /**
1457
+ * Получение интересов пользователя
1458
+ */
1459
+ getUserInterests() {
1460
+ return __async(this, null, function* () {
1461
+ const { data } = yield this.api.get("/api/user/user_interest");
1462
+ return data;
1463
+ });
1464
+ }
1465
+ /**
1466
+ * Обновление интересов пользователя
1467
+ * @param {Partial<UserInterests>} data интересы пользователя
1468
+ */
1469
+ updateUserInterests(data) {
1470
+ return __async(this, null, function* () {
1471
+ yield this.api.put("/api/user/user_interest", { user_interest: decamelize(data) });
1472
+ });
1473
+ }
1474
+ /**
1475
+ * Обновления множества интересов пользователя
1476
+ * @param {Partial<UserInterests>} data интересы пользователя
1477
+ */
1478
+ updateMultipleUserInterests(data) {
1479
+ return __async(this, null, function* () {
1480
+ yield this.api.put("/api/user/user_interest", { user_interests: data.map((i) => decamelize(i)) });
1481
+ });
1482
+ }
1483
+ };
1484
+
1485
+ // src/utils/merge.ts
1486
+ function isObject(item) {
1487
+ return Boolean(item) && typeof item === "object" && !Array.isArray(item);
1488
+ }
1489
+ function mergeDeep(target, ...sources) {
1490
+ if (!sources.length) return target;
1491
+ const output = Object.assign({}, target);
1492
+ const source = sources.shift();
1493
+ if (isObject(target) && isObject(source)) {
1494
+ for (const key in source) {
1495
+ if (isObject(source[key])) {
1496
+ if (!(key in target)) {
1497
+ Object.assign(output, { [key]: source[key] });
1498
+ } else {
1499
+ output[key] = mergeDeep(target[key], source[key]);
1500
+ }
1501
+ } else {
1502
+ Object.assign(output, { [key]: source[key] });
1503
+ }
1504
+ }
1505
+ }
1506
+ return output;
1507
+ }
1508
+
1509
+ // src/services/widgets.ts
1510
+ var _Widgets = class _Widgets {
1511
+ constructor(config = _Widgets.DEFAULT_CONFIG, apiInstance) {
1512
+ this.manifest = null;
1513
+ this.config = mergeDeep(_Widgets.DEFAULT_CONFIG, config);
1514
+ this.api = apiInstance;
1515
+ }
1516
+ create(config) {
1517
+ return __async(this, null, function* () {
1518
+ if (!config) throw new Error("You must specify config for creating widgets");
1519
+ yield this.loadManifest();
1520
+ yield this.loadAssets();
1521
+ if (!window.Foxford || !window.Foxford.Widgets) throw new Error("FoxfordWidgets not found in global scope");
1522
+ if (typeof window.Foxford.Widgets.create !== "function")
1523
+ throw new Error("Not found function create in FoxfordWidgets library");
1524
+ window.Foxford.Widgets.create(config);
1525
+ });
1526
+ }
1527
+ // Публичный метод у инстанса
1528
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
1529
+ update(name, config) {
1530
+ return __async(this, null, function* () {
1531
+ if (window.Foxford && window.Foxford.Widgets) window.Foxford.Widgets.update(name, config);
1532
+ });
1533
+ }
1534
+ loadManifest() {
1535
+ return __async(this, null, function* () {
1536
+ const url = `https://dist.ngcdn.ru/libs/foxford-widgets/${this.config.version}/manifest.json`;
1537
+ const response = yield this.api.get(url);
1538
+ this.manifest = response.data;
1539
+ });
1540
+ }
1541
+ static appendScript(src) {
1542
+ return __async(this, null, function* () {
1543
+ return new Promise((resolve, reject) => {
1544
+ const script = document.createElement("script");
1545
+ script.type = "text/javascript";
1546
+ script.defer = true;
1547
+ script.onload = () => resolve(true);
1548
+ script.onerror = (event) => reject(event);
1549
+ script.src = src;
1550
+ document.body.appendChild(script);
1551
+ });
1552
+ });
1553
+ }
1554
+ loadAssets() {
1555
+ return __async(this, null, function* () {
1556
+ if (!this.config.version) this.config.version = "latest";
1557
+ yield Promise.all(
1558
+ _Widgets.ENTRY.map((entry) => {
1559
+ if (!this.manifest) return Promise.resolve;
1560
+ const src = this.manifest[entry];
1561
+ if (!src) return Promise.resolve;
1562
+ return _Widgets.appendScript(`https://dist.ngcdn.ru/libs/foxford-widgets/${this.config.version}/${src}`).then(
1563
+ (res) => res
1564
+ );
1565
+ })
1566
+ );
1567
+ });
1568
+ }
1569
+ };
1570
+ _Widgets.ENTRY = ["vendors~react.js", "vendors~ui.js", "main.js"];
1571
+ _Widgets.DEFAULT_CONFIG = {
1572
+ locale: "ru",
1573
+ version: "latest"
1574
+ };
1575
+ var Widgets = _Widgets;
1576
+
1577
+ // src/foxford.ts
1578
+ var _Foxford = class _Foxford {
1579
+ constructor(config = _Foxford.DEFAULT_CONFIG) {
1580
+ var _a, _b, _c, _d;
1581
+ this.config = mergeDeep(_Foxford.DEFAULT_CONFIG, config);
1582
+ this.foxApi = this.buildFoxApi();
1583
+ this.api = ApiService.createApiInstance({ config: apiBaseConfig });
1584
+ this.staticApi = ApiService.createStaticApiInstance();
1585
+ this.appOptions = new AppOptionsService(this.foxApi, _Foxford.events.FETCH_APP_OPTIONS);
1586
+ this.user = new UserService(this.foxApi, this.appOptions);
1587
+ this.promo = new PromoService(this.foxApi);
1588
+ this.tag = new TagService(this.foxApi);
1589
+ this.cart = new CartService(this.foxApi);
1590
+ this.course = new CourseService(this.foxApi);
1591
+ this.widgets = new Widgets(
1592
+ __spreadValues({
1593
+ version: this.config.widgetsVersion
1594
+ }, this.config.widgetsConfig),
1595
+ this.api
1596
+ );
1597
+ this.productPack = new ProductPackService(this.foxApi);
1598
+ this.leadrequest = new LeadRequestService(this.foxApi);
1599
+ this.captcha = new CaptchaService2(
1600
+ typeof ((_a = this.config) == null ? void 0 : _a.captchaConfig) === "function" ? (_b = this.config) == null ? void 0 : _b.captchaConfig() : (_d = (_c = this.config) == null ? void 0 : _c.captchaConfig) != null ? _d : {}
1601
+ );
1602
+ if (this.config.antibot === true) {
1603
+ new FoxfordAntibot(this.config.antibotConfig);
1604
+ }
1605
+ }
1606
+ buildFoxApi() {
1607
+ var _a, _b, _c, _d;
1608
+ const apiConfig2 = ((_a = this.config) == null ? void 0 : _a.api) || { config: {} };
1609
+ const captchaConfig = (_b = this.config) == null ? void 0 : _b.captchaConfig;
1610
+ const apiInstance = ApiService.createFoxApiInstance({
1611
+ config: apiConfig2.config,
1612
+ plugins: getPlugins(apiConfig2, captchaConfig)
1613
+ });
1614
+ if (!((_d = (_c = this.config) == null ? void 0 : _c.api) == null ? void 0 : _d.config.baseURL) && this.config.host) apiInstance.defaults.baseURL = this.config.host;
1615
+ return apiInstance;
1616
+ }
1617
+ /**
1618
+ * Get short link
1619
+ * @param {string} url link for shortening
1620
+ */
1621
+ shortURL(url) {
1622
+ return this.foxApi.post(`/api/short_urls`, {
1623
+ link: url
1624
+ }).then((data) => data);
1625
+ }
1626
+ /**
1627
+ * Applies and throwing itself into plugin for access to Api
1628
+ * @param {SdkPlugin} plugin Plugin to apply
1629
+ */
1630
+ applyPlugin(plugin) {
1631
+ plugin.apply(this);
1632
+ }
1633
+ };
1634
+ _Foxford.events = {
1635
+ FETCH_APP_OPTIONS: "Foxford.app_options.fetch",
1636
+ LR_REGISTRATION_SET
1637
+ };
1638
+ _Foxford.DEFAULT_CONFIG = {
1639
+ antibot: true,
1640
+ api: {
1641
+ config: apiConfig
1642
+ },
1643
+ host: FOXFORD_HOST,
1644
+ widgetsConfig: {
1645
+ locale: "ru",
1646
+ version: "latest"
1647
+ },
1648
+ widgetsVersion: "latest"
1649
+ };
1650
+ var Foxford = _Foxford;
1651
+
1652
+ // src/analytics/external/abstract.external.ts
1653
+ var ExternalScript = class _ExternalScript {
1654
+ constructor(analytics) {
1655
+ this.sendCallstack = [];
1656
+ this.ready = false;
1657
+ this.analytics = analytics;
1658
+ }
1659
+ static appendScript(src) {
1660
+ return new Promise((resolve, reject) => {
1661
+ const script = document.createElement("script");
1662
+ script.type = "text/javascript";
1663
+ script.defer = true;
1664
+ script.onload = () => resolve(true);
1665
+ script.onerror = (event) => reject(event);
1666
+ script.src = src;
1667
+ document.body.appendChild(script);
1668
+ });
1669
+ }
1670
+ load() {
1671
+ return __async(this, null, function* () {
1672
+ if (!this.url) return;
1673
+ try {
1674
+ if (!this.ready) yield _ExternalScript.appendScript(this.url);
1675
+ this.ready = true;
1676
+ } catch (error) {
1677
+ console.error(error);
1678
+ }
1679
+ });
1680
+ }
1681
+ send(payload, forced) {
1682
+ return __async(this, null, function* () {
1683
+ if (!this.analytics.__isInitialized__ && !forced) {
1684
+ this.sendCallstack.push(payload);
1685
+ return Promise.resolve();
1686
+ }
1687
+ return yield this.sendHandler(payload);
1688
+ });
1689
+ }
1690
+ sendForce(_payload) {
1691
+ return __async(this, null, function* () {
1692
+ yield this.load();
1693
+ return yield this.send(_payload, true);
1694
+ });
1695
+ }
1696
+ runSendCallstack() {
1697
+ this.sendCallstack.forEach((payload) => this.send(payload));
1698
+ this.sendCallstack = [];
1699
+ }
1700
+ };
1701
+
1702
+ // src/analytics/index.ts
1703
+ var initObj = { __isInitialized__: false };
1704
+ var Analytics = {
1705
+ initGlobal() {
1706
+ return __async(this, null, function* () {
1707
+ if (initObj.__isInitialized__) return;
1708
+ initObj.__isInitialized__ = true;
1709
+ Object.values(this).forEach((provider) => {
1710
+ if (!(provider instanceof ExternalScript)) return;
1711
+ provider.load();
1712
+ provider.runSendCallstack();
1713
+ });
1714
+ });
1715
+ }
1716
+ };
1717
+
1718
+ // src/index.ts
1719
+ import {
1720
+ CaptchaService as CaptchaService3,
1721
+ CaptchaError,
1722
+ ApiService as ApiService2,
1723
+ RequestPlugin,
1724
+ ResponseSuccessPlugin,
1725
+ ResponseFailPlugin
1726
+ } from "@foxford/services";
1727
+ export {
1728
+ Analytics,
1729
+ ApiService2 as ApiService,
1730
+ AppOptionsService,
1731
+ CaptchaError,
1732
+ CaptchaService3 as CaptchaService,
1733
+ CartService,
1734
+ CourseService,
1735
+ Foxford,
1736
+ FoxfordAntibot,
1737
+ LeadRequestService,
1738
+ LeadRequestType,
1739
+ ProductPackService,
1740
+ PromoService,
1741
+ RequestPlugin,
1742
+ ResponseFailPlugin,
1743
+ ResponseSuccessPlugin,
1744
+ TagService,
1745
+ User,
1746
+ UserService,
1747
+ Widgets
1748
+ };