Skip to content

Commit 32e68cc

Browse files
authored
Merge pull request #41 from Relewise/feat/objectpath-and-scopes
feat: implement objectpath and scopes for filters
2 parents c2843b8 + 240eb37 commit 32e68cc

File tree

6 files changed

+124
-23
lines changed

6 files changed

+124
-23
lines changed

lib/src/builders/filterBuilder.ts

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import { AndFilter, BrandAssortmentFilter, BrandDataFilter, BrandIdFilter, CartDataFilter, ContentCategoryAssortmentFilter, ContentCategoryDataFilter, ContentCategoryHasAncestorFilter, ContentCategoryHasChildFilter, ContentCategoryHasParentFilter, ContentCategoryIdFilter, ContentCategoryLevelFilter, ContentDataFilter, ContentIdFilter, Filter, FilterCollection, OrFilter, ProductAndVariantId, ProductAndVariantIdFilter, ProductAssortmentFilter, ProductCategoryAssortmentFilter, ProductCategoryDataFilter, ProductCategoryHasAncestorFilter, ProductCategoryHasChildFilter, ProductCategoryHasParentFilter, ProductCategoryIdFilter, ProductCategoryLevelFilter, ProductDataFilter, ProductDisplayNameFilter, ProductHasVariantsFilter, ProductIdFilter, ProductListPriceFilter, ProductRecentlyPurchasedByUserFilter, ProductRecentlyViewedByUserFilter, ProductSalesPriceFilter, VariantAssortmentFilter, VariantDataFilter, VariantIdFilter, VariantListPriceFilter, VariantSalesPriceFilter, VariantSpecificationFilter } from '../models/data-contracts';
2+
import { FilterSettingsBuilder } from './filterSettingsBuilder';
23
import { ConditionBuilder } from './conditionBuilder';
34

5+
export type EntityDataFilterOptions = {
6+
objectPath?: string[],
7+
filterSettings?: (builder: FilterSettingsBuilder) => void
8+
};
9+
410
export class FilterBuilder {
511
private filters: (AndFilter
612
| BrandAssortmentFilter
@@ -463,17 +469,22 @@ export class FilterBuilder {
463469
* @param filterOutIfKeyIsNotFound
464470
* @param negated
465471
*/
466-
public addProductDataFilter(key: string, conditionBuilder: (builder: ConditionBuilder) => void, mustMatchAllConditions: boolean = true, filterOutIfKeyIsNotFound: boolean = true, negated: boolean = false): this {
472+
public addProductDataFilter(key: string, conditionBuilder: (builder: ConditionBuilder) => void, mustMatchAllConditions: boolean = true, filterOutIfKeyIsNotFound: boolean = true, negated: boolean = false, options?: EntityDataFilterOptions): this {
467473
const builder = new ConditionBuilder();
468474
conditionBuilder(builder);
469475

476+
const internalSettingsBuilder = new FilterSettingsBuilder();
477+
options?.filterSettings?.(internalSettingsBuilder);
478+
470479
const filter: ProductDataFilter = {
471480
$type: 'Relewise.Client.Requests.Filters.ProductDataFilter, Relewise.Client',
472481
key: key,
473482
filterOutIfKeyIsNotFound: filterOutIfKeyIsNotFound,
474483
mustMatchAllConditions: mustMatchAllConditions,
475484
conditions: builder.build(),
476485
negated: negated,
486+
objectPath: options?.objectPath,
487+
settings: internalSettingsBuilder.build(),
477488
};
478489
this.filters.push(filter);
479490

@@ -488,17 +499,22 @@ export class FilterBuilder {
488499
* @param filterOutIfKeyIsNotFound
489500
* @param negated
490501
*/
491-
public addVariantDataFilter(key: string, conditionBuilder: (builder: ConditionBuilder) => void, mustMatchAllConditions: boolean = true, filterOutIfKeyIsNotFound: boolean = true, negated: boolean = false): this {
502+
public addVariantDataFilter(key: string, conditionBuilder: (builder: ConditionBuilder) => void, mustMatchAllConditions: boolean = true, filterOutIfKeyIsNotFound: boolean = true, negated: boolean = false, options?: EntityDataFilterOptions): this {
492503
const builder = new ConditionBuilder();
493504
conditionBuilder(builder);
494505

506+
const internalSettingsBuilder = new FilterSettingsBuilder();
507+
options?.filterSettings?.(internalSettingsBuilder);
508+
495509
const filter: VariantDataFilter = {
496510
$type: 'Relewise.Client.Requests.Filters.VariantDataFilter, Relewise.Client',
497511
key: key,
498512
filterOutIfKeyIsNotFound: filterOutIfKeyIsNotFound,
499513
mustMatchAllConditions: mustMatchAllConditions,
500514
conditions: builder.build(),
501515
negated: negated,
516+
objectPath: options?.objectPath,
517+
settings: internalSettingsBuilder.build(),
502518
};
503519
this.filters.push(filter);
504520

@@ -513,17 +529,22 @@ export class FilterBuilder {
513529
* @param filterOutIfKeyIsNotFound
514530
* @param negated
515531
*/
516-
public addBrandDataFilter(key: string, conditionBuilder: (builder: ConditionBuilder) => void, mustMatchAllConditions: boolean = true, filterOutIfKeyIsNotFound: boolean = true, negated: boolean = false): this {
532+
public addBrandDataFilter(key: string, conditionBuilder: (builder: ConditionBuilder) => void, mustMatchAllConditions: boolean = true, filterOutIfKeyIsNotFound: boolean = true, negated: boolean = false, options?: EntityDataFilterOptions): this {
517533
const builder = new ConditionBuilder();
518534
conditionBuilder(builder);
519535

536+
const internalSettingsBuilder = new FilterSettingsBuilder();
537+
options?.filterSettings?.(internalSettingsBuilder);
538+
520539
const filter: BrandDataFilter = {
521540
$type: 'Relewise.Client.Requests.Filters.BrandDataFilter, Relewise.Client',
522541
key: key,
523542
filterOutIfKeyIsNotFound: filterOutIfKeyIsNotFound,
524543
mustMatchAllConditions: mustMatchAllConditions,
525544
conditions: builder.build(),
526545
negated: negated,
546+
objectPath: options?.objectPath,
547+
settings: internalSettingsBuilder.build(),
527548
};
528549
this.filters.push(filter);
529550

@@ -563,17 +584,22 @@ export class FilterBuilder {
563584
* @param filterOutIfKeyIsNotFound
564585
* @param negated
565586
*/
566-
public addContentCategoryDataFilter(key: string, conditionBuilder: (builder: ConditionBuilder) => void, mustMatchAllConditions: boolean = true, filterOutIfKeyIsNotFound: boolean = true, negated: boolean = false): this {
587+
public addContentCategoryDataFilter(key: string, conditionBuilder: (builder: ConditionBuilder) => void, mustMatchAllConditions: boolean = true, filterOutIfKeyIsNotFound: boolean = true, negated: boolean = false, options?: EntityDataFilterOptions): this {
567588
const builder = new ConditionBuilder();
568589
conditionBuilder(builder);
569590

591+
const internalSettingsBuilder = new FilterSettingsBuilder();
592+
options?.filterSettings?.(internalSettingsBuilder);
593+
570594
const filter: ContentCategoryDataFilter = {
571595
$type: 'Relewise.Client.Requests.Filters.ContentCategoryDataFilter, Relewise.Client',
572596
key: key,
573597
filterOutIfKeyIsNotFound: filterOutIfKeyIsNotFound,
574598
mustMatchAllConditions: mustMatchAllConditions,
575599
conditions: builder.build(),
576600
negated: negated,
601+
objectPath: options?.objectPath,
602+
settings: internalSettingsBuilder.build(),
577603
};
578604
this.filters.push(filter);
579605

@@ -588,17 +614,22 @@ export class FilterBuilder {
588614
* @param filterOutIfKeyIsNotFound
589615
* @param negated
590616
*/
591-
public addContentDataFilter(key: string, conditionBuilder: (builder: ConditionBuilder) => void, mustMatchAllConditions: boolean = true, filterOutIfKeyIsNotFound: boolean = true, negated: boolean = false): this {
617+
public addContentDataFilter(key: string, conditionBuilder: (builder: ConditionBuilder) => void, mustMatchAllConditions: boolean = true, filterOutIfKeyIsNotFound: boolean = true, negated: boolean = false, options?: EntityDataFilterOptions): this {
592618
const builder = new ConditionBuilder();
593619
conditionBuilder(builder);
594620

621+
const internalSettingsBuilder = new FilterSettingsBuilder();
622+
options?.filterSettings?.(internalSettingsBuilder);
623+
595624
const filter: ContentDataFilter = {
596625
$type: 'Relewise.Client.Requests.Filters.ContentDataFilter, Relewise.Client',
597626
key: key,
598627
filterOutIfKeyIsNotFound: filterOutIfKeyIsNotFound,
599628
mustMatchAllConditions: mustMatchAllConditions,
600629
conditions: builder.build(),
601630
negated: negated,
631+
objectPath: options?.objectPath,
632+
settings: internalSettingsBuilder.build(),
602633
};
603634
this.filters.push(filter);
604635

@@ -613,17 +644,22 @@ export class FilterBuilder {
613644
* @param filterOutIfKeyIsNotFound
614645
* @param negated
615646
*/
616-
public addProductCategoryDataFilter(key: string, conditionBuilder: (builder: ConditionBuilder) => void, mustMatchAllConditions: boolean = true, filterOutIfKeyIsNotFound: boolean = true, negated: boolean = false): this {
647+
public addProductCategoryDataFilter(key: string, conditionBuilder: (builder: ConditionBuilder) => void, mustMatchAllConditions: boolean = true, filterOutIfKeyIsNotFound: boolean = true, negated: boolean = false, options?: EntityDataFilterOptions): this {
617648
const builder = new ConditionBuilder();
618649
conditionBuilder(builder);
619650

651+
const internalSettingsBuilder = new FilterSettingsBuilder();
652+
options?.filterSettings?.(internalSettingsBuilder);
653+
620654
const filter: ProductCategoryDataFilter = {
621655
$type: 'Relewise.Client.Requests.Filters.ProductCategoryDataFilter, Relewise.Client',
622656
key: key,
623657
filterOutIfKeyIsNotFound: filterOutIfKeyIsNotFound,
624658
mustMatchAllConditions: mustMatchAllConditions,
625659
conditions: builder.build(),
626660
negated: negated,
661+
objectPath: options?.objectPath,
662+
settings: internalSettingsBuilder.build(),
627663
};
628664
this.filters.push(filter);
629665

@@ -681,7 +717,7 @@ export class FilterBuilder {
681717
negated: negated,
682718
};
683719
this.filters.push(filter);
684-
720+
685721
return this;
686722
}
687723

@@ -697,7 +733,7 @@ export class FilterBuilder {
697733
negated: negated,
698734
};
699735
this.filters.push(filter);
700-
736+
701737
return this;
702738
}
703739

@@ -713,7 +749,7 @@ export class FilterBuilder {
713749
negated: negated,
714750
};
715751
this.filters.push(filter);
716-
752+
717753
return this;
718754
}
719755

@@ -729,7 +765,7 @@ export class FilterBuilder {
729765
negated: negated,
730766
};
731767
this.filters.push(filter);
732-
768+
733769
return this;
734770
}
735771

@@ -745,7 +781,7 @@ export class FilterBuilder {
745781
negated: negated,
746782
};
747783
this.filters.push(filter);
748-
784+
749785
return this;
750786
}
751787

@@ -761,7 +797,7 @@ export class FilterBuilder {
761797
negated: negated,
762798
};
763799
this.filters.push(filter);
764-
800+
765801
return this;
766802
}
767803

@@ -777,7 +813,7 @@ export class FilterBuilder {
777813
negated: negated,
778814
};
779815
this.filters.push(filter);
780-
816+
781817
return this;
782818
}
783819

@@ -793,7 +829,7 @@ export class FilterBuilder {
793829
negated: negated,
794830
};
795831
this.filters.push(filter);
796-
832+
797833
return this;
798834
}
799835

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { ApplyFilterSettings, FilterScopes } from '../models/data-contracts';
2+
3+
export class FilterScopesBuilder {
4+
5+
private fillScope: ApplyFilterSettings | undefined = undefined;
6+
private defaultScope: ApplyFilterSettings | undefined = undefined;
7+
8+
public fill({ apply }: { apply: boolean; }): this {
9+
this.fillScope = {
10+
$type: 'Relewise.Client.Requests.Filters.Settings.ApplyFilterSettings, Relewise.Client',
11+
apply,
12+
};
13+
14+
return this;
15+
}
16+
17+
public default({ apply }: { apply: boolean; }): this {
18+
this.defaultScope = {
19+
$type: 'Relewise.Client.Requests.Filters.Settings.ApplyFilterSettings, Relewise.Client',
20+
apply,
21+
};
22+
23+
return this;
24+
}
25+
26+
public build(): FilterScopes | null {
27+
return this.fillScope || this.defaultScope
28+
? {
29+
fill: this.fillScope,
30+
default: this.defaultScope,
31+
}
32+
: null;
33+
}
34+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { FilterSettings } from '../models/data-contracts';
2+
import { FilterScopesBuilder } from './filterScopesBuilder';
3+
4+
export class FilterSettingsBuilder {
5+
private scopesBuilder: FilterScopesBuilder = new FilterScopesBuilder();
6+
7+
public scopes(builder: (builder: FilterScopesBuilder) => void): this {
8+
builder(this.scopesBuilder);
9+
10+
return this;
11+
}
12+
13+
public build(): FilterSettings | null {
14+
const scopes = this.scopesBuilder.build();
15+
return scopes
16+
? { scopes: scopes }
17+
: null;
18+
}
19+
}

lib/src/builders/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
export * from './settings';
2+
export * from './filterScopesBuilder';
3+
export * from './filterSettingsBuilder';
24
export * from './dataObjectFilterConditionBuilder';
35
export * from './filterBuilder';
46
export * from './paginationBuilder';

lib/tests/integration-tests/filters.integration.test.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,28 @@ test('Product Assortment filter', async() => {
2929
test('Product Id filter', async() => {
3030

3131
const request: ProductSearchRequest = baseBuilder()
32-
.filters(f => f.addProductIdFilter(['1']))
32+
.filters(f => f.addProductIdFilter(['1'])
33+
.addVariantDataFilter('avaliableMarkets', c => c.addGreaterThanCondition(1693526400 - 1)))
3334
.pagination(p => p.setPageSize(20))
3435
.build();
3536

3637
const result = await searcher.searchProducts(request);
3738

3839
expect(result?.results?.length).toBe(1);
40+
});
41+
42+
test('Product Variant Object Path filter', async() => {
43+
44+
const request: ProductSearchRequest = baseBuilder()
45+
.filters(f => f.addVariantDataFilter('avaliableMarkets', c => c.addGreaterThanCondition(1693526400 - 1), undefined, undefined, undefined,
46+
{
47+
objectPath: ['US', 'ValidFromDate'],
48+
filterSettings: s => s.scopes(sc => sc.fill({ apply: true }).default({ apply: false })),
49+
}))
50+
.pagination(p => p.setPageSize(20))
51+
.build();
52+
53+
const result = await searcher.searchProducts(request);
54+
55+
expect(result?.results?.length).toBe(20);
3956
});

lib/tests/integration-tests/productSearch.integration.test.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,7 @@ test('ProductSearch: Relevance modifier without conditions', async() => {
2626
});
2727

2828
test('Product search - data object facets', async() => {
29-
var builder = new ProductSearchBuilder({
30-
language: 'da',
31-
currency: 'DKK',
32-
displayedAtLocation: 'integration test - dataobjects',
33-
user: UserFactory.anonymous(),
34-
});
35-
36-
const request: ProductSearchRequest = builder
29+
const request: ProductSearchRequest = baseProductBuilder()
3730
.facets(f => f.addProductDataObjectFacet(
3831
't',
3932
'Product',

0 commit comments

Comments
 (0)