@snabcentr/client-core 2.64.2 → 2.65.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.
Files changed (182) hide show
  1. package/cart/internal/sc-i-cart-item-dto.d.ts +2 -2
  2. package/catalog/classes/index.d.ts +1 -0
  3. package/catalog/classes/sc-catalog-item.d.ts +31 -0
  4. package/catalog/dto/index.d.ts +0 -2
  5. package/catalog/dto/sc-category.d.ts +18 -51
  6. package/catalog/dto/sc-product.d.ts +26 -51
  7. package/catalog/dto/sc-virtual-category.d.ts +13 -30
  8. package/catalog/interfaces/index.d.ts +4 -0
  9. package/catalog/interfaces/sc-i-catalog-item.d.ts +16 -0
  10. package/catalog/interfaces/sc-i-category.d.ts +29 -0
  11. package/catalog/{internal/sc-i-product-dto.d.ts → interfaces/sc-i-product.d.ts} +8 -27
  12. package/catalog/interfaces/sc-i-virtual-category.d.ts +20 -0
  13. package/catalog/internal/index.d.ts +0 -4
  14. package/catalog/services/sc-catalog.service.d.ts +3 -2
  15. package/catalog/services/sc-favorite.service.d.ts +1 -1
  16. package/common/classes/index.d.ts +9 -0
  17. package/common/classes/sc-catalogable-item.d.ts +17 -0
  18. package/common/classes/sc-coded-identity.d.ts +17 -0
  19. package/common/classes/sc-deletable-named-identity.d.ts +17 -0
  20. package/common/classes/sc-hidden-catalogable-item.d.ts +17 -0
  21. package/common/classes/sc-identity.d.ts +25 -0
  22. package/common/classes/sc-image.d.ts +6 -8
  23. package/common/classes/sc-named-identity.d.ts +17 -0
  24. package/common/classes/sc-primary-catalogable-item.d.ts +17 -0
  25. package/common/classes/sc-reference.d.ts +21 -0
  26. package/common/classes/sc-updatable-named-identity.d.ts +17 -0
  27. package/common/index.d.ts +1 -1
  28. package/common/interfaces/index.d.ts +16 -0
  29. package/common/interfaces/sc-i-catalogable-item.d.ts +10 -0
  30. package/common/interfaces/sc-i-coded-identity.d.ts +10 -0
  31. package/common/interfaces/sc-i-created-at.d.ts +9 -0
  32. package/common/interfaces/sc-i-date-period.d.ts +6 -0
  33. package/common/interfaces/sc-i-deletable-named-identity.d.ts +7 -0
  34. package/common/interfaces/sc-i-deleted-at.d.ts +9 -0
  35. package/common/interfaces/sc-i-file.d.ts +13 -0
  36. package/common/interfaces/sc-i-hidden-catalogable-item.d.ts +10 -0
  37. package/common/interfaces/sc-i-identity.d.ts +13 -0
  38. package/common/interfaces/sc-i-image.d.ts +1 -1
  39. package/common/interfaces/sc-i-named-identity.d.ts +7 -0
  40. package/common/interfaces/sc-i-named.d.ts +9 -0
  41. package/common/interfaces/sc-i-primary-catalogable-item.d.ts +10 -0
  42. package/common/interfaces/sc-i-reference.d.ts +14 -0
  43. package/common/interfaces/sc-i-typed-nullable-range.d.ts +13 -0
  44. package/common/interfaces/sc-i-updatable-named-identity.d.ts +7 -0
  45. package/common/interfaces/sc-i-updated-at.d.ts +9 -0
  46. package/config/index.d.ts +0 -1
  47. package/esm2022/cart/internal/sc-i-cart-item-dto.mjs +1 -1
  48. package/esm2022/catalog/classes/index.mjs +2 -1
  49. package/esm2022/catalog/classes/sc-catalog-item.mjs +19 -0
  50. package/esm2022/catalog/dto/index.mjs +1 -3
  51. package/esm2022/catalog/dto/sc-category.mjs +20 -38
  52. package/esm2022/catalog/dto/sc-product.mjs +27 -32
  53. package/esm2022/catalog/dto/sc-virtual-category.mjs +11 -14
  54. package/esm2022/catalog/interfaces/index.mjs +5 -1
  55. package/esm2022/catalog/interfaces/sc-i-catalog-item.mjs +2 -0
  56. package/esm2022/catalog/interfaces/sc-i-category.mjs +3 -0
  57. package/esm2022/catalog/interfaces/sc-i-product.mjs +3 -0
  58. package/esm2022/catalog/interfaces/sc-i-virtual-category.mjs +2 -0
  59. package/esm2022/catalog/internal/index.mjs +1 -5
  60. package/esm2022/catalog/services/sc-catalog.service.mjs +1 -1
  61. package/esm2022/catalog/services/sc-favorite.service.mjs +2 -2
  62. package/esm2022/catalog/services/sc-recommendation.service.mjs +1 -1
  63. package/esm2022/common/classes/index.mjs +10 -1
  64. package/esm2022/common/classes/sc-catalogable-item.mjs +16 -0
  65. package/esm2022/common/classes/sc-coded-identity.mjs +21 -0
  66. package/esm2022/common/classes/sc-deletable-named-identity.mjs +18 -0
  67. package/esm2022/common/classes/sc-hidden-catalogable-item.mjs +16 -0
  68. package/esm2022/common/classes/sc-identity.mjs +23 -0
  69. package/esm2022/common/classes/sc-image.mjs +7 -9
  70. package/esm2022/common/classes/sc-named-identity.mjs +21 -0
  71. package/esm2022/common/classes/sc-primary-catalogable-item.mjs +16 -0
  72. package/esm2022/common/classes/sc-reference.mjs +17 -0
  73. package/esm2022/common/classes/sc-updatable-named-identity.mjs +18 -0
  74. package/esm2022/common/index.mjs +2 -2
  75. package/esm2022/common/interfaces/index.mjs +17 -1
  76. package/esm2022/common/interfaces/sc-i-catalogable-item.mjs +2 -0
  77. package/esm2022/common/interfaces/sc-i-coded-identity.mjs +2 -0
  78. package/esm2022/common/interfaces/sc-i-created-at.mjs +2 -0
  79. package/esm2022/common/interfaces/sc-i-date-period.mjs +2 -0
  80. package/esm2022/common/interfaces/sc-i-deletable-named-identity.mjs +2 -0
  81. package/esm2022/common/interfaces/sc-i-deleted-at.mjs +2 -0
  82. package/esm2022/common/interfaces/sc-i-file.mjs +2 -0
  83. package/esm2022/common/interfaces/sc-i-hidden-catalogable-item.mjs +2 -0
  84. package/esm2022/common/interfaces/sc-i-identity.mjs +2 -0
  85. package/esm2022/common/interfaces/sc-i-image.mjs +1 -1
  86. package/esm2022/common/interfaces/sc-i-named-identity.mjs +2 -0
  87. package/esm2022/common/interfaces/sc-i-named.mjs +2 -0
  88. package/esm2022/common/interfaces/sc-i-primary-catalogable-item.mjs +2 -0
  89. package/esm2022/common/interfaces/sc-i-reference.mjs +2 -0
  90. package/esm2022/common/interfaces/sc-i-typed-nullable-range.mjs +2 -0
  91. package/esm2022/common/interfaces/sc-i-updatable-named-identity.mjs +2 -0
  92. package/esm2022/common/interfaces/sc-i-updated-at.mjs +2 -0
  93. package/esm2022/config/index.mjs +1 -2
  94. package/esm2022/configurator/services/sc-configurator.service.mjs +1 -1
  95. package/esm2022/guards/index.mjs +1 -2
  96. package/esm2022/helpers/sc-image-helper.mjs +13 -3
  97. package/esm2022/helpers/sc-units-helper.mjs +1 -1
  98. package/esm2022/news/classes/index.mjs +1 -5
  99. package/esm2022/news/classes/sc-news.mjs +13 -12
  100. package/esm2022/news/index.mjs +4 -7
  101. package/esm2022/news/interfaces/index.mjs +3 -0
  102. package/esm2022/news/interfaces/sc-i-news-tile.mjs +2 -0
  103. package/esm2022/news/interfaces/sc-i-news.mjs +2 -0
  104. package/esm2022/news/services/index.mjs +2 -0
  105. package/esm2022/news/services/sc-news.service.mjs +2 -2
  106. package/esm2022/news/tokens/index.mjs +2 -0
  107. package/esm2022/public-api.mjs +2 -6
  108. package/esm2022/search/services/sc-search.service.mjs +5 -5
  109. package/esm2022/seo/classes/index.mjs +2 -0
  110. package/esm2022/seo/classes/schema-org-factory.mjs +269 -0
  111. package/esm2022/seo/index.mjs +5 -0
  112. package/esm2022/seo/interfaces/index.mjs +5 -0
  113. package/esm2022/seo/interfaces/sc-i-default-page-meta.mjs +2 -0
  114. package/esm2022/seo/interfaces/sc-i-schema-org-breadcrumb-list.mjs +2 -0
  115. package/esm2022/seo/interfaces/sc-i-seo-resource.mjs +2 -0
  116. package/esm2022/seo/interfaces/sc-i-seo.mjs +2 -0
  117. package/esm2022/seo/services/index.mjs +2 -0
  118. package/esm2022/seo/services/sc-seo.service.mjs +206 -0
  119. package/esm2022/seo/types/index.mjs +2 -0
  120. package/esm2022/seo/types/robots-tag-type.mjs +2 -0
  121. package/esm2022/tokens/sc-default-page-meta.mjs +1 -1
  122. package/fesm2022/snabcentr-client-core.mjs +782 -588
  123. package/fesm2022/snabcentr-client-core.mjs.map +1 -1
  124. package/guards/index.d.ts +0 -1
  125. package/helpers/sc-image-helper.d.ts +1 -1
  126. package/helpers/sc-units-helper.d.ts +1 -1
  127. package/news/classes/index.d.ts +0 -1
  128. package/news/classes/sc-news.d.ts +18 -13
  129. package/news/index.d.ts +3 -3
  130. package/news/interfaces/index.d.ts +2 -0
  131. package/news/interfaces/sc-i-news-tile.d.ts +22 -0
  132. package/news/interfaces/sc-i-news.d.ts +11 -0
  133. package/news/services/index.d.ts +1 -0
  134. package/news/services/sc-news.service.d.ts +4 -3
  135. package/news/tokens/index.d.ts +1 -0
  136. package/package.json +1 -1
  137. package/public-api.d.ts +1 -2
  138. package/search/services/sc-search.service.d.ts +5 -4
  139. package/seo/classes/index.d.ts +1 -0
  140. package/seo/classes/schema-org-factory.d.ts +88 -0
  141. package/seo/index.d.ts +4 -0
  142. package/seo/interfaces/index.d.ts +4 -0
  143. package/seo/interfaces/sc-i-default-page-meta.d.ts +17 -0
  144. package/seo/interfaces/sc-i-schema-org-breadcrumb-list.d.ts +34 -0
  145. package/seo/interfaces/sc-i-seo-resource.d.ts +14 -0
  146. package/{catalog/dto → seo/interfaces}/sc-i-seo.d.ts +3 -14
  147. package/seo/services/index.d.ts +1 -0
  148. package/seo/services/sc-seo.service.d.ts +125 -0
  149. package/seo/types/index.d.ts +1 -0
  150. package/tokens/sc-default-page-meta.d.ts +1 -1
  151. package/catalog/dto/sc-i-seo-resource.d.ts +0 -10
  152. package/catalog/dto/sc-seo-resource.d.ts +0 -22
  153. package/catalog/internal/sc-i-category-dto.d.ts +0 -48
  154. package/catalog/internal/sc-i-seo-resource-dto.d.ts +0 -10
  155. package/catalog/internal/sc-i-virtual-category-dto.d.ts +0 -37
  156. package/config/sc-i-default-page-meta.d.ts +0 -17
  157. package/esm2022/catalog/dto/sc-i-seo-resource.mjs +0 -2
  158. package/esm2022/catalog/dto/sc-i-seo.mjs +0 -2
  159. package/esm2022/catalog/dto/sc-seo-resource.mjs +0 -23
  160. package/esm2022/catalog/internal/sc-i-category-dto.mjs +0 -3
  161. package/esm2022/catalog/internal/sc-i-product-dto.mjs +0 -2
  162. package/esm2022/catalog/internal/sc-i-seo-resource-dto.mjs +0 -2
  163. package/esm2022/catalog/internal/sc-i-virtual-category-dto.mjs +0 -2
  164. package/esm2022/config/sc-i-default-page-meta.mjs +0 -2
  165. package/esm2022/guards/catalog-seo.guard.mjs +0 -71
  166. package/esm2022/news/classes/sc-news-tile.mjs +0 -2
  167. package/esm2022/news/internal/sc-i-news-dto.mjs +0 -2
  168. package/esm2022/sc-json-ld/index.mjs +0 -3
  169. package/esm2022/sc-json-ld/sc-json-ld.component.mjs +0 -49
  170. package/esm2022/sc-json-ld/sc-json-ld.module.mjs +0 -19
  171. package/esm2022/services/index.mjs +0 -3
  172. package/esm2022/services/sc-seo.service.mjs +0 -271
  173. package/esm2022/services/types/robots-tag-type.mjs +0 -2
  174. package/guards/catalog-seo.guard.d.ts +0 -14
  175. package/news/classes/sc-news-tile.d.ts +0 -25
  176. package/news/internal/sc-i-news-dto.d.ts +0 -30
  177. package/sc-json-ld/index.d.ts +0 -2
  178. package/sc-json-ld/sc-json-ld.component.d.ts +0 -31
  179. package/sc-json-ld/sc-json-ld.module.d.ts +0 -10
  180. package/services/index.d.ts +0 -2
  181. package/services/sc-seo.service.d.ts +0 -184
  182. /package/{services → seo}/types/robots-tag-type.d.ts +0 -0
@@ -1,5 +1,7 @@
1
+ import { parseISO, parse, isValid, format } from 'date-fns';
2
+ import { isString, isMatch, isArray } from 'lodash-es';
1
3
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, PLATFORM_ID, Injectable, Inject, Optional, EventEmitter, LOCALE_ID, Pipe, RendererFactory2, Component, ChangeDetectionStrategy, HostBinding, Input, NgModule } from '@angular/core';
4
+ import { InjectionToken, inject, PLATFORM_ID, Injectable, Inject, Optional, EventEmitter, LOCALE_ID, Pipe, RendererFactory2 } from '@angular/core';
3
5
  import { WA_LOCAL_STORAGE, WA_USER_AGENT, WA_WINDOW } from '@ng-web-apis/common';
4
6
  import { filterByKey, toValue, WA_STORAGE_EVENT, StorageService } from '@ng-web-apis/storage';
5
7
  import * as i1 from 'rxjs';
@@ -13,28 +15,176 @@ import { tuiCleanObject } from '@taiga-ui/addon-doc/utils';
13
15
  import { __decorate } from 'tslib';
14
16
  import * as i2 from '@angular/router';
15
17
  import { ActivatedRoute, Router, NavigationEnd } from '@angular/router';
16
- import { isString, isMatch, isArray } from 'lodash-es';
17
- import { filter as filter$1, tap as tap$1, map as map$1, catchError as catchError$1 } from 'rxjs/operators';
18
- import * as i1$2 from '@angular/platform-browser';
19
- import { Meta, Title } from '@angular/platform-browser';
20
18
  import { objectToSnake, objectToCamel, toSnake } from 'ts-case-convert';
21
- import { parse, isValid, format } from 'date-fns';
19
+ import { Meta, Title } from '@angular/platform-browser';
20
+
21
+ /**
22
+ * Базовая идентифицируемая сущность.
23
+ */
24
+ class ScIdentity {
25
+ /**
26
+ * Инициализирует экземпляр класса {@link ScIdentity}.
27
+ *
28
+ * @param data Данные для первоначальной инициализации.
29
+ */
30
+ constructor(data) {
31
+ this.id = data?.id ?? this.getDefaultId();
32
+ this.guid = data?.guid ?? '';
33
+ }
34
+ /**
35
+ * Значение по умолчанию для {@link id}, когда тип не удаётся определить по {@link data}.
36
+ * Переопределяется в наследниках, например, с {@link T} = string, чтобы возвращать `''`.
37
+ */
38
+ // eslint-disable-next-line class-methods-use-this
39
+ getDefaultId() {
40
+ return -1;
41
+ }
42
+ }
43
+
44
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition */
45
+ /**
46
+ * Базовая идентифицируемая сущность содержащая название.
47
+ */
48
+ class ScNamedIdentity extends ScIdentity {
49
+ /**
50
+ * Инициализирует экземпляр класса {@link ScNamedIdentity}.
51
+ *
52
+ * @param data Данные для первоначальной инициализации.
53
+ */
54
+ constructor(data) {
55
+ super(data);
56
+ /**
57
+ * @inheritDoc
58
+ */
59
+ this.name = '';
60
+ this.name = data?.name ?? '';
61
+ }
62
+ }
63
+
64
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition */
65
+ /**
66
+ * Базовая идентифицируемая сущность содержащая название и артикул.
67
+ */
68
+ class ScCodedIdentity extends ScNamedIdentity {
69
+ /**
70
+ * Инициализирует экземпляр класса {@link ScCodedIdentity}.
71
+ *
72
+ * @param data Данные для первоначальной инициализации.
73
+ */
74
+ constructor(data) {
75
+ super(data);
76
+ /**
77
+ * @inheritDoc
78
+ */
79
+ this.code = '';
80
+ this.code = data?.code ?? '';
81
+ }
82
+ }
83
+
84
+ /**
85
+ * DTO-объект записи данных из справочника.
86
+ */
87
+ class ScReference extends ScNamedIdentity {
88
+ /**
89
+ * Инициализирует экземпляр класса {@link ScReference}.
90
+ *
91
+ * @param data Данные для первоначальной инициализации.
92
+ */
93
+ constructor(data) {
94
+ super(data);
95
+ this.description = data?.description;
96
+ this.slug = data?.slug;
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Базовая идентифицируемая сущность содержащая название и дату изменения.
102
+ */
103
+ class ScUpdatableNamedIdentity extends ScNamedIdentity {
104
+ /**
105
+ * Инициализирует экземпляр класса {@link ScUpdatableNamedIdentity}.
106
+ *
107
+ * @param data Данные для первоначальной инициализации.
108
+ */
109
+ constructor(data) {
110
+ super(data);
111
+ this.updatedAt = isString(data?.updatedAt) ? parseISO(data.updatedAt) : data?.updatedAt;
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Базовая идентифицируемая сущность содержащая название, дату изменения и удаления.
117
+ */
118
+ class ScDeletableNamedIdentity extends ScUpdatableNamedIdentity {
119
+ /**
120
+ * Инициализирует экземпляр класса {@link ScUpdatableNamedIdentity}.
121
+ *
122
+ * @param data Данные для первоначальной инициализации.
123
+ */
124
+ constructor(data) {
125
+ super(data);
126
+ this.deletedAt = isString(data?.deletedAt) ? parseISO(data.deletedAt) : data?.deletedAt;
127
+ }
128
+ }
22
129
 
23
130
  /**
24
- * Базовый класс для изображений.
131
+ * Данные об изображении.
25
132
  */
26
133
  class ScImage {
27
134
  /**
28
135
  * Инициализирует экземпляр класса {@link ScImage}.
29
136
  *
30
- * @param image Изображение.
31
- * @param alt Альтернативный текст.
32
- * @param imageWebp Изображение в формате WebP.
137
+ * @param data Данные для первоначальной инициализации.
138
+ */
139
+ constructor(data) {
140
+ this.image = data.image;
141
+ this.imageWebp = data.imageWebp;
142
+ this.alt = data.alt;
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Данные об элементе каталога.
148
+ */
149
+ class ScCatalogableItem extends ScCodedIdentity {
150
+ /**
151
+ * Инициализирует экземпляр класса {@link ScCatalogableItem}.
152
+ *
153
+ * @param data Данные для первоначальной инициализации.
154
+ */
155
+ constructor(data) {
156
+ super(data);
157
+ this.slug = data?.slug ?? '';
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Данные о каталогизируемом элементе, который может быть скрыт.
163
+ */
164
+ class ScHiddenCatalogableItem extends ScCatalogableItem {
165
+ /**
166
+ * Инициализирует экземпляр класса {@link ScHiddenCatalogableItem}.
167
+ *
168
+ * @param data Данные для первоначальной инициализации.
169
+ */
170
+ constructor(data) {
171
+ super(data);
172
+ this.isHidden = data?.isHidden ?? false;
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Данные о каталогизируемом элементе, который может быть помечен как основной.
178
+ */
179
+ class ScPrimaryCatalogableItem extends ScHiddenCatalogableItem {
180
+ /**
181
+ * Инициализирует экземпляр класса {@link ScPrimaryCatalogableItem}.
182
+ *
183
+ * @param data Данные для первоначальной инициализации.
33
184
  */
34
- constructor(image, alt, imageWebp) {
35
- this.image = image;
36
- this.imageWebp = imageWebp;
37
- this.alt = alt;
185
+ constructor(data) {
186
+ super(data);
187
+ this.isPrimary = data?.isPrimary ?? false;
38
188
  }
39
189
  }
40
190
 
@@ -1249,32 +1399,27 @@ class ScSum {
1249
1399
  }
1250
1400
 
1251
1401
  /**
1252
- * Модель данных объекта имеющего SEO данные.
1402
+ * Данные об элементе каталога.
1253
1403
  */
1254
- class ScSeoResource {
1404
+ class ScCatalogItem extends ScCatalogableItem {
1255
1405
  /**
1256
- * Инициализирует экземпляр класса {@link ScSeoResource}.
1406
+ * Инициализирует экземпляр класса {@link ScCatalogItem}.
1257
1407
  *
1258
- * @param seoResourceDTO Данные для инициализации.
1408
+ * @param data Данные для первоначальной инициализации.
1259
1409
  */
1260
- constructor(seoResourceDTO) {
1261
- if (!seoResourceDTO) {
1262
- return;
1263
- }
1264
- if ('_Seo' in seoResourceDTO) {
1265
- // eslint-disable-next-line no-underscore-dangle
1266
- this.seo = seoResourceDTO._Seo;
1267
- }
1268
- else if ('seo' in seoResourceDTO) {
1269
- this.seo = seoResourceDTO.seo;
1270
- }
1410
+ constructor(data) {
1411
+ super(data);
1412
+ this.properties = data?.properties;
1413
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-assignment,no-underscore-dangle,@typescript-eslint/no-unsafe-member-access
1414
+ this.seo = data._Seo ?? data?.seo;
1415
+ this.image = data?.image;
1271
1416
  }
1272
1417
  }
1273
1418
 
1274
1419
  /**
1275
1420
  * Модель данных категории товаров.
1276
1421
  */
1277
- class ScCategory extends ScSeoResource {
1422
+ class ScCategory extends ScCatalogItem {
1278
1423
  /**
1279
1424
  * Признак, что категория является избранной для клиента.
1280
1425
  *
@@ -1286,38 +1431,23 @@ class ScCategory extends ScSeoResource {
1286
1431
  /**
1287
1432
  * Инициализирует экземпляр класса {@link ScCategory}.
1288
1433
  *
1289
- * @param categoryDTO DTO с данными о категории товаров.
1434
+ * @param data DTO с данными о категории товаров.
1290
1435
  */
1291
- constructor(categoryDTO) {
1292
- super(categoryDTO);
1293
- /**
1294
- * Признак, что информация о категории загружается.
1295
- *
1296
- * @deprecated
1297
- */
1298
- this.isLoading = false;
1436
+ constructor(data) {
1437
+ super(data);
1299
1438
  /**
1300
1439
  * Фильтры категории древовидного представления каталога.
1301
1440
  *
1302
1441
  * @deprecated
1303
1442
  */
1304
1443
  this.filter = '*';
1305
- /**
1306
- * Признак, что категория является скелетоном.
1307
- *
1308
- * @deprecated
1309
- */
1310
- this.isSkeleton = false;
1311
- this.id = categoryDTO.id;
1312
- this.slug = categoryDTO.slug;
1313
- this.name = categoryDTO.name;
1314
- this.isPrimary = categoryDTO.isPrimary;
1315
- this.isFavoriteValue = Boolean(categoryDTO.isFavorite);
1316
- this.properties = categoryDTO.properties;
1317
- this.parentCategory = categoryDTO.parentCategory && new ScCategory(categoryDTO.parentCategory);
1318
- this.hasChild = categoryDTO.hasChild;
1319
- this.categories = categoryDTO.categories?.map((item) => new ScCategory(item));
1320
- this.image = categoryDTO.properties?.image;
1444
+ this.parentCategory = data.parentCategory && new ScCategory(data.parentCategory);
1445
+ this.image = data.properties?.image;
1446
+ this.isHidden = data.isHidden;
1447
+ this.isPrimary = data.isPrimary;
1448
+ this.categories = data.categories?.map((item) => new ScCategory(item));
1449
+ this.hasChild = data.hasChild;
1450
+ this.isFavoriteValue = Boolean(data.isFavorite);
1321
1451
  if (this.properties?.editor) {
1322
1452
  this.showConfigurator = true;
1323
1453
  }
@@ -1332,14 +1462,8 @@ class ScCategory extends ScSeoResource {
1332
1462
  * Признак, что в категории есть товары для отображения.
1333
1463
  */
1334
1464
  get isNotHiddenProducts() {
1335
- return this.products?.find((product) => !product.isHiddenFilter) !== undefined;
1336
- }
1337
- /**
1338
- * Признак, что в категории или вложенных подкатегориях есть товары для отображения.
1339
- */
1340
- get isNotHiddenProductsIncludeSubcategories() {
1341
- return (this.products?.find((product) => !product.isHiddenFilter) !== undefined ||
1342
- this.categories?.find((category) => category.isNotHiddenProductsIncludeSubcategories) !== undefined);
1465
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1466
+ return this.products?.find((product) => !product?.isHiddenFilter) !== undefined;
1343
1467
  }
1344
1468
  /**
1345
1469
  * Признак, что категория является избранной для клиента.
@@ -1407,7 +1531,8 @@ class ScCategory extends ScSeoResource {
1407
1531
  */
1408
1532
  setChildrenCategoriesFilters() {
1409
1533
  this.categories?.forEach((item) => {
1410
- item.setFilter(this.filter === '*' || this.filter === undefined ? this.filter : this.filter.categories?.[item.id]);
1534
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1535
+ item?.setFilter(this.filter === '*' || this.filter === undefined ? this.filter : this.filter.categories?.[item.id]);
1411
1536
  });
1412
1537
  }
1413
1538
  /**
@@ -1447,7 +1572,8 @@ class ScCategory extends ScSeoResource {
1447
1572
  sortProduct(sortFcn) {
1448
1573
  this.products = this.products?.sort(sortFcn);
1449
1574
  this.categories?.forEach((category) => {
1450
- category.sortProduct(sortFcn);
1575
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1576
+ category?.sortProduct(sortFcn);
1451
1577
  });
1452
1578
  }
1453
1579
  /**
@@ -1457,6 +1583,7 @@ class ScCategory extends ScSeoResource {
1457
1583
  * @deprecated
1458
1584
  */
1459
1585
  setIsFavoriteFromChild(isFavorite) {
1586
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1460
1587
  this.parentCategory?.setIsFavoriteFromChild(isFavorite);
1461
1588
  this.products
1462
1589
  ?.filter((product) => product.primaryCategory?.id === this.id)
@@ -1471,15 +1598,15 @@ class ScCategory extends ScSeoResource {
1471
1598
  /**
1472
1599
  * Модель данных товара/услуги.
1473
1600
  */
1474
- class ScProduct extends ScSeoResource {
1601
+ class ScProduct extends ScCatalogItem {
1475
1602
  /**
1476
1603
  * Инициализирует экземпляр класса {@link ScProduct}.
1477
1604
  *
1478
- * @param productDTO Данные о продукте.
1605
+ * @param data Данные о продукте.
1479
1606
  * @param ord Порядок следования продукта в списке.
1480
1607
  */
1481
- constructor(productDTO, ord = 0) {
1482
- super(productDTO);
1608
+ constructor(data, ord = 0) {
1609
+ super(data ?? undefined);
1483
1610
  /**
1484
1611
  * Признак наличия изображения у товара.
1485
1612
  */
@@ -1496,37 +1623,32 @@ class ScProduct extends ScSeoResource {
1496
1623
  * Признак необходимости игнорировать проверку минимального количества и кратности при добавлении товара в корзину и создании заказа.
1497
1624
  */
1498
1625
  this.ignoreMinCountCheck = false;
1499
- if (productDTO === null) {
1626
+ this.isHidden = data?.isHidden ?? false;
1627
+ this.ord = ord;
1628
+ if (data === null) {
1500
1629
  this.isNull = true;
1501
1630
  this.name = 'Товар не найден';
1502
1631
  }
1503
1632
  else {
1504
- this.id = productDTO.id;
1505
- this.slug = productDTO.slug;
1506
- this.supplierSku = productDTO.supplierSku;
1507
- this.name = productDTO.name;
1508
- this.cost = productDTO.cost;
1509
- this.costRub = productDTO.costRub;
1510
- this.costDate = productDTO.costDate;
1511
- this.currency = productDTO.currency;
1512
- this.code = productDTO.code;
1513
- this.unit = productDTO.unit;
1514
- this.minCount = productDTO.minCount;
1515
- this.stockCount = productDTO.stockCount;
1516
- this.onOrder = productDTO.onOrder;
1517
- this.pack = productDTO.pack;
1518
- this.isFavorite = Boolean(productDTO.isFavorite);
1519
- this.isPreviouslyOrdered = productDTO.isPreviouslyOrdered;
1520
- this.hasImage = (productDTO.images && productDTO.images.length > 0) ?? false;
1521
- this.images = productDTO.images?.slice().sort((img1, img2) => Number(img2.isDefault) - Number(img1.isDefault));
1522
- this.image = productDTO.images?.find((img) => img.isDefault)?.image ?? productDTO.properties?.image;
1523
- this.categories = productDTO.categories.map((category) => new ScCategory(category));
1633
+ this.image = data.images?.find((img) => img.isDefault)?.image ?? data.properties?.image;
1634
+ this.supplierSku = data.supplierSku;
1635
+ this.cost = data.cost;
1636
+ this.costRub = data.costRub;
1637
+ this.costDate = data.costDate;
1638
+ this.currency = data.currency;
1639
+ this.unit = data.unit;
1640
+ this.minCount = data.minCount;
1641
+ this.stockCount = data.stockCount;
1642
+ this.onOrder = data.onOrder;
1643
+ this.pack = data.pack;
1644
+ this.isFavorite = Boolean(data.isFavorite);
1645
+ this.isPreviouslyOrdered = data.isPreviouslyOrdered;
1646
+ this.hasImage = (data.images && data.images.length > 0) ?? false;
1647
+ this.images = data.images?.slice().sort((img1, img2) => Number(img2.isDefault) - Number(img1.isDefault));
1648
+ this.categories = data.categories.map((category) => new ScCategory(category));
1524
1649
  this.primaryCategory = this.categories.find((item) => item.isPrimary);
1525
- this.ignoreMinCountCheck = productDTO.properties?.ignoreMinCountCheck ?? this.properties?.ignoreMinCountCheck ?? this.ignoreMinCountCheck;
1526
- this.properties = productDTO.properties;
1527
- this.discount = productDTO.discount;
1528
- this.ord = ord;
1529
- this.isHidden = productDTO.isHidden;
1650
+ this.ignoreMinCountCheck = data.properties?.ignoreMinCountCheck ?? this.properties?.ignoreMinCountCheck ?? this.ignoreMinCountCheck;
1651
+ this.discount = data.discount;
1530
1652
  }
1531
1653
  }
1532
1654
  /**
@@ -2797,6 +2919,10 @@ var ScMimeTypes;
2797
2919
  ScMimeTypes["7z"] = "application/x-7z-compressed";
2798
2920
  })(ScMimeTypes || (ScMimeTypes = {}));
2799
2921
 
2922
+ /* TODO: Вынести в internal после переноса в библиотеку CatalogService - TASK[#6433], ConfiguratorService - TASK[#6434], FavoriteService - TASK[#6435] */
2923
+
2924
+ /* TODO: Вынести в internal после переноса в библиотеку CatalogService - TASK[#6433], FavoriteService - TASK[#6435] */
2925
+
2800
2926
  /**
2801
2927
  * Модель закэшированных данных.
2802
2928
  */
@@ -2857,27 +2983,22 @@ class ScCachedItem {
2857
2983
  /**
2858
2984
  * Данные о виртуальной категории.
2859
2985
  */
2860
- class ScVirtualCategory extends ScSeoResource {
2986
+ class ScVirtualCategory extends ScCatalogItem {
2861
2987
  /**
2862
2988
  * Инициализирует экземпляр класса {@link ScVirtualCategory}.
2863
2989
  *
2864
- * @param virtualCategoryDTO Данные о виртуальной категории.
2990
+ * @param data Данные о виртуальной категории.
2865
2991
  */
2866
- constructor(virtualCategoryDTO) {
2867
- super(virtualCategoryDTO);
2868
- this.name = virtualCategoryDTO.name;
2869
- this.slug = virtualCategoryDTO.slug;
2870
- this.properties = virtualCategoryDTO.properties;
2871
- this.image = virtualCategoryDTO.properties?.image;
2872
- this.parentCategory = virtualCategoryDTO.parentCategory ? new ScVirtualCategory(virtualCategoryDTO.parentCategory) : undefined;
2873
- this.childCategories = virtualCategoryDTO.childCategories?.map((item) => new ScVirtualCategory(item));
2874
- this.products = virtualCategoryDTO.products?.map((item) => new ScProduct(item));
2875
- this.productCategories = virtualCategoryDTO.productCategories?.map((item) => new ScCategory(item));
2992
+ constructor(data) {
2993
+ super(data);
2994
+ this.image = data.properties?.image;
2995
+ this.parentCategory = data.parentCategory ? new ScVirtualCategory(data.parentCategory) : undefined;
2996
+ this.childCategories = data.childCategories?.map((item) => new ScVirtualCategory(item));
2997
+ this.products = data.products?.map((item) => new ScProduct(item));
2998
+ this.productCategories = data.productCategories?.map((item) => new ScCategory(item));
2876
2999
  }
2877
3000
  }
2878
3001
 
2879
- /* TODO: Вынести в internal после переноса в библиотеку CatalogService - TASK[#6433], FavoriteService - TASK[#6435] */
2880
-
2881
3002
  /**
2882
3003
  * Токен, указывающий число первых записей товаров со скидкой.
2883
3004
  */
@@ -4820,6 +4941,85 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
4820
4941
  args: [SC_URLS]
4821
4942
  }] }] });
4822
4943
 
4944
+ /**
4945
+ * Сервис аутентификации пользователя на основе ключей, переданных в параметрах запроса.
4946
+ */
4947
+ class ScAuthAsClientGuard {
4948
+ /**
4949
+ * Инициализирует экземпляр класса {@link AuthAsClientGuard}.
4950
+ *
4951
+ * @param authService Сервис аутентификации.
4952
+ * @param router Сервис маршрутизации.
4953
+ * @param options Параметры авторизации под клиентом.
4954
+ */
4955
+ constructor(authService, router, options) {
4956
+ this.authService = authService;
4957
+ this.router = router;
4958
+ this.options = options;
4959
+ }
4960
+ /**
4961
+ * Разрешает/запрещает доступ к маршруту.
4962
+ *
4963
+ * @param route Данные о текущем маршруте.
4964
+ */
4965
+ // eslint-disable-next-line sonarjs/function-return-type
4966
+ canActivate(route) {
4967
+ const expiredAt = new Date();
4968
+ expiredAt.setMinutes(new Date().getMinutes() + this.options.expiredAtMinute);
4969
+ return this.authService.getAuthChange().pipe(first(),
4970
+ // Если пользователь авторизирован, то завершаем сеанс.
4971
+ concatMap((state) => (state ? this.authService.getSignOut$(false) : of(null))),
4972
+ // Обновляем полученные ключи, чтобы они перестали действовать. getRefreshTokenObservable() запишет новые ключи в систему, после чего проложение само запросит нового пользователя.
4973
+ concatMap(() => this.authService.getRefreshToken$({
4974
+ access: {
4975
+ token: route.paramMap.get('atoken') ?? '',
4976
+ expiredAt: expiredAt,
4977
+ },
4978
+ refresh: {
4979
+ token: route.paramMap.get('rtoken') ?? '',
4980
+ expiredAt: expiredAt,
4981
+ },
4982
+ })), first(), map(() => this.router.createUrlTree(this.options.urlTree)));
4983
+ }
4984
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScAuthAsClientGuard, deps: [{ token: ScAuthService }, { token: i2.Router }, { token: SC_AUTH_AS_CLIENT_OPTIONS }], target: i0.ɵɵFactoryTarget.Injectable }); }
4985
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScAuthAsClientGuard }); }
4986
+ }
4987
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScAuthAsClientGuard, decorators: [{
4988
+ type: Injectable
4989
+ }], ctorParameters: () => [{ type: ScAuthService }, { type: i2.Router }, { type: undefined, decorators: [{
4990
+ type: Inject,
4991
+ args: [SC_AUTH_AS_CLIENT_OPTIONS]
4992
+ }] }] });
4993
+
4994
+ /**
4995
+ * Страж выполняющий проверку маршрута товара и категории, и редиректа в зависимости от настроек окружения.
4996
+ *
4997
+ * @param route Сервис предоставляющий доступ к данным о маршруте.
4998
+ */
4999
+ // eslint-disable-next-line sonarjs/function-return-type
5000
+ const ScIdOrSlugGuard = (route) => {
5001
+ const { paramMap } = route;
5002
+ const categoryIdOrSlug = paramMap.get('categoryIdOrSlug');
5003
+ const productIdOrSlug = paramMap.get('productIdOrSlug');
5004
+ const idOrSlug = inject(SC_ID_OR_SLUG_IN_ROUTE);
5005
+ const router = inject(Router);
5006
+ if (categoryIdOrSlug && /^\d+$/.test(categoryIdOrSlug) !== (idOrSlug === 'id')) {
5007
+ return inject(ScCatalogService)
5008
+ .getCategoryCached$(categoryIdOrSlug)
5009
+ .pipe(filter(tuiIsPresent),
5010
+ // eslint-disable-next-line security/detect-object-injection
5011
+ map((category) => router.createUrlTree(['/catalog', category[idOrSlug]])), catchError(() => of(TUI_TRUE_HANDLER())));
5012
+ }
5013
+ if (productIdOrSlug && /^\d+$/.test(productIdOrSlug) !== (idOrSlug === 'id')) {
5014
+ return inject(ScCatalogService)
5015
+ .getProductData$(productIdOrSlug)
5016
+ .pipe(filter(tuiIsPresent),
5017
+ // eslint-disable-next-line security/detect-object-injection
5018
+ map((product) => router.createUrlTree(['/catalog', 'product', product[idOrSlug]])), catchError(() => of(TUI_TRUE_HANDLER())));
5019
+ }
5020
+ return true;
5021
+ };
5022
+
4823
5023
  /**
4824
5024
  * Пайп для формирования полного URI изображения на media сервере.
4825
5025
  */
@@ -4852,432 +5052,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
4852
5052
  }] });
4853
5053
 
4854
5054
  /**
4855
- * Сервис управления SEO-параметрами.
5055
+ * Класс с вспомогательными методами для работы с изображениями.
4856
5056
  */
4857
- class ScSeoService {
4858
- /**
4859
- * Инициализирует экземпляр класса {@link ScSeoService}.
4860
- */
5057
+ class ScImageHelper {
4861
5058
  constructor() {
4862
5059
  /**
4863
- * Событие установки meta-тегов страницы.
4864
- */
4865
- this.isSetMetaTagsEventEmitter = new EventEmitter();
4866
- /**
4867
- * Данные о мета-данных страницы по умолчанию.
4868
- */
4869
- this.defaultSeo = inject(SC_DEFAULT_PAGE_META);
4870
- /**
4871
- * Сервис маршрутизации.
4872
- */
4873
- this.router = inject(Router);
4874
- /**
4875
- * Список ссылок приложения.
4876
- */
4877
- this.urls = inject(SC_URLS);
4878
- /**
4879
- * Сервис установки метаданных страницы.
4880
- */
4881
- this.metaService = inject(Meta);
4882
- /**
4883
- * Сервис управления заголовком страницы.
4884
- */
4885
- this.titleService = inject(Title);
4886
- /**
4887
- * Селектор группы для устанавливаемых метатегов.
4888
- */
4889
- this.dataGroupSelector = 'seo-tags';
4890
- /**
4891
- * Объект {@link Document}, предоставляющий доступ к DOM страницы.
4892
- */
4893
- this.document = inject(DOCUMENT);
4894
- /**
4895
- * Фабрика для создания экземпляров {@link Renderer2}.
4896
- */
4897
- this.rendererFactory = inject(RendererFactory2);
4898
- /**
4899
- * Экземпляр {@link Renderer2} для безопасной работы с DOM.
4900
- */
4901
- this.renderer = this.rendererFactory.createRenderer(null, null);
4902
- /**
4903
- * Название компании.
5060
+ * Список ссылок на разделы backend'a.
4904
5061
  */
4905
- this.companyName = inject(SC_COMPANY_NAME);
4906
- this.setShareType('website');
5062
+ this.mediaImageTransformerPipe = inject(ScMediaImageTransformerPipe);
4907
5063
  }
4908
5064
  /**
4909
- * Устанавливает meta-теги.
5065
+ * Возвращает изображение товара по индексу.
4910
5066
  *
4911
- * @param title Заголовок страницы.
4912
- * @param description Описание страницы.
4913
- * @param keywords Ключевые слова страницы.
4914
- * @param emitEventAfterSet Признак того, необходимо ли генерировать событие, после установки тегов. По умолчанию {@link true}.
4915
- * @param robots Список robots тегов для страницы.
5067
+ * @param product Позиция товара/услуги.
5068
+ * @param imgIndex Индекс изображения в массиве.
5069
+ * @returns Возвращает изображение товара по индексу. Возвращает пути до изображения 'Товар не найден' {@link pathImageNotFound} если изображения по индексу не найдено.
4916
5070
  */
4917
- setPageMetaTags(title = this.defaultSeo.title, description = this.defaultSeo.description, keywords = this.defaultSeo.keywords, emitEventAfterSet = true, robots = ['index', 'follow']) {
4918
- this.setPageTitle(title);
4919
- this.setPageMetaDescription(description);
4920
- this.setPageMetaKeywords(keywords);
4921
- this.setPageMetaRobots(robots);
4922
- if (emitEventAfterSet) {
4923
- this.isSetMetaTagsEventEmitter.emit();
4924
- }
5071
+ getImage(product, imgIndex = 0) {
5072
+ return {
5073
+ image: this.mediaImageTransformerPipe.transform(product.getImage(imgIndex), true),
5074
+ alt: `${product.name} (${imgIndex + 1})`,
5075
+ imageWebp: this.mediaImageTransformerPipe.transform(product.getImageWebp(imgIndex), false),
5076
+ };
4925
5077
  }
4926
5078
  /**
4927
- * Устанавливает Open Graph meta-теги.
4928
- *
4929
- * @param ogTitle Open Graph заголовок.
4930
- * @param ogDescription Open Graph описание.
4931
- * @param ogImg Open Graph изображение.
4932
- * @param emitEventAfterSet Признак того, необходимо ли генерировать событие, после установки тегов. По умолчанию {@link true}.
4933
- */
4934
- setPageOpenGraphMetaTags(ogTitle = this.defaultSeo.title, ogDescription = this.defaultSeo.description, ogImg = this.urls.logoUrl, emitEventAfterSet = true) {
4935
- this.setOpenGraphMetaTags(ogTitle, ogDescription, `${this.urls.siteUrl}${this.router.url}`, ogImg);
4936
- if (emitEventAfterSet) {
4937
- this.isSetMetaTagsEventEmitter.emit();
4938
- }
4939
- }
4940
- /**
4941
- * Устанавливает все meta-теги из пришедшего источника. Если какого-то тега нет, будет установлено значение по умолчанию.
4942
- *
4943
- * @param resource Источник meta - тегов.
4944
- * @param img Изображение. Если не пришло, то будет установлено значение по умолчанию.
4945
- * @param robots Список robots тегов для страницы.
4946
- */
4947
- setMetaTagsFromResource(resource, img = this.urls.logoUrl, robots = ['index', 'follow']) {
4948
- this.setAllPageMetaTags(resource?.title, resource?.description, resource?.keywords, img, resource?.meta, robots);
4949
- }
4950
- /**
4951
- * Устанавливает все meta-теги страницы со значением по умолчанию, внедряя туда заголовок, если он передан.
4952
- *
4953
- * @param title Заголовок страницы.
4954
- * @param robots Список robots тегов для страницы.
4955
- */
4956
- setDefaultAllPageMetaTags(title = this.defaultSeo.title, robots = ['index', 'follow']) {
4957
- this.setAllPageMetaTags(`${title} - ${this.companyName}`, `${title}, ${this.defaultSeo.description}`, undefined, undefined, [], robots);
4958
- }
4959
- /**
4960
- * Устанавливает все meta-теги страницы со значением по умолчанию, внедряя туда заголовок, если он передан. Устанавливает значение "не индексировать" для поисковых роботов.
4961
- *
4962
- * @param title Заголовок страницы.
4963
- */
4964
- setNoIndexDefaultAllPageMetaTags(title = this.defaultSeo.title) {
4965
- this.setAllPageMetaTags(`${title} - ${this.companyName}`, `${title}, ${this.defaultSeo.description}`, undefined, undefined, [], ['noindex', 'nofollow', 'noarchive']);
4966
- }
4967
- /**
4968
- * Устанавливает все meta-теги страницы. Если какой-либо из параметров не указан, для него устанавливается значение по умолчанию.
4969
- *
4970
- * @param title Заголовок страницы.
4971
- * @param description Описание страницы.
4972
- * @param keywords Ключевые слова страницы.
4973
- * @param img Изображение.
4974
- * @param meta Массив дополнительных значений метатегов.
4975
- * @param robots Список robots тегов для страницы.
4976
- */
4977
- setAllPageMetaTags(title = this.defaultSeo.title, description = this.defaultSeo.description, keywords = this.defaultSeo.keywords, img = this.urls.logoUrl, meta = [], robots = ['index', 'follow']) {
4978
- this.removeMetaTags();
4979
- this.setPageTitle(title);
4980
- this.setPageMetaDescription(description);
4981
- this.setPageMetaKeywords(keywords);
4982
- this.setOpenGraphMetaTags(title, description, `${this.urls.siteUrl}${this.router.url}`, img);
4983
- meta.forEach((tag) => {
4984
- this.setPageMetaByName(tag.name, tag.content);
4985
- });
4986
- this.setPageMetaRobots(robots);
4987
- this.isSetMetaTagsEventEmitter.emit();
4988
- }
4989
- /**
4990
- * Устанавливает meta-тег robots для страницы.
4991
- *
4992
- * @param robots Список robots тегов для страницы.
4993
- */
4994
- setPageMetaRobots(robots) {
4995
- this.setPageMetaByName('robots', robots.join(', '));
4996
- }
4997
- /**
4998
- * Удаляет все установленные meta-теги.
4999
- */
5000
- removeMetaTags() {
5001
- const tags = this.document.querySelectorAll(`meta[data-group="${this.dataGroupSelector}"]`);
5002
- tags.forEach((tag) => {
5003
- this.metaService.removeTagElement(tag);
5004
- });
5005
- }
5006
- /**
5007
- * Возвращает сгенерированный SEO-resource с указанными параметрами.
5008
- *
5009
- * @param seo Данные SEO ресурса.
5010
- * @param defaultTitle Заголовок страницы используемый в случае отсутствия заголовка в SEO-ресурсе.
5011
- * @param defaultDescription Описание страницы используемое в случае отсутствия описания в SEO-ресурсе.
5012
- * @param defaultKeyWords Ключевые слова страницы используемые в случае отсутствия ключевых слов в SEO-ресурсе.
5013
- */
5014
- getGenerateSeoResource(seo, defaultTitle, defaultDescription = this.defaultSeo.description, defaultKeyWords = this.defaultSeo.keywords) {
5015
- return {
5016
- title: seo?.title ?? defaultTitle,
5017
- description: seo?.description ?? defaultDescription,
5018
- keywords: seo?.keywords ?? defaultKeyWords,
5019
- meta: seo?.meta,
5020
- };
5021
- }
5022
- /**
5023
- * Устанавливает тег канонической страницы <link rel="canonical" href="..." />.
5024
- *
5025
- * @param url URL который необходимо использовать в качестве ссылки.
5026
- */
5027
- setCanonicalLink(url) {
5028
- // Удаляем существующий link canonical.
5029
- const existingLink = this.document.querySelector('link[rel="canonical"]');
5030
- if (existingLink?.parentNode) {
5031
- this.renderer.removeChild(existingLink.parentNode, existingLink);
5032
- }
5033
- // Создаём и устанавливаем новый тег.
5034
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
5035
- const link = this.renderer.createElement('link');
5036
- this.renderer.setAttribute(link, 'rel', 'canonical');
5037
- this.renderer.setAttribute(link, 'href', url);
5038
- this.renderer.appendChild(this.document.head, link);
5039
- }
5040
- /**
5041
- * Устанавливает title-заголовок страницы.
5042
- *
5043
- * @param title Заголовок страницы.
5044
- * @param appendDefaultTitle Флаг необходимости добавить заголовок по умолчанию в конец заголовка страницы.
5045
- */
5046
- setPageTitle(title, appendDefaultTitle = false) {
5047
- this.titleService.setTitle(title + (appendDefaultTitle ? ` - ${this.defaultSeo.title}` : ''));
5048
- }
5049
- /**
5050
- * Устанавливает meta-описание страницы.
5051
- *
5052
- * @param description Meta-описание страницы.
5053
- */
5054
- setPageMetaDescription(description) {
5055
- this.setPageMetaByName('description', description);
5056
- }
5057
- /**
5058
- * Устанавливает meta-ключевые слова страницы.
5059
- *
5060
- * @param keywords Meta-ключевые слова страницы.
5061
- */
5062
- setPageMetaKeywords(keywords) {
5063
- this.setPageMetaByName('keywords', keywords);
5064
- }
5065
- /**
5066
- * Устанавливает Open Graph meta-теги страницы для социальных сетей.
5067
- *
5068
- * @param title Заголовок страницы.
5069
- * @param description Описание страницы.
5070
- * @param url Ссылка на страницу.
5071
- * @param img Изображение.
5072
- */
5073
- setOpenGraphMetaTags(title, description, url, img) {
5074
- this.setOpenGraphMetaByProperty('og:title', title);
5075
- this.setOpenGraphMetaByProperty('og:url', url);
5076
- this.setOpenGraphMetaByProperty('og:image', img);
5077
- this.setOpenGraphMetaByProperty('og:description', description);
5078
- this.setOpenGraphMetaByProperty('og:type', 'website');
5079
- }
5080
- /**
5081
- * Устанавливает meta-тег страницы с указанным именем.
5082
- * Будет создан или обновлён заголовок вида `<meta name="{name}" content="{content}" />`
5083
- *
5084
- * @param name Название заголовка.
5085
- * @param content Содержимое заголовка.
5086
- */
5087
- setPageMetaByName(name, content) {
5088
- this.metaService.updateTag({ name: name, content: content, 'data-group': this.dataGroupSelector });
5089
- }
5090
- /**
5091
- * Устанавливает Open Graph meta-тег по свойству атрибута property.
5092
- *
5093
- * @param property Свойство атрибута.
5094
- * @param content Содержимое тега.
5095
- */
5096
- setOpenGraphMetaByProperty(property, content) {
5097
- this.metaService.updateTag({ property: property, content: content, 'data-group': this.dataGroupSelector });
5098
- }
5099
- /**
5100
- * Устанавливает Open Graph мета-тег типа объекта.
5101
- *
5102
- * @param type Тип объекта.
5103
- */
5104
- setShareType(type) {
5105
- this.setOpenGraphMetaByProperty('og:type', type);
5106
- }
5107
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScSeoService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5108
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScSeoService, providedIn: 'root' }); }
5109
- }
5110
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScSeoService, decorators: [{
5111
- type: Injectable,
5112
- args: [{
5113
- providedIn: 'root',
5114
- }]
5115
- }], ctorParameters: () => [] });
5116
-
5117
- /**
5118
- * Устанавливает SEO-теги для страниц каталога.
5119
- *
5120
- * @param seoService Сервис для работы с SEO.
5121
- * @param name Название страницы.
5122
- * @param seo SEO-теги.
5123
- * @param image Ссылка на основное изображение.
5124
- */
5125
- const setSeoTags = (seoService, name, seo, image) => {
5126
- const companyInfo = inject(SC_COMPANY_INFO);
5127
- const catalogMeta = inject(SC_CATALOG_PAGE_META);
5128
- const seoResource = seoService.getGenerateSeoResource(seo, `${name} - Купить в ${companyInfo.name}`, `${name} - Купить по выгодным ценам в ${companyInfo.name}`, `${name}, ${catalogMeta.keywords}`);
5129
- seoService.setMetaTagsFromResource(seoResource, image);
5130
- };
5131
- /**
5132
- * Создает SEO-guard для указанного сервиса и метода получения данных.
5133
- *
5134
- * @param getDataFunction Функция для получения данных из сервиса.
5135
- * @param setCanonical Признак необходимости установить на странице каноническую ссылку.
5136
- * @returns Функция-guard.
5137
- */
5138
- const createSeoGuard = (getDataFunction, setCanonical = false) => {
5139
- // eslint-disable-next-line sonarjs/function-return-type
5140
- return ({ paramMap }, state) => {
5141
- const seoService = inject(ScSeoService);
5142
- const mediaImageTransformerPipe = inject(ScMediaImageTransformerPipe);
5143
- const recId = paramMap.get('productIdOrSlug') ?? paramMap.get('categoryIdOrSlug') ?? paramMap.get('categorySlug');
5144
- if (!recId) {
5145
- return false;
5146
- }
5147
- return getDataFunction(recId).pipe(filter$1(tuiIsPresent), tap$1(({ id, name, seo, image, slug }) => {
5148
- setSeoTags(seoService, name, seo, mediaImageTransformerPipe.transform(image, true));
5149
- const idOrSlugInRoute = inject(SC_ID_OR_SLUG_IN_ROUTE);
5150
- // В том случае, если используется slug для формирования ссылок, то необходимо сформировать кононическую ссылку
5151
- // на страницу в которой используется slug (а не id).
5152
- if (setCanonical && idOrSlugInRoute === 'slug' && id && slug) {
5153
- const canonicalPath = state.url
5154
- .split('/')
5155
- .map((segment) => (segment === id.toString() ? slug : segment))
5156
- .join('/');
5157
- const { siteUrl } = inject(SC_URLS);
5158
- seoService.setCanonicalLink(`${siteUrl}${canonicalPath}`);
5159
- }
5160
- }), map$1(TUI_TRUE_HANDLER), catchError$1(() => of(true)), takeUntilDestroyed());
5161
- };
5162
- };
5163
- /**
5164
- * Устанавливает SEO-теги для страницы продукта.
5165
- */
5166
- const ScProductSeoGuard = createSeoGuard((recId) => inject(ScCatalogService).getProductDataCached$(recId), true);
5167
- /**
5168
- * Устанавливает SEO-теги для страницы виртуальной категории.
5169
- */
5170
- const ScVirtualCategorySeoGuard = createSeoGuard((recId) => inject(ScCatalogService).getVirtualCategoryCached$(recId));
5171
- /**
5172
- * Устанавливает SEO-теги для страницы категории.
5173
- */
5174
- const ScCategorySeoGuard = createSeoGuard((recId) => inject(ScCatalogService).getCategoryCached$(recId), true);
5175
-
5176
- /**
5177
- * Сервис аутентификации пользователя на основе ключей, переданных в параметрах запроса.
5178
- */
5179
- class ScAuthAsClientGuard {
5180
- /**
5181
- * Инициализирует экземпляр класса {@link AuthAsClientGuard}.
5182
- *
5183
- * @param authService Сервис аутентификации.
5184
- * @param router Сервис маршрутизации.
5185
- * @param options Параметры авторизации под клиентом.
5186
- */
5187
- constructor(authService, router, options) {
5188
- this.authService = authService;
5189
- this.router = router;
5190
- this.options = options;
5191
- }
5192
- /**
5193
- * Разрешает/запрещает доступ к маршруту.
5194
- *
5195
- * @param route Данные о текущем маршруте.
5196
- */
5197
- // eslint-disable-next-line sonarjs/function-return-type
5198
- canActivate(route) {
5199
- const expiredAt = new Date();
5200
- expiredAt.setMinutes(new Date().getMinutes() + this.options.expiredAtMinute);
5201
- return this.authService.getAuthChange().pipe(first(),
5202
- // Если пользователь авторизирован, то завершаем сеанс.
5203
- concatMap((state) => (state ? this.authService.getSignOut$(false) : of(null))),
5204
- // Обновляем полученные ключи, чтобы они перестали действовать. getRefreshTokenObservable() запишет новые ключи в систему, после чего проложение само запросит нового пользователя.
5205
- concatMap(() => this.authService.getRefreshToken$({
5206
- access: {
5207
- token: route.paramMap.get('atoken') ?? '',
5208
- expiredAt: expiredAt,
5209
- },
5210
- refresh: {
5211
- token: route.paramMap.get('rtoken') ?? '',
5212
- expiredAt: expiredAt,
5213
- },
5214
- })), first(), map(() => this.router.createUrlTree(this.options.urlTree)));
5215
- }
5216
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScAuthAsClientGuard, deps: [{ token: ScAuthService }, { token: i2.Router }, { token: SC_AUTH_AS_CLIENT_OPTIONS }], target: i0.ɵɵFactoryTarget.Injectable }); }
5217
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScAuthAsClientGuard }); }
5218
- }
5219
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScAuthAsClientGuard, decorators: [{
5220
- type: Injectable
5221
- }], ctorParameters: () => [{ type: ScAuthService }, { type: i2.Router }, { type: undefined, decorators: [{
5222
- type: Inject,
5223
- args: [SC_AUTH_AS_CLIENT_OPTIONS]
5224
- }] }] });
5225
-
5226
- /**
5227
- * Страж выполняющий проверку маршрута товара и категории, и редиректа в зависимости от настроек окружения.
5228
- *
5229
- * @param route Сервис предоставляющий доступ к данным о маршруте.
5230
- */
5231
- // eslint-disable-next-line sonarjs/function-return-type
5232
- const ScIdOrSlugGuard = (route) => {
5233
- const { paramMap } = route;
5234
- const categoryIdOrSlug = paramMap.get('categoryIdOrSlug');
5235
- const productIdOrSlug = paramMap.get('productIdOrSlug');
5236
- const idOrSlug = inject(SC_ID_OR_SLUG_IN_ROUTE);
5237
- const router = inject(Router);
5238
- if (categoryIdOrSlug && /^\d+$/.test(categoryIdOrSlug) !== (idOrSlug === 'id')) {
5239
- return inject(ScCatalogService)
5240
- .getCategoryCached$(categoryIdOrSlug)
5241
- .pipe(filter(tuiIsPresent),
5242
- // eslint-disable-next-line security/detect-object-injection
5243
- map((category) => router.createUrlTree(['/catalog', category[idOrSlug]])), catchError(() => of(TUI_TRUE_HANDLER())));
5244
- }
5245
- if (productIdOrSlug && /^\d+$/.test(productIdOrSlug) !== (idOrSlug === 'id')) {
5246
- return inject(ScCatalogService)
5247
- .getProductData$(productIdOrSlug)
5248
- .pipe(filter(tuiIsPresent),
5249
- // eslint-disable-next-line security/detect-object-injection
5250
- map((product) => router.createUrlTree(['/catalog', 'product', product[idOrSlug]])), catchError(() => of(TUI_TRUE_HANDLER())));
5251
- }
5252
- return true;
5253
- };
5254
-
5255
- /**
5256
- * Класс с вспомогательными методами для работы с изображениями.
5257
- */
5258
- class ScImageHelper {
5259
- constructor() {
5260
- /**
5261
- * Список ссылок на разделы backend'a.
5262
- */
5263
- this.mediaImageTransformerPipe = inject(ScMediaImageTransformerPipe);
5264
- }
5265
- /**
5266
- * Возвращает изображение товара по индексу.
5267
- *
5268
- * @param product Позиция товара/услуги.
5269
- * @param imgIndex Индекс изображения в массиве.
5270
- * @returns Возвращает изображение товара по индексу. Возвращает пути до изображения 'Товар не найден' {@link pathImageNotFound} если изображения по индексу не найдено.
5271
- */
5272
- getImage(product, imgIndex = 0) {
5273
- return {
5274
- image: this.mediaImageTransformerPipe.transform(product.getImage(imgIndex), true),
5275
- alt: `${product.name} (${imgIndex + 1})`,
5276
- imageWebp: this.mediaImageTransformerPipe.transform(product.getImageWebp(imgIndex), false),
5277
- };
5278
- }
5279
- /**
5280
- * Возвращает превью-изображение товара по индексу.
5079
+ * Возвращает превью-изображение товара по индексу.
5281
5080
  *
5282
5081
  * @param product Позиция товара/услуги.
5283
5082
  * @param previewIndex Индекс превью-изображения в массиве.
@@ -5296,7 +5095,12 @@ class ScImageHelper {
5296
5095
  return images;
5297
5096
  }
5298
5097
  if (useDefaultImage) {
5299
- return [new ScImage(this.mediaImageTransformerPipe.transform(undefined, true), product.name)];
5098
+ return [
5099
+ new ScImage({
5100
+ image: this.mediaImageTransformerPipe.transform(undefined, true),
5101
+ alt: product.name,
5102
+ }),
5103
+ ];
5300
5104
  }
5301
5105
  return undefined;
5302
5106
  }
@@ -5306,7 +5110,12 @@ class ScImageHelper {
5306
5110
  return images;
5307
5111
  }
5308
5112
  if (useDefaultImage) {
5309
- return [new ScImage(this.mediaImageTransformerPipe.transform(undefined, true), product.name)];
5113
+ return [
5114
+ new ScImage({
5115
+ image: this.mediaImageTransformerPipe.transform(undefined, true),
5116
+ alt: product.name,
5117
+ }),
5118
+ ];
5310
5119
  }
5311
5120
  return undefined;
5312
5121
  }
@@ -6042,27 +5851,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
6042
5851
  /**
6043
5852
  * Модель данных новости.
6044
5853
  */
6045
- class ScNews extends ScSeoResource {
5854
+ class ScNews extends ScIdentity {
6046
5855
  /**
6047
5856
  * Инициализирует экземпляр класса {@link ScCategory}.
6048
5857
  *
6049
- * @param newsDTO Данные для инициализации.
5858
+ * @param data Данные для инициализации.
6050
5859
  */
6051
- constructor(newsDTO) {
6052
- super(newsDTO);
6053
- this.id = newsDTO.id;
6054
- this.subject = newsDTO.subject;
6055
- this.image = newsDTO.image;
6056
- this.imageWebp = newsDTO.imageWebp;
6057
- this.createdAt = newsDTO.createdAt;
6058
- this.text = newsDTO.text;
5860
+ constructor(data) {
5861
+ super(data);
5862
+ this.subject = data.subject;
5863
+ this.image = data.image;
5864
+ this.imageWebp = data.imageWebp;
5865
+ this.createdAt = data.createdAt;
5866
+ this.text = data.text;
5867
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-assignment,no-underscore-dangle,@typescript-eslint/no-unsafe-member-access
5868
+ this.seo = data._Seo ?? data.seo;
6059
5869
  }
6060
5870
  }
6061
5871
 
6062
- /*
6063
- * Публичное API библиотеки бизнес-логики.
6064
- */
6065
-
6066
5872
  /**
6067
5873
  * Токен, указывающий число записей новостей отображаемых в "Последние новости".
6068
5874
  */
@@ -6131,10 +5937,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
6131
5937
  }]
6132
5938
  }] });
6133
5939
 
6134
- /*
6135
- * Публичное API библиотеки бизнес-логики.
6136
- */
6137
-
6138
5940
  /**
6139
5941
  * Перечисление типов действий для уведомлений.
6140
5942
  */
@@ -7114,64 +6916,460 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
7114
6916
  }] }] });
7115
6917
 
7116
6918
  /**
7117
- * Компонент структурированных данных.
6919
+ * Механизмы генерации схем данных Schema.org.
7118
6920
  */
7119
- class ScJsonLdComponent {
6921
+ class SchemaOrgFactory {
6922
+ constructor() {
6923
+ /**
6924
+ * Данные о компании.
6925
+ */
6926
+ this.companyInfo = inject(SC_COMPANY_INFO);
6927
+ /**
6928
+ * Список ссылок приложения.
6929
+ */
6930
+ this.urls = inject(SC_URLS);
6931
+ /**
6932
+ * Пайп, возвращающий идентификатор или символьное обозначение (slug) исходя из настроек окружения.
6933
+ */
6934
+ this.idOrSlugPipe = inject(ScIdOrSlugPipe);
6935
+ /**
6936
+ * Пайп для формирования полного URI изображения на media сервере.
6937
+ */
6938
+ this.mediaImageTransformerPipe = inject(ScMediaImageTransformerPipe);
6939
+ }
6940
+ /**
6941
+ * Генерирует и возвращает схему данных для указанного продукта.
6942
+ *
6943
+ * @param product Данные о продукте.
6944
+ * @param productPath Url путь к товару. В пути должен присутствовать шаблон ':id', обозначающий идентификатор товара для подстановки.
6945
+ */
6946
+ generateForProductItem(product, productPath) {
6947
+ const productUrl = `${this.urls.siteUrl}${productPath.replace(':id', this.idOrSlugPipe.transform(product).toString())}`;
6948
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
6949
+ const image = this.mediaImageTransformerPipe.transform(product?.getImagePreview() ?? product.image, true);
6950
+ const description = product.properties?.description;
6951
+ const priceValidUntil = this.normalizePriceValidUntil(product.discount?.expiredAt);
6952
+ return {
6953
+ '@context': 'https://schema.org',
6954
+ '@type': 'Product',
6955
+ name: product.name,
6956
+ ...(image && { image }),
6957
+ ...(description && { description }),
6958
+ mpn: product.code,
6959
+ url: productUrl,
6960
+ offers: [
6961
+ {
6962
+ '@type': 'Offer',
6963
+ priceCurrency: 'RUB',
6964
+ ...(priceValidUntil && { priceValidUntil }),
6965
+ price: product.costRub,
6966
+ availability: this.getAvailability(product),
6967
+ itemCondition: 'https://schema.org/NewCondition',
6968
+ seller: {
6969
+ '@type': 'Organization',
6970
+ name: this.companyInfo.name,
6971
+ },
6972
+ url: productUrl,
6973
+ },
6974
+ ],
6975
+ };
6976
+ }
6977
+ /**
6978
+ * Генерирует и возвращает схему данных для указанного продукта.
6979
+ *
6980
+ * @param category Данные о категории.
6981
+ * @param products Данные о продуктах категории.
6982
+ * @param categoryPath Url путь к категориям товаров. В пути должен присутствовать шаблон ':id', обозначающий идентификатор категории для подстановки.
6983
+ * @param productPath Url путь к товару. В пути должен присутствовать шаблон ':id', обозначающий идентификатор товара для подстановки.
6984
+ * @param breadcrumbs Данные о хлебных крошках для категории.
6985
+ */
6986
+ generateForCategoryItem(category, products, categoryPath, productPath, breadcrumbs) {
6987
+ const description = category.seo?.description ?? category.properties?.description;
6988
+ const image = this.mediaImageTransformerPipe.transform(category.image, true);
6989
+ return {
6990
+ '@context': 'https://schema.org',
6991
+ '@type': 'CollectionPage',
6992
+ name: category.seo?.title ?? category.name,
6993
+ ...(description && { description }),
6994
+ url: this.getCategoryCanonicalUrl(category, categoryPath),
6995
+ ...(image && { image }),
6996
+ // SEO данные.
6997
+ ...(category.seo?.keywords && { keywords: category.seo.keywords }),
6998
+ // Основной контент страницы - список товаров и подкатегорий.
6999
+ mainEntity: this.createCategoryMainEntity(category, products, categoryPath, productPath),
7000
+ // Навигационные хлебные крошки (Schema.org: breadcrumb).
7001
+ breadcrumb: breadcrumbs,
7002
+ // Дополнительные метаданные для SEO.
7003
+ about: {
7004
+ '@type': 'CategoryCode',
7005
+ codeValue: category.slug,
7006
+ name: category.name,
7007
+ ...(description && { description }),
7008
+ },
7009
+ // Информация о сайте.
7010
+ isPartOf: {
7011
+ '@type': 'WebSite',
7012
+ name: this.companyInfo.name,
7013
+ url: this.urls.siteUrl,
7014
+ },
7015
+ // Связанные страницы.
7016
+ relatedLink: [
7017
+ `${this.urls.siteUrl}${categoryPath.replace(':id', '')}`,
7018
+ ...(this.isVirtualCategory(category) || !category.parentCategory ? [] : [this.getCategoryCanonicalUrl(category.parentCategory, categoryPath)]),
7019
+ ],
7020
+ // Дополнительные свойства категории (не изображения).
7021
+ additionalProperty: [
7022
+ {
7023
+ '@type': 'PropertyValue',
7024
+ name: 'Количество товаров',
7025
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
7026
+ value: (products?.length ?? 0).toString(),
7027
+ },
7028
+ {
7029
+ '@type': 'PropertyValue',
7030
+ name: 'Slug категории',
7031
+ value: category.slug,
7032
+ },
7033
+ // Добавляем SEO данные если есть.
7034
+ ...(category.seo?.keywords
7035
+ ? [
7036
+ {
7037
+ '@type': 'PropertyValue',
7038
+ name: 'SEO Keywords',
7039
+ value: category.seo.keywords,
7040
+ },
7041
+ ]
7042
+ : []),
7043
+ ...(category.seo?.title
7044
+ ? [
7045
+ {
7046
+ '@type': 'PropertyValue',
7047
+ name: 'SEO Title',
7048
+ value: category.seo.title,
7049
+ },
7050
+ ]
7051
+ : []),
7052
+ ],
7053
+ };
7054
+ }
7055
+ /**
7056
+ * Нормализует дату окончания цены в формат Schema.org (YYYY-MM-DD).
7057
+ *
7058
+ * @param expiredAt Дата для нормализации
7059
+ */
7060
+ // eslint-disable-next-line class-methods-use-this
7061
+ normalizePriceValidUntil(expiredAt) {
7062
+ if (!expiredAt) {
7063
+ return undefined;
7064
+ }
7065
+ const date = expiredAt.slice(0, 10);
7066
+ return /^\d{4}-\d{2}-\d{2}$/.test(date) ? date : undefined;
7067
+ }
7120
7068
  /**
7121
- * Инициализирует экземпляр класса {@link ScJsonLdComponent}.
7069
+ * Определяет доступность товара по данным продукта.
7122
7070
  *
7123
- * @param sanitizer Объект DomSanitizer для безопасной обработки HTML и стилей.
7071
+ * @param product Данные о продукте.
7124
7072
  */
7125
- constructor(sanitizer) {
7126
- this.sanitizer = sanitizer;
7073
+ // eslint-disable-next-line class-methods-use-this
7074
+ getAvailability(product) {
7075
+ if (product.onOrder) {
7076
+ return 'PreOrder';
7077
+ }
7078
+ return product.stockCount?.length ? 'InStock' : 'OutOfStock';
7127
7079
  }
7128
7080
  /**
7129
- * Объект структурированных данных о товаре.
7081
+ * Проверяет, является ли категория виртуальной.
7082
+ *
7083
+ * @param category Данные о категории для проверки.
7130
7084
  */
7131
- set json(currentValue) {
7132
- this.jsonLD = this.getSafeHTML(currentValue);
7085
+ // eslint-disable-next-line class-methods-use-this
7086
+ isVirtualCategory(category) {
7087
+ return 'childCategories' in category && 'productCategories' in category;
7133
7088
  }
7134
7089
  /**
7135
- * Возвращает безопасный html код.
7090
+ * Возвращает URL для указанной категории.
7136
7091
  *
7137
- * @param json JSON данные.
7092
+ * @param category Данные о категории
7093
+ * @param categoryPath Url путь к категориям товаров. В пути должен присутствовать шаблон ':id', обозначающий идентификатор категории для подстановки.
7138
7094
  */
7139
- getSafeHTML(json) {
7140
- // eslint-disable-next-line sonarjs/no-angular-bypass-sanitization
7141
- return this.sanitizer.bypassSecurityTrustHtml(
7142
- // eslint-disable-next-line sonarjs/no-nested-template-literals
7143
- `<script type="application/ld+json">${json ? JSON.stringify(json, null, 2).replaceAll('</script>', String.raw `<\/script>`) : ''}</script>`);
7095
+ getCategoryCanonicalUrl(category, categoryPath) {
7096
+ const id = this.isVirtualCategory(category) ? category.slug : this.idOrSlugPipe.transform(category).toString();
7097
+ const path = categoryPath.replace(':id', id);
7098
+ return `${this.urls.siteUrl}${path}`;
7144
7099
  }
7145
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScJsonLdComponent, deps: [{ token: i1$2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component }); }
7146
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ScJsonLdComponent, selector: "sc-json-ld", inputs: { json: "json" }, host: { properties: { "innerHTML": "this.jsonLD" } }, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7100
+ /**
7101
+ * Создаёт элемент списка ItemList с кратким Product для страницы категории.
7102
+ *
7103
+ * @param product Данные о продукте.
7104
+ * @param position Позиция в списке.
7105
+ * @param productPath Url путь к товару. В пути должен присутствовать шаблон ':id', обозначающий идентификатор товара для подстановки.
7106
+ */
7107
+ createProductsListItem(product, position, productPath) {
7108
+ const productUrl = `${this.urls.siteUrl}${productPath.replace(':id', this.idOrSlugPipe.transform(product).toString())}`;
7109
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
7110
+ const image = this.mediaImageTransformerPipe.transform(product?.getImagePreview?.() ?? product.image, true);
7111
+ const description = product.seo?.description ?? product.properties?.description;
7112
+ const priceValidUntil = this.normalizePriceValidUntil(product.discount?.expiredAt);
7113
+ return {
7114
+ '@type': 'ListItem',
7115
+ position,
7116
+ item: {
7117
+ '@type': 'Product',
7118
+ name: product.name,
7119
+ url: productUrl,
7120
+ ...(image && { image }),
7121
+ ...(description && { description }),
7122
+ offers: [
7123
+ {
7124
+ '@type': 'Offer',
7125
+ priceCurrency: 'RUB',
7126
+ ...(priceValidUntil && { priceValidUntil }),
7127
+ price: product.costRub,
7128
+ availability: this.getAvailability(product),
7129
+ itemCondition: 'https://schema.org/NewCondition',
7130
+ seller: {
7131
+ '@type': 'Organization',
7132
+ name: this.companyInfo.name,
7133
+ },
7134
+ url: productUrl,
7135
+ },
7136
+ ],
7137
+ },
7138
+ };
7139
+ }
7140
+ /**
7141
+ * Создает mainEntity для указанной категории товаров.
7142
+ *
7143
+ * @param category Данные о категории.
7144
+ * @param products Данные о товарах категории.
7145
+ * @param categoryPath Url путь к категориям товаров. В пути должен присутствовать шаблон ':id', обозначающий идентификатор категории для подстановки.
7146
+ * @param productPath Url путь к товару. В пути должен присутствовать шаблон ':id', обозначающий идентификатор товара для подстановки.
7147
+ */
7148
+ createCategoryMainEntity(category, products, categoryPath, productPath) {
7149
+ const childCategories = this.isVirtualCategory(category)
7150
+ ? [...(category.childCategories ?? []), ...(category.productCategories ?? [])]
7151
+ : (category.categories ?? []);
7152
+ return {
7153
+ '@type': 'ItemList',
7154
+ numberOfItems: products.length + childCategories.length,
7155
+ itemListOrder: 'https://schema.org/ItemListUnordered',
7156
+ itemListElement: [
7157
+ // Добавляем подкатегории в начало списка.
7158
+ ...childCategories.slice(0, 5).map((subCategory, index) => ({
7159
+ '@type': 'ListItem',
7160
+ position: index + 1,
7161
+ name: subCategory.name,
7162
+ url: this.getCategoryCanonicalUrl(subCategory, categoryPath),
7163
+ image: this.mediaImageTransformerPipe.transform(subCategory.image, true),
7164
+ description: subCategory.seo?.description ?? subCategory.properties?.description,
7165
+ })),
7166
+ // Добавляем товары после подкатегорий.
7167
+ ...products.slice(0, 10).map((product, index) => this.createProductsListItem(product, childCategories.length + index + 1, productPath)),
7168
+ ],
7169
+ };
7170
+ }
7171
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SchemaOrgFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
7172
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SchemaOrgFactory, providedIn: 'root' }); }
7147
7173
  }
7148
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScJsonLdComponent, decorators: [{
7149
- type: Component,
7174
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SchemaOrgFactory, decorators: [{
7175
+ type: Injectable,
7150
7176
  args: [{
7151
- selector: 'sc-json-ld',
7152
- template: '',
7153
- changeDetection: ChangeDetectionStrategy.OnPush,
7177
+ providedIn: 'root',
7154
7178
  }]
7155
- }], ctorParameters: () => [{ type: i1$2.DomSanitizer }], propDecorators: { jsonLD: [{
7156
- type: HostBinding,
7157
- args: ['innerHTML']
7158
- }], json: [{
7159
- type: Input
7160
- }] } });
7179
+ }] });
7161
7180
 
7162
7181
  /**
7163
- * Модуль структурированных данных.
7182
+ * Сервис управления SEO-параметрами.
7164
7183
  */
7165
- class ScJsonLdModule {
7166
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScJsonLdModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
7167
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.14", ngImport: i0, type: ScJsonLdModule, declarations: [ScJsonLdComponent], exports: [ScJsonLdComponent] }); }
7168
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScJsonLdModule }); }
7184
+ class ScSeoService {
7185
+ constructor() {
7186
+ /**
7187
+ * Данные о компании.
7188
+ */
7189
+ this.companyInfo = inject(SC_COMPANY_INFO);
7190
+ /**
7191
+ * Метаданные по умолчанию.
7192
+ */
7193
+ this.defaultSeo = inject(SC_DEFAULT_PAGE_META);
7194
+ /**
7195
+ * Метаданные страницы каталога по умолчанию.
7196
+ */
7197
+ this.catalogDefaultSeo = inject(SC_CATALOG_PAGE_META);
7198
+ /**
7199
+ * Признак необходимости использовать Id или Slug при маршрутизации.
7200
+ */
7201
+ this.idOrSlugInRoute = inject(SC_ID_OR_SLUG_IN_ROUTE);
7202
+ /**
7203
+ * Список ссылок приложения.
7204
+ */
7205
+ this.urls = inject(SC_URLS);
7206
+ /**
7207
+ * Пайп, возвращающий идентификатор или символьное обозначение (slug) исходя из настроек окружения.
7208
+ */
7209
+ this.idOrSlugPipe = inject(ScIdOrSlugPipe);
7210
+ /**
7211
+ * Пайп для формирования полного URI изображения на media сервере.
7212
+ */
7213
+ this.mediaImageTransformerPipe = inject(ScMediaImageTransformerPipe);
7214
+ /**
7215
+ * Сервис установки метаданных страницы.
7216
+ */
7217
+ this.metaService = inject(Meta);
7218
+ /**
7219
+ * Сервис маршрутизации.
7220
+ */
7221
+ this.router = inject(Router);
7222
+ /**
7223
+ * Сервис управления заголовком страницы.
7224
+ */
7225
+ this.titleService = inject(Title);
7226
+ /**
7227
+ * Объект {@link Document}, предоставляющий доступ к DOM страницы.
7228
+ */
7229
+ this.document = inject(DOCUMENT);
7230
+ /**
7231
+ * Фабрика для создания экземпляров {@link Renderer2}.
7232
+ */
7233
+ this.rendererFactory = inject(RendererFactory2);
7234
+ /**
7235
+ * Экземпляр {@link Renderer2} для безопасной работы с DOM.
7236
+ */
7237
+ this.renderer = this.rendererFactory.createRenderer(null, null);
7238
+ }
7239
+ /**
7240
+ * Устанавливает seo параметры на основе указанного ресурса. Если какого-то тега нет, будет установлено значение по умолчанию.
7241
+ *
7242
+ * @param resource Ресурс на основе которого необходимо установить мета-теги.
7243
+ * @param img Изображение. Если не пришло, то будет установлено значение по умолчанию.
7244
+ * @param robots Список robots-тегов для страницы.
7245
+ */
7246
+ setFromResource(resource, img = this.urls.logoUrl, robots = ['index', 'follow']) {
7247
+ const updatedResource = {
7248
+ title: resource?.title ?? this.defaultSeo.title,
7249
+ description: resource?.description ?? this.defaultSeo.description,
7250
+ keywords: resource?.keywords ?? this.defaultSeo.keywords,
7251
+ meta: resource?.meta ?? [],
7252
+ };
7253
+ const url = `${this.urls.siteUrl}${this.router.url}`;
7254
+ this.setMetaTags(updatedResource.title, updatedResource.description, updatedResource.keywords, updatedResource.meta, robots);
7255
+ this.setOpenGraphMetaTags(updatedResource.title, updatedResource.description, url, img);
7256
+ }
7257
+ /**
7258
+ * Устанавливает seo параметры со значением по умолчанию.
7259
+ *
7260
+ * @param title Заголовок страницы.
7261
+ * @param robots Список robots тегов для страницы.
7262
+ */
7263
+ setByDefault(title, robots = ['index', 'follow']) {
7264
+ this.setFromResource({
7265
+ title: `${title ?? this.defaultSeo.title} - ${this.companyInfo.name}`,
7266
+ description: `${title}, ${this.defaultSeo.description}`,
7267
+ }, this.urls.logoUrl, robots);
7268
+ }
7269
+ /**
7270
+ * Устанавливает seo параметры со значением по умолчанию. Устанавливает значение "не индексировать" для поисковых роботов.
7271
+ *
7272
+ * @param title Заголовок страницы.
7273
+ */
7274
+ setByDefaultAsNoIndexed(title) {
7275
+ this.setByDefault(title, ['noindex', 'nofollow', 'noarchive']);
7276
+ }
7277
+ /**
7278
+ * Устанавливает seo-параметры для указанного элемента каталога.
7279
+ *
7280
+ * @param item Данные об элементе каталога.
7281
+ * @param urlPath Url путь к элементу каталога. В пути должен присутствовать шаблон ':id', обозначающий идентификатор элемента каталога для подстановки.
7282
+ * @param schemaOrgData Данные Schema.org элемента каталога
7283
+ */
7284
+ setForCategoryItem(item, urlPath, schemaOrgData) {
7285
+ const url = `${this.urls.siteUrl}${urlPath.replace(':id', this.idOrSlugPipe.transform(item).toString())}`;
7286
+ const title = item.seo?.title ?? `${item.name} - Купить в ${this.companyInfo.name}`;
7287
+ const description = item.seo?.description ?? `${item.name} - Купить по выгодным ценам в ${this.companyInfo.name}`;
7288
+ const keywords = item.seo?.keywords ?? `${item.name}, ${this.catalogDefaultSeo.keywords}`;
7289
+ const meta = item.seo?.meta ?? [];
7290
+ // Устанавливаем стандартные seo-параметры.
7291
+ this.setMetaTags(title, description, keywords, meta, ['index', 'follow']);
7292
+ this.setOpenGraphMetaTags(title, description, url, this.mediaImageTransformerPipe.transform(item.image, true));
7293
+ // В том случае, если используется slug для формирования ссылок, то необходимо сформировать кононическую
7294
+ // ссылку на страницу в которой используется slug (а не id).
7295
+ if (this.idOrSlugInRoute === 'slug' && item.id && item.slug) {
7296
+ this.setCanonicalLink(url);
7297
+ }
7298
+ // Устанавливаем Schema.org параметры.
7299
+ if (schemaOrgData) {
7300
+ this.setSchemaOrgData(schemaOrgData);
7301
+ }
7302
+ }
7303
+ /**
7304
+ * Устанавливает все meta-теги страницы. Если какой-либо из параметров не указан, для него устанавливается значение по умолчанию.
7305
+ *
7306
+ * @param title Заголовок страницы.
7307
+ * @param description Описание страницы.
7308
+ * @param keywords Ключевые слова страницы.
7309
+ * @param meta Массив дополнительных значений метатегов.
7310
+ * @param robots Список robots тегов для страницы.
7311
+ */
7312
+ setMetaTags(title = this.defaultSeo.title, description = this.defaultSeo.description, keywords = this.defaultSeo.keywords, meta = [], robots = ['index', 'follow']) {
7313
+ this.titleService.setTitle(title);
7314
+ this.metaService.updateTag({ name: 'description', content: description });
7315
+ this.metaService.updateTag({ name: 'keywords', content: keywords });
7316
+ this.metaService.updateTag({ name: 'robots', content: robots.join(', ') });
7317
+ meta.forEach((tag) => {
7318
+ this.metaService.updateTag({ name: tag.name, content: tag.content });
7319
+ });
7320
+ }
7321
+ /**
7322
+ * Устанавливает Open Graph meta-теги.
7323
+ *
7324
+ * @param ogTitle Заголовок.
7325
+ * @param ogDescription Описание.
7326
+ * @param ogUrl Url.
7327
+ * @param ogImg Ссылка на изображение.
7328
+ */
7329
+ setOpenGraphMetaTags(ogTitle, ogDescription, ogUrl, ogImg) {
7330
+ this.metaService.updateTag({ property: 'og:type', content: 'website' });
7331
+ this.metaService.updateTag({ property: 'og:title', content: ogTitle });
7332
+ this.metaService.updateTag({ property: 'og:description', content: ogDescription });
7333
+ this.metaService.updateTag({ property: 'og:url', content: ogUrl });
7334
+ this.metaService.updateTag({ property: 'og:image', content: ogImg });
7335
+ }
7336
+ /**
7337
+ * Устанавливает тег канонической страницы <link rel="canonical" href="..." />.
7338
+ *
7339
+ * @param url URL который необходимо использовать в качестве ссылки.
7340
+ */
7341
+ setCanonicalLink(url) {
7342
+ // Удаляем существующий link canonical.
7343
+ const existingLink = this.document.querySelector('link[rel="canonical"]');
7344
+ if (existingLink?.parentNode) {
7345
+ this.renderer.removeChild(existingLink.parentNode, existingLink);
7346
+ }
7347
+ // Создаём и устанавливаем новый тег.
7348
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
7349
+ const link = this.renderer.createElement('link');
7350
+ this.renderer.setAttribute(link, 'rel', 'canonical');
7351
+ this.renderer.setAttribute(link, 'href', url);
7352
+ this.renderer.appendChild(this.document.head, link);
7353
+ }
7354
+ /**
7355
+ * Устанавливает Schema.org объект страницы.
7356
+ *
7357
+ * @param data Данные Schema.org для встраивания на странице.
7358
+ */
7359
+ setSchemaOrgData(data) {
7360
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
7361
+ const script = this.renderer.createElement('script');
7362
+ this.renderer.setAttribute(script, 'type', 'application/ld+json');
7363
+ this.renderer.appendChild(script, this.document.createTextNode(JSON.stringify(data)));
7364
+ this.renderer.appendChild(this.document.head, script);
7365
+ }
7366
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScSeoService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
7367
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScSeoService, providedIn: 'root' }); }
7169
7368
  }
7170
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScJsonLdModule, decorators: [{
7171
- type: NgModule,
7369
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScSeoService, decorators: [{
7370
+ type: Injectable,
7172
7371
  args: [{
7173
- declarations: [ScJsonLdComponent],
7174
- exports: [ScJsonLdComponent],
7372
+ providedIn: 'root',
7175
7373
  }]
7176
7374
  }] });
7177
7375
 
@@ -7550,13 +7748,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
7550
7748
  args: [SC_URLS]
7551
7749
  }] }] });
7552
7750
 
7553
- /*
7554
- * Публичное API библиотеки бизнес-логики.
7555
- */
7556
-
7557
7751
  /**
7558
7752
  * Generated bundle index. Do not edit.
7559
7753
  */
7560
7754
 
7561
- export { CATEGORY_INFO, CATEGORY_PROVIDERS, EMPTY_CART, ERROR_HANDLER, IS_BROWSER, IS_RUNNING_ON_TERMINAL, IS_SERVER, RESPONSE, SC_ACCESS_AUTH_TOKEN_STORAGE_KEY, SC_API_KEYS, SC_AUTH_ADD_HEADER_REQUIRED, SC_AUTH_AS_CLIENT_DEFAULT_OPTIONS, SC_AUTH_AS_CLIENT_OPTIONS, SC_CACHE_LIFETIME, SC_CACHE_SETTINGS, SC_CATALOG_PAGE_META, SC_COMPANY_INFO, SC_COMPANY_NAME, SC_CONFIGURATOR_COMPONENTS, SC_CONFIGURATOR_SETTINGS, SC_COUNT_FIRST_DISCOUNTED_PRODUCTS, SC_COUNT_LAST_NEWS, SC_DATE_FORMAT, SC_DEFAULT_PAGE_META, SC_FEEDBACK_API, SC_GUEST_ENDPOINTS_TOKEN, SC_GUEST_PARAMETER_NAME_TOKEN, SC_GUEST_TOKEN_STORAGE_KEY, SC_ID_OR_SLUG_IN_ROUTE, SC_IS_HEADER_REQUIRED, SC_IS_HIDDEN_ERROR_ALERT, SC_IS_HIDDEN_ERROR_ALERT_HTTP_CONTEXT, SC_IS_LOGOUT_REQUEST, SC_IS_REFRESH_REQUIRED, SC_LINEAR_VALUES, SC_LINEAR_VALUES_TOKEN, SC_MAX_LENGTH_SEARCH_TERM, SC_MIN_LENGTH_SEARCH_TERM, SC_NEXT_PAGE_PAGINATION_CLICK, SC_PATH_IMAGE_NOT_FOUND, SC_PRODUCT_PAGINATION_DEFAULT_OPTIONS, SC_PRODUCT_PAGINATION_OPTIONS, SC_REFRESH_AUTH_TOKEN_STORAGE_KEY, SC_RELEASE, SC_UPDATE_INTERVAL, SC_URLS, SC_USER_INFO, SC_VACANCIES_DATA_SOURCE, SC_VIRTUAL_CATEGORY_INFO, SC_VIRTUAL_CATEGORY_PROVIDERS, SEARCH_TERM, SEARCH_TERM_PROVIDERS, ScAuthAsClientGuard, ScAuthInterceptor, ScAuthService, ScBanner, ScBannerService, ScCacheInterceptor, ScCacheSettings, ScCachedData, ScCachedItem, ScCart, ScCartItem, ScCartService, ScCatalogFilterService, ScCatalogFormat, ScCatalogService, ScCategory, ScCategorySeoGuard, ScClientType, ScConfiguratorService, ScContactsService, ScContragentService, ScConvertInterceptor, ScConvertersService, ScDateFormatInterceptor, ScDeliveryAddressService, ScDeliveryCost, ScDeliveryType, ScDocumentInfoNode, ScDocumentInfoTypesEnum, ScErrorsInterceptor, ScFavoriteService, ScFeedbackForms, ScFeedbackService, ScFilesService, ScFrequentlyAskedQuestionsService, ScGuestInterceptor, ScISalesDirectionCart, ScISuggestionType, ScIconTypesEnum, ScIdOrSlugGuard, ScIdOrSlugPipe, ScImage, ScImageHelper, ScJsonLdComponent, ScJsonLdModule, ScLocationsService, ScMediaImageTransformerPipe, ScMimeTypes, ScNews, ScNewsService, ScNotificationActionTypes, ScNotificationLevelNames, ScNotificationsService, ScOpfList, ScOptionsInterceptor, ScOrder, ScOrderShort, ScOrderStateStatus, ScOrdersService, ScPaginationService, ScPaymentStatus, ScPaymentType, ScPhoneService, ScProduct, ScProductSeoGuard, ScProductTileType, ScQuestionnaireService, ScQuestionnaireStatusEnum, ScReclamationService, ScReclamationStatus, ScRecommendationService, ScReferenceName, ScReferencesService, ScRequisitesService, ScRouteKeys, ScSearchService, ScSeoResource, ScSeoService, ScSocialType, ScSuggestionService, ScSum, ScTokenService, ScUIService, ScUTMService, ScUnitsHelper, ScUploadedFile, ScUser, ScUserMetadata, ScUserMetrikaGoalsEnum, ScUserMetrikaService, ScUserService, ScUserType, ScVCardService, ScVacanciesList, ScVacanciesService, ScVacancy, ScVerificationService, ScVirtualCategory, ScVirtualCategorySeoGuard, ScWarehouseService, TERMINAL_PROVIDERS, USER_AGENT_TERMINAL, filterChangedByKey, runningOnTerminalFactory, searchTermFactory };
7755
+ export { CATEGORY_INFO, CATEGORY_PROVIDERS, EMPTY_CART, ERROR_HANDLER, IS_BROWSER, IS_RUNNING_ON_TERMINAL, IS_SERVER, RESPONSE, SC_ACCESS_AUTH_TOKEN_STORAGE_KEY, SC_API_KEYS, SC_AUTH_ADD_HEADER_REQUIRED, SC_AUTH_AS_CLIENT_DEFAULT_OPTIONS, SC_AUTH_AS_CLIENT_OPTIONS, SC_CACHE_LIFETIME, SC_CACHE_SETTINGS, SC_CATALOG_PAGE_META, SC_COMPANY_INFO, SC_COMPANY_NAME, SC_CONFIGURATOR_COMPONENTS, SC_CONFIGURATOR_SETTINGS, SC_COUNT_FIRST_DISCOUNTED_PRODUCTS, SC_COUNT_LAST_NEWS, SC_DATE_FORMAT, SC_DEFAULT_PAGE_META, SC_FEEDBACK_API, SC_GUEST_ENDPOINTS_TOKEN, SC_GUEST_PARAMETER_NAME_TOKEN, SC_GUEST_TOKEN_STORAGE_KEY, SC_ID_OR_SLUG_IN_ROUTE, SC_IS_HEADER_REQUIRED, SC_IS_HIDDEN_ERROR_ALERT, SC_IS_HIDDEN_ERROR_ALERT_HTTP_CONTEXT, SC_IS_LOGOUT_REQUEST, SC_IS_REFRESH_REQUIRED, SC_LINEAR_VALUES, SC_LINEAR_VALUES_TOKEN, SC_MAX_LENGTH_SEARCH_TERM, SC_MIN_LENGTH_SEARCH_TERM, SC_NEXT_PAGE_PAGINATION_CLICK, SC_PATH_IMAGE_NOT_FOUND, SC_PRODUCT_PAGINATION_DEFAULT_OPTIONS, SC_PRODUCT_PAGINATION_OPTIONS, SC_REFRESH_AUTH_TOKEN_STORAGE_KEY, SC_RELEASE, SC_UPDATE_INTERVAL, SC_URLS, SC_USER_INFO, SC_VACANCIES_DATA_SOURCE, SC_VIRTUAL_CATEGORY_INFO, SC_VIRTUAL_CATEGORY_PROVIDERS, SEARCH_TERM, SEARCH_TERM_PROVIDERS, ScAuthAsClientGuard, ScAuthInterceptor, ScAuthService, ScBanner, ScBannerService, ScCacheInterceptor, ScCacheSettings, ScCachedData, ScCachedItem, ScCart, ScCartItem, ScCartService, ScCatalogFilterService, ScCatalogFormat, ScCatalogItem, ScCatalogService, ScCatalogableItem, ScCategory, ScClientType, ScCodedIdentity, ScConfiguratorService, ScContactsService, ScContragentService, ScConvertInterceptor, ScConvertersService, ScDateFormatInterceptor, ScDeletableNamedIdentity, ScDeliveryAddressService, ScDeliveryCost, ScDeliveryType, ScDocumentInfoNode, ScDocumentInfoTypesEnum, ScErrorsInterceptor, ScFavoriteService, ScFeedbackForms, ScFeedbackService, ScFilesService, ScFrequentlyAskedQuestionsService, ScGuestInterceptor, ScHiddenCatalogableItem, ScISalesDirectionCart, ScISuggestionType, ScIconTypesEnum, ScIdOrSlugGuard, ScIdOrSlugPipe, ScIdentity, ScImage, ScImageHelper, ScLocationsService, ScMediaImageTransformerPipe, ScMimeTypes, ScNamedIdentity, ScNews, ScNewsService, ScNotificationActionTypes, ScNotificationLevelNames, ScNotificationsService, ScOpfList, ScOptionsInterceptor, ScOrder, ScOrderShort, ScOrderStateStatus, ScOrdersService, ScPaginationService, ScPaymentStatus, ScPaymentType, ScPhoneService, ScPrimaryCatalogableItem, ScProduct, ScProductTileType, ScQuestionnaireService, ScQuestionnaireStatusEnum, ScReclamationService, ScReclamationStatus, ScRecommendationService, ScReference, ScReferenceName, ScReferencesService, ScRequisitesService, ScRouteKeys, ScSearchService, ScSeoService, ScSocialType, ScSuggestionService, ScSum, ScTokenService, ScUIService, ScUTMService, ScUnitsHelper, ScUpdatableNamedIdentity, ScUploadedFile, ScUser, ScUserMetadata, ScUserMetrikaGoalsEnum, ScUserMetrikaService, ScUserService, ScUserType, ScVCardService, ScVacanciesList, ScVacanciesService, ScVacancy, ScVerificationService, ScVirtualCategory, ScWarehouseService, SchemaOrgFactory, TERMINAL_PROVIDERS, USER_AGENT_TERMINAL, filterChangedByKey, runningOnTerminalFactory, searchTermFactory };
7562
7756
  //# sourceMappingURL=snabcentr-client-core.mjs.map