From 05c2bb7bd3b6e4f211a5e290b95aaeab1fe4be3d Mon Sep 17 00:00:00 2001 From: Will Schurman Date: Thu, 2 May 2024 13:57:29 -0400 Subject: [PATCH] feat: Add StrictEnumField with better validation --- packages/entity/src/EntityFields.ts | 15 +++++++++++++++ .../entity/src/__tests__/EntityFields-test.ts | 12 ++++++++++++ .../cases/TwoEntitySameTableDisjointRows-test.ts | 5 +++-- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/packages/entity/src/EntityFields.ts b/packages/entity/src/EntityFields.ts index 03e1ad36..054ce48f 100644 --- a/packages/entity/src/EntityFields.ts +++ b/packages/entity/src/EntityFields.ts @@ -88,3 +88,18 @@ export class EnumField extends EntityFieldDefinition { return typeof value === 'number' || typeof value === 'string'; } } + +/** + * EntityFieldDefinition for a enum column with a strict typescript enum type. + */ +export class StrictEnumField extends EnumField { + private readonly enum: T; + constructor(options: ConstructorParameters[0] & { enum: T }) { + super(options); + this.enum = options.enum; + } + + protected override validateInputValueInternal(value: string | number): boolean { + return super.validateInputValueInternal(value) && Object.values(this.enum).includes(value); + } +} diff --git a/packages/entity/src/__tests__/EntityFields-test.ts b/packages/entity/src/__tests__/EntityFields-test.ts index a5fa000d..7c44790c 100644 --- a/packages/entity/src/__tests__/EntityFields-test.ts +++ b/packages/entity/src/__tests__/EntityFields-test.ts @@ -11,6 +11,7 @@ import { StringArrayField, JSONObjectField, EnumField, + StrictEnumField, } from '../EntityFields'; import describeFieldTestCase from '../utils/testing/describeFieldTestCase'; @@ -75,3 +76,14 @@ describeFieldTestCase( ); describeFieldTestCase(new JSONObjectField({ columnName: 'wat' }), [{}], [true, 'hello']); describeFieldTestCase(new EnumField({ columnName: 'wat' }), ['hello', 1], [true]); + +enum TestEnum { + HELLO = 'world', + WHO = 'wat', +} + +describeFieldTestCase( + new StrictEnumField({ columnName: 'wat', enum: TestEnum }), + [TestEnum.HELLO, TestEnum.WHO, 'world'], + ['what', 1, true] +); diff --git a/packages/entity/src/__tests__/cases/TwoEntitySameTableDisjointRows-test.ts b/packages/entity/src/__tests__/cases/TwoEntitySameTableDisjointRows-test.ts index cc136089..658f4d09 100644 --- a/packages/entity/src/__tests__/cases/TwoEntitySameTableDisjointRows-test.ts +++ b/packages/entity/src/__tests__/cases/TwoEntitySameTableDisjointRows-test.ts @@ -1,7 +1,7 @@ import Entity from '../../Entity'; import { EntityCompanionDefinition } from '../../EntityCompanionProvider'; import EntityConfiguration from '../../EntityConfiguration'; -import { UUIDField, EnumField, StringField } from '../../EntityFields'; +import { UUIDField, StringField, StrictEnumField } from '../../EntityFields'; import EntityPrivacyPolicy from '../../EntityPrivacyPolicy'; import ViewerContext from '../../ViewerContext'; import { successfulResults, failedResults } from '../../entityUtils'; @@ -98,8 +98,9 @@ const testEntityConfiguration = new EntityConfiguration({ common_other_field: new StringField({ columnName: 'common_other_field', }), - entity_type: new EnumField({ + entity_type: new StrictEnumField({ columnName: 'entity_type', + enum: EntityType, }), }, databaseAdapterFlavor: 'postgres',