From c4fa36402b33f2e0ec3b6ec8ba30dac108a147d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20M?= Date: Tue, 17 Oct 2023 17:57:02 +0200 Subject: [PATCH] feat: add default filter types (#2087) * feat: add default filter types * fix: fields doesn't need to be a function --- .../input/big-float-filter.type.ts | 22 +++++++++ .../input/big-int-filter.type.ts | 22 +++++++++ .../graphql-types/input/date-filter.type.ts | 19 ++++++++ .../input/datetime-filter.type.ts | 19 ++++++++ .../input/filter-is-enum-filter.type.ts | 9 ++++ .../graphql-types/input/float-filter.type.ts | 22 +++++++++ .../graphql-types/input/int-filter.type.ts | 22 +++++++++ .../graphql-types/input/money-filter.type.ts | 12 +++++ .../graphql-types/input/string-filter.type.ts | 27 +++++++++++ .../graphql-types/input/time-filter.type.ts | 19 ++++++++ .../graphql-types/input/url-filter.type.ts | 11 +++++ .../graphql-types/input/uuid-filter.type.ts | 15 ++++++ .../object/page-into.type.ts} | 0 .../graphql-types/scalars/big-float.scalar.ts | 21 +++++++++ .../graphql-types/scalars/big-int.scalar.ts | 20 ++++++++ .../graphql-types/scalars/date.scalar.ts | 20 ++++++++ .../graphql-types/scalars/datetime.scalar.ts | 38 +++++++++++++++ .../graphql-types/scalars/time.scalar.ts | 24 ++++++++++ .../graphql-types/scalars/uuid.scalar.ts | 27 +++++++++++ .../generate-connection-type.spec.ts | 2 +- .../map-column-type-to-filter-type.spec.ts | 47 +++++++++++++++++++ .../utils/generate-connection-type.util.ts | 2 +- .../map-column-type-to-filter-type.util.ts | 39 +++++++++++++++ 23 files changed, 457 insertions(+), 2 deletions(-) create mode 100644 server/src/tenant/schema-builder/graphql-types/input/big-float-filter.type.ts create mode 100644 server/src/tenant/schema-builder/graphql-types/input/big-int-filter.type.ts create mode 100644 server/src/tenant/schema-builder/graphql-types/input/date-filter.type.ts create mode 100644 server/src/tenant/schema-builder/graphql-types/input/datetime-filter.type.ts create mode 100644 server/src/tenant/schema-builder/graphql-types/input/filter-is-enum-filter.type.ts create mode 100644 server/src/tenant/schema-builder/graphql-types/input/float-filter.type.ts create mode 100644 server/src/tenant/schema-builder/graphql-types/input/int-filter.type.ts create mode 100644 server/src/tenant/schema-builder/graphql-types/input/money-filter.type.ts create mode 100644 server/src/tenant/schema-builder/graphql-types/input/string-filter.type.ts create mode 100644 server/src/tenant/schema-builder/graphql-types/input/time-filter.type.ts create mode 100644 server/src/tenant/schema-builder/graphql-types/input/url-filter.type.ts create mode 100644 server/src/tenant/schema-builder/graphql-types/input/uuid-filter.type.ts rename server/src/tenant/schema-builder/{utils/page-into-type.util.ts => graphql-types/object/page-into.type.ts} (100%) create mode 100644 server/src/tenant/schema-builder/graphql-types/scalars/big-float.scalar.ts create mode 100644 server/src/tenant/schema-builder/graphql-types/scalars/big-int.scalar.ts create mode 100644 server/src/tenant/schema-builder/graphql-types/scalars/date.scalar.ts create mode 100644 server/src/tenant/schema-builder/graphql-types/scalars/datetime.scalar.ts create mode 100644 server/src/tenant/schema-builder/graphql-types/scalars/time.scalar.ts create mode 100644 server/src/tenant/schema-builder/graphql-types/scalars/uuid.scalar.ts create mode 100644 server/src/tenant/schema-builder/utils/__tests__/map-column-type-to-filter-type.spec.ts create mode 100644 server/src/tenant/schema-builder/utils/map-column-type-to-filter-type.util.ts diff --git a/server/src/tenant/schema-builder/graphql-types/input/big-float-filter.type.ts b/server/src/tenant/schema-builder/graphql-types/input/big-float-filter.type.ts new file mode 100644 index 000000000..89de6263c --- /dev/null +++ b/server/src/tenant/schema-builder/graphql-types/input/big-float-filter.type.ts @@ -0,0 +1,22 @@ +import { + GraphQLInputObjectType, + GraphQLList, + GraphQLNonNull, + GraphQLFloat, +} from 'graphql'; + +import { FilterIsEnumType } from './filter-is-enum-filter.type'; + +export const BigFloatFilterType = new GraphQLInputObjectType({ + name: 'BigFloatType', + fields: { + eq: { type: GraphQLFloat }, + gt: { type: GraphQLFloat }, + gte: { type: GraphQLFloat }, + in: { type: new GraphQLList(new GraphQLNonNull(GraphQLFloat)) }, + lt: { type: GraphQLFloat }, + lte: { type: GraphQLFloat }, + neq: { type: GraphQLFloat }, + is: { type: FilterIsEnumType }, + }, +}); diff --git a/server/src/tenant/schema-builder/graphql-types/input/big-int-filter.type.ts b/server/src/tenant/schema-builder/graphql-types/input/big-int-filter.type.ts new file mode 100644 index 000000000..0d30efb58 --- /dev/null +++ b/server/src/tenant/schema-builder/graphql-types/input/big-int-filter.type.ts @@ -0,0 +1,22 @@ +import { + GraphQLInputObjectType, + GraphQLList, + GraphQLNonNull, + GraphQLInt, +} from 'graphql'; + +import { FilterIsEnumType } from './filter-is-enum-filter.type'; + +export const BigIntFilterType = new GraphQLInputObjectType({ + name: 'BigIntFilter', + fields: { + eq: { type: GraphQLInt }, + gt: { type: GraphQLInt }, + gte: { type: GraphQLInt }, + in: { type: new GraphQLList(new GraphQLNonNull(GraphQLInt)) }, + lt: { type: GraphQLInt }, + lte: { type: GraphQLInt }, + neq: { type: GraphQLInt }, + is: { type: FilterIsEnumType }, + }, +}); diff --git a/server/src/tenant/schema-builder/graphql-types/input/date-filter.type.ts b/server/src/tenant/schema-builder/graphql-types/input/date-filter.type.ts new file mode 100644 index 000000000..d89d0d46a --- /dev/null +++ b/server/src/tenant/schema-builder/graphql-types/input/date-filter.type.ts @@ -0,0 +1,19 @@ +import { GraphQLInputObjectType, GraphQLList, GraphQLNonNull } from 'graphql'; + +import { DateScalarType } from 'src/tenant/schema-builder/graphql-types/scalars/date.scalar'; + +import { FilterIsEnumType } from './filter-is-enum-filter.type'; + +export const DateFilterType = new GraphQLInputObjectType({ + name: 'DateFilter', + fields: { + eq: { type: DateScalarType }, + gt: { type: DateScalarType }, + gte: { type: DateScalarType }, + in: { type: new GraphQLList(new GraphQLNonNull(DateScalarType)) }, + lt: { type: DateScalarType }, + lte: { type: DateScalarType }, + neq: { type: DateScalarType }, + is: { type: FilterIsEnumType }, + }, +}); diff --git a/server/src/tenant/schema-builder/graphql-types/input/datetime-filter.type.ts b/server/src/tenant/schema-builder/graphql-types/input/datetime-filter.type.ts new file mode 100644 index 000000000..2f3595e27 --- /dev/null +++ b/server/src/tenant/schema-builder/graphql-types/input/datetime-filter.type.ts @@ -0,0 +1,19 @@ +import { GraphQLInputObjectType, GraphQLList, GraphQLNonNull } from 'graphql'; + +import { DatetimeScalarType } from 'src/tenant/schema-builder/graphql-types/scalars/datetime.scalar'; + +import { FilterIsEnumType } from './filter-is-enum-filter.type'; + +export const DatetimeFilterInputType = new GraphQLInputObjectType({ + name: 'DatetimeFilter', + fields: { + eq: { type: DatetimeScalarType }, + gt: { type: DatetimeScalarType }, + gte: { type: DatetimeScalarType }, + in: { type: new GraphQLList(new GraphQLNonNull(DatetimeScalarType)) }, + lt: { type: DatetimeScalarType }, + lte: { type: DatetimeScalarType }, + neq: { type: DatetimeScalarType }, + is: { type: FilterIsEnumType }, + }, +}); diff --git a/server/src/tenant/schema-builder/graphql-types/input/filter-is-enum-filter.type.ts b/server/src/tenant/schema-builder/graphql-types/input/filter-is-enum-filter.type.ts new file mode 100644 index 000000000..3e61b0da5 --- /dev/null +++ b/server/src/tenant/schema-builder/graphql-types/input/filter-is-enum-filter.type.ts @@ -0,0 +1,9 @@ +import { GraphQLEnumType } from 'graphql'; + +export const FilterIsEnumType = new GraphQLEnumType({ + name: 'FilterIs', + values: { + PENDING: { value: 'PENDING' }, + RELEASED: { value: 'RELEASED' }, + }, +}); diff --git a/server/src/tenant/schema-builder/graphql-types/input/float-filter.type.ts b/server/src/tenant/schema-builder/graphql-types/input/float-filter.type.ts new file mode 100644 index 000000000..990f5dd40 --- /dev/null +++ b/server/src/tenant/schema-builder/graphql-types/input/float-filter.type.ts @@ -0,0 +1,22 @@ +import { + GraphQLInputObjectType, + GraphQLFloat, + GraphQLList, + GraphQLNonNull, +} from 'graphql'; + +import { FilterIsEnumType } from './filter-is-enum-filter.type'; + +export const FloatFilter = new GraphQLInputObjectType({ + name: 'FloatFilter', + fields: { + eq: { type: GraphQLFloat }, + gt: { type: GraphQLFloat }, + gte: { type: GraphQLFloat }, + in: { type: new GraphQLList(new GraphQLNonNull(GraphQLFloat)) }, + lt: { type: GraphQLFloat }, + lte: { type: GraphQLFloat }, + neq: { type: GraphQLFloat }, + is: { type: FilterIsEnumType }, + }, +}); diff --git a/server/src/tenant/schema-builder/graphql-types/input/int-filter.type.ts b/server/src/tenant/schema-builder/graphql-types/input/int-filter.type.ts new file mode 100644 index 000000000..162840288 --- /dev/null +++ b/server/src/tenant/schema-builder/graphql-types/input/int-filter.type.ts @@ -0,0 +1,22 @@ +import { + GraphQLInputObjectType, + GraphQLList, + GraphQLNonNull, + GraphQLInt, +} from 'graphql'; + +import { FilterIsEnumType } from './filter-is-enum-filter.type'; + +export const IntFilter = new GraphQLInputObjectType({ + name: 'IntFilter', + fields: { + eq: { type: GraphQLInt }, + gt: { type: GraphQLInt }, + gte: { type: GraphQLInt }, + in: { type: new GraphQLList(new GraphQLNonNull(GraphQLInt)) }, + lt: { type: GraphQLInt }, + lte: { type: GraphQLInt }, + neq: { type: GraphQLInt }, + is: { type: FilterIsEnumType }, + }, +}); diff --git a/server/src/tenant/schema-builder/graphql-types/input/money-filter.type.ts b/server/src/tenant/schema-builder/graphql-types/input/money-filter.type.ts new file mode 100644 index 000000000..a3baf0665 --- /dev/null +++ b/server/src/tenant/schema-builder/graphql-types/input/money-filter.type.ts @@ -0,0 +1,12 @@ +import { GraphQLInputObjectType } from 'graphql'; + +import { StringFilterType } from 'src/tenant/schema-builder/graphql-types/input/string-filter.type'; +import { IntFilter } from 'src/tenant/schema-builder/graphql-types/input/int-filter.type'; + +export const MoneyFilterType = new GraphQLInputObjectType({ + name: 'MoneyFilter', + fields: { + amount: { type: IntFilter }, + currency: { type: StringFilterType }, + }, +}); diff --git a/server/src/tenant/schema-builder/graphql-types/input/string-filter.type.ts b/server/src/tenant/schema-builder/graphql-types/input/string-filter.type.ts new file mode 100644 index 000000000..961753b22 --- /dev/null +++ b/server/src/tenant/schema-builder/graphql-types/input/string-filter.type.ts @@ -0,0 +1,27 @@ +import { + GraphQLInputObjectType, + GraphQLList, + GraphQLNonNull, + GraphQLString, +} from 'graphql'; + +import { FilterIsEnumType } from './filter-is-enum-filter.type'; + +export const StringFilterType = new GraphQLInputObjectType({ + name: 'StringFilter', + fields: { + eq: { type: GraphQLString }, + gt: { type: GraphQLString }, + gte: { type: GraphQLString }, + in: { type: new GraphQLList(new GraphQLNonNull(GraphQLString)) }, + lt: { type: GraphQLString }, + lte: { type: GraphQLString }, + neq: { type: GraphQLString }, + is: { type: FilterIsEnumType }, + startsWith: { type: GraphQLString }, + like: { type: GraphQLString }, + ilike: { type: GraphQLString }, + regex: { type: GraphQLString }, + iregex: { type: GraphQLString }, + }, +}); diff --git a/server/src/tenant/schema-builder/graphql-types/input/time-filter.type.ts b/server/src/tenant/schema-builder/graphql-types/input/time-filter.type.ts new file mode 100644 index 000000000..645949a80 --- /dev/null +++ b/server/src/tenant/schema-builder/graphql-types/input/time-filter.type.ts @@ -0,0 +1,19 @@ +import { GraphQLInputObjectType, GraphQLList, GraphQLNonNull } from 'graphql'; + +import { TimeScalarType } from 'src/tenant/schema-builder/graphql-types/scalars/time.scalar'; + +import { FilterIsEnumType } from './filter-is-enum-filter.type'; + +export const TimeFilter = new GraphQLInputObjectType({ + name: 'TimeFilter', + fields: { + eq: { type: TimeScalarType }, + gt: { type: TimeScalarType }, + gte: { type: TimeScalarType }, + in: { type: new GraphQLList(new GraphQLNonNull(TimeScalarType)) }, + lt: { type: TimeScalarType }, + lte: { type: TimeScalarType }, + neq: { type: TimeScalarType }, + is: { type: FilterIsEnumType }, + }, +}); diff --git a/server/src/tenant/schema-builder/graphql-types/input/url-filter.type.ts b/server/src/tenant/schema-builder/graphql-types/input/url-filter.type.ts new file mode 100644 index 000000000..e89cd3742 --- /dev/null +++ b/server/src/tenant/schema-builder/graphql-types/input/url-filter.type.ts @@ -0,0 +1,11 @@ +import { GraphQLInputObjectType } from 'graphql'; + +import { StringFilterType } from 'src/tenant/schema-builder/graphql-types/input/string-filter.type'; + +export const UrlFilterType = new GraphQLInputObjectType({ + name: 'UrlFilter', + fields: { + text: { type: StringFilterType }, + link: { type: StringFilterType }, + }, +}); diff --git a/server/src/tenant/schema-builder/graphql-types/input/uuid-filter.type.ts b/server/src/tenant/schema-builder/graphql-types/input/uuid-filter.type.ts new file mode 100644 index 000000000..d81f7601a --- /dev/null +++ b/server/src/tenant/schema-builder/graphql-types/input/uuid-filter.type.ts @@ -0,0 +1,15 @@ +import { GraphQLInputObjectType, GraphQLList } from 'graphql'; + +import { UUIDScalarType } from 'src/tenant/schema-builder/graphql-types/scalars/uuid.scalar'; + +import { FilterIsEnumType } from './filter-is-enum-filter.type'; + +export const UUIDFilterType = new GraphQLInputObjectType({ + name: 'UUIDFilter', + fields: { + eq: { type: UUIDScalarType }, + in: { type: new GraphQLList(UUIDScalarType) }, + neq: { type: UUIDScalarType }, + is: { type: FilterIsEnumType }, + }, +}); diff --git a/server/src/tenant/schema-builder/utils/page-into-type.util.ts b/server/src/tenant/schema-builder/graphql-types/object/page-into.type.ts similarity index 100% rename from server/src/tenant/schema-builder/utils/page-into-type.util.ts rename to server/src/tenant/schema-builder/graphql-types/object/page-into.type.ts diff --git a/server/src/tenant/schema-builder/graphql-types/scalars/big-float.scalar.ts b/server/src/tenant/schema-builder/graphql-types/scalars/big-float.scalar.ts new file mode 100644 index 000000000..0bccac1ee --- /dev/null +++ b/server/src/tenant/schema-builder/graphql-types/scalars/big-float.scalar.ts @@ -0,0 +1,21 @@ +import { GraphQLScalarType } from 'graphql'; +import { Kind } from 'graphql/language'; + +export const BigFloatScalarType = new GraphQLScalarType({ + name: 'BigFloat', + description: + 'A custom scalar type for representing big floating point numbers', + serialize(value: number): string { + return String(value); + }, + parseValue(value: string): number { + return parseFloat(value); + }, + parseLiteral(ast): number | null { + if (ast.kind === Kind.FLOAT) { + return parseFloat(ast.value); + } + + return null; + }, +}); diff --git a/server/src/tenant/schema-builder/graphql-types/scalars/big-int.scalar.ts b/server/src/tenant/schema-builder/graphql-types/scalars/big-int.scalar.ts new file mode 100644 index 000000000..cffbdc6d5 --- /dev/null +++ b/server/src/tenant/schema-builder/graphql-types/scalars/big-int.scalar.ts @@ -0,0 +1,20 @@ +import { GraphQLScalarType } from 'graphql'; + +export const BigIntScalarType = new GraphQLScalarType({ + name: 'BigInt', + description: + 'The `BigInt` scalar type represents non-fractional signed whole numeric values.', + serialize(value: bigint): string { + return value.toString(); + }, + parseValue(value: string): bigint { + return BigInt(value); + }, + parseLiteral(ast): bigint | null { + if (ast.kind === 'IntValue') { + return BigInt(ast.value); + } + + return null; + }, +}); diff --git a/server/src/tenant/schema-builder/graphql-types/scalars/date.scalar.ts b/server/src/tenant/schema-builder/graphql-types/scalars/date.scalar.ts new file mode 100644 index 000000000..16aeabc42 --- /dev/null +++ b/server/src/tenant/schema-builder/graphql-types/scalars/date.scalar.ts @@ -0,0 +1,20 @@ +import { GraphQLScalarType } from 'graphql'; +import { Kind } from 'graphql/language'; + +export const DateScalarType = new GraphQLScalarType({ + name: 'Date', + description: 'Date custom scalar type', + serialize(value: Date): number { + return value.getTime(); + }, + parseValue(value: number): Date { + return new Date(value); + }, + parseLiteral(ast): Date | null { + if (ast.kind === Kind.INT) { + return new Date(parseInt(ast.value, 10)); + } + + return null; + }, +}); diff --git a/server/src/tenant/schema-builder/graphql-types/scalars/datetime.scalar.ts b/server/src/tenant/schema-builder/graphql-types/scalars/datetime.scalar.ts new file mode 100644 index 000000000..05a081f22 --- /dev/null +++ b/server/src/tenant/schema-builder/graphql-types/scalars/datetime.scalar.ts @@ -0,0 +1,38 @@ +import { GraphQLScalarType } from 'graphql'; +import { Kind } from 'graphql/language'; + +export const DatetimeScalarType = new GraphQLScalarType({ + name: 'Datetime', + description: 'A custom scalar that represents a datetime in ISO format', + serialize(value: string): string { + const date = new Date(value); + + if (isNaN(date.getTime())) { + throw new Error('Invalid date format, expected ISO date string'); + } + + return date.toISOString(); + }, + parseValue(value: string): Date { + const date = new Date(value); + + if (isNaN(date.getTime())) { + throw new Error('Invalid date format, expected ISO date string'); + } + + return date; + }, + parseLiteral(ast): Date { + if (ast.kind !== Kind.STRING) { + throw new Error('Invalid date format, expected ISO date string'); + } + + const date = new Date(ast.value); + + if (isNaN(date.getTime())) { + throw new Error('Invalid date format, expected ISO date string'); + } + + return date; + }, +}); diff --git a/server/src/tenant/schema-builder/graphql-types/scalars/time.scalar.ts b/server/src/tenant/schema-builder/graphql-types/scalars/time.scalar.ts new file mode 100644 index 000000000..55f3811fa --- /dev/null +++ b/server/src/tenant/schema-builder/graphql-types/scalars/time.scalar.ts @@ -0,0 +1,24 @@ +import { GraphQLScalarType } from 'graphql'; +import { IntValueNode, Kind } from 'graphql/language'; + +export const TimeScalarType = new GraphQLScalarType({ + name: 'Time', + description: 'Time custom scalar type', + serialize(value: Date): number { + return value.getTime(); + }, + parseValue(value: number): Date { + return new Date(value); + }, + parseLiteral(ast): Date { + if (ast.kind === Kind.INT) { + const intAst = ast as IntValueNode; + + if (typeof intAst.value === 'number') { + return new Date(intAst.value); + } + throw new Error(`Invalid timestamp value: ${ast.value}`); + } + throw new Error(`Invalid AST kind: ${ast.kind}`); + }, +}); diff --git a/server/src/tenant/schema-builder/graphql-types/scalars/uuid.scalar.ts b/server/src/tenant/schema-builder/graphql-types/scalars/uuid.scalar.ts new file mode 100644 index 000000000..328d3335a --- /dev/null +++ b/server/src/tenant/schema-builder/graphql-types/scalars/uuid.scalar.ts @@ -0,0 +1,27 @@ +import { GraphQLScalarType, Kind } from 'graphql'; + +export const UUIDScalarType = new GraphQLScalarType({ + name: 'UUID', + description: 'A UUID scalar type', + serialize(value: string): string { + if (typeof value !== 'string') { + throw new Error('UUID must be a string'); + } + + return value; + }, + parseValue(value: string): string { + if (typeof value !== 'string') { + throw new Error('UUID must be a string'); + } + + return value; + }, + parseLiteral(ast): string { + if (ast.kind !== Kind.STRING) { + throw new Error('UUID must be a string'); + } + + return ast.value; + }, +}); diff --git a/server/src/tenant/schema-builder/utils/__tests__/generate-connection-type.spec.ts b/server/src/tenant/schema-builder/utils/__tests__/generate-connection-type.spec.ts index b68dba2be..4c7f45df4 100644 --- a/server/src/tenant/schema-builder/utils/__tests__/generate-connection-type.spec.ts +++ b/server/src/tenant/schema-builder/utils/__tests__/generate-connection-type.spec.ts @@ -5,7 +5,7 @@ import { GraphQLString, } from 'graphql'; -import { PageInfoType } from 'src/tenant/schema-builder/utils/page-into-type.util'; +import { PageInfoType } from 'src/tenant/schema-builder/graphql-types/object/page-into.type'; import { generateConnectionType } from 'src/tenant/schema-builder/utils/generate-connection-type.util'; describe('generateConnectionType', () => { diff --git a/server/src/tenant/schema-builder/utils/__tests__/map-column-type-to-filter-type.spec.ts b/server/src/tenant/schema-builder/utils/__tests__/map-column-type-to-filter-type.spec.ts new file mode 100644 index 000000000..244dc8a6f --- /dev/null +++ b/server/src/tenant/schema-builder/utils/__tests__/map-column-type-to-filter-type.spec.ts @@ -0,0 +1,47 @@ +import { GraphQLBoolean } from 'graphql'; + +import { mapColumnTypeToFilterType } from 'src/tenant/schema-builder/utils/map-column-type-to-filter-type.util'; // Update with the actual path +import { FieldMetadata } from 'src/metadata/field-metadata/field-metadata.entity'; +import { UUIDFilterType } from 'src/tenant/schema-builder/graphql-types/input/uuid-filter.type'; +import { StringFilterType } from 'src/tenant/schema-builder/graphql-types/input/string-filter.type'; +import { DateFilterType } from 'src/tenant/schema-builder/graphql-types/input/date-filter.type'; +import { IntFilter } from 'src/tenant/schema-builder/graphql-types/input/int-filter.type'; +import { UrlFilterType } from 'src/tenant/schema-builder/graphql-types/input/url-filter.type'; +import { MoneyFilterType } from 'src/tenant/schema-builder/graphql-types/input/money-filter.type'; + +describe('mapColumnTypeToFilterType', () => { + it('should map column types to corresponding filter types', () => { + const fields: { column: FieldMetadata; expected: any }[] = [ + { column: { type: 'uuid' } as FieldMetadata, expected: UUIDFilterType }, + { column: { type: 'text' } as FieldMetadata, expected: StringFilterType }, + { + column: { type: 'phone' } as FieldMetadata, + expected: StringFilterType, + }, + { + column: { type: 'email' } as FieldMetadata, + expected: StringFilterType, + }, + { column: { type: 'date' } as FieldMetadata, expected: DateFilterType }, + { + column: { type: 'boolean' } as FieldMetadata, + expected: GraphQLBoolean, + }, + { column: { type: 'number' } as FieldMetadata, expected: IntFilter }, + { column: { type: 'url' } as FieldMetadata, expected: UrlFilterType }, + { column: { type: 'money' } as FieldMetadata, expected: MoneyFilterType }, + ]; + + fields.forEach((field) => { + expect(mapColumnTypeToFilterType(field.column)).toBe(field.expected); + }); + }); + + it('should throw an error for unimplemented filter types', () => { + const column = { type: 'enum' } as FieldMetadata; + + expect(() => mapColumnTypeToFilterType(column)).toThrowError( + 'enum filter type not yet implemented', + ); + }); +}); diff --git a/server/src/tenant/schema-builder/utils/generate-connection-type.util.ts b/server/src/tenant/schema-builder/utils/generate-connection-type.util.ts index 759cfbed8..bba542888 100644 --- a/server/src/tenant/schema-builder/utils/generate-connection-type.util.ts +++ b/server/src/tenant/schema-builder/utils/generate-connection-type.util.ts @@ -1,6 +1,6 @@ import { GraphQLList, GraphQLNonNull, GraphQLObjectType } from 'graphql'; -import { PageInfoType } from './page-into-type.util'; +import { PageInfoType } from 'src/tenant/schema-builder/graphql-types/object/page-into.type'; /** * Generate a GraphQL connection type based on the EdgeType. diff --git a/server/src/tenant/schema-builder/utils/map-column-type-to-filter-type.util.ts b/server/src/tenant/schema-builder/utils/map-column-type-to-filter-type.util.ts new file mode 100644 index 000000000..6c88b79fb --- /dev/null +++ b/server/src/tenant/schema-builder/utils/map-column-type-to-filter-type.util.ts @@ -0,0 +1,39 @@ +import { GraphQLBoolean } from 'graphql'; + +import { FieldMetadata } from 'src/metadata/field-metadata/field-metadata.entity'; +import { UUIDFilterType } from 'src/tenant/schema-builder/graphql-types/input/uuid-filter.type'; +import { StringFilterType } from 'src/tenant/schema-builder/graphql-types/input/string-filter.type'; +import { DateFilterType } from 'src/tenant/schema-builder/graphql-types/input/date-filter.type'; +import { IntFilter } from 'src/tenant/schema-builder/graphql-types/input/int-filter.type'; +import { UrlFilterType } from 'src/tenant/schema-builder/graphql-types/input/url-filter.type'; +import { MoneyFilterType } from 'src/tenant/schema-builder/graphql-types/input/money-filter.type'; + +/** + * Map the column type from field-metadata to its corresponding filter type. + * @param columnType Type of the column in the database. + */ +export const mapColumnTypeToFilterType = (column: FieldMetadata) => { + switch (column.type) { + case 'uuid': + return UUIDFilterType; + case 'text': + case 'phone': + case 'email': + return StringFilterType; + case 'date': + return DateFilterType; + case 'boolean': + return GraphQLBoolean; + case 'number': + return IntFilter; + case 'url': { + return UrlFilterType; + } + case 'money': { + return MoneyFilterType; + } + case 'enum': + default: + throw new Error(`${column.type} filter type not yet implemented`); + } +};