Fix/enum validation (#2863)

* fix: SELECT enum can have a color key

* fix: "findOneOrFail" of undefined

* feat: alter column migration store previous metadata informations

* fix: enum validation extra keys
This commit is contained in:
Jérémy M
2023-12-07 17:04:49 +01:00
committed by GitHub
parent 145b432dc6
commit d70f8deeec
13 changed files with 176 additions and 109 deletions

View File

@@ -26,7 +26,6 @@ const bootstrap = async () => {
// Apply validation pipes globally // Apply validation pipes globally
app.useGlobalPipes( app.useGlobalPipes(
new ValidationPipe({ new ValidationPipe({
// whitelist: true,
transform: true, transform: true,
}), }),
); );

View File

@@ -16,6 +16,7 @@ import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
import { IsFieldMetadataDefaultValue } from 'src/metadata/field-metadata/validators/is-field-metadata-default-value.validator'; import { IsFieldMetadataDefaultValue } from 'src/metadata/field-metadata/validators/is-field-metadata-default-value.validator';
import { FieldMetadataResolver } from 'src/metadata/field-metadata/field-metadata.resolver'; import { FieldMetadataResolver } from 'src/metadata/field-metadata/field-metadata.resolver';
import { FieldMetadataDTO } from 'src/metadata/field-metadata/dtos/field-metadata.dto'; import { FieldMetadataDTO } from 'src/metadata/field-metadata/dtos/field-metadata.dto';
import { IsFieldMetadataOptions } from 'src/metadata/field-metadata/validators/is-field-metadata-options.validator';
import { FieldMetadataService } from './field-metadata.service'; import { FieldMetadataService } from './field-metadata.service';
import { FieldMetadataEntity } from './field-metadata.entity'; import { FieldMetadataEntity } from './field-metadata.entity';
@@ -65,6 +66,7 @@ import { UpdateFieldInput } from './dtos/update-field.input';
], ],
providers: [ providers: [
IsFieldMetadataDefaultValue, IsFieldMetadataDefaultValue,
IsFieldMetadataOptions,
FieldMetadataService, FieldMetadataService,
FieldMetadataResolver, FieldMetadataResolver,
], ],

View File

@@ -57,7 +57,13 @@ export const validateDefaultValueForType = (
FieldMetadataDefaultValue FieldMetadataDefaultValue
>(validator, defaultValue); >(validator, defaultValue);
return validateSync(defaultValueInstance).length === 0; return (
validateSync(defaultValueInstance, {
whitelist: true,
forbidNonWhitelisted: true,
forbidUnknownValues: true,
}).length === 0
);
}); });
return isValid; return isValid;

View File

@@ -11,7 +11,7 @@ import {
export const optionsValidatorsMap = { export const optionsValidatorsMap = {
[FieldMetadataType.RATING]: [FieldMetadataDefaultOptions], [FieldMetadataType.RATING]: [FieldMetadataDefaultOptions],
[FieldMetadataType.SELECT]: [FieldMetadataDefaultOptions], [FieldMetadataType.SELECT]: [FieldMetadataComplexOptions],
[FieldMetadataType.MULTI_SELECT]: [FieldMetadataComplexOptions], [FieldMetadataType.MULTI_SELECT]: [FieldMetadataComplexOptions],
}; };
@@ -31,12 +31,18 @@ export const validateOptionsForType = (
const isValid = options.every((option) => { const isValid = options.every((option) => {
return validators.some((validator) => { return validators.some((validator) => {
const optionsInstance = plainToInstance<any, FieldMetadataDefaultOptions>( const optionsInstance = plainToInstance<
validator, any,
option, FieldMetadataDefaultOptions | FieldMetadataComplexOptions
); >(validator, option);
return validateSync(optionsInstance).length === 0; return (
validateSync(optionsInstance, {
whitelist: true,
forbidNonWhitelisted: true,
forbidUnknownValues: true,
}).length === 0
);
}); });
}); });

View File

@@ -5,7 +5,10 @@ import { ValidationArguments, ValidatorConstraint } from 'class-validator';
import { FieldMetadataOptions } from 'src/metadata/field-metadata/interfaces/field-metadata-options.interface'; import { FieldMetadataOptions } from 'src/metadata/field-metadata/interfaces/field-metadata-options.interface';
import { FieldMetadataService } from 'src/metadata/field-metadata/field-metadata.service'; import { FieldMetadataService } from 'src/metadata/field-metadata/field-metadata.service';
import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; import {
FieldMetadataEntity,
FieldMetadataType,
} from 'src/metadata/field-metadata/field-metadata.entity';
import { validateOptionsForType } from 'src/metadata/field-metadata/utils/validate-options-for-type.util'; import { validateOptionsForType } from 'src/metadata/field-metadata/utils/validate-options-for-type.util';
@Injectable() @Injectable()
@@ -28,7 +31,13 @@ export class IsFieldMetadataOptions {
return false; return false;
} }
const fieldMetadata = await this.fieldMetadataService.findOneOrFail(id); let fieldMetadata: FieldMetadataEntity;
try {
fieldMetadata = await this.fieldMetadataService.findOneOrFail(id);
} catch {
return false;
}
type = fieldMetadata.type; type = fieldMetadata.type;
} }

View File

@@ -47,21 +47,31 @@ export class BasicColumnActionFactory extends ColumnActionAbstractFactory<BasicF
} }
protected handleAlterAction( protected handleAlterAction(
previousFieldMetadata: FieldMetadataInterface<BasicFieldMetadataType>, currentFieldMetadata: FieldMetadataInterface<BasicFieldMetadataType>,
nextFieldMetadata: FieldMetadataInterface<BasicFieldMetadataType>, alteredFieldMetadata: FieldMetadataInterface<BasicFieldMetadataType>,
options?: WorkspaceColumnActionOptions, options?: WorkspaceColumnActionOptions,
): WorkspaceMigrationColumnAlter { ): WorkspaceMigrationColumnAlter {
const defaultValue = const defaultValue =
this.getDefaultValue(nextFieldMetadata.defaultValue) ?? this.getDefaultValue(alteredFieldMetadata.defaultValue) ??
options?.defaultValue; options?.defaultValue;
const serializedDefaultValue = serializeDefaultValue(defaultValue); const serializedDefaultValue = serializeDefaultValue(defaultValue);
return { return {
action: WorkspaceMigrationColumnActionType.ALTER, action: WorkspaceMigrationColumnActionType.ALTER,
columnName: nextFieldMetadata.targetColumnMap.value, currentColumnDefinition: {
columnType: fieldMetadataTypeToColumnType(nextFieldMetadata.type), columnName: currentFieldMetadata.targetColumnMap.value,
isNullable: nextFieldMetadata.isNullable, columnType: fieldMetadataTypeToColumnType(currentFieldMetadata.type),
defaultValue: serializedDefaultValue, isNullable: currentFieldMetadata.isNullable,
defaultValue: serializeDefaultValue(
this.getDefaultValue(currentFieldMetadata.defaultValue),
),
},
alteredColumnDefinition: {
columnName: alteredFieldMetadata.targetColumnMap.value,
columnType: fieldMetadataTypeToColumnType(alteredFieldMetadata.type),
isNullable: alteredFieldMetadata.isNullable,
defaultValue: serializedDefaultValue,
},
}; };
} }

View File

@@ -23,21 +23,21 @@ export class ColumnActionAbstractFactory<
action: action:
| WorkspaceMigrationColumnActionType.CREATE | WorkspaceMigrationColumnActionType.CREATE
| WorkspaceMigrationColumnActionType.ALTER, | WorkspaceMigrationColumnActionType.ALTER,
previousFieldMetadata: FieldMetadataInterface<T> | undefined, currentFieldMetadata: FieldMetadataInterface<T> | undefined,
nextFieldMetadata: FieldMetadataInterface<T>, alteredFieldMetadata: FieldMetadataInterface<T>,
options?: WorkspaceColumnActionOptions, options?: WorkspaceColumnActionOptions,
): WorkspaceMigrationColumnAction { ): WorkspaceMigrationColumnAction {
switch (action) { switch (action) {
case WorkspaceMigrationColumnActionType.CREATE: case WorkspaceMigrationColumnActionType.CREATE:
return this.handleCreateAction(nextFieldMetadata, options); return this.handleCreateAction(alteredFieldMetadata, options);
case WorkspaceMigrationColumnActionType.ALTER: { case WorkspaceMigrationColumnActionType.ALTER: {
if (!previousFieldMetadata) { if (!currentFieldMetadata) {
throw new Error('Previous field metadata is required for alter'); throw new Error('current field metadata is required for alter');
} }
return this.handleAlterAction( return this.handleAlterAction(
previousFieldMetadata, currentFieldMetadata,
nextFieldMetadata, alteredFieldMetadata,
options, options,
); );
} }
@@ -57,8 +57,8 @@ export class ColumnActionAbstractFactory<
} }
protected handleAlterAction( protected handleAlterAction(
_previousFieldMetadata: FieldMetadataInterface<T>, _currentFieldMetadata: FieldMetadataInterface<T>,
_nextFieldMetadata: FieldMetadataInterface<T>, _alteredFieldMetadata: FieldMetadataInterface<T>,
_options?: WorkspaceColumnActionOptions, _options?: WorkspaceColumnActionOptions,
): WorkspaceMigrationColumnAlter { ): WorkspaceMigrationColumnAlter {
throw new Error('handleAlterAction method not implemented.'); throw new Error('handleAlterAction method not implemented.');

View File

@@ -45,24 +45,24 @@ export class EnumColumnActionFactory extends ColumnActionAbstractFactory<EnumFie
} }
protected handleAlterAction( protected handleAlterAction(
previousFieldMetadata: FieldMetadataInterface<EnumFieldMetadataType>, currentFieldMetadata: FieldMetadataInterface<EnumFieldMetadataType>,
nextFieldMetadata: FieldMetadataInterface<EnumFieldMetadataType>, alteredFieldMetadata: FieldMetadataInterface<EnumFieldMetadataType>,
options: WorkspaceColumnActionOptions, options: WorkspaceColumnActionOptions,
): WorkspaceMigrationColumnAlter { ): WorkspaceMigrationColumnAlter {
const defaultValue = const defaultValue =
nextFieldMetadata.defaultValue?.value ?? options?.defaultValue; alteredFieldMetadata.defaultValue?.value ?? options?.defaultValue;
const serializedDefaultValue = serializeDefaultValue(defaultValue); const serializedDefaultValue = serializeDefaultValue(defaultValue);
const enumOptions = nextFieldMetadata.options const enumOptions = alteredFieldMetadata.options
? [ ? [
...nextFieldMetadata.options.map((option) => { ...alteredFieldMetadata.options.map((option) => {
const previousOption = previousFieldMetadata.options?.find( const currentOption = currentFieldMetadata.options?.find(
(previousOption) => previousOption.id === option.id, (currentOption) => currentOption.id === option.id,
); );
// The id is the same, but the value is different, so we need to alter the enum // The id is the same, but the value is different, so we need to alter the enum
if (previousOption && previousOption.value !== option.value) { if (currentOption && currentOption.value !== option.value) {
return { return {
from: previousOption.value, from: currentOption.value,
to: option.value, to: option.value,
}; };
} }
@@ -74,12 +74,26 @@ export class EnumColumnActionFactory extends ColumnActionAbstractFactory<EnumFie
return { return {
action: WorkspaceMigrationColumnActionType.ALTER, action: WorkspaceMigrationColumnActionType.ALTER,
columnName: nextFieldMetadata.targetColumnMap.value, currentColumnDefinition: {
columnType: fieldMetadataTypeToColumnType(nextFieldMetadata.type), columnName: currentFieldMetadata.targetColumnMap.value,
enum: enumOptions, columnType: fieldMetadataTypeToColumnType(currentFieldMetadata.type),
isArray: nextFieldMetadata.type === FieldMetadataType.MULTI_SELECT, enum: currentFieldMetadata.options
isNullable: nextFieldMetadata.isNullable, ? [...currentFieldMetadata.options.map((option) => option.value)]
defaultValue: serializedDefaultValue, : undefined,
isArray: currentFieldMetadata.type === FieldMetadataType.MULTI_SELECT,
isNullable: currentFieldMetadata.isNullable,
defaultValue: serializeDefaultValue(
currentFieldMetadata.defaultValue?.value,
),
},
alteredColumnDefinition: {
columnName: alteredFieldMetadata.targetColumnMap.value,
columnType: fieldMetadataTypeToColumnType(alteredFieldMetadata.type),
enum: enumOptions,
isArray: alteredFieldMetadata.type === FieldMetadataType.MULTI_SELECT,
isNullable: alteredFieldMetadata.isNullable,
defaultValue: serializedDefaultValue,
},
}; };
} }
} }

View File

@@ -14,8 +14,8 @@ export interface WorkspaceColumnActionFactory<
action: action:
| WorkspaceMigrationColumnActionType.CREATE | WorkspaceMigrationColumnActionType.CREATE
| WorkspaceMigrationColumnActionType.ALTER, | WorkspaceMigrationColumnActionType.ALTER,
previousFieldMetadata: FieldMetadataInterface<T> | undefined, currentFieldMetadata: FieldMetadataInterface<T> | undefined,
nextFieldMetadata: FieldMetadataInterface<T>, alteredFieldMetadata: FieldMetadataInterface<T>,
options?: WorkspaceColumnActionOptions, options?: WorkspaceColumnActionOptions,
): WorkspaceMigrationColumnAction; ): WorkspaceMigrationColumnAction;
} }

View File

@@ -13,24 +13,24 @@ export enum WorkspaceMigrationColumnActionType {
export type WorkspaceMigrationEnum = string | { from: string; to: string }; export type WorkspaceMigrationEnum = string | { from: string; to: string };
export type WorkspaceMigrationColumnCreate = { export interface WorkspaceMigrationColumnDefinition {
action: WorkspaceMigrationColumnActionType.CREATE;
columnName: string; columnName: string;
columnType: string; columnType: string;
enum?: WorkspaceMigrationEnum[]; enum?: WorkspaceMigrationEnum[];
isArray?: boolean; isArray?: boolean;
isNullable?: boolean; isNullable?: boolean;
defaultValue?: any; defaultValue?: any;
}; }
export interface WorkspaceMigrationColumnCreate
extends WorkspaceMigrationColumnDefinition {
action: WorkspaceMigrationColumnActionType.CREATE;
}
export type WorkspaceMigrationColumnAlter = { export type WorkspaceMigrationColumnAlter = {
action: WorkspaceMigrationColumnActionType.ALTER; action: WorkspaceMigrationColumnActionType.ALTER;
columnName: string; currentColumnDefinition: WorkspaceMigrationColumnDefinition;
columnType: string; alteredColumnDefinition: WorkspaceMigrationColumnDefinition;
enum?: WorkspaceMigrationEnum[];
isArray?: boolean;
isNullable?: boolean;
defaultValue?: any;
}; };
export type WorkspaceMigrationColumnRelation = { export type WorkspaceMigrationColumnRelation = {

View File

@@ -97,51 +97,51 @@ export class WorkspaceMigrationFactory {
createColumnActions( createColumnActions(
action: WorkspaceMigrationColumnActionType.ALTER, action: WorkspaceMigrationColumnActionType.ALTER,
previousFieldMetadata: FieldMetadataInterface, currentFieldMetadata: FieldMetadataInterface,
nextFieldMetadata: FieldMetadataInterface, alteredFieldMetadata: FieldMetadataInterface,
): WorkspaceMigrationColumnAction[]; ): WorkspaceMigrationColumnAction[];
createColumnActions( createColumnActions(
action: action:
| WorkspaceMigrationColumnActionType.CREATE | WorkspaceMigrationColumnActionType.CREATE
| WorkspaceMigrationColumnActionType.ALTER, | WorkspaceMigrationColumnActionType.ALTER,
fieldMetadataOrPreviousFieldMetadata: FieldMetadataInterface, fieldMetadataOrCurrentFieldMetadata: FieldMetadataInterface,
undefinedOrnextFieldMetadata?: FieldMetadataInterface, undefinedOrAlteredFieldMetadata?: FieldMetadataInterface,
): WorkspaceMigrationColumnAction[] { ): WorkspaceMigrationColumnAction[] {
const previousFieldMetadata = const currentFieldMetadata =
action === WorkspaceMigrationColumnActionType.ALTER action === WorkspaceMigrationColumnActionType.ALTER
? fieldMetadataOrPreviousFieldMetadata ? fieldMetadataOrCurrentFieldMetadata
: undefined; : undefined;
const nextFieldMetadata = const alteredFieldMetadata =
action === WorkspaceMigrationColumnActionType.CREATE action === WorkspaceMigrationColumnActionType.CREATE
? fieldMetadataOrPreviousFieldMetadata ? fieldMetadataOrCurrentFieldMetadata
: undefinedOrnextFieldMetadata; : undefinedOrAlteredFieldMetadata;
if (!nextFieldMetadata) { if (!alteredFieldMetadata) {
this.logger.error( this.logger.error(
`No field metadata provided for action ${action}`, `No field metadata provided for action ${action}`,
fieldMetadataOrPreviousFieldMetadata, undefinedOrAlteredFieldMetadata,
); );
throw new Error(`No field metadata provided for action ${action}`); throw new Error(`No field metadata provided for action ${action}`);
} }
// If it's a composite field type, we need to create a column action for each of the fields // If it's a composite field type, we need to create a column action for each of the fields
if (isCompositeFieldMetadataType(nextFieldMetadata.type)) { if (isCompositeFieldMetadataType(alteredFieldMetadata.type)) {
const fieldMetadataCollection = this.compositeDefinitions.get( const fieldMetadataCollection = this.compositeDefinitions.get(
nextFieldMetadata.type, alteredFieldMetadata.type,
); );
if (!fieldMetadataCollection) { if (!fieldMetadataCollection) {
this.logger.error( this.logger.error(
`No composite definition found for type ${nextFieldMetadata.type}`, `No composite definition found for type ${alteredFieldMetadata.type}`,
{ {
nextFieldMetadata, alteredFieldMetadata,
}, },
); );
throw new Error( throw new Error(
`No composite definition found for type ${nextFieldMetadata.type}`, `No composite definition found for type ${alteredFieldMetadata.type}`,
); );
} }
@@ -153,8 +153,8 @@ export class WorkspaceMigrationFactory {
// Otherwise, we create a single column action // Otherwise, we create a single column action
const columnAction = this.createColumnAction( const columnAction = this.createColumnAction(
action, action,
previousFieldMetadata, currentFieldMetadata,
nextFieldMetadata, alteredFieldMetadata,
); );
return [columnAction]; return [columnAction];
@@ -164,24 +164,27 @@ export class WorkspaceMigrationFactory {
action: action:
| WorkspaceMigrationColumnActionType.CREATE | WorkspaceMigrationColumnActionType.CREATE
| WorkspaceMigrationColumnActionType.ALTER, | WorkspaceMigrationColumnActionType.ALTER,
previousFieldMetadata: FieldMetadataInterface | undefined, currentFieldMetadata: FieldMetadataInterface | undefined,
nextFieldMetadata: FieldMetadataInterface, alteredFieldMetadata: FieldMetadataInterface,
): WorkspaceMigrationColumnAction { ): WorkspaceMigrationColumnAction {
const { factory, options } = const { factory, options } =
this.factoriesMap.get(nextFieldMetadata.type) ?? {}; this.factoriesMap.get(alteredFieldMetadata.type) ?? {};
if (!factory) { if (!factory) {
this.logger.error(`No factory found for type ${nextFieldMetadata.type}`, { this.logger.error(
nextFieldMetadata, `No factory found for type ${alteredFieldMetadata.type}`,
}); {
alteredFieldMetadata,
},
);
throw new Error(`No factory found for type ${nextFieldMetadata.type}`); throw new Error(`No factory found for type ${alteredFieldMetadata.type}`);
} }
return factory.create( return factory.create(
action, action,
previousFieldMetadata, currentFieldMetadata,
nextFieldMetadata, alteredFieldMetadata,
options, options,
); );
} }

View File

@@ -12,10 +12,11 @@ export class WorkspaceMigrationEnumService {
tableName: string, tableName: string,
migrationColumn: WorkspaceMigrationColumnAlter, migrationColumn: WorkspaceMigrationColumnAlter,
) { ) {
const oldEnumTypeName = `${tableName}_${migrationColumn.columnName}_enum`; const columnDefinition = migrationColumn.alteredColumnDefinition;
const newEnumTypeName = `${tableName}_${migrationColumn.columnName}_enum_new`; const oldEnumTypeName = `${tableName}_${columnDefinition.columnName}_enum`;
const newEnumTypeName = `${tableName}_${columnDefinition.columnName}_enum_new`;
const enumValues = const enumValues =
migrationColumn.enum?.map((enumValue) => { columnDefinition.enum?.map((enumValue) => {
if (typeof enumValue === 'string') { if (typeof enumValue === 'string') {
return enumValue; return enumValue;
} }
@@ -23,8 +24,8 @@ export class WorkspaceMigrationEnumService {
return enumValue.to; return enumValue.to;
}) ?? []; }) ?? [];
if (!migrationColumn.isNullable && !migrationColumn.defaultValue) { if (!columnDefinition.isNullable && !columnDefinition.defaultValue) {
migrationColumn.defaultValue = migrationColumn.enum?.[0]; columnDefinition.defaultValue = columnDefinition.enum?.[0];
} }
// Create new enum type with new values // Create new enum type with new values
@@ -38,7 +39,7 @@ export class WorkspaceMigrationEnumService {
// Temporarily change column type to text // Temporarily change column type to text
await queryRunner.query(` await queryRunner.query(`
ALTER TABLE "${schemaName}"."${tableName}" ALTER TABLE "${schemaName}"."${tableName}"
ALTER COLUMN "${migrationColumn.columnName}" TYPE TEXT ALTER COLUMN "${columnDefinition.columnName}" TYPE TEXT
`); `);
// Migrate existing values to new values // Migrate existing values to new values
@@ -63,7 +64,7 @@ export class WorkspaceMigrationEnumService {
queryRunner, queryRunner,
schemaName, schemaName,
tableName, tableName,
migrationColumn.columnName, columnDefinition.columnName,
newEnumTypeName, newEnumTypeName,
); );
@@ -100,20 +101,21 @@ export class WorkspaceMigrationEnumService {
tableName: string, tableName: string,
migrationColumn: WorkspaceMigrationColumnAlter, migrationColumn: WorkspaceMigrationColumnAlter,
) { ) {
if (!migrationColumn.enum) { const columnDefinition = migrationColumn.alteredColumnDefinition;
if (!columnDefinition.enum) {
return; return;
} }
for (const enumValue of migrationColumn.enum) { for (const enumValue of columnDefinition.enum) {
// Skip string values // Skip string values
if (typeof enumValue === 'string') { if (typeof enumValue === 'string') {
continue; continue;
} }
await queryRunner.query(` await queryRunner.query(`
UPDATE "${schemaName}"."${tableName}" UPDATE "${schemaName}"."${tableName}"
SET "${migrationColumn.columnName}" = '${enumValue.to}' SET "${columnDefinition.columnName}" = '${enumValue.to}'
WHERE "${migrationColumn.columnName}" = '${enumValue.from}' WHERE "${columnDefinition.columnName}" = '${enumValue.from}'
`); `);
} }
} }
@@ -125,23 +127,25 @@ export class WorkspaceMigrationEnumService {
migrationColumn: WorkspaceMigrationColumnAlter, migrationColumn: WorkspaceMigrationColumnAlter,
enumValues: string[], enumValues: string[],
) { ) {
const columnDefinition = migrationColumn.alteredColumnDefinition;
// Set missing values to null or default value // Set missing values to null or default value
let defaultValue = 'NULL'; let defaultValue = 'NULL';
if (migrationColumn.defaultValue) { if (columnDefinition.defaultValue) {
if (Array.isArray(migrationColumn.defaultValue)) { if (Array.isArray(columnDefinition.defaultValue)) {
defaultValue = `ARRAY[${migrationColumn.defaultValue defaultValue = `ARRAY[${columnDefinition.defaultValue
.map((e) => `'${e}'`) .map((e) => `'${e}'`)
.join(', ')}]`; .join(', ')}]`;
} else { } else {
defaultValue = `'${migrationColumn.defaultValue}'`; defaultValue = `'${columnDefinition.defaultValue}'`;
} }
} }
await queryRunner.query(` await queryRunner.query(`
UPDATE "${schemaName}"."${tableName}" UPDATE "${schemaName}"."${tableName}"
SET "${migrationColumn.columnName}" = ${defaultValue} SET "${columnDefinition.columnName}" = ${defaultValue}
WHERE "${migrationColumn.columnName}" NOT IN (${enumValues WHERE "${columnDefinition.columnName}" NOT IN (${enumValues
.map((e) => `'${e}'`) .map((e) => `'${e}'`)
.join(', ')}) .join(', ')})
`); `);

View File

@@ -237,7 +237,7 @@ export class WorkspaceMigrationRunnerService {
tableName: string, tableName: string,
migrationColumn: WorkspaceMigrationColumnAlter, migrationColumn: WorkspaceMigrationColumnAlter,
) { ) {
const enumValues = migrationColumn.enum; const enumValues = migrationColumn.alteredColumnDefinition.enum;
// TODO: Maybe we can do something better if we can recreate the old `TableColumn` object // TODO: Maybe we can do something better if we can recreate the old `TableColumn` object
if (enumValues) { if (enumValues) {
@@ -248,18 +248,32 @@ export class WorkspaceMigrationRunnerService {
tableName, tableName,
migrationColumn, migrationColumn,
); );
} else {
await queryRunner.changeColumn(
`${schemaName}.${tableName}`,
migrationColumn.columnName,
new TableColumn({
name: migrationColumn.columnName,
type: migrationColumn.columnType,
default: migrationColumn.defaultValue,
isNullable: migrationColumn.isNullable,
}),
);
} }
await queryRunner.changeColumn(
`${schemaName}.${tableName}`,
new TableColumn({
name: migrationColumn.currentColumnDefinition.columnName,
type: migrationColumn.currentColumnDefinition.columnType,
default: migrationColumn.currentColumnDefinition.defaultValue,
enum: migrationColumn.currentColumnDefinition.enum?.filter(
(value): value is string => typeof value === 'string',
),
isArray: migrationColumn.currentColumnDefinition.isArray,
isNullable: migrationColumn.currentColumnDefinition.isNullable,
}),
new TableColumn({
name: migrationColumn.alteredColumnDefinition.columnName,
type: migrationColumn.alteredColumnDefinition.columnType,
default: migrationColumn.alteredColumnDefinition.defaultValue,
enum: migrationColumn.currentColumnDefinition.enum?.filter(
(value): value is string => typeof value === 'string',
),
isArray: migrationColumn.alteredColumnDefinition.isArray,
isNullable: migrationColumn.alteredColumnDefinition.isNullable,
}),
);
// }
} }
private async createForeignKey( private async createForeignKey(