@snabcentr/client-core 3.5.4 → 3.7.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/catalog/services/sc-catalog-filter.service.d.ts +13 -1
- package/catalog/services/sc-catalog.service.d.ts +8 -0
- package/catalog/services/sc-recommendation.service.d.ts +16 -0
- package/esm2022/catalog/services/sc-catalog-filter.service.mjs +38 -9
- package/esm2022/catalog/services/sc-catalog.service.mjs +26 -10
- package/esm2022/catalog/services/sc-favorite.service.mjs +2 -2
- package/esm2022/catalog/services/sc-recommendation.service.mjs +44 -5
- package/esm2022/helpers/sc-units-helper.mjs +17 -36
- package/esm2022/notifications/services/sc-notifications.service.mjs +8 -3
- package/fesm2022/snabcentr-client-core.mjs +121 -52
- package/fesm2022/snabcentr-client-core.mjs.map +1 -1
- package/helpers/sc-units-helper.d.ts +10 -20
- package/notifications/services/sc-notifications.service.d.ts +4 -0
- package/package.json +1 -1
- package/release_notes.tmp +2 -4
|
@@ -3123,6 +3123,24 @@ class ScCatalogFilterService {
|
|
|
3123
3123
|
* HTTP клиент для выполнения запросов.
|
|
3124
3124
|
*/
|
|
3125
3125
|
this.http = inject(HttpClient);
|
|
3126
|
+
/**
|
|
3127
|
+
* Время жизни кэша фильтров.
|
|
3128
|
+
*/
|
|
3129
|
+
this.cacheLifeTime = inject(SC_CACHE_LIFETIME);
|
|
3130
|
+
/**
|
|
3131
|
+
* Кэш фильтров по ключу `categoryIdOrSlug:recursively`.
|
|
3132
|
+
*/
|
|
3133
|
+
this.filterMap = new Map();
|
|
3134
|
+
}
|
|
3135
|
+
/**
|
|
3136
|
+
* Удаляет просроченные записи кэша, чтобы карта не удерживала фильтры неиспользуемых категорий.
|
|
3137
|
+
*/
|
|
3138
|
+
deleteExpiredCacheItems() {
|
|
3139
|
+
this.filterMap.forEach((cachedItem, key) => {
|
|
3140
|
+
if (!cachedItem.cachedDataIsActual()) {
|
|
3141
|
+
this.filterMap.delete(key);
|
|
3142
|
+
}
|
|
3143
|
+
});
|
|
3126
3144
|
}
|
|
3127
3145
|
/**
|
|
3128
3146
|
* Возвращает список доступных фильтров продуктов в категории.
|
|
@@ -3131,14 +3149,24 @@ class ScCatalogFilterService {
|
|
|
3131
3149
|
* @param recursively Признак того, что необходимо вернуть фильтры с учетом вложенных категорий.
|
|
3132
3150
|
*/
|
|
3133
3151
|
getFilters$(categoryIdOrSlug, recursively) {
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3152
|
+
const key = `${categoryIdOrSlug}:${recursively ?? ''}`;
|
|
3153
|
+
this.deleteExpiredCacheItems();
|
|
3154
|
+
let cachedItem = this.filterMap.get(key);
|
|
3155
|
+
if (!cachedItem) {
|
|
3156
|
+
let params = new HttpParams();
|
|
3157
|
+
if (recursively !== undefined) {
|
|
3158
|
+
params = params.set('recursively', String(recursively));
|
|
3159
|
+
}
|
|
3160
|
+
cachedItem = new ScCachedItem(this.cacheLifeTime.categoryData, this.http.get(`${this.urls.apiUrl}/catalog/categories/${categoryIdOrSlug}/filters`, {
|
|
3161
|
+
params,
|
|
3162
|
+
context: SC_IS_HIDDEN_ERROR_ALERT_HTTP_CONTEXT,
|
|
3163
|
+
}));
|
|
3164
|
+
this.filterMap.set(key, cachedItem);
|
|
3137
3165
|
}
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3166
|
+
if (!cachedItem.cachedDataIsActual()) {
|
|
3167
|
+
cachedItem.update();
|
|
3168
|
+
}
|
|
3169
|
+
return cachedItem.item$;
|
|
3142
3170
|
}
|
|
3143
3171
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScCatalogFilterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3144
3172
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScCatalogFilterService, providedIn: 'root' }); }
|
|
@@ -3256,10 +3284,14 @@ class ScCatalogService {
|
|
|
3256
3284
|
* Сервис информации о пользователе.
|
|
3257
3285
|
*/
|
|
3258
3286
|
this.userService = inject(ScUserService);
|
|
3287
|
+
/**
|
|
3288
|
+
* Ссылка на жизненный цикл сервиса.
|
|
3289
|
+
*/
|
|
3290
|
+
this.destroyRef = inject(DestroyRef);
|
|
3259
3291
|
/**
|
|
3260
3292
|
* {@link Observable} изменения списка товаров со скидкой.
|
|
3261
3293
|
*/
|
|
3262
|
-
this.firstDiscounted$ = inject(SC_USER_INFO).pipe(switchMap((user) => user.isGuest ? of(null) : this.getProducts$({ filters: { onlyDiscounted: true }, paginate: true, page: 1, perPage: this.countFirstDiscountedProducts })), shareReplay(1));
|
|
3294
|
+
this.firstDiscounted$ = inject(SC_USER_INFO).pipe(switchMap((user) => user.isGuest ? of(null) : this.getProducts$({ filters: { onlyDiscounted: true }, paginate: true, page: 1, perPage: this.countFirstDiscountedProducts })), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
3263
3295
|
/**
|
|
3264
3296
|
* {@link Observable} изменения списка из первых товаров со скидкой.
|
|
3265
3297
|
*/
|
|
@@ -3270,16 +3302,24 @@ class ScCatalogService {
|
|
|
3270
3302
|
this.countDiscountedProducts$ = this.firstDiscounted$.pipe(map$1((data) => data?.meta.total ?? 0));
|
|
3271
3303
|
this.userService
|
|
3272
3304
|
.getUserChange$()
|
|
3273
|
-
.pipe(skip(1))
|
|
3305
|
+
.pipe(skip(1), takeUntilDestroyed(this.destroyRef))
|
|
3274
3306
|
.subscribe(() => {
|
|
3275
|
-
this.
|
|
3276
|
-
this.categoryMap.clear();
|
|
3277
|
-
this.productHistoryMap.clear();
|
|
3278
|
-
this.productMap.clear();
|
|
3279
|
-
this.categoryProductsMap.clear();
|
|
3280
|
-
this.virtualCategoryMap.clear();
|
|
3307
|
+
this.clearCache();
|
|
3281
3308
|
});
|
|
3282
3309
|
}
|
|
3310
|
+
/**
|
|
3311
|
+
* Очищает данные каталога, привязанные к текущему пользователю.
|
|
3312
|
+
*/
|
|
3313
|
+
clearCache() {
|
|
3314
|
+
this.idCategoryMap.clear();
|
|
3315
|
+
this.categoryMap.clear();
|
|
3316
|
+
this.productHistoryMap.clear();
|
|
3317
|
+
this.productMap.clear();
|
|
3318
|
+
this.categoryProductsMap.clear();
|
|
3319
|
+
this.virtualCategoryMap.clear();
|
|
3320
|
+
this.categoryIdOrSlugMap.clear();
|
|
3321
|
+
this.productIdOrSlugMap.clear();
|
|
3322
|
+
}
|
|
3283
3323
|
/**
|
|
3284
3324
|
* Возвращает категорию из коллекции каталога, если её срок жизни не истёк.
|
|
3285
3325
|
*
|
|
@@ -3390,6 +3430,9 @@ class ScCatalogService {
|
|
|
3390
3430
|
.pipe(catchError$1(() => of({}))), null);
|
|
3391
3431
|
this.productHistoryMap.set(product.id.toString(), cachedItem);
|
|
3392
3432
|
}
|
|
3433
|
+
if (!cachedItem.cachedDataIsActual()) {
|
|
3434
|
+
cachedItem.update();
|
|
3435
|
+
}
|
|
3393
3436
|
return cachedItem.item$;
|
|
3394
3437
|
}
|
|
3395
3438
|
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
|
|
@@ -3533,7 +3576,7 @@ class ScFavoriteService {
|
|
|
3533
3576
|
/**
|
|
3534
3577
|
* {@link Observable} списка избранных категорий.
|
|
3535
3578
|
*/
|
|
3536
|
-
this.categories$ = this.categoriesUpdateSubject.pipe(switchMap(() => this.user$), switchMap((user) => (user.isGuest ? of([]) : this.getFavoriteCategories$())), shareReplay(1) // Подогреваем запрос во избежание повторения запросов получения списка избранных категорий для новых подписчиков.
|
|
3579
|
+
this.categories$ = this.categoriesUpdateSubject.pipe(switchMap(() => this.user$), switchMap((user) => (user.isGuest ? of([]) : this.getFavoriteCategories$())), shareReplay({ refCount: true, bufferSize: 1 }) // Подогреваем запрос во избежание повторения запросов получения списка избранных категорий для новых подписчиков.
|
|
3537
3580
|
);
|
|
3538
3581
|
}
|
|
3539
3582
|
/**
|
|
@@ -3624,11 +3667,41 @@ class ScRecommendationService {
|
|
|
3624
3667
|
* Сервис для работы с корзиной.
|
|
3625
3668
|
*/
|
|
3626
3669
|
this.cartService = inject(ScCartService);
|
|
3670
|
+
/**
|
|
3671
|
+
* Ссылка на жизненный цикл сервиса.
|
|
3672
|
+
*/
|
|
3673
|
+
this.destroyRef = inject(DestroyRef);
|
|
3627
3674
|
inject(SC_USER_INFO)
|
|
3628
|
-
.pipe(skip(1))
|
|
3675
|
+
.pipe(skip(1), takeUntilDestroyed(this.destroyRef))
|
|
3629
3676
|
.subscribe(() => {
|
|
3630
|
-
this.
|
|
3631
|
-
|
|
3677
|
+
this.clearCache();
|
|
3678
|
+
});
|
|
3679
|
+
}
|
|
3680
|
+
/**
|
|
3681
|
+
* Очищает кэшированные рекомендации.
|
|
3682
|
+
*/
|
|
3683
|
+
clearCache() {
|
|
3684
|
+
this.productsByCategoryMap.clear();
|
|
3685
|
+
this.productsByProductMap.clear();
|
|
3686
|
+
}
|
|
3687
|
+
/**
|
|
3688
|
+
* Удаляет просроченные записи кэша, чтобы карты не росли бесконечно при смене ключей.
|
|
3689
|
+
*/
|
|
3690
|
+
deleteExpiredCategoryCacheItems() {
|
|
3691
|
+
this.productsByCategoryMap.forEach((cachedItem, key) => {
|
|
3692
|
+
if (!cachedItem.cachedDataIsActual()) {
|
|
3693
|
+
this.productsByCategoryMap.delete(key);
|
|
3694
|
+
}
|
|
3695
|
+
});
|
|
3696
|
+
}
|
|
3697
|
+
/**
|
|
3698
|
+
* Удаляет просроченные записи кэша товаров, чтобы карты не росли бесконечно при смене ключей.
|
|
3699
|
+
*/
|
|
3700
|
+
deleteExpiredProductCacheItems() {
|
|
3701
|
+
this.productsByProductMap.forEach((cachedItem, key) => {
|
|
3702
|
+
if (!cachedItem.cachedDataIsActual()) {
|
|
3703
|
+
this.productsByProductMap.delete(key);
|
|
3704
|
+
}
|
|
3632
3705
|
});
|
|
3633
3706
|
}
|
|
3634
3707
|
/**
|
|
@@ -3637,6 +3710,7 @@ class ScRecommendationService {
|
|
|
3637
3710
|
* @param categoryIdOrSlug Идентификатор или slug категории товаров.
|
|
3638
3711
|
*/
|
|
3639
3712
|
getProductsByCategory$(categoryIdOrSlug) {
|
|
3713
|
+
this.deleteExpiredCategoryCacheItems();
|
|
3640
3714
|
let cachedItem = this.productsByCategoryMap.get(categoryIdOrSlug.toString());
|
|
3641
3715
|
if (!cachedItem) {
|
|
3642
3716
|
// Устанавливаем время жизни cachedItem равное, потому что нам не важно время жизни. Нам нужен функционал update().
|
|
@@ -3648,6 +3722,9 @@ class ScRecommendationService {
|
|
|
3648
3722
|
.pipe(startWith$1(null)), null);
|
|
3649
3723
|
this.productsByCategoryMap.set(categoryIdOrSlug.toString(), cachedItem);
|
|
3650
3724
|
}
|
|
3725
|
+
if (!cachedItem.cachedDataIsActual()) {
|
|
3726
|
+
cachedItem.update();
|
|
3727
|
+
}
|
|
3651
3728
|
return cachedItem.item$;
|
|
3652
3729
|
}
|
|
3653
3730
|
/**
|
|
@@ -3656,6 +3733,7 @@ class ScRecommendationService {
|
|
|
3656
3733
|
* @param productIdOrSlug Идентификатор или slug товара/услуги.
|
|
3657
3734
|
*/
|
|
3658
3735
|
getProductsByProduct$(productIdOrSlug) {
|
|
3736
|
+
this.deleteExpiredProductCacheItems();
|
|
3659
3737
|
let cachedItem = this.productsByProductMap.get(productIdOrSlug.toString());
|
|
3660
3738
|
if (!cachedItem) {
|
|
3661
3739
|
// Устанавливаем время жизни cachedItem равное, потому что нам не важно время жизни. Нам нужен функционал update().
|
|
@@ -3667,6 +3745,9 @@ class ScRecommendationService {
|
|
|
3667
3745
|
.pipe(startWith$1(null)), null);
|
|
3668
3746
|
this.productsByProductMap.set(productIdOrSlug.toString(), cachedItem);
|
|
3669
3747
|
}
|
|
3748
|
+
if (!cachedItem.cachedDataIsActual()) {
|
|
3749
|
+
cachedItem.update();
|
|
3750
|
+
}
|
|
3670
3751
|
return cachedItem.item$;
|
|
3671
3752
|
}
|
|
3672
3753
|
/**
|
|
@@ -4269,53 +4350,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
4269
4350
|
}] });
|
|
4270
4351
|
|
|
4271
4352
|
/**
|
|
4272
|
-
*
|
|
4353
|
+
* Класс-помощник для работы со значениями единиц измерения товара.
|
|
4273
4354
|
*/
|
|
4274
4355
|
class ScUnitsHelper {
|
|
4275
4356
|
/**
|
|
4276
|
-
*
|
|
4277
|
-
*
|
|
4278
|
-
* @param linearValues Единицы измерения линейной величины.
|
|
4279
|
-
*/
|
|
4280
|
-
constructor(linearValues) {
|
|
4281
|
-
this.linearValues = linearValues;
|
|
4282
|
-
}
|
|
4283
|
-
/**
|
|
4284
|
-
* Возвращает признак возможности продажи товара на метраж.
|
|
4357
|
+
* Возвращает признак, что указанный товар имеет линейную единицу измерения.
|
|
4285
4358
|
*
|
|
4286
|
-
* @param product
|
|
4359
|
+
* @param product Данные о товаре для которого нужно проверить линейность его единицы измерения.
|
|
4287
4360
|
*/
|
|
4288
|
-
productIsMeasurable(product) {
|
|
4289
|
-
return
|
|
4361
|
+
static productIsMeasurable(product) {
|
|
4362
|
+
return product.unit.isLinear || product.unit.isSquare;
|
|
4290
4363
|
}
|
|
4291
4364
|
/**
|
|
4292
|
-
* Возвращает кратность количества для товара.
|
|
4365
|
+
* Возвращает кратность количества для указанного товара.
|
|
4293
4366
|
*
|
|
4294
|
-
* @param product
|
|
4367
|
+
* @param product Данные о товаре для которого необходимо вернуть кратность количества.
|
|
4295
4368
|
*/
|
|
4296
|
-
|
|
4297
|
-
return product.minCount && !
|
|
4369
|
+
static getProductMultiplicity(product) {
|
|
4370
|
+
return !product.properties?.ignoreMinCountCheck && product.minCount && !ScUnitsHelper.productIsMeasurable(product) ? product.minCount : 1;
|
|
4298
4371
|
}
|
|
4299
4372
|
/**
|
|
4300
|
-
* Возвращает
|
|
4373
|
+
* Возвращает кратность длины для указанного товара.
|
|
4301
4374
|
*
|
|
4302
|
-
* @param product
|
|
4375
|
+
* @param product Данные о товаре для которого необходимо вернуть кратность длины.
|
|
4303
4376
|
*/
|
|
4304
|
-
|
|
4305
|
-
|
|
4377
|
+
static getProductLengthMultiplicity(product) {
|
|
4378
|
+
if (product.properties?.lengthStep) {
|
|
4379
|
+
return product.properties.lengthStep;
|
|
4380
|
+
}
|
|
4381
|
+
return !product.properties?.ignoreMinCountCheck && product.minCount ? product.minCount : 0.01;
|
|
4306
4382
|
}
|
|
4307
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScUnitsHelper, deps: [{ token: SC_LINEAR_VALUES_TOKEN }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4308
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScUnitsHelper, providedIn: 'root' }); }
|
|
4309
4383
|
}
|
|
4310
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScUnitsHelper, decorators: [{
|
|
4311
|
-
type: Injectable,
|
|
4312
|
-
args: [{
|
|
4313
|
-
providedIn: 'root',
|
|
4314
|
-
}]
|
|
4315
|
-
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
4316
|
-
type: Inject,
|
|
4317
|
-
args: [SC_LINEAR_VALUES_TOKEN]
|
|
4318
|
-
}] }] });
|
|
4319
4384
|
|
|
4320
4385
|
/**
|
|
4321
4386
|
* Возвращает текущий маршрут.
|
|
@@ -6250,6 +6315,10 @@ class ScNotificationsService {
|
|
|
6250
6315
|
* {@link Observable} данных о текущем пользователе.
|
|
6251
6316
|
*/
|
|
6252
6317
|
this.user$ = inject(SC_USER_INFO);
|
|
6318
|
+
/**
|
|
6319
|
+
* Ссылка на жизненный цикл сервиса.
|
|
6320
|
+
*/
|
|
6321
|
+
this.destroyRef = inject(DestroyRef);
|
|
6253
6322
|
/**
|
|
6254
6323
|
* Интервалы обновления данных.
|
|
6255
6324
|
*/
|
|
@@ -6278,7 +6347,7 @@ class ScNotificationsService {
|
|
|
6278
6347
|
else {
|
|
6279
6348
|
this.updateUserNotificationsCount();
|
|
6280
6349
|
}
|
|
6281
|
-
}), switchMap((user) => (user.isGuest ? of() : this.interval$)))
|
|
6350
|
+
}), switchMap((user) => (user.isGuest ? of() : this.interval$)), takeUntilDestroyed(this.destroyRef))
|
|
6282
6351
|
.subscribe();
|
|
6283
6352
|
}
|
|
6284
6353
|
/**
|