diff --git a/packages/twenty-apps/examples/postcard/src/__tests__/schema.integration-test.ts b/packages/twenty-apps/examples/postcard/src/__tests__/schema.integration-test.ts index 2bc6e07aed..c59422465d 100644 --- a/packages/twenty-apps/examples/postcard/src/__tests__/schema.integration-test.ts +++ b/packages/twenty-apps/examples/postcard/src/__tests__/schema.integration-test.ts @@ -25,12 +25,12 @@ describe('PostCard object', () => { const { objects } = await client.query({ objects: { - __args: { paging: { first: 50 } }, + __args: { paging: { first: 50 }, filter: {} }, edges: { node: { nameSingular: true, fields: { - __args: { paging: { first: 500 } }, + __args: { paging: { first: 500 }, filter: {} }, edges: { node: { name: true } }, }, }, @@ -39,13 +39,14 @@ describe('PostCard object', () => { }); const obj = objects.edges - .map((e: { node: { nameSingular: string } }) => e.node) + .map((e) => e.node) .find((n: { nameSingular: string }) => n.nameSingular === 'postCard'); expect(obj).toBeDefined(); const names = obj!.fields.edges.map( (e: { node: { name: string } }) => e.node.name, ); + console.log('names', names); expect(names).toContain('name'); expect(names).toContain('content'); expect(names).toContain('status'); diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/graphql-types/input/date-time-filter.input-type.ts b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/graphql-types/input/date-time-filter.input-type.ts new file mode 100644 index 0000000000..067efd8ddd --- /dev/null +++ b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/graphql-types/input/date-time-filter.input-type.ts @@ -0,0 +1,19 @@ +import { GraphQLISODateTime } from '@nestjs/graphql'; + +import { GraphQLInputObjectType, GraphQLList, GraphQLNonNull } from 'graphql'; + +import { FilterIs } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/input/filter-is.input-type'; + +export const DateTimeFilterType = new GraphQLInputObjectType({ + name: 'DateTimeFilter', + fields: { + eq: { type: GraphQLISODateTime }, + gt: { type: GraphQLISODateTime }, + gte: { type: GraphQLISODateTime }, + in: { type: new GraphQLList(new GraphQLNonNull(GraphQLISODateTime)) }, + lt: { type: GraphQLISODateTime }, + lte: { type: GraphQLISODateTime }, + neq: { type: GraphQLISODateTime }, + is: { type: FilterIs }, + }, +}); diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/graphql-types/input/index.ts b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/graphql-types/input/index.ts index cb0e63832e..f9f468c28e 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/graphql-types/input/index.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/graphql-types/input/index.ts @@ -3,6 +3,7 @@ export * from './big-float-filter.input-type'; export * from './big-int-filter.input-type'; export * from './boolean-filter.input-type'; export * from './date-filter.input-type'; +export * from './date-time-filter.input-type'; export * from './float-filter.input-type'; export * from './int-filter.input-type'; export * from './raw-json-filter.input-type'; diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/services/__tests__/type-mapper.service.spec.ts b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/services/__tests__/type-mapper.service.spec.ts new file mode 100644 index 0000000000..6fe0f9c8dd --- /dev/null +++ b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/services/__tests__/type-mapper.service.spec.ts @@ -0,0 +1,54 @@ +import { isInputObjectType } from 'graphql'; +import { FieldMetadataType } from 'twenty-shared/types'; + +import { TypeMapperService } from 'src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service'; + +describe('TypeMapperService', () => { + const typeMapperService = new TypeMapperService(); + + describe('mapToFilterType', () => { + it('should map DATE_TIME to a DateTimeFilter input object with operators', () => { + const filterType = typeMapperService.mapToFilterType( + FieldMetadataType.DATE_TIME, + ); + + if (!isInputObjectType(filterType)) { + throw new Error('Expected DATE_TIME filter type to be an input object'); + } + + expect(filterType.name).toBe('DateTimeFilter'); + + const fields = filterType.getFields(); + + expect(Object.keys(fields).sort()).toEqual([ + 'eq', + 'gt', + 'gte', + 'in', + 'is', + 'lt', + 'lte', + 'neq', + ]); + + for (const operator of ['eq', 'gt', 'gte', 'lt', 'lte', 'neq']) { + expect(fields[operator].type.toString()).toBe('DateTime'); + } + + expect(fields.in.type.toString()).toBe('[DateTime!]'); + expect(fields.is.type.toString()).toBe('FilterIs'); + }); + + it('should map DATE to a DateFilter input object', () => { + const filterType = typeMapperService.mapToFilterType( + FieldMetadataType.DATE, + ); + + if (!isInputObjectType(filterType)) { + throw new Error('Expected DATE filter type to be an input object'); + } + + expect(filterType.name).toBe('DateFilter'); + }); + }); +}); diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service.ts b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service.ts index 3afa5cc394..24df849681 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service.ts @@ -27,6 +27,7 @@ import { BigFloatFilterType, BooleanFilterType, DateFilterType, + DateTimeFilterType, FloatFilterType, RawJsonFilterType, StringFilterType, @@ -163,7 +164,7 @@ export class TypeMapperService { >([ [FieldMetadataType.UUID, UUIDFilterType], [FieldMetadataType.TEXT, StringFilterType], - [FieldMetadataType.DATE_TIME, GraphQLISODateTime], + [FieldMetadataType.DATE_TIME, DateTimeFilterType], [FieldMetadataType.DATE, DateFilterType], [FieldMetadataType.BOOLEAN, BooleanFilterType], [