Browse Source

feat(core): Allow length of custom field strings to be specified

Closes #166
Michael Bromley 6 years ago
parent
commit
fe360f59e3

+ 1 - 0
packages/admin-ui/src/app/common/generated-types.ts

@@ -3153,6 +3153,7 @@ export type StringCustomFieldConfig = CustomField & {
   __typename?: 'StringCustomFieldConfig',
   name: Scalars['String'],
   type: Scalars['String'],
+  length?: Maybe<Scalars['Int']>,
   label?: Maybe<Array<LocalizedString>>,
   description?: Maybe<Array<LocalizedString>>,
   pattern?: Maybe<Scalars['String']>,

+ 1 - 0
packages/common/src/generated-shop-types.ts

@@ -2101,6 +2101,7 @@ export type StringCustomFieldConfig = CustomField & {
     __typename?: 'StringCustomFieldConfig';
     name: Scalars['String'];
     type: Scalars['String'];
+    length?: Maybe<Scalars['Int']>;
     label?: Maybe<Array<LocalizedString>>;
     description?: Maybe<Array<LocalizedString>>;
     pattern?: Maybe<Scalars['String']>;

+ 1 - 0
packages/common/src/generated-types.ts

@@ -3127,6 +3127,7 @@ export type StringCustomFieldConfig = CustomField & {
   __typename?: 'StringCustomFieldConfig',
   name: Scalars['String'],
   type: Scalars['String'],
+  length?: Maybe<Scalars['Int']>,
   label?: Maybe<Array<LocalizedString>>,
   description?: Maybe<Array<LocalizedString>>,
   pattern?: Maybe<Scalars['String']>,

+ 24 - 0
packages/core/e2e/custom-fields.e2e-spec.ts

@@ -89,6 +89,10 @@ describe('Custom fields', () => {
                             defaultValue: 'ho!',
                             public: true,
                         },
+                        {
+                            name: 'longString',
+                            type: 'string',
+                        },
                     ],
                     Facet: [
                         {
@@ -145,6 +149,7 @@ describe('Custom fields', () => {
                 { name: 'stringWithOptions', type: 'string' },
                 { name: 'nonPublic', type: 'string' },
                 { name: 'public', type: 'string' },
+                { name: 'longString', type: 'string' },
             ],
         });
     });
@@ -238,6 +243,25 @@ describe('Custom fields', () => {
         }, 'NOT NULL constraint failed: product.customFieldsNotnullable'),
     );
 
+    it('string length allows long strings', async () => {
+        const longString = Array.from({ length: 5000 }, v => 'hello there!').join(' ');
+        const result = await adminClient.query(
+            gql`
+                mutation($stringValue: String!) {
+                    updateProduct(input: { id: "T_1", customFields: { longString: $stringValue } }) {
+                        id
+                        customFields {
+                            longString
+                        }
+                    }
+                }
+            `,
+            { stringValue: longString },
+        );
+
+        expect(result.updateProduct.customFields.longString).toBe(longString);
+    });
+
     describe('validation', () => {
         it(
             'invalid string',

+ 1 - 0
packages/core/e2e/graphql/generated-e2e-admin-types.ts

@@ -3026,6 +3026,7 @@ export type StringCustomFieldConfig = CustomField & {
     __typename?: 'StringCustomFieldConfig';
     name: Scalars['String'];
     type: Scalars['String'];
+    length?: Maybe<Scalars['Int']>;
     label?: Maybe<Array<LocalizedString>>;
     description?: Maybe<Array<LocalizedString>>;
     pattern?: Maybe<Scalars['String']>;

+ 1 - 0
packages/core/e2e/graphql/generated-e2e-shop-types.ts

@@ -2101,6 +2101,7 @@ export type StringCustomFieldConfig = CustomField & {
     __typename?: 'StringCustomFieldConfig';
     name: Scalars['String'];
     type: Scalars['String'];
+    length?: Maybe<Scalars['Int']>;
     label?: Maybe<Array<LocalizedString>>;
     description?: Maybe<Array<LocalizedString>>;
     pattern?: Maybe<Scalars['String']>;

+ 1 - 0
packages/core/src/api/schema/common/custom-field-types.graphql

@@ -8,6 +8,7 @@ interface CustomField {
 type StringCustomFieldConfig implements CustomField {
     name: String!
     type: String!
+    length: Int
     label: [LocalizedString!]
     description: [LocalizedString!]
     pattern: String

+ 1 - 0
packages/core/src/config/custom-field/custom-field-types.ts

@@ -93,6 +93,7 @@ export type CustomFieldConfig =
  *
  * * `pattern?: string`: A regex pattern which the field value must match
  * * `options?: { value: string; label?: LocalizedString[]; };`: An array of pre-defined options for the field.
+ * * `length?: number`: The max length of the varchar created in the database. Defaults to 255. Maximum is 65,535.
  *
  * #### `localeString` type
  *

+ 21 - 4
packages/core/src/entity/register-custom-entity-fields.ts

@@ -1,9 +1,10 @@
 import { CustomFieldType } from '@vendure/common/lib/shared-types';
 import { assertNever } from '@vendure/common/lib/shared-utils';
-import { Column, ColumnType, ConnectionOptions } from 'typeorm';
+import { Column, ColumnOptions, ColumnType, ConnectionOptions } from 'typeorm';
 import { DateUtils } from 'typeorm/util/DateUtils';
 
 import { CustomFields } from '../config/custom-field/custom-field-types';
+import { Logger } from '../config/logger/vendure-logger';
 import { VendureConfig } from '../config/vendure-config';
 
 import {
@@ -29,6 +30,11 @@ import {
     CustomUserFields,
 } from './custom-entity-fields';
 
+/**
+ * The maximum length of the "length" argument of a MySQL varchar column.
+ */
+const MAX_STRING_LENGTH = 65535;
+
 /**
  * Dynamically add columns to the custom field entity based on the CustomFields config.
  */
@@ -44,14 +50,25 @@ function registerCustomFieldsForEntity(
     if (customFields) {
         for (const customField of customFields) {
             const { name, type, defaultValue, nullable } = customField;
-            const registerColumn = () =>
-                Column({
+            const registerColumn = () => {
+                const options: ColumnOptions = {
                     type: getColumnType(dbEngine, type),
                     default:
                         type === 'datetime' ? formatDefaultDatetime(dbEngine, defaultValue) : defaultValue,
                     name,
                     nullable: nullable === false ? false : true,
-                })(new ctor(), name);
+                };
+                if (customField.type === 'string') {
+                    const length = customField.length || 255;
+                    if (MAX_STRING_LENGTH < length) {
+                        throw new Error(
+                            `ERROR: The "length" property of the custom field "${customField.name}" is greater than the maximum allowed value of ${MAX_STRING_LENGTH}`,
+                        );
+                    }
+                    options.length = length;
+                }
+                Column(options)(new ctor(), name);
+            };
 
             if (translation) {
                 if (type === 'localeString') {

File diff suppressed because it is too large
+ 0 - 0
schema-admin.json


File diff suppressed because it is too large
+ 0 - 0
schema-shop.json


Some files were not shown because too many files changed in this diff