feat: simplification of default-value specification in FieldMetadata (#4592)

* feat: wip refactor default-value

* feat: health check to migrate default value

* fix: tests

* fix: refactor defaultValue to make it more clean

* fix: unit tests

* fix: front-end default value
This commit is contained in:
Jérémy M
2024-03-27 10:56:04 +01:00
committed by GitHub
parent 90ce7709dd
commit 5c0b65eecb
43 changed files with 481 additions and 328 deletions

View File

@ -34,9 +34,8 @@ export const currencyFields = (
isNullable: true,
...(inferredFieldMetadata
? {
defaultValue: {
value: inferredFieldMetadata.defaultValue?.amountMicros ?? null,
},
defaultValue:
inferredFieldMetadata.defaultValue?.amountMicros ?? null,
}
: {}),
} satisfies FieldMetadataInterface<FieldMetadataType.NUMERIC>,
@ -52,9 +51,8 @@ export const currencyFields = (
isNullable: true,
...(inferredFieldMetadata
? {
defaultValue: {
value: inferredFieldMetadata.defaultValue?.currencyCode ?? null,
},
defaultValue:
inferredFieldMetadata.defaultValue?.currencyCode ?? null,
}
: {}),
} satisfies FieldMetadataInterface<FieldMetadataType.TEXT>,

View File

@ -34,9 +34,7 @@ export const fullNameFields = (
isNullable: true,
...(inferredFieldMetadata
? {
defaultValue: {
value: inferredFieldMetadata.defaultValue?.firstName ?? null,
},
defaultValue: inferredFieldMetadata.defaultValue?.firstName ?? null,
}
: {}),
} satisfies FieldMetadataInterface<FieldMetadataType.TEXT>,
@ -52,9 +50,7 @@ export const fullNameFields = (
isNullable: true,
...(inferredFieldMetadata
? {
defaultValue: {
value: inferredFieldMetadata.defaultValue?.lastName ?? null,
},
defaultValue: inferredFieldMetadata.defaultValue?.lastName ?? null,
}
: {}),
} satisfies FieldMetadataInterface<FieldMetadataType.TEXT>,

View File

@ -34,9 +34,7 @@ export const linkFields = (
isNullable: true,
...(inferredFieldMetadata
? {
defaultValue: {
value: inferredFieldMetadata.defaultValue?.label ?? null,
},
defaultValue: inferredFieldMetadata.defaultValue?.label ?? null,
}
: {}),
} satisfies FieldMetadataInterface<FieldMetadataType.TEXT>,
@ -52,9 +50,7 @@ export const linkFields = (
isNullable: true,
...(inferredFieldMetadata
? {
defaultValue: {
value: inferredFieldMetadata.defaultValue?.url ?? null,
},
defaultValue: inferredFieldMetadata.defaultValue?.url ?? null,
}
: {}),
} satisfies FieldMetadataInterface<FieldMetadataType.TEXT>,

View File

@ -6,88 +6,95 @@ import {
IsNotEmpty,
IsNumber,
IsNumberString,
IsString,
Matches,
ValidateIf,
} from 'class-validator';
import { IsQuotedString } from 'src/engine/metadata-modules/field-metadata/validators/is-quoted-string.validator';
export const fieldMetadataDefaultValueFunctionName = {
UUID: 'uuid',
NOW: 'now',
} as const;
export type FieldMetadataDefaultValueFunctionNames =
(typeof fieldMetadataDefaultValueFunctionName)[keyof typeof fieldMetadataDefaultValueFunctionName];
export class FieldMetadataDefaultValueString {
@ValidateIf((_object, value) => value !== null)
@IsString()
@ValidateIf((object, value) => value !== null)
@IsQuotedString()
value: string | null;
}
export class FieldMetadataDefaultValueRawJson {
@ValidateIf((_object, value) => value !== null)
@ValidateIf((object, value) => value !== null)
@IsJSON()
value: JSON | null;
}
export class FieldMetadataDefaultValueNumber {
@ValidateIf((_object, value) => value !== null)
@ValidateIf((object, value) => value !== null)
@IsNumber()
value: number | null;
}
export class FieldMetadataDefaultValueBoolean {
@ValidateIf((_object, value) => value !== null)
@ValidateIf((object, value) => value !== null)
@IsBoolean()
value: boolean | null;
}
export class FieldMetadataDefaultValueStringArray {
@ValidateIf((_object, value) => value !== null)
@ValidateIf((object, value) => value !== null)
@IsArray()
@IsString({ each: true })
@IsQuotedString({ each: true })
value: string[] | null;
}
export class FieldMetadataDefaultValueDateTime {
@ValidateIf((_object, value) => value !== null)
@ValidateIf((object, value) => value !== null)
@IsDate()
value: Date | null;
}
export class FieldMetadataDefaultValueLink {
@ValidateIf((_object, value) => value !== null)
@IsString()
@ValidateIf((object, value) => value !== null)
@IsQuotedString()
label: string | null;
@ValidateIf((_object, value) => value !== null)
@IsString()
@ValidateIf((object, value) => value !== null)
@IsQuotedString()
url: string | null;
}
export class FieldMetadataDefaultValueCurrency {
@ValidateIf((_object, value) => value !== null)
@ValidateIf((object, value) => value !== null)
@IsNumberString()
amountMicros: string | null;
@ValidateIf((_object, value) => value !== null)
@IsString()
@ValidateIf((object, value) => value !== null)
@IsQuotedString()
currencyCode: string | null;
}
export class FieldMetadataDefaultValueFullName {
@ValidateIf((_object, value) => value !== null)
@IsString()
@ValidateIf((object, value) => value !== null)
@IsQuotedString()
firstName: string | null;
@ValidateIf((_object, value) => value !== null)
@IsString()
@ValidateIf((object, value) => value !== null)
@IsQuotedString()
lastName: string | null;
}
export class FieldMetadataDynamicDefaultValueUuid {
@Matches('uuid')
export class FieldMetadataDefaultValueUuidFunction {
@Matches(fieldMetadataDefaultValueFunctionName.UUID)
@IsNotEmpty()
@IsString()
type: 'uuid';
value: typeof fieldMetadataDefaultValueFunctionName.UUID;
}
export class FieldMetadataDynamicDefaultValueNow {
@Matches('now')
export class FieldMetadataDefaultValueNowFunction {
@Matches(fieldMetadataDefaultValueFunctionName.NOW)
@IsNotEmpty()
@IsString()
type: 'now';
value: typeof fieldMetadataDefaultValueFunctionName.NOW;
}

View File

@ -300,8 +300,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
existingFieldMetadata.type !== FieldMetadataType.SELECT
? existingFieldMetadata.defaultValue
: updatableFieldInput.defaultValue
? // Todo: we need to rework DefaultValue typing and format to be simpler, there is no need to have this complexity
{ value: updatableFieldInput.defaultValue as unknown as string }
? updatableFieldInput.defaultValue
: null,
// If the name is updated, the targetColumnMap should be updated as well
targetColumnMap: updatableFieldInput.name

View File

@ -8,38 +8,25 @@ import {
FieldMetadataDefaultValueNumber,
FieldMetadataDefaultValueString,
FieldMetadataDefaultValueStringArray,
FieldMetadataDynamicDefaultValueNow,
FieldMetadataDynamicDefaultValueUuid,
FieldMetadataDefaultValueUuidFunction,
FieldMetadataDefaultValueNowFunction,
} from 'src/engine/metadata-modules/field-metadata/dtos/default-value.input';
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
type FieldMetadataScalarDefaultValue =
| FieldMetadataDefaultValueString
| FieldMetadataDefaultValueNumber
| FieldMetadataDefaultValueBoolean
| FieldMetadataDefaultValueDateTime;
type ExtractValueType<T> = T extends { value: infer V } ? V : T;
export type FieldMetadataDynamicDefaultValue =
| FieldMetadataDynamicDefaultValueUuid
| FieldMetadataDynamicDefaultValueNow;
type AllFieldMetadataDefaultValueTypes =
| FieldMetadataScalarDefaultValue
| FieldMetadataDynamicDefaultValue
| FieldMetadataDefaultValueLink
| FieldMetadataDefaultValueCurrency
| FieldMetadataDefaultValueFullName;
type UnionOfValues<T> = T[keyof T];
type FieldMetadataDefaultValueMapping = {
[FieldMetadataType.UUID]:
| FieldMetadataDefaultValueString
| FieldMetadataDynamicDefaultValueUuid;
| FieldMetadataDefaultValueUuidFunction;
[FieldMetadataType.TEXT]: FieldMetadataDefaultValueString;
[FieldMetadataType.PHONE]: FieldMetadataDefaultValueString;
[FieldMetadataType.EMAIL]: FieldMetadataDefaultValueString;
[FieldMetadataType.DATE_TIME]:
| FieldMetadataDefaultValueDateTime
| FieldMetadataDynamicDefaultValueNow;
| FieldMetadataDefaultValueNowFunction;
[FieldMetadataType.BOOLEAN]: FieldMetadataDefaultValueBoolean;
[FieldMetadataType.NUMBER]: FieldMetadataDefaultValueNumber;
[FieldMetadataType.POSITION]: FieldMetadataDefaultValueNumber;
@ -54,35 +41,31 @@ type FieldMetadataDefaultValueMapping = {
[FieldMetadataType.RAW_JSON]: FieldMetadataDefaultValueRawJson;
};
export type FieldMetadataClassValidation =
UnionOfValues<FieldMetadataDefaultValueMapping>;
export type FieldMetadataFunctionDefaultValue = ExtractValueType<
FieldMetadataDefaultValueUuidFunction | FieldMetadataDefaultValueNowFunction
>;
type DefaultValueByFieldMetadata<T extends FieldMetadataType | 'default'> = [
T,
] extends [keyof FieldMetadataDefaultValueMapping]
? FieldMetadataDefaultValueMapping[T] | null
? ExtractValueType<FieldMetadataDefaultValueMapping[T]> | null
: T extends 'default'
? AllFieldMetadataDefaultValueTypes | null
? ExtractValueType<UnionOfValues<FieldMetadataDefaultValueMapping>> | null
: never;
export type FieldMetadataDefaultValue<
T extends FieldMetadataType | 'default' = 'default',
> = DefaultValueByFieldMetadata<T>;
type FieldMetadataDefaultValueExtractNestedType<T> = T extends {
value: infer U;
}
? U
: T extends object
? { [K in keyof T]: T[K] } extends { value: infer V }
? V
: T[keyof T]
: never;
type FieldMetadataDefaultValueExtractedTypes = {
[K in keyof FieldMetadataDefaultValueMapping]: FieldMetadataDefaultValueExtractNestedType<
[K in keyof FieldMetadataDefaultValueMapping]: ExtractValueType<
FieldMetadataDefaultValueMapping[K]
>;
};
export type FieldMetadataDefaultSerializableValue =
| FieldMetadataDefaultValueExtractedTypes[keyof FieldMetadataDefaultValueExtractedTypes]
| FieldMetadataDynamicDefaultValue
| null;

View File

@ -8,25 +8,19 @@ describe('serializeDefaultValue', () => {
});
it('should handle uuid dynamic default value', () => {
expect(serializeDefaultValue({ type: 'uuid' })).toBe(
'public.uuid_generate_v4()',
);
expect(serializeDefaultValue('uuid')).toBe('public.uuid_generate_v4()');
});
it('should handle now dynamic default value', () => {
expect(serializeDefaultValue({ type: 'now' })).toBe('now()');
expect(serializeDefaultValue('now')).toBe('now()');
});
it('should throw BadRequestException for invalid dynamic default value type', () => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error Just for testing purposes
expect(() => serializeDefaultValue({ type: 'invalid' })).toThrow(
BadRequestException,
);
expect(() => serializeDefaultValue('invalid')).toThrow(BadRequestException);
});
it('should handle string static default value', () => {
expect(serializeDefaultValue('test')).toBe("'test'");
expect(serializeDefaultValue("'test'")).toBe("'test'");
});
it('should handle number static default value', () => {

View File

@ -10,110 +10,105 @@ describe('validateDefaultValueForType', () => {
// Dynamic default values
it('should validate uuid dynamic default value for UUID type', () => {
expect(
validateDefaultValueForType(FieldMetadataType.UUID, { type: 'uuid' }),
).toBe(true);
expect(validateDefaultValueForType(FieldMetadataType.UUID, 'uuid')).toBe(
true,
);
});
it('should validate now dynamic default value for DATE_TIME type', () => {
expect(
validateDefaultValueForType(FieldMetadataType.DATE_TIME, { type: 'now' }),
validateDefaultValueForType(FieldMetadataType.DATE_TIME, 'now'),
).toBe(true);
});
it('should return false for mismatched dynamic default value', () => {
expect(
validateDefaultValueForType(FieldMetadataType.UUID, { type: 'now' }),
).toBe(false);
expect(validateDefaultValueForType(FieldMetadataType.UUID, 'now')).toBe(
false,
);
});
// Static default values
it('should validate string default value for TEXT type', () => {
expect(
validateDefaultValueForType(FieldMetadataType.TEXT, { value: 'test' }),
).toBe(true);
expect(validateDefaultValueForType(FieldMetadataType.TEXT, "'test'")).toBe(
true,
);
});
it('should return false for invalid string default value for TEXT type', () => {
expect(
validateDefaultValueForType(FieldMetadataType.TEXT, { value: 123 }),
).toBe(false);
expect(validateDefaultValueForType(FieldMetadataType.TEXT, 123)).toBe(
false,
);
});
it('should validate string default value for PHONE type', () => {
expect(
validateDefaultValueForType(FieldMetadataType.PHONE, {
value: '+123456789',
}),
validateDefaultValueForType(FieldMetadataType.PHONE, "'+123456789'"),
).toBe(true);
});
it('should return false for invalid string default value for PHONE type', () => {
expect(
validateDefaultValueForType(FieldMetadataType.PHONE, { value: 123 }),
).toBe(false);
expect(validateDefaultValueForType(FieldMetadataType.PHONE, 123)).toBe(
false,
);
});
it('should validate string default value for EMAIL type', () => {
expect(
validateDefaultValueForType(FieldMetadataType.EMAIL, {
value: 'test@example.com',
}),
validateDefaultValueForType(
FieldMetadataType.EMAIL,
"'test@example.com'",
),
).toBe(true);
});
it('should return false for invalid string default value for EMAIL type', () => {
expect(
validateDefaultValueForType(FieldMetadataType.EMAIL, { value: 123 }),
).toBe(false);
expect(validateDefaultValueForType(FieldMetadataType.EMAIL, 123)).toBe(
false,
);
});
it('should validate number default value for NUMBER type', () => {
expect(
validateDefaultValueForType(FieldMetadataType.NUMBER, { value: 100 }),
).toBe(true);
expect(validateDefaultValueForType(FieldMetadataType.NUMBER, 100)).toBe(
true,
);
});
it('should return false for invalid number default value for NUMBER type', () => {
expect(
validateDefaultValueForType(FieldMetadataType.NUMBER, { value: '100' }),
).toBe(false);
expect(validateDefaultValueForType(FieldMetadataType.NUMBER, '100')).toBe(
false,
);
});
it('should validate number default value for PROBABILITY type', () => {
expect(
validateDefaultValueForType(FieldMetadataType.PROBABILITY, {
value: 0.5,
}),
validateDefaultValueForType(FieldMetadataType.PROBABILITY, 0.5),
).toBe(true);
});
it('should return false for invalid number default value for PROBABILITY type', () => {
expect(
validateDefaultValueForType(FieldMetadataType.PROBABILITY, {
value: '50%',
}),
validateDefaultValueForType(FieldMetadataType.PROBABILITY, '50%'),
).toBe(false);
});
it('should validate boolean default value for BOOLEAN type', () => {
expect(
validateDefaultValueForType(FieldMetadataType.BOOLEAN, { value: true }),
).toBe(true);
expect(validateDefaultValueForType(FieldMetadataType.BOOLEAN, true)).toBe(
true,
);
});
it('should return false for invalid boolean default value for BOOLEAN type', () => {
expect(
validateDefaultValueForType(FieldMetadataType.BOOLEAN, { value: 'true' }),
).toBe(false);
expect(validateDefaultValueForType(FieldMetadataType.BOOLEAN, 'true')).toBe(
false,
);
});
// LINK type
it('should validate LINK default value', () => {
expect(
validateDefaultValueForType(FieldMetadataType.LINK, {
label: 'http://example.com',
url: 'Example',
label: "'http://example.com'",
url: "'Example'",
}),
).toBe(true);
});
@ -134,7 +129,7 @@ describe('validateDefaultValueForType', () => {
expect(
validateDefaultValueForType(FieldMetadataType.CURRENCY, {
amountMicros: '100',
currencyCode: 'USD',
currencyCode: "'USD'",
}),
).toBe(true);
});
@ -144,7 +139,7 @@ describe('validateDefaultValueForType', () => {
validateDefaultValueForType(
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error Just for testing purposes
{ amountMicros: 100, currencyCode: 'USD' },
{ amountMicros: 100, currencyCode: "'USD'" },
FieldMetadataType.CURRENCY,
),
).toBe(false);
@ -153,9 +148,7 @@ describe('validateDefaultValueForType', () => {
// Unknown type
it('should return false for unknown type', () => {
expect(
validateDefaultValueForType('unknown' as FieldMetadataType, {
value: 'test',
}),
validateDefaultValueForType('unknown' as FieldMetadataType, "'test'"),
).toBe(false);
});
});

View File

@ -9,23 +9,21 @@ export function generateDefaultValue(
case FieldMetadataType.TEXT:
case FieldMetadataType.PHONE:
case FieldMetadataType.EMAIL:
return {
value: '',
};
return "''";
case FieldMetadataType.FULL_NAME:
return {
firstName: '',
lastName: '',
firstName: "''",
lastName: "''",
};
case FieldMetadataType.LINK:
return {
url: '',
label: '',
url: "''",
label: "''",
};
case FieldMetadataType.CURRENCY:
return {
amountMicros: null,
currencyCode: '',
currencyCode: "''",
};
default:
return null;

View File

@ -0,0 +1,21 @@
import {
FieldMetadataDefaultSerializableValue,
FieldMetadataFunctionDefaultValue,
} from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
import {
FieldMetadataDefaultValueFunctionNames,
fieldMetadataDefaultValueFunctionName,
} from 'src/engine/metadata-modules/field-metadata/dtos/default-value.input';
export const isFunctionDefaultValue = (
defaultValue: FieldMetadataDefaultSerializableValue,
): defaultValue is FieldMetadataFunctionDefaultValue => {
return (
typeof defaultValue === 'string' &&
!defaultValue.startsWith("'") &&
Object.values(fieldMetadataDefaultValueFunctionName).includes(
defaultValue as FieldMetadataDefaultValueFunctionNames,
)
);
};

View File

@ -2,7 +2,8 @@ import { BadRequestException } from '@nestjs/common';
import { FieldMetadataDefaultSerializableValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
import { serializeTypeDefaultValue } from 'src/engine/metadata-modules/field-metadata/utils/serialize-type-default-value.util';
import { isFunctionDefaultValue } from 'src/engine/metadata-modules/field-metadata/utils/is-function-default-value.util';
import { serializeFunctionDefaultValue } from 'src/engine/metadata-modules/field-metadata/utils/serialize-function-default-value.util';
export const serializeDefaultValue = (
defaultValue?: FieldMetadataDefaultSerializableValue,
@ -11,13 +12,10 @@ export const serializeDefaultValue = (
return null;
}
// Dynamic default values
if (
!Array.isArray(defaultValue) &&
typeof defaultValue === 'object' &&
'type' in defaultValue
) {
const serializedTypeDefaultValue = serializeTypeDefaultValue(defaultValue);
// Function default values
if (isFunctionDefaultValue(defaultValue)) {
const serializedTypeDefaultValue =
serializeFunctionDefaultValue(defaultValue);
if (!serializedTypeDefaultValue) {
throw new BadRequestException('Invalid default value');
@ -27,8 +25,8 @@ export const serializeDefaultValue = (
}
// Static default values
if (typeof defaultValue === 'string') {
return `'${defaultValue}'`;
if (typeof defaultValue === 'string' && defaultValue.startsWith("'")) {
return defaultValue;
}
if (typeof defaultValue === 'number') {
@ -51,5 +49,5 @@ export const serializeDefaultValue = (
return `'${JSON.stringify(defaultValue)}'`;
}
throw new BadRequestException('Invalid default value');
throw new BadRequestException(`Invalid default value "${defaultValue}"`);
};

View File

@ -0,0 +1,14 @@
import { FieldMetadataFunctionDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
export const serializeFunctionDefaultValue = (
defaultValue?: FieldMetadataFunctionDefaultValue,
) => {
switch (defaultValue) {
case 'uuid':
return 'public.uuid_generate_v4()';
case 'now':
return 'now()';
default:
return null;
}
};

View File

@ -1,18 +0,0 @@
import { FieldMetadataDynamicDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
export const serializeTypeDefaultValue = (
defaultValue?: FieldMetadataDynamicDefaultValue,
) => {
if (!defaultValue?.type) {
return null;
}
switch (defaultValue.type) {
case 'uuid':
return 'public.uuid_generate_v4()';
case 'now':
return 'now()';
default:
return null;
}
};

View File

@ -1,7 +1,10 @@
import { plainToInstance } from 'class-transformer';
import { validateSync } from 'class-validator';
import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
import {
FieldMetadataClassValidation,
FieldMetadataDefaultValue,
} from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import {
@ -14,21 +17,22 @@ import {
FieldMetadataDefaultValueNumber,
FieldMetadataDefaultValueString,
FieldMetadataDefaultValueStringArray,
FieldMetadataDynamicDefaultValueNow,
FieldMetadataDynamicDefaultValueUuid,
FieldMetadataDefaultValueNowFunction,
FieldMetadataDefaultValueUuidFunction,
} from 'src/engine/metadata-modules/field-metadata/dtos/default-value.input';
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
export const defaultValueValidatorsMap = {
[FieldMetadataType.UUID]: [
FieldMetadataDefaultValueString,
FieldMetadataDynamicDefaultValueUuid,
FieldMetadataDefaultValueUuidFunction,
],
[FieldMetadataType.TEXT]: [FieldMetadataDefaultValueString],
[FieldMetadataType.PHONE]: [FieldMetadataDefaultValueString],
[FieldMetadataType.EMAIL]: [FieldMetadataDefaultValueString],
[FieldMetadataType.DATE_TIME]: [
FieldMetadataDefaultValueDateTime,
FieldMetadataDynamicDefaultValueNow,
FieldMetadataDefaultValueNowFunction,
],
[FieldMetadataType.BOOLEAN]: [FieldMetadataDefaultValueBoolean],
[FieldMetadataType.NUMBER]: [FieldMetadataDefaultValueNumber],
@ -54,10 +58,14 @@ export const validateDefaultValueForType = (
if (!validators) return false;
const isValid = validators.some((validator) => {
const conputedDefaultValue = isCompositeFieldMetadataType(type)
? defaultValue
: { value: defaultValue };
const defaultValueInstance = plainToInstance<
any,
FieldMetadataDefaultValue
>(validator, defaultValue);
FieldMetadataClassValidation
>(validator, conputedDefaultValue as FieldMetadataClassValidation);
return (
validateSync(defaultValueInstance, {

View File

@ -0,0 +1,24 @@
import {
ValidationArguments,
ValidationOptions,
registerDecorator,
} from 'class-validator';
export function IsQuotedString(validationOptions?: ValidationOptions) {
return function (object: object, propertyName: string) {
registerDecorator({
name: 'isQuotedString',
target: object.constructor,
propertyName: propertyName,
options: validationOptions,
validator: {
validate(value: any) {
return typeof value === 'string' && /^'.*'$/.test(value);
},
defaultMessage(args: ValidationArguments) {
return `${args.property} must be a quoted string`;
},
},
});
};
}

View File

@ -256,7 +256,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
isCustom: false,
isSystem: true,
workspaceId: objectMetadataInput.workspaceId,
defaultValue: { type: 'uuid' },
defaultValue: 'uuid',
},
{
standardId: customObjectStandardFieldIds.name,
@ -272,7 +272,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
isActive: true,
isCustom: false,
workspaceId: objectMetadataInput.workspaceId,
defaultValue: { value: 'Untitled' },
defaultValue: "'Untitled'",
},
{
standardId: baseObjectStandardFieldIds.createdAt,
@ -288,7 +288,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
isActive: true,
isCustom: false,
workspaceId: objectMetadataInput.workspaceId,
defaultValue: { type: 'now' },
defaultValue: 'now',
},
{
standardId: baseObjectStandardFieldIds.updatedAt,
@ -305,7 +305,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
isCustom: false,
isSystem: true,
workspaceId: objectMetadataInput.workspaceId,
defaultValue: { type: 'now' },
defaultValue: 'now',
},
{
standardId: customObjectStandardFieldIds.position,

View File

@ -2,7 +2,6 @@ import { Injectable, Logger } from '@nestjs/common';
import { WorkspaceColumnActionOptions } from 'src/engine/metadata-modules/workspace-migration/interfaces/workspace-column-action-options.interface';
import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface';
import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import {
@ -35,8 +34,7 @@ export class BasicColumnActionFactory extends ColumnActionAbstractFactory<BasicF
fieldMetadata: FieldMetadataInterface<BasicFieldMetadataType>,
options?: WorkspaceColumnActionOptions,
): WorkspaceMigrationColumnCreate {
const defaultValue =
this.getDefaultValue(fieldMetadata.defaultValue) ?? options?.defaultValue;
const defaultValue = fieldMetadata.defaultValue ?? options?.defaultValue;
const serializedDefaultValue = serializeDefaultValue(defaultValue);
return {
@ -54,8 +52,7 @@ export class BasicColumnActionFactory extends ColumnActionAbstractFactory<BasicF
options?: WorkspaceColumnActionOptions,
): WorkspaceMigrationColumnAlter {
const defaultValue =
this.getDefaultValue(alteredFieldMetadata.defaultValue) ??
options?.defaultValue;
alteredFieldMetadata.defaultValue ?? options?.defaultValue;
const serializedDefaultValue = serializeDefaultValue(defaultValue);
const currentColumnName = currentFieldMetadata.targetColumnMap.value;
const alteredColumnName = alteredFieldMetadata.targetColumnMap.value;
@ -75,9 +72,7 @@ export class BasicColumnActionFactory extends ColumnActionAbstractFactory<BasicF
columnName: currentColumnName,
columnType: fieldMetadataTypeToColumnType(currentFieldMetadata.type),
isNullable: currentFieldMetadata.isNullable,
defaultValue: serializeDefaultValue(
this.getDefaultValue(currentFieldMetadata.defaultValue),
),
defaultValue: serializeDefaultValue(currentFieldMetadata.defaultValue),
},
alteredColumnDefinition: {
columnName: alteredColumnName,
@ -87,19 +82,4 @@ export class BasicColumnActionFactory extends ColumnActionAbstractFactory<BasicF
},
};
}
private getDefaultValue(
defaultValue:
| FieldMetadataDefaultValue<BasicFieldMetadataType>
| undefined
| null,
) {
if (!defaultValue) return null;
if ('type' in defaultValue) {
return defaultValue;
} else {
return defaultValue?.value;
}
}
}

View File

@ -26,8 +26,7 @@ export class EnumColumnActionFactory extends ColumnActionAbstractFactory<EnumFie
fieldMetadata: FieldMetadataInterface<EnumFieldMetadataType>,
options: WorkspaceColumnActionOptions,
): WorkspaceMigrationColumnCreate {
const defaultValue =
fieldMetadata.defaultValue?.value ?? options?.defaultValue;
const defaultValue = fieldMetadata.defaultValue ?? options?.defaultValue;
const serializedDefaultValue = serializeDefaultValue(defaultValue);
const enumOptions = fieldMetadata.options
? [...fieldMetadata.options.map((option) => option.value)]
@ -50,7 +49,7 @@ export class EnumColumnActionFactory extends ColumnActionAbstractFactory<EnumFie
options: WorkspaceColumnActionOptions,
): WorkspaceMigrationColumnAlter {
const defaultValue =
alteredFieldMetadata.defaultValue?.value ?? options?.defaultValue;
alteredFieldMetadata.defaultValue ?? options?.defaultValue;
const serializedDefaultValue = serializeDefaultValue(defaultValue);
const enumOptions = alteredFieldMetadata.options
@ -94,9 +93,7 @@ export class EnumColumnActionFactory extends ColumnActionAbstractFactory<EnumFie
: undefined,
isArray: currentFieldMetadata.type === FieldMetadataType.MULTI_SELECT,
isNullable: currentFieldMetadata.isNullable,
defaultValue: serializeDefaultValue(
currentFieldMetadata.defaultValue?.value,
),
defaultValue: serializeDefaultValue(currentFieldMetadata.defaultValue),
},
alteredColumnDefinition: {
columnName: alteredColumnName,