@labdigital/commercetools-mock 2.29.1 → 2.30.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/dist/index.cjs +175 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +175 -51
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/lib/searchQueryTypeChecker.test.ts +96 -0
- package/src/lib/searchQueryTypeChecker.ts +120 -0
- package/src/product-projection-search.ts +1 -1
- package/src/product-search.ts +123 -0
- package/src/repositories/product/index.ts +13 -0
- package/src/services/product.test.ts +76 -1
- package/src/services/product.ts +15 -1
- package/src/types.ts +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
2
|
import { SetupServerApi, SetupServer } from 'msw/node';
|
|
3
3
|
import * as ctp from '@commercetools/platform-sdk';
|
|
4
|
-
import { QueryParam, BaseResource, Project, UpdateAction, ResourceIdentifier, ProductTailoring, AssociateRoleDraft, AssociateRole, AttributeGroupDraft, AttributeGroup, BusinessUnitDraft, BusinessUnit, CartDraft, Cart, LineItemDraft, LineItem, CartDiscountDraft, CartDiscount, CategoryDraft, Category, ChannelDraft, Channel, CustomObjectDraft, CustomObject, CustomerDraft, Customer, CustomerCreatePasswordResetToken, CustomerToken, CustomerResetPassword, MyCustomerResetPassword, CustomerGroupDraft, CustomerGroup, DiscountCodeDraft, DiscountCode, ExtensionDraft, Extension, InventoryEntryDraft, InventoryEntry, MyCustomerChangePassword, MyCustomerEmailVerify, OrderFromCartDraft, Order, CartReference, OrderImportDraft, MyOrderFromCartDraft, OrderEditDraft, OrderEdit, PaymentDraft, Payment,
|
|
4
|
+
import { QueryParam, BaseResource, Project, UpdateAction, ResourceIdentifier, ProductTailoring, AssociateRoleDraft, AssociateRole, AttributeGroupDraft, AttributeGroup, BusinessUnitDraft, BusinessUnit, CartDraft, Cart, LineItemDraft, LineItem, CartDiscountDraft, CartDiscount, CategoryDraft, Category, ChannelDraft, Channel, CustomObjectDraft, CustomObject, CustomerDraft, Customer, CustomerCreatePasswordResetToken, CustomerToken, CustomerResetPassword, MyCustomerResetPassword, CustomerGroupDraft, CustomerGroup, DiscountCodeDraft, DiscountCode, ExtensionDraft, Extension, InventoryEntryDraft, InventoryEntry, MyCustomerChangePassword, MyCustomerEmailVerify, OrderFromCartDraft, Order, CartReference, OrderImportDraft, MyOrderFromCartDraft, OrderEditDraft, OrderEdit, PaymentDraft, Payment, ProductSearchRequest, ProductPagedSearchResponse, Product, ProductProjection, ProductDraft, ProductDiscountDraft, ProductDiscount, ProductProjectionPagedSearchResponse, FacetResults, TermFacetResult, FilteredFacetResult, RangeFacetResult, ProductSelectionDraft, ProductSelection, ProductTypeDraft, ProductType, QuoteDraft, Quote, QuoteRequestDraft, QuoteRequest, ReviewDraft, Review, ShippingMethodDraft, ShippingMethod, ZoneReference, ShoppingListDraft, ShoppingList, ShoppingListLineItem, StagedQuoteDraft, StagedQuote, StandalonePriceDraft, StandalonePrice, ChannelResourceIdentifier, ChannelReference, StateDraft, State, StoreDraft, Store, SubscriptionDraft, Subscription, TaxCategoryDraft, TaxCategory, TypeDraft, Type, ZoneDraft, Zone } from '@commercetools/platform-sdk';
|
|
5
5
|
|
|
6
6
|
type Token = {
|
|
7
7
|
access_token: string;
|
|
@@ -299,9 +299,18 @@ declare class PaymentRepository extends AbstractResourceRepository<"payment"> {
|
|
|
299
299
|
create(context: RepositoryContext, draft: PaymentDraft): Payment;
|
|
300
300
|
}
|
|
301
301
|
|
|
302
|
+
declare class ProductSearch {
|
|
303
|
+
protected _storage: AbstractStorage;
|
|
304
|
+
constructor(storage: AbstractStorage);
|
|
305
|
+
search(projectKey: string, params: ProductSearchRequest): ProductPagedSearchResponse;
|
|
306
|
+
transform(product: Product, staged: boolean): ProductProjection;
|
|
307
|
+
}
|
|
308
|
+
|
|
302
309
|
declare class ProductRepository extends AbstractResourceRepository<"product"> {
|
|
310
|
+
protected _searchService: ProductSearch;
|
|
303
311
|
constructor(storage: AbstractStorage);
|
|
304
312
|
create(context: RepositoryContext, draft: ProductDraft): Product;
|
|
313
|
+
search(context: RepositoryContext, searchRequest: ProductSearchRequest): ProductPagedSearchResponse;
|
|
305
314
|
}
|
|
306
315
|
|
|
307
316
|
declare class ProductDiscountRepository extends AbstractResourceRepository<"product-discount"> {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
2
|
import { SetupServerApi, SetupServer } from 'msw/node';
|
|
3
3
|
import * as ctp from '@commercetools/platform-sdk';
|
|
4
|
-
import { QueryParam, BaseResource, Project, UpdateAction, ResourceIdentifier, ProductTailoring, AssociateRoleDraft, AssociateRole, AttributeGroupDraft, AttributeGroup, BusinessUnitDraft, BusinessUnit, CartDraft, Cart, LineItemDraft, LineItem, CartDiscountDraft, CartDiscount, CategoryDraft, Category, ChannelDraft, Channel, CustomObjectDraft, CustomObject, CustomerDraft, Customer, CustomerCreatePasswordResetToken, CustomerToken, CustomerResetPassword, MyCustomerResetPassword, CustomerGroupDraft, CustomerGroup, DiscountCodeDraft, DiscountCode, ExtensionDraft, Extension, InventoryEntryDraft, InventoryEntry, MyCustomerChangePassword, MyCustomerEmailVerify, OrderFromCartDraft, Order, CartReference, OrderImportDraft, MyOrderFromCartDraft, OrderEditDraft, OrderEdit, PaymentDraft, Payment,
|
|
4
|
+
import { QueryParam, BaseResource, Project, UpdateAction, ResourceIdentifier, ProductTailoring, AssociateRoleDraft, AssociateRole, AttributeGroupDraft, AttributeGroup, BusinessUnitDraft, BusinessUnit, CartDraft, Cart, LineItemDraft, LineItem, CartDiscountDraft, CartDiscount, CategoryDraft, Category, ChannelDraft, Channel, CustomObjectDraft, CustomObject, CustomerDraft, Customer, CustomerCreatePasswordResetToken, CustomerToken, CustomerResetPassword, MyCustomerResetPassword, CustomerGroupDraft, CustomerGroup, DiscountCodeDraft, DiscountCode, ExtensionDraft, Extension, InventoryEntryDraft, InventoryEntry, MyCustomerChangePassword, MyCustomerEmailVerify, OrderFromCartDraft, Order, CartReference, OrderImportDraft, MyOrderFromCartDraft, OrderEditDraft, OrderEdit, PaymentDraft, Payment, ProductSearchRequest, ProductPagedSearchResponse, Product, ProductProjection, ProductDraft, ProductDiscountDraft, ProductDiscount, ProductProjectionPagedSearchResponse, FacetResults, TermFacetResult, FilteredFacetResult, RangeFacetResult, ProductSelectionDraft, ProductSelection, ProductTypeDraft, ProductType, QuoteDraft, Quote, QuoteRequestDraft, QuoteRequest, ReviewDraft, Review, ShippingMethodDraft, ShippingMethod, ZoneReference, ShoppingListDraft, ShoppingList, ShoppingListLineItem, StagedQuoteDraft, StagedQuote, StandalonePriceDraft, StandalonePrice, ChannelResourceIdentifier, ChannelReference, StateDraft, State, StoreDraft, Store, SubscriptionDraft, Subscription, TaxCategoryDraft, TaxCategory, TypeDraft, Type, ZoneDraft, Zone } from '@commercetools/platform-sdk';
|
|
5
5
|
|
|
6
6
|
type Token = {
|
|
7
7
|
access_token: string;
|
|
@@ -299,9 +299,18 @@ declare class PaymentRepository extends AbstractResourceRepository<"payment"> {
|
|
|
299
299
|
create(context: RepositoryContext, draft: PaymentDraft): Payment;
|
|
300
300
|
}
|
|
301
301
|
|
|
302
|
+
declare class ProductSearch {
|
|
303
|
+
protected _storage: AbstractStorage;
|
|
304
|
+
constructor(storage: AbstractStorage);
|
|
305
|
+
search(projectKey: string, params: ProductSearchRequest): ProductPagedSearchResponse;
|
|
306
|
+
transform(product: Product, staged: boolean): ProductProjection;
|
|
307
|
+
}
|
|
308
|
+
|
|
302
309
|
declare class ProductRepository extends AbstractResourceRepository<"product"> {
|
|
310
|
+
protected _searchService: ProductSearch;
|
|
303
311
|
constructor(storage: AbstractStorage);
|
|
304
312
|
create(context: RepositoryContext, draft: ProductDraft): Product;
|
|
313
|
+
search(context: RepositoryContext, searchRequest: ProductSearchRequest): ProductPagedSearchResponse;
|
|
305
314
|
}
|
|
306
315
|
|
|
307
316
|
declare class ProductDiscountRepository extends AbstractResourceRepository<"product-discount"> {
|
package/dist/index.js
CHANGED
|
@@ -4504,6 +4504,165 @@ var PaymentRepository = class extends AbstractResourceRepository {
|
|
|
4504
4504
|
}
|
|
4505
4505
|
};
|
|
4506
4506
|
|
|
4507
|
+
// src/lib/searchQueryTypeChecker.ts
|
|
4508
|
+
var validateSearchQuery = (query) => {
|
|
4509
|
+
if (isSearchAndExpression(query)) {
|
|
4510
|
+
query.and.forEach((expr) => validateSearchQuery(expr));
|
|
4511
|
+
} else if (isSearchOrExpression(query)) {
|
|
4512
|
+
query.or.forEach((expr) => validateSearchQuery(expr));
|
|
4513
|
+
} else if (isSearchNotExpression(query)) {
|
|
4514
|
+
validateSearchQuery(query.not);
|
|
4515
|
+
} else if (isSearchFilterExpression(query) || isSearchRangeExpression(query) || isSearchExactExpression(query) || isSearchExistsExpression(query) || isSearchFullTextExpression(query) || isSearchFullTextPrefixExpression(query) || isSearchPrefixExpression(query) || isSearchWildCardExpression(query) || isSearchAnyValue(query)) {
|
|
4516
|
+
return;
|
|
4517
|
+
} else {
|
|
4518
|
+
throw new Error("Unsupported search query expression");
|
|
4519
|
+
}
|
|
4520
|
+
};
|
|
4521
|
+
var isSearchAndExpression = (expr) => expr.and !== void 0;
|
|
4522
|
+
var isSearchOrExpression = (expr) => expr.or !== void 0;
|
|
4523
|
+
var isSearchNotExpression = (expr) => expr.not !== void 0;
|
|
4524
|
+
var isSearchFilterExpression = (expr) => expr.filter !== void 0;
|
|
4525
|
+
var isSearchRangeExpression = (expr) => expr.range !== void 0;
|
|
4526
|
+
var isSearchExactExpression = (expr) => expr.exact !== void 0;
|
|
4527
|
+
var isSearchExistsExpression = (expr) => expr.exists !== void 0;
|
|
4528
|
+
var isSearchFullTextExpression = (expr) => expr.fullText !== void 0;
|
|
4529
|
+
var isSearchFullTextPrefixExpression = (expr) => expr.fullTextPrefix !== void 0;
|
|
4530
|
+
var isSearchPrefixExpression = (expr) => expr.prefix !== void 0;
|
|
4531
|
+
var isSearchWildCardExpression = (expr) => expr.wildcard !== void 0;
|
|
4532
|
+
var isSearchAnyValue = (expr) => expr.value !== void 0;
|
|
4533
|
+
|
|
4534
|
+
// src/priceSelector.ts
|
|
4535
|
+
var applyPriceSelector = (products, selector, noScopedPrice = false) => {
|
|
4536
|
+
validatePriceSelector(selector);
|
|
4537
|
+
for (const product of products) {
|
|
4538
|
+
const variants = [
|
|
4539
|
+
product.masterVariant,
|
|
4540
|
+
...product.variants ?? []
|
|
4541
|
+
].filter((x) => x != void 0);
|
|
4542
|
+
for (const variant of variants) {
|
|
4543
|
+
const scopedPrices = variant.prices?.filter((p) => priceSelectorFilter(p, selector)) ?? [];
|
|
4544
|
+
if (scopedPrices.length > 0) {
|
|
4545
|
+
const price = scopedPrices[0];
|
|
4546
|
+
variant.price = scopedPrices[0];
|
|
4547
|
+
if (!noScopedPrice) {
|
|
4548
|
+
variant.scopedPriceDiscounted = false;
|
|
4549
|
+
variant.scopedPrice = {
|
|
4550
|
+
...price,
|
|
4551
|
+
currentValue: price.value
|
|
4552
|
+
};
|
|
4553
|
+
}
|
|
4554
|
+
}
|
|
4555
|
+
}
|
|
4556
|
+
}
|
|
4557
|
+
};
|
|
4558
|
+
var validatePriceSelector = (selector) => {
|
|
4559
|
+
if ((selector.country || selector.channel || selector.customerGroup) && !selector.currency) {
|
|
4560
|
+
throw new CommercetoolsError(
|
|
4561
|
+
{
|
|
4562
|
+
code: "InvalidInput",
|
|
4563
|
+
message: "The price selecting parameters country, channel and customerGroup cannot be used without the currency."
|
|
4564
|
+
},
|
|
4565
|
+
400
|
|
4566
|
+
);
|
|
4567
|
+
}
|
|
4568
|
+
};
|
|
4569
|
+
var priceSelectorFilter = (price, selector) => {
|
|
4570
|
+
if ((selector.country || price.country) && selector.country !== price.country) {
|
|
4571
|
+
return false;
|
|
4572
|
+
}
|
|
4573
|
+
if ((selector.currency || price.value.currencyCode) && selector.currency !== price.value.currencyCode) {
|
|
4574
|
+
return false;
|
|
4575
|
+
}
|
|
4576
|
+
if ((selector.channel || price.channel?.id) && selector.channel !== price.channel?.id) {
|
|
4577
|
+
return false;
|
|
4578
|
+
}
|
|
4579
|
+
if ((selector.customerGroup || price.customerGroup?.id) && selector.customerGroup !== price.customerGroup?.id) {
|
|
4580
|
+
return false;
|
|
4581
|
+
}
|
|
4582
|
+
return true;
|
|
4583
|
+
};
|
|
4584
|
+
|
|
4585
|
+
// src/product-search.ts
|
|
4586
|
+
var ProductSearch = class {
|
|
4587
|
+
_storage;
|
|
4588
|
+
constructor(storage) {
|
|
4589
|
+
this._storage = storage;
|
|
4590
|
+
}
|
|
4591
|
+
search(projectKey, params) {
|
|
4592
|
+
const resources = this._storage.all(projectKey, "product").map(
|
|
4593
|
+
(r) => this.transform(r, params.productProjectionParameters?.staged ?? false)
|
|
4594
|
+
).filter((p) => {
|
|
4595
|
+
if (!params.productProjectionParameters?.staged) {
|
|
4596
|
+
return p.published;
|
|
4597
|
+
}
|
|
4598
|
+
return true;
|
|
4599
|
+
});
|
|
4600
|
+
if (params.query) {
|
|
4601
|
+
try {
|
|
4602
|
+
validateSearchQuery(params.query);
|
|
4603
|
+
} catch (err) {
|
|
4604
|
+
console.error(err);
|
|
4605
|
+
throw new CommercetoolsError(
|
|
4606
|
+
{
|
|
4607
|
+
code: "InvalidInput",
|
|
4608
|
+
message: err.message
|
|
4609
|
+
},
|
|
4610
|
+
400
|
|
4611
|
+
);
|
|
4612
|
+
}
|
|
4613
|
+
}
|
|
4614
|
+
if (params.productProjectionParameters) {
|
|
4615
|
+
applyPriceSelector(resources, {
|
|
4616
|
+
country: params.productProjectionParameters.priceCountry,
|
|
4617
|
+
channel: params.productProjectionParameters.priceChannel,
|
|
4618
|
+
customerGroup: params.productProjectionParameters.priceCustomerGroup,
|
|
4619
|
+
currency: params.productProjectionParameters.priceCurrency
|
|
4620
|
+
});
|
|
4621
|
+
}
|
|
4622
|
+
const offset = params.offset || 0;
|
|
4623
|
+
const limit = params.limit || 20;
|
|
4624
|
+
const productProjectionsResult = resources.slice(offset, offset + limit);
|
|
4625
|
+
const productProjectionsParameterGiven = !!params?.productProjectionParameters;
|
|
4626
|
+
const results = productProjectionsResult.map(
|
|
4627
|
+
(product) => ({
|
|
4628
|
+
productProjection: productProjectionsParameterGiven ? product : void 0,
|
|
4629
|
+
id: product.id
|
|
4630
|
+
/**
|
|
4631
|
+
* @TODO: possibly add support for optional matchingVariants
|
|
4632
|
+
* https://docs.commercetools.com/api/projects/product-search#productsearchmatchingvariants
|
|
4633
|
+
*/
|
|
4634
|
+
})
|
|
4635
|
+
);
|
|
4636
|
+
return {
|
|
4637
|
+
total: resources.length,
|
|
4638
|
+
offset,
|
|
4639
|
+
limit,
|
|
4640
|
+
results,
|
|
4641
|
+
facets: []
|
|
4642
|
+
};
|
|
4643
|
+
}
|
|
4644
|
+
transform(product, staged) {
|
|
4645
|
+
const obj = !staged ? product.masterData.current : product.masterData.staged;
|
|
4646
|
+
return {
|
|
4647
|
+
id: product.id,
|
|
4648
|
+
createdAt: product.createdAt,
|
|
4649
|
+
lastModifiedAt: product.lastModifiedAt,
|
|
4650
|
+
version: product.version,
|
|
4651
|
+
name: obj.name,
|
|
4652
|
+
key: product.key,
|
|
4653
|
+
description: obj.description,
|
|
4654
|
+
metaDescription: obj.metaDescription,
|
|
4655
|
+
slug: obj.slug,
|
|
4656
|
+
categories: obj.categories,
|
|
4657
|
+
masterVariant: obj.masterVariant,
|
|
4658
|
+
variants: obj.variants,
|
|
4659
|
+
productType: product.productType,
|
|
4660
|
+
hasStagedChanges: product.masterData.hasStagedChanges,
|
|
4661
|
+
published: product.masterData.published
|
|
4662
|
+
};
|
|
4663
|
+
}
|
|
4664
|
+
};
|
|
4665
|
+
|
|
4507
4666
|
// src/repositories/product/helpers.ts
|
|
4508
4667
|
import deepEqual2 from "deep-equal";
|
|
4509
4668
|
import { v4 as uuidv410 } from "uuid";
|
|
@@ -5234,9 +5393,11 @@ var ProductUpdateHandler = class extends AbstractUpdateHandler {
|
|
|
5234
5393
|
|
|
5235
5394
|
// src/repositories/product/index.ts
|
|
5236
5395
|
var ProductRepository = class extends AbstractResourceRepository {
|
|
5396
|
+
_searchService;
|
|
5237
5397
|
constructor(storage) {
|
|
5238
5398
|
super("product", storage);
|
|
5239
5399
|
this.actions = new ProductUpdateHandler(storage);
|
|
5400
|
+
this._searchService = new ProductSearch(storage);
|
|
5240
5401
|
}
|
|
5241
5402
|
create(context, draft) {
|
|
5242
5403
|
if (!draft.masterVariant) {
|
|
@@ -5329,6 +5490,9 @@ var ProductRepository = class extends AbstractResourceRepository {
|
|
|
5329
5490
|
};
|
|
5330
5491
|
return this.saveNew(context, resource);
|
|
5331
5492
|
}
|
|
5493
|
+
search(context, searchRequest) {
|
|
5494
|
+
return this._searchService.search(context.projectKey, searchRequest);
|
|
5495
|
+
}
|
|
5332
5496
|
};
|
|
5333
5497
|
|
|
5334
5498
|
// src/repositories/product-discount.ts
|
|
@@ -5412,57 +5576,6 @@ var ProductDiscountUpdateHandler = class extends AbstractUpdateHandler {
|
|
|
5412
5576
|
}
|
|
5413
5577
|
};
|
|
5414
5578
|
|
|
5415
|
-
// src/priceSelector.ts
|
|
5416
|
-
var applyPriceSelector = (products, selector, noScopedPrice = false) => {
|
|
5417
|
-
validatePriceSelector(selector);
|
|
5418
|
-
for (const product of products) {
|
|
5419
|
-
const variants = [
|
|
5420
|
-
product.masterVariant,
|
|
5421
|
-
...product.variants ?? []
|
|
5422
|
-
].filter((x) => x != void 0);
|
|
5423
|
-
for (const variant of variants) {
|
|
5424
|
-
const scopedPrices = variant.prices?.filter((p) => priceSelectorFilter(p, selector)) ?? [];
|
|
5425
|
-
if (scopedPrices.length > 0) {
|
|
5426
|
-
const price = scopedPrices[0];
|
|
5427
|
-
variant.price = scopedPrices[0];
|
|
5428
|
-
if (!noScopedPrice) {
|
|
5429
|
-
variant.scopedPriceDiscounted = false;
|
|
5430
|
-
variant.scopedPrice = {
|
|
5431
|
-
...price,
|
|
5432
|
-
currentValue: price.value
|
|
5433
|
-
};
|
|
5434
|
-
}
|
|
5435
|
-
}
|
|
5436
|
-
}
|
|
5437
|
-
}
|
|
5438
|
-
};
|
|
5439
|
-
var validatePriceSelector = (selector) => {
|
|
5440
|
-
if ((selector.country || selector.channel || selector.customerGroup) && !selector.currency) {
|
|
5441
|
-
throw new CommercetoolsError(
|
|
5442
|
-
{
|
|
5443
|
-
code: "InvalidInput",
|
|
5444
|
-
message: "The price selecting parameters country, channel and customerGroup cannot be used without the currency."
|
|
5445
|
-
},
|
|
5446
|
-
400
|
|
5447
|
-
);
|
|
5448
|
-
}
|
|
5449
|
-
};
|
|
5450
|
-
var priceSelectorFilter = (price, selector) => {
|
|
5451
|
-
if ((selector.country || price.country) && selector.country !== price.country) {
|
|
5452
|
-
return false;
|
|
5453
|
-
}
|
|
5454
|
-
if ((selector.currency || price.value.currencyCode) && selector.currency !== price.value.currencyCode) {
|
|
5455
|
-
return false;
|
|
5456
|
-
}
|
|
5457
|
-
if ((selector.channel || price.channel?.id) && selector.channel !== price.channel?.id) {
|
|
5458
|
-
return false;
|
|
5459
|
-
}
|
|
5460
|
-
if ((selector.customerGroup || price.customerGroup?.id) && selector.customerGroup !== price.customerGroup?.id) {
|
|
5461
|
-
return false;
|
|
5462
|
-
}
|
|
5463
|
-
return true;
|
|
5464
|
-
};
|
|
5465
|
-
|
|
5466
5579
|
// src/lib/projectionSearchFilter.ts
|
|
5467
5580
|
var parseFilterExpression = (filter) => {
|
|
5468
5581
|
const exprFunc = generateMatchFunc2(filter);
|
|
@@ -7967,6 +8080,17 @@ var ProductService = class extends AbstractService {
|
|
|
7967
8080
|
getBasePath() {
|
|
7968
8081
|
return "products";
|
|
7969
8082
|
}
|
|
8083
|
+
extraRoutes(router) {
|
|
8084
|
+
router.post("/search", this.search.bind(this));
|
|
8085
|
+
}
|
|
8086
|
+
search(request, response) {
|
|
8087
|
+
const searchBody = request.body;
|
|
8088
|
+
const resource = this.repository.search(
|
|
8089
|
+
getRepositoryContext(request),
|
|
8090
|
+
searchBody
|
|
8091
|
+
);
|
|
8092
|
+
return response.status(200).send(resource);
|
|
8093
|
+
}
|
|
7970
8094
|
};
|
|
7971
8095
|
|
|
7972
8096
|
// src/services/product-discount.ts
|