Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement objectpath and scopes for filters #41

Merged
merged 4 commits into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 50 additions & 14 deletions lib/src/builders/filterBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
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';
import { FilterSettingsBuilder } from './filterSettingsBuilder';
import { ConditionBuilder } from './conditionBuilder';

export type EntityDataFilterOptions = {
objectPath?: string[],
filterSettings?: (builder: FilterSettingsBuilder) => void
};

export class FilterBuilder {
private filters: (AndFilter
| BrandAssortmentFilter
Expand Down Expand Up @@ -463,17 +469,22 @@ export class FilterBuilder {
* @param filterOutIfKeyIsNotFound
* @param negated
*/
public addProductDataFilter(key: string, conditionBuilder: (builder: ConditionBuilder) => void, mustMatchAllConditions: boolean = true, filterOutIfKeyIsNotFound: boolean = true, negated: boolean = false): this {
public addProductDataFilter(key: string, conditionBuilder: (builder: ConditionBuilder) => void, mustMatchAllConditions: boolean = true, filterOutIfKeyIsNotFound: boolean = true, negated: boolean = false, options?: EntityDataFilterOptions): this {
const builder = new ConditionBuilder();
conditionBuilder(builder);

const internalSettingsBuilder = new FilterSettingsBuilder();
options?.filterSettings?.(internalSettingsBuilder);

const filter: ProductDataFilter = {
$type: 'Relewise.Client.Requests.Filters.ProductDataFilter, Relewise.Client',
key: key,
filterOutIfKeyIsNotFound: filterOutIfKeyIsNotFound,
mustMatchAllConditions: mustMatchAllConditions,
conditions: builder.build(),
negated: negated,
objectPath: options?.objectPath,
settings: internalSettingsBuilder.build(),
};
this.filters.push(filter);

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

const internalSettingsBuilder = new FilterSettingsBuilder();
options?.filterSettings?.(internalSettingsBuilder);

const filter: VariantDataFilter = {
$type: 'Relewise.Client.Requests.Filters.VariantDataFilter, Relewise.Client',
key: key,
filterOutIfKeyIsNotFound: filterOutIfKeyIsNotFound,
mustMatchAllConditions: mustMatchAllConditions,
conditions: builder.build(),
negated: negated,
objectPath: options?.objectPath,
settings: internalSettingsBuilder.build(),
};
this.filters.push(filter);

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

const internalSettingsBuilder = new FilterSettingsBuilder();
options?.filterSettings?.(internalSettingsBuilder);

const filter: BrandDataFilter = {
$type: 'Relewise.Client.Requests.Filters.BrandDataFilter, Relewise.Client',
key: key,
filterOutIfKeyIsNotFound: filterOutIfKeyIsNotFound,
mustMatchAllConditions: mustMatchAllConditions,
conditions: builder.build(),
negated: negated,
objectPath: options?.objectPath,
settings: internalSettingsBuilder.build(),
};
this.filters.push(filter);

Expand Down Expand Up @@ -563,17 +584,22 @@ export class FilterBuilder {
* @param filterOutIfKeyIsNotFound
* @param negated
*/
public addContentCategoryDataFilter(key: string, conditionBuilder: (builder: ConditionBuilder) => void, mustMatchAllConditions: boolean = true, filterOutIfKeyIsNotFound: boolean = true, negated: boolean = false): this {
public addContentCategoryDataFilter(key: string, conditionBuilder: (builder: ConditionBuilder) => void, mustMatchAllConditions: boolean = true, filterOutIfKeyIsNotFound: boolean = true, negated: boolean = false, options?: EntityDataFilterOptions): this {
const builder = new ConditionBuilder();
conditionBuilder(builder);

const internalSettingsBuilder = new FilterSettingsBuilder();
options?.filterSettings?.(internalSettingsBuilder);

const filter: ContentCategoryDataFilter = {
$type: 'Relewise.Client.Requests.Filters.ContentCategoryDataFilter, Relewise.Client',
key: key,
filterOutIfKeyIsNotFound: filterOutIfKeyIsNotFound,
mustMatchAllConditions: mustMatchAllConditions,
conditions: builder.build(),
negated: negated,
objectPath: options?.objectPath,
settings: internalSettingsBuilder.build(),
};
this.filters.push(filter);

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

const internalSettingsBuilder = new FilterSettingsBuilder();
options?.filterSettings?.(internalSettingsBuilder);

const filter: ContentDataFilter = {
$type: 'Relewise.Client.Requests.Filters.ContentDataFilter, Relewise.Client',
key: key,
filterOutIfKeyIsNotFound: filterOutIfKeyIsNotFound,
mustMatchAllConditions: mustMatchAllConditions,
conditions: builder.build(),
negated: negated,
objectPath: options?.objectPath,
settings: internalSettingsBuilder.build(),
};
this.filters.push(filter);

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

const internalSettingsBuilder = new FilterSettingsBuilder();
options?.filterSettings?.(internalSettingsBuilder);

const filter: ProductCategoryDataFilter = {
$type: 'Relewise.Client.Requests.Filters.ProductCategoryDataFilter, Relewise.Client',
key: key,
filterOutIfKeyIsNotFound: filterOutIfKeyIsNotFound,
mustMatchAllConditions: mustMatchAllConditions,
conditions: builder.build(),
negated: negated,
objectPath: options?.objectPath,
settings: internalSettingsBuilder.build(),
};
this.filters.push(filter);

Expand Down Expand Up @@ -681,7 +717,7 @@ export class FilterBuilder {
negated: negated,
};
this.filters.push(filter);

return this;
}

Expand All @@ -697,7 +733,7 @@ export class FilterBuilder {
negated: negated,
};
this.filters.push(filter);

return this;
}

Expand All @@ -713,7 +749,7 @@ export class FilterBuilder {
negated: negated,
};
this.filters.push(filter);

return this;
}

Expand All @@ -729,7 +765,7 @@ export class FilterBuilder {
negated: negated,
};
this.filters.push(filter);

return this;
}

Expand All @@ -745,7 +781,7 @@ export class FilterBuilder {
negated: negated,
};
this.filters.push(filter);

return this;
}

Expand All @@ -761,7 +797,7 @@ export class FilterBuilder {
negated: negated,
};
this.filters.push(filter);

return this;
}

Expand All @@ -777,7 +813,7 @@ export class FilterBuilder {
negated: negated,
};
this.filters.push(filter);

return this;
}

Expand All @@ -793,7 +829,7 @@ export class FilterBuilder {
negated: negated,
};
this.filters.push(filter);

return this;
}

Expand Down
34 changes: 34 additions & 0 deletions lib/src/builders/filterScopesBuilder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { ApplyFilterSettings, FilterScopes } from '../models/data-contracts';

export class FilterScopesBuilder {

private fillScope: ApplyFilterSettings | undefined = undefined;
private defaultScope: ApplyFilterSettings | undefined = undefined;

public fill({ apply }: { apply: boolean; }): this {
this.fillScope = {
$type: 'Relewise.Client.Requests.Filters.Settings.ApplyFilterSettings, Relewise.Client',
apply,
};

return this;
}

public default({ apply }: { apply: boolean; }): this {
this.defaultScope = {
$type: 'Relewise.Client.Requests.Filters.Settings.ApplyFilterSettings, Relewise.Client',
apply,
};

return this;
}

public build(): FilterScopes | null {
return this.fillScope || this.defaultScope
? {
fill: this.fillScope,
default: this.defaultScope,
}
: null;
}
}
19 changes: 19 additions & 0 deletions lib/src/builders/filterSettingsBuilder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { FilterSettings } from '../models/data-contracts';
import { FilterScopesBuilder } from './filterScopesBuilder';

export class FilterSettingsBuilder {
private scopesBuilder: FilterScopesBuilder = new FilterScopesBuilder();

public scopes(builder: (builder: FilterScopesBuilder) => void): this {
builder(this.scopesBuilder);

return this;
}

public build(): FilterSettings | null {
const scopes = this.scopesBuilder.build();
return scopes
? { scopes: scopes }
: null;
}
}
2 changes: 2 additions & 0 deletions lib/src/builders/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export * from './settings';
export * from './filterScopesBuilder';
export * from './filterSettingsBuilder';
export * from './dataObjectFilterConditionBuilder';
export * from './filterBuilder';
export * from './paginationBuilder';
Expand Down
19 changes: 18 additions & 1 deletion lib/tests/integration-tests/filters.integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,28 @@ test('Product Assortment filter', async() => {
test('Product Id filter', async() => {

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

const result = await searcher.searchProducts(request);

expect(result?.results?.length).toBe(1);
});

test('Product Variant Object Path filter', async() => {

const request: ProductSearchRequest = baseBuilder()
.filters(f => f.addVariantDataFilter('avaliableMarkets', c => c.addGreaterThanCondition(1693526400 - 1), undefined, undefined, undefined,
{
objectPath: ['US', 'ValidFromDate'],
filterSettings: s => s.scopes(sc => sc.fill({ apply: true }).default({ apply: false })),
}))
.pagination(p => p.setPageSize(20))
.build();

const result = await searcher.searchProducts(request);

expect(result?.results?.length).toBe(20);
});
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,7 @@ test('ProductSearch: Relevance modifier without conditions', async() => {
});

test('Product search - data object facets', async() => {
var builder = new ProductSearchBuilder({
language: 'da',
currency: 'DKK',
displayedAtLocation: 'integration test - dataobjects',
user: UserFactory.anonymous(),
});

const request: ProductSearchRequest = builder
const request: ProductSearchRequest = baseProductBuilder()
.facets(f => f.addProductDataObjectFacet(
't',
'Product',
Expand Down