feat: Adding support for new FieldMetadataType with Postgres enums (#2674)

* feat: add enum type (RATING, SELECT, MULTI_SELECT)

feat: wip enum type

feat: try to alter enum

feat: wip enum

feat: wip enum

feat: schema-builder can handle enum

fix: return default value in field metadata response

* fix: create fieldMedata with options

* fix: lint issues

* fix: rename abstract factory

* feat: drop `PHONE` and `EMAIL` fieldMetadata types

* feat: drop `VARCHAR` fieldMetadata type and rely on `TEXT`

* Revert "feat: drop `PHONE` and `EMAIL` fieldMetadata types"

This reverts commit 3857539f7d42f17c81f6ab92a6db950140b3c8e5.
This commit is contained in:
Jérémy M
2023-11-30 15:24:26 +01:00
committed by GitHub
parent c2131a29b8
commit 6e6f0af26e
92 changed files with 1371 additions and 484 deletions
@@ -1,70 +0,0 @@
import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity';
import { convertFieldMetadataToColumnActions } from 'src/metadata/field-metadata/utils/convert-field-metadata-to-column-action.util';
describe('convertFieldMetadataToColumnActions', () => {
it('should convert TEXT field metadata to column actions', () => {
const fieldMetadata = {
type: FieldMetadataType.TEXT,
targetColumnMap: { value: 'name' },
defaultValue: { value: 'default text' },
} as any;
const columnActions = convertFieldMetadataToColumnActions(fieldMetadata);
expect(columnActions).toEqual([
{
action: 'CREATE',
columnName: 'name',
columnType: 'text',
defaultValue: "'default text'",
},
]);
});
it('should convert LINK field metadata to column actions', () => {
const fieldMetadata = {
type: FieldMetadataType.LINK,
targetColumnMap: { label: 'linkLabel', url: 'linkURL' },
defaultValue: { label: 'http://example.com', url: 'Example' },
} as any;
const columnActions = convertFieldMetadataToColumnActions(fieldMetadata);
expect(columnActions).toEqual([
{
action: 'CREATE',
columnName: 'linkLabel',
columnType: 'varchar',
defaultValue: "'http://example.com'",
},
{
action: 'CREATE',
columnName: 'linkURL',
columnType: 'varchar',
defaultValue: "'Example'",
},
]);
});
it('should convert CURRENCY field metadata to column actions', () => {
const fieldMetadata = {
type: FieldMetadataType.CURRENCY,
targetColumnMap: {
amountMicros: 'moneyAmountMicros',
currencyCode: 'moneyCurrencyCode',
},
defaultValue: { amountMicros: 100 * 1_000_000, currencyCode: 'USD' },
} as any;
const columnActions = convertFieldMetadataToColumnActions(fieldMetadata);
expect(columnActions).toEqual([
{
action: 'CREATE',
columnName: 'moneyAmountMicros',
columnType: 'numeric',
defaultValue: 100 * 1_000_000,
},
{
action: 'CREATE',
columnName: 'moneyCurrencyCode',
columnType: 'varchar',
defaultValue: "'USD'",
},
]);
});
});
@@ -1,175 +0,0 @@
import { FieldMetadataDefaultValue } from 'src/metadata/field-metadata/interfaces/field-metadata-default-value.interface';
import {
FieldMetadataEntity,
FieldMetadataType,
} from 'src/metadata/field-metadata/field-metadata.entity';
import {
WorkspaceMigrationColumnAction,
WorkspaceMigrationColumnActionType,
} from 'src/metadata/workspace-migration/workspace-migration.entity';
import { serializeDefaultValue } from 'src/metadata/field-metadata/utils/serialize-default-value';
export function convertFieldMetadataToColumnActions(
fieldMetadata: FieldMetadataEntity,
): WorkspaceMigrationColumnAction[] {
switch (fieldMetadata.type) {
case FieldMetadataType.UUID: {
const defaultValue =
fieldMetadata.defaultValue as FieldMetadataDefaultValue<FieldMetadataType.UUID>;
return [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: fieldMetadata.targetColumnMap.value,
columnType: 'uuid',
defaultValue: serializeDefaultValue(defaultValue?.value),
},
];
}
case FieldMetadataType.TEXT: {
const defaultValue =
fieldMetadata.defaultValue as FieldMetadataDefaultValue<FieldMetadataType.TEXT>;
return [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: fieldMetadata.targetColumnMap.value,
columnType: 'text',
defaultValue: serializeDefaultValue(defaultValue?.value ?? ''),
},
];
}
case FieldMetadataType.PHONE:
case FieldMetadataType.EMAIL: {
const defaultValue =
fieldMetadata.defaultValue as FieldMetadataDefaultValue<
FieldMetadataType.PHONE | FieldMetadataType.EMAIL
>;
return [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: fieldMetadata.targetColumnMap.value,
columnType: 'varchar',
defaultValue: serializeDefaultValue(defaultValue?.value ?? ''),
},
];
}
case FieldMetadataType.NUMERIC: {
const defaultValue =
fieldMetadata.defaultValue as FieldMetadataDefaultValue<FieldMetadataType.NUMERIC>;
return [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: fieldMetadata.targetColumnMap.value,
columnType: 'numeric',
defaultValue: serializeDefaultValue(defaultValue?.value),
},
];
}
case FieldMetadataType.NUMBER:
case FieldMetadataType.PROBABILITY: {
const defaultValue =
fieldMetadata.defaultValue as FieldMetadataDefaultValue<
FieldMetadataType.NUMBER | FieldMetadataType.PROBABILITY
>;
return [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: fieldMetadata.targetColumnMap.value,
columnType: 'float',
defaultValue: serializeDefaultValue(defaultValue?.value),
},
];
}
case FieldMetadataType.BOOLEAN: {
const defaultValue =
fieldMetadata.defaultValue as FieldMetadataDefaultValue<FieldMetadataType.BOOLEAN>;
return [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: fieldMetadata.targetColumnMap.value,
columnType: 'boolean',
defaultValue: serializeDefaultValue(defaultValue?.value),
},
];
}
case FieldMetadataType.DATE_TIME: {
const defaultValue =
fieldMetadata.defaultValue as FieldMetadataDefaultValue<FieldMetadataType.DATE_TIME>;
return [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: fieldMetadata.targetColumnMap.value,
columnType: 'timestamp',
defaultValue: serializeDefaultValue(defaultValue?.value),
},
];
}
case FieldMetadataType.LINK: {
const defaultValue =
fieldMetadata.defaultValue as FieldMetadataDefaultValue<FieldMetadataType.LINK>;
return [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: fieldMetadata.targetColumnMap.label,
columnType: 'varchar',
defaultValue: serializeDefaultValue(defaultValue?.label ?? ''),
},
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: fieldMetadata.targetColumnMap.url,
columnType: 'varchar',
defaultValue: serializeDefaultValue(defaultValue?.url ?? ''),
},
];
}
case FieldMetadataType.CURRENCY: {
const defaultValue =
fieldMetadata.defaultValue as FieldMetadataDefaultValue<FieldMetadataType.CURRENCY>;
return [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: fieldMetadata.targetColumnMap.amountMicros,
columnType: 'numeric',
defaultValue: serializeDefaultValue(defaultValue?.amountMicros),
},
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: fieldMetadata.targetColumnMap.currencyCode,
columnType: 'varchar',
defaultValue: serializeDefaultValue(defaultValue?.currencyCode ?? ''),
},
];
}
case FieldMetadataType.FULL_NAME: {
const defaultValue =
fieldMetadata.defaultValue as FieldMetadataDefaultValue<FieldMetadataType.FULL_NAME>;
return [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: fieldMetadata.targetColumnMap.firstName,
columnType: 'varchar',
defaultValue: serializeDefaultValue(defaultValue?.firstName ?? ''),
},
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: fieldMetadata.targetColumnMap.lastName,
columnType: 'varchar',
defaultValue: serializeDefaultValue(defaultValue?.lastName ?? ''),
},
];
}
default:
throw new Error(`Unknown type ${fieldMetadata.type}`);
}
}
@@ -28,6 +28,9 @@ export function generateTargetColumnMap(
case FieldMetadataType.PROBABILITY:
case FieldMetadataType.BOOLEAN:
case FieldMetadataType.DATE_TIME:
case FieldMetadataType.RATING:
case FieldMetadataType.SELECT:
case FieldMetadataType.MULTI_SELECT:
return {
value: columnName,
};
@@ -0,0 +1,14 @@
import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity';
export const isCompositeFieldMetadataType = (
type: FieldMetadataType,
): type is
| FieldMetadataType.LINK
| FieldMetadataType.CURRENCY
| FieldMetadataType.FULL_NAME => {
return (
type === FieldMetadataType.LINK ||
type === FieldMetadataType.CURRENCY ||
type === FieldMetadataType.FULL_NAME
);
};
@@ -0,0 +1,14 @@
import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity';
export const isEnumFieldMetadataType = (
type: FieldMetadataType,
): type is
| FieldMetadataType.RATING
| FieldMetadataType.SELECT
| FieldMetadataType.MULTI_SELECT => {
return (
type === FieldMetadataType.RATING ||
type === FieldMetadataType.SELECT ||
type === FieldMetadataType.MULTI_SELECT
);
};
@@ -10,7 +10,11 @@ export const serializeDefaultValue = (
}
// Dynamic default values
if (typeof defaultValue === 'object' && 'type' in defaultValue) {
if (
!Array.isArray(defaultValue) &&
typeof defaultValue === 'object' &&
'type' in defaultValue
) {
switch (defaultValue.type) {
case 'uuid':
return 'public.uuid_generate_v4()';
@@ -38,6 +42,10 @@ export const serializeDefaultValue = (
return `'${defaultValue.toISOString()}'`;
}
if (Array.isArray(defaultValue)) {
return defaultValue;
}
if (typeof defaultValue === 'object') {
return `'${JSON.stringify(defaultValue)}'`;
}
@@ -25,7 +25,8 @@ export const validateDefaultValueBasedOnType = (
case FieldMetadataType.TEXT:
case FieldMetadataType.PHONE:
case FieldMetadataType.EMAIL:
case FieldMetadataType.ENUM:
case FieldMetadataType.RATING:
case FieldMetadataType.SELECT:
case FieldMetadataType.NUMERIC:
return (
typeof defaultValue === 'object' &&
@@ -82,6 +83,12 @@ export const validateDefaultValueBasedOnType = (
typeof defaultValue.lastName === 'string'
);
case FieldMetadataType.MULTI_SELECT:
return (
Array.isArray(defaultValue) &&
defaultValue.every((value) => typeof value === 'string')
);
default:
return false;
}