Browse Source

refactor: Use i18n for facet filter error message, minor code cleanup

Michael Bromley 4 years ago
parent
commit
ce147dc13e

+ 1 - 0
packages/core/src/i18n/messages/en.json

@@ -17,6 +17,7 @@
     "default-channel-not-found": "Default channel not found",
     "entity-has-no-translation-in-language": "Translatable entity '{ entityName }' has not been translated into the requested language ({ languageCode })",
     "entity-with-id-not-found": "No { entityName } with the id '{ id }' could be found",
+    "facetfilterinput-invalid-input": "A FacetValueFilterInput object may not specify the 'and' and 'or' fields simultaneously",
     "field-invalid-datetime-range-max": "The custom field '{ name }' value [{ value }] is greater than the maximum [{ max }]",
     "field-invalid-datetime-range-min": "The custom field '{ name }' value [{ value }] is less than the minimum [{ min }]",
     "field-invalid-non-nullable": "The custom field '{ name }' value cannot be set to null",

+ 29 - 21
packages/core/src/plugin/default-search-plugin/search-strategy/mysql-search-strategy.ts

@@ -3,6 +3,7 @@ import { ID } from '@vendure/common/lib/shared-types';
 import { Brackets, SelectQueryBuilder } from 'typeorm';
 
 import { RequestContext } from '../../../api/common/request-context';
+import { UserInputError } from '../../../common/error/errors';
 import { TransactionalConnection } from '../../../service/transaction/transactional-connection';
 import { SearchIndexItem } from '../search-index-item.entity';
 
@@ -108,7 +109,14 @@ export class MysqlSearchStrategy implements SearchStrategy {
         qb: SelectQueryBuilder<SearchIndexItem>,
         input: SearchInput,
     ): SelectQueryBuilder<SearchIndexItem> {
-        const { term, facetValueFilters, facetValueIds, facetValueOperator, collectionId, collectionSlug } = input;
+        const {
+            term,
+            facetValueFilters,
+            facetValueIds,
+            facetValueOperator,
+            collectionId,
+            collectionSlug,
+        } = input;
 
         if (term && term.length > this.minTermLength) {
             const termScoreQuery = this.connection
@@ -161,28 +169,28 @@ export class MysqlSearchStrategy implements SearchStrategy {
         if (facetValueFilters?.length) {
             qb.andWhere(
                 new Brackets(qb1 => {
-                    for (const facetValueFilter of facetValueFilters)
-                    {
-                        qb1.andWhere(new Brackets(qb2 => {
-                            if (facetValueFilter.and && facetValueFilter.or && facetValueFilter.or.length) {
-                                throw Error('facetValueId and facetValueIds cannot be specified simultaneously');
-                            }
-                            if (facetValueFilter.and) {
-                                const placeholder = '_' + facetValueFilter.and;
-                                const clause = `FIND_IN_SET(:${placeholder}, facetValueIds)`;
-                                const params = { [placeholder]: facetValueFilter.and };
-                                qb2.where(clause, params);
-                            }
-                            if (facetValueFilter.or && facetValueFilter.or.length) {
-                                for (const id of facetValueFilter.or)
-                                {
-                                    const placeholder = '_' + id;
+                    for (const facetValueFilter of facetValueFilters) {
+                        qb1.andWhere(
+                            new Brackets(qb2 => {
+                                if (facetValueFilter.and && facetValueFilter.or?.length) {
+                                    throw new UserInputError('error.facetfilterinput-invalid-input');
+                                }
+                                if (facetValueFilter.and) {
+                                    const placeholder = '_' + facetValueFilter.and;
                                     const clause = `FIND_IN_SET(:${placeholder}, facetValueIds)`;
-                                    const params = { [placeholder]: id };
-                                    qb2.orWhere(clause, params);
+                                    const params = { [placeholder]: facetValueFilter.and };
+                                    qb2.where(clause, params);
+                                }
+                                if (facetValueFilter.or?.length) {
+                                    for (const id of facetValueFilter.or) {
+                                        const placeholder = '_' + id;
+                                        const clause = `FIND_IN_SET(:${placeholder}, facetValueIds)`;
+                                        const params = { [placeholder]: id };
+                                        qb2.orWhere(clause, params);
+                                    }
                                 }
-                            }
-                        }))
+                            }),
+                        );
                     }
                 }),
             );

+ 29 - 21
packages/core/src/plugin/default-search-plugin/search-strategy/postgres-search-strategy.ts

@@ -3,6 +3,7 @@ import { ID } from '@vendure/common/lib/shared-types';
 import { Brackets, SelectQueryBuilder } from 'typeorm';
 
 import { RequestContext } from '../../../api/common/request-context';
+import { UserInputError } from '../../../common/error/errors';
 import { TransactionalConnection } from '../../../service/transaction/transactional-connection';
 import { SearchIndexItem } from '../search-index-item.entity';
 
@@ -111,7 +112,14 @@ export class PostgresSearchStrategy implements SearchStrategy {
         input: SearchInput,
         forceGroup: boolean = false,
     ): SelectQueryBuilder<SearchIndexItem> {
-        const { term, facetValueFilters, facetValueIds, facetValueOperator, collectionId, collectionSlug } = input;
+        const {
+            term,
+            facetValueFilters,
+            facetValueIds,
+            facetValueOperator,
+            collectionId,
+            collectionSlug,
+        } = input;
         // join multiple words with the logical AND operator
         const termLogicalAnd = term ? term.trim().replace(/\s+/g, ' & ') : '';
 
@@ -159,28 +167,28 @@ export class PostgresSearchStrategy implements SearchStrategy {
         if (facetValueFilters?.length) {
             qb.andWhere(
                 new Brackets(qb1 => {
-                    for (const facetValueFilter of facetValueFilters)
-                    {
-                        qb1.andWhere(new Brackets(qb2 => {
-                            if (facetValueFilter.and && facetValueFilter.or && facetValueFilter.or.length) {
-                                throw Error('facetValueId and facetValueIds cannot be specified simultaneously');
-                            }
-                            if (facetValueFilter.and) {
-                                const placeholder = '_' + facetValueFilter.and;
-                                const clause = `:${placeholder} = ANY (string_to_array(si.facetValueIds, ','))`;
-                                const params = { [placeholder]: facetValueFilter.and };
-                                qb2.where(clause, params);
-                            }
-                            if (facetValueFilter.or && facetValueFilter.or.length) {
-                                for (const id of facetValueFilter.or)
-                                {
-                                    const placeholder = '_' + id;
+                    for (const facetValueFilter of facetValueFilters) {
+                        qb1.andWhere(
+                            new Brackets(qb2 => {
+                                if (facetValueFilter.and && facetValueFilter.or?.length) {
+                                    throw new UserInputError('error.facetfilterinput-invalid-input');
+                                }
+                                if (facetValueFilter.and) {
+                                    const placeholder = '_' + facetValueFilter.and;
                                     const clause = `:${placeholder} = ANY (string_to_array(si.facetValueIds, ','))`;
-                                    const params = { [placeholder]: id };
-                                    qb2.orWhere(clause, params);
+                                    const params = { [placeholder]: facetValueFilter.and };
+                                    qb2.where(clause, params);
+                                }
+                                if (facetValueFilter.or?.length) {
+                                    for (const id of facetValueFilter.or) {
+                                        const placeholder = '_' + id;
+                                        const clause = `:${placeholder} = ANY (string_to_array(si.facetValueIds, ','))`;
+                                        const params = { [placeholder]: id };
+                                        qb2.orWhere(clause, params);
+                                    }
                                 }
-                            }
-                        }))
+                            }),
+                        );
                     }
                 }),
             );

+ 29 - 21
packages/core/src/plugin/default-search-plugin/search-strategy/sqlite-search-strategy.ts

@@ -3,6 +3,7 @@ import { ID } from '@vendure/common/lib/shared-types';
 import { Brackets, SelectQueryBuilder } from 'typeorm';
 
 import { RequestContext } from '../../../api/common/request-context';
+import { UserInputError } from '../../../common/error/errors';
 import { TransactionalConnection } from '../../../service/transaction/transactional-connection';
 import { SearchIndexItem } from '../search-index-item.entity';
 
@@ -105,7 +106,14 @@ export class SqliteSearchStrategy implements SearchStrategy {
         qb: SelectQueryBuilder<SearchIndexItem>,
         input: SearchInput,
     ): SelectQueryBuilder<SearchIndexItem> {
-        const { term, facetValueFilters, facetValueIds, facetValueOperator, collectionId, collectionSlug } = input;
+        const {
+            term,
+            facetValueFilters,
+            facetValueIds,
+            facetValueOperator,
+            collectionId,
+            collectionSlug,
+        } = input;
 
         qb.where('1 = 1');
         if (term && term.length > this.minTermLength) {
@@ -148,28 +156,28 @@ export class SqliteSearchStrategy implements SearchStrategy {
         if (facetValueFilters?.length) {
             qb.andWhere(
                 new Brackets(qb1 => {
-                    for (const facetValueFilter of facetValueFilters)
-                    {
-                        qb1.andWhere(new Brackets(qb2 => {
-                            if (facetValueFilter.and && facetValueFilter.or && facetValueFilter.or.length) {
-                                throw Error('facetValueId and facetValueIds cannot be specified simultaneously');
-                            }
-                            if (facetValueFilter.and) {
-                                const placeholder = '_' + facetValueFilter.and;
-                                const clause = `(',' || facetValueIds || ',') LIKE :${placeholder}`;
-                                const params = { [placeholder]: `%,${facetValueFilter.and},%` }
-                                qb2.where(clause, params);
-                            }
-                            if (facetValueFilter.or && facetValueFilter.or.length) {
-                                for (const id of facetValueFilter.or)
-                                {
-                                    const placeholder = '_' + id;
+                    for (const facetValueFilter of facetValueFilters) {
+                        qb1.andWhere(
+                            new Brackets(qb2 => {
+                                if (facetValueFilter.and && facetValueFilter.or?.length) {
+                                    throw new UserInputError('error.facetfilterinput-invalid-input');
+                                }
+                                if (facetValueFilter.and) {
+                                    const placeholder = '_' + facetValueFilter.and;
                                     const clause = `(',' || facetValueIds || ',') LIKE :${placeholder}`;
-                                    const params = { [placeholder]: `%,${id},%` };
-                                    qb2.orWhere(clause, params);
+                                    const params = { [placeholder]: `%,${facetValueFilter.and},%` };
+                                    qb2.where(clause, params);
+                                }
+                                if (facetValueFilter.or?.length) {
+                                    for (const id of facetValueFilter.or) {
+                                        const placeholder = '_' + id;
+                                        const clause = `(',' || facetValueIds || ',') LIKE :${placeholder}`;
+                                        const params = { [placeholder]: `%,${id},%` };
+                                        qb2.orWhere(clause, params);
+                                    }
                                 }
-                            }
-                        }))
+                            }),
+                        );
                     }
                 }),
             );

+ 3 - 1
packages/elasticsearch-plugin/src/build-elastic-body.ts

@@ -1,6 +1,8 @@
 import { LanguageCode, LogicalOperator, PriceRange, SortOrder } from '@vendure/common/lib/generated-types';
 import { DeepRequired, ID } from '@vendure/core';
 
+import { UserInputError } from '../../core/src/common/error/errors';
+
 import { SearchConfig } from './options';
 import { ElasticSearchInput, SearchRequestBody } from './types';
 
@@ -64,7 +66,7 @@ export function buildElasticBody(
         ensureBoolFilterExists(query);
         facetValueFilters.forEach(facetValueFilter => {
             if (facetValueFilter.and && facetValueFilter.or && facetValueFilter.or.length) {
-                throw Error('facetId and facetIds cannot be specified simultaneously');
+                throw new UserInputError('error.facetfilterinput-invalid-input');
             }
 
             if (facetValueFilter.and) {