Browse Source

feat(elasticsearch-plugin): Add option to hide indexed fields in api (#1181) (#1212)

Drayke 4 years ago
parent
commit
9193deeeeb

+ 31 - 0
packages/elasticsearch-plugin/e2e/elasticsearch-plugin.e2e-spec.ts

@@ -9,6 +9,7 @@ import {
     mergeConfig,
 } from '@vendure/core';
 import { createTestEnvironment, E2E_DEFAULT_CHANNEL_TOKEN } from '@vendure/testing';
+import { fail } from 'assert';
 import gql from 'graphql-tag';
 import path from 'path';
 
@@ -138,6 +139,13 @@ describe('Elasticsearch plugin', () => {
                                 return 42;
                             },
                         },
+                        hello: {
+                            graphQlType: 'String!',
+                            public: false,
+                            valueFn: args => {
+                                return 'World';
+                            },
+                        },
                     },
                     searchConfig: {
                         scriptFields: {
@@ -1344,6 +1352,29 @@ describe('Elasticsearch plugin', () => {
                 },
             });
         });
+
+        it('private mappings', async () => {
+            const query = `{
+            search(input: { take: 1, groupByProduct: true, sort: { name: ASC } }) {
+                items {
+                  customMappings {
+                    ...on CustomProductMappings {
+                      answer
+                      hello
+                    }
+                  }
+                }
+              }
+            }`;
+            try {
+                await shopClient.query(gql(query));
+            } catch (error) {
+                expect(error).toBeDefined();
+                expect(error.message).toContain('Cannot query field "hello"');
+                return;
+            }
+            fail('should not be able to query field "hello"');
+        });
     });
 
     describe('scriptFields', () => {

+ 6 - 2
packages/elasticsearch-plugin/src/api/api-extensions.ts

@@ -44,8 +44,12 @@ export function generateSchemaExtensions(options: ElasticsearchOptions): Documen
 }
 
 function generateCustomMappingTypes(options: ElasticsearchOptions): DocumentNode | undefined {
-    const productMappings = Object.entries(options.customProductMappings || {});
-    const variantMappings = Object.entries(options.customProductVariantMappings || {});
+    const productMappings = Object.entries(options.customProductMappings || {}).filter(
+        ([, value]) => value.public ?? true,
+    );
+    const variantMappings = Object.entries(options.customProductVariantMappings || {}).filter(
+        ([, value]) => value.public ?? true,
+    );
     const searchInputTypeExtensions = Object.entries(options.extendSearchInputType || {});
     const scriptProductFields = Object.entries(options.searchConfig?.scriptFields || {}).filter(
         ([, scriptField]) => scriptField.context !== 'variant',

+ 10 - 0
packages/elasticsearch-plugin/src/options.ts

@@ -166,6 +166,10 @@ export interface ElasticsearchOptions {
      * The `graphQlType` property may be one of `String`, `Int`, `Float`, `Boolean`, `ID` or list
      * versions thereof (`[String!]` etc) and can be appended with a `!` to indicate non-nullable fields.
      *
+     * The `public` (default = `true`) property is used to reveal or hide the property in the GraphQL API schema.
+     * If this property is set to `false` it's not accessible in the `customMappings` field but it's still getting
+     * parsed to the elasticsearch index.
+     *
      * This config option defines custom mappings which are accessible when the "groupByProduct"
      * input options is set to `true`.
      *
@@ -178,8 +182,14 @@ export interface ElasticsearchOptions {
      *    },
      *    reviewRating: {
      *        graphQlType: 'Float',
+     *        public: true,
      *        valueFn: product => (product.customFields as any).reviewRating,
      *    },
+     *    priority: {
+     *        graphQlType: 'Int!',
+     *        public: false,
+     *        valueFn: product => (product.customFields as any).priority,
+     *    },
      * }
      * ```
      *

+ 1 - 0
packages/elasticsearch-plugin/src/types.ts

@@ -249,6 +249,7 @@ type GraphQlPermittedReturnType = PrimitiveTypeVariations<GraphQlPrimitive>;
 
 type CustomMappingDefinition<Args extends any[], T extends GraphQlPermittedReturnType, R> = {
     graphQlType: T;
+    public?: boolean;
     valueFn: (...args: Args) => R;
 };