Преглед изворни кода

fix(server): Define customFields as JSON if not set

Michael Bromley пре 7 година
родитељ
комит
f28c822355

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
schema.json


+ 6 - 6
server/src/app.module.ts

@@ -4,6 +4,8 @@ import { TypeOrmModule } from '@nestjs/typeorm';
 import { graphiqlExpress, graphqlExpress } from 'apollo-server-express';
 import * as GraphQLJSON from 'graphql-type-json';
 
+import { CustomFields } from '../../shared/shared-types';
+
 import { AdministratorResolver } from './api/administrator/administrator.resolver';
 import { AuthController } from './api/auth/auth.controller';
 import { ConfigResolver } from './api/config/config.resolver';
@@ -26,10 +28,8 @@ import { ProductOptionService } from './service/product-option.service';
 import { ProductVariantService } from './service/product-variant.service';
 import { ProductService } from './service/product.service';
 
-const config = getConfig();
-
 @Module({
-    imports: [GraphQLModule, TypeOrmModule.forRoot(config.dbConnectionOptions)],
+    imports: [GraphQLModule, TypeOrmModule.forRoot(getConfig().dbConnectionOptions)],
     controllers: [AuthController, CustomerController],
     providers: [
         AdministratorResolver,
@@ -60,7 +60,7 @@ export class AppModule implements NestModule {
     ) {}
 
     configure(consumer: MiddlewareConsumer) {
-        const schema = this.createSchema();
+        const schema = this.createSchema(this.configService.customFields);
 
         consumer
             .apply(
@@ -81,9 +81,9 @@ export class AppModule implements NestModule {
             .forRoutes(this.configService.apiPath);
     }
 
-    createSchema() {
+    private createSchema(customFields: CustomFields) {
         const typeDefs = this.graphQLFactory.mergeTypesByPaths(__dirname + '/**/*.graphql');
-        const extendedTypeDefs = addGraphQLCustomFields(typeDefs, config.customFields);
+        const extendedTypeDefs = addGraphQLCustomFields(typeDefs, customFields);
         return this.graphQLFactory.createSchema({
             typeDefs: extendedTypeDefs,
             resolverValidationOptions: {

+ 9 - 1
server/src/config/vendure-config.ts

@@ -61,7 +61,15 @@ const defaultConfig: ReadOnlyRequired<VendureConfig> = {
     dbConnectionOptions: {
         type: 'mysql',
     },
-    customFields: {},
+    customFields: {
+        Address: [],
+        Customer: [],
+        Product: [],
+        ProductOption: [],
+        ProductOptionGroup: [],
+        ProductVariant: [],
+        User: [],
+    },
 };
 
 let activeConfig = defaultConfig;

+ 23 - 3
server/src/entity/__snapshots__/graphql-custom-fields.spec.ts.snap

@@ -1,7 +1,9 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`addGraphQLCustomFields() extends a type 1`] = `
-"type Product {
+"scalar JSON
+
+type Product {
   id: ID
   customFields: ProductCustomFields
 }
@@ -22,6 +24,8 @@ input CreateProductInput {
   customFields: CreateProductCustomFieldsInput
 }
 
+scalar JSON
+
 type Product {
   id: ID
   customFields: ProductCustomFields
@@ -44,6 +48,8 @@ input CreateProductInput {
   customFields: CreateProductCustomFieldsInput
 }
 
+scalar JSON
+
 type Product {
   id: ID
   customFields: ProductCustomFields
@@ -75,7 +81,9 @@ input ProductTranslationInput {
 `;
 
 exports[`addGraphQLCustomFields() extends a type with a translation 1`] = `
-"type Product {
+"scalar JSON
+
+type Product {
   id: ID
   translations: [ProductTranslation!]!
   customFields: ProductCustomFields
@@ -98,7 +106,9 @@ type ProductTranslationCustomFields {
 `;
 
 exports[`addGraphQLCustomFields() extends a type with an Update input 1`] = `
-"type Product {
+"scalar JSON
+
+type Product {
   id: ID
   customFields: ProductCustomFields
 }
@@ -118,3 +128,13 @@ input UpdateProductInput {
 }
 "
 `;
+
+exports[`addGraphQLCustomFields() uses JSON scalar if no custom fields defined 1`] = `
+"scalar JSON
+
+type Product {
+  id: ID
+  customFields: JSON
+}
+"
+`;

+ 13 - 0
server/src/entity/graphql-custom-fields.spec.ts

@@ -3,6 +3,19 @@ import { CustomFields } from '../../../shared/shared-types';
 import { addGraphQLCustomFields } from './graphql-custom-fields';
 
 describe('addGraphQLCustomFields()', () => {
+    it('uses JSON scalar if no custom fields defined', () => {
+        const input = `
+            type Product {
+                id: ID
+            }
+        `;
+        const customFieldConfig: CustomFields = {
+            Product: [],
+        };
+        const result = addGraphQLCustomFields(input, customFieldConfig);
+        expect(result).toMatchSnapshot();
+    });
+
     it('extends a type', () => {
         const input = `
             type Product {

+ 48 - 16
server/src/entity/graphql-custom-fields.ts

@@ -8,23 +8,25 @@ import { assertNever } from '../../../shared/shared-utils';
  * types with a customFields property for all entities, translations and inputs for which
  * custom fields are defined.
  */
-export function addGraphQLCustomFields(typeDefs: string, customFieldConfig?: CustomFields): string {
+export function addGraphQLCustomFields(typeDefs: string, customFieldConfig: CustomFields): string {
     const schema = buildSchema(typeDefs);
 
-    if (!customFieldConfig) {
-        return typeDefs;
-    }
-
     let customFieldTypeDefs = '';
 
+    if (!schema.getType('JSON')) {
+        customFieldTypeDefs += `
+            scalar JSON
+        `;
+    }
+
     for (const entityName of Object.keys(customFieldConfig)) {
-        const customEntityFields = customFieldConfig[entityName as keyof CustomFields];
+        const customEntityFields = customFieldConfig[entityName as keyof CustomFields] || [];
 
-        if (customEntityFields) {
-            const localeStringFields = customEntityFields.filter(field => field.type === 'localeString');
-            const nonLocaleStringFields = customEntityFields.filter(field => field.type !== 'localeString');
+        const localeStringFields = customEntityFields.filter(field => field.type === 'localeString');
+        const nonLocaleStringFields = customEntityFields.filter(field => field.type !== 'localeString');
 
-            if (schema.getType(entityName)) {
+        if (schema.getType(entityName)) {
+            if (customEntityFields.length) {
                 customFieldTypeDefs += `
                     type ${entityName}CustomFields {
                         ${mapToFields(customEntityFields)}
@@ -34,10 +36,17 @@ export function addGraphQLCustomFields(typeDefs: string, customFieldConfig?: Cus
                         customFields: ${entityName}CustomFields
                     }
                 `;
+            } else {
+                customFieldTypeDefs += `
+                    extend type ${entityName} {
+                        customFields: JSON
+                    }
+                `;
             }
+        }
 
-            if (localeStringFields.length && schema.getType(`${entityName}Translation`)) {
-                customFieldTypeDefs += `
+        if (localeStringFields.length && schema.getType(`${entityName}Translation`)) {
+            customFieldTypeDefs += `
                     type ${entityName}TranslationCustomFields {
                          ${mapToFields(localeStringFields)}
                     }
@@ -46,9 +55,10 @@ export function addGraphQLCustomFields(typeDefs: string, customFieldConfig?: Cus
                         customFields: ${entityName}TranslationCustomFields
                     }
                 `;
-            }
+        }
 
-            if (schema.getType(`Create${entityName}Input`)) {
+        if (schema.getType(`Create${entityName}Input`)) {
+            if (nonLocaleStringFields.length) {
                 customFieldTypeDefs += `
                     input Create${entityName}CustomFieldsInput {
                        ${mapToFields(nonLocaleStringFields)}
@@ -58,9 +68,17 @@ export function addGraphQLCustomFields(typeDefs: string, customFieldConfig?: Cus
                         customFields: Create${entityName}CustomFieldsInput
                     }
                 `;
+            } else {
+                customFieldTypeDefs += `
+                   extend input Create${entityName}Input {
+                       customFields: JSON
+                   }
+               `;
             }
+        }
 
-            if (schema.getType(`Update${entityName}Input`)) {
+        if (schema.getType(`Update${entityName}Input`)) {
+            if (nonLocaleStringFields.length) {
                 customFieldTypeDefs += `
                     input Update${entityName}CustomFieldsInput {
                        ${mapToFields(nonLocaleStringFields)}
@@ -70,9 +88,17 @@ export function addGraphQLCustomFields(typeDefs: string, customFieldConfig?: Cus
                         customFields: Update${entityName}CustomFieldsInput
                     }
                 `;
+            } else {
+                customFieldTypeDefs += `
+                    extend input Update${entityName}Input {
+                        customFields: JSON
+                    }
+                `;
             }
+        }
 
-            if (localeStringFields && schema.getType(`${entityName}TranslationInput`)) {
+        if (localeStringFields && schema.getType(`${entityName}TranslationInput`)) {
+            if (localeStringFields.length) {
                 customFieldTypeDefs += `
                     input ${entityName}TranslationCustomFieldsInput {
                         ${mapToFields(localeStringFields)}
@@ -82,6 +108,12 @@ export function addGraphQLCustomFields(typeDefs: string, customFieldConfig?: Cus
                         customFields: ${entityName}TranslationCustomFieldsInput
                     }
                 `;
+            } else {
+                customFieldTypeDefs += `
+                    extend input ${entityName}TranslationInput {
+                        customFields: JSON
+                    }
+                `;
             }
         }
     }

+ 1 - 0
server/src/service/config.service.mock.ts

@@ -12,6 +12,7 @@ export class MockConfigService implements MockClass<ConfigService> {
     defaultLanguageCode: jest.Mock<any>;
     entityIdStrategy = new MockIdStrategy();
     dbConnectionOptions = {};
+    customFields = {};
 }
 
 export const ENCODED = 'encoded';

+ 3 - 1
shared/shared-types.ts

@@ -49,4 +49,6 @@ export interface HasCustomFields {
     customFields: CustomFieldsObject;
 }
 
-export type CustomFieldsObject = object;
+export type MayHaveCustomFields = Partial<HasCustomFields>;
+
+export type CustomFieldsObject = { [key: string]: any; };

Неке датотеке нису приказане због велике количине промена