Просмотр исходного кода

fix(core): Add warning for list defaults in mysql

Michael Bromley 5 лет назад
Родитель
Сommit
d47becc44f

+ 14 - 10
packages/core/e2e/custom-fields.e2e-spec.ts

@@ -5,7 +5,7 @@ import gql from 'graphql-tag';
 import path from 'path';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
-import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
+import { TEST_SETUP_TIMEOUT_MS, testConfig } from '../../../e2e-common/test-config';
 
 import { assertThrowsWithMessage } from './utils/assert-throws-with-message';
 import { fixPostgresTimezone } from './utils/fix-pg-timezone';
@@ -276,18 +276,22 @@ describe('Custom fields', () => {
             }
         `);
 
+        const customFields = {
+            stringWithDefault: 'hello',
+            localeStringWithDefault: 'hola',
+            intWithDefault: 5,
+            floatWithDefault: 5.5,
+            booleanWithDefault: true,
+            dateTimeWithDefault: '2019-04-30T12:59:16.415Z',
+            // MySQL does not support defaults on TEXT fields, which is what "simple-json" uses
+            // internally. See https://stackoverflow.com/q/3466872/772859
+            stringListWithDefault: testConfig.dbConnectionOptions.type === 'mysql' ? null : ['cat'],
+        };
+
         expect(product).toEqual({
             id: 'T_1',
             name: 'Laptop',
-            customFields: {
-                stringWithDefault: 'hello',
-                localeStringWithDefault: 'hola',
-                intWithDefault: 5,
-                floatWithDefault: 5.5,
-                booleanWithDefault: true,
-                dateTimeWithDefault: '2019-04-30T12:59:16.415Z',
-                stringListWithDefault: ['cat'],
-            },
+            customFields,
         });
     });
 

+ 18 - 7
packages/core/src/entity/register-custom-entity-fields.ts

@@ -3,7 +3,7 @@ import { assertNever } from '@vendure/common/lib/shared-utils';
 import { Column, ColumnOptions, ColumnType, ConnectionOptions } from 'typeorm';
 import { DateUtils } from 'typeorm/util/DateUtils';
 
-import { CustomFields } from '../config/custom-field/custom-field-types';
+import { CustomFieldConfig, CustomFields } from '../config/custom-field/custom-field-types';
 import { Logger } from '../config/logger/vendure-logger';
 import { VendureConfig } from '../config/vendure-config';
 
@@ -54,12 +54,7 @@ function registerCustomFieldsForEntity(
             const registerColumn = () => {
                 const options: ColumnOptions = {
                     type: list ? 'simple-json' : getColumnType(dbEngine, type),
-                    default:
-                        list && defaultValue
-                            ? JSON.stringify(defaultValue)
-                            : type === 'datetime'
-                            ? formatDefaultDatetime(dbEngine, defaultValue)
-                            : defaultValue,
+                    default: getDefault(customField, dbEngine),
                     name,
                     nullable: nullable === false ? false : true,
                 };
@@ -151,6 +146,22 @@ function getColumnType(dbEngine: ConnectionOptions['type'], type: CustomFieldTyp
     return 'varchar';
 }
 
+function getDefault(customField: CustomFieldConfig, dbEngine: ConnectionOptions['type']) {
+    const { name, type, list, defaultValue, nullable } = customField;
+    if (list && defaultValue) {
+        if (dbEngine === 'mysql') {
+            // MySQL does not support defaults on TEXT fields, which is what "simple-json" uses
+            // internally. See https://stackoverflow.com/q/3466872/772859
+            Logger.warn(
+                `MySQL does not support default values on list fields (${name}). No default will be set.`,
+            );
+            return undefined;
+        }
+        return JSON.stringify(defaultValue);
+    }
+    return type === 'datetime' ? formatDefaultDatetime(dbEngine, defaultValue) : defaultValue;
+}
+
 /**
  * Dynamically registers any custom fields with TypeORM. This function should be run at the bootstrap
  * stage of the app lifecycle, before the AppModule is initialized.