From 7b9175a4a44b7ed66b94b37eca353bda161d4b38 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Fri, 10 Nov 2023 11:48:44 +0100 Subject: [PATCH] Revert "Convert metadata tables to camelCase" (#2419) Revert "Convert metadata tables to camelCase (#2400)" This reverts commit 1cf08c797fbcc50539cc60ca74dc260a0dbe220c. --- front/src/generated-metadata/graphql.ts | 54 +------ front/src/generated/graphql.tsx | 39 ----- .../ActivityAssigneeEditableField.tsx | 2 +- .../components/ActivityEditorDateField.tsx | 2 +- .../tasks/hooks/useCurrentUserDueTaskCount.ts | 2 +- .../companies/components/CompanyBoardCard.tsx | 6 +- .../companiesAvailableFieldDefinitions.tsx | 24 +-- .../metadata/components/RecordShowPage.tsx | 8 +- .../metadata/hooks/useCreateOneObject.ts | 1 - .../metadata/hooks/useFindOneObject.ts | 10 +- .../metadata/hooks/useMetadataField.ts | 10 +- .../hooks/useUpdateOneMetadataField.ts | 6 +- .../formatMetadataFieldAsColumnDefinition.ts | 2 +- .../formatMetadataFieldAsFilterDefinition.ts | 2 +- .../formatMetadataFieldAsSortDefinition.ts | 2 +- .../utils/generateFindOneCustomObjectQuery.ts | 4 +- .../peopleAvailableFieldDefinitions.tsx | 18 +-- .../pipelineAvailableFieldDefinitions.tsx | 8 +- .../components/SettingsObjectFieldPreview.tsx | 2 +- front/src/modules/types/AppPath.ts | 2 +- .../layout/board/hooks/useBoardCardFields.ts | 2 +- .../boardCardFieldsByKeyScopedSelector.ts | 2 +- .../hiddenBoardCardFieldsScopedSelector.ts | 4 +- ...savedBoardCardFieldsByKeyFamilySelector.ts | 2 +- .../field/hooks/useFieldInitialValue.ts | 2 +- .../ui/object/field/hooks/useIsFieldEmpty.ts | 2 +- .../__stories__/DateFieldDisplay.stories.tsx | 2 +- .../DoubleTextFieldDisplay.stories.tsx | 2 +- .../__stories__/EmailFieldDisplay.stories.tsx | 2 +- .../__stories__/MoneyFieldDisplay.stories.tsx | 2 +- .../NumberFieldDisplay.stories.tsx | 2 +- .../__stories__/PhoneFieldDisplay.stories.tsx | 2 +- .../__stories__/TextFieldDisplay.stories.tsx | 2 +- .../__stories__/URLFieldDisplay.stories.tsx | 2 +- .../__stories__/BooleanFieldInput.stories.tsx | 2 +- .../__stories__/ChipFieldInput.stories.tsx | 2 +- .../__stories__/DateFieldInput.stories.tsx | 2 +- .../DoubleTextChipFieldInput.stories.tsx | 2 +- .../DoubleTextFieldInput.stories.tsx | 2 +- .../__stories__/EmailFieldInput.stories.tsx | 2 +- .../__stories__/MoneyFieldInput.stories.tsx | 2 +- .../__stories__/NumberFieldInput.stories.tsx | 2 +- .../__stories__/PhoneFieldInput.stories.tsx | 2 +- .../ProbabilityFieldInput.stories.tsx | 2 +- .../RelationFieldInput.stories.tsx | 2 +- .../__stories__/TextFieldInput.stories.tsx | 2 +- .../__stories__/URLFieldInput.stories.tsx | 2 +- .../entityFieldInitialValueFamilyState.ts | 2 +- .../isEntityFieldEmptyFamilySelector.ts | 2 +- .../ui/object/field/types/FieldDefinition.ts | 2 +- .../ObjectFilterDropdownDateSearchInput.tsx | 2 +- ...ObjectFilterDropdownEntitySearchSelect.tsx | 4 +- .../ObjectFilterDropdownNumberSearchInput.tsx | 2 +- .../ObjectFilterDropdownOperandSelect.tsx | 2 +- .../ObjectFilterDropdownTextSearchInput.tsx | 2 +- .../object-filter-dropdown/types/Filter.ts | 2 +- .../types/FilterDefinition.ts | 2 +- .../types/FilterDefinitionByEntity.ts | 2 +- .../utils/turnFilterIntoWhereClause.ts | 18 +-- .../utils/turnFiltersIntoWhereClauseV2.ts | 4 +- .../components/ObjectSortDropdownButton.tsx | 2 +- .../object/object-sort-dropdown/types/Sort.ts | 2 +- .../types/SortDefinition.ts | 2 +- .../object-sort-dropdown/utils/helpers.ts | 2 +- .../utils/turnSortsIntoOrderByV2.ts | 4 +- .../components/ColumnHeadWithDropdown.tsx | 4 +- .../RecordTableColumnDropdownMenu.tsx | 2 +- .../components/RecordTableHeader.tsx | 25 ++- .../RecordTableHeaderPlusButtonContent.tsx | 2 +- .../components/RecordTableRow.tsx | 2 +- .../record-table/hooks/useTableColumns.ts | 10 +- .../record-table-cell/hooks/useTableCell.ts | 2 +- .../hiddenTableColumnsScopedSelector.ts | 4 +- .../savedTableColumnsByKeyFamilySelector.ts | 5 +- .../tableColumnsByKeyScopedSelector.ts | 5 +- .../visibleTableColumnsScopedSelector.ts | 5 +- .../views/components/ViewBarDetails.tsx | 12 +- .../views/components/ViewBarEffect.tsx | 11 +- .../ViewFieldsVisibilityDropdownSection.tsx | 8 +- .../views/hooks/internal/useViewFields.ts | 16 +- .../views/hooks/internal/useViewFilters.ts | 25 ++- .../views/hooks/internal/useViewSorts.ts | 19 ++- .../modules/views/hooks/internal/useViews.ts | 2 +- ...savedViewFieldByKeyScopedFamilySelector.ts | 2 +- ...vedViewFiltersByKeyScopedFamilySelector.ts | 2 +- ...savedViewSortsByKeyScopedFamilySelector.ts | 2 +- front/src/modules/views/types/View.ts | 2 +- front/src/modules/views/types/ViewField.ts | 2 +- front/src/modules/views/types/ViewFilter.ts | 2 +- front/src/modules/views/types/ViewSort.ts | 2 +- .../utils/mapColumnDefinitionToViewField.ts | 2 +- .../mapViewFieldsToBoardFieldDefinitions.ts | 4 +- .../utils/mapViewFieldsToColumnDefinitions.ts | 4 +- .../views/utils/mapViewFiltersToFilters.ts | 2 +- .../views/utils/mapViewSortsToSorts.ts | 2 +- front/src/pages/companies/CompanyShow.tsx | 5 +- .../constants/companyShowFieldDefinitions.tsx | 14 +- .../companyTableFilterDefinitions.tsx | 12 +- .../constants/companyTableSortDefinitions.tsx | 10 +- .../opportunityBoardFilterDefinitions.tsx | 8 +- .../opportunityBoardSortDefinitions.tsx | 6 +- .../constants/personShowFieldDefinitions.tsx | 16 +- .../personTableFilterDefinitions.tsx | 14 +- .../constants/personTableSortDefinitions.tsx | 12 +- .../settings/data-model/SettingsNewObject.tsx | 2 +- .../SettingsObjectNewFieldStep1.tsx | 6 +- .../SettingsObjectNewFieldStep2.tsx | 6 +- front/src/pages/tasks/TasksEffect.tsx | 2 +- .../pages/tasks/tasks-filter-definitions.tsx | 2 +- front/src/testing/graphqlMocks.ts | 6 +- front/src/testing/mock-data/metadata.ts | 4 +- front/src/testing/mock-data/view-fields.ts | 44 ++--- front/src/testing/mock-data/views.ts | 8 +- server/ormconfig.ts | 2 +- server/package.json | 2 +- server/src/command.module.ts | 10 +- .../services/workspace.service.spec.ts | 4 +- .../workspace/services/workspace.service.ts | 8 +- server/src/core/workspace/workspace.module.ts | 4 +- .../commands/database-command.module.ts | 23 +-- server/src/database/seeds/metadata.ts | 4 +- .../typeorm-seeds/metadata/field-metadata.ts | 60 +++---- .../typeorm-seeds/metadata/object-metadata.ts | 2 +- .../typeorm-seeds/tenant/view-fields.ts | 36 ++--- .../database/typeorm-seeds/tenant/views.ts | 15 +- .../entities/field-metadata.entity.ts | 102 ------------ .../entities/object-metadata.entity.ts | 81 ---------- .../entities/relation-metadata.entity.ts | 75 --------- .../1699543628458-setupMetadataTables.ts | 65 -------- server/src/database/typeorm/typeorm.module.ts | 23 --- .../src/database/typeorm/typeorm.service.ts | 106 ------------ .../commands/data-seed-tenant.command.ts | 19 ++- .../commands/metadata-command.module.ts | 31 ++++ .../commands/run-tenant-migrations.command.ts | 6 +- .../commands/sync-tenant-metadata.command.ts | 10 +- .../data-source-metadata.entity.ts} | 20 +-- .../data-source-metadata.module.ts | 5 +- .../data-source-metadata.service.spec.ts | 27 ++++ .../data-source-metadata.service.ts | 6 +- .../data-source/data-source.module.ts | 12 ++ .../data-source/data-source.service.spec.ts | 34 ++++ .../data-source/data-source.service.ts | 153 ++++++++++++++++++ .../metadata/data-source/data-source.util.ts | 21 +++ .../field-metadata/dtos/create-field.input.ts | 17 +- .../field-metadata/dtos/field-metadata.dto.ts | 81 ---------- .../field-metadata.auto-resolver-opts.ts | 44 +++++ .../field-metadata/field-metadata.entity.ts | 141 ++++++++++++++++ .../field-metadata/field-metadata.module.ts | 44 +---- .../hooks/before-create-one-field.hook.ts | 6 +- ...ld-metadata-target-column-map.interface.ts | 2 +- .../services/field-metadata.service.spec.ts | 43 +++++ .../{ => services}/field-metadata.service.ts | 39 +++-- .../utils/field-metadata.util.spec.ts | 2 +- .../utils/field-metadata.util.ts | 10 +- .../metadata/metadata.datasource.ts | 2 +- server/src/metadata/metadata.module.ts | 19 ++- .../custom-table-default-column.util.ts | 0 .../migration-runner.module.ts | 13 ++ .../migration-runner.service.spec.ts | 32 ++++ .../migration-runner.service.ts} | 20 ++- .../1695214465080-InitMetadataTables.ts | 32 ++++ ...695717691800-alter-field-metadata-table.ts | 61 +++++++ .../1696409050890-add-target-column-map.ts | 71 ++++++++ ...7126636202-MetadataNameLabelRefactoring.ts | 149 +++++++++++++++++ ...71445015-removeFieldMetadataPlaceholder.ts | 19 +++ .../migrations/1697474804403-addSoftDelete.ts | 23 +++ ...moveSingularPluralFromFieldLabelAndName.ts | 49 ++++++ ...467-addNameAndIsCustomToTenantMigration.ts | 55 +++++++ ...dUniqueConstraintsOnFieldObjectMetadata.ts | 43 +++++ .../1698328717102-removeMetadataSoftDelete.ts | 37 +++++ .../1699289664146-addRelationMetadata.ts | 39 +++++ .../dtos/create-object.input.ts | 12 +- .../dtos/object-metadata.dto.ts | 64 -------- .../hooks/before-create-one-object.hook.ts | 7 +- .../object-metadata.auto-resolver-opts.ts | 44 +++++ .../object-metadata/object-metadata.entity.ts | 112 +++++++++++++ .../object-metadata/object-metadata.module.ts | 44 +---- .../services/object-metadata.service.spec.ts | 38 +++++ .../{ => services}/object-metadata.service.ts | 64 +++++--- .../dtos/create-relation.input.ts | 6 +- .../dtos/relation-metadata.dto.ts | 62 ------- .../relation-metadata.auto-resolver-opts.ts | 35 ++++ .../relation-metadata.entity.ts | 93 +++++++++++ .../relation-metadata.module.ts | 38 +---- .../relation-metadata.service.ts | 34 ++-- .../companies/companies.metadata.ts | 0 .../standard-object-metadata.ts | 0 .../view-fields/view-fields.metadata.ts | 4 +- .../view-filters/view-filters.metadata.ts | 4 +- .../view-sorts/view-sorts.metadata.ts | 4 +- .../standard-objects}/views/views.metadata.ts | 4 +- .../standard-objects-prefill-data.ts | 58 +++---- .../tenant-initialisation.module.ts} | 22 +-- .../tenant-initialisation.service.ts | 90 +++++++++++ .../migrations/1697618009-addCompanyTable.ts | 4 +- .../migrations/1697618011-addViewTable.ts | 6 +- .../1697618012-addViewFieldTable.ts | 6 +- .../1697618013-addViewFilterTable.ts | 6 +- .../migrations/1697618014-addViewSortTable.ts | 6 +- .../tenant-migration.entity.ts | 4 +- .../tenant-migration.module.ts | 5 +- .../tenant-migration.service.spec.ts | 27 ++++ .../tenant-migration.service.ts | 13 +- .../tenant-datasource.module.ts | 13 -- .../tenant-datasource.service.ts | 101 ------------ .../tenant-manager-commands.module.ts | 12 -- .../tenant-manager/tenant-manager.service.ts | 143 ---------------- ...tenant-migration-runner-commands.module.ts | 12 -- .../tenant-migration-runner.module.ts | 13 -- .../factories/create-many-resolver.factory.ts | 8 +- .../factories/create-one-resolver.factory.ts | 12 +- .../factories/delete-one-resolver.factory.ts | 12 +- .../factories/find-many-resolver.factory.ts | 8 +- .../factories/find-one-resolver.factory.ts | 12 +- .../factories/update-one-resolver.factory.ts | 12 +- .../pg-graphql-query-builder.spec.ts | 6 +- .../pg-graphql/pg-graphql-query-runner.ts | 12 +- .../resolver-builder.module.ts | 4 +- .../utils/__tests__/convert-arguments.spec.ts | 8 +- .../convert-fields-to-graphql.spec.ts | 8 +- .../filter-type-definition.factory.ts | 4 +- .../input-type-definition.factory.ts | 4 +- .../object-type-definition.factory.ts | 4 +- .../order-by-type-definition.factory.ts | 4 +- .../schema-builder/graphql-schema.factory.ts | 2 +- .../interfaces/field-metadata.interface.ts | 4 +- .../interfaces/param-metadata.interface.ts | 2 +- .../money.object-definition.ts | 2 +- .../url.object-definition.ts | 2 +- .../services/type-mapper.service.ts | 2 +- .../storages/type-definitions.storage.ts | 2 +- .../type-definitions.generator.ts | 6 +- .../__tests__/get-field-metadata-type.spec.ts | 2 +- .../utils/__tests__/get-resolver-args.spec.ts | 2 +- .../utils/get-field-metadata-type.util.ts | 2 +- .../utils/get-resolver-args.util.ts | 2 +- server/src/tenant/tenant.service.spec.ts | 2 +- server/src/tenant/tenant.service.ts | 4 +- 238 files changed, 2253 insertions(+), 1852 deletions(-) delete mode 100644 server/src/database/typeorm/metadata/entities/field-metadata.entity.ts delete mode 100644 server/src/database/typeorm/metadata/entities/object-metadata.entity.ts delete mode 100644 server/src/database/typeorm/metadata/entities/relation-metadata.entity.ts delete mode 100644 server/src/database/typeorm/metadata/migrations/1699543628458-setupMetadataTables.ts delete mode 100644 server/src/database/typeorm/typeorm.module.ts delete mode 100644 server/src/database/typeorm/typeorm.service.ts rename server/src/{database => metadata}/commands/data-seed-tenant.command.ts (80%) create mode 100644 server/src/metadata/commands/metadata-command.module.ts rename server/src/{tenant-migration-runner => metadata}/commands/run-tenant-migrations.command.ts (80%) rename server/src/{tenant-manager => metadata}/commands/sync-tenant-metadata.command.ts (77%) rename server/src/{database/typeorm/metadata/entities/data-source.entity.ts => metadata/data-source-metadata/data-source-metadata.entity.ts} (63%) create mode 100644 server/src/metadata/data-source-metadata/data-source-metadata.service.spec.ts create mode 100644 server/src/metadata/data-source/data-source.module.ts create mode 100644 server/src/metadata/data-source/data-source.service.spec.ts create mode 100644 server/src/metadata/data-source/data-source.service.ts create mode 100644 server/src/metadata/data-source/data-source.util.ts delete mode 100644 server/src/metadata/field-metadata/dtos/field-metadata.dto.ts create mode 100644 server/src/metadata/field-metadata/field-metadata.auto-resolver-opts.ts create mode 100644 server/src/metadata/field-metadata/field-metadata.entity.ts rename server/src/{tenant/schema-builder => metadata/field-metadata}/interfaces/field-metadata-target-column-map.interface.ts (89%) create mode 100644 server/src/metadata/field-metadata/services/field-metadata.service.spec.ts rename server/src/metadata/field-metadata/{ => services}/field-metadata.service.ts (71%) rename server/src/{database/typeorm => }/metadata/metadata.datasource.ts (92%) rename server/src/{tenant-migration-runner/utils => metadata/migration-runner}/custom-table-default-column.util.ts (100%) create mode 100644 server/src/metadata/migration-runner/migration-runner.module.ts create mode 100644 server/src/metadata/migration-runner/migration-runner.service.spec.ts rename server/src/{tenant-migration-runner/tenant-migration-runner.service.ts => metadata/migration-runner/migration-runner.service.ts} (91%) create mode 100644 server/src/metadata/migrations/1695214465080-InitMetadataTables.ts create mode 100644 server/src/metadata/migrations/1695717691800-alter-field-metadata-table.ts create mode 100644 server/src/metadata/migrations/1696409050890-add-target-column-map.ts create mode 100644 server/src/metadata/migrations/1697126636202-MetadataNameLabelRefactoring.ts create mode 100644 server/src/metadata/migrations/1697471445015-removeFieldMetadataPlaceholder.ts create mode 100644 server/src/metadata/migrations/1697474804403-addSoftDelete.ts create mode 100644 server/src/metadata/migrations/1697534910933-removeSingularPluralFromFieldLabelAndName.ts create mode 100644 server/src/metadata/migrations/1697622715467-addNameAndIsCustomToTenantMigration.ts create mode 100644 server/src/metadata/migrations/1697630766924-addUniqueConstraintsOnFieldObjectMetadata.ts create mode 100644 server/src/metadata/migrations/1698328717102-removeMetadataSoftDelete.ts create mode 100644 server/src/metadata/migrations/1699289664146-addRelationMetadata.ts delete mode 100644 server/src/metadata/object-metadata/dtos/object-metadata.dto.ts create mode 100644 server/src/metadata/object-metadata/object-metadata.auto-resolver-opts.ts create mode 100644 server/src/metadata/object-metadata/object-metadata.entity.ts create mode 100644 server/src/metadata/object-metadata/services/object-metadata.service.spec.ts rename server/src/metadata/object-metadata/{ => services}/object-metadata.service.ts (60%) delete mode 100644 server/src/metadata/relation-metadata/dtos/relation-metadata.dto.ts create mode 100644 server/src/metadata/relation-metadata/relation-metadata.auto-resolver-opts.ts create mode 100644 server/src/metadata/relation-metadata/relation-metadata.entity.ts rename server/src/metadata/relation-metadata/{ => services}/relation-metadata.service.ts (84%) rename server/src/{tenant-manager/standard-objects-metadata => metadata/standard-objects}/companies/companies.metadata.ts (100%) rename server/src/{tenant-manager/standard-objects-metadata => metadata/standard-objects}/standard-object-metadata.ts (100%) rename server/src/{tenant-manager/standard-objects-metadata => metadata/standard-objects}/view-fields/view-fields.metadata.ts (95%) rename server/src/{tenant-manager/standard-objects-metadata => metadata/standard-objects}/view-filters/view-filters.metadata.ts (95%) rename server/src/{tenant-manager/standard-objects-metadata => metadata/standard-objects}/view-sorts/view-sorts.metadata.ts (93%) rename server/src/{tenant-manager/standard-objects-metadata => metadata/standard-objects}/views/views.metadata.ts (92%) rename server/src/{tenant-manager => metadata/tenant-initialisation}/standard-objects-prefill-data/standard-objects-prefill-data.ts (82%) rename server/src/{tenant-manager/tenant-manager.module.ts => metadata/tenant-initialisation/tenant-initialisation.module.ts} (56%) create mode 100644 server/src/metadata/tenant-initialisation/tenant-initialisation.service.ts rename server/src/{database/typeorm/metadata/entities => metadata/tenant-migration}/tenant-migration.entity.ts (94%) create mode 100644 server/src/metadata/tenant-migration/tenant-migration.service.spec.ts delete mode 100644 server/src/tenant-datasource/tenant-datasource.module.ts delete mode 100644 server/src/tenant-datasource/tenant-datasource.service.ts delete mode 100644 server/src/tenant-manager/commands/tenant-manager-commands.module.ts delete mode 100644 server/src/tenant-manager/tenant-manager.service.ts delete mode 100644 server/src/tenant-migration-runner/commands/tenant-migration-runner-commands.module.ts delete mode 100644 server/src/tenant-migration-runner/tenant-migration-runner.module.ts diff --git a/front/src/generated-metadata/graphql.ts b/front/src/generated-metadata/graphql.ts index 2b462fd57..8b25c5a11 100644 --- a/front/src/generated-metadata/graphql.ts +++ b/front/src/generated-metadata/graphql.ts @@ -173,7 +173,7 @@ export type CreateFieldInput = { icon?: InputMaybe; label: Scalars['String']['input']; name: Scalars['String']['input']; - objectMetadataId: Scalars['String']['input']; + objectId: Scalars['String']['input']; type: FieldMetadataType; }; @@ -196,21 +196,6 @@ export type CreateOneObjectInput = { object: CreateObjectInput; }; -export type CreateOneRelationInput = { - /** The record to create */ - relation: CreateRelationInput; -}; - -export type CreateRelationInput = { - description?: InputMaybe; - fromObjectMetadataId: Scalars['String']['input']; - icon?: InputMaybe; - label: Scalars['String']['input']; - name: Scalars['String']['input']; - relationType: Scalars['String']['input']; - toObjectMetadataId: Scalars['String']['input']; -}; - export enum Currency { Aed = 'AED', Afn = 'AFN', @@ -452,7 +437,6 @@ export enum FieldMetadataType { Money = 'MONEY', Number = 'NUMBER', Phone = 'PHONE', - Relation = 'RELATION', Text = 'TEXT', Url = 'URL', Uuid = 'UUID' @@ -462,7 +446,6 @@ export type Mutation = { __typename?: 'Mutation'; createOneField: Field; createOneObject: Object; - createOneRelation: Relation; deleteOneField: FieldDeleteResponse; deleteOneObject: ObjectDeleteResponse; updateOneField: Field; @@ -480,11 +463,6 @@ export type MutationCreateOneObjectArgs = { }; -export type MutationCreateOneRelationArgs = { - input: CreateOneRelationInput; -}; - - export type MutationDeleteOneFieldArgs = { input: DeleteOneFieldInput; }; @@ -633,7 +611,6 @@ export type Query = { fields: FieldConnection; object: Object; objects: ObjectConnection; - relation: Relation; }; @@ -656,11 +633,6 @@ export type QueryObjectsArgs = { paging?: CursorPaging; }; - -export type QueryRelationArgs = { - id: Scalars['ID']['input']; -}; - export type Support = { __typename?: 'Support'; supportDriver: Scalars['String']['output']; @@ -797,7 +769,6 @@ export type Field = { __typename?: 'field'; createdAt: Scalars['DateTime']['output']; description?: Maybe; - fromRelationMetadata?: Maybe; icon?: Maybe; id: Scalars['ID']['output']; isActive: Scalars['Boolean']['output']; @@ -807,7 +778,6 @@ export type Field = { name: Scalars['String']['output']; /** @deprecated Use label name instead */ placeholder?: Maybe; - toRelationMetadata?: Maybe; type: FieldMetadataType; updatedAt: Scalars['DateTime']['output']; }; @@ -850,28 +820,6 @@ export type ObjectEdge = { node: Object; }; -export type Relation = { - __typename?: 'relation'; - createdAt: Scalars['DateTime']['output']; - fromFieldMetadataId: Scalars['String']['output']; - fromObjectMetadata: Object; - fromObjectMetadataId: Scalars['String']['output']; - id: Scalars['ID']['output']; - relationType: Scalars['String']['output']; - toFieldMetadataId: Scalars['String']['output']; - toObjectMetadata: Object; - toObjectMetadataId: Scalars['String']['output']; - updatedAt: Scalars['DateTime']['output']; -}; - -export type RelationEdge = { - __typename?: 'relationEdge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']['output']; - /** The node containing the relation */ - node: Relation; -}; - export type CreateOneObjectMetadataItemMutationVariables = Exact<{ input: CreateOneObjectInput; }>; diff --git a/front/src/generated/graphql.tsx b/front/src/generated/graphql.tsx index f8e6652dd..54e61db1e 100644 --- a/front/src/generated/graphql.tsx +++ b/front/src/generated/graphql.tsx @@ -1322,7 +1322,6 @@ export enum FieldMetadataType { Money = 'MONEY', Number = 'NUMBER', Phone = 'PHONE', - Relation = 'RELATION', Text = 'TEXT', Url = 'URL', Uuid = 'UUID' @@ -1392,7 +1391,6 @@ export type Mutation = { createOneApiKey: ApiKeyToken; createOneComment: Comment; createOneCompany: Company; - createOneField: Field; createOneObject: Object; createOnePerson: Person; createOnePipelineProgress: PipelineProgress; @@ -1404,7 +1402,6 @@ export type Mutation = { deleteManyCompany: AffectedRows; deleteManyPerson: AffectedRows; deleteManyPipelineProgress: AffectedRows; - deleteOneField: FieldDeleteResponse; deleteOneObject: ObjectDeleteResponse; deleteOnePipelineStage: PipelineStage; deleteOneWebHook: WebHook; @@ -1417,7 +1414,6 @@ export type Mutation = { updateOneActivity: Activity; updateOneCompany?: Maybe; updateOneFavorites: Favorite; - updateOneField: Field; updateOneObject: Object; updateOnePerson?: Maybe; updateOnePipelineProgress?: Maybe; @@ -2408,8 +2404,6 @@ export type Query = { clientConfig: ClientConfig; currentUser: User; currentWorkspace: Workspace; - field: Field; - fields: FieldConnection; findFavorites: Array; findManyActivities: Array; findManyApiKey: Array; @@ -2599,15 +2593,6 @@ export type Support = { supportFrontChatId?: Maybe; }; -export type TUser = { - __typename?: 'TUser'; - email: Scalars['String']; - emailVerified: Scalars['Boolean']; - firstName?: Maybe; - id: Scalars['ID']; - lastName?: Maybe; -}; - export type Telemetry = { __typename?: 'Telemetry'; anonymizationEnabled: Scalars['Boolean']; @@ -3108,7 +3093,6 @@ export type Field = { __typename?: 'field'; createdAt: Scalars['DateTime']; description?: Maybe; - fromRelationMetadata?: Maybe; icon?: Maybe; id: Scalars['ID']; isActive: Scalars['Boolean']; @@ -3118,7 +3102,6 @@ export type Field = { name: Scalars['String']; /** @deprecated Use label name instead */ placeholder?: Maybe; - toRelationMetadata?: Maybe; type: FieldMetadataType; updatedAt: Scalars['DateTime']; }; @@ -3161,28 +3144,6 @@ export type ObjectEdge = { node: Object; }; -export type Relation = { - __typename?: 'relation'; - createdAt: Scalars['DateTime']; - fromFieldMetadataId: Scalars['String']; - fromObjectMetadata: Object; - fromObjectMetadataId: Scalars['String']; - id: Scalars['ID']; - relationType: Scalars['String']; - toFieldMetadataId: Scalars['String']; - toObjectMetadata: Object; - toObjectMetadataId: Scalars['String']; - updatedAt: Scalars['DateTime']; -}; - -export type RelationEdge = { - __typename?: 'relationEdge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']; - /** The node containing the relation */ - node: Relation; -}; - export type ActivityWithTargetsFragment = { __typename?: 'Activity', id: string, createdAt: string, updatedAt: string, activityTargets?: Array<{ __typename?: 'ActivityTarget', id: string, createdAt: string, updatedAt: string, companyId?: string | null, personId?: string | null }> | null }; export type ActivityQueryFragmentFragment = { __typename?: 'Activity', id: string, createdAt: string, title?: string | null, body?: string | null, type: ActivityType, completedAt?: string | null, dueAt?: string | null, assignee?: { __typename?: 'User', id: string, firstName?: string | null, lastName?: string | null, displayName: string, avatarUrl?: string | null } | null, author: { __typename?: 'User', id: string, firstName?: string | null, lastName?: string | null, displayName: string }, comments?: Array<{ __typename?: 'Comment', id: string, body: string, createdAt: string, updatedAt: string, author: { __typename?: 'User', id: string, displayName: string, firstName?: string | null, lastName?: string | null, avatarUrl?: string | null } }> | null, activityTargets?: Array<{ __typename?: 'ActivityTarget', id: string, companyId?: string | null, personId?: string | null, company?: { __typename?: 'Company', id: string, name: string, domainName: string } | null, person?: { __typename?: 'Person', id: string, displayName: string, avatarUrl?: string | null } | null }> | null }; diff --git a/front/src/modules/activities/editable-fields/components/ActivityAssigneeEditableField.tsx b/front/src/modules/activities/editable-fields/components/ActivityAssigneeEditableField.tsx index 1c8cc55b1..f97b93eb9 100644 --- a/front/src/modules/activities/editable-fields/components/ActivityAssigneeEditableField.tsx +++ b/front/src/modules/activities/editable-fields/components/ActivityAssigneeEditableField.tsx @@ -23,7 +23,7 @@ export const ActivityAssigneeEditableField = ({ entityId: activity.id, recoilScopeId: 'assignee', fieldDefinition: { - fieldMetadataId: 'assignee', + fieldId: 'assignee', label: 'Assignee', Icon: IconUserCircle, type: 'RELATION', diff --git a/front/src/modules/activities/editable-fields/components/ActivityEditorDateField.tsx b/front/src/modules/activities/editable-fields/components/ActivityEditorDateField.tsx index e4daac942..d7e4680f3 100644 --- a/front/src/modules/activities/editable-fields/components/ActivityEditorDateField.tsx +++ b/front/src/modules/activities/editable-fields/components/ActivityEditorDateField.tsx @@ -21,7 +21,7 @@ export const ActivityEditorDateField = ({ entityId: activityId, recoilScopeId: 'activityDueAt', fieldDefinition: { - fieldMetadataId: 'activityDueAt', + fieldId: 'activityDueAt', label: 'Due date', Icon: IconCalendar, type: 'DATE', diff --git a/front/src/modules/activities/tasks/hooks/useCurrentUserDueTaskCount.ts b/front/src/modules/activities/tasks/hooks/useCurrentUserDueTaskCount.ts index a6281c1e5..c31af5e60 100644 --- a/front/src/modules/activities/tasks/hooks/useCurrentUserDueTaskCount.ts +++ b/front/src/modules/activities/tasks/hooks/useCurrentUserDueTaskCount.ts @@ -17,7 +17,7 @@ export const useCurrentUserTaskCount = () => { completedAt: { equals: null }, ...(currentUser ? turnFilterIntoWhereClause({ - fieldMetadataId: 'assigneeId', + fieldId: 'assigneeId', value: currentUser.id, operand: ViewFilterOperand.Is, displayValue: currentUser.displayName, diff --git a/front/src/modules/companies/components/CompanyBoardCard.tsx b/front/src/modules/companies/components/CompanyBoardCard.tsx index 10e9cc2e0..85652feb2 100644 --- a/front/src/modules/companies/components/CompanyBoardCard.tsx +++ b/front/src/modules/companies/components/CompanyBoardCard.tsx @@ -222,13 +222,13 @@ export const CompanyBoardCard = () => { {visibleBoardCardFields.map((viewField) => ( - + [] = [ { - fieldMetadataId: 'name', + fieldId: 'name', label: 'Name', Icon: IconBuildingSkyscraper, size: 180, @@ -45,7 +45,7 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition basePathToShowPage: '/companies/', } satisfies ColumnDefinition, { - fieldMetadataId: 'domainName', + fieldId: 'domainName', label: 'URL', Icon: IconLink, size: 100, @@ -60,7 +60,7 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition 'The company website URL. We use this url to fetch the company icon.', } satisfies ColumnDefinition, { - fieldMetadataId: 'accountOwner', + fieldId: 'accountOwner', label: 'Account Owner', Icon: IconUserCircle, size: 150, @@ -82,7 +82,7 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition }, } satisfies ColumnDefinition, { - fieldMetadataId: 'createdAt', + fieldId: 'createdAt', label: 'Creation', Icon: IconCalendarEvent, size: 150, @@ -95,7 +95,7 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition infoTooltipContent: "Date when the company's record was created.", } satisfies ColumnDefinition, { - fieldMetadataId: 'employees', + fieldId: 'employees', label: 'Employees', Icon: IconUsers, size: 150, @@ -110,7 +110,7 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition infoTooltipContent: 'Number of employees in the company.', } satisfies ColumnDefinition, { - fieldMetadataId: 'linkedin', + fieldId: 'linkedin', label: 'LinkedIn', Icon: IconBrandLinkedin, size: 170, @@ -124,7 +124,7 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition infoTooltipContent: 'The company Linkedin account.', } satisfies ColumnDefinition, { - fieldMetadataId: 'address', + fieldId: 'address', label: 'Address', Icon: IconMap, size: 170, @@ -138,7 +138,7 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition infoTooltipContent: 'The company address.', } satisfies ColumnDefinition, { - fieldMetadataId: 'idealCustomerProfile', + fieldId: 'idealCustomerProfile', label: 'ICP', Icon: IconTarget, size: 150, @@ -152,7 +152,7 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition 'Ideal Customer Profile: Indicates whether the company is the most suitable and valuable customer for you.', } satisfies ColumnDefinition, { - fieldMetadataId: 'annualRecurringRevenue', + fieldId: 'annualRecurringRevenue', label: 'ARR', Icon: IconMoneybag, size: 150, @@ -166,7 +166,7 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition 'Annual Recurring Revenue: The actual or estimated annual revenue of the company.', } satisfies ColumnDefinition, { - fieldMetadataId: 'xUrl', + fieldId: 'xUrl', label: 'Twitter', Icon: IconBrandX, size: 150, @@ -184,7 +184,7 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition export const suppliersAvailableColumnDefinitions: ColumnDefinition[] = [ { - fieldMetadataId: 'name', + fieldId: 'name', label: 'Name', Icon: IconBuildingSkyscraper, size: 180, @@ -199,7 +199,7 @@ export const suppliersAvailableColumnDefinitions: ColumnDefinition, { - fieldMetadataId: 'city', + fieldId: 'city', label: 'City', Icon: IconBuildingSkyscraper, size: 180, diff --git a/front/src/modules/metadata/components/RecordShowPage.tsx b/front/src/modules/metadata/components/RecordShowPage.tsx index 54ce627f1..4c73d3881 100644 --- a/front/src/modules/metadata/components/RecordShowPage.tsx +++ b/front/src/modules/metadata/components/RecordShowPage.tsx @@ -29,9 +29,9 @@ import { useUpdateOneObject } from '../hooks/useUpdateOneObject'; import { formatMetadataFieldAsColumnDefinition } from '../utils/formatMetadataFieldAsColumnDefinition'; export const RecordShowPage = () => { - const { objectNameSingular, objectMetadataId } = useParams<{ + const { objectNameSingular, objectId } = useParams<{ objectNameSingular: string; - objectMetadataId: string; + objectId: string; }>(); const { icons } = useLazyLoadIcons(); @@ -41,11 +41,11 @@ export const RecordShowPage = () => { }); const [, setEntityFields] = useRecoilState( - entityFieldsFamilyState(objectMetadataId ?? ''), + entityFieldsFamilyState(objectId ?? ''), ); const { object } = useFindOneObject({ - objectMetadataId: objectMetadataId, + objectId: objectId, objectNameSingular, onCompleted: (data) => { setEntityFields(data); diff --git a/front/src/modules/metadata/hooks/useCreateOneObject.ts b/front/src/modules/metadata/hooks/useCreateOneObject.ts index d47098619..5d2f9e161 100644 --- a/front/src/modules/metadata/hooks/useCreateOneObject.ts +++ b/front/src/modules/metadata/hooks/useCreateOneObject.ts @@ -14,7 +14,6 @@ const defaultFieldValues: Record = { [FieldMetadataType.Email]: '', [FieldMetadataType.Enum]: null, [FieldMetadataType.Number]: null, - [FieldMetadataType.Relation]: null, [FieldMetadataType.Phone]: '', [FieldMetadataType.Text]: '', [FieldMetadataType.Url]: { link: '', text: '' }, diff --git a/front/src/modules/metadata/hooks/useFindOneObject.ts b/front/src/modules/metadata/hooks/useFindOneObject.ts index 454d96566..6bf4baf42 100644 --- a/front/src/modules/metadata/hooks/useFindOneObject.ts +++ b/front/src/modules/metadata/hooks/useFindOneObject.ts @@ -8,10 +8,10 @@ export const useFindOneObject = < ObjectType extends { id: string } & Record, >({ objectNameSingular, - objectMetadataId, + objectId, onCompleted, }: Pick & { - objectMetadataId: string | undefined; + objectId: string | undefined; onCompleted?: (data: ObjectType) => void; }) => { const { foundObjectMetadataItem, objectNotFoundInMetadata, findOneQuery } = @@ -21,11 +21,11 @@ export const useFindOneObject = < const { data, loading, error } = useQuery< { [nameSingular: string]: ObjectType }, - { objectMetadataId: string } + { objectId: string } >(findOneQuery, { - skip: !foundObjectMetadataItem || !objectMetadataId, + skip: !foundObjectMetadataItem || !objectId, variables: { - objectMetadataId: objectMetadataId ?? '', + objectId: objectId ?? '', }, onCompleted: (data) => { if (onCompleted && objectNameSingular) { diff --git a/front/src/modules/metadata/hooks/useMetadataField.ts b/front/src/modules/metadata/hooks/useMetadataField.ts index a72bf40a3..bb898d3e9 100644 --- a/front/src/modules/metadata/hooks/useMetadataField.ts +++ b/front/src/modules/metadata/hooks/useMetadataField.ts @@ -14,13 +14,13 @@ export const useMetadataField = () => { const createMetadataField = ( input: Pick & { - objectMetadataId: string; + objectId: string; type: MetadataFieldDataType; }, ) => createOneMetadataField({ ...formatMetadataFieldInput(input), - objectMetadataId: input.objectMetadataId, + objectId: input.objectId, type: input.type, }); @@ -28,19 +28,19 @@ export const useMetadataField = () => { input: Pick, ) => updateOneMetadataField({ - fieldMetadataIdToUpdate: input.id, + fieldIdToUpdate: input.id, updatePayload: formatMetadataFieldInput(input), }); const activateMetadataField = (metadataField: Field) => updateOneMetadataField({ - fieldMetadataIdToUpdate: metadataField.id, + fieldIdToUpdate: metadataField.id, updatePayload: { isActive: true }, }); const disableMetadataField = (metadataField: Field) => updateOneMetadataField({ - fieldMetadataIdToUpdate: metadataField.id, + fieldIdToUpdate: metadataField.id, updatePayload: { isActive: false }, }); diff --git a/front/src/modules/metadata/hooks/useUpdateOneMetadataField.ts b/front/src/modules/metadata/hooks/useUpdateOneMetadataField.ts index 8df8fbdbb..43506b9ba 100644 --- a/front/src/modules/metadata/hooks/useUpdateOneMetadataField.ts +++ b/front/src/modules/metadata/hooks/useUpdateOneMetadataField.ts @@ -22,10 +22,10 @@ export const useUpdateOneMetadataField = () => { }); const updateOneMetadataField = async ({ - fieldMetadataIdToUpdate, + fieldIdToUpdate, updatePayload, }: { - fieldMetadataIdToUpdate: UpdateOneMetadataFieldMutationVariables['idToUpdate']; + fieldIdToUpdate: UpdateOneMetadataFieldMutationVariables['idToUpdate']; updatePayload: Pick< UpdateOneMetadataFieldMutationVariables['updatePayload'], 'description' | 'icon' | 'isActive' | 'label' | 'name' @@ -33,7 +33,7 @@ export const useUpdateOneMetadataField = () => { }) => { return await mutate({ variables: { - idToUpdate: fieldMetadataIdToUpdate, + idToUpdate: fieldIdToUpdate, updatePayload: { ...updatePayload, label: updatePayload.label ?? undefined, diff --git a/front/src/modules/metadata/utils/formatMetadataFieldAsColumnDefinition.ts b/front/src/modules/metadata/utils/formatMetadataFieldAsColumnDefinition.ts index f744d64b0..c2c2d53aa 100644 --- a/front/src/modules/metadata/utils/formatMetadataFieldAsColumnDefinition.ts +++ b/front/src/modules/metadata/utils/formatMetadataFieldAsColumnDefinition.ts @@ -19,7 +19,7 @@ export const formatMetadataFieldAsColumnDefinition = ({ icons: Record; }): ColumnDefinition => ({ position, - fieldMetadataId: field.id, + fieldId: field.id, label: field.label, size: 100, type: parseFieldType(field.type), diff --git a/front/src/modules/metadata/utils/formatMetadataFieldAsFilterDefinition.ts b/front/src/modules/metadata/utils/formatMetadataFieldAsFilterDefinition.ts index 56bc5b837..016fb1016 100644 --- a/front/src/modules/metadata/utils/formatMetadataFieldAsFilterDefinition.ts +++ b/front/src/modules/metadata/utils/formatMetadataFieldAsFilterDefinition.ts @@ -9,7 +9,7 @@ export const formatMetadataFieldAsFilterDefinition = ({ field: ObjectMetadataItem['fields'][0]; icons: Record; }): FilterDefinition => ({ - fieldMetadataId: field.id, + fieldId: field.id, label: field.label, Icon: icons[field.icon ?? 'Icon123'], type: 'TEXT', diff --git a/front/src/modules/metadata/utils/formatMetadataFieldAsSortDefinition.ts b/front/src/modules/metadata/utils/formatMetadataFieldAsSortDefinition.ts index 899d5c4d7..2b5fd8d26 100644 --- a/front/src/modules/metadata/utils/formatMetadataFieldAsSortDefinition.ts +++ b/front/src/modules/metadata/utils/formatMetadataFieldAsSortDefinition.ts @@ -9,7 +9,7 @@ export const formatMetadataFieldAsSortDefinition = ({ field: ObjectMetadataItem['fields'][0]; icons: Record; }): SortDefinition => ({ - fieldMetadataId: field.id, + fieldId: field.id, label: field.label, Icon: icons[field.icon ?? 'Icon123'], }); diff --git a/front/src/modules/metadata/utils/generateFindOneCustomObjectQuery.ts b/front/src/modules/metadata/utils/generateFindOneCustomObjectQuery.ts index c585b11d2..4a996e4e7 100644 --- a/front/src/modules/metadata/utils/generateFindOneCustomObjectQuery.ts +++ b/front/src/modules/metadata/utils/generateFindOneCustomObjectQuery.ts @@ -10,10 +10,10 @@ export const generateFindOneCustomObjectQuery = ({ objectMetadataItem: ObjectMetadataItem; }) => { return gql` - query FindOne${objectMetadataItem.nameSingular}($objectMetadataId: UUID!) { + query FindOne${objectMetadataItem.nameSingular}($objectId: UUID!) { ${objectMetadataItem.nameSingular}(filter: { id: { - eq: $objectMetadataId + eq: $objectId } }){ id diff --git a/front/src/modules/people/constants/peopleAvailableFieldDefinitions.tsx b/front/src/modules/people/constants/peopleAvailableFieldDefinitions.tsx index 9365386a0..ad82e7914 100644 --- a/front/src/modules/people/constants/peopleAvailableFieldDefinitions.tsx +++ b/front/src/modules/people/constants/peopleAvailableFieldDefinitions.tsx @@ -27,7 +27,7 @@ import { getLogoUrlFromDomainName } from '~/utils'; export const peopleAvailableFieldDefinitions: ColumnDefinition[] = [ { - fieldMetadataId: 'displayName', + fieldId: 'displayName', label: 'People', Icon: IconUser, size: 210, @@ -45,7 +45,7 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition[] basePathToShowPage: '/person/', } satisfies ColumnDefinition, { - fieldMetadataId: 'email', + fieldId: 'email', label: 'Email', Icon: IconMail, size: 150, @@ -58,7 +58,7 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition[] infoTooltipContent: 'Contact’s Email.', } satisfies ColumnDefinition, { - fieldMetadataId: 'company', + fieldId: 'company', label: 'Company', Icon: IconBuildingSkyscraper, size: 150, @@ -78,7 +78,7 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition[] }, } satisfies ColumnDefinition, { - fieldMetadataId: 'phone', + fieldId: 'phone', label: 'Phone', Icon: IconPhone, size: 150, @@ -91,7 +91,7 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition[] infoTooltipContent: 'Contact’s phone number.', } satisfies ColumnDefinition, { - fieldMetadataId: 'createdAt', + fieldId: 'createdAt', label: 'Creation', Icon: IconCalendarEvent, size: 150, @@ -103,7 +103,7 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition[] infoTooltipContent: 'Date when the contact was added.', } satisfies ColumnDefinition, { - fieldMetadataId: 'city', + fieldId: 'city', label: 'City', Icon: IconMap, size: 150, @@ -116,7 +116,7 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition[] infoTooltipContent: 'Contact’s city.', } satisfies ColumnDefinition, { - fieldMetadataId: 'jobTitle', + fieldId: 'jobTitle', label: 'Job title', Icon: IconBriefcase, size: 150, @@ -129,7 +129,7 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition[] infoTooltipContent: 'Contact’s job title.', } satisfies ColumnDefinition, { - fieldMetadataId: 'linkedin', + fieldId: 'linkedin', label: 'LinkedIn', Icon: IconBrandLinkedin, size: 150, @@ -142,7 +142,7 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition[] infoTooltipContent: 'Contact’s Linkedin account.', } satisfies ColumnDefinition, { - fieldMetadataId: 'x', + fieldId: 'x', label: 'Twitter', Icon: IconBrandX, size: 150, diff --git a/front/src/modules/pipeline/constants/pipelineAvailableFieldDefinitions.tsx b/front/src/modules/pipeline/constants/pipelineAvailableFieldDefinitions.tsx index 49834d68c..c29caff32 100644 --- a/front/src/modules/pipeline/constants/pipelineAvailableFieldDefinitions.tsx +++ b/front/src/modules/pipeline/constants/pipelineAvailableFieldDefinitions.tsx @@ -18,7 +18,7 @@ import { Person } from '~/generated/graphql'; export const pipelineAvailableFieldDefinitions: ColumnDefinition[] = [ { - fieldMetadataId: 'closeDate', + fieldId: 'closeDate', label: 'Close Date', Icon: IconCalendarEvent, position: 0, @@ -32,7 +32,7 @@ export const pipelineAvailableFieldDefinitions: ColumnDefinition[ 'Specified date by which an opportunity must be completed.', } satisfies ColumnDefinition, { - fieldMetadataId: 'amount', + fieldId: 'amount', label: 'Amount', Icon: IconCurrencyDollar, position: 1, @@ -46,7 +46,7 @@ export const pipelineAvailableFieldDefinitions: ColumnDefinition[ infoTooltipContent: 'Potential monetary value of a business opportunity.', } satisfies ColumnDefinition, { - fieldMetadataId: 'probability', + fieldId: 'probability', label: 'Probability', Icon: IconProgressCheck, position: 2, @@ -60,7 +60,7 @@ export const pipelineAvailableFieldDefinitions: ColumnDefinition[ "Level of certainty in the lead's potential to convert into a success.", } satisfies ColumnDefinition, { - fieldMetadataId: 'pointOfContact', + fieldId: 'pointOfContact', label: 'Point of Contact', Icon: IconUser, position: 3, diff --git a/front/src/modules/settings/data-model/components/SettingsObjectFieldPreview.tsx b/front/src/modules/settings/data-model/components/SettingsObjectFieldPreview.tsx index b53bc1b50..ae8ab2b84 100644 --- a/front/src/modules/settings/data-model/components/SettingsObjectFieldPreview.tsx +++ b/front/src/modules/settings/data-model/components/SettingsObjectFieldPreview.tsx @@ -141,7 +141,7 @@ export const SettingsObjectFieldPreview = ({ fieldDefinition: { type: parseFieldType(fieldType as FieldMetadataType), Icon: FieldIcon, - fieldMetadataId: '', + fieldId: '', label: fieldLabel, metadata: { fieldName: fieldName || 'new-field' }, }, diff --git a/front/src/modules/types/AppPath.ts b/front/src/modules/types/AppPath.ts index 11f501e21..629c2ccb9 100644 --- a/front/src/modules/types/AppPath.ts +++ b/front/src/modules/types/AppPath.ts @@ -19,7 +19,7 @@ export enum AppPath { OpportunitiesPage = '/opportunities', RecordTablePage = '/objects/:objectNamePlural', - RecordShowPage = '/object/:objectNameSingular/:objectMetadataId', + RecordShowPage = '/object/:objectNameSingular/:objectId', SettingsCatchAll = `/settings/*`, DevelopersCatchAll = `/developers/*`, diff --git a/front/src/modules/ui/layout/board/hooks/useBoardCardFields.ts b/front/src/modules/ui/layout/board/hooks/useBoardCardFields.ts index 35cc98415..71818f362 100644 --- a/front/src/modules/ui/layout/board/hooks/useBoardCardFields.ts +++ b/front/src/modules/ui/layout/board/hooks/useBoardCardFields.ts @@ -19,7 +19,7 @@ export const useBoardCardFields = () => { ) => { setBoardCardFields((previousFields) => previousFields.map((previousField) => - previousField.fieldMetadataId === field.fieldMetadataId + previousField.fieldId === field.fieldId ? { ...previousField, isVisible: !field.isVisible } : previousField, ), diff --git a/front/src/modules/ui/layout/board/states/selectors/boardCardFieldsByKeyScopedSelector.ts b/front/src/modules/ui/layout/board/states/selectors/boardCardFieldsByKeyScopedSelector.ts index cebd20e36..ef741eaf5 100644 --- a/front/src/modules/ui/layout/board/states/selectors/boardCardFieldsByKeyScopedSelector.ts +++ b/front/src/modules/ui/layout/board/states/selectors/boardCardFieldsByKeyScopedSelector.ts @@ -12,5 +12,5 @@ export const boardCardFieldsByKeyScopedSelector = selectorFamily({ ({ get }) => get(boardCardFieldsScopedState(scopeId)).reduce< Record> - >((result, field) => ({ ...result, [field.fieldMetadataId]: field }), {}), + >((result, field) => ({ ...result, [field.fieldId]: field }), {}), }); diff --git a/front/src/modules/ui/layout/board/states/selectors/hiddenBoardCardFieldsScopedSelector.ts b/front/src/modules/ui/layout/board/states/selectors/hiddenBoardCardFieldsScopedSelector.ts index 29c56cc4c..2376296f1 100644 --- a/front/src/modules/ui/layout/board/states/selectors/hiddenBoardCardFieldsScopedSelector.ts +++ b/front/src/modules/ui/layout/board/states/selectors/hiddenBoardCardFieldsScopedSelector.ts @@ -9,10 +9,10 @@ export const hiddenBoardCardFieldsScopedSelector = selectorFamily({ (scopeId: string) => ({ get }) => { const fields = get(boardCardFieldsScopedState(scopeId)); - const fieldKeys = fields.map(({ fieldMetadataId }) => fieldMetadataId); + const fieldKeys = fields.map(({ fieldId }) => fieldId); const otherAvailableKeys = get( availableBoardCardFieldsScopedState(scopeId), - ).filter(({ fieldMetadataId }) => !fieldKeys.includes(fieldMetadataId)); + ).filter(({ fieldId }) => !fieldKeys.includes(fieldId)); return [ ...fields.filter((field) => !field.isVisible), diff --git a/front/src/modules/ui/layout/board/states/selectors/savedBoardCardFieldsByKeyFamilySelector.ts b/front/src/modules/ui/layout/board/states/selectors/savedBoardCardFieldsByKeyFamilySelector.ts index 891ed831f..af64c0fb2 100644 --- a/front/src/modules/ui/layout/board/states/selectors/savedBoardCardFieldsByKeyFamilySelector.ts +++ b/front/src/modules/ui/layout/board/states/selectors/savedBoardCardFieldsByKeyFamilySelector.ts @@ -12,5 +12,5 @@ export const savedBoardCardFieldsByKeyFamilySelector = selectorFamily({ ({ get }) => get(savedBoardCardFieldsFamilyState(viewId)).reduce< Record> - >((result, field) => ({ ...result, [field.fieldMetadataId]: field }), {}), + >((result, field) => ({ ...result, [field.fieldId]: field }), {}), }); diff --git a/front/src/modules/ui/object/field/hooks/useFieldInitialValue.ts b/front/src/modules/ui/object/field/hooks/useFieldInitialValue.ts index a99563a40..b228b1b98 100644 --- a/front/src/modules/ui/object/field/hooks/useFieldInitialValue.ts +++ b/front/src/modules/ui/object/field/hooks/useFieldInitialValue.ts @@ -9,7 +9,7 @@ export const useFieldInitialValue = () => { const fieldInitialValue = useRecoilValue( entityFieldInitialValueFamilyState({ - fieldMetadataId: fieldDefinition.fieldMetadataId, + fieldId: fieldDefinition.fieldId, entityId, }), ); diff --git a/front/src/modules/ui/object/field/hooks/useIsFieldEmpty.ts b/front/src/modules/ui/object/field/hooks/useIsFieldEmpty.ts index b7af6865a..cbb75fefc 100644 --- a/front/src/modules/ui/object/field/hooks/useIsFieldEmpty.ts +++ b/front/src/modules/ui/object/field/hooks/useIsFieldEmpty.ts @@ -10,7 +10,7 @@ export const useIsFieldEmpty = () => { const isFieldEmpty = useRecoilValue( isEntityFieldEmptyFamilySelector({ fieldDefinition: { - fieldMetadataId: fieldDefinition.fieldMetadataId, + fieldId: fieldDefinition.fieldId, label: fieldDefinition.label, type: fieldDefinition.type, metadata: fieldDefinition.metadata, diff --git a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/DateFieldDisplay.stories.tsx b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/DateFieldDisplay.stories.tsx index cf05e8a53..97b473694 100644 --- a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/DateFieldDisplay.stories.tsx +++ b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/DateFieldDisplay.stories.tsx @@ -27,7 +27,7 @@ const meta: Meta = { value={{ entityId: '', fieldDefinition: { - fieldMetadataId: 'date', + fieldId: 'date', label: 'Date', type: 'DATE', metadata: { diff --git a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/DoubleTextFieldDisplay.stories.tsx b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/DoubleTextFieldDisplay.stories.tsx index dd9ab566b..0385c176f 100644 --- a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/DoubleTextFieldDisplay.stories.tsx +++ b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/DoubleTextFieldDisplay.stories.tsx @@ -32,7 +32,7 @@ const meta: Meta = { value={{ entityId: '', fieldDefinition: { - fieldMetadataId: 'double-text', + fieldId: 'double-text', label: 'Double-Text', type: 'DOUBLE_TEXT', metadata: { diff --git a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/EmailFieldDisplay.stories.tsx b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/EmailFieldDisplay.stories.tsx index 76fa24092..e0d7b612d 100644 --- a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/EmailFieldDisplay.stories.tsx +++ b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/EmailFieldDisplay.stories.tsx @@ -26,7 +26,7 @@ const meta: Meta = { value={{ entityId: '', fieldDefinition: { - fieldMetadataId: 'email', + fieldId: 'email', label: 'Email', type: 'EMAIL', metadata: { diff --git a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/MoneyFieldDisplay.stories.tsx b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/MoneyFieldDisplay.stories.tsx index 2028056a6..157f27b73 100644 --- a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/MoneyFieldDisplay.stories.tsx +++ b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/MoneyFieldDisplay.stories.tsx @@ -25,7 +25,7 @@ const meta: Meta = { value={{ entityId: '', fieldDefinition: { - fieldMetadataId: 'money', + fieldId: 'money', label: 'Money', type: 'MONEY_AMOUNT', metadata: { diff --git a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/NumberFieldDisplay.stories.tsx b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/NumberFieldDisplay.stories.tsx index 456096f63..02bdffdef 100644 --- a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/NumberFieldDisplay.stories.tsx +++ b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/NumberFieldDisplay.stories.tsx @@ -25,7 +25,7 @@ const meta: Meta = { value={{ entityId: '', fieldDefinition: { - fieldMetadataId: 'number', + fieldId: 'number', label: 'Number', type: 'NUMBER', metadata: { diff --git a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/PhoneFieldDisplay.stories.tsx b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/PhoneFieldDisplay.stories.tsx index dfd48f2b9..1d8265d52 100644 --- a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/PhoneFieldDisplay.stories.tsx +++ b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/PhoneFieldDisplay.stories.tsx @@ -26,7 +26,7 @@ const meta: Meta = { value={{ entityId: '', fieldDefinition: { - fieldMetadataId: 'phone', + fieldId: 'phone', label: 'Phone', type: 'PHONE', metadata: { diff --git a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/TextFieldDisplay.stories.tsx b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/TextFieldDisplay.stories.tsx index 9434539af..d405fafe7 100644 --- a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/TextFieldDisplay.stories.tsx +++ b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/TextFieldDisplay.stories.tsx @@ -25,7 +25,7 @@ const meta: Meta = { value={{ entityId: '', fieldDefinition: { - fieldMetadataId: 'text', + fieldId: 'text', label: 'Text', type: 'TEXT', metadata: { diff --git a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/URLFieldDisplay.stories.tsx b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/URLFieldDisplay.stories.tsx index aaee99662..f377fa945 100644 --- a/front/src/modules/ui/object/field/meta-types/display/components/__stories__/URLFieldDisplay.stories.tsx +++ b/front/src/modules/ui/object/field/meta-types/display/components/__stories__/URLFieldDisplay.stories.tsx @@ -26,7 +26,7 @@ const meta: Meta = { value={{ entityId: '', fieldDefinition: { - fieldMetadataId: 'URL', + fieldId: 'URL', label: 'URL', type: 'URL', metadata: { diff --git a/front/src/modules/ui/object/field/meta-types/input/components/__stories__/BooleanFieldInput.stories.tsx b/front/src/modules/ui/object/field/meta-types/input/components/__stories__/BooleanFieldInput.stories.tsx index 0a5c1c1b5..9b9df6376 100644 --- a/front/src/modules/ui/object/field/meta-types/input/components/__stories__/BooleanFieldInput.stories.tsx +++ b/front/src/modules/ui/object/field/meta-types/input/components/__stories__/BooleanFieldInput.stories.tsx @@ -34,7 +34,7 @@ const BooleanFieldInputWithContext = ({ return ( ({ key: 'entityFieldInitialValueFamilyState', default: undefined, diff --git a/front/src/modules/ui/object/field/states/selectors/isEntityFieldEmptyFamilySelector.ts b/front/src/modules/ui/object/field/states/selectors/isEntityFieldEmptyFamilySelector.ts index 8b1f479ea..df376d025 100644 --- a/front/src/modules/ui/object/field/states/selectors/isEntityFieldEmptyFamilySelector.ts +++ b/front/src/modules/ui/object/field/states/selectors/isEntityFieldEmptyFamilySelector.ts @@ -33,7 +33,7 @@ export const isEntityFieldEmptyFamilySelector = selectorFamily({ }: { fieldDefinition: Pick< FieldDefinition, - 'type' | 'metadata' | 'fieldMetadataId' | 'label' + 'type' | 'metadata' | 'fieldId' | 'label' >; entityId: string; }) => { diff --git a/front/src/modules/ui/object/field/types/FieldDefinition.ts b/front/src/modules/ui/object/field/types/FieldDefinition.ts index 37b6a618d..92113e5d6 100644 --- a/front/src/modules/ui/object/field/types/FieldDefinition.ts +++ b/front/src/modules/ui/object/field/types/FieldDefinition.ts @@ -5,7 +5,7 @@ import { FieldMetadata } from './FieldMetadata'; import { FieldType } from './FieldType'; export type FieldDefinition = { - fieldMetadataId: string; + fieldId: string; label: string; Icon?: IconComponent; type: FieldType; diff --git a/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownDateSearchInput.tsx b/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownDateSearchInput.tsx index bcad9464e..333d968d3 100644 --- a/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownDateSearchInput.tsx +++ b/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownDateSearchInput.tsx @@ -14,7 +14,7 @@ export const ObjectFilterDropdownDateSearchInput = () => { if (!filterDefinitionUsedInDropdown || !selectedOperandInDropdown) return; selectFilter?.({ - fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId, + fieldId: filterDefinitionUsedInDropdown.fieldId, value: date.toISOString(), operand: selectedOperandInDropdown, displayValue: date.toLocaleDateString(), diff --git a/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownEntitySearchSelect.tsx b/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownEntitySearchSelect.tsx index 9e1b2b627..f697b541c 100644 --- a/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownEntitySearchSelect.tsx +++ b/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownEntitySearchSelect.tsx @@ -42,7 +42,7 @@ export const ObjectFilterDropdownEntitySearchSelect = ({ selectFilter?.({ displayValue: selectedEntity.name, - fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId, + fieldId: filterDefinitionUsedInDropdown.fieldId, operand: selectedOperandInDropdown, value: selectedEntity.id, displayAvatarUrl: selectedEntity.avatarUrl, @@ -72,7 +72,7 @@ export const ObjectFilterDropdownEntitySearchSelect = ({ selectFilter?.({ displayValue: filterDefinitionUsedInDropdown.selectAllLabel, - fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId, + fieldId: filterDefinitionUsedInDropdown.fieldId, operand: ViewFilterOperand.IsNotNull, value: '', definition: filterDefinitionUsedInDropdown, diff --git a/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownNumberSearchInput.tsx b/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownNumberSearchInput.tsx index e4c58a1ad..a7130feb0 100644 --- a/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownNumberSearchInput.tsx +++ b/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownNumberSearchInput.tsx @@ -20,7 +20,7 @@ export const ObjectFilterDropdownNumberSearchInput = () => { placeholder={filterDefinitionUsedInDropdown.label} onChange={(event: ChangeEvent) => { selectFilter?.({ - fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId, + fieldId: filterDefinitionUsedInDropdown.fieldId, value: event.target.value, operand: selectedOperandInDropdown, displayValue: event.target.value, diff --git a/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownOperandSelect.tsx b/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownOperandSelect.tsx index 596efe79c..82ca978d2 100644 --- a/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownOperandSelect.tsx +++ b/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownOperandSelect.tsx @@ -26,7 +26,7 @@ export const ObjectFilterDropdownOperandSelect = () => { if (filterDefinitionUsedInDropdown && selectedFilter) { selectFilter?.({ - fieldMetadataId: selectedFilter.fieldMetadataId, + fieldId: selectedFilter.fieldId, displayValue: selectedFilter.displayValue, operand: newOperand, value: selectedFilter.value, diff --git a/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownTextSearchInput.tsx b/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownTextSearchInput.tsx index f33106cd2..66811672b 100644 --- a/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownTextSearchInput.tsx +++ b/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownTextSearchInput.tsx @@ -26,7 +26,7 @@ export const ObjectFilterDropdownTextSearchInput = () => { setObjectFilterDropdownSearchInput(event.target.value); selectFilter?.({ - fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId, + fieldId: filterDefinitionUsedInDropdown.fieldId, value: event.target.value, operand: selectedOperandInDropdown, displayValue: event.target.value, diff --git a/front/src/modules/ui/object/object-filter-dropdown/types/Filter.ts b/front/src/modules/ui/object/object-filter-dropdown/types/Filter.ts index bb72dfd46..a41fdfdb4 100644 --- a/front/src/modules/ui/object/object-filter-dropdown/types/Filter.ts +++ b/front/src/modules/ui/object/object-filter-dropdown/types/Filter.ts @@ -3,7 +3,7 @@ import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { FilterDefinition } from './FilterDefinition'; export type Filter = { - fieldMetadataId: string; + fieldId: string; value: string; displayValue: string; displayAvatarUrl?: string; diff --git a/front/src/modules/ui/object/object-filter-dropdown/types/FilterDefinition.ts b/front/src/modules/ui/object/object-filter-dropdown/types/FilterDefinition.ts index 6968c509e..dd9bc07f5 100644 --- a/front/src/modules/ui/object/object-filter-dropdown/types/FilterDefinition.ts +++ b/front/src/modules/ui/object/object-filter-dropdown/types/FilterDefinition.ts @@ -3,7 +3,7 @@ import { IconComponent } from '@/ui/display/icon/types/IconComponent'; import { FilterType } from './FilterType'; export type FilterDefinition = { - fieldMetadataId: string; + fieldId: string; label: string; Icon: IconComponent; type: FilterType; diff --git a/front/src/modules/ui/object/object-filter-dropdown/types/FilterDefinitionByEntity.ts b/front/src/modules/ui/object/object-filter-dropdown/types/FilterDefinitionByEntity.ts index 4723227eb..f351f9e01 100644 --- a/front/src/modules/ui/object/object-filter-dropdown/types/FilterDefinitionByEntity.ts +++ b/front/src/modules/ui/object/object-filter-dropdown/types/FilterDefinitionByEntity.ts @@ -1,5 +1,5 @@ import { FilterDefinition } from './FilterDefinition'; export type FilterDefinitionByEntity = FilterDefinition & { - fieldMetadataId: keyof T; + fieldId: keyof T; }; diff --git a/front/src/modules/ui/object/object-filter-dropdown/utils/turnFilterIntoWhereClause.ts b/front/src/modules/ui/object/object-filter-dropdown/utils/turnFilterIntoWhereClause.ts index c0a9e6662..e6c600f4a 100644 --- a/front/src/modules/ui/object/object-filter-dropdown/utils/turnFilterIntoWhereClause.ts +++ b/front/src/modules/ui/object/object-filter-dropdown/utils/turnFilterIntoWhereClause.ts @@ -18,7 +18,7 @@ export const turnFilterIntoWhereClause = ( switch (filter.operand) { case ViewFilterOperand.IsNotNull: return { - [filter.fieldMetadataId]: { + [filter.fieldId]: { not: null, }, }; @@ -28,14 +28,14 @@ export const turnFilterIntoWhereClause = ( switch (filter.operand) { case ViewFilterOperand.Contains: return { - [filter.fieldMetadataId]: { + [filter.fieldId]: { contains: filter.value, mode: QueryMode.Insensitive, }, }; case ViewFilterOperand.DoesNotContain: return { - [filter.fieldMetadataId]: { + [filter.fieldId]: { not: { contains: filter.value, mode: QueryMode.Insensitive, @@ -51,13 +51,13 @@ export const turnFilterIntoWhereClause = ( switch (filter.operand) { case ViewFilterOperand.GreaterThan: return { - [filter.fieldMetadataId]: { + [filter.fieldId]: { gte: parseFloat(filter.value), }, }; case ViewFilterOperand.LessThan: return { - [filter.fieldMetadataId]: { + [filter.fieldId]: { lte: parseFloat(filter.value), }, }; @@ -70,13 +70,13 @@ export const turnFilterIntoWhereClause = ( switch (filter.operand) { case ViewFilterOperand.GreaterThan: return { - [filter.fieldMetadataId]: { + [filter.fieldId]: { gte: filter.value, }, }; case ViewFilterOperand.LessThan: return { - [filter.fieldMetadataId]: { + [filter.fieldId]: { lte: filter.value, }, }; @@ -89,13 +89,13 @@ export const turnFilterIntoWhereClause = ( switch (filter.operand) { case ViewFilterOperand.Is: return { - [filter.fieldMetadataId]: { + [filter.fieldId]: { equals: filter.value, }, }; case ViewFilterOperand.IsNot: return { - [filter.fieldMetadataId]: { + [filter.fieldId]: { not: { equals: filter.value }, }, }; diff --git a/front/src/modules/ui/object/object-filter-dropdown/utils/turnFiltersIntoWhereClauseV2.ts b/front/src/modules/ui/object/object-filter-dropdown/utils/turnFiltersIntoWhereClauseV2.ts index 781fa21ea..145883006 100644 --- a/front/src/modules/ui/object/object-filter-dropdown/utils/turnFiltersIntoWhereClauseV2.ts +++ b/front/src/modules/ui/object/object-filter-dropdown/utils/turnFiltersIntoWhereClauseV2.ts @@ -17,11 +17,11 @@ export const turnFiltersIntoWhereClauseV2 = ( filters.forEach((filter) => { const correspondingField = fields.find( - (field) => field.id === filter.fieldMetadataId, + (field) => field.id === filter.fieldId, ); if (!correspondingField) { throw new Error( - `Could not find field ${filter.fieldMetadataId} in metadata object`, + `Could not find field ${filter.fieldId} in metadata object`, ); } diff --git a/front/src/modules/ui/object/object-sort-dropdown/components/ObjectSortDropdownButton.tsx b/front/src/modules/ui/object/object-sort-dropdown/components/ObjectSortDropdownButton.tsx index bdcabc66f..1586f20af 100644 --- a/front/src/modules/ui/object/object-sort-dropdown/components/ObjectSortDropdownButton.tsx +++ b/front/src/modules/ui/object/object-sort-dropdown/components/ObjectSortDropdownButton.tsx @@ -50,7 +50,7 @@ export const ObjectSortDropdownButton = ({ const handleAddSort = (selectedSortDefinition: SortDefinition) => { toggleDropdown(); onSortSelect?.({ - fieldMetadataId: selectedSortDefinition.fieldMetadataId, + fieldId: selectedSortDefinition.fieldId, direction: selectedSortDirection, definition: selectedSortDefinition, }); diff --git a/front/src/modules/ui/object/object-sort-dropdown/types/Sort.ts b/front/src/modules/ui/object/object-sort-dropdown/types/Sort.ts index 64a6b25da..2f39094b6 100644 --- a/front/src/modules/ui/object/object-sort-dropdown/types/Sort.ts +++ b/front/src/modules/ui/object/object-sort-dropdown/types/Sort.ts @@ -2,7 +2,7 @@ import { SortDefinition } from './SortDefinition'; import { SortDirection } from './SortDirection'; export type Sort = { - fieldMetadataId: string; + fieldId: string; direction: SortDirection; definition: SortDefinition; }; diff --git a/front/src/modules/ui/object/object-sort-dropdown/types/SortDefinition.ts b/front/src/modules/ui/object/object-sort-dropdown/types/SortDefinition.ts index 4fe06f5af..83a1134e8 100644 --- a/front/src/modules/ui/object/object-sort-dropdown/types/SortDefinition.ts +++ b/front/src/modules/ui/object/object-sort-dropdown/types/SortDefinition.ts @@ -3,7 +3,7 @@ import { IconComponent } from '@/ui/display/icon/types/IconComponent'; import { SortDirection } from './SortDirection'; export type SortDefinition = { - fieldMetadataId: string; + fieldId: string; label: string; Icon?: IconComponent; getOrderByTemplate?: (direction: SortDirection) => any[]; diff --git a/front/src/modules/ui/object/object-sort-dropdown/utils/helpers.ts b/front/src/modules/ui/object/object-sort-dropdown/utils/helpers.ts index e5bc4a085..028013941 100644 --- a/front/src/modules/ui/object/object-sort-dropdown/utils/helpers.ts +++ b/front/src/modules/ui/object/object-sort-dropdown/utils/helpers.ts @@ -10,7 +10,7 @@ export const reduceSortsToOrderBy = (sorts: Sort[]): any[] => if (sort.definition.getOrderByTemplate) { return sort.definition.getOrderByTemplate(direction); } else { - return [{ [sort.definition.fieldMetadataId]: direction }]; + return [{ [sort.definition.fieldId]: direction }]; } }) .flat(); diff --git a/front/src/modules/ui/object/object-sort-dropdown/utils/turnSortsIntoOrderByV2.ts b/front/src/modules/ui/object/object-sort-dropdown/utils/turnSortsIntoOrderByV2.ts index b8a90a95b..306a030a2 100644 --- a/front/src/modules/ui/object/object-sort-dropdown/utils/turnSortsIntoOrderByV2.ts +++ b/front/src/modules/ui/object/object-sort-dropdown/utils/turnSortsIntoOrderByV2.ts @@ -9,11 +9,11 @@ export const turnSortsIntoOrderByV2 = ( const sortsObject: Record = {}; sorts.forEach((sort) => { const correspondingField = fields.find( - (field) => field.id === sort.fieldMetadataId, + (field) => field.id === sort.fieldId, ); if (!correspondingField) { throw new Error( - `Could not find field ${sort.fieldMetadataId} in metadata object`, + `Could not find field ${sort.fieldId} in metadata object`, ); } const direction = diff --git a/front/src/modules/ui/object/record-table/components/ColumnHeadWithDropdown.tsx b/front/src/modules/ui/object/record-table/components/ColumnHeadWithDropdown.tsx index dd84a7fef..4f92fc954 100644 --- a/front/src/modules/ui/object/record-table/components/ColumnHeadWithDropdown.tsx +++ b/front/src/modules/ui/object/record-table/components/ColumnHeadWithDropdown.tsx @@ -21,7 +21,7 @@ export const ColumnHeadWithDropdown = ({ primaryColumnKey, }: ColumnHeadWithDropdownProps) => { return ( - + } dropdownComponents={ @@ -34,7 +34,7 @@ export const ColumnHeadWithDropdown = ({ } dropdownOffset={{ x: -1 }} dropdownPlacement="bottom-start" - dropdownHotkeyScope={{ scope: column.fieldMetadataId + '-header' }} + dropdownHotkeyScope={{ scope: column.fieldId + '-header' }} /> ); diff --git a/front/src/modules/ui/object/record-table/components/RecordTableColumnDropdownMenu.tsx b/front/src/modules/ui/object/record-table/components/RecordTableColumnDropdownMenu.tsx index 902b7a01d..ad2ba13a1 100644 --- a/front/src/modules/ui/object/record-table/components/RecordTableColumnDropdownMenu.tsx +++ b/front/src/modules/ui/object/record-table/components/RecordTableColumnDropdownMenu.tsx @@ -46,7 +46,7 @@ export const RecordTableColumnDropdownMenu = ({ handleColumnVisibilityChange(column); }; - return column.fieldMetadataId === primaryColumnKey ? ( + return column.fieldId === primaryColumnKey ? ( <> ) : ( diff --git a/front/src/modules/ui/object/record-table/components/RecordTableHeader.tsx b/front/src/modules/ui/object/record-table/components/RecordTableHeader.tsx index 196e6f17d..0fbbae3a1 100644 --- a/front/src/modules/ui/object/record-table/components/RecordTableHeader.tsx +++ b/front/src/modules/ui/object/record-table/components/RecordTableHeader.tsx @@ -156,7 +156,7 @@ export const RecordTableHeader = () => { if (nextWidth !== tableColumnsByKey[resizedFieldKey].size) { const nextColumns = tableColumns.map((column) => - column.fieldMetadataId === resizedFieldKey + column.fieldId === resizedFieldKey ? { ...column, size: nextWidth } : column, ); @@ -194,13 +194,11 @@ export const RecordTableHeader = () => { {visibleTableColumns.map((column) => ( @@ -211,21 +209,20 @@ export const RecordTableHeader = () => { isLastColumn={ column.position === visibleTableColumns.length - 1 } - primaryColumnKey={primaryColumn?.fieldMetadataId || ''} + primaryColumnKey={primaryColumn?.fieldId || ''} /> { - setResizedFieldKey(column.fieldMetadataId); + setResizedFieldKey(column.fieldId); }} /> ))} - - - {hiddenTableColumns.length > 0 && ( + {hiddenTableColumns.length > 0 && ( + @@ -242,8 +239,8 @@ export const RecordTableHeader = () => { }} /> - )} - + + )} ); diff --git a/front/src/modules/ui/object/record-table/components/RecordTableHeaderPlusButtonContent.tsx b/front/src/modules/ui/object/record-table/components/RecordTableHeaderPlusButtonContent.tsx index 2be385f24..cb9b1b791 100644 --- a/front/src/modules/ui/object/record-table/components/RecordTableHeaderPlusButtonContent.tsx +++ b/front/src/modules/ui/object/record-table/components/RecordTableHeaderPlusButtonContent.tsx @@ -32,7 +32,7 @@ export const RecordTableHeaderPlusButtonContent = () => { {hiddenTableColumns.map((column) => ( columnA.position - columnB.position) .map((column, columnIndex) => { return ( - + ); diff --git a/front/src/modules/ui/object/record-table/hooks/useTableColumns.ts b/front/src/modules/ui/object/record-table/hooks/useTableColumns.ts index ced3ebe54..1e8f380de 100644 --- a/front/src/modules/ui/object/record-table/hooks/useTableColumns.ts +++ b/front/src/modules/ui/object/record-table/hooks/useTableColumns.ts @@ -47,14 +47,13 @@ export const useTableColumns = () => { viewField: Omit, 'size' | 'position'>, ) => { const isNewColumn = !tableColumns.some( - (tableColumns) => - tableColumns.fieldMetadataId === viewField.fieldMetadataId, + (tableColumns) => tableColumns.fieldId === viewField.fieldId, ); if (isNewColumn) { const newColumn = availableTableColumns.find( (availableTableColumn) => - availableTableColumn.fieldMetadataId === viewField.fieldMetadataId, + availableTableColumn.fieldId === viewField.fieldId, ); if (!newColumn) return; @@ -66,7 +65,7 @@ export const useTableColumns = () => { await handleColumnsChange(nextColumns); } else { const nextColumns = tableColumns.map((previousColumn) => - previousColumn.fieldMetadataId === viewField.fieldMetadataId + previousColumn.fieldId === viewField.fieldId ? { ...previousColumn, isVisible: !viewField.isVisible } : previousColumn, ); @@ -83,8 +82,7 @@ export const useTableColumns = () => { column: ColumnDefinition, ) => { const currentColumnArrayIndex = visibleTableColumns.findIndex( - (visibleColumn) => - visibleColumn.fieldMetadataId === column.fieldMetadataId, + (visibleColumn) => visibleColumn.fieldId === column.fieldId, ); const columns = handleColumnMove( diff --git a/front/src/modules/ui/object/record-table/record-table-cell/hooks/useTableCell.ts b/front/src/modules/ui/object/record-table/record-table-cell/hooks/useTableCell.ts index b578bbacf..9b7d357ac 100644 --- a/front/src/modules/ui/object/record-table/record-table-cell/hooks/useTableCell.ts +++ b/front/src/modules/ui/object/record-table/record-table-cell/hooks/useTableCell.ts @@ -42,7 +42,7 @@ export const useTableCell = () => { const [, setFieldInitialValue] = useRecoilState( entityFieldInitialValueFamilyState({ entityId, - fieldMetadataId: fieldDefinition.fieldMetadataId, + fieldId: fieldDefinition.fieldId, }), ); diff --git a/front/src/modules/ui/object/record-table/states/selectors/hiddenTableColumnsScopedSelector.ts b/front/src/modules/ui/object/record-table/states/selectors/hiddenTableColumnsScopedSelector.ts index 658bf6e30..d672233f8 100644 --- a/front/src/modules/ui/object/record-table/states/selectors/hiddenTableColumnsScopedSelector.ts +++ b/front/src/modules/ui/object/record-table/states/selectors/hiddenTableColumnsScopedSelector.ts @@ -9,10 +9,10 @@ export const hiddenTableColumnsScopedSelector = selectorFamily({ (scopeId: string) => ({ get }) => { const columns = get(tableColumnsScopedState({ scopeId })); - const columnKeys = columns.map(({ fieldMetadataId }) => fieldMetadataId); + const columnKeys = columns.map(({ fieldId }) => fieldId); const otherAvailableColumns = get( availableTableColumnsScopedState({ scopeId }), - ).filter(({ fieldMetadataId }) => !columnKeys.includes(fieldMetadataId)); + ).filter(({ fieldId }) => !columnKeys.includes(fieldId)); return [ ...columns.filter((column) => !column.isVisible), diff --git a/front/src/modules/ui/object/record-table/states/selectors/savedTableColumnsByKeyFamilySelector.ts b/front/src/modules/ui/object/record-table/states/selectors/savedTableColumnsByKeyFamilySelector.ts index 094d74f62..1b8f121f8 100644 --- a/front/src/modules/ui/object/record-table/states/selectors/savedTableColumnsByKeyFamilySelector.ts +++ b/front/src/modules/ui/object/record-table/states/selectors/savedTableColumnsByKeyFamilySelector.ts @@ -12,8 +12,5 @@ export const savedTableColumnsByKeyFamilySelector = selectorFamily({ ({ get }) => get(savedTableColumnsFamilyState(viewId)).reduce< Record> - >( - (result, column) => ({ ...result, [column.fieldMetadataId]: column }), - {}, - ), + >((result, column) => ({ ...result, [column.fieldId]: column }), {}), }); diff --git a/front/src/modules/ui/object/record-table/states/selectors/tableColumnsByKeyScopedSelector.ts b/front/src/modules/ui/object/record-table/states/selectors/tableColumnsByKeyScopedSelector.ts index 7e4ab5826..419e32b55 100644 --- a/front/src/modules/ui/object/record-table/states/selectors/tableColumnsByKeyScopedSelector.ts +++ b/front/src/modules/ui/object/record-table/states/selectors/tableColumnsByKeyScopedSelector.ts @@ -12,8 +12,5 @@ export const tableColumnsByKeyScopedSelector = selectorFamily({ ({ get }) => get(tableColumnsScopedState({ scopeId })).reduce< Record> - >( - (result, column) => ({ ...result, [column.fieldMetadataId]: column }), - {}, - ), + >((result, column) => ({ ...result, [column.fieldId]: column }), {}), }); diff --git a/front/src/modules/ui/object/record-table/states/selectors/visibleTableColumnsScopedSelector.ts b/front/src/modules/ui/object/record-table/states/selectors/visibleTableColumnsScopedSelector.ts index 348f371d8..476a1a1d3 100644 --- a/front/src/modules/ui/object/record-table/states/selectors/visibleTableColumnsScopedSelector.ts +++ b/front/src/modules/ui/object/record-table/states/selectors/visibleTableColumnsScopedSelector.ts @@ -11,13 +11,12 @@ export const visibleTableColumnsScopedSelector = selectorFamily({ const columns = get(tableColumnsScopedState({ scopeId })); const availableColumnKeys = get( availableTableColumnsScopedState({ scopeId }), - ).map(({ fieldMetadataId }) => fieldMetadataId); + ).map(({ fieldId }) => fieldId); return [...columns] .filter( (column) => - column.isVisible && - availableColumnKeys.includes(column.fieldMetadataId), + column.isVisible && availableColumnKeys.includes(column.fieldId), ) .sort((a, b) => a.position - b.position); }, diff --git a/front/src/modules/views/components/ViewBarDetails.tsx b/front/src/modules/views/components/ViewBarDetails.tsx index a362e50f7..97a254284 100644 --- a/front/src/modules/views/components/ViewBarDetails.tsx +++ b/front/src/modules/views/components/ViewBarDetails.tsx @@ -126,12 +126,12 @@ export const ViewBarDetails = ({ {currentViewSorts?.map((sort) => { return ( removeViewSort(sort.fieldMetadataId)} + onRemove={() => removeViewSort(sort.fieldId)} /> ); })} @@ -143,15 +143,15 @@ export const ViewBarDetails = ({ {currentViewFilters?.map((filter) => { return ( { - removeViewFilter(filter.fieldMetadataId); + removeViewFilter(filter.fieldId); }} /> ); diff --git a/front/src/modules/views/components/ViewBarEffect.tsx b/front/src/modules/views/components/ViewBarEffect.tsx index fa074ab98..24e97e52a 100644 --- a/front/src/modules/views/components/ViewBarEffect.tsx +++ b/front/src/modules/views/components/ViewBarEffect.tsx @@ -35,14 +35,14 @@ export const ViewBarEffect = () => { useFindManyObjects({ objectNamePlural: 'viewsV2', - filter: { type: { eq: viewType }, objectMetadataId: { eq: viewObjectId } }, + filter: { type: { eq: viewType }, objectId: { eq: viewObjectId } }, onCompleted: useRecoilCallback( ({ snapshot, set }) => async (data: PaginatedObjectTypeResults) => { const nextViews = data.edges.map((view) => ({ id: view.node.id, name: view.node.name, - objectMetadataId: view.node.objectMetadataId, + objectId: view.node.objectId, })); const { viewsState } = getViewScopedStatesFromSnapshot({ @@ -132,8 +132,7 @@ export const ViewBarEffect = () => { const queriedViewFilters = data.edges .map(({ node }) => { const availableFilterDefinition = availableFilterDefinitions.find( - (filterDefinition) => - filterDefinition.fieldMetadataId === node.fieldMetadataId, + (filterDefinition) => filterDefinition.fieldId === node.fieldId, ); if (!availableFilterDefinition) return null; @@ -186,14 +185,14 @@ export const ViewBarEffect = () => { const queriedViewSorts = data.edges .map(({ node }) => { const availableSortDefinition = availableSortDefinitions.find( - (sort) => sort.fieldMetadataId === node.fieldMetadataId, + (sort) => sort.fieldId === node.fieldId, ); if (!availableSortDefinition) return null; return { id: node.id, - fieldMetadataId: node.fieldMetadataId, + fieldId: node.fieldId, direction: node.direction, definition: availableSortDefinition, }; diff --git a/front/src/modules/views/components/ViewFieldsVisibilityDropdownSection.tsx b/front/src/modules/views/components/ViewFieldsVisibilityDropdownSection.tsx index bcfe9a537..a8eab87b7 100644 --- a/front/src/modules/views/components/ViewFieldsVisibilityDropdownSection.tsx +++ b/front/src/modules/views/components/ViewFieldsVisibilityDropdownSection.tsx @@ -97,12 +97,12 @@ export const ViewFieldsVisibilityDropdownSection = ({ .sort((a, b) => a.position - b.position) .map((field, index) => ( ( { mutation: createOneMutation, variables: { input: { - fieldMetadataId: viewField.fieldMetadataId, + fieldId: viewField.fieldId, viewId: viewIdToPersist, isVisible: viewField.isVisible, size: viewField.size, @@ -76,18 +76,18 @@ export const useViewFields = (viewScopeId: string) => { }; const viewFieldsToCreate = viewFieldsToPersist.filter( - (viewField) => !savedViewFieldsByKey[viewField.fieldMetadataId], + (viewField) => !savedViewFieldsByKey[viewField.fieldId], ); const viewFieldsToUpdate = viewFieldsToPersist.filter( (viewFieldToPersit) => - savedViewFieldsByKey[viewFieldToPersit.fieldMetadataId] && - (savedViewFieldsByKey[viewFieldToPersit.fieldMetadataId].size !== + savedViewFieldsByKey[viewFieldToPersit.fieldId] && + (savedViewFieldsByKey[viewFieldToPersit.fieldId].size !== viewFieldToPersit.size || - savedViewFieldsByKey[viewFieldToPersit.fieldMetadataId] - .position !== viewFieldToPersit.position || - savedViewFieldsByKey[viewFieldToPersit.fieldMetadataId] - .isVisible !== viewFieldToPersit.isVisible), + savedViewFieldsByKey[viewFieldToPersit.fieldId].position !== + viewFieldToPersit.position || + savedViewFieldsByKey[viewFieldToPersit.fieldId].isVisible !== + viewFieldToPersit.isVisible), ); await _createViewFields(viewFieldsToCreate); diff --git a/front/src/modules/views/hooks/internal/useViewFilters.ts b/front/src/modules/views/hooks/internal/useViewFilters.ts index 8ec7d7620..e1354347b 100644 --- a/front/src/modules/views/hooks/internal/useViewFilters.ts +++ b/front/src/modules/views/hooks/internal/useViewFilters.ts @@ -53,7 +53,7 @@ export const useViewFilters = (viewScopeId: string) => { mutation: createOneMutation, variables: { input: { - fieldMetadataId: viewFilter.fieldMetadataId, + fieldId: viewFilter.fieldId, viewId: viewId ?? currentViewId, value: viewFilter.value, displayValue: viewFilter.displayValue, @@ -102,23 +102,19 @@ export const useViewFilters = (viewScopeId: string) => { }; const filtersToCreate = currentViewFilters.filter( - (filter) => !savedViewFiltersByKey[filter.fieldMetadataId], + (filter) => !savedViewFiltersByKey[filter.fieldId], ); await createViewFilters(filtersToCreate); const filtersToUpdate = currentViewFilters.filter( (filter) => - savedViewFiltersByKey[filter.fieldMetadataId] && - (savedViewFiltersByKey[filter.fieldMetadataId].operand !== - filter.operand || - savedViewFiltersByKey[filter.fieldMetadataId].value !== - filter.value), + savedViewFiltersByKey[filter.fieldId] && + (savedViewFiltersByKey[filter.fieldId].operand !== filter.operand || + savedViewFiltersByKey[filter.fieldId].value !== filter.value), ); await updateViewFilters(filtersToUpdate); - const filterKeys = currentViewFilters.map( - (filter) => filter.fieldMetadataId, - ); + const filterKeys = currentViewFilters.map((filter) => filter.fieldId); const filterKeysToDelete = Object.keys(savedViewFiltersByKey).filter( (previousFilterKey) => !filterKeys.includes(previousFilterKey), ); @@ -163,13 +159,12 @@ export const useViewFilters = (viewScopeId: string) => { } const existingSavedFilterId = - savedViewFiltersByKey[filterToUpsert.fieldMetadataId]?.id; + savedViewFiltersByKey[filterToUpsert.fieldId]?.id; set(currentViewFiltersState, (filters) => { const newViewFilters = produce(filters, (filtersDraft) => { const existingFilterIndex = filtersDraft.findIndex( - (filter) => - filter.fieldMetadataId === filterToUpsert.fieldMetadataId, + (filter) => filter.fieldId === filterToUpsert.fieldId, ); if (existingFilterIndex === -1) { @@ -194,7 +189,7 @@ export const useViewFilters = (viewScopeId: string) => { const removeViewFilter = useRecoilCallback( ({ snapshot, set }) => - (fieldMetadataId: string) => { + (fieldId: string) => { const { currentViewId, currentViewFilters, onViewFiltersChange } = getViewScopedStateValuesFromSnapshot({ snapshot, @@ -206,7 +201,7 @@ export const useViewFilters = (viewScopeId: string) => { } const newViewFilters = currentViewFilters.filter((filter) => { - return filter.fieldMetadataId !== fieldMetadataId; + return filter.fieldId !== fieldId; }); set(currentViewFiltersState, newViewFilters); onViewFiltersChange?.(newViewFilters); diff --git a/front/src/modules/views/hooks/internal/useViewSorts.ts b/front/src/modules/views/hooks/internal/useViewSorts.ts index 9e308f808..3b815764e 100644 --- a/front/src/modules/views/hooks/internal/useViewSorts.ts +++ b/front/src/modules/views/hooks/internal/useViewSorts.ts @@ -54,7 +54,7 @@ export const useViewSorts = (viewScopeId: string) => { mutation: createOneMutation, variables: { input: { - fieldMetadataId: viewSort.fieldMetadataId, + fieldId: viewSort.fieldId, viewId: viewId ?? currentViewId, direction: viewSort.direction, }, @@ -99,20 +99,19 @@ export const useViewSorts = (viewScopeId: string) => { }; const sortsToCreate = currentViewSorts.filter( - (sort) => !savedViewSortsByKey[sort.fieldMetadataId], + (sort) => !savedViewSortsByKey[sort.fieldId], ); await createViewSorts(sortsToCreate); const sortsToUpdate = currentViewSorts.filter( (sort) => - savedViewSortsByKey[sort.fieldMetadataId] && - savedViewSortsByKey[sort.fieldMetadataId].direction !== - sort.direction, + savedViewSortsByKey[sort.fieldId] && + savedViewSortsByKey[sort.fieldId].direction !== sort.direction, ); await updateViewSorts(sortsToUpdate); - const sortKeys = currentViewSorts.map((sort) => sort.fieldMetadataId); + const sortKeys = currentViewSorts.map((sort) => sort.fieldId); const sortKeysToDelete = Object.keys(savedViewSortsByKey).filter( (previousSortKey) => !sortKeys.includes(previousSortKey), ); @@ -156,12 +155,12 @@ export const useViewSorts = (viewScopeId: string) => { } const existingSavedSortId = - savedViewSortsByKey[sortToUpsert.fieldMetadataId]?.id; + savedViewSortsByKey[sortToUpsert.fieldId]?.id; set(currentViewSortsState, (sorts) => { const newViewSorts = produce(sorts, (sortsDraft) => { const existingSortIndex = sortsDraft.findIndex( - (sort) => sort.fieldMetadataId === sortToUpsert.fieldMetadataId, + (sort) => sort.fieldId === sortToUpsert.fieldId, ); if (existingSortIndex === -1) { @@ -183,7 +182,7 @@ export const useViewSorts = (viewScopeId: string) => { const removeViewSort = useRecoilCallback( ({ snapshot, set }) => - (fieldMetadataId: string) => { + (fieldId: string) => { const { currentViewId, onViewSortsChange, currentViewSorts } = getViewScopedStateValuesFromSnapshot({ snapshot, @@ -195,7 +194,7 @@ export const useViewSorts = (viewScopeId: string) => { } const newViewSorts = currentViewSorts.filter((filter) => { - return filter.fieldMetadataId !== fieldMetadataId; + return filter.fieldId !== fieldId; }); set(currentViewSortsState, newViewSorts); onViewSortsChange?.(newViewSorts); diff --git a/front/src/modules/views/hooks/internal/useViews.ts b/front/src/modules/views/hooks/internal/useViews.ts index a41edf623..5190607b3 100644 --- a/front/src/modules/views/hooks/internal/useViews.ts +++ b/front/src/modules/views/hooks/internal/useViews.ts @@ -34,7 +34,7 @@ export const useViews = (scopeId: string) => { variables: { input: { ...view, - objectMetadataId: viewObjectId, + objectId: viewObjectId, type: viewType, }, }, diff --git a/front/src/modules/views/states/selectors/savedViewFieldByKeyScopedFamilySelector.ts b/front/src/modules/views/states/selectors/savedViewFieldByKeyScopedFamilySelector.ts index fc56e7fde..aba69d834 100644 --- a/front/src/modules/views/states/selectors/savedViewFieldByKeyScopedFamilySelector.ts +++ b/front/src/modules/views/states/selectors/savedViewFieldByKeyScopedFamilySelector.ts @@ -25,7 +25,7 @@ export const savedViewFieldByKeyScopedFamilySelector = selectorFamily({ familyKey: viewId, }), ).reduce>( - (result, column) => ({ ...result, [column.fieldMetadataId]: column }), + (result, column) => ({ ...result, [column.fieldId]: column }), {}, ); }, diff --git a/front/src/modules/views/states/selectors/savedViewFiltersByKeyScopedFamilySelector.ts b/front/src/modules/views/states/selectors/savedViewFiltersByKeyScopedFamilySelector.ts index 235d5375f..d7e03a0bb 100644 --- a/front/src/modules/views/states/selectors/savedViewFiltersByKeyScopedFamilySelector.ts +++ b/front/src/modules/views/states/selectors/savedViewFiltersByKeyScopedFamilySelector.ts @@ -18,7 +18,7 @@ export const savedViewFiltersByKeyScopedFamilySelector = selectorFamily({ familyKey: viewId, }), ).reduce>( - (result, filter) => ({ ...result, [filter.fieldMetadataId]: filter }), + (result, filter) => ({ ...result, [filter.fieldId]: filter }), {}, ); }, diff --git a/front/src/modules/views/states/selectors/savedViewSortsByKeyScopedFamilySelector.ts b/front/src/modules/views/states/selectors/savedViewSortsByKeyScopedFamilySelector.ts index 2348464d4..cdfe2bfae 100644 --- a/front/src/modules/views/states/selectors/savedViewSortsByKeyScopedFamilySelector.ts +++ b/front/src/modules/views/states/selectors/savedViewSortsByKeyScopedFamilySelector.ts @@ -18,7 +18,7 @@ export const savedViewSortsByKeyScopedFamilySelector = selectorFamily({ familyKey: viewId, }), ).reduce>( - (result, sort) => ({ ...result, [sort.fieldMetadataId]: sort }), + (result, sort) => ({ ...result, [sort.fieldId]: sort }), {}, ); }, diff --git a/front/src/modules/views/types/View.ts b/front/src/modules/views/types/View.ts index c2e312219..484b49db7 100644 --- a/front/src/modules/views/types/View.ts +++ b/front/src/modules/views/types/View.ts @@ -1 +1 @@ -export type View = { id: string; name: string; objectMetadataId: string }; +export type View = { id: string; name: string; objectId: string }; diff --git a/front/src/modules/views/types/ViewField.ts b/front/src/modules/views/types/ViewField.ts index 536796da9..c7d3c1aa6 100644 --- a/front/src/modules/views/types/ViewField.ts +++ b/front/src/modules/views/types/ViewField.ts @@ -3,7 +3,7 @@ import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinitio export type ViewField = { id: string; - fieldMetadataId: string; + fieldId: string; position: number; isVisible: boolean; size: number; diff --git a/front/src/modules/views/types/ViewFilter.ts b/front/src/modules/views/types/ViewFilter.ts index 49e78ee1f..44c3edb76 100644 --- a/front/src/modules/views/types/ViewFilter.ts +++ b/front/src/modules/views/types/ViewFilter.ts @@ -4,7 +4,7 @@ import { ViewFilterOperand } from './ViewFilterOperand'; export type ViewFilter = { id?: string; - fieldMetadataId: string; + fieldId: string; operand: ViewFilterOperand; value: string; displayValue: string; diff --git a/front/src/modules/views/types/ViewSort.ts b/front/src/modules/views/types/ViewSort.ts index e2b2581d2..8e486c717 100644 --- a/front/src/modules/views/types/ViewSort.ts +++ b/front/src/modules/views/types/ViewSort.ts @@ -3,7 +3,7 @@ import { SortDirection } from '@/ui/object/object-sort-dropdown/types/SortDirect export type ViewSort = { id?: string; - fieldMetadataId: string; + fieldId: string; direction: SortDirection; definition: SortDefinition; }; diff --git a/front/src/modules/views/utils/mapColumnDefinitionToViewField.ts b/front/src/modules/views/utils/mapColumnDefinitionToViewField.ts index 470bd42f3..7e4ed2a70 100644 --- a/front/src/modules/views/utils/mapColumnDefinitionToViewField.ts +++ b/front/src/modules/views/utils/mapColumnDefinitionToViewField.ts @@ -8,7 +8,7 @@ export const mapColumnDefinitionsToViewFields = ( ): ViewField[] => { return columnDefinitions.map((columnDefinition) => ({ id: columnDefinition.viewFieldId || '', - fieldMetadataId: columnDefinition.fieldMetadataId, + fieldId: columnDefinition.fieldId, position: columnDefinition.position, size: columnDefinition.size, isVisible: columnDefinition.isVisible ?? true, diff --git a/front/src/modules/views/utils/mapViewFieldsToBoardFieldDefinitions.ts b/front/src/modules/views/utils/mapViewFieldsToBoardFieldDefinitions.ts index be4f29909..700c477be 100644 --- a/front/src/modules/views/utils/mapViewFieldsToBoardFieldDefinitions.ts +++ b/front/src/modules/views/utils/mapViewFieldsToBoardFieldDefinitions.ts @@ -11,12 +11,12 @@ export const mapViewFieldsToBoardFieldDefinitions = ( return viewFields .map((viewField) => { const correspondingFieldMetadata = fieldsMetadata.find( - ({ fieldMetadataId }) => viewField.fieldMetadataId === fieldMetadataId, + ({ fieldId }) => viewField.fieldId === fieldId, ); return correspondingFieldMetadata ? { - fieldMetadataId: viewField.fieldMetadataId, + fieldId: viewField.fieldId, label: correspondingFieldMetadata.label, metadata: correspondingFieldMetadata.metadata, entityChipDisplayMapper: diff --git a/front/src/modules/views/utils/mapViewFieldsToColumnDefinitions.ts b/front/src/modules/views/utils/mapViewFieldsToColumnDefinitions.ts index d3119a6ee..901b07e05 100644 --- a/front/src/modules/views/utils/mapViewFieldsToColumnDefinitions.ts +++ b/front/src/modules/views/utils/mapViewFieldsToColumnDefinitions.ts @@ -11,12 +11,12 @@ export const mapViewFieldsToColumnDefinitions = ( return viewFields .map((viewField) => { const correspondingFieldMetadata = fieldsMetadata.find( - ({ fieldMetadataId }) => viewField.fieldMetadataId === fieldMetadataId, + ({ fieldId }) => viewField.fieldId === fieldId, ); return correspondingFieldMetadata ? { - fieldMetadataId: viewField.fieldMetadataId, + fieldId: viewField.fieldId, label: correspondingFieldMetadata.label, metadata: correspondingFieldMetadata.metadata, entityChipDisplayMapper: diff --git a/front/src/modules/views/utils/mapViewFiltersToFilters.ts b/front/src/modules/views/utils/mapViewFiltersToFilters.ts index 00ae87913..fcc1144c2 100644 --- a/front/src/modules/views/utils/mapViewFiltersToFilters.ts +++ b/front/src/modules/views/utils/mapViewFiltersToFilters.ts @@ -7,7 +7,7 @@ export const mapViewFiltersToFilters = ( ): Filter[] => { return viewFilters.map((viewFilter) => { return { - fieldMetadataId: viewFilter.fieldMetadataId, + fieldId: viewFilter.fieldId, value: viewFilter.value, displayValue: viewFilter.displayValue, operand: viewFilter.operand, diff --git a/front/src/modules/views/utils/mapViewSortsToSorts.ts b/front/src/modules/views/utils/mapViewSortsToSorts.ts index d49250054..360d0df19 100644 --- a/front/src/modules/views/utils/mapViewSortsToSorts.ts +++ b/front/src/modules/views/utils/mapViewSortsToSorts.ts @@ -5,7 +5,7 @@ import { ViewSort } from '../types/ViewSort'; export const mapViewSortsToSorts = (viewSorts: ViewSort[]): Sort[] => { return viewSorts.map((viewSort) => { return { - fieldMetadataId: viewSort.fieldMetadataId, + fieldId: viewSort.fieldId, direction: viewSort.direction, definition: viewSort.definition, }; diff --git a/front/src/pages/companies/CompanyShow.tsx b/front/src/pages/companies/CompanyShow.tsx index e3a9e0e23..ec02de3e9 100644 --- a/front/src/pages/companies/CompanyShow.tsx +++ b/front/src/pages/companies/CompanyShow.tsx @@ -93,11 +93,10 @@ export const CompanyShow = () => { {companyShowFieldDefinitions.map((fieldDefinition) => { return ( [] = [ { - fieldMetadataId: 'domainName', + fieldId: 'domainName', label: 'Domain name', Icon: IconLink, type: 'URL', @@ -32,7 +32,7 @@ export const companyShowFieldDefinitions: FieldDefinition[] = [ }, } satisfies FieldDefinition, { - fieldMetadataId: 'accountOwner', + fieldId: 'accountOwner', label: 'Account owner', Icon: IconUserCircle, type: 'RELATION', @@ -49,7 +49,7 @@ export const companyShowFieldDefinitions: FieldDefinition[] = [ }, } satisfies FieldDefinition, { - fieldMetadataId: 'employees', + fieldId: 'employees', label: 'Employees', Icon: IconUsers, type: 'NUMBER', @@ -59,7 +59,7 @@ export const companyShowFieldDefinitions: FieldDefinition[] = [ }, } satisfies FieldDefinition, { - fieldMetadataId: 'address', + fieldId: 'address', label: 'Address', Icon: IconMap, type: 'TEXT', @@ -69,7 +69,7 @@ export const companyShowFieldDefinitions: FieldDefinition[] = [ }, } satisfies FieldDefinition, { - fieldMetadataId: 'idealCustomerProfile', + fieldId: 'idealCustomerProfile', label: 'ICP', Icon: IconTarget, type: 'BOOLEAN', @@ -78,7 +78,7 @@ export const companyShowFieldDefinitions: FieldDefinition[] = [ }, } satisfies FieldDefinition, { - fieldMetadataId: 'xUrl', + fieldId: 'xUrl', label: 'Twitter', Icon: IconBrandX, type: 'URL', @@ -88,7 +88,7 @@ export const companyShowFieldDefinitions: FieldDefinition[] = [ }, } satisfies FieldDefinition, { - fieldMetadataId: 'createdAt', + fieldId: 'createdAt', label: 'Created at', Icon: IconCalendar, type: 'DATE', diff --git a/front/src/pages/companies/constants/companyTableFilterDefinitions.tsx b/front/src/pages/companies/constants/companyTableFilterDefinitions.tsx index ace176c23..8a467c913 100644 --- a/front/src/pages/companies/constants/companyTableFilterDefinitions.tsx +++ b/front/src/pages/companies/constants/companyTableFilterDefinitions.tsx @@ -13,37 +13,37 @@ import { Company } from '~/generated/graphql'; export const companyTableFilterDefinitions: FilterDefinitionByEntity[] = [ { - fieldMetadataId: 'name', + fieldId: 'name', label: 'Name', Icon: IconBuildingSkyscraper, type: 'TEXT', }, { - fieldMetadataId: 'employees', + fieldId: 'employees', label: 'Employees', Icon: IconUsers, type: 'NUMBER', }, { - fieldMetadataId: 'domainName', + fieldId: 'domainName', label: 'URL', Icon: IconLink, type: 'TEXT', }, { - fieldMetadataId: 'address', + fieldId: 'address', label: 'Address', Icon: IconMap, type: 'TEXT', }, { - fieldMetadataId: 'createdAt', + fieldId: 'createdAt', label: 'Created at', Icon: IconCalendarEvent, type: 'DATE', }, { - fieldMetadataId: 'accountOwnerId', + fieldId: 'accountOwnerId', label: 'Account owner', Icon: IconUser, type: 'ENTITY', diff --git a/front/src/pages/companies/constants/companyTableSortDefinitions.tsx b/front/src/pages/companies/constants/companyTableSortDefinitions.tsx index 284ababfb..b2e999338 100644 --- a/front/src/pages/companies/constants/companyTableSortDefinitions.tsx +++ b/front/src/pages/companies/constants/companyTableSortDefinitions.tsx @@ -9,27 +9,27 @@ import { SortDefinition } from '@/ui/object/object-sort-dropdown/types/SortDefin export const companyTableSortDefinitions: SortDefinition[] = [ { - fieldMetadataId: 'name', + fieldId: 'name', label: 'Name', Icon: IconBuildingSkyscraper, }, { - fieldMetadataId: 'employees', + fieldId: 'employees', label: 'Employees', Icon: IconUsers, }, { - fieldMetadataId: 'domainName', + fieldId: 'domainName', label: 'Url', Icon: IconLink, }, { - fieldMetadataId: 'address', + fieldId: 'address', label: 'Address', Icon: IconMap, }, { - fieldMetadataId: 'createdAt', + fieldId: 'createdAt', label: 'Creation', Icon: IconCalendarEvent, }, diff --git a/front/src/pages/opportunities/constants/opportunityBoardFilterDefinitions.tsx b/front/src/pages/opportunities/constants/opportunityBoardFilterDefinitions.tsx index 17218af0c..00210f28e 100644 --- a/front/src/pages/opportunities/constants/opportunityBoardFilterDefinitions.tsx +++ b/front/src/pages/opportunities/constants/opportunityBoardFilterDefinitions.tsx @@ -13,26 +13,26 @@ import { FilterDropdownPeopleSearchSelect } from '../../../modules/people/compon export const opportunityBoardFilterDefinitions: FilterDefinitionByEntity[] = [ { - fieldMetadataId: 'amount', + fieldId: 'amount', label: 'Amount', Icon: IconCurrencyDollar, type: 'NUMBER', }, { - fieldMetadataId: 'closeDate', + fieldId: 'closeDate', label: 'Close date', Icon: IconCalendarEvent, type: 'DATE', }, { - fieldMetadataId: 'companyId', + fieldId: 'companyId', label: 'Company', Icon: IconBuildingSkyscraper, type: 'ENTITY', entitySelectComponent: , }, { - fieldMetadataId: 'pointOfContactId', + fieldId: 'pointOfContactId', label: 'Point of contact', Icon: IconUser, type: 'ENTITY', diff --git a/front/src/pages/opportunities/constants/opportunityBoardSortDefinitions.tsx b/front/src/pages/opportunities/constants/opportunityBoardSortDefinitions.tsx index cc75e15e0..4cd9de0d3 100644 --- a/front/src/pages/opportunities/constants/opportunityBoardSortDefinitions.tsx +++ b/front/src/pages/opportunities/constants/opportunityBoardSortDefinitions.tsx @@ -3,17 +3,17 @@ import { SortDefinition } from '@/ui/object/object-sort-dropdown/types/SortDefin export const opportunityBoardSortDefinitions: SortDefinition[] = [ { - fieldMetadataId: 'createdAt', + fieldId: 'createdAt', label: 'Creation', Icon: IconCalendarEvent, }, { - fieldMetadataId: 'amount', + fieldId: 'amount', label: 'Amount', Icon: IconCurrencyDollar, }, { - fieldMetadataId: 'closeDate', + fieldId: 'closeDate', label: 'Expected close date', Icon: IconCalendarEvent, }, diff --git a/front/src/pages/people/constants/personShowFieldDefinitions.tsx b/front/src/pages/people/constants/personShowFieldDefinitions.tsx index 08abc5ac7..38a4ed0c4 100644 --- a/front/src/pages/people/constants/personShowFieldDefinitions.tsx +++ b/front/src/pages/people/constants/personShowFieldDefinitions.tsx @@ -23,7 +23,7 @@ import { getLogoUrlFromDomainName } from '~/utils'; export const personShowFieldDefinition: FieldDefinition[] = [ { - fieldMetadataId: 'email', + fieldId: 'email', label: 'Email', Icon: IconMail, type: 'TEXT', @@ -33,7 +33,7 @@ export const personShowFieldDefinition: FieldDefinition[] = [ }, } satisfies FieldDefinition, { - fieldMetadataId: 'company', + fieldId: 'company', label: 'Company', Icon: IconBuildingSkyscraper, type: 'RELATION', @@ -50,7 +50,7 @@ export const personShowFieldDefinition: FieldDefinition[] = [ }, } satisfies FieldDefinition, { - fieldMetadataId: 'phone', + fieldId: 'phone', label: 'Phone', Icon: IconPhone, type: 'PHONE', @@ -60,7 +60,7 @@ export const personShowFieldDefinition: FieldDefinition[] = [ }, } satisfies FieldDefinition, { - fieldMetadataId: 'jobTitle', + fieldId: 'jobTitle', label: 'Job Title', Icon: IconBriefcase, type: 'TEXT', @@ -70,7 +70,7 @@ export const personShowFieldDefinition: FieldDefinition[] = [ }, } satisfies FieldDefinition, { - fieldMetadataId: 'city', + fieldId: 'city', label: 'City', Icon: IconMap, type: 'TEXT', @@ -80,7 +80,7 @@ export const personShowFieldDefinition: FieldDefinition[] = [ }, } satisfies FieldDefinition, { - fieldMetadataId: 'linkedinUrl', + fieldId: 'linkedinUrl', label: 'Linkedin URL', Icon: IconBrandLinkedin, type: 'URL', @@ -90,7 +90,7 @@ export const personShowFieldDefinition: FieldDefinition[] = [ }, } satisfies FieldDefinition, { - fieldMetadataId: 'xUrl', + fieldId: 'xUrl', label: 'X URL', Icon: IconBrandX, type: 'URL', @@ -100,7 +100,7 @@ export const personShowFieldDefinition: FieldDefinition[] = [ }, } satisfies FieldDefinition, { - fieldMetadataId: 'createdAt', + fieldId: 'createdAt', label: 'Created at', Icon: IconCalendar, type: 'DATE', diff --git a/front/src/pages/people/constants/personTableFilterDefinitions.tsx b/front/src/pages/people/constants/personTableFilterDefinitions.tsx index be4ade7e1..983c6de72 100644 --- a/front/src/pages/people/constants/personTableFilterDefinitions.tsx +++ b/front/src/pages/people/constants/personTableFilterDefinitions.tsx @@ -13,25 +13,25 @@ import { Person } from '~/generated/graphql'; export const personTableFilterDefinitions: FilterDefinitionByEntity[] = [ { - fieldMetadataId: 'firstName', + fieldId: 'firstName', label: 'First name', Icon: IconUser, type: 'TEXT', }, { - fieldMetadataId: 'lastName', + fieldId: 'lastName', label: 'Last name', Icon: IconUser, type: 'TEXT', }, { - fieldMetadataId: 'email', + fieldId: 'email', label: 'Email', Icon: IconMail, type: 'TEXT', }, { - fieldMetadataId: 'companyId', + fieldId: 'companyId', label: 'Company', Icon: IconBuildingSkyscraper, type: 'ENTITY', @@ -39,19 +39,19 @@ export const personTableFilterDefinitions: FilterDefinitionByEntity[] = entitySelectComponent: , }, { - fieldMetadataId: 'phone', + fieldId: 'phone', label: 'Phone', Icon: IconPhone, type: 'TEXT', }, { - fieldMetadataId: 'createdAt', + fieldId: 'createdAt', label: 'Created at', Icon: IconCalendarEvent, type: 'DATE', }, { - fieldMetadataId: 'city', + fieldId: 'city', label: 'City', Icon: IconMap, type: 'TEXT', diff --git a/front/src/pages/people/constants/personTableSortDefinitions.tsx b/front/src/pages/people/constants/personTableSortDefinitions.tsx index 6c9eff630..10e2e440e 100644 --- a/front/src/pages/people/constants/personTableSortDefinitions.tsx +++ b/front/src/pages/people/constants/personTableSortDefinitions.tsx @@ -11,7 +11,7 @@ import { SortDirection } from '@/ui/object/object-sort-dropdown/types/SortDirect export const personTableSortDefinitions: SortDefinition[] = [ { - fieldMetadataId: 'fullname', + fieldId: 'fullname', label: 'People', Icon: IconUser, @@ -21,7 +21,7 @@ export const personTableSortDefinitions: SortDefinition[] = [ ], }, { - fieldMetadataId: 'company_name', + fieldId: 'company_name', label: 'Company', Icon: IconBuildingSkyscraper, getOrderByTemplate: (direction: SortDirection) => [ @@ -29,22 +29,22 @@ export const personTableSortDefinitions: SortDefinition[] = [ ], }, { - fieldMetadataId: 'email', + fieldId: 'email', label: 'Email', Icon: IconMail, }, { - fieldMetadataId: 'phone', + fieldId: 'phone', label: 'Phone', Icon: IconPhone, }, { - fieldMetadataId: 'createdAt', + fieldId: 'createdAt', label: 'Created at', Icon: IconCalendarEvent, }, { - fieldMetadataId: 'city', + fieldId: 'city', label: 'City', Icon: IconMap, }, diff --git a/front/src/pages/settings/data-model/SettingsNewObject.tsx b/front/src/pages/settings/data-model/SettingsNewObject.tsx index 851208161..eb1be07c9 100644 --- a/front/src/pages/settings/data-model/SettingsNewObject.tsx +++ b/front/src/pages/settings/data-model/SettingsNewObject.tsx @@ -77,7 +77,7 @@ export const SettingsNewObject = () => { }); await createOneView?.({ - objectMetadataId: createdObject.data?.createOneObject.id, + objectId: createdObject.data?.createOneObject.id, type: ViewType.Table, name: `All ${customFormValues.labelPlural}`, }); diff --git a/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep1.tsx b/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep1.tsx index 942f1ba50..fd6ca594e 100644 --- a/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep1.tsx +++ b/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep1.tsx @@ -72,12 +72,10 @@ export const SettingsObjectNewFieldStep1 = () => { if (!activeObjectMetadataItem) return null; - const handleToggleField = (fieldMetadataId: string) => + const handleToggleField = (fieldId: string) => setMetadataFields((previousFields) => previousFields.map((field) => - field.id === fieldMetadataId - ? { ...field, isActive: !field.isActive } - : field, + field.id === fieldId ? { ...field, isActive: !field.isActive } : field, ), ); diff --git a/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx b/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx index ff7d91c27..1329b59bb 100644 --- a/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx +++ b/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx @@ -52,7 +52,7 @@ export const SettingsObjectNewFieldStep2 = () => { objectNamePlural: 'viewsV2', filter: { type: { eq: ViewType.Table }, - objectMetadataId: { eq: activeObjectMetadataItem?.id }, + objectId: { eq: activeObjectMetadataItem?.id }, }, onCompleted: async (data: PaginatedObjectTypeResults) => { const views = data.edges; @@ -72,12 +72,12 @@ export const SettingsObjectNewFieldStep2 = () => { const handleSave = async () => { const createdField = await createMetadataField({ ...formValues, - objectMetadataId: activeObjectMetadataItem.id, + objectId: activeObjectMetadataItem.id, }); objectViews.forEach(async (view) => { await createOneViewField?.({ viewId: view.id, - fieldMetadataId: createdField.data?.createOneField.id, + fieldId: createdField.data?.createOneField.id, position: activeObjectMetadataItem.fields.length, isVisible: true, size: 100, diff --git a/front/src/pages/tasks/TasksEffect.tsx b/front/src/pages/tasks/TasksEffect.tsx index 566577531..045fa758d 100644 --- a/front/src/pages/tasks/TasksEffect.tsx +++ b/front/src/pages/tasks/TasksEffect.tsx @@ -18,7 +18,7 @@ export const TasksEffect = () => { useEffect(() => { if (currentUser) { setSelectedFilter({ - fieldMetadataId: 'assigneeId', + fieldId: 'assigneeId', value: currentUser.id, operand: ViewFilterOperand.Is, displayValue: currentUser.displayName, diff --git a/front/src/pages/tasks/tasks-filter-definitions.tsx b/front/src/pages/tasks/tasks-filter-definitions.tsx index 2349693df..7d860b454 100644 --- a/front/src/pages/tasks/tasks-filter-definitions.tsx +++ b/front/src/pages/tasks/tasks-filter-definitions.tsx @@ -5,7 +5,7 @@ import { Activity } from '~/generated/graphql'; export const tasksFilterDefinitions: FilterDefinitionByEntity[] = [ { - fieldMetadataId: 'assigneeId', + fieldId: 'assigneeId', label: 'Assignee', Icon: IconUser, type: 'ENTITY', diff --git a/front/src/testing/graphqlMocks.ts b/front/src/testing/graphqlMocks.ts index 22048d0fb..d6614a3df 100644 --- a/front/src/testing/graphqlMocks.ts +++ b/front/src/testing/graphqlMocks.ts @@ -318,7 +318,7 @@ export const graphqlMocks = [ }, ), graphql.query('FindManyviewsV2', (req, res, ctx) => { - const objectMetadataId = req.variables.filter.objectMetadataId.eq; + const objectId = req.variables.filter.objectId.eq; const viewType = req.variables.filter.type.eq; return res( @@ -326,9 +326,7 @@ export const graphqlMocks = [ viewsV2: { edges: mockedViewsData .filter( - (view) => - view.objectMetadataId === objectMetadataId && - view.type === viewType, + (view) => view.objectId === objectId && view.type === viewType, ) .map((view) => ({ node: view, diff --git a/front/src/testing/mock-data/metadata.ts b/front/src/testing/mock-data/metadata.ts index 8db984347..8d9ea5913 100644 --- a/front/src/testing/mock-data/metadata.ts +++ b/front/src/testing/mock-data/metadata.ts @@ -20,7 +20,7 @@ export const mockedObjectMetadataItems = { node: { id: '5db475e7-8208-402d-97a1-62c9ce344dd4', type: 'TEXT', - name: 'objectMetadataId', + name: 'objectId', label: 'Object Id', description: 'View target object', icon: null, @@ -127,7 +127,7 @@ export const mockedObjectMetadataItems = { node: { id: '4d77c2dd-2b04-4989-b11e-cb0e386d1b4d', type: 'TEXT', - name: 'fieldMetadataId', + name: 'fieldId', label: 'Field Id', description: 'View Field target field', icon: null, diff --git a/front/src/testing/mock-data/view-fields.ts b/front/src/testing/mock-data/view-fields.ts index c644510c9..4bb4f8977 100644 --- a/front/src/testing/mock-data/view-fields.ts +++ b/front/src/testing/mock-data/view-fields.ts @@ -4,7 +4,7 @@ export const mockedViewFieldsData = [ // Companies { id: '79035310-e955-4986-a4a4-73f9d9949c6a', - fieldMetadataId: 'name', + fieldId: 'name', viewId: mockedViewsData[0].id, position: 0, isVisible: true, @@ -12,7 +12,7 @@ export const mockedViewFieldsData = [ }, { id: '2a96bbc8-d86d-439a-8e50-4b07ebd27750', - fieldMetadataId: 'domainName', + fieldId: 'domainName', viewId: mockedViewsData[0].id, position: 1, isVisible: true, @@ -20,7 +20,7 @@ export const mockedViewFieldsData = [ }, { id: '0c1b4c7b-6a3d-4fb0-bf2b-5d7c8fb844ed', - fieldMetadataId: 'accountOwner', + fieldId: 'accountOwner', viewId: mockedViewsData[0].id, position: 2, isVisible: true, @@ -28,7 +28,7 @@ export const mockedViewFieldsData = [ }, { id: 'cc7f9560-32b5-4b82-8fd9-b05fe77c8cf7', - fieldMetadataId: 'createdAt', + fieldId: 'createdAt', viewId: mockedViewsData[0].id, position: 3, isVisible: true, @@ -36,7 +36,7 @@ export const mockedViewFieldsData = [ }, { id: '3de4d078-3396-4480-be2d-6f3b1a228b0d', - fieldMetadataId: 'employees', + fieldId: 'employees', viewId: mockedViewsData[0].id, position: 4, isVisible: true, @@ -44,7 +44,7 @@ export const mockedViewFieldsData = [ }, { id: '4650c8fb-0f1e-4342-88dc-adedae1445f9', - fieldMetadataId: 'linkedin', + fieldId: 'linkedin', viewId: mockedViewsData[0].id, position: 5, isVisible: true, @@ -52,7 +52,7 @@ export const mockedViewFieldsData = [ }, { id: '727430bf-6ff8-4c85-9828-cbe72ac0fc27', - fieldMetadataId: 'address', + fieldId: 'address', viewId: mockedViewsData[0].id, position: 6, isVisible: true, @@ -62,7 +62,7 @@ export const mockedViewFieldsData = [ // People { id: '28894146-4fde-4a16-a9ca-1a31b5b788b4', - fieldMetadataId: 'displayName', + fieldId: 'displayName', viewId: mockedViewsData[1].id, position: 0, isVisible: true, @@ -70,7 +70,7 @@ export const mockedViewFieldsData = [ }, { id: 'e1e24864-8601-4cd8-8a63-09c1285f2e39', - fieldMetadataId: 'email', + fieldId: 'email', viewId: mockedViewsData[1].id, position: 1, isVisible: true, @@ -78,7 +78,7 @@ export const mockedViewFieldsData = [ }, { id: '5a1df716-7211-445a-9f16-9783a00998a7', - fieldMetadataId: 'company', + fieldId: 'company', viewId: mockedViewsData[1].id, position: 2, isVisible: true, @@ -86,7 +86,7 @@ export const mockedViewFieldsData = [ }, { id: 'a6e1197a-7e84-4d92-ace2-367c0bc46c49', - fieldMetadataId: 'phone', + fieldId: 'phone', viewId: mockedViewsData[1].id, position: 3, isVisible: true, @@ -94,7 +94,7 @@ export const mockedViewFieldsData = [ }, { id: 'c9343097-d14b-4559-a5fa-626c1527d39f', - fieldMetadataId: 'createdAt', + fieldId: 'createdAt', viewId: mockedViewsData[1].id, position: 4, isVisible: true, @@ -102,7 +102,7 @@ export const mockedViewFieldsData = [ }, { id: 'a873e5f0-fed6-47e9-a712-6854eab3ec77', - fieldMetadataId: 'city', + fieldId: 'city', viewId: mockedViewsData[1].id, position: 5, isVisible: true, @@ -110,7 +110,7 @@ export const mockedViewFieldsData = [ }, { id: '66f134b8-5329-422f-b88e-83e6bb707eb5', - fieldMetadataId: 'jobTitle', + fieldId: 'jobTitle', viewId: mockedViewsData[1].id, position: 6, isVisible: true, @@ -118,7 +118,7 @@ export const mockedViewFieldsData = [ }, { id: '648faa24-cabb-482a-8578-ba3f09906017', - fieldMetadataId: 'linkedin', + fieldId: 'linkedin', viewId: mockedViewsData[1].id, position: 7, isVisible: true, @@ -126,7 +126,7 @@ export const mockedViewFieldsData = [ }, { id: '3a9e7f0d-a4ce-4ad5-aac7-3a24eb1a412d', - fieldMetadataId: 'x', + fieldId: 'x', viewId: mockedViewsData[1].id, position: 8, isVisible: true, @@ -136,7 +136,7 @@ export const mockedViewFieldsData = [ // Opportunities { id: '35a42e2d-83dd-4b57-ada6-f90616da706d', - fieldMetadataId: 'amount', + fieldId: 'amount', viewId: mockedViewsData[2].id, position: 0, isVisible: true, @@ -144,7 +144,7 @@ export const mockedViewFieldsData = [ }, { id: 'e5a731bb-82b9-4abe-ad22-1ddea94722f9', - fieldMetadataId: 'probability', + fieldId: 'probability', viewId: mockedViewsData[2].id, position: 1, isVisible: true, @@ -152,7 +152,7 @@ export const mockedViewFieldsData = [ }, { id: '3159acd8-463f-458d-bf9a-af8ac6f57dc0', - fieldMetadataId: 'closeDate', + fieldId: 'closeDate', viewId: mockedViewsData[2].id, position: 2, isVisible: true, @@ -160,7 +160,7 @@ export const mockedViewFieldsData = [ }, { id: 'afc0819d-b694-4e3c-a2e6-25261aa3ed2c', - fieldMetadataId: 'company', + fieldId: 'company', viewId: mockedViewsData[2].id, position: 3, isVisible: true, @@ -168,7 +168,7 @@ export const mockedViewFieldsData = [ }, { id: 'ec0507bb-aedc-4695-ba96-d81bdeb9db83', - fieldMetadataId: 'createdAt', + fieldId: 'createdAt', viewId: mockedViewsData[2].id, position: 4, isVisible: true, @@ -176,7 +176,7 @@ export const mockedViewFieldsData = [ }, { id: '3f1585f6-44f6-45c5-b840-bc05af5d0008', - fieldMetadataId: 'pointOfContact', + fieldId: 'pointOfContact', viewId: mockedViewsData[2].id, position: 5, isVisible: true, diff --git a/front/src/testing/mock-data/views.ts b/front/src/testing/mock-data/views.ts index c58e50846..f007560dc 100644 --- a/front/src/testing/mock-data/views.ts +++ b/front/src/testing/mock-data/views.ts @@ -2,25 +2,25 @@ export const mockedViewsData = [ { id: '37a8a866-eb17-4e76-9382-03143a2f6a80', name: 'All companies', - objectMetadataId: 'company', + objectId: 'company', type: 'table', }, { id: '6095799e-b48f-4e00-b071-10818083593a', name: 'All people', - objectMetadataId: 'person', + objectId: 'person', type: 'table', }, { id: 'e26f66b7-f890-4a5c-b4d2-ec09987b5308', name: 'All opportunities', - objectMetadataId: 'company', + objectId: 'company', type: 'kanban', }, { id: '5c307222-1dd5-4ff3-ab06-8d990e9b3c74', name: 'All companies (v2)', - objectMetadataId: 'a3195559-cc20-4749-9565-572a2f506581', + objectId: 'a3195559-cc20-4749-9565-572a2f506581', type: 'table', }, ]; diff --git a/server/ormconfig.ts b/server/ormconfig.ts index 153603fdc..19a3d8f28 100644 --- a/server/ormconfig.ts +++ b/server/ormconfig.ts @@ -7,7 +7,7 @@ export default { type: 'postgres', entities: [__dirname + '/src/coreV2/**/*.entity{.ts,.js}'], synchronize: false, - migrationsRun: false, + migrationsRun: true, migrationsTableName: '_typeorm_migrations', migrations: [__dirname + '/migrations/**/*{.ts,.js}'], cli: { diff --git a/server/package.json b/server/package.json index 703a33ba1..76a88ff9b 100644 --- a/server/package.json +++ b/server/package.json @@ -27,7 +27,7 @@ "prisma:seed": "npx prisma db seed", "prisma:migrate": "npx prisma migrate deploy", "typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js", - "typeorm:migrate": "yarn typeorm migration:run -d ./src/database/typeorm/metadata/metadata.datasource.ts", + "typeorm:migrate": "yarn typeorm migration:run -d ./src/metadata/metadata.datasource.ts", "database:init": "yarn database:setup && yarn database:seed", "database:setup": "npx ts-node ./scripts/setup-db.ts && yarn database:migrate && yarn database:generate", "database:truncate": "npx ts-node ./scripts/truncate-db.ts", diff --git a/server/src/command.module.ts b/server/src/command.module.ts index c74dfed98..a875dbd6a 100644 --- a/server/src/command.module.ts +++ b/server/src/command.module.ts @@ -4,15 +4,9 @@ import { DatabaseCommandModule } from 'src/database/commands/database-command.mo import { AppModule } from './app.module'; -import { TenantMigrationRunnerCommandsModule } from './tenant-migration-runner/commands/tenant-migration-runner-commands.module'; -import { TenantManagerCommandsModule } from './tenant-manager/commands/tenant-manager-commands.module'; +import { MetadataCommandModule } from './metadata/commands/metadata-command.module'; @Module({ - imports: [ - AppModule, - TenantMigrationRunnerCommandsModule, - TenantManagerCommandsModule, - DatabaseCommandModule, - ], + imports: [AppModule, MetadataCommandModule, DatabaseCommandModule], }) export class CommandModule {} diff --git a/server/src/core/workspace/services/workspace.service.spec.ts b/server/src/core/workspace/services/workspace.service.spec.ts index 6e3e9f80a..3a73c544e 100644 --- a/server/src/core/workspace/services/workspace.service.spec.ts +++ b/server/src/core/workspace/services/workspace.service.spec.ts @@ -7,7 +7,7 @@ import { PipelineStageService } from 'src/core/pipeline/services/pipeline-stage. import { PersonService } from 'src/core/person/person.service'; import { CompanyService } from 'src/core/company/company.service'; import { PipelineProgressService } from 'src/core/pipeline/services/pipeline-progress.service'; -import { TenantManagerService } from 'src/tenant-manager/tenant-manager.service'; +import { TenantInitialisationService } from 'src/metadata/tenant-initialisation/tenant-initialisation.service'; import { WorkspaceService } from './workspace.service'; @@ -43,7 +43,7 @@ describe('WorkspaceService', () => { useValue: {}, }, { - provide: TenantManagerService, + provide: TenantInitialisationService, useValue: {}, }, ], diff --git a/server/src/core/workspace/services/workspace.service.ts b/server/src/core/workspace/services/workspace.service.ts index 075c2d96b..17c2fb7c3 100644 --- a/server/src/core/workspace/services/workspace.service.ts +++ b/server/src/core/workspace/services/workspace.service.ts @@ -10,7 +10,7 @@ import { PipelineStageService } from 'src/core/pipeline/services/pipeline-stage. import { PipelineService } from 'src/core/pipeline/services/pipeline.service'; import { PrismaService } from 'src/database/prisma.service'; import { assert } from 'src/utils/assert'; -import { TenantManagerService } from 'src/tenant-manager/tenant-manager.service'; +import { TenantInitialisationService } from 'src/metadata/tenant-initialisation/tenant-initialisation.service'; @Injectable() export class WorkspaceService { @@ -21,7 +21,7 @@ export class WorkspaceService { private readonly personService: PersonService, private readonly pipelineStageService: PipelineStageService, private readonly pipelineProgressService: PipelineProgressService, - private readonly tenantManagerService: TenantManagerService, + private readonly tenantInitialisationService: TenantInitialisationService, ) {} // Find @@ -64,7 +64,7 @@ export class WorkspaceService { }); // Create workspace schema - await this.tenantManagerService.init(workspace.id); + await this.tenantInitialisationService.init(workspace.id); // Create default companies const companies = await this.companyService.createDefaultCompanies({ @@ -161,7 +161,7 @@ export class WorkspaceService { this.delete({ where: { id: workspaceId } }), ]); - await this.tenantManagerService.delete(workspaceId); + await this.tenantInitialisationService.delete(workspaceId); return workspace; } diff --git a/server/src/core/workspace/workspace.module.ts b/server/src/core/workspace/workspace.module.ts index f2faf7171..be1e24c03 100644 --- a/server/src/core/workspace/workspace.module.ts +++ b/server/src/core/workspace/workspace.module.ts @@ -4,9 +4,9 @@ import { FileUploadService } from 'src/core/file/services/file-upload.service'; import { PipelineModule } from 'src/core/pipeline/pipeline.module'; import { CompanyModule } from 'src/core/company/company.module'; import { PersonModule } from 'src/core/person/person.module'; +import { TenantInitialisationModule } from 'src/metadata/tenant-initialisation/tenant-initialisation.module'; import { AbilityModule } from 'src/ability/ability.module'; import { PrismaModule } from 'src/database/prisma.module'; -import { TenantManagerModule } from 'src/tenant-manager/tenant-manager.module'; import { WorkspaceService } from './services/workspace.service'; import { WorkspaceMemberService } from './services/workspace-member.service'; @@ -19,7 +19,7 @@ import { WorkspaceResolver } from './resolvers/workspace.resolver'; PipelineModule, CompanyModule, PersonModule, - TenantManagerModule, + TenantInitialisationModule, PrismaModule, ], providers: [ diff --git a/server/src/database/commands/database-command.module.ts b/server/src/database/commands/database-command.module.ts index bb4b084fa..3d89ee29e 100644 --- a/server/src/database/commands/database-command.module.ts +++ b/server/src/database/commands/database-command.module.ts @@ -2,36 +2,21 @@ import { Module } from '@nestjs/common'; import { DataCleanInactiveCommand } from 'src/database/commands/clean-inactive-workspaces.command'; import { ConfirmationQuestion } from 'src/database/commands/questions/confirmation.question'; +import { WorkspaceService } from 'src/core/workspace/services/workspace.service'; import { PipelineModule } from 'src/core/pipeline/pipeline.module'; import { CompanyModule } from 'src/core/company/company.module'; import { PersonModule } from 'src/core/person/person.module'; +import { TenantInitialisationModule } from 'src/metadata/tenant-initialisation/tenant-initialisation.module'; import { PrismaModule } from 'src/database/prisma.module'; -import { TenantManagerModule } from 'src/tenant-manager/tenant-manager.module'; -import { DataSourceMetadataModule } from 'src/metadata/data-source-metadata/data-source-metadata.module'; -import { TenantMigrationModule } from 'src/metadata/tenant-migration/tenant-migration.module'; -import { TenantMigrationRunnerModule } from 'src/tenant-migration-runner/tenant-migration-runner.module'; -import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; -import { WorkspaceModule } from 'src/core/workspace/workspace.module'; - -import { DataSeedTenantCommand } from './data-seed-tenant.command'; @Module({ imports: [ PipelineModule, CompanyModule, PersonModule, - TenantManagerModule, + TenantInitialisationModule, PrismaModule, - DataSourceMetadataModule, - TypeORMModule, - TenantMigrationModule, - TenantMigrationRunnerModule, - WorkspaceModule, - ], - providers: [ - DataSeedTenantCommand, - DataCleanInactiveCommand, - ConfirmationQuestion, ], + providers: [DataCleanInactiveCommand, ConfirmationQuestion, WorkspaceService], }) export class DatabaseCommandModule {} diff --git a/server/src/database/seeds/metadata.ts b/server/src/database/seeds/metadata.ts index bf62ea6b0..575ace3b0 100644 --- a/server/src/database/seeds/metadata.ts +++ b/server/src/database/seeds/metadata.ts @@ -5,8 +5,8 @@ export const seedMetadata = async (prisma: PrismaClient) => { 'CREATE SCHEMA IF NOT EXISTS workspace_twenty_7icsva0r6s00mpcp6cwg4w4rd', ); await prisma.$queryRawUnsafe( - `INSERT INTO metadata."dataSource"( - id, schema, type, "workspaceId" + `INSERT INTO metadata.data_source_metadata( + id, schema, type, workspace_id ) VALUES ( 'b37b2163-7f63-47a9-b1b3-6c7290ca9fb1', 'workspace_twenty_7icsva0r6s00mpcp6cwg4w4rd', 'postgres', 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419' diff --git a/server/src/database/typeorm-seeds/metadata/field-metadata.ts b/server/src/database/typeorm-seeds/metadata/field-metadata.ts index f5bf6f392..d3c913c5f 100644 --- a/server/src/database/typeorm-seeds/metadata/field-metadata.ts +++ b/server/src/database/typeorm-seeds/metadata/field-metadata.ts @@ -1,6 +1,6 @@ import { DataSource } from 'typeorm'; -const tableName = 'fieldMetadata'; +const tableName = 'field_metadata'; export const seedFieldMetadata = async ( workspaceDataSource: DataSource, @@ -10,7 +10,7 @@ export const seedFieldMetadata = async ( .createQueryBuilder() .insert() .into(`${schemaName}.${tableName}`, [ - 'objectMetadataId', + 'objectId', 'isCustom', 'workspaceId', 'isActive', @@ -26,7 +26,7 @@ export const seedFieldMetadata = async ( .values([ // Companies { - objectMetadataId: '1a8487a0-480c-434e-b4c7-e22408b97047', + objectId: '1a8487a0-480c-434e-b4c7-e22408b97047', isCustom: false, workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', isActive: true, @@ -41,7 +41,7 @@ export const seedFieldMetadata = async ( isNullable: false, }, { - objectMetadataId: '1a8487a0-480c-434e-b4c7-e22408b97047', + objectId: '1a8487a0-480c-434e-b4c7-e22408b97047', isCustom: false, workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', isActive: true, @@ -56,7 +56,7 @@ export const seedFieldMetadata = async ( isNullable: true, }, { - objectMetadataId: '1a8487a0-480c-434e-b4c7-e22408b97047', + objectId: '1a8487a0-480c-434e-b4c7-e22408b97047', isCustom: false, workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', isActive: true, @@ -71,7 +71,7 @@ export const seedFieldMetadata = async ( isNullable: true, }, { - objectMetadataId: '1a8487a0-480c-434e-b4c7-e22408b97047', + objectId: '1a8487a0-480c-434e-b4c7-e22408b97047', isCustom: false, workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', isActive: true, @@ -87,7 +87,7 @@ export const seedFieldMetadata = async ( }, // Views { - objectMetadataId: '9ab6b3dc-767f-473f-8fd0-6cdbefbf8dbe', + objectId: '9ab6b3dc-767f-473f-8fd0-6cdbefbf8dbe', isCustom: false, workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', isActive: true, @@ -102,22 +102,22 @@ export const seedFieldMetadata = async ( isNullable: false, }, { - objectMetadataId: '9ab6b3dc-767f-473f-8fd0-6cdbefbf8dbe', + objectId: '9ab6b3dc-767f-473f-8fd0-6cdbefbf8dbe', isCustom: false, workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', isActive: true, type: 'TEXT', - name: 'objectMetadataId', + name: 'objectId', label: 'Object Id', targetColumnMap: { - value: 'objectMetadataId', + value: 'objectId', }, description: 'View target object', icon: null, isNullable: false, }, { - objectMetadataId: '9ab6b3dc-767f-473f-8fd0-6cdbefbf8dbe', + objectId: '9ab6b3dc-767f-473f-8fd0-6cdbefbf8dbe', isCustom: false, workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', isActive: true, @@ -133,22 +133,22 @@ export const seedFieldMetadata = async ( }, // View Fields { - objectMetadataId: '61d9000b-485c-4c48-a22e-0d9a164f9647', + objectId: '61d9000b-485c-4c48-a22e-0d9a164f9647', isCustom: false, workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', isActive: true, type: 'TEXT', - name: 'fieldMetadataId', + name: 'fieldId', label: 'Field Id', targetColumnMap: { - value: 'fieldMetadataId', + value: 'fieldId', }, description: 'View Field target field', icon: null, isNullable: false, }, { - objectMetadataId: '61d9000b-485c-4c48-a22e-0d9a164f9647', + objectId: '61d9000b-485c-4c48-a22e-0d9a164f9647', isCustom: false, workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', isActive: true, @@ -163,7 +163,7 @@ export const seedFieldMetadata = async ( isNullable: false, }, { - objectMetadataId: '61d9000b-485c-4c48-a22e-0d9a164f9647', + objectId: '61d9000b-485c-4c48-a22e-0d9a164f9647', isCustom: false, workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', isActive: true, @@ -178,7 +178,7 @@ export const seedFieldMetadata = async ( isNullable: false, }, { - objectMetadataId: '61d9000b-485c-4c48-a22e-0d9a164f9647', + objectId: '61d9000b-485c-4c48-a22e-0d9a164f9647', isCustom: false, workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', isActive: true, @@ -193,7 +193,7 @@ export const seedFieldMetadata = async ( isNullable: false, }, { - objectMetadataId: '61d9000b-485c-4c48-a22e-0d9a164f9647', + objectId: '61d9000b-485c-4c48-a22e-0d9a164f9647', isCustom: false, workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', isActive: true, @@ -209,22 +209,22 @@ export const seedFieldMetadata = async ( }, // View Filters { - objectMetadataId: '5d9b1ab9-4461-4e2d-bf9e-9b47e68846d3', + objectId: '5d9b1ab9-4461-4e2d-bf9e-9b47e68846d3', isCustom: false, workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', isActive: true, type: 'TEXT', - name: 'fieldMetadataId', + name: 'fieldId', label: 'Field Id', targetColumnMap: { - value: 'fieldMetadataId', + value: 'fieldId', }, description: 'View Filter target field', icon: null, isNullable: false, }, { - objectMetadataId: '5d9b1ab9-4461-4e2d-bf9e-9b47e68846d3', + objectId: '5d9b1ab9-4461-4e2d-bf9e-9b47e68846d3', isCustom: false, workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', isActive: true, @@ -239,7 +239,7 @@ export const seedFieldMetadata = async ( isNullable: false, }, { - objectMetadataId: '5d9b1ab9-4461-4e2d-bf9e-9b47e68846d3', + objectId: '5d9b1ab9-4461-4e2d-bf9e-9b47e68846d3', isCustom: false, workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', isActive: true, @@ -254,7 +254,7 @@ export const seedFieldMetadata = async ( isNullable: false, }, { - objectMetadataId: '5d9b1ab9-4461-4e2d-bf9e-9b47e68846d3', + objectId: '5d9b1ab9-4461-4e2d-bf9e-9b47e68846d3', isCustom: false, workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', isActive: true, @@ -269,7 +269,7 @@ export const seedFieldMetadata = async ( isNullable: false, }, { - objectMetadataId: '5d9b1ab9-4461-4e2d-bf9e-9b47e68846d3', + objectId: '5d9b1ab9-4461-4e2d-bf9e-9b47e68846d3', isCustom: false, workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', isActive: true, @@ -285,22 +285,22 @@ export const seedFieldMetadata = async ( }, // View Sorts { - objectMetadataId: '6f8dcd4b-cf28-41dd-b98b-d6e1f5b3a251', + objectId: '6f8dcd4b-cf28-41dd-b98b-d6e1f5b3a251', isCustom: false, workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', isActive: true, type: 'TEXT', - name: 'fieldMetadataId', + name: 'fieldId', label: 'Field Id', targetColumnMap: { - value: 'fieldMetadataId', + value: 'fieldId', }, description: 'View Sort target field', icon: null, isNullable: false, }, { - objectMetadataId: '6f8dcd4b-cf28-41dd-b98b-d6e1f5b3a251', + objectId: '6f8dcd4b-cf28-41dd-b98b-d6e1f5b3a251', isCustom: false, workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', isActive: true, @@ -315,7 +315,7 @@ export const seedFieldMetadata = async ( isNullable: false, }, { - objectMetadataId: '6f8dcd4b-cf28-41dd-b98b-d6e1f5b3a251', + objectId: '6f8dcd4b-cf28-41dd-b98b-d6e1f5b3a251', isCustom: false, workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', isActive: true, diff --git a/server/src/database/typeorm-seeds/metadata/object-metadata.ts b/server/src/database/typeorm-seeds/metadata/object-metadata.ts index 5f96fced6..25131b86c 100644 --- a/server/src/database/typeorm-seeds/metadata/object-metadata.ts +++ b/server/src/database/typeorm-seeds/metadata/object-metadata.ts @@ -1,6 +1,6 @@ import { DataSource } from 'typeorm'; -const tableName = 'objectMetadata'; +const tableName = 'object_metadata'; export const seedObjectMetadata = async ( workspaceDataSource: DataSource, diff --git a/server/src/database/typeorm-seeds/tenant/view-fields.ts b/server/src/database/typeorm-seeds/tenant/view-fields.ts index d8d0a9b03..987a5ce8a 100644 --- a/server/src/database/typeorm-seeds/tenant/view-fields.ts +++ b/server/src/database/typeorm-seeds/tenant/view-fields.ts @@ -11,7 +11,7 @@ export const seedViewFields = async ( .insert() .into(`${schemaName}.${tableName}`, [ 'id', - 'fieldMetadataId', + 'fieldId', 'viewId', 'position', 'isVisible', @@ -21,7 +21,7 @@ export const seedViewFields = async ( .values([ { id: '46a72a5b-276e-4241-a05f-c054410aebcb', - fieldMetadataId: 'name', + fieldId: 'name', viewId: '10bec73c-0aea-4cc4-a3b2-8c2186f29b43', position: 0, isVisible: true, @@ -29,7 +29,7 @@ export const seedViewFields = async ( }, { id: 'f15b26ff-8f79-49dd-8f53-4286dd1af846', - fieldMetadataId: 'name', + fieldId: 'name', viewId: '37a8a866-eb17-4e76-9382-03143a2f6a80', position: 0, isVisible: true, @@ -37,7 +37,7 @@ export const seedViewFields = async ( }, { id: '8d1dbb50-c97f-42c4-8575-3d2c9bdeb6e5', - fieldMetadataId: 'domainName', + fieldId: 'domainName', viewId: '37a8a866-eb17-4e76-9382-03143a2f6a80', position: 1, isVisible: true, @@ -45,7 +45,7 @@ export const seedViewFields = async ( }, { id: '33833b3b-4e02-4f10-91fc-c594422952af', - fieldMetadataId: 'accountOwner', + fieldId: 'accountOwner', viewId: '37a8a866-eb17-4e76-9382-03143a2f6a80', position: 2, isVisible: true, @@ -53,7 +53,7 @@ export const seedViewFields = async ( }, { id: 'c750a968-832e-4812-a1a2-74f515af55c1', - fieldMetadataId: 'createdAt', + fieldId: 'createdAt', viewId: '37a8a866-eb17-4e76-9382-03143a2f6a80', position: 3, isVisible: true, @@ -61,7 +61,7 @@ export const seedViewFields = async ( }, { id: '2fde3187-a0bc-47ca-80bd-457bd826fb4a', - fieldMetadataId: 'employees', + fieldId: 'employees', viewId: '37a8a866-eb17-4e76-9382-03143a2f6a80', position: 4, isVisible: true, @@ -69,7 +69,7 @@ export const seedViewFields = async ( }, { id: '2fead26f-3f4f-4a4d-a4c6-3abe7b2f74c9', - fieldMetadataId: 'linkedin', + fieldId: 'linkedin', viewId: '37a8a866-eb17-4e76-9382-03143a2f6a80', position: 5, isVisible: true, @@ -77,7 +77,7 @@ export const seedViewFields = async ( }, { id: '0cffa82a-c851-4e17-b46c-2c4642d78329', - fieldMetadataId: 'address', + fieldId: 'address', viewId: '37a8a866-eb17-4e76-9382-03143a2f6a80', position: 6, isVisible: true, @@ -85,7 +85,7 @@ export const seedViewFields = async ( }, { id: '93a68c4a-8107-409a-9adb-06305ffbd692', - fieldMetadataId: 'displayName', + fieldId: 'displayName', viewId: '6095799e-b48f-4e00-b071-10818083593a', position: 0, isVisible: true, @@ -93,7 +93,7 @@ export const seedViewFields = async ( }, { id: 'd955ee31-6316-4cb2-af71-9609dede4d7e', - fieldMetadataId: 'email', + fieldId: 'email', viewId: '6095799e-b48f-4e00-b071-10818083593a', position: 1, isVisible: true, @@ -101,7 +101,7 @@ export const seedViewFields = async ( }, { id: 'bceb4d84-8ad1-4a0e-9333-efb870b42eb8', - fieldMetadataId: 'company', + fieldId: 'company', viewId: '6095799e-b48f-4e00-b071-10818083593a', position: 2, isVisible: true, @@ -109,7 +109,7 @@ export const seedViewFields = async ( }, { id: 'bef874d4-f349-4cdb-ae28-6e9fc497449b', - fieldMetadataId: 'phone', + fieldId: 'phone', viewId: '6095799e-b48f-4e00-b071-10818083593a', position: 3, isVisible: true, @@ -117,7 +117,7 @@ export const seedViewFields = async ( }, { id: 'e06f920d-1af9-404d-8b9a-4f97c4009a4a', - fieldMetadataId: 'createdAt', + fieldId: 'createdAt', viewId: '6095799e-b48f-4e00-b071-10818083593a', position: 4, isVisible: true, @@ -125,7 +125,7 @@ export const seedViewFields = async ( }, { id: '92d94ee8-31fc-4025-a427-29291abb2b19', - fieldMetadataId: 'city', + fieldId: 'city', viewId: '6095799e-b48f-4e00-b071-10818083593a', position: 5, isVisible: true, @@ -133,7 +133,7 @@ export const seedViewFields = async ( }, { id: 'b38e4022-1559-40da-bd5e-29d89b6c8330', - fieldMetadataId: 'jobTitle', + fieldId: 'jobTitle', viewId: '6095799e-b48f-4e00-b071-10818083593a', position: 6, isVisible: true, @@ -141,7 +141,7 @@ export const seedViewFields = async ( }, { id: '30147fab-9666-4db5-a11b-20af4544c712', - fieldMetadataId: 'linkedin', + fieldId: 'linkedin', viewId: '6095799e-b48f-4e00-b071-10818083593a', position: 7, isVisible: true, @@ -149,7 +149,7 @@ export const seedViewFields = async ( }, { id: 'f0870949-21ac-46a2-b3ec-d1b0107c434c', - fieldMetadataId: 'x', + fieldId: 'x', viewId: '6095799e-b48f-4e00-b071-10818083593a', position: 8, isVisible: true, diff --git a/server/src/database/typeorm-seeds/tenant/views.ts b/server/src/database/typeorm-seeds/tenant/views.ts index aadf4c7e2..6f253d341 100644 --- a/server/src/database/typeorm-seeds/tenant/views.ts +++ b/server/src/database/typeorm-seeds/tenant/views.ts @@ -9,36 +9,31 @@ export const seedViews = async ( await workspaceDataSource .createQueryBuilder() .insert() - .into(`${schemaName}.${tableName}`, [ - 'id', - 'name', - 'objectMetadataId', - 'type', - ]) + .into(`${schemaName}.${tableName}`, ['id', 'name', 'objectId', 'type']) .orIgnore() .values([ { id: '37a8a866-eb17-4e76-9382-03143a2f6a80', name: 'All companies', - objectMetadataId: 'company', + objectId: 'company', type: 'table', }, { id: '6095799e-b48f-4e00-b071-10818083593a', name: 'All people', - objectMetadataId: 'person', + objectId: 'person', type: 'table', }, { id: 'e26f66b7-f890-4a5c-b4d2-ec09987b5308', name: 'All opportunities', - objectMetadataId: 'company', + objectId: 'company', type: 'kanban', }, { id: '10bec73c-0aea-4cc4-a3b2-8c2186f29b43', name: 'All Companies (V2)', - objectMetadataId: '1a8487a0-480c-434e-b4c7-e22408b97047', + objectId: '1a8487a0-480c-434e-b4c7-e22408b97047', type: 'table', }, ]) diff --git a/server/src/database/typeorm/metadata/entities/field-metadata.entity.ts b/server/src/database/typeorm/metadata/entities/field-metadata.entity.ts deleted file mode 100644 index d4818e184..000000000 --- a/server/src/database/typeorm/metadata/entities/field-metadata.entity.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { - Entity, - Unique, - PrimaryGeneratedColumn, - Column, - ManyToOne, - JoinColumn, - OneToOne, - CreateDateColumn, - UpdateDateColumn, -} from 'typeorm'; - -import { FieldMetadataInterface } from 'src/tenant/schema-builder/interfaces/field-metadata.interface'; -import { FieldMetadataTargetColumnMap } from 'src/tenant/schema-builder/interfaces/field-metadata-target-column-map.interface'; - -import { ObjectMetadataEntity } from './object-metadata.entity'; -import { RelationMetadataEntity } from './relation-metadata.entity'; - -export enum FieldMetadataType { - UUID = 'uuid', - TEXT = 'TEXT', - PHONE = 'PHONE', - EMAIL = 'EMAIL', - DATE = 'DATE', - BOOLEAN = 'BOOLEAN', - NUMBER = 'NUMBER', - ENUM = 'ENUM', - URL = 'URL', - MONEY = 'MONEY', - RELATION = 'RELATION', -} - -@Entity('fieldMetadata') -@Unique('IndexOnNameObjectMetadataIdAndWorkspaceIdUnique', [ - 'name', - 'objectMetadataId', - 'workspaceId', -]) -export class FieldMetadataEntity implements FieldMetadataInterface { - @PrimaryGeneratedColumn('uuid') - id: string; - - @Column({ nullable: false, type: 'uuid' }) - objectMetadataId: string; - - @ManyToOne(() => ObjectMetadataEntity, (object) => object.fields, { - onDelete: 'CASCADE', - }) - @JoinColumn({ name: 'objectMetadataId' }) - object: ObjectMetadataEntity; - - @Column({ nullable: false }) - type: FieldMetadataType; - - @Column({ nullable: false }) - name: string; - - @Column({ nullable: false }) - label: string; - - @Column({ nullable: false, type: 'jsonb' }) - targetColumnMap: FieldMetadataTargetColumnMap; - - @Column({ nullable: true, type: 'text' }) - description: string; - - @Column({ nullable: true }) - icon: string; - - @Column('text', { nullable: true, array: true }) - enums: string[]; - - @Column({ default: false }) - isCustom: boolean; - - @Column({ default: false }) - isActive: boolean; - - @Column({ nullable: true, default: true }) - isNullable: boolean; - - @Column({ nullable: false }) - workspaceId: string; - - @OneToOne( - () => RelationMetadataEntity, - (relation: RelationMetadataEntity) => relation.fromFieldMetadata, - ) - fromRelationMetadata: RelationMetadataEntity; - - @OneToOne( - () => RelationMetadataEntity, - (relation: RelationMetadataEntity) => relation.toFieldMetadata, - ) - toRelationMetadata: RelationMetadataEntity; - - @CreateDateColumn() - createdAt: Date; - - @UpdateDateColumn() - updatedAt: Date; -} diff --git a/server/src/database/typeorm/metadata/entities/object-metadata.entity.ts b/server/src/database/typeorm/metadata/entities/object-metadata.entity.ts deleted file mode 100644 index 3140ca20f..000000000 --- a/server/src/database/typeorm/metadata/entities/object-metadata.entity.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { - Entity, - Unique, - PrimaryGeneratedColumn, - Column, - OneToMany, - CreateDateColumn, - UpdateDateColumn, -} from 'typeorm'; - -import { ObjectMetadataInterface } from 'src/tenant/schema-builder/interfaces/object-metadata.interface'; - -import { FieldMetadataEntity } from './field-metadata.entity'; -import { RelationMetadataEntity } from './relation-metadata.entity'; - -@Entity('objectMetadata') -@Unique('IndexOnNameSingularAndWorkspaceIdUnique', [ - 'nameSingular', - 'workspaceId', -]) -@Unique('IndexOnNamePluralAndWorkspaceIdUnique', ['namePlural', 'workspaceId']) -export class ObjectMetadataEntity implements ObjectMetadataInterface { - @PrimaryGeneratedColumn('uuid') - id: string; - - @Column({ nullable: false, type: 'uuid' }) - dataSourceId: string; - - @Column({ nullable: false }) - nameSingular: string; - - @Column({ nullable: false }) - namePlural: string; - - @Column({ nullable: false }) - labelSingular: string; - - @Column({ nullable: false }) - labelPlural: string; - - @Column({ nullable: true, type: 'text' }) - description: string; - - @Column({ nullable: true }) - icon: string; - - @Column({ nullable: false }) - targetTableName: string; - - @Column({ default: false }) - isCustom: boolean; - - @Column({ default: false }) - isActive: boolean; - - @Column({ nullable: false }) - workspaceId: string; - - @OneToMany(() => FieldMetadataEntity, (field) => field.object, { - cascade: true, - }) - fields: FieldMetadataEntity[]; - - @OneToMany( - () => RelationMetadataEntity, - (relation: RelationMetadataEntity) => relation.fromObjectMetadata, - ) - fromRelations: RelationMetadataEntity[]; - - @OneToMany( - () => RelationMetadataEntity, - (relation: RelationMetadataEntity) => relation.toObjectMetadata, - ) - toRelations: RelationMetadataEntity[]; - - @CreateDateColumn() - createdAt: Date; - - @UpdateDateColumn() - updatedAt: Date; -} diff --git a/server/src/database/typeorm/metadata/entities/relation-metadata.entity.ts b/server/src/database/typeorm/metadata/entities/relation-metadata.entity.ts deleted file mode 100644 index 3a3b53c32..000000000 --- a/server/src/database/typeorm/metadata/entities/relation-metadata.entity.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { - Column, - CreateDateColumn, - Entity, - JoinColumn, - ManyToOne, - OneToOne, - PrimaryGeneratedColumn, - UpdateDateColumn, -} from 'typeorm'; - -import { FieldMetadataEntity } from './field-metadata.entity'; -import { ObjectMetadataEntity } from './object-metadata.entity'; - -export enum RelationType { - ONE_TO_ONE = 'ONE_TO_ONE', - ONE_TO_MANY = 'ONE_TO_MANY', - MANY_TO_MANY = 'MANY_TO_MANY', -} - -@Entity('relationMetadata') -export class RelationMetadataEntity { - @PrimaryGeneratedColumn('uuid') - id: string; - - @Column({ nullable: false }) - relationType: RelationType; - - @Column({ nullable: false, type: 'uuid' }) - fromObjectMetadataId: string; - - @Column({ nullable: false, type: 'uuid' }) - toObjectMetadataId: string; - - @Column({ nullable: false, type: 'uuid' }) - fromFieldMetadataId: string; - - @Column({ nullable: false, type: 'uuid' }) - toFieldMetadataId: string; - - @Column({ nullable: false }) - workspaceId: string; - - @ManyToOne( - () => ObjectMetadataEntity, - (object: ObjectMetadataEntity) => object.fromRelations, - ) - fromObjectMetadata: ObjectMetadataEntity; - - @ManyToOne( - () => ObjectMetadataEntity, - (object: ObjectMetadataEntity) => object.toRelations, - ) - toObjectMetadata: ObjectMetadataEntity; - - @OneToOne( - () => FieldMetadataEntity, - (field: FieldMetadataEntity) => field.fromRelationMetadata, - ) - @JoinColumn() - fromFieldMetadata: FieldMetadataEntity; - - @OneToOne( - () => FieldMetadataEntity, - (field: FieldMetadataEntity) => field.toRelationMetadata, - ) - @JoinColumn() - toFieldMetadata: FieldMetadataEntity; - - @CreateDateColumn() - createdAt: Date; - - @UpdateDateColumn() - updatedAt: Date; -} diff --git a/server/src/database/typeorm/metadata/migrations/1699543628458-setupMetadataTables.ts b/server/src/database/typeorm/metadata/migrations/1699543628458-setupMetadataTables.ts deleted file mode 100644 index 1d07b4b0c..000000000 --- a/server/src/database/typeorm/metadata/migrations/1699543628458-setupMetadataTables.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { MigrationInterface, QueryRunner } from 'typeorm'; - -export class SetupMetadataTables1699543628458 implements MigrationInterface { - name = 'SetupMetadataTables1699543628458'; - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `CREATE TABLE "metadata"."objectMetadata" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "dataSourceId" uuid NOT NULL, "nameSingular" character varying NOT NULL, "namePlural" character varying NOT NULL, "labelSingular" character varying NOT NULL, "labelPlural" character varying NOT NULL, "description" text, "icon" character varying, "targetTableName" character varying NOT NULL, "isCustom" boolean NOT NULL DEFAULT false, "isActive" boolean NOT NULL DEFAULT false, "workspaceId" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "IndexOnNamePluralAndWorkspaceIdUnique" UNIQUE ("namePlural", "workspaceId"), CONSTRAINT "IndexOnNameSingularAndWorkspaceIdUnique" UNIQUE ("nameSingular", "workspaceId"), CONSTRAINT "PK_81fb7f4f4244211cfbd188af1e8" PRIMARY KEY ("id"))`, - ); - await queryRunner.query( - `CREATE TABLE "metadata"."fieldMetadata" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "objectMetadataId" uuid NOT NULL, "type" character varying NOT NULL, "name" character varying NOT NULL, "label" character varying NOT NULL, "targetColumnMap" jsonb NOT NULL, "description" text, "icon" character varying, "enums" text array, "isCustom" boolean NOT NULL DEFAULT false, "isActive" boolean NOT NULL DEFAULT false, "isNullable" boolean DEFAULT true, "workspaceId" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "IndexOnNameObjectMetadataIdAndWorkspaceIdUnique" UNIQUE ("name", "objectMetadataId", "workspaceId"), CONSTRAINT "PK_d046b1c7cea325ebc4cdc25e7a9" PRIMARY KEY ("id"))`, - ); - await queryRunner.query( - `CREATE TABLE "metadata"."relationMetadata" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "relationType" character varying NOT NULL, "fromObjectMetadataId" uuid NOT NULL, "toObjectMetadataId" uuid NOT NULL, "fromFieldMetadataId" uuid NOT NULL, "toFieldMetadataId" uuid NOT NULL, "workspaceId" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "REL_3deb257254145a3bdde9575e7d" UNIQUE ("fromFieldMetadataId"), CONSTRAINT "REL_9dea8f90d04edbbf9c541a95c3" UNIQUE ("toFieldMetadataId"), CONSTRAINT "PK_2724f60cb4f17a89481a7e8d7d3" PRIMARY KEY ("id"))`, - ); - await queryRunner.query( - `CREATE TYPE "metadata"."dataSource_type_enum" AS ENUM('postgres')`, - ); - await queryRunner.query( - `CREATE TABLE "metadata"."dataSource" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "url" character varying, "schema" character varying, "type" "metadata"."dataSource_type_enum" NOT NULL DEFAULT 'postgres', "label" character varying, "isRemote" boolean NOT NULL DEFAULT false, "workspaceId" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_6d01ae6c0f47baf4f8e37342268" PRIMARY KEY ("id"))`, - ); - await queryRunner.query( - `CREATE TABLE "metadata"."tenantMigration" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "migrations" jsonb, "name" character varying, "isCustom" boolean NOT NULL DEFAULT false, "appliedAt" TIMESTAMP, "workspaceId" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_f9b06eb42494795f73acb5c2350" PRIMARY KEY ("id"))`, - ); - await queryRunner.query( - `ALTER TABLE "metadata"."fieldMetadata" ADD CONSTRAINT "FK_de2a09b9e3e690440480d2dee26" FOREIGN KEY ("objectMetadataId") REFERENCES "metadata"."objectMetadata"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "metadata"."relationMetadata" ADD CONSTRAINT "FK_f2a0acd3a548ee446a1a35df44d" FOREIGN KEY ("fromObjectMetadataId") REFERENCES "metadata"."objectMetadata"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "metadata"."relationMetadata" ADD CONSTRAINT "FK_0f781f589e5a527b8f3d3a4b824" FOREIGN KEY ("toObjectMetadataId") REFERENCES "metadata"."objectMetadata"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "metadata"."relationMetadata" ADD CONSTRAINT "FK_3deb257254145a3bdde9575e7d6" FOREIGN KEY ("fromFieldMetadataId") REFERENCES "metadata"."fieldMetadata"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "metadata"."relationMetadata" ADD CONSTRAINT "FK_9dea8f90d04edbbf9c541a95c3b" FOREIGN KEY ("toFieldMetadataId") REFERENCES "metadata"."fieldMetadata"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, - ); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `ALTER TABLE "metadata"."relationMetadata" DROP CONSTRAINT "FK_9dea8f90d04edbbf9c541a95c3b"`, - ); - await queryRunner.query( - `ALTER TABLE "metadata"."relationMetadata" DROP CONSTRAINT "FK_3deb257254145a3bdde9575e7d6"`, - ); - await queryRunner.query( - `ALTER TABLE "metadata"."relationMetadata" DROP CONSTRAINT "FK_0f781f589e5a527b8f3d3a4b824"`, - ); - await queryRunner.query( - `ALTER TABLE "metadata"."relationMetadata" DROP CONSTRAINT "FK_f2a0acd3a548ee446a1a35df44d"`, - ); - await queryRunner.query( - `ALTER TABLE "metadata"."fieldMetadata" DROP CONSTRAINT "FK_de2a09b9e3e690440480d2dee26"`, - ); - await queryRunner.query(`DROP TABLE "metadata"."tenantMigration"`); - await queryRunner.query(`DROP TABLE "metadata"."dataSource"`); - await queryRunner.query(`DROP TYPE "metadata"."dataSource_type_enum"`); - await queryRunner.query(`DROP TABLE "metadata"."relationMetadata"`); - await queryRunner.query(`DROP TABLE "metadata"."fieldMetadata"`); - await queryRunner.query(`DROP TABLE "metadata"."objectMetadata"`); - } -} diff --git a/server/src/database/typeorm/typeorm.module.ts b/server/src/database/typeorm/typeorm.module.ts deleted file mode 100644 index 955f44f8f..000000000 --- a/server/src/database/typeorm/typeorm.module.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm'; - -import { TypeORMService } from './typeorm.service'; - -import { typeORMMetadataModuleOptions } from './metadata/metadata.datasource'; - -const metadataTypeORMFactory = async (): Promise => ({ - ...typeORMMetadataModuleOptions, - name: 'metadata', -}); - -@Module({ - imports: [ - TypeOrmModule.forRootAsync({ - useFactory: metadataTypeORMFactory, - name: 'metadata', - }), - ], - providers: [TypeORMService], - exports: [TypeORMService], -}) -export class TypeORMModule {} diff --git a/server/src/database/typeorm/typeorm.service.ts b/server/src/database/typeorm/typeorm.service.ts deleted file mode 100644 index df0d6c34f..000000000 --- a/server/src/database/typeorm/typeorm.service.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common'; - -import { DataSource } from 'typeorm'; - -import { EnvironmentService } from 'src/integrations/environment/environment.service'; - -import { DataSourceEntity } from './metadata/entities/data-source.entity'; - -@Injectable() -export class TypeORMService implements OnModuleInit, OnModuleDestroy { - private mainDataSource: DataSource; - private dataSources: Map = new Map(); - - constructor(private readonly environmentService: EnvironmentService) { - this.mainDataSource = new DataSource({ - url: environmentService.getPGDatabaseUrl(), - type: 'postgres', - logging: false, - schema: 'public', - }); - } - - /** - * Connects to a data source using metadata. Returns a cached connection if it exists. - * @param dataSource DataSourceEntity - * @returns Promise - */ - public async connectToDataSource( - dataSource: DataSourceEntity, - ): Promise { - if (this.dataSources.has(dataSource.id)) { - return this.dataSources.get(dataSource.id); - } - - const schema = dataSource.schema; - - const workspaceDataSource = new DataSource({ - url: dataSource.url ?? this.environmentService.getPGDatabaseUrl(), - type: 'postgres', - logging: ['query'], - schema, - }); - - await workspaceDataSource.initialize(); - - this.dataSources.set(dataSource.id, workspaceDataSource); - - return workspaceDataSource; - } - - /** - * Disconnects from a workspace data source. - * @param dataSourceId - * @returns Promise - * - */ - public async disconnectFromDataSource(dataSourceId: string) { - if (!this.dataSources.has(dataSourceId)) { - return; - } - - const dataSource = this.dataSources.get(dataSourceId); - - await dataSource?.destroy(); - - this.dataSources.delete(dataSourceId); - } - - /** - * Creates a new schema - * @param workspaceId - * @returns Promise - */ - public async createSchema(schemaName: string): Promise { - const queryRunner = this.mainDataSource.createQueryRunner(); - - await queryRunner.createSchema(schemaName, true); - - await queryRunner.release(); - - return schemaName; - } - - public async deleteSchema(schemaName: string) { - const queryRunner = this.mainDataSource.createQueryRunner(); - - await queryRunner.dropSchema(schemaName, true, true); - - await queryRunner.release(); - } - - async onModuleInit() { - // Init main data source "default" schema - await this.mainDataSource.initialize(); - } - - async onModuleDestroy() { - // Destroy main data source "default" schema - await this.mainDataSource.destroy(); - - // Destroy all workspace data sources - for (const [, dataSource] of this.dataSources) { - await dataSource.destroy(); - } - } -} diff --git a/server/src/database/commands/data-seed-tenant.command.ts b/server/src/metadata/commands/data-seed-tenant.command.ts similarity index 80% rename from server/src/database/commands/data-seed-tenant.command.ts rename to server/src/metadata/commands/data-seed-tenant.command.ts index 07b96444a..107aa917d 100644 --- a/server/src/database/commands/data-seed-tenant.command.ts +++ b/server/src/metadata/commands/data-seed-tenant.command.ts @@ -4,14 +4,14 @@ import { Command, CommandRunner } from 'nest-commander'; import { DataSource } from 'typeorm'; import { DataSourceMetadataService } from 'src/metadata/data-source-metadata/data-source-metadata.service'; +import { DataSourceService } from 'src/metadata/data-source/data-source.service'; import { TenantMigrationService } from 'src/metadata/tenant-migration/tenant-migration.service'; -import { TenantMigrationRunnerService } from 'src/tenant-migration-runner/tenant-migration-runner.service'; +import { MigrationRunnerService } from 'src/metadata/migration-runner/migration-runner.service'; import { seedCompanies } from 'src/database/typeorm-seeds/tenant/companies'; import { seedViewFields } from 'src/database/typeorm-seeds/tenant/view-fields'; import { seedViews } from 'src/database/typeorm-seeds/tenant/views'; import { seedFieldMetadata } from 'src/database/typeorm-seeds/metadata/field-metadata'; import { seedObjectMetadata } from 'src/database/typeorm-seeds/metadata/object-metadata'; -import { TypeORMService } from 'src/database/typeorm/typeorm.service'; // TODO: implement dry-run @Command({ @@ -26,9 +26,9 @@ export class DataSeedTenantCommand extends CommandRunner { @InjectDataSource('metadata') private readonly metadataDataSource: DataSource, private readonly dataSourceMetadataService: DataSourceMetadataService, - private readonly typeORMService: TypeORMService, + private readonly dataSourceService: DataSourceService, private readonly tenantMigrationService: TenantMigrationService, - private readonly migrationRunnerService: TenantMigrationRunnerService, + private readonly migrationRunnerService: MigrationRunnerService, ) { super(); } @@ -39,9 +39,10 @@ export class DataSeedTenantCommand extends CommandRunner { this.workspaceId, ); - const workspaceDataSource = await this.typeORMService.connectToDataSource( - dataSourceMetadata, - ); + const workspaceDataSource = + await this.dataSourceService.connectToWorkspaceDataSource( + this.workspaceId, + ); if (!workspaceDataSource) { throw new Error('Could not connect to workspace data source'); @@ -61,6 +62,8 @@ export class DataSeedTenantCommand extends CommandRunner { await seedViewFields(workspaceDataSource, dataSourceMetadata.schema); await seedViews(workspaceDataSource, dataSourceMetadata.schema); - await this.typeORMService.disconnectFromDataSource(dataSourceMetadata.id); + await this.dataSourceService.disconnectFromWorkspaceDataSource( + this.workspaceId, + ); } } diff --git a/server/src/metadata/commands/metadata-command.module.ts b/server/src/metadata/commands/metadata-command.module.ts new file mode 100644 index 000000000..14f0919c2 --- /dev/null +++ b/server/src/metadata/commands/metadata-command.module.ts @@ -0,0 +1,31 @@ +import { Module } from '@nestjs/common'; + +import { TenantMigrationModule } from 'src/metadata/tenant-migration/tenant-migration.module'; +import { MigrationRunnerModule } from 'src/metadata/migration-runner/migration-runner.module'; +import { ObjectMetadataModule } from 'src/metadata/object-metadata/object-metadata.module'; +import { FieldMetadataModule } from 'src/metadata/field-metadata/field-metadata.module'; +import { TenantInitialisationModule } from 'src/metadata/tenant-initialisation/tenant-initialisation.module'; +import { DataSourceMetadataModule } from 'src/metadata/data-source-metadata/data-source-metadata.module'; +import { DataSourceModule } from 'src/metadata/data-source/data-source.module'; + +import { SyncTenantMetadataCommand } from './sync-tenant-metadata.command'; +import { RunTenantMigrationsCommand } from './run-tenant-migrations.command'; +import { DataSeedTenantCommand } from './data-seed-tenant.command'; + +@Module({ + imports: [ + TenantMigrationModule, + MigrationRunnerModule, + ObjectMetadataModule, + FieldMetadataModule, + DataSourceMetadataModule, + TenantInitialisationModule, + DataSourceModule, + ], + providers: [ + RunTenantMigrationsCommand, + SyncTenantMetadataCommand, + DataSeedTenantCommand, + ], +}) +export class MetadataCommandModule {} diff --git a/server/src/tenant-migration-runner/commands/run-tenant-migrations.command.ts b/server/src/metadata/commands/run-tenant-migrations.command.ts similarity index 80% rename from server/src/tenant-migration-runner/commands/run-tenant-migrations.command.ts rename to server/src/metadata/commands/run-tenant-migrations.command.ts index 89ec659ca..557a23574 100644 --- a/server/src/tenant-migration-runner/commands/run-tenant-migrations.command.ts +++ b/server/src/metadata/commands/run-tenant-migrations.command.ts @@ -1,7 +1,7 @@ import { Command, CommandRunner, Option } from 'nest-commander'; import { TenantMigrationService } from 'src/metadata/tenant-migration/tenant-migration.service'; -import { TenantMigrationRunnerService } from 'src/tenant-migration-runner/tenant-migration-runner.service'; +import { MigrationRunnerService } from 'src/metadata/migration-runner/migration-runner.service'; // TODO: implement dry-run interface RunTenantMigrationsOptions { @@ -15,7 +15,7 @@ interface RunTenantMigrationsOptions { export class RunTenantMigrationsCommand extends CommandRunner { constructor( private readonly tenantMigrationService: TenantMigrationService, - private readonly tenantMigrationRunnerService: TenantMigrationRunnerService, + private readonly migrationRunnerService: MigrationRunnerService, ) { super(); } @@ -28,7 +28,7 @@ export class RunTenantMigrationsCommand extends CommandRunner { await this.tenantMigrationService.insertStandardMigrations( options.workspaceId, ); - await this.tenantMigrationRunnerService.executeMigrationFromPendingMigrations( + await this.migrationRunnerService.executeMigrationFromPendingMigrations( options.workspaceId, ); } diff --git a/server/src/tenant-manager/commands/sync-tenant-metadata.command.ts b/server/src/metadata/commands/sync-tenant-metadata.command.ts similarity index 77% rename from server/src/tenant-manager/commands/sync-tenant-metadata.command.ts rename to server/src/metadata/commands/sync-tenant-metadata.command.ts index f489d47a2..ffa299d27 100644 --- a/server/src/tenant-manager/commands/sync-tenant-metadata.command.ts +++ b/server/src/metadata/commands/sync-tenant-metadata.command.ts @@ -1,7 +1,7 @@ import { Command, CommandRunner, Option } from 'nest-commander'; +import { ObjectMetadataService } from 'src/metadata/object-metadata/services/object-metadata.service'; import { DataSourceMetadataService } from 'src/metadata/data-source-metadata/data-source-metadata.service'; -import { TenantManagerService } from 'src/tenant-manager/tenant-manager.service'; // TODO: implement dry-run interface RunTenantMigrationsOptions { @@ -14,7 +14,7 @@ interface RunTenantMigrationsOptions { }) export class SyncTenantMetadataCommand extends CommandRunner { constructor( - private readonly tenantManagerService: TenantManagerService, + private readonly objectMetadataService: ObjectMetadataService, private readonly dataSourceMetadataService: DataSourceMetadataService, ) { super(); @@ -31,7 +31,11 @@ export class SyncTenantMetadataCommand extends CommandRunner { ); // TODO: This solution could be improved, using a diff for example, we should not have to delete all metadata and recreate them. - await this.tenantManagerService.resetStandardObjectsAndFieldsMetadata( + await this.objectMetadataService.deleteMany({ + workspaceId: { eq: options.workspaceId }, + }); + + await this.objectMetadataService.createStandardObjectsAndFieldsMetadata( dataSourceMetadata.id, options.workspaceId, ); diff --git a/server/src/database/typeorm/metadata/entities/data-source.entity.ts b/server/src/metadata/data-source-metadata/data-source-metadata.entity.ts similarity index 63% rename from server/src/database/typeorm/metadata/entities/data-source.entity.ts rename to server/src/metadata/data-source-metadata/data-source-metadata.entity.ts index 29011c72d..0af0aa0ed 100644 --- a/server/src/database/typeorm/metadata/entities/data-source.entity.ts +++ b/server/src/metadata/data-source-metadata/data-source-metadata.entity.ts @@ -1,16 +1,16 @@ import { - DataSourceOptions, - Entity, - PrimaryGeneratedColumn, Column, CreateDateColumn, + Entity, + PrimaryGeneratedColumn, UpdateDateColumn, + DataSourceOptions, } from 'typeorm'; type DataSourceType = DataSourceOptions['type']; -@Entity('dataSource') -export class DataSourceEntity { +@Entity('data_source_metadata') +export class DataSourceMetadata { @PrimaryGeneratedColumn('uuid') id: string; @@ -23,18 +23,18 @@ export class DataSourceEntity { @Column({ type: 'enum', enum: ['postgres'], default: 'postgres' }) type: DataSourceType; - @Column({ nullable: true }) + @Column({ nullable: true, name: 'label' }) label: string; - @Column({ default: false }) + @Column({ default: false, name: 'is_remote' }) isRemote: boolean; - @Column({ nullable: false }) + @Column({ nullable: false, name: 'workspace_id' }) workspaceId: string; - @CreateDateColumn() + @CreateDateColumn({ name: 'created_at' }) createdAt: Date; - @UpdateDateColumn() + @UpdateDateColumn({ name: 'updated_at' }) updatedAt: Date; } diff --git a/server/src/metadata/data-source-metadata/data-source-metadata.module.ts b/server/src/metadata/data-source-metadata/data-source-metadata.module.ts index 511588db6..b4fdc2f38 100644 --- a/server/src/metadata/data-source-metadata/data-source-metadata.module.ts +++ b/server/src/metadata/data-source-metadata/data-source-metadata.module.ts @@ -1,12 +1,11 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { DataSourceEntity } from 'src/database/typeorm/metadata/entities/data-source.entity'; - import { DataSourceMetadataService } from './data-source-metadata.service'; +import { DataSourceMetadata } from './data-source-metadata.entity'; @Module({ - imports: [TypeOrmModule.forFeature([DataSourceEntity], 'metadata')], + imports: [TypeOrmModule.forFeature([DataSourceMetadata], 'metadata')], providers: [DataSourceMetadataService], exports: [DataSourceMetadataService], }) diff --git a/server/src/metadata/data-source-metadata/data-source-metadata.service.spec.ts b/server/src/metadata/data-source-metadata/data-source-metadata.service.spec.ts new file mode 100644 index 000000000..50403ed8b --- /dev/null +++ b/server/src/metadata/data-source-metadata/data-source-metadata.service.spec.ts @@ -0,0 +1,27 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { getRepositoryToken } from '@nestjs/typeorm'; + +import { DataSourceMetadataService } from './data-source-metadata.service'; +import { DataSourceMetadata } from './data-source-metadata.entity'; + +describe('DataSourceMetadataService', () => { + let service: DataSourceMetadataService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + DataSourceMetadataService, + { + provide: getRepositoryToken(DataSourceMetadata, 'metadata'), + useValue: {}, + }, + ], + }).compile(); + + service = module.get(DataSourceMetadataService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/server/src/metadata/data-source-metadata/data-source-metadata.service.ts b/server/src/metadata/data-source-metadata/data-source-metadata.service.ts index 2ab2acea9..6698a2bf6 100644 --- a/server/src/metadata/data-source-metadata/data-source-metadata.service.ts +++ b/server/src/metadata/data-source-metadata/data-source-metadata.service.ts @@ -3,13 +3,13 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { DataSourceEntity } from 'src/database/typeorm/metadata/entities/data-source.entity'; +import { DataSourceMetadata } from './data-source-metadata.entity'; @Injectable() export class DataSourceMetadataService { constructor( - @InjectRepository(DataSourceEntity, 'metadata') - private readonly dataSourceMetadataRepository: Repository, + @InjectRepository(DataSourceMetadata, 'metadata') + private readonly dataSourceMetadataRepository: Repository, ) {} async createDataSourceMetadata(workspaceId: string, workspaceSchema: string) { diff --git a/server/src/metadata/data-source/data-source.module.ts b/server/src/metadata/data-source/data-source.module.ts new file mode 100644 index 000000000..48cd14143 --- /dev/null +++ b/server/src/metadata/data-source/data-source.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; + +import { DataSourceMetadataModule } from 'src/metadata/data-source-metadata/data-source-metadata.module'; + +import { DataSourceService } from './data-source.service'; + +@Module({ + imports: [DataSourceMetadataModule], + providers: [DataSourceService], + exports: [DataSourceService], +}) +export class DataSourceModule {} diff --git a/server/src/metadata/data-source/data-source.service.spec.ts b/server/src/metadata/data-source/data-source.service.spec.ts new file mode 100644 index 000000000..a4026407f --- /dev/null +++ b/server/src/metadata/data-source/data-source.service.spec.ts @@ -0,0 +1,34 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +import { EnvironmentService } from 'src/integrations/environment/environment.service'; +import { DataSourceMetadataService } from 'src/metadata/data-source-metadata/data-source-metadata.service'; + +import { DataSourceService } from './data-source.service'; + +describe('DataSourceService', () => { + let service: DataSourceService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + DataSourceService, + { + provide: EnvironmentService, + useValue: { + getPGDatabaseUrl: () => '', + }, + }, + { + provide: DataSourceMetadataService, + useValue: {}, + }, + ], + }).compile(); + + service = module.get(DataSourceService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/server/src/metadata/data-source/data-source.service.ts b/server/src/metadata/data-source/data-source.service.ts new file mode 100644 index 000000000..60d761766 --- /dev/null +++ b/server/src/metadata/data-source/data-source.service.ts @@ -0,0 +1,153 @@ +import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common'; + +import { DataSource } from 'typeorm'; + +import { EnvironmentService } from 'src/integrations/environment/environment.service'; +import { DataSourceMetadataService } from 'src/metadata/data-source-metadata/data-source-metadata.service'; +import { TenantMigration } from 'src/metadata/tenant-migration/tenant-migration.entity'; + +import { uuidToBase36 } from './data-source.util'; + +@Injectable() +export class DataSourceService implements OnModuleInit, OnModuleDestroy { + private mainDataSource: DataSource; + private dataSources: Map = new Map(); + + constructor( + private readonly environmentService: EnvironmentService, + private readonly dataSourceMetadataService: DataSourceMetadataService, + ) { + this.mainDataSource = new DataSource({ + url: environmentService.getPGDatabaseUrl(), + type: 'postgres', + logging: false, + schema: 'public', + }); + } + + /** + * Creates a new schema for a given workspaceId + * @param workspaceId + * @returns Promise + */ + public async createWorkspaceSchema(workspaceId: string): Promise { + const schemaName = this.getSchemaName(workspaceId); + + const queryRunner = this.mainDataSource.createQueryRunner(); + const schemaAlreadyExists = await queryRunner.hasSchema(schemaName); + + if (schemaAlreadyExists) { + throw new Error(`Schema ${schemaName} already exists`); + } + + await queryRunner.createSchema(schemaName, true); + + await queryRunner.release(); + + return schemaName; + } + + /** + * Connects to a workspace data source using the workspace metadata. Returns a cached connection if it exists. + * @param workspaceId + * @returns Promise + */ + public async connectToWorkspaceDataSource( + workspaceId: string, + ): Promise { + if (this.dataSources.has(workspaceId)) { + const cachedDataSource = this.dataSources.get(workspaceId); + return cachedDataSource; + } + + // We only want the first one for now, we will handle multiple data sources later with remote datasources. + // However, we will need to differentiate the data sources because we won't run migrations on remote data sources for example. + const dataSourceMetadata = + await this.dataSourceMetadataService.getLastDataSourceMetadataFromWorkspaceIdOrFail( + workspaceId, + ); + const schema = dataSourceMetadata.schema; + + // Probably not needed as we will ask for the schema name OR store public by default if it's remote + if (!schema && !dataSourceMetadata.isRemote) { + throw Error( + "No schema found for this non-remote data source, we don't want to fallback to public for workspace data sources.", + ); + } + + const workspaceDataSource = new DataSource({ + // TODO: We should use later dataSourceMetadata.type and use a switch case condition to create the right data source + url: dataSourceMetadata.url ?? this.environmentService.getPGDatabaseUrl(), + type: 'postgres', + logging: ['query'], + schema, + entities: { + TenantMigration, + }, + }); + + await workspaceDataSource.initialize(); + + this.dataSources.set(workspaceId, workspaceDataSource); + + return workspaceDataSource; + } + + /** + * Disconnects from a workspace data source. + * @param workspaceId + * @returns Promise + * + */ + public async disconnectFromWorkspaceDataSource(workspaceId: string) { + if (!this.dataSources.has(workspaceId)) { + return; + } + + const dataSource = this.dataSources.get(workspaceId); + + await dataSource?.destroy(); + + this.dataSources.delete(workspaceId); + } + + /** + * + * Returns the schema name for a given workspaceId + * @param workspaceId + * @returns string + */ + public getSchemaName(workspaceId: string): string { + return `workspace_${uuidToBase36(workspaceId)}`; + } + + public async deleteWorkspaceSchema(workspaceId: string) { + const schemaName = this.getSchemaName(workspaceId); + const queryRunner = this.mainDataSource.createQueryRunner(); + const schemaAlreadyExists = await queryRunner.hasSchema(schemaName); + + if (!schemaAlreadyExists) { + await queryRunner.release(); + return; + } + + await queryRunner.dropSchema(schemaName, true, true); + + await queryRunner.release(); + } + + async onModuleInit() { + // Init main data source "default" schema + await this.mainDataSource.initialize(); + } + + async onModuleDestroy() { + // Destroy main data source "default" schema + await this.mainDataSource.destroy(); + + // Destroy all workspace data sources + for (const [, dataSource] of this.dataSources) { + await dataSource.destroy(); + } + } +} diff --git a/server/src/metadata/data-source/data-source.util.ts b/server/src/metadata/data-source/data-source.util.ts new file mode 100644 index 000000000..0658a1e46 --- /dev/null +++ b/server/src/metadata/data-source/data-source.util.ts @@ -0,0 +1,21 @@ +/** + * Converts a UUID to a base 36 string. + * This is used to generate the schema name since hyphens from workspace uuid are not allowed in postgres schema names. + * + * @param uuid + * @returns + */ +export function uuidToBase36(uuid: string): string { + let devId = false; + + if (uuid.startsWith('twenty-')) { + devId = true; + // Clean dev uuids (twenty-) + uuid = uuid.replace('twenty-', ''); + } + const hexString = uuid.replace(/-/g, ''); + const base10Number = BigInt('0x' + hexString); + const base36String = base10Number.toString(36); + + return `${devId ? 'twenty_' : ''}${base36String}`; +} diff --git a/server/src/metadata/field-metadata/dtos/create-field.input.ts b/server/src/metadata/field-metadata/dtos/create-field.input.ts index cc4e7d8cf..04b445aac 100644 --- a/server/src/metadata/field-metadata/dtos/create-field.input.ts +++ b/server/src/metadata/field-metadata/dtos/create-field.input.ts @@ -1,6 +1,5 @@ -import { Field, HideField, InputType } from '@nestjs/graphql'; +import { Field, InputType } from '@nestjs/graphql'; -import { BeforeCreateOne } from '@ptc-org/nestjs-query-graphql'; import { IsEnum, IsNotEmpty, @@ -9,13 +8,9 @@ import { IsUUID, } from 'class-validator'; -import { FieldMetadataTargetColumnMap } from 'src/tenant/schema-builder/interfaces/field-metadata-target-column-map.interface'; - -import { FieldMetadataType } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; -import { BeforeCreateOneField } from 'src/metadata/field-metadata/hooks/before-create-one-field.hook'; +import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; @InputType() -@BeforeCreateOne(BeforeCreateOneField) export class CreateFieldInput { @IsString() @IsNotEmpty() @@ -34,7 +29,7 @@ export class CreateFieldInput { @IsUUID() @Field() - objectMetadataId: string; + objectId: string; @IsString() @IsOptional() @@ -45,10 +40,4 @@ export class CreateFieldInput { @IsOptional() @Field({ nullable: true }) icon?: string; - - @HideField() - targetColumnMap: FieldMetadataTargetColumnMap; - - @HideField() - workspaceId: string; } diff --git a/server/src/metadata/field-metadata/dtos/field-metadata.dto.ts b/server/src/metadata/field-metadata/dtos/field-metadata.dto.ts deleted file mode 100644 index 70636d24d..000000000 --- a/server/src/metadata/field-metadata/dtos/field-metadata.dto.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { - Field, - HideField, - ID, - ObjectType, - registerEnumType, -} from '@nestjs/graphql'; - -import { - Authorize, - IDField, - QueryOptions, - Relation, -} from '@ptc-org/nestjs-query-graphql'; - -import { FieldMetadataType } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; -import { RelationMetadataDTO } from 'src/metadata/relation-metadata/dtos/relation-metadata.dto'; - -registerEnumType(FieldMetadataType, { - name: 'FieldMetadataType', - description: 'Type of the field', -}); - -@ObjectType('field') -@Authorize({ - authorize: (context: any) => ({ - workspaceId: { eq: context?.req?.user?.workspace?.id }, - }), -}) -@QueryOptions({ - defaultResultSize: 10, - disableFilter: true, - disableSort: true, - maxResultsSize: 1000, -}) -@Relation('toRelationMetadata', () => RelationMetadataDTO, { - nullable: true, -}) -@Relation('fromRelationMetadata', () => RelationMetadataDTO, { - nullable: true, -}) -export class FieldMetadataDTO { - @IDField(() => ID) - id: string; - - @Field(() => FieldMetadataType) - type: FieldMetadataType; - - @Field() - name: string; - - @Field() - label: string; - - @Field({ nullable: true }) - description: string; - - @Field({ nullable: true }) - icon: string; - - @Field({ nullable: true, deprecationReason: 'Use label name instead' }) - placeholder?: string; - - @Field() - isCustom: boolean; - - @Field() - isActive: boolean; - - @Field() - isNullable: boolean; - - @HideField() - workspaceId: string; - - @Field() - createdAt: Date; - - @Field() - updatedAt: Date; -} diff --git a/server/src/metadata/field-metadata/field-metadata.auto-resolver-opts.ts b/server/src/metadata/field-metadata/field-metadata.auto-resolver-opts.ts new file mode 100644 index 000000000..66f3c53da --- /dev/null +++ b/server/src/metadata/field-metadata/field-metadata.auto-resolver-opts.ts @@ -0,0 +1,44 @@ +import { SortDirection } from '@ptc-org/nestjs-query-core'; +import { + AutoResolverOpts, + PagingStrategies, + ReadResolverOpts, +} from '@ptc-org/nestjs-query-graphql'; + +import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; + +import { FieldMetadata } from './field-metadata.entity'; + +import { FieldMetadataService } from './services/field-metadata.service'; +import { CreateFieldInput } from './dtos/create-field.input'; +import { UpdateFieldInput } from './dtos/update-field.input'; + +export const fieldMetadataAutoResolverOpts: AutoResolverOpts< + any, + any, + unknown, + unknown, + ReadResolverOpts, + PagingStrategies +>[] = [ + { + EntityClass: FieldMetadata, + DTOClass: FieldMetadata, + CreateDTOClass: CreateFieldInput, + UpdateDTOClass: UpdateFieldInput, + ServiceClass: FieldMetadataService, + enableTotalCount: true, + pagingStrategy: PagingStrategies.CURSOR, + read: { + defaultSort: [{ field: 'id', direction: SortDirection.DESC }], + }, + create: { + many: { disabled: true }, + }, + update: { + many: { disabled: true }, + }, + delete: { many: { disabled: true } }, + guards: [JwtAuthGuard], + }, +]; diff --git a/server/src/metadata/field-metadata/field-metadata.entity.ts b/server/src/metadata/field-metadata/field-metadata.entity.ts new file mode 100644 index 000000000..0d78f56e8 --- /dev/null +++ b/server/src/metadata/field-metadata/field-metadata.entity.ts @@ -0,0 +1,141 @@ +import { Field, ID, ObjectType, registerEnumType } from '@nestjs/graphql'; + +import { + Column, + CreateDateColumn, + Entity, + JoinColumn, + ManyToOne, + OneToOne, + PrimaryGeneratedColumn, + Unique, + UpdateDateColumn, +} from 'typeorm'; +import { + Authorize, + BeforeCreateOne, + IDField, + QueryOptions, + Relation, +} from '@ptc-org/nestjs-query-graphql'; + +import { FieldMetadataInterface } from 'src/tenant/schema-builder/interfaces/field-metadata.interface'; + +import { ObjectMetadata } from 'src/metadata/object-metadata/object-metadata.entity'; +import { RelationMetadata } from 'src/metadata/relation-metadata/relation-metadata.entity'; + +import { BeforeCreateOneField } from './hooks/before-create-one-field.hook'; +import { FieldMetadataTargetColumnMap } from './interfaces/field-metadata-target-column-map.interface'; + +export enum FieldMetadataType { + UUID = 'uuid', + TEXT = 'TEXT', + PHONE = 'PHONE', + EMAIL = 'EMAIL', + DATE = 'DATE', + BOOLEAN = 'BOOLEAN', + NUMBER = 'NUMBER', + ENUM = 'ENUM', + URL = 'URL', + MONEY = 'MONEY', + RELATION = 'RELATION', +} + +registerEnumType(FieldMetadataType, { + name: 'FieldMetadataType', + description: 'Type of the field', +}); + +@Entity('field_metadata') +@ObjectType('field') +@BeforeCreateOne(BeforeCreateOneField) +@Authorize({ + authorize: (context: any) => ({ + workspaceId: { eq: context?.req?.user?.workspace?.id }, + }), +}) +@QueryOptions({ + defaultResultSize: 10, + disableFilter: true, + disableSort: true, + maxResultsSize: 1000, +}) +@Unique('IndexOnNameObjectIdAndWorkspaceIdUnique', [ + 'name', + 'objectId', + 'workspaceId', +]) +@Relation('toRelationMetadata', () => RelationMetadata, { nullable: true }) +@Relation('fromRelationMetadata', () => RelationMetadata, { nullable: true }) +export class FieldMetadata implements FieldMetadataInterface { + @IDField(() => ID) + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column({ nullable: false, name: 'object_id' }) + objectId: string; + + @Field(() => FieldMetadataType) + @Column({ nullable: false }) + type: FieldMetadataType; + + @Field() + @Column({ nullable: false }) + name: string; + + @Field() + @Column({ nullable: false }) + label: string; + + @Column({ nullable: false, name: 'target_column_map', type: 'jsonb' }) + targetColumnMap: FieldMetadataTargetColumnMap; + + @Field({ nullable: true }) + @Column({ nullable: true, name: 'description', type: 'text' }) + description: string; + + @Field({ nullable: true }) + @Column({ nullable: true, name: 'icon' }) + icon: string; + + @Field({ nullable: true, deprecationReason: 'Use label name instead' }) + placeholder: string; + + @Column('text', { nullable: true, array: true }) + enums: string[]; + + @Field() + @Column({ default: false, name: 'is_custom' }) + isCustom: boolean; + + @Field() + @Column({ default: false, name: 'is_active' }) + isActive: boolean; + + @Field() + @Column({ nullable: true, default: true, name: 'is_nullable' }) + isNullable: boolean; + + @Column({ nullable: false, name: 'workspace_id' }) + workspaceId: string; + + @ManyToOne(() => ObjectMetadata, (object) => object.fields, { + onDelete: 'CASCADE', + }) + @JoinColumn({ name: 'object_id' }) + object: ObjectMetadata; + + @OneToOne(() => RelationMetadata, (relation) => relation.fromFieldMetadata) + fromRelationMetadata: RelationMetadata; + + @OneToOne(() => RelationMetadata, (relation) => relation.toFieldMetadata) + toRelationMetadata: RelationMetadata; + + @Field() + @CreateDateColumn({ name: 'created_at' }) + createdAt: Date; + + @Field() + @UpdateDateColumn({ name: 'updated_at' }) + updatedAt: Date; +} diff --git a/server/src/metadata/field-metadata/field-metadata.module.ts b/server/src/metadata/field-metadata/field-metadata.module.ts index 87bfa82cb..45b1ae626 100644 --- a/server/src/metadata/field-metadata/field-metadata.module.ts +++ b/server/src/metadata/field-metadata/field-metadata.module.ts @@ -1,56 +1,28 @@ import { Module } from '@nestjs/common'; -import { - NestjsQueryGraphQLModule, - PagingStrategies, -} from '@ptc-org/nestjs-query-graphql'; +import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'; import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'; -import { SortDirection } from '@ptc-org/nestjs-query-core'; -import { TenantMigrationRunnerModule } from 'src/tenant-migration-runner/tenant-migration-runner.module'; +import { MigrationRunnerModule } from 'src/metadata/migration-runner/migration-runner.module'; import { TenantMigrationModule } from 'src/metadata/tenant-migration/tenant-migration.module'; import { ObjectMetadataModule } from 'src/metadata/object-metadata/object-metadata.module'; -import { FieldMetadataEntity } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; -import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -import { FieldMetadataService } from './field-metadata.service'; +import { FieldMetadata } from './field-metadata.entity'; +import { fieldMetadataAutoResolverOpts } from './field-metadata.auto-resolver-opts'; -import { CreateFieldInput } from './dtos/create-field.input'; -import { FieldMetadataDTO } from './dtos/field-metadata.dto'; -import { UpdateFieldInput } from './dtos/update-field.input'; +import { FieldMetadataService } from './services/field-metadata.service'; @Module({ imports: [ NestjsQueryGraphQLModule.forFeature({ imports: [ - NestjsQueryTypeOrmModule.forFeature([FieldMetadataEntity], 'metadata'), + NestjsQueryTypeOrmModule.forFeature([FieldMetadata], 'metadata'), TenantMigrationModule, - TenantMigrationRunnerModule, + MigrationRunnerModule, ObjectMetadataModule, ], services: [FieldMetadataService], - resolvers: [ - { - EntityClass: FieldMetadataEntity, - DTOClass: FieldMetadataDTO, - CreateDTOClass: CreateFieldInput, - UpdateDTOClass: UpdateFieldInput, - ServiceClass: FieldMetadataService, - enableTotalCount: true, - pagingStrategy: PagingStrategies.CURSOR, - read: { - defaultSort: [{ field: 'id', direction: SortDirection.DESC }], - }, - create: { - many: { disabled: true }, - }, - update: { - many: { disabled: true }, - }, - delete: { many: { disabled: true } }, - guards: [JwtAuthGuard], - }, - ], + resolvers: fieldMetadataAutoResolverOpts, }), ], providers: [FieldMetadataService], diff --git a/server/src/metadata/field-metadata/hooks/before-create-one-field.hook.ts b/server/src/metadata/field-metadata/hooks/before-create-one-field.hook.ts index bd878871f..1d4402578 100644 --- a/server/src/metadata/field-metadata/hooks/before-create-one-field.hook.ts +++ b/server/src/metadata/field-metadata/hooks/before-create-one-field.hook.ts @@ -5,10 +5,10 @@ import { CreateOneInputType, } from '@ptc-org/nestjs-query-graphql'; -import { CreateFieldInput } from 'src/metadata/field-metadata/dtos/create-field.input'; +import { FieldMetadata } from 'src/metadata/field-metadata/field-metadata.entity'; @Injectable() -export class BeforeCreateOneField +export class BeforeCreateOneField implements BeforeCreateOneHook { async run( @@ -22,6 +22,8 @@ export class BeforeCreateOneField } instance.input.workspaceId = workspaceId; + instance.input.isActive = true; + instance.input.isCustom = true; return instance; } } diff --git a/server/src/tenant/schema-builder/interfaces/field-metadata-target-column-map.interface.ts b/server/src/metadata/field-metadata/interfaces/field-metadata-target-column-map.interface.ts similarity index 89% rename from server/src/tenant/schema-builder/interfaces/field-metadata-target-column-map.interface.ts rename to server/src/metadata/field-metadata/interfaces/field-metadata-target-column-map.interface.ts index cdde4daa0..65580c811 100644 --- a/server/src/tenant/schema-builder/interfaces/field-metadata-target-column-map.interface.ts +++ b/server/src/metadata/field-metadata/interfaces/field-metadata-target-column-map.interface.ts @@ -1,4 +1,4 @@ -import { FieldMetadataType } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; +import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; export interface FieldMetadataTargetColumnMapValue { value: string; diff --git a/server/src/metadata/field-metadata/services/field-metadata.service.spec.ts b/server/src/metadata/field-metadata/services/field-metadata.service.spec.ts new file mode 100644 index 000000000..87b62cad3 --- /dev/null +++ b/server/src/metadata/field-metadata/services/field-metadata.service.spec.ts @@ -0,0 +1,43 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { getRepositoryToken } from '@nestjs/typeorm'; + +import { FieldMetadata } from 'src/metadata/field-metadata/field-metadata.entity'; +import { MigrationRunnerService } from 'src/metadata/migration-runner/migration-runner.service'; +import { TenantMigrationService } from 'src/metadata/tenant-migration/tenant-migration.service'; +import { ObjectMetadataService } from 'src/metadata/object-metadata/services/object-metadata.service'; + +import { FieldMetadataService } from './field-metadata.service'; + +describe('FieldMetadataService', () => { + let service: FieldMetadataService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + FieldMetadataService, + { + provide: getRepositoryToken(FieldMetadata, 'metadata'), + useValue: {}, + }, + { + provide: ObjectMetadataService, + useValue: {}, + }, + { + provide: TenantMigrationService, + useValue: {}, + }, + { + provide: MigrationRunnerService, + useValue: {}, + }, + ], + }).compile(); + + service = module.get(FieldMetadataService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/server/src/metadata/field-metadata/field-metadata.service.ts b/server/src/metadata/field-metadata/services/field-metadata.service.ts similarity index 71% rename from server/src/metadata/field-metadata/field-metadata.service.ts rename to server/src/metadata/field-metadata/services/field-metadata.service.ts index c0cce5f92..36a418541 100644 --- a/server/src/metadata/field-metadata/field-metadata.service.ts +++ b/server/src/metadata/field-metadata/services/field-metadata.service.ts @@ -10,38 +10,37 @@ import { Repository } from 'typeorm'; import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; import { DeleteOneOptions } from '@ptc-org/nestjs-query-core'; +import { FieldMetadata } from 'src/metadata/field-metadata/field-metadata.entity'; import { convertFieldMetadataToColumnActions, generateTargetColumnMap, } from 'src/metadata/field-metadata/utils/field-metadata.util'; -import { TenantMigrationRunnerService } from 'src/tenant-migration-runner/tenant-migration-runner.service'; +import { MigrationRunnerService } from 'src/metadata/migration-runner/migration-runner.service'; import { TenantMigrationService } from 'src/metadata/tenant-migration/tenant-migration.service'; -import { ObjectMetadataService } from 'src/metadata/object-metadata/object-metadata.service'; -import { FieldMetadataEntity } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; -import { FieldMetadataDTO } from 'src/metadata/field-metadata/dtos/field-metadata.dto'; -import { CreateFieldInput } from 'src/metadata/field-metadata/dtos/create-field.input'; -import { TenantMigrationTableAction } from 'src/database/typeorm/metadata/entities/tenant-migration.entity'; +import { ObjectMetadataService } from 'src/metadata/object-metadata/services/object-metadata.service'; +import { TenantMigrationTableAction } from 'src/metadata/tenant-migration/tenant-migration.entity'; @Injectable() -export class FieldMetadataService extends TypeOrmQueryService { +export class FieldMetadataService extends TypeOrmQueryService { constructor( - @InjectRepository(FieldMetadataEntity, 'metadata') - private readonly fieldMetadataRepository: Repository, + @InjectRepository(FieldMetadata, 'metadata') + private readonly fieldMetadataRepository: Repository, private readonly objectMetadataService: ObjectMetadataService, private readonly tenantMigrationService: TenantMigrationService, - private readonly migrationRunnerService: TenantMigrationRunnerService, + private readonly migrationRunnerService: MigrationRunnerService, ) { super(fieldMetadataRepository); } override async deleteOne( id: string, - opts?: DeleteOneOptions | undefined, - ): Promise { + opts?: DeleteOneOptions | undefined, + ): Promise { const fieldMetadata = await this.fieldMetadataRepository.findOne({ where: { id }, }); + if (!fieldMetadata) { throw new NotFoundException('Field does not exist'); } @@ -59,12 +58,10 @@ export class FieldMetadataService extends TypeOrmQueryService { + override async createOne(record: FieldMetadata): Promise { const objectMetadata = await this.objectMetadataService.findOneWithinWorkspace( - record.objectMetadataId, + record.objectId, record.workspaceId, ); @@ -75,7 +72,7 @@ export class FieldMetadataService extends TypeOrmQueryService => ({ + ...typeORMMetadataModuleOptions, + name: 'metadata', +}); + @Module({ imports: [ + TypeOrmModule.forRootAsync({ + useFactory: typeORMFactory, + name: 'metadata', + }), GraphQLModule.forRoot({ context: ({ req }) => ({ req }), driver: YogaDriver, @@ -22,10 +36,11 @@ import { RelationMetadataModule } from './relation-metadata/relation-metadata.mo plugins: [], path: '/metadata', }), + DataSourceModule, DataSourceMetadataModule, FieldMetadataModule, ObjectMetadataModule, - TenantMigrationRunnerModule, + MigrationRunnerModule, TenantMigrationModule, RelationMetadataModule, ], diff --git a/server/src/tenant-migration-runner/utils/custom-table-default-column.util.ts b/server/src/metadata/migration-runner/custom-table-default-column.util.ts similarity index 100% rename from server/src/tenant-migration-runner/utils/custom-table-default-column.util.ts rename to server/src/metadata/migration-runner/custom-table-default-column.util.ts diff --git a/server/src/metadata/migration-runner/migration-runner.module.ts b/server/src/metadata/migration-runner/migration-runner.module.ts new file mode 100644 index 000000000..c042a7671 --- /dev/null +++ b/server/src/metadata/migration-runner/migration-runner.module.ts @@ -0,0 +1,13 @@ +import { Module } from '@nestjs/common'; + +import { DataSourceModule } from 'src/metadata/data-source/data-source.module'; +import { TenantMigrationModule } from 'src/metadata/tenant-migration/tenant-migration.module'; + +import { MigrationRunnerService } from './migration-runner.service'; + +@Module({ + imports: [DataSourceModule, TenantMigrationModule], + exports: [MigrationRunnerService], + providers: [MigrationRunnerService], +}) +export class MigrationRunnerModule {} diff --git a/server/src/metadata/migration-runner/migration-runner.service.spec.ts b/server/src/metadata/migration-runner/migration-runner.service.spec.ts new file mode 100644 index 000000000..e97caafe2 --- /dev/null +++ b/server/src/metadata/migration-runner/migration-runner.service.spec.ts @@ -0,0 +1,32 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +import { DataSourceService } from 'src/metadata/data-source/data-source.service'; +import { TenantMigrationService } from 'src/metadata/tenant-migration/tenant-migration.service'; + +import { MigrationRunnerService } from './migration-runner.service'; + +describe('MigrationRunnerService', () => { + let service: MigrationRunnerService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + MigrationRunnerService, + { + provide: DataSourceService, + useValue: {}, + }, + { + provide: TenantMigrationService, + useValue: {}, + }, + ], + }).compile(); + + service = module.get(MigrationRunnerService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/server/src/tenant-migration-runner/tenant-migration-runner.service.ts b/server/src/metadata/migration-runner/migration-runner.service.ts similarity index 91% rename from server/src/tenant-migration-runner/tenant-migration-runner.service.ts rename to server/src/metadata/migration-runner/migration-runner.service.ts index b0517b205..ca2193103 100644 --- a/server/src/tenant-migration-runner/tenant-migration-runner.service.ts +++ b/server/src/metadata/migration-runner/migration-runner.service.ts @@ -2,22 +2,22 @@ import { Injectable } from '@nestjs/common'; import { QueryRunner, Table, TableColumn, TableForeignKey } from 'typeorm'; -import { TenantMigrationService } from 'src/metadata/tenant-migration/tenant-migration.service'; +import { DataSourceService } from 'src/metadata/data-source/data-source.service'; import { TenantMigrationTableAction, TenantMigrationColumnAction, - TenantMigrationColumnActionType, TenantMigrationColumnCreate, TenantMigrationColumnRelation, -} from 'src/database/typeorm/metadata/entities/tenant-migration.entity'; -import { TenantDataSourceService } from 'src/tenant-datasource/tenant-datasource.service'; + TenantMigrationColumnActionType, +} from 'src/metadata/tenant-migration/tenant-migration.entity'; +import { TenantMigrationService } from 'src/metadata/tenant-migration/tenant-migration.service'; -import { customTableDefaultColumns } from './utils/custom-table-default-column.util'; +import { customTableDefaultColumns } from './custom-table-default-column.util'; @Injectable() -export class TenantMigrationRunnerService { +export class MigrationRunnerService { constructor( - private readonly tenantDataSourceService: TenantDataSourceService, + private readonly dataSourceService: DataSourceService, private readonly tenantMigrationService: TenantMigrationService, ) {} @@ -31,9 +31,7 @@ export class TenantMigrationRunnerService { workspaceId: string, ): Promise { const workspaceDataSource = - await this.tenantDataSourceService.connectToWorkspaceDataSource( - workspaceId, - ); + await this.dataSourceService.connectToWorkspaceDataSource(workspaceId); if (!workspaceDataSource) { throw new Error('Workspace data source not found'); @@ -52,7 +50,7 @@ export class TenantMigrationRunnerService { }, []); const queryRunner = workspaceDataSource?.createQueryRunner(); - const schemaName = this.tenantDataSourceService.getSchemaName(workspaceId); + const schemaName = this.dataSourceService.getSchemaName(workspaceId); // Loop over each migration and create or update the table // TODO: Should be done in a transaction diff --git a/server/src/metadata/migrations/1695214465080-InitMetadataTables.ts b/server/src/metadata/migrations/1695214465080-InitMetadataTables.ts new file mode 100644 index 000000000..13647df58 --- /dev/null +++ b/server/src/metadata/migrations/1695214465080-InitMetadataTables.ts @@ -0,0 +1,32 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class InitMetadataTables1695214465080 implements MigrationInterface { + name = 'InitMetadataTables1695214465080'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TYPE "metadata"."data_source_metadata_type_enum" AS ENUM ('postgres', 'mysql');`, + ); + await queryRunner.query( + `CREATE TABLE "metadata"."data_source_metadata" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "url" character varying, "schema" character varying, "type" "metadata"."data_source_metadata_type_enum" NOT NULL DEFAULT 'postgres', "display_name" character varying, "is_remote" boolean NOT NULL DEFAULT false, "workspace_id" character varying NOT NULL, "created_at" TIMESTAMP NOT NULL DEFAULT now(), "updated_at" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_923752b7e62a300a4969bd0e038" PRIMARY KEY ("id"))`, + ); + await queryRunner.query( + `CREATE TABLE "metadata"."field_metadata" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "object_id" uuid NOT NULL, "type" character varying NOT NULL, "display_name" character varying NOT NULL, "target_column_name" character varying NOT NULL, "is_custom" boolean NOT NULL DEFAULT false, "workspace_id" character varying NOT NULL, "created_at" TIMESTAMP NOT NULL DEFAULT now(), "updated_at" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_c75db587904cad6af109b5c65f1" PRIMARY KEY ("id"))`, + ); + await queryRunner.query( + `CREATE TABLE "metadata"."object_metadata" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "data_source_id" character varying NOT NULL, "display_name" character varying NOT NULL, "target_table_name" character varying NOT NULL, "is_custom" boolean NOT NULL DEFAULT false, "workspace_id" character varying NOT NULL, "created_at" TIMESTAMP NOT NULL DEFAULT now(), "updated_at" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_c8c5f885767b356949c18c201c1" PRIMARY KEY ("id"))`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD CONSTRAINT "FK_38179b299795e48887fc99f937a" FOREIGN KEY ("object_id") REFERENCES "metadata"."object_metadata"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP CONSTRAINT "FK_38179b299795e48887fc99f937a"`, + ); + await queryRunner.query(`DROP TABLE "metadata"."object_metadata"`); + await queryRunner.query(`DROP TABLE "metadata"."field_metadata"`); + await queryRunner.query(`DROP TABLE "metadata"."data_source_metadata"`); + } +} diff --git a/server/src/metadata/migrations/1695717691800-alter-field-metadata-table.ts b/server/src/metadata/migrations/1695717691800-alter-field-metadata-table.ts new file mode 100644 index 000000000..4483db8df --- /dev/null +++ b/server/src/metadata/migrations/1695717691800-alter-field-metadata-table.ts @@ -0,0 +1,61 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AlterFieldMetadataTable1695717691800 + implements MigrationInterface +{ + name = 'AlterFieldMetadataTable1695717691800'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "enums" text array`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "is_nullable" boolean DEFAULT true`, + ); + await queryRunner.query( + `ALTER TYPE "metadata"."data_source_metadata_type_enum" RENAME TO "data_source_metadata_type_enum_old"`, + ); + await queryRunner.query( + `CREATE TYPE "metadata"."data_source_metadata_type_enum" AS ENUM('postgres')`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."data_source_metadata" ALTER COLUMN "type" DROP DEFAULT`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."data_source_metadata" ALTER COLUMN "type" TYPE "metadata"."data_source_metadata_type_enum" USING "type"::"text"::"metadata"."data_source_metadata_type_enum"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."data_source_metadata" ALTER COLUMN "type" SET DEFAULT 'postgres'`, + ); + await queryRunner.query( + `DROP TYPE "metadata"."data_source_metadata_type_enum_old"`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TYPE "metadata"."data_source_metadata_type_enum_old" AS ENUM('postgres', 'mysql')`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."data_source_metadata" ALTER COLUMN "type" DROP DEFAULT`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."data_source_metadata" ALTER COLUMN "type" TYPE "metadata"."data_source_metadata_type_enum_old" USING "type"::"text"::"metadata"."data_source_metadata_type_enum_old"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."data_source_metadata" ALTER COLUMN "type" SET DEFAULT 'postgres'`, + ); + await queryRunner.query( + `DROP TYPE "metadata"."data_source_metadata_type_enum"`, + ); + await queryRunner.query( + `ALTER TYPE "metadata"."data_source_metadata_type_enum_old" RENAME TO "data_source_metadata_type_enum"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "is_nullable"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "enums"`, + ); + } +} diff --git a/server/src/metadata/migrations/1696409050890-add-target-column-map.ts b/server/src/metadata/migrations/1696409050890-add-target-column-map.ts new file mode 100644 index 000000000..23da21eb0 --- /dev/null +++ b/server/src/metadata/migrations/1696409050890-add-target-column-map.ts @@ -0,0 +1,71 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddTargetColumnMap1696409050890 implements MigrationInterface { + name = 'AddTargetColumnMap1696409050890'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "description" text`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "icon" character varying`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "placeholder" character varying`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "target_column_map" jsonb`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "is_active" boolean NOT NULL DEFAULT false`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ADD "display_name_singular" character varying`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ADD "display_name_plural" character varying`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ADD "description" text`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ADD "icon" character varying`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ADD "is_active" boolean NOT NULL DEFAULT false`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" DROP COLUMN "is_active"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" DROP COLUMN "icon"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" DROP COLUMN "description"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" DROP COLUMN "display_name_plural"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" DROP COLUMN "display_name_singular"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "is_active"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "target_column_map"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "placeholder"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "icon"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "description"`, + ); + } +} diff --git a/server/src/metadata/migrations/1697126636202-MetadataNameLabelRefactoring.ts b/server/src/metadata/migrations/1697126636202-MetadataNameLabelRefactoring.ts new file mode 100644 index 000000000..1f0bc5094 --- /dev/null +++ b/server/src/metadata/migrations/1697126636202-MetadataNameLabelRefactoring.ts @@ -0,0 +1,149 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class MetadataNameLabelRefactoring1697126636202 + implements MigrationInterface +{ + name = 'MetadataNameLabelRefactoring1697126636202'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."data_source_metadata" RENAME COLUMN "display_name" TO "label"`, + ); + await queryRunner.query( + `CREATE TABLE "metadata"."tenant_migrations" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "migrations" jsonb, "applied_at" TIMESTAMP, "created_at" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_cb644cbc7f5092850f25eecb465" PRIMARY KEY ("id"))`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" DROP COLUMN "display_name"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" DROP COLUMN "display_name_singular"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" DROP COLUMN "display_name_plural"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "display_name"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "target_column_name"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ADD "name_singular" character varying NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ADD CONSTRAINT "UQ_8b063d2a685474dbae56cd685d2" UNIQUE ("name_singular")`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ADD "name_plural" character varying NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ADD CONSTRAINT "UQ_a2387e1b21120110b7e3db83da1" UNIQUE ("name_plural")`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ADD "label_singular" character varying NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ADD "label_plural" character varying NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "name_singular" character varying NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "name_plural" character varying`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "label_singular" character varying NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "label_plural" character varying`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."data_source_metadata" ALTER COLUMN "id" SET DEFAULT uuid_generate_v4()`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP CONSTRAINT "FK_38179b299795e48887fc99f937a"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ALTER COLUMN "id" SET DEFAULT uuid_generate_v4()`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ALTER COLUMN "id" SET DEFAULT uuid_generate_v4()`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ALTER COLUMN "target_column_map" SET NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD CONSTRAINT "FK_38179b299795e48887fc99f937a" FOREIGN KEY ("object_id") REFERENCES "metadata"."object_metadata"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP CONSTRAINT "FK_38179b299795e48887fc99f937a"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ALTER COLUMN "target_column_map" DROP NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ALTER COLUMN "id" DROP DEFAULT`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ALTER COLUMN "id" DROP DEFAULT`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD CONSTRAINT "FK_38179b299795e48887fc99f937a" FOREIGN KEY ("object_id") REFERENCES "metadata"."object_metadata"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."data_source_metadata" ALTER COLUMN "id" DROP DEFAULT`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "label_plural"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "label_singular"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "name_plural"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "name_singular"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" DROP COLUMN "label_plural"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" DROP COLUMN "label_singular"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" DROP CONSTRAINT "UQ_a2387e1b21120110b7e3db83da1"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" DROP COLUMN "name_plural"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" DROP CONSTRAINT "UQ_8b063d2a685474dbae56cd685d2"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" DROP COLUMN "name_singular"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "target_column_name" character varying NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "display_name" character varying NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ADD "display_name_plural" character varying`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ADD "display_name_singular" character varying`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ADD "display_name" character varying NOT NULL`, + ); + await queryRunner.query(`DROP TABLE "metadata"."tenant_migrations"`); + await queryRunner.query( + `ALTER TABLE "metadata"."data_source_metadata" RENAME COLUMN "label" TO "display_name"`, + ); + } +} diff --git a/server/src/metadata/migrations/1697471445015-removeFieldMetadataPlaceholder.ts b/server/src/metadata/migrations/1697471445015-removeFieldMetadataPlaceholder.ts new file mode 100644 index 000000000..b1235e2e5 --- /dev/null +++ b/server/src/metadata/migrations/1697471445015-removeFieldMetadataPlaceholder.ts @@ -0,0 +1,19 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class RemoveFieldMetadataPlaceholder1697471445015 + implements MigrationInterface +{ + name = 'RemoveFieldMetadataPlaceholder1697471445015'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "placeholder"`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "placeholder" character varying`, + ); + } +} diff --git a/server/src/metadata/migrations/1697474804403-addSoftDelete.ts b/server/src/metadata/migrations/1697474804403-addSoftDelete.ts new file mode 100644 index 000000000..675525c67 --- /dev/null +++ b/server/src/metadata/migrations/1697474804403-addSoftDelete.ts @@ -0,0 +1,23 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddSoftDelete1697474804403 implements MigrationInterface { + name = 'AddSoftDelete1697474804403'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ADD "deleted_at" TIMESTAMP`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "deleted_at" TIMESTAMP`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "deleted_at"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" DROP COLUMN "deleted_at"`, + ); + } +} diff --git a/server/src/metadata/migrations/1697534910933-removeSingularPluralFromFieldLabelAndName.ts b/server/src/metadata/migrations/1697534910933-removeSingularPluralFromFieldLabelAndName.ts new file mode 100644 index 000000000..e8a351513 --- /dev/null +++ b/server/src/metadata/migrations/1697534910933-removeSingularPluralFromFieldLabelAndName.ts @@ -0,0 +1,49 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class RemoveSingularPluralFromFieldLabelAndName1697534910933 + implements MigrationInterface +{ + name = 'RemoveSingularPluralFromFieldLabelAndName1697534910933'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "name_singular"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "name_plural"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "label_singular"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "label_plural"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "name" character varying NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "label" character varying NOT NULL`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "label"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "name"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "label_plural" character varying`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "label_singular" character varying NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "name_plural" character varying`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "name_singular" character varying NOT NULL`, + ); + } +} diff --git a/server/src/metadata/migrations/1697622715467-addNameAndIsCustomToTenantMigration.ts b/server/src/metadata/migrations/1697622715467-addNameAndIsCustomToTenantMigration.ts new file mode 100644 index 000000000..7e828d9f2 --- /dev/null +++ b/server/src/metadata/migrations/1697622715467-addNameAndIsCustomToTenantMigration.ts @@ -0,0 +1,55 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddNameAndIsCustomToTenantMigration1697622715467 + implements MigrationInterface +{ + name = 'AddNameAndIsCustomToTenantMigration1697622715467'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."tenant_migrations" DROP COLUMN "applied_at"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."tenant_migrations" DROP COLUMN "created_at"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."tenant_migrations" ADD "name" character varying`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."tenant_migrations" ADD "isCustom" boolean NOT NULL DEFAULT false`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."tenant_migrations" ADD "appliedAt" TIMESTAMP`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."tenant_migrations" ADD "workspaceId" character varying NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."tenant_migrations" ADD "createdAt" TIMESTAMP NOT NULL DEFAULT now()`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."tenant_migrations" DROP COLUMN "createdAt"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."tenant_migrations" DROP COLUMN "workspaceId"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."tenant_migrations" DROP COLUMN "appliedAt"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."tenant_migrations" DROP COLUMN "isCustom"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."tenant_migrations" DROP COLUMN "name"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."tenant_migrations" ADD "created_at" TIMESTAMP NOT NULL DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."tenant_migrations" ADD "applied_at" TIMESTAMP`, + ); + } +} diff --git a/server/src/metadata/migrations/1697630766924-addUniqueConstraintsOnFieldObjectMetadata.ts b/server/src/metadata/migrations/1697630766924-addUniqueConstraintsOnFieldObjectMetadata.ts new file mode 100644 index 000000000..cf1b58037 --- /dev/null +++ b/server/src/metadata/migrations/1697630766924-addUniqueConstraintsOnFieldObjectMetadata.ts @@ -0,0 +1,43 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddUniqueConstraintsOnFieldObjectMetadata1697630766924 + implements MigrationInterface +{ + name = 'AddUniqueConstraintsOnFieldObjectMetadata1697630766924'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" DROP CONSTRAINT "UQ_8b063d2a685474dbae56cd685d2"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" DROP CONSTRAINT "UQ_a2387e1b21120110b7e3db83da1"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD CONSTRAINT "IndexOnNameObjectIdAndWorkspaceIdUnique" UNIQUE ("name", "object_id", "workspace_id")`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ADD CONSTRAINT "IndexOnNamePluralAndWorkspaceIdUnique" UNIQUE ("name_plural", "workspace_id")`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ADD CONSTRAINT "IndexOnNameSingularAndWorkspaceIdUnique" UNIQUE ("name_singular", "workspace_id")`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" DROP CONSTRAINT "IndexOnNameSingularAndWorkspaceIdUnique"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" DROP CONSTRAINT "IndexOnNamePluralAndWorkspaceIdUnique"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP CONSTRAINT "IndexOnNameAndWorkspaceIdUnique"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ADD CONSTRAINT "UQ_a2387e1b21120110b7e3db83da1" UNIQUE ("name_plural")`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ADD CONSTRAINT "UQ_8b063d2a685474dbae56cd685d2" UNIQUE ("name_singular")`, + ); + } +} diff --git a/server/src/metadata/migrations/1698328717102-removeMetadataSoftDelete.ts b/server/src/metadata/migrations/1698328717102-removeMetadataSoftDelete.ts new file mode 100644 index 000000000..1f960e711 --- /dev/null +++ b/server/src/metadata/migrations/1698328717102-removeMetadataSoftDelete.ts @@ -0,0 +1,37 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class RemoveMetadataSoftDelete1698328717102 + implements MigrationInterface +{ + name = 'RemoveMetadataSoftDelete1698328717102'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP CONSTRAINT "FK_38179b299795e48887fc99f937a"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" DROP COLUMN "deleted_at"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP COLUMN "deleted_at"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD CONSTRAINT "FK_38179b299795e48887fc99f937a" FOREIGN KEY ("object_id") REFERENCES "metadata"."object_metadata"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" DROP CONSTRAINT "FK_38179b299795e48887fc99f937a"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD "deleted_at" TIMESTAMP`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."object_metadata" ADD "deleted_at" TIMESTAMP`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."field_metadata" ADD CONSTRAINT "FK_38179b299795e48887fc99f937a" FOREIGN KEY ("object_id") REFERENCES "metadata"."object_metadata"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, + ); + } +} diff --git a/server/src/metadata/migrations/1699289664146-addRelationMetadata.ts b/server/src/metadata/migrations/1699289664146-addRelationMetadata.ts new file mode 100644 index 000000000..f2b7d333b --- /dev/null +++ b/server/src/metadata/migrations/1699289664146-addRelationMetadata.ts @@ -0,0 +1,39 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddRelationMetadata1699289664146 implements MigrationInterface { + name = 'AddRelationMetadata1699289664146'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TABLE "metadata"."relationMetadata" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "relationType" character varying NOT NULL, "fromObjectMetadataId" uuid NOT NULL, "toObjectMetadataId" uuid NOT NULL, "fromFieldMetadataId" uuid NOT NULL, "toFieldMetadataId" uuid NOT NULL, "workspaceId" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "REL_3deb257254145a3bdde9575e7d" UNIQUE ("fromFieldMetadataId"), CONSTRAINT "REL_9dea8f90d04edbbf9c541a95c3" UNIQUE ("toFieldMetadataId"), CONSTRAINT "PK_2724f60cb4f17a89481a7e8d7d3" PRIMARY KEY ("id"))`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."relationMetadata" ADD CONSTRAINT "FK_f2a0acd3a548ee446a1a35df44d" FOREIGN KEY ("fromObjectMetadataId") REFERENCES "metadata"."object_metadata"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."relationMetadata" ADD CONSTRAINT "FK_0f781f589e5a527b8f3d3a4b824" FOREIGN KEY ("toObjectMetadataId") REFERENCES "metadata"."object_metadata"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."relationMetadata" ADD CONSTRAINT "FK_3deb257254145a3bdde9575e7d6" FOREIGN KEY ("fromFieldMetadataId") REFERENCES "metadata"."field_metadata"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."relationMetadata" ADD CONSTRAINT "FK_9dea8f90d04edbbf9c541a95c3b" FOREIGN KEY ("toFieldMetadataId") REFERENCES "metadata"."field_metadata"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "metadata"."relationMetadata" DROP CONSTRAINT "FK_9dea8f90d04edbbf9c541a95c3b"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."relationMetadata" DROP CONSTRAINT "FK_3deb257254145a3bdde9575e7d6"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."relationMetadata" DROP CONSTRAINT "FK_0f781f589e5a527b8f3d3a4b824"`, + ); + await queryRunner.query( + `ALTER TABLE "metadata"."relationMetadata" DROP CONSTRAINT "FK_f2a0acd3a548ee446a1a35df44d"`, + ); + await queryRunner.query(`DROP TABLE "metadata"."relationMetadata"`); + } +} diff --git a/server/src/metadata/object-metadata/dtos/create-object.input.ts b/server/src/metadata/object-metadata/dtos/create-object.input.ts index 505bb7a60..4c0ac158e 100644 --- a/server/src/metadata/object-metadata/dtos/create-object.input.ts +++ b/server/src/metadata/object-metadata/dtos/create-object.input.ts @@ -1,12 +1,8 @@ -import { Field, HideField, InputType } from '@nestjs/graphql'; +import { Field, InputType } from '@nestjs/graphql'; -import { BeforeCreateOne } from '@ptc-org/nestjs-query-graphql'; import { IsNotEmpty, IsOptional, IsString } from 'class-validator'; -import { BeforeCreateOneObject } from 'src/metadata/object-metadata/hooks/before-create-one-object.hook'; - @InputType() -@BeforeCreateOne(BeforeCreateOneObject) export class CreateObjectInput { @IsString() @IsNotEmpty() @@ -37,10 +33,4 @@ export class CreateObjectInput { @IsOptional() @Field({ nullable: true }) icon?: string; - - @HideField() - dataSourceId: string; - - @HideField() - workspaceId: string; } diff --git a/server/src/metadata/object-metadata/dtos/object-metadata.dto.ts b/server/src/metadata/object-metadata/dtos/object-metadata.dto.ts deleted file mode 100644 index 5baaec569..000000000 --- a/server/src/metadata/object-metadata/dtos/object-metadata.dto.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { ObjectType, ID, Field, HideField } from '@nestjs/graphql'; - -import { - Authorize, - CursorConnection, - IDField, - QueryOptions, -} from '@ptc-org/nestjs-query-graphql'; - -import { FieldMetadataDTO } from 'src/metadata/field-metadata/dtos/field-metadata.dto'; - -@ObjectType('object') -@Authorize({ - authorize: (context: any) => ({ - workspaceId: { eq: context?.req?.user?.workspace?.id }, - }), -}) -@QueryOptions({ - defaultResultSize: 10, - disableFilter: true, - disableSort: true, - maxResultsSize: 1000, -}) -@CursorConnection('fields', () => FieldMetadataDTO) -export class ObjectMetadataDTO { - @IDField(() => ID) - id: string; - - @Field() - dataSourceId: string; - - @Field() - nameSingular: string; - - @Field() - namePlural: string; - - @Field() - labelSingular: string; - - @Field() - labelPlural: string; - - @Field({ nullable: true }) - description: string; - - @Field({ nullable: true }) - icon: string; - - @Field() - isCustom: boolean; - - @Field() - isActive: boolean; - - @HideField() - workspaceId: string; - - @Field() - createdAt: Date; - - @Field() - updatedAt: Date; -} diff --git a/server/src/metadata/object-metadata/hooks/before-create-one-object.hook.ts b/server/src/metadata/object-metadata/hooks/before-create-one-object.hook.ts index 0d0f0c20b..b291d2bbd 100644 --- a/server/src/metadata/object-metadata/hooks/before-create-one-object.hook.ts +++ b/server/src/metadata/object-metadata/hooks/before-create-one-object.hook.ts @@ -6,10 +6,10 @@ import { } from '@ptc-org/nestjs-query-graphql'; import { DataSourceMetadataService } from 'src/metadata/data-source-metadata/data-source-metadata.service'; -import { CreateObjectInput } from 'src/metadata/object-metadata/dtos/create-object.input'; +import { ObjectMetadata } from 'src/metadata/object-metadata/object-metadata.entity'; @Injectable() -export class BeforeCreateOneObject +export class BeforeCreateOneObject implements BeforeCreateOneHook { constructor(readonly dataSourceMetadataService: DataSourceMetadataService) {} @@ -30,7 +30,10 @@ export class BeforeCreateOneObject ); instance.input.dataSourceId = lastDataSourceMetadata.id; + instance.input.targetTableName = `_${instance.input.namePlural}`; instance.input.workspaceId = workspaceId; + instance.input.isActive = true; + instance.input.isCustom = true; return instance; } } diff --git a/server/src/metadata/object-metadata/object-metadata.auto-resolver-opts.ts b/server/src/metadata/object-metadata/object-metadata.auto-resolver-opts.ts new file mode 100644 index 000000000..dd0477c50 --- /dev/null +++ b/server/src/metadata/object-metadata/object-metadata.auto-resolver-opts.ts @@ -0,0 +1,44 @@ +import { SortDirection } from '@ptc-org/nestjs-query-core'; +import { + AutoResolverOpts, + PagingStrategies, + ReadResolverOpts, +} from '@ptc-org/nestjs-query-graphql'; + +import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; + +import { ObjectMetadata } from './object-metadata.entity'; + +import { ObjectMetadataService } from './services/object-metadata.service'; +import { CreateObjectInput } from './dtos/create-object.input'; +import { UpdateObjectInput } from './dtos/update-object.input'; + +export const objectMetadataAutoResolverOpts: AutoResolverOpts< + any, + any, + unknown, + unknown, + ReadResolverOpts, + PagingStrategies +>[] = [ + { + EntityClass: ObjectMetadata, + DTOClass: ObjectMetadata, + CreateDTOClass: CreateObjectInput, + UpdateDTOClass: UpdateObjectInput, + ServiceClass: ObjectMetadataService, + enableTotalCount: true, + pagingStrategy: PagingStrategies.CURSOR, + read: { + defaultSort: [{ field: 'id', direction: SortDirection.DESC }], + }, + create: { + many: { disabled: true }, + }, + update: { + many: { disabled: true }, + }, + delete: { many: { disabled: true } }, + guards: [JwtAuthGuard], + }, +]; diff --git a/server/src/metadata/object-metadata/object-metadata.entity.ts b/server/src/metadata/object-metadata/object-metadata.entity.ts new file mode 100644 index 000000000..4caabefb1 --- /dev/null +++ b/server/src/metadata/object-metadata/object-metadata.entity.ts @@ -0,0 +1,112 @@ +import { ObjectType, ID, Field } from '@nestjs/graphql'; + +import { + Column, + CreateDateColumn, + Entity, + OneToMany, + PrimaryGeneratedColumn, + Unique, + UpdateDateColumn, +} from 'typeorm'; +import { + Authorize, + BeforeCreateOne, + CursorConnection, + IDField, + QueryOptions, +} from '@ptc-org/nestjs-query-graphql'; + +import { ObjectMetadataInterface } from 'src/tenant/schema-builder/interfaces/object-metadata.interface'; + +import { FieldMetadata } from 'src/metadata/field-metadata/field-metadata.entity'; +import { RelationMetadata } from 'src/metadata/relation-metadata/relation-metadata.entity'; + +import { BeforeCreateOneObject } from './hooks/before-create-one-object.hook'; + +@Entity('object_metadata') +@ObjectType('object') +@BeforeCreateOne(BeforeCreateOneObject) +@Authorize({ + authorize: (context: any) => ({ + workspaceId: { eq: context?.req?.user?.workspace?.id }, + }), +}) +@QueryOptions({ + defaultResultSize: 10, + disableFilter: true, + disableSort: true, + maxResultsSize: 1000, +}) +@CursorConnection('fields', () => FieldMetadata) +@Unique('IndexOnNameSingularAndWorkspaceIdUnique', [ + 'nameSingular', + 'workspaceId', +]) +@Unique('IndexOnNamePluralAndWorkspaceIdUnique', ['namePlural', 'workspaceId']) +export class ObjectMetadata implements ObjectMetadataInterface { + @IDField(() => ID) + @PrimaryGeneratedColumn('uuid') + id: string; + + @Field() + @Column({ nullable: false, name: 'data_source_id' }) + dataSourceId: string; + + @Field() + @Column({ nullable: false, name: 'name_singular' }) + nameSingular: string; + + @Field() + @Column({ nullable: false, name: 'name_plural' }) + namePlural: string; + + @Field() + @Column({ nullable: false, name: 'label_singular' }) + labelSingular: string; + + @Field() + @Column({ nullable: false, name: 'label_plural' }) + labelPlural: string; + + @Field({ nullable: true }) + @Column({ nullable: true, name: 'description', type: 'text' }) + description: string; + + @Field({ nullable: true }) + @Column({ nullable: true, name: 'icon' }) + icon: string; + + @Column({ nullable: false, name: 'target_table_name' }) + targetTableName: string; + + @Field() + @Column({ default: false, name: 'is_custom' }) + isCustom: boolean; + + @Field() + @Column({ default: false, name: 'is_active' }) + isActive: boolean; + + @Column({ nullable: false, name: 'workspace_id' }) + workspaceId: string; + + @OneToMany(() => FieldMetadata, (field) => field.object, { + cascade: true, + }) + fields: FieldMetadata[]; + + @OneToMany(() => RelationMetadata, (relation) => relation.fromObjectMetadata) + fromRelations: RelationMetadata[]; + + @OneToMany(() => RelationMetadata, (relation) => relation.toObjectMetadata) + toRelations: RelationMetadata[]; + + @Field() + @CreateDateColumn({ name: 'created_at' }) + createdAt: Date; + + @Field() + @UpdateDateColumn({ name: 'updated_at' }) + updatedAt: Date; +} diff --git a/server/src/metadata/object-metadata/object-metadata.module.ts b/server/src/metadata/object-metadata/object-metadata.module.ts index 1b24985fd..24822972a 100644 --- a/server/src/metadata/object-metadata/object-metadata.module.ts +++ b/server/src/metadata/object-metadata/object-metadata.module.ts @@ -1,56 +1,28 @@ import { Module } from '@nestjs/common'; -import { - NestjsQueryGraphQLModule, - PagingStrategies, -} from '@ptc-org/nestjs-query-graphql'; +import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'; import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'; -import { SortDirection } from '@ptc-org/nestjs-query-core'; import { DataSourceMetadataModule } from 'src/metadata/data-source-metadata/data-source-metadata.module'; -import { TenantMigrationRunnerModule } from 'src/tenant-migration-runner/tenant-migration-runner.module'; +import { MigrationRunnerModule } from 'src/metadata/migration-runner/migration-runner.module'; import { TenantMigrationModule } from 'src/metadata/tenant-migration/tenant-migration.module'; -import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -import { ObjectMetadataEntity } from 'src/database/typeorm/metadata/entities/object-metadata.entity'; -import { ObjectMetadataService } from './object-metadata.service'; +import { ObjectMetadata } from './object-metadata.entity'; +import { objectMetadataAutoResolverOpts } from './object-metadata.auto-resolver-opts'; -import { CreateObjectInput } from './dtos/create-object.input'; -import { UpdateObjectInput } from './dtos/update-object.input'; -import { ObjectMetadataDTO } from './dtos/object-metadata.dto'; +import { ObjectMetadataService } from './services/object-metadata.service'; @Module({ imports: [ NestjsQueryGraphQLModule.forFeature({ imports: [ - NestjsQueryTypeOrmModule.forFeature([ObjectMetadataEntity], 'metadata'), + NestjsQueryTypeOrmModule.forFeature([ObjectMetadata], 'metadata'), DataSourceMetadataModule, TenantMigrationModule, - TenantMigrationRunnerModule, + MigrationRunnerModule, ], services: [ObjectMetadataService], - resolvers: [ - { - EntityClass: ObjectMetadataEntity, - DTOClass: ObjectMetadataDTO, - CreateDTOClass: CreateObjectInput, - UpdateDTOClass: UpdateObjectInput, - ServiceClass: ObjectMetadataService, - enableTotalCount: true, - pagingStrategy: PagingStrategies.CURSOR, - read: { - defaultSort: [{ field: 'id', direction: SortDirection.DESC }], - }, - create: { - many: { disabled: true }, - }, - update: { - many: { disabled: true }, - }, - delete: { many: { disabled: true } }, - guards: [JwtAuthGuard], - }, - ], + resolvers: objectMetadataAutoResolverOpts, }), ], providers: [ObjectMetadataService], diff --git a/server/src/metadata/object-metadata/services/object-metadata.service.spec.ts b/server/src/metadata/object-metadata/services/object-metadata.service.spec.ts new file mode 100644 index 000000000..8b179110b --- /dev/null +++ b/server/src/metadata/object-metadata/services/object-metadata.service.spec.ts @@ -0,0 +1,38 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { getRepositoryToken } from '@nestjs/typeorm'; + +import { ObjectMetadata } from 'src/metadata/object-metadata/object-metadata.entity'; +import { MigrationRunnerService } from 'src/metadata/migration-runner/migration-runner.service'; +import { TenantMigrationService } from 'src/metadata/tenant-migration/tenant-migration.service'; + +import { ObjectMetadataService } from './object-metadata.service'; + +describe('ObjectMetadataService', () => { + let service: ObjectMetadataService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + ObjectMetadataService, + { + provide: getRepositoryToken(ObjectMetadata, 'metadata'), + useValue: {}, + }, + { + provide: TenantMigrationService, + useValue: {}, + }, + { + provide: MigrationRunnerService, + useValue: {}, + }, + ], + }).compile(); + + service = module.get(ObjectMetadataService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/server/src/metadata/object-metadata/object-metadata.service.ts b/server/src/metadata/object-metadata/services/object-metadata.service.ts similarity index 60% rename from server/src/metadata/object-metadata/object-metadata.service.ts rename to server/src/metadata/object-metadata/services/object-metadata.service.ts index f14a66e4e..3324d3b9c 100644 --- a/server/src/metadata/object-metadata/object-metadata.service.ts +++ b/server/src/metadata/object-metadata/services/object-metadata.service.ts @@ -7,27 +7,30 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Equal, In, Repository } from 'typeorm'; import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; +import { DeleteOneOptions } from '@ptc-org/nestjs-query-core'; import { TenantMigrationService } from 'src/metadata/tenant-migration/tenant-migration.service'; -import { TenantMigrationRunnerService } from 'src/tenant-migration-runner/tenant-migration-runner.service'; -import { ObjectMetadataEntity } from 'src/database/typeorm/metadata/entities/object-metadata.entity'; -import { TenantMigrationTableAction } from 'src/database/typeorm/metadata/entities/tenant-migration.entity'; - -import { CreateObjectInput } from './dtos/create-object.input'; +import { TenantMigrationTableAction } from 'src/metadata/tenant-migration/tenant-migration.entity'; +import { MigrationRunnerService } from 'src/metadata/migration-runner/migration-runner.service'; +import { ObjectMetadata } from 'src/metadata/object-metadata/object-metadata.entity'; +import { standardObjectsMetadata } from 'src/metadata/standard-objects/standard-object-metadata'; @Injectable() -export class ObjectMetadataService extends TypeOrmQueryService { +export class ObjectMetadataService extends TypeOrmQueryService { constructor( - @InjectRepository(ObjectMetadataEntity, 'metadata') - private readonly objectMetadataRepository: Repository, + @InjectRepository(ObjectMetadata, 'metadata') + private readonly objectMetadataRepository: Repository, private readonly tenantMigrationService: TenantMigrationService, - private readonly migrationRunnerService: TenantMigrationRunnerService, + private readonly migrationRunnerService: MigrationRunnerService, ) { super(objectMetadataRepository); } - override async deleteOne(id: string): Promise { + override async deleteOne( + id: string, + opts?: DeleteOneOptions | undefined, + ): Promise { const objectMetadata = await this.objectMetadataRepository.findOne({ where: { id }, }); @@ -44,18 +47,11 @@ export class ObjectMetadataService extends TypeOrmQueryService { - const createdObjectMetadata = await super.createOne({ - ...record, - targetTableName: `_${record.nameSingular}`, - isActive: true, - isCustom: true, - }); + override async createOne(record: ObjectMetadata): Promise { + const createdObjectMetadata = await super.createOne(record); await this.tenantMigrationService.createCustomMigration( createdObjectMetadata.workspaceId, @@ -107,6 +103,34 @@ export class ObjectMetadataService extends TypeOrmQueryService ({ + ...objectMetadata, + dataSourceId: dataSourceMetadataId, + workspaceId, + isCustom: false, + isActive: true, + fields: objectMetadata.fields.map((field) => ({ + ...field, + workspaceId, + isCustom: false, + isActive: true, + })), + })), + ); + } + public async deleteObjectsMetadata(workspaceId: string) { await this.objectMetadataRepository.delete({ workspaceId }); } diff --git a/server/src/metadata/relation-metadata/dtos/create-relation.input.ts b/server/src/metadata/relation-metadata/dtos/create-relation.input.ts index cc6a7f615..2068b1fd0 100644 --- a/server/src/metadata/relation-metadata/dtos/create-relation.input.ts +++ b/server/src/metadata/relation-metadata/dtos/create-relation.input.ts @@ -1,4 +1,4 @@ -import { Field, HideField, InputType } from '@nestjs/graphql'; +import { Field, InputType } from '@nestjs/graphql'; import { BeforeCreateOne } from '@ptc-org/nestjs-query-graphql'; import { @@ -9,10 +9,9 @@ import { IsUUID, } from 'class-validator'; +import { RelationType } from 'src/metadata/relation-metadata/relation-metadata.entity'; import { BeforeCreateOneRelation } from 'src/metadata/relation-metadata/hooks/before-create-one-relation.hook'; -import { RelationType } from './relation-metadata.dto'; - @InputType() @BeforeCreateOne(BeforeCreateOneRelation) export class CreateRelationInput { @@ -51,6 +50,5 @@ export class CreateRelationInput { @Field({ nullable: true }) icon?: string; - @HideField() workspaceId: string; } diff --git a/server/src/metadata/relation-metadata/dtos/relation-metadata.dto.ts b/server/src/metadata/relation-metadata/dtos/relation-metadata.dto.ts deleted file mode 100644 index 9c8ffac66..000000000 --- a/server/src/metadata/relation-metadata/dtos/relation-metadata.dto.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { ObjectType, ID, Field, HideField } from '@nestjs/graphql'; - -import { CreateDateColumn, UpdateDateColumn } from 'typeorm'; -import { - Authorize, - IDField, - QueryOptions, - Relation, -} from '@ptc-org/nestjs-query-graphql'; - -import { ObjectMetadataDTO } from 'src/metadata/object-metadata/dtos/object-metadata.dto'; - -export enum RelationType { - ONE_TO_ONE = 'ONE_TO_ONE', - ONE_TO_MANY = 'ONE_TO_MANY', - MANY_TO_MANY = 'MANY_TO_MANY', -} - -@ObjectType('relation') -@Authorize({ - authorize: (context: any) => ({ - workspaceId: { eq: context?.req?.user?.workspace?.id }, - }), -}) -@QueryOptions({ - defaultResultSize: 10, - disableFilter: true, - disableSort: true, - maxResultsSize: 1000, -}) -@Relation('fromObjectMetadata', () => ObjectMetadataDTO) -@Relation('toObjectMetadata', () => ObjectMetadataDTO) -export class RelationMetadataDTO { - @IDField(() => ID) - id: string; - - @Field() - relationType: RelationType; - - @Field() - fromObjectMetadataId: string; - - @Field() - toObjectMetadataId: string; - - @Field() - fromFieldMetadataId: string; - - @Field() - toFieldMetadataId: string; - - @HideField() - workspaceId: string; - - @Field() - @CreateDateColumn() - createdAt: Date; - - @Field() - @UpdateDateColumn() - updatedAt: Date; -} diff --git a/server/src/metadata/relation-metadata/relation-metadata.auto-resolver-opts.ts b/server/src/metadata/relation-metadata/relation-metadata.auto-resolver-opts.ts new file mode 100644 index 000000000..c9e902321 --- /dev/null +++ b/server/src/metadata/relation-metadata/relation-metadata.auto-resolver-opts.ts @@ -0,0 +1,35 @@ +import { + AutoResolverOpts, + PagingStrategies, + ReadResolverOpts, +} from '@ptc-org/nestjs-query-graphql'; + +import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; + +import { RelationMetadata } from './relation-metadata.entity'; + +import { RelationMetadataService } from './services/relation-metadata.service'; +import { CreateRelationInput } from './dtos/create-relation.input'; + +export const relationMetadataAutoResolverOpts: AutoResolverOpts< + any, + any, + unknown, + unknown, + ReadResolverOpts, + PagingStrategies +>[] = [ + { + EntityClass: RelationMetadata, + DTOClass: RelationMetadata, + ServiceClass: RelationMetadataService, + CreateDTOClass: CreateRelationInput, + enableTotalCount: true, + pagingStrategy: PagingStrategies.CURSOR, + read: { many: { disabled: true } }, + create: { many: { disabled: true } }, + update: { disabled: true }, + delete: { disabled: true }, + guards: [JwtAuthGuard], + }, +]; diff --git a/server/src/metadata/relation-metadata/relation-metadata.entity.ts b/server/src/metadata/relation-metadata/relation-metadata.entity.ts new file mode 100644 index 000000000..7e7e66ee8 --- /dev/null +++ b/server/src/metadata/relation-metadata/relation-metadata.entity.ts @@ -0,0 +1,93 @@ +import { ObjectType, ID, Field } from '@nestjs/graphql'; + +import { + Column, + CreateDateColumn, + Entity, + JoinColumn, + ManyToOne, + OneToOne, + PrimaryGeneratedColumn, + UpdateDateColumn, +} from 'typeorm'; +import { + Authorize, + IDField, + QueryOptions, + Relation, +} from '@ptc-org/nestjs-query-graphql'; + +import { FieldMetadata } from 'src/metadata/field-metadata/field-metadata.entity'; +import { ObjectMetadata } from 'src/metadata/object-metadata/object-metadata.entity'; + +export enum RelationType { + ONE_TO_ONE = 'ONE_TO_ONE', + ONE_TO_MANY = 'ONE_TO_MANY', + MANY_TO_MANY = 'MANY_TO_MANY', +} + +@Entity('relationMetadata') +@ObjectType('relation') +@Authorize({ + authorize: (context: any) => ({ + workspaceId: { eq: context?.req?.user?.workspace?.id }, + }), +}) +@QueryOptions({ + defaultResultSize: 10, + disableFilter: true, + disableSort: true, + maxResultsSize: 1000, +}) +@Relation('fromObjectMetadata', () => ObjectMetadata) +@Relation('toObjectMetadata', () => ObjectMetadata) +export class RelationMetadata { + @IDField(() => ID) + @PrimaryGeneratedColumn('uuid') + id: string; + + @Field() + @Column({ nullable: false }) + relationType: RelationType; + + @Field() + @Column({ nullable: false, type: 'uuid' }) + fromObjectMetadataId: string; + + @Field() + @Column({ nullable: false, type: 'uuid' }) + toObjectMetadataId: string; + + @Field() + @Column({ nullable: false, type: 'uuid' }) + fromFieldMetadataId: string; + + @Field() + @Column({ nullable: false, type: 'uuid' }) + toFieldMetadataId: string; + + @Column({ nullable: false }) + workspaceId: string; + + @ManyToOne(() => ObjectMetadata, (object) => object.fromRelations) + fromObjectMetadata: ObjectMetadata; + + @ManyToOne(() => ObjectMetadata, (object) => object.toRelations) + toObjectMetadata: ObjectMetadata; + + @OneToOne(() => FieldMetadata, (field) => field.fromRelationMetadata) + @JoinColumn() + fromFieldMetadata: FieldMetadata; + + @OneToOne(() => FieldMetadata, (field) => field.toRelationMetadata) + @JoinColumn() + toFieldMetadata: FieldMetadata; + + @Field() + @CreateDateColumn() + createdAt: Date; + + @Field() + @UpdateDateColumn() + updatedAt: Date; +} diff --git a/server/src/metadata/relation-metadata/relation-metadata.module.ts b/server/src/metadata/relation-metadata/relation-metadata.module.ts index 1759eab71..1900be0ad 100644 --- a/server/src/metadata/relation-metadata/relation-metadata.module.ts +++ b/server/src/metadata/relation-metadata/relation-metadata.module.ts @@ -1,52 +1,30 @@ import { Module } from '@nestjs/common'; -import { - NestjsQueryGraphQLModule, - PagingStrategies, -} from '@ptc-org/nestjs-query-graphql'; +import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'; import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'; import { FieldMetadataModule } from 'src/metadata/field-metadata/field-metadata.module'; import { ObjectMetadataModule } from 'src/metadata/object-metadata/object-metadata.module'; -import { TenantMigrationRunnerModule } from 'src/tenant-migration-runner/tenant-migration-runner.module'; +import { MigrationRunnerModule } from 'src/metadata/migration-runner/migration-runner.module'; import { TenantMigrationModule } from 'src/metadata/tenant-migration/tenant-migration.module'; -import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -import { RelationMetadataEntity } from 'src/database/typeorm/metadata/entities/relation-metadata.entity'; -import { RelationMetadataService } from './relation-metadata.service'; +import { RelationMetadata } from './relation-metadata.entity'; +import { relationMetadataAutoResolverOpts } from './relation-metadata.auto-resolver-opts'; -import { CreateRelationInput } from './dtos/create-relation.input'; -import { RelationMetadataDTO } from './dtos/relation-metadata.dto'; +import { RelationMetadataService } from './services/relation-metadata.service'; @Module({ imports: [ NestjsQueryGraphQLModule.forFeature({ imports: [ - NestjsQueryTypeOrmModule.forFeature( - [RelationMetadataEntity], - 'metadata', - ), + NestjsQueryTypeOrmModule.forFeature([RelationMetadata], 'metadata'), ObjectMetadataModule, FieldMetadataModule, - TenantMigrationRunnerModule, + MigrationRunnerModule, TenantMigrationModule, ], services: [RelationMetadataService], - resolvers: [ - { - EntityClass: RelationMetadataEntity, - DTOClass: RelationMetadataDTO, - ServiceClass: RelationMetadataService, - CreateDTOClass: CreateRelationInput, - enableTotalCount: true, - pagingStrategy: PagingStrategies.CURSOR, - read: { many: { disabled: true } }, - create: { many: { disabled: true } }, - update: { disabled: true }, - delete: { disabled: true }, - guards: [JwtAuthGuard], - }, - ], + resolvers: relationMetadataAutoResolverOpts, }), ], providers: [RelationMetadataService], diff --git a/server/src/metadata/relation-metadata/relation-metadata.service.ts b/server/src/metadata/relation-metadata/services/relation-metadata.service.ts similarity index 84% rename from server/src/metadata/relation-metadata/relation-metadata.service.ts rename to server/src/metadata/relation-metadata/services/relation-metadata.service.ts index 53cfa19c1..ebe108537 100644 --- a/server/src/metadata/relation-metadata/relation-metadata.service.ts +++ b/server/src/metadata/relation-metadata/services/relation-metadata.service.ts @@ -8,34 +8,34 @@ import { InjectRepository } from '@nestjs/typeorm'; import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; import { Repository } from 'typeorm'; -import { ObjectMetadataService } from 'src/metadata/object-metadata/object-metadata.service'; -import { FieldMetadataService } from 'src/metadata/field-metadata/field-metadata.service'; -import { CreateRelationInput } from 'src/metadata/relation-metadata/dtos/create-relation.input'; -import { TenantMigrationRunnerService } from 'src/tenant-migration-runner/tenant-migration-runner.service'; -import { TenantMigrationService } from 'src/metadata/tenant-migration/tenant-migration.service'; import { - RelationMetadataEntity, + RelationMetadata, RelationType, -} from 'src/database/typeorm/metadata/entities/relation-metadata.entity'; -import { FieldMetadataType } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; -import { TenantMigrationColumnActionType } from 'src/database/typeorm/metadata/entities/tenant-migration.entity'; +} from 'src/metadata/relation-metadata/relation-metadata.entity'; +import { ObjectMetadataService } from 'src/metadata/object-metadata/services/object-metadata.service'; +import { FieldMetadataService } from 'src/metadata/field-metadata/services/field-metadata.service'; +import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; +import { CreateRelationInput } from 'src/metadata/relation-metadata/dtos/create-relation.input'; +import { MigrationRunnerService } from 'src/metadata/migration-runner/migration-runner.service'; +import { TenantMigrationService } from 'src/metadata/tenant-migration/tenant-migration.service'; +import { TenantMigrationColumnActionType } from 'src/metadata/tenant-migration/tenant-migration.entity'; @Injectable() -export class RelationMetadataService extends TypeOrmQueryService { +export class RelationMetadataService extends TypeOrmQueryService { constructor( - @InjectRepository(RelationMetadataEntity, 'metadata') - private readonly relationMetadataRepository: Repository, + @InjectRepository(RelationMetadata, 'metadata') + private readonly relationMetadataRepository: Repository, private readonly objectMetadataService: ObjectMetadataService, private readonly fieldMetadataService: FieldMetadataService, private readonly tenantMigrationService: TenantMigrationService, - private readonly migrationRunnerService: TenantMigrationRunnerService, + private readonly migrationRunnerService: MigrationRunnerService, ) { super(relationMetadataRepository); } override async createOne( record: CreateRelationInput, - ): Promise { + ): Promise { if (record.relationType === RelationType.MANY_TO_MANY) { throw new BadRequestException( 'Many to many relations are not supported yet', @@ -72,7 +72,7 @@ export class RelationMetadataService extends TypeOrmQueryService { - acc[curr.objectMetadataId] = curr; + acc[curr.objectId] = curr; return acc; }, {}); diff --git a/server/src/tenant-manager/standard-objects-metadata/companies/companies.metadata.ts b/server/src/metadata/standard-objects/companies/companies.metadata.ts similarity index 100% rename from server/src/tenant-manager/standard-objects-metadata/companies/companies.metadata.ts rename to server/src/metadata/standard-objects/companies/companies.metadata.ts diff --git a/server/src/tenant-manager/standard-objects-metadata/standard-object-metadata.ts b/server/src/metadata/standard-objects/standard-object-metadata.ts similarity index 100% rename from server/src/tenant-manager/standard-objects-metadata/standard-object-metadata.ts rename to server/src/metadata/standard-objects/standard-object-metadata.ts diff --git a/server/src/tenant-manager/standard-objects-metadata/view-fields/view-fields.metadata.ts b/server/src/metadata/standard-objects/view-fields/view-fields.metadata.ts similarity index 95% rename from server/src/tenant-manager/standard-objects-metadata/view-fields/view-fields.metadata.ts rename to server/src/metadata/standard-objects/view-fields/view-fields.metadata.ts index fecd270e4..0995fc24f 100644 --- a/server/src/tenant-manager/standard-objects-metadata/view-fields/view-fields.metadata.ts +++ b/server/src/metadata/standard-objects/view-fields/view-fields.metadata.ts @@ -9,10 +9,10 @@ const viewFieldsMetadata = { fields: [ { type: 'TEXT', - name: 'fieldMetadataId', + name: 'fieldId', label: 'Field Id', targetColumnMap: { - value: 'fieldMetadataId', + value: 'fieldId', }, description: 'View Field target field', icon: null, diff --git a/server/src/tenant-manager/standard-objects-metadata/view-filters/view-filters.metadata.ts b/server/src/metadata/standard-objects/view-filters/view-filters.metadata.ts similarity index 95% rename from server/src/tenant-manager/standard-objects-metadata/view-filters/view-filters.metadata.ts rename to server/src/metadata/standard-objects/view-filters/view-filters.metadata.ts index 8ee351c41..8fa165fd4 100644 --- a/server/src/tenant-manager/standard-objects-metadata/view-filters/view-filters.metadata.ts +++ b/server/src/metadata/standard-objects/view-filters/view-filters.metadata.ts @@ -9,10 +9,10 @@ const viewFiltersMetadata = { fields: [ { type: 'TEXT', - name: 'fieldMetadataId', + name: 'fieldId', label: 'Field Id', targetColumnMap: { - value: 'fieldMetadataId', + value: 'fieldId', }, description: 'View Filter target field', icon: null, diff --git a/server/src/tenant-manager/standard-objects-metadata/view-sorts/view-sorts.metadata.ts b/server/src/metadata/standard-objects/view-sorts/view-sorts.metadata.ts similarity index 93% rename from server/src/tenant-manager/standard-objects-metadata/view-sorts/view-sorts.metadata.ts rename to server/src/metadata/standard-objects/view-sorts/view-sorts.metadata.ts index 596a6b351..eb08b3921 100644 --- a/server/src/tenant-manager/standard-objects-metadata/view-sorts/view-sorts.metadata.ts +++ b/server/src/metadata/standard-objects/view-sorts/view-sorts.metadata.ts @@ -9,10 +9,10 @@ const viewSortsMetadata = { fields: [ { type: 'TEXT', - name: 'fieldMetadataId', + name: 'fieldId', label: 'Field Id', targetColumnMap: { - value: 'fieldMetadataId', + value: 'fieldId', }, description: 'View Sort target field', icon: null, diff --git a/server/src/tenant-manager/standard-objects-metadata/views/views.metadata.ts b/server/src/metadata/standard-objects/views/views.metadata.ts similarity index 92% rename from server/src/tenant-manager/standard-objects-metadata/views/views.metadata.ts rename to server/src/metadata/standard-objects/views/views.metadata.ts index c03d14816..82dd3ac6f 100644 --- a/server/src/tenant-manager/standard-objects-metadata/views/views.metadata.ts +++ b/server/src/metadata/standard-objects/views/views.metadata.ts @@ -20,10 +20,10 @@ const viewsMetadata = { }, { type: 'TEXT', - name: 'objectMetadataId', + name: 'objectId', label: 'Object Id', targetColumnMap: { - value: 'objectMetadataId', + value: 'objectId', }, description: 'View target object', icon: null, diff --git a/server/src/tenant-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts b/server/src/metadata/tenant-initialisation/standard-objects-prefill-data/standard-objects-prefill-data.ts similarity index 82% rename from server/src/tenant-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts rename to server/src/metadata/tenant-initialisation/standard-objects-prefill-data/standard-objects-prefill-data.ts index 2fcca6d85..10e292985 100644 --- a/server/src/tenant-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts +++ b/server/src/metadata/tenant-initialisation/standard-objects-prefill-data/standard-objects-prefill-data.ts @@ -58,27 +58,27 @@ export const standardObjectsPrefillData = async ( const createdViews = await entityManager .createQueryBuilder() .insert() - .into(`${schemaName}.view`, ['name', 'objectMetadataId', 'type']) + .into(`${schemaName}.view`, ['name', 'objectId', 'type']) .orIgnore() .values([ { name: 'All companies', - objectMetadataId: 'company', + objectId: 'company', type: 'table', }, { name: 'All people', - objectMetadataId: 'person', + objectId: 'person', type: 'table', }, { name: 'All opportunities', - objectMetadataId: 'company', + objectId: 'company', type: 'kanban', }, { name: 'All Companies (V2)', - objectMetadataId: companyIdMap['Airbnb'], + objectId: companyIdMap['Airbnb'], type: 'table', }, ]) @@ -94,7 +94,7 @@ export const standardObjectsPrefillData = async ( .createQueryBuilder() .insert() .into(`${schemaName}.viewField`, [ - 'fieldMetadataId', + 'fieldId', 'viewId', 'position', 'isVisible', @@ -103,161 +103,161 @@ export const standardObjectsPrefillData = async ( .orIgnore() .values([ { - fieldMetadataId: 'name', + fieldId: 'name', viewId: viewIdMap['All Companies (V2)'], position: 0, isVisible: true, size: 180, }, { - fieldMetadataId: 'name', + fieldId: 'name', viewId: viewIdMap['All companies'], position: 0, isVisible: true, size: 180, }, { - fieldMetadataId: 'domainName', + fieldId: 'domainName', viewId: viewIdMap['All companies'], position: 1, isVisible: true, size: 100, }, { - fieldMetadataId: 'accountOwner', + fieldId: 'accountOwner', viewId: viewIdMap['All companies'], position: 2, isVisible: true, size: 150, }, { - fieldMetadataId: 'createdAt', + fieldId: 'createdAt', viewId: viewIdMap['All companies'], position: 3, isVisible: true, size: 150, }, { - fieldMetadataId: 'employees', + fieldId: 'employees', viewId: viewIdMap['All companies'], position: 4, isVisible: true, size: 150, }, { - fieldMetadataId: 'linkedin', + fieldId: 'linkedin', viewId: viewIdMap['All companies'], position: 5, isVisible: true, size: 170, }, { - fieldMetadataId: 'address', + fieldId: 'address', viewId: viewIdMap['All companies'], position: 6, isVisible: true, size: 170, }, { - fieldMetadataId: 'displayName', + fieldId: 'displayName', viewId: viewIdMap['All people'], position: 0, isVisible: true, size: 210, }, { - fieldMetadataId: 'email', + fieldId: 'email', viewId: viewIdMap['All people'], position: 1, isVisible: true, size: 150, }, { - fieldMetadataId: 'company', + fieldId: 'company', viewId: viewIdMap['All people'], position: 2, isVisible: true, size: 150, }, { - fieldMetadataId: 'phone', + fieldId: 'phone', viewId: viewIdMap['All people'], position: 3, isVisible: true, size: 150, }, { - fieldMetadataId: 'createdAt', + fieldId: 'createdAt', viewId: viewIdMap['All people'], position: 4, isVisible: true, size: 150, }, { - fieldMetadataId: 'city', + fieldId: 'city', viewId: viewIdMap['All people'], position: 5, isVisible: true, size: 150, }, { - fieldMetadataId: 'jobTitle', + fieldId: 'jobTitle', viewId: viewIdMap['All people'], position: 6, isVisible: true, size: 150, }, { - fieldMetadataId: 'linkedin', + fieldId: 'linkedin', viewId: viewIdMap['All people'], position: 7, isVisible: true, size: 150, }, { - fieldMetadataId: 'x', + fieldId: 'x', viewId: viewIdMap['All people'], position: 8, isVisible: true, size: 150, }, { - fieldMetadataId: 'amount', + fieldId: 'amount', viewId: viewIdMap['All opportunities'], position: 0, isVisible: true, size: 180, }, { - fieldMetadataId: 'probability', + fieldId: 'probability', viewId: viewIdMap['All opportunities'], position: 1, isVisible: true, size: 150, }, { - fieldMetadataId: 'closeDate', + fieldId: 'closeDate', viewId: viewIdMap['All opportunities'], position: 2, isVisible: true, size: 100, }, { - fieldMetadataId: 'company', + fieldId: 'company', viewId: viewIdMap['All opportunities'], position: 3, isVisible: true, size: 150, }, { - fieldMetadataId: 'createdAt', + fieldId: 'createdAt', viewId: viewIdMap['All opportunities'], position: 4, isVisible: true, size: 150, }, { - fieldMetadataId: 'pointOfContact', + fieldId: 'pointOfContact', viewId: viewIdMap['All opportunities'], position: 5, isVisible: true, diff --git a/server/src/tenant-manager/tenant-manager.module.ts b/server/src/metadata/tenant-initialisation/tenant-initialisation.module.ts similarity index 56% rename from server/src/tenant-manager/tenant-manager.module.ts rename to server/src/metadata/tenant-initialisation/tenant-initialisation.module.ts index de6bc167f..07d8d0f73 100644 --- a/server/src/tenant-manager/tenant-manager.module.ts +++ b/server/src/metadata/tenant-initialisation/tenant-initialisation.module.ts @@ -1,24 +1,24 @@ import { Module } from '@nestjs/common'; -import { DataSourceMetadataModule } from 'src/metadata/data-source-metadata/data-source-metadata.module'; -import { FieldMetadataModule } from 'src/metadata/field-metadata/field-metadata.module'; -import { ObjectMetadataModule } from 'src/metadata/object-metadata/object-metadata.module'; +import { DataSourceModule } from 'src/metadata/data-source/data-source.module'; +import { MigrationRunnerModule } from 'src/metadata/migration-runner/migration-runner.module'; import { TenantMigrationModule } from 'src/metadata/tenant-migration/tenant-migration.module'; -import { TenantDataSourceModule } from 'src/tenant-datasource/tenant-datasource.module'; -import { TenantMigrationRunnerModule } from 'src/tenant-migration-runner/tenant-migration-runner.module'; +import { DataSourceMetadataModule } from 'src/metadata/data-source-metadata/data-source-metadata.module'; +import { ObjectMetadataModule } from 'src/metadata/object-metadata/object-metadata.module'; +import { FieldMetadataModule } from 'src/metadata/field-metadata/field-metadata.module'; -import { TenantManagerService } from './tenant-manager.service'; +import { TenantInitialisationService } from './tenant-initialisation.service'; @Module({ imports: [ - TenantDataSourceModule, + DataSourceModule, TenantMigrationModule, - TenantMigrationRunnerModule, + MigrationRunnerModule, ObjectMetadataModule, FieldMetadataModule, DataSourceMetadataModule, ], - exports: [TenantManagerService], - providers: [TenantManagerService], + exports: [TenantInitialisationService], + providers: [TenantInitialisationService], }) -export class TenantManagerModule {} +export class TenantInitialisationModule {} diff --git a/server/src/metadata/tenant-initialisation/tenant-initialisation.service.ts b/server/src/metadata/tenant-initialisation/tenant-initialisation.service.ts new file mode 100644 index 000000000..31154e52b --- /dev/null +++ b/server/src/metadata/tenant-initialisation/tenant-initialisation.service.ts @@ -0,0 +1,90 @@ +import { Injectable } from '@nestjs/common'; + +import { TenantMigrationService } from 'src/metadata/tenant-migration/tenant-migration.service'; +import { MigrationRunnerService } from 'src/metadata/migration-runner/migration-runner.service'; +import { DataSourceService } from 'src/metadata/data-source/data-source.service'; +import { DataSourceMetadataService } from 'src/metadata/data-source-metadata/data-source-metadata.service'; +import { ObjectMetadataService } from 'src/metadata/object-metadata/services/object-metadata.service'; +import { DataSourceMetadata } from 'src/metadata/data-source-metadata/data-source-metadata.entity'; +import { FieldMetadataService } from 'src/metadata/field-metadata/services/field-metadata.service'; + +import { standardObjectsPrefillData } from './standard-objects-prefill-data/standard-objects-prefill-data'; + +@Injectable() +export class TenantInitialisationService { + constructor( + private readonly dataSourceService: DataSourceService, + private readonly tenantMigrationService: TenantMigrationService, + private readonly migrationRunnerService: MigrationRunnerService, + private readonly objectMetadataService: ObjectMetadataService, + private readonly fieldMetadataService: FieldMetadataService, + private readonly dataSourceMetadataService: DataSourceMetadataService, + ) {} + + /** + * Init a workspace by creating a new data source and running all migrations + * @param workspaceId + * @returns Promise + */ + public async init(workspaceId: string): Promise { + const schemaName = await this.dataSourceService.createWorkspaceSchema( + workspaceId, + ); + + const dataSourceMetadata = + await this.dataSourceMetadataService.createDataSourceMetadata( + workspaceId, + schemaName, + ); + + await this.tenantMigrationService.insertStandardMigrations(workspaceId); + + // Todo: keep in mind that we don't handle concurrency issues such as migrations being created at the same time + // but it shouldn't be the role of this service to handle this kind of issues for now. + // To check later when we run this in a job. + await this.migrationRunnerService.executeMigrationFromPendingMigrations( + workspaceId, + ); + + await this.objectMetadataService.createStandardObjectsAndFieldsMetadata( + dataSourceMetadata.id, + workspaceId, + ); + + await this.prefillWorkspaceWithStandardObjects( + dataSourceMetadata, + workspaceId, + ); + } + + /** + * + * We are prefilling a few standard objects with data to make it easier for the user to get started. + * + * @param dataSourceMetadata + * @param workspaceId + */ + private async prefillWorkspaceWithStandardObjects( + dataSourceMetadata: DataSourceMetadata, + workspaceId: string, + ) { + const workspaceDataSource = + await this.dataSourceService.connectToWorkspaceDataSource(workspaceId); + + if (!workspaceDataSource) { + throw new Error('Could not connect to workspace data source'); + } + + standardObjectsPrefillData(workspaceDataSource, dataSourceMetadata.schema); + } + + public async delete(workspaceId: string): Promise { + // Delete data from metadata tables + await this.fieldMetadataService.deleteFieldsMetadata(workspaceId); + await this.objectMetadataService.deleteObjectsMetadata(workspaceId); + await this.tenantMigrationService.delete(workspaceId); + await this.dataSourceMetadataService.delete(workspaceId); + // Delete schema + await this.dataSourceService.deleteWorkspaceSchema(workspaceId); + } +} diff --git a/server/src/metadata/tenant-migration/migrations/1697618009-addCompanyTable.ts b/server/src/metadata/tenant-migration/migrations/1697618009-addCompanyTable.ts index 34af4615f..4039d58dc 100644 --- a/server/src/metadata/tenant-migration/migrations/1697618009-addCompanyTable.ts +++ b/server/src/metadata/tenant-migration/migrations/1697618009-addCompanyTable.ts @@ -1,7 +1,7 @@ import { - TenantMigrationTableAction, TenantMigrationColumnActionType, -} from 'src/database/typeorm/metadata/entities/tenant-migration.entity'; + TenantMigrationTableAction, +} from 'src/metadata/tenant-migration/tenant-migration.entity'; export const addCompanyTable: TenantMigrationTableAction[] = [ { diff --git a/server/src/metadata/tenant-migration/migrations/1697618011-addViewTable.ts b/server/src/metadata/tenant-migration/migrations/1697618011-addViewTable.ts index 406b21882..60570a89f 100644 --- a/server/src/metadata/tenant-migration/migrations/1697618011-addViewTable.ts +++ b/server/src/metadata/tenant-migration/migrations/1697618011-addViewTable.ts @@ -1,7 +1,7 @@ import { - TenantMigrationTableAction, TenantMigrationColumnActionType, -} from 'src/database/typeorm/metadata/entities/tenant-migration.entity'; + TenantMigrationTableAction, +} from 'src/metadata/tenant-migration/tenant-migration.entity'; export const addViewTable: TenantMigrationTableAction[] = [ { @@ -18,7 +18,7 @@ export const addViewTable: TenantMigrationTableAction[] = [ action: TenantMigrationColumnActionType.CREATE, }, { - columnName: 'objectMetadataId', + columnName: 'objectId', columnType: 'varchar', action: TenantMigrationColumnActionType.CREATE, }, diff --git a/server/src/metadata/tenant-migration/migrations/1697618012-addViewFieldTable.ts b/server/src/metadata/tenant-migration/migrations/1697618012-addViewFieldTable.ts index 1e0f311c0..b479d929d 100644 --- a/server/src/metadata/tenant-migration/migrations/1697618012-addViewFieldTable.ts +++ b/server/src/metadata/tenant-migration/migrations/1697618012-addViewFieldTable.ts @@ -1,7 +1,7 @@ import { - TenantMigrationTableAction, TenantMigrationColumnActionType, -} from 'src/database/typeorm/metadata/entities/tenant-migration.entity'; + TenantMigrationTableAction, +} from 'src/metadata/tenant-migration/tenant-migration.entity'; export const addViewFieldTable: TenantMigrationTableAction[] = [ { @@ -13,7 +13,7 @@ export const addViewFieldTable: TenantMigrationTableAction[] = [ action: 'alter', columns: [ { - columnName: 'fieldMetadataId', + columnName: 'fieldId', columnType: 'varchar', action: TenantMigrationColumnActionType.CREATE, }, diff --git a/server/src/metadata/tenant-migration/migrations/1697618013-addViewFilterTable.ts b/server/src/metadata/tenant-migration/migrations/1697618013-addViewFilterTable.ts index 2e1d1d394..7ff19c319 100644 --- a/server/src/metadata/tenant-migration/migrations/1697618013-addViewFilterTable.ts +++ b/server/src/metadata/tenant-migration/migrations/1697618013-addViewFilterTable.ts @@ -1,7 +1,7 @@ import { - TenantMigrationTableAction, TenantMigrationColumnActionType, -} from 'src/database/typeorm/metadata/entities/tenant-migration.entity'; + TenantMigrationTableAction, +} from 'src/metadata/tenant-migration/tenant-migration.entity'; export const addViewFilterTable: TenantMigrationTableAction[] = [ { @@ -13,7 +13,7 @@ export const addViewFilterTable: TenantMigrationTableAction[] = [ action: 'alter', columns: [ { - columnName: 'fieldMetadataId', + columnName: 'fieldId', columnType: 'varchar', action: TenantMigrationColumnActionType.CREATE, }, diff --git a/server/src/metadata/tenant-migration/migrations/1697618014-addViewSortTable.ts b/server/src/metadata/tenant-migration/migrations/1697618014-addViewSortTable.ts index 9bd7be210..1bb4307c9 100644 --- a/server/src/metadata/tenant-migration/migrations/1697618014-addViewSortTable.ts +++ b/server/src/metadata/tenant-migration/migrations/1697618014-addViewSortTable.ts @@ -1,7 +1,7 @@ import { - TenantMigrationTableAction, TenantMigrationColumnActionType, -} from 'src/database/typeorm/metadata/entities/tenant-migration.entity'; + TenantMigrationTableAction, +} from 'src/metadata/tenant-migration/tenant-migration.entity'; export const addViewSortTable: TenantMigrationTableAction[] = [ { @@ -13,7 +13,7 @@ export const addViewSortTable: TenantMigrationTableAction[] = [ action: 'alter', columns: [ { - columnName: 'fieldMetadataId', + columnName: 'fieldId', columnType: 'varchar', action: TenantMigrationColumnActionType.CREATE, }, diff --git a/server/src/database/typeorm/metadata/entities/tenant-migration.entity.ts b/server/src/metadata/tenant-migration/tenant-migration.entity.ts similarity index 94% rename from server/src/database/typeorm/metadata/entities/tenant-migration.entity.ts rename to server/src/metadata/tenant-migration/tenant-migration.entity.ts index 110ba58bb..de10716d3 100644 --- a/server/src/database/typeorm/metadata/entities/tenant-migration.entity.ts +++ b/server/src/metadata/tenant-migration/tenant-migration.entity.ts @@ -32,8 +32,8 @@ export type TenantMigrationTableAction = { action: 'create' | 'alter'; columns?: TenantMigrationColumnAction[]; }; -@Entity('tenantMigration') -export class TenantMigrationEntity { +@Entity('tenant_migrations') +export class TenantMigration { @PrimaryGeneratedColumn('uuid') id: string; diff --git a/server/src/metadata/tenant-migration/tenant-migration.module.ts b/server/src/metadata/tenant-migration/tenant-migration.module.ts index 758bcfeaf..4bd73b39a 100644 --- a/server/src/metadata/tenant-migration/tenant-migration.module.ts +++ b/server/src/metadata/tenant-migration/tenant-migration.module.ts @@ -1,12 +1,11 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { TenantMigrationEntity } from 'src/database/typeorm/metadata/entities/tenant-migration.entity'; - import { TenantMigrationService } from './tenant-migration.service'; +import { TenantMigration } from './tenant-migration.entity'; @Module({ - imports: [TypeOrmModule.forFeature([TenantMigrationEntity], 'metadata')], + imports: [TypeOrmModule.forFeature([TenantMigration], 'metadata')], exports: [TenantMigrationService], providers: [TenantMigrationService], }) diff --git a/server/src/metadata/tenant-migration/tenant-migration.service.spec.ts b/server/src/metadata/tenant-migration/tenant-migration.service.spec.ts new file mode 100644 index 000000000..371fbdbad --- /dev/null +++ b/server/src/metadata/tenant-migration/tenant-migration.service.spec.ts @@ -0,0 +1,27 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { getRepositoryToken } from '@nestjs/typeorm'; + +import { TenantMigrationService } from './tenant-migration.service'; +import { TenantMigration } from './tenant-migration.entity'; + +describe('TenantMigrationService', () => { + let service: TenantMigrationService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + TenantMigrationService, + { + provide: getRepositoryToken(TenantMigration, 'metadata'), + useValue: {}, + }, + ], + }).compile(); + + service = module.get(TenantMigrationService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/server/src/metadata/tenant-migration/tenant-migration.service.ts b/server/src/metadata/tenant-migration/tenant-migration.service.ts index 9e252cec9..aa8af710a 100644 --- a/server/src/metadata/tenant-migration/tenant-migration.service.ts +++ b/server/src/metadata/tenant-migration/tenant-migration.service.ts @@ -4,17 +4,16 @@ import { InjectRepository } from '@nestjs/typeorm'; import { IsNull, Repository } from 'typeorm'; import { - TenantMigrationEntity, + TenantMigration, TenantMigrationTableAction, -} from 'src/database/typeorm/metadata/entities/tenant-migration.entity'; - +} from './tenant-migration.entity'; import { standardMigrations } from './standard-migrations'; @Injectable() export class TenantMigrationService { constructor( - @InjectRepository(TenantMigrationEntity, 'metadata') - private readonly tenantMigrationRepository: Repository, + @InjectRepository(TenantMigration, 'metadata') + private readonly tenantMigrationRepository: Repository, ) {} /** @@ -61,7 +60,7 @@ export class TenantMigrationService { */ public async getPendingMigrations( workspaceId: string, - ): Promise { + ): Promise { return await this.tenantMigrationRepository.find({ order: { createdAt: 'ASC' }, where: { @@ -80,7 +79,7 @@ export class TenantMigrationService { */ public async setAppliedAtForMigration( workspaceId: string, - migration: TenantMigrationEntity, + migration: TenantMigration, ) { await this.tenantMigrationRepository.save({ id: migration.id, diff --git a/server/src/tenant-datasource/tenant-datasource.module.ts b/server/src/tenant-datasource/tenant-datasource.module.ts deleted file mode 100644 index 514f3d5d5..000000000 --- a/server/src/tenant-datasource/tenant-datasource.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; -import { DataSourceMetadataModule } from 'src/metadata/data-source-metadata/data-source-metadata.module'; - -import { TenantDataSourceService } from './tenant-datasource.service'; - -@Module({ - imports: [DataSourceMetadataModule, TypeORMModule], - exports: [TenantDataSourceService], - providers: [TenantDataSourceService], -}) -export class TenantDataSourceModule {} diff --git a/server/src/tenant-datasource/tenant-datasource.service.ts b/server/src/tenant-datasource/tenant-datasource.service.ts deleted file mode 100644 index 4e2428d7c..000000000 --- a/server/src/tenant-datasource/tenant-datasource.service.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { DataSource } from 'typeorm'; - -import { DataSourceMetadataService } from 'src/metadata/data-source-metadata/data-source-metadata.service'; -import { TypeORMService } from 'src/database/typeorm/typeorm.service'; - -@Injectable() -export class TenantDataSourceService { - constructor( - private readonly dataSourceMetadataService: DataSourceMetadataService, - private readonly typeormService: TypeORMService, - ) {} - - /** - * - * Connect to the workspace data source - * - * @param workspaceId - * @returns - */ - public async connectToWorkspaceDataSource( - workspaceId: string, - ): Promise { - const dataSourceMetadata = - await this.dataSourceMetadataService.getLastDataSourceMetadataFromWorkspaceIdOrFail( - workspaceId, - ); - - const dataSource = await this.typeormService.connectToDataSource( - dataSourceMetadata, - ); - - if (!dataSource) { - throw new Error( - `Could not connect to workspace data source for workspace ${workspaceId}`, - ); - } - - return dataSource; - } - - /** - * - * Create a new DB schema for a workspace - * - * @param workspaceId - * @returns - */ - public async createWorkspaceDBSchema(workspaceId: string): Promise { - const schemaName = this.getSchemaName(workspaceId); - - return await this.typeormService.createSchema(schemaName); - } - - /** - * - * Delete a DB schema for a workspace - * - * @param workspaceId - * @returns - */ - public async deleteWorkspaceDBSchema(workspaceId: string): Promise { - const schemaName = this.getSchemaName(workspaceId); - - return await this.typeormService.deleteSchema(schemaName); - } - - /** - * - * Get the schema name for a workspace - * - * @param workspaceId - * @returns string - */ - public getSchemaName(workspaceId: string): string { - return `workspace_${this.uuidToBase36(workspaceId)}`; - } - - /** - * - * Convert a uuid to base36 - * - * @param uuid - * @returns string - */ - private uuidToBase36(uuid: string): string { - let devId = false; - - if (uuid.startsWith('twenty-')) { - devId = true; - // Clean dev uuids (twenty-) - uuid = uuid.replace('twenty-', ''); - } - const hexString = uuid.replace(/-/g, ''); - const base10Number = BigInt('0x' + hexString); - const base36String = base10Number.toString(36); - - return `${devId ? 'twenty_' : ''}${base36String}`; - } -} diff --git a/server/src/tenant-manager/commands/tenant-manager-commands.module.ts b/server/src/tenant-manager/commands/tenant-manager-commands.module.ts deleted file mode 100644 index fed8cd2ac..000000000 --- a/server/src/tenant-manager/commands/tenant-manager-commands.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { TenantManagerModule } from 'src/tenant-manager/tenant-manager.module'; -import { DataSourceMetadataModule } from 'src/metadata/data-source-metadata/data-source-metadata.module'; - -import { SyncTenantMetadataCommand } from './sync-tenant-metadata.command'; - -@Module({ - imports: [TenantManagerModule, DataSourceMetadataModule], - providers: [SyncTenantMetadataCommand], -}) -export class TenantManagerCommandsModule {} diff --git a/server/src/tenant-manager/tenant-manager.service.ts b/server/src/tenant-manager/tenant-manager.service.ts deleted file mode 100644 index ea5732f83..000000000 --- a/server/src/tenant-manager/tenant-manager.service.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { DataSourceEntity } from 'src/database/typeorm/metadata/entities/data-source.entity'; -import { DataSourceMetadataService } from 'src/metadata/data-source-metadata/data-source-metadata.service'; -import { FieldMetadataService } from 'src/metadata/field-metadata/field-metadata.service'; -import { ObjectMetadataService } from 'src/metadata/object-metadata/object-metadata.service'; -import { TenantMigrationRunnerService } from 'src/tenant-migration-runner/tenant-migration-runner.service'; -import { TenantMigrationService } from 'src/metadata/tenant-migration/tenant-migration.service'; -import { standardObjectsPrefillData } from 'src/tenant-manager/standard-objects-prefill-data/standard-objects-prefill-data'; -import { TenantDataSourceService } from 'src/tenant-datasource/tenant-datasource.service'; -import { standardObjectsMetadata } from 'src/tenant-manager/standard-objects-metadata/standard-object-metadata'; - -@Injectable() -export class TenantManagerService { - constructor( - private readonly tenantDataSourceService: TenantDataSourceService, - private readonly tenantMigrationService: TenantMigrationService, - private readonly migrationRunnerService: TenantMigrationRunnerService, - private readonly objectMetadataService: ObjectMetadataService, - private readonly fieldMetadataService: FieldMetadataService, - private readonly dataSourceMetadataService: DataSourceMetadataService, - ) {} - - /** - * Init a workspace by creating a new data source and running all migrations - * @param workspaceId - * @returns Promise - */ - public async init(workspaceId: string): Promise { - const schemaName = - await this.tenantDataSourceService.createWorkspaceDBSchema(workspaceId); - - const dataSourceMetadata = - await this.dataSourceMetadataService.createDataSourceMetadata( - workspaceId, - schemaName, - ); - - await this.tenantMigrationService.insertStandardMigrations(workspaceId); - - await this.migrationRunnerService.executeMigrationFromPendingMigrations( - workspaceId, - ); - - await this.createStandardObjectsAndFieldsMetadata( - dataSourceMetadata.id, - workspaceId, - ); - - await this.prefillWorkspaceWithStandardObjects( - dataSourceMetadata, - workspaceId, - ); - } - - /** - * - * Create all standard objects and fields metadata for a given workspace - * - * @param dataSourceId - * @param workspaceId - */ - public async createStandardObjectsAndFieldsMetadata( - dataSourceId: string, - workspaceId: string, - ) { - await this.objectMetadataService.createMany( - Object.values(standardObjectsMetadata).map((objectMetadata) => ({ - ...objectMetadata, - dataSourceId, - workspaceId, - isCustom: false, - isActive: true, - fields: objectMetadata.fields.map((field) => ({ - ...field, - workspaceId, - isCustom: false, - isActive: true, - })), - })), - ); - } - - /** - * - * Reset all standard objects and fields metadata for a given workspace - * - * @param dataSourceId - * @param workspaceId - */ - public async resetStandardObjectsAndFieldsMetadata( - dataSourceId: string, - workspaceId: string, - ) { - await this.objectMetadataService.deleteMany({ - workspaceId: { eq: workspaceId }, - }); - - await this.createStandardObjectsAndFieldsMetadata( - dataSourceId, - workspaceId, - ); - } - - /** - * - * We are prefilling a few standard objects with data to make it easier for the user to get started. - * - * @param dataSourceMetadata - * @param workspaceId - */ - private async prefillWorkspaceWithStandardObjects( - dataSourceMetadata: DataSourceEntity, - workspaceId: string, - ) { - const workspaceDataSource = - await this.tenantDataSourceService.connectToWorkspaceDataSource( - workspaceId, - ); - - if (!workspaceDataSource) { - throw new Error('Could not connect to workspace data source'); - } - - standardObjectsPrefillData(workspaceDataSource, dataSourceMetadata.schema); - } - - /** - * - * Delete a workspace by deleting all metadata and the schema - * - * @param workspaceId - */ - public async delete(workspaceId: string): Promise { - // Delete data from metadata tables - await this.fieldMetadataService.deleteFieldsMetadata(workspaceId); - await this.objectMetadataService.deleteObjectsMetadata(workspaceId); - await this.tenantMigrationService.delete(workspaceId); - await this.dataSourceMetadataService.delete(workspaceId); - // Delete schema - await this.tenantDataSourceService.deleteWorkspaceDBSchema(workspaceId); - } -} diff --git a/server/src/tenant-migration-runner/commands/tenant-migration-runner-commands.module.ts b/server/src/tenant-migration-runner/commands/tenant-migration-runner-commands.module.ts deleted file mode 100644 index dff01df6d..000000000 --- a/server/src/tenant-migration-runner/commands/tenant-migration-runner-commands.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { TenantMigrationModule } from 'src/metadata/tenant-migration/tenant-migration.module'; -import { TenantMigrationRunnerModule } from 'src/tenant-migration-runner/tenant-migration-runner.module'; - -import { RunTenantMigrationsCommand } from './run-tenant-migrations.command'; - -@Module({ - imports: [TenantMigrationModule, TenantMigrationRunnerModule], - providers: [RunTenantMigrationsCommand], -}) -export class TenantMigrationRunnerCommandsModule {} diff --git a/server/src/tenant-migration-runner/tenant-migration-runner.module.ts b/server/src/tenant-migration-runner/tenant-migration-runner.module.ts deleted file mode 100644 index a96340cf3..000000000 --- a/server/src/tenant-migration-runner/tenant-migration-runner.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { TenantMigrationModule } from 'src/metadata/tenant-migration/tenant-migration.module'; -import { TenantDataSourceModule } from 'src/tenant-datasource/tenant-datasource.module'; - -import { TenantMigrationRunnerService } from './tenant-migration-runner.service'; - -@Module({ - imports: [TenantDataSourceModule, TenantMigrationModule], - exports: [TenantMigrationRunnerService], - providers: [TenantMigrationRunnerService], -}) -export class TenantMigrationRunnerModule {} diff --git a/server/src/tenant/resolver-builder/factories/create-many-resolver.factory.ts b/server/src/tenant/resolver-builder/factories/create-many-resolver.factory.ts index cda2dc788..78a432270 100644 --- a/server/src/tenant/resolver-builder/factories/create-many-resolver.factory.ts +++ b/server/src/tenant/resolver-builder/factories/create-many-resolver.factory.ts @@ -7,8 +7,8 @@ import { import { SchemaBuilderContext } from 'src/tenant/schema-builder/interfaces/schema-builder-context.interface'; import { ResolverBuilderFactoryInterface } from 'src/tenant/resolver-builder/interfaces/resolver-builder-factory.interface'; +import { DataSourceService } from 'src/metadata/data-source/data-source.service'; import { PGGraphQLQueryRunner } from 'src/tenant/resolver-builder/pg-graphql/pg-graphql-query-runner'; -import { TenantDataSourceService } from 'src/tenant-datasource/tenant-datasource.service'; @Injectable() export class CreateManyResolverFactory @@ -16,15 +16,13 @@ export class CreateManyResolverFactory { public static methodName = 'createMany' as const; - constructor( - private readonly tenantDataSourceService: TenantDataSourceService, - ) {} + constructor(private readonly dataSourceService: DataSourceService) {} create(context: SchemaBuilderContext): Resolver { const internalContext = context; return (_source, args, context, info) => { - const runner = new PGGraphQLQueryRunner(this.tenantDataSourceService, { + const runner = new PGGraphQLQueryRunner(this.dataSourceService, { targetTableName: internalContext.targetTableName, workspaceId: internalContext.workspaceId, info, diff --git a/server/src/tenant/resolver-builder/factories/create-one-resolver.factory.ts b/server/src/tenant/resolver-builder/factories/create-one-resolver.factory.ts index 2d35ecbc0..c599682fb 100644 --- a/server/src/tenant/resolver-builder/factories/create-one-resolver.factory.ts +++ b/server/src/tenant/resolver-builder/factories/create-one-resolver.factory.ts @@ -7,9 +7,9 @@ import { import { SchemaBuilderContext } from 'src/tenant/schema-builder/interfaces/schema-builder-context.interface'; import { ResolverBuilderFactoryInterface } from 'src/tenant/resolver-builder/interfaces/resolver-builder-factory.interface'; +import { DataSourceService } from 'src/metadata/data-source/data-source.service'; import { PGGraphQLQueryRunner } from 'src/tenant/resolver-builder/pg-graphql/pg-graphql-query-runner'; -import { FieldMetadataEntity } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; -import { TenantDataSourceService } from 'src/tenant-datasource/tenant-datasource.service'; +import { FieldMetadata } from 'src/metadata/field-metadata/field-metadata.entity'; @Injectable() export class CreateOneResolverFactory @@ -17,20 +17,18 @@ export class CreateOneResolverFactory { public static methodName = 'createOne' as const; - constructor( - private readonly tenantDataSourceService: TenantDataSourceService, - ) {} + constructor(private readonly dataSourceService: DataSourceService) {} create(context: SchemaBuilderContext): Resolver { const internalContext = context; return (_source, args, context, info) => { - const runner = new PGGraphQLQueryRunner(this.tenantDataSourceService, { + const runner = new PGGraphQLQueryRunner(this.dataSourceService, { targetTableName: internalContext.targetTableName, workspaceId: internalContext.workspaceId, info, fieldMetadataCollection: - internalContext.fieldMetadataCollection as FieldMetadataEntity[], + internalContext.fieldMetadataCollection as FieldMetadata[], }); return runner.createOne(args); diff --git a/server/src/tenant/resolver-builder/factories/delete-one-resolver.factory.ts b/server/src/tenant/resolver-builder/factories/delete-one-resolver.factory.ts index 08ddf7171..4bd2f00cf 100644 --- a/server/src/tenant/resolver-builder/factories/delete-one-resolver.factory.ts +++ b/server/src/tenant/resolver-builder/factories/delete-one-resolver.factory.ts @@ -7,9 +7,9 @@ import { import { SchemaBuilderContext } from 'src/tenant/schema-builder/interfaces/schema-builder-context.interface'; import { ResolverBuilderFactoryInterface } from 'src/tenant/resolver-builder/interfaces/resolver-builder-factory.interface'; +import { DataSourceService } from 'src/metadata/data-source/data-source.service'; import { PGGraphQLQueryRunner } from 'src/tenant/resolver-builder/pg-graphql/pg-graphql-query-runner'; -import { FieldMetadataEntity } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; -import { TenantDataSourceService } from 'src/tenant-datasource/tenant-datasource.service'; +import { FieldMetadata } from 'src/metadata/field-metadata/field-metadata.entity'; @Injectable() export class DeleteOneResolverFactory @@ -17,20 +17,18 @@ export class DeleteOneResolverFactory { public static methodName = 'deleteOne' as const; - constructor( - private readonly tenantDataSourceService: TenantDataSourceService, - ) {} + constructor(private readonly dataSourceService: DataSourceService) {} create(context: SchemaBuilderContext): Resolver { const internalContext = context; return (_source, args, context, info) => { - const runner = new PGGraphQLQueryRunner(this.tenantDataSourceService, { + const runner = new PGGraphQLQueryRunner(this.dataSourceService, { targetTableName: internalContext.targetTableName, workspaceId: internalContext.workspaceId, info, fieldMetadataCollection: - internalContext.fieldMetadataCollection as FieldMetadataEntity[], + internalContext.fieldMetadataCollection as FieldMetadata[], }); return runner.deleteOne(args); diff --git a/server/src/tenant/resolver-builder/factories/find-many-resolver.factory.ts b/server/src/tenant/resolver-builder/factories/find-many-resolver.factory.ts index 765441a38..450c8ae4b 100644 --- a/server/src/tenant/resolver-builder/factories/find-many-resolver.factory.ts +++ b/server/src/tenant/resolver-builder/factories/find-many-resolver.factory.ts @@ -7,8 +7,8 @@ import { import { SchemaBuilderContext } from 'src/tenant/schema-builder/interfaces/schema-builder-context.interface'; import { ResolverBuilderFactoryInterface } from 'src/tenant/resolver-builder/interfaces/resolver-builder-factory.interface'; +import { DataSourceService } from 'src/metadata/data-source/data-source.service'; import { PGGraphQLQueryRunner } from 'src/tenant/resolver-builder/pg-graphql/pg-graphql-query-runner'; -import { TenantDataSourceService } from 'src/tenant-datasource/tenant-datasource.service'; @Injectable() export class FindManyResolverFactory @@ -16,15 +16,13 @@ export class FindManyResolverFactory { public static methodName = 'findMany' as const; - constructor( - private readonly tenantDataSourceService: TenantDataSourceService, - ) {} + constructor(private readonly dataSourceService: DataSourceService) {} create(context: SchemaBuilderContext): Resolver { const internalContext = context; return (_source, args, context, info) => { - const runner = new PGGraphQLQueryRunner(this.tenantDataSourceService, { + const runner = new PGGraphQLQueryRunner(this.dataSourceService, { targetTableName: internalContext.targetTableName, workspaceId: internalContext.workspaceId, info, diff --git a/server/src/tenant/resolver-builder/factories/find-one-resolver.factory.ts b/server/src/tenant/resolver-builder/factories/find-one-resolver.factory.ts index f98669abb..806fac3ec 100644 --- a/server/src/tenant/resolver-builder/factories/find-one-resolver.factory.ts +++ b/server/src/tenant/resolver-builder/factories/find-one-resolver.factory.ts @@ -7,28 +7,26 @@ import { import { SchemaBuilderContext } from 'src/tenant/schema-builder/interfaces/schema-builder-context.interface'; import { ResolverBuilderFactoryInterface } from 'src/tenant/resolver-builder/interfaces/resolver-builder-factory.interface'; +import { DataSourceService } from 'src/metadata/data-source/data-source.service'; import { PGGraphQLQueryRunner } from 'src/tenant/resolver-builder/pg-graphql/pg-graphql-query-runner'; -import { FieldMetadataEntity } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; -import { TenantDataSourceService } from 'src/tenant-datasource/tenant-datasource.service'; +import { FieldMetadata } from 'src/metadata/field-metadata/field-metadata.entity'; @Injectable() export class FindOneResolverFactory implements ResolverBuilderFactoryInterface { public static methodName = 'findOne' as const; - constructor( - private readonly tenantDataSourceService: TenantDataSourceService, - ) {} + constructor(private readonly dataSourceService: DataSourceService) {} create(context: SchemaBuilderContext): Resolver { const internalContext = context; return (_source, args, context, info) => { - const runner = new PGGraphQLQueryRunner(this.tenantDataSourceService, { + const runner = new PGGraphQLQueryRunner(this.dataSourceService, { targetTableName: internalContext.targetTableName, workspaceId: internalContext.workspaceId, info, fieldMetadataCollection: - internalContext.fieldMetadataCollection as FieldMetadataEntity[], + internalContext.fieldMetadataCollection as FieldMetadata[], }); return runner.findOne(args); diff --git a/server/src/tenant/resolver-builder/factories/update-one-resolver.factory.ts b/server/src/tenant/resolver-builder/factories/update-one-resolver.factory.ts index fa91a13d1..837468129 100644 --- a/server/src/tenant/resolver-builder/factories/update-one-resolver.factory.ts +++ b/server/src/tenant/resolver-builder/factories/update-one-resolver.factory.ts @@ -7,9 +7,9 @@ import { import { SchemaBuilderContext } from 'src/tenant/schema-builder/interfaces/schema-builder-context.interface'; import { ResolverBuilderFactoryInterface } from 'src/tenant/resolver-builder/interfaces/resolver-builder-factory.interface'; +import { DataSourceService } from 'src/metadata/data-source/data-source.service'; import { PGGraphQLQueryRunner } from 'src/tenant/resolver-builder/pg-graphql/pg-graphql-query-runner'; -import { FieldMetadataEntity } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; -import { TenantDataSourceService } from 'src/tenant-datasource/tenant-datasource.service'; +import { FieldMetadata } from 'src/metadata/field-metadata/field-metadata.entity'; @Injectable() export class UpdateOneResolverFactory @@ -17,20 +17,18 @@ export class UpdateOneResolverFactory { public static methodName = 'updateOne' as const; - constructor( - private readonly tenantDataSourceService: TenantDataSourceService, - ) {} + constructor(private readonly dataSourceService: DataSourceService) {} create(context: SchemaBuilderContext): Resolver { const internalContext = context; return (_source, args, context, info) => { - const runner = new PGGraphQLQueryRunner(this.tenantDataSourceService, { + const runner = new PGGraphQLQueryRunner(this.dataSourceService, { targetTableName: internalContext.targetTableName, workspaceId: internalContext.workspaceId, info, fieldMetadataCollection: - internalContext.fieldMetadataCollection as FieldMetadataEntity[], + internalContext.fieldMetadataCollection as FieldMetadata[], }); return runner.updateOne(args); diff --git a/server/src/tenant/resolver-builder/pg-graphql/__tests__/pg-graphql-query-builder.spec.ts b/server/src/tenant/resolver-builder/pg-graphql/__tests__/pg-graphql-query-builder.spec.ts index a75b8e874..0905dab46 100644 --- a/server/src/tenant/resolver-builder/pg-graphql/__tests__/pg-graphql-query-builder.spec.ts +++ b/server/src/tenant/resolver-builder/pg-graphql/__tests__/pg-graphql-query-builder.spec.ts @@ -1,12 +1,12 @@ import { GraphQLResolveInfo } from 'graphql'; -import { FieldMetadataTargetColumnMap } from 'src/tenant/schema-builder/interfaces/field-metadata-target-column-map.interface'; +import { FieldMetadataTargetColumnMap } from 'src/metadata/field-metadata/interfaces/field-metadata-target-column-map.interface'; +import { FieldMetadata } from 'src/metadata/field-metadata/field-metadata.entity'; import { PGGraphQLQueryBuilder, PGGraphQLQueryBuilderOptions, } from 'src/tenant/resolver-builder/pg-graphql/pg-graphql-query-builder'; -import { FieldMetadataEntity } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; const testUUID = '123e4567-e89b-12d3-a456-426614174001'; @@ -53,7 +53,7 @@ describe('PGGraphQLQueryBuilder', () => { subField2: 'column_subField2', } as FieldMetadataTargetColumnMap, }, - ] as FieldMetadataEntity[]; + ] as FieldMetadata[]; mockOptions = { targetTableName: 'TestTable', diff --git a/server/src/tenant/resolver-builder/pg-graphql/pg-graphql-query-runner.ts b/server/src/tenant/resolver-builder/pg-graphql/pg-graphql-query-runner.ts index 0c088dec6..254821a9e 100644 --- a/server/src/tenant/resolver-builder/pg-graphql/pg-graphql-query-runner.ts +++ b/server/src/tenant/resolver-builder/pg-graphql/pg-graphql-query-runner.ts @@ -22,8 +22,8 @@ import { PGGraphQLResult, } from 'src/tenant/resolver-builder/interfaces/pg-graphql.interface'; +import { DataSourceService } from 'src/metadata/data-source/data-source.service'; import { parseResult } from 'src/tenant/resolver-builder/utils/parse-result.util'; -import { TenantDataSourceService } from 'src/tenant-datasource/tenant-datasource.service'; import { PGGraphQLQueryBuilder } from './pg-graphql-query-builder'; @@ -43,7 +43,7 @@ export class PGGraphQLQueryRunner< private options: QueryRunnerOptions; constructor( - private tenantDataSourceService: TenantDataSourceService, + private dataSourceService: DataSourceService, options: QueryRunnerOptions, ) { this.queryBuilder = new PGGraphQLQueryBuilder({ @@ -59,14 +59,10 @@ export class PGGraphQLQueryRunner< workspaceId: string, ): Promise { const workspaceDataSource = - await this.tenantDataSourceService.connectToWorkspaceDataSource( - workspaceId, - ); + await this.dataSourceService.connectToWorkspaceDataSource(workspaceId); await workspaceDataSource?.query(` - SET search_path TO ${this.tenantDataSourceService.getSchemaName( - workspaceId, - )}; + SET search_path TO ${this.dataSourceService.getSchemaName(workspaceId)}; `); return workspaceDataSource?.query(` diff --git a/server/src/tenant/resolver-builder/resolver-builder.module.ts b/server/src/tenant/resolver-builder/resolver-builder.module.ts index e1e2534f3..a580fb463 100644 --- a/server/src/tenant/resolver-builder/resolver-builder.module.ts +++ b/server/src/tenant/resolver-builder/resolver-builder.module.ts @@ -1,13 +1,13 @@ import { Module } from '@nestjs/common'; -import { TenantDataSourceModule } from 'src/tenant-datasource/tenant-datasource.module'; +import { DataSourceModule } from 'src/metadata/data-source/data-source.module'; import { ResolverFactory } from './resolver.factory'; import { resolverBuilderFactories } from './factories/factories'; @Module({ - imports: [TenantDataSourceModule], + imports: [DataSourceModule], providers: [...resolverBuilderFactories, ResolverFactory], exports: [ResolverFactory], }) diff --git a/server/src/tenant/resolver-builder/utils/__tests__/convert-arguments.spec.ts b/server/src/tenant/resolver-builder/utils/__tests__/convert-arguments.spec.ts index ec4ed204c..582b9aeee 100644 --- a/server/src/tenant/resolver-builder/utils/__tests__/convert-arguments.spec.ts +++ b/server/src/tenant/resolver-builder/utils/__tests__/convert-arguments.spec.ts @@ -1,9 +1,9 @@ -import { FieldMetadataTargetColumnMap } from 'src/tenant/schema-builder/interfaces/field-metadata-target-column-map.interface'; +import { FieldMetadataTargetColumnMap } from 'src/metadata/field-metadata/interfaces/field-metadata-target-column-map.interface'; import { - FieldMetadataEntity, + FieldMetadata, FieldMetadataType, -} from 'src/database/typeorm/metadata/entities/field-metadata.entity'; +} from 'src/metadata/field-metadata/field-metadata.entity'; import { convertArguments } from 'src/tenant/resolver-builder/utils/convert-arguments.util'; describe('convertArguments', () => { @@ -33,7 +33,7 @@ describe('convertArguments', () => { } as FieldMetadataTargetColumnMap, type: FieldMetadataType.URL, }, - ] as FieldMetadataEntity[]; + ] as FieldMetadata[]; }); test('should handle non-array arguments', () => { diff --git a/server/src/tenant/resolver-builder/utils/__tests__/convert-fields-to-graphql.spec.ts b/server/src/tenant/resolver-builder/utils/__tests__/convert-fields-to-graphql.spec.ts index 3b33ecf24..54c7a9ec4 100644 --- a/server/src/tenant/resolver-builder/utils/__tests__/convert-fields-to-graphql.spec.ts +++ b/server/src/tenant/resolver-builder/utils/__tests__/convert-fields-to-graphql.spec.ts @@ -1,7 +1,7 @@ -import { FieldMetadataTargetColumnMap } from 'src/tenant/schema-builder/interfaces/field-metadata-target-column-map.interface'; +import { FieldMetadataTargetColumnMap } from 'src/metadata/field-metadata/interfaces/field-metadata-target-column-map.interface'; +import { FieldMetadata } from 'src/metadata/field-metadata/field-metadata.entity'; import { convertFieldsToGraphQL } from 'src/tenant/resolver-builder/utils/convert-fields-to-graphql.util'; -import { FieldMetadataEntity } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; const normalizeWhitespace = (str) => str.replace(/\s+/g, ' ').trim(); @@ -23,7 +23,7 @@ describe('convertFieldsToGraphQL', () => { text: 'column_RANDOMSTRING3', } as FieldMetadataTargetColumnMap, }, - ] as FieldMetadataEntity[]; + ] as FieldMetadata[]; }); test('should handle simple fields correctly', () => { @@ -75,7 +75,7 @@ describe('convertFieldsToGraphQL', () => { const emptyField = { name: 'emptyField', targetColumnMap: {}, - } as FieldMetadataEntity; + } as FieldMetadata; fields.push(emptyField); diff --git a/server/src/tenant/schema-builder/factories/filter-type-definition.factory.ts b/server/src/tenant/schema-builder/factories/filter-type-definition.factory.ts index 318d50919..6b330b2c6 100644 --- a/server/src/tenant/schema-builder/factories/filter-type-definition.factory.ts +++ b/server/src/tenant/schema-builder/factories/filter-type-definition.factory.ts @@ -6,8 +6,8 @@ import { BuildSchemaOptions } from 'src/tenant/schema-builder/interfaces/build-s import { ObjectMetadataInterface } from 'src/tenant/schema-builder/interfaces/object-metadata.interface'; import { pascalCase } from 'src/utils/pascal-case'; +import { FieldMetadata } from 'src/metadata/field-metadata/field-metadata.entity'; import { TypeMapperService } from 'src/tenant/schema-builder/services/type-mapper.service'; -import { FieldMetadataEntity } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; import { FilterTypeFactory } from './filter-type.factory'; import { @@ -67,7 +67,7 @@ export class FilterTypeDefinitionFactory { ): GraphQLInputFieldConfigMap { const fields: GraphQLInputFieldConfigMap = {}; - objectMetadata.fields.forEach((fieldMetadata: FieldMetadataEntity) => { + objectMetadata.fields.forEach((fieldMetadata: FieldMetadata) => { const type = this.filterTypeFactory.create(fieldMetadata, options, { nullable: fieldMetadata.isNullable, }); diff --git a/server/src/tenant/schema-builder/factories/input-type-definition.factory.ts b/server/src/tenant/schema-builder/factories/input-type-definition.factory.ts index ca32e25b1..9dcb3e0e6 100644 --- a/server/src/tenant/schema-builder/factories/input-type-definition.factory.ts +++ b/server/src/tenant/schema-builder/factories/input-type-definition.factory.ts @@ -6,7 +6,7 @@ import { BuildSchemaOptions } from 'src/tenant/schema-builder/interfaces/build-s import { ObjectMetadataInterface } from 'src/tenant/schema-builder/interfaces/object-metadata.interface'; import { pascalCase } from 'src/utils/pascal-case'; -import { FieldMetadataEntity } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; +import { FieldMetadata } from 'src/metadata/field-metadata/field-metadata.entity'; import { InputTypeFactory } from './input-type.factory'; @@ -52,7 +52,7 @@ export class InputTypeDefinitionFactory { ): GraphQLInputFieldConfigMap { const fields: GraphQLInputFieldConfigMap = {}; - objectMetadata.fields.forEach((fieldMetadata: FieldMetadataEntity) => { + objectMetadata.fields.forEach((fieldMetadata: FieldMetadata) => { const type = this.inputTypeFactory.create(fieldMetadata, kind, options, { nullable: fieldMetadata.isNullable, }); diff --git a/server/src/tenant/schema-builder/factories/object-type-definition.factory.ts b/server/src/tenant/schema-builder/factories/object-type-definition.factory.ts index 2d3ddb63c..336ee7600 100644 --- a/server/src/tenant/schema-builder/factories/object-type-definition.factory.ts +++ b/server/src/tenant/schema-builder/factories/object-type-definition.factory.ts @@ -5,8 +5,8 @@ import { GraphQLFieldConfigMap, GraphQLObjectType } from 'graphql'; import { BuildSchemaOptions } from 'src/tenant/schema-builder/interfaces/build-schema-optionts.interface'; import { ObjectMetadataInterface } from 'src/tenant/schema-builder/interfaces/object-metadata.interface'; +import { FieldMetadata } from 'src/metadata/field-metadata/field-metadata.entity'; import { pascalCase } from 'src/utils/pascal-case'; -import { FieldMetadataEntity } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; import { OutputTypeFactory } from './output-type.factory'; @@ -49,7 +49,7 @@ export class ObjectTypeDefinitionFactory { ): GraphQLFieldConfigMap { const fields: GraphQLFieldConfigMap = {}; - objectMetadata.fields.forEach((fieldMetadata: FieldMetadataEntity) => { + objectMetadata.fields.forEach((fieldMetadata: FieldMetadata) => { const type = this.outputTypeFactory.create(fieldMetadata, kind, options, { nullable: fieldMetadata.isNullable, }); diff --git a/server/src/tenant/schema-builder/factories/order-by-type-definition.factory.ts b/server/src/tenant/schema-builder/factories/order-by-type-definition.factory.ts index 0e871ab80..74452fd5b 100644 --- a/server/src/tenant/schema-builder/factories/order-by-type-definition.factory.ts +++ b/server/src/tenant/schema-builder/factories/order-by-type-definition.factory.ts @@ -6,7 +6,7 @@ import { BuildSchemaOptions } from 'src/tenant/schema-builder/interfaces/build-s import { ObjectMetadataInterface } from 'src/tenant/schema-builder/interfaces/object-metadata.interface'; import { pascalCase } from 'src/utils/pascal-case'; -import { FieldMetadataEntity } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; +import { FieldMetadata } from 'src/metadata/field-metadata/field-metadata.entity'; import { InputTypeDefinition, @@ -43,7 +43,7 @@ export class OrderByTypeDefinitionFactory { ): GraphQLInputFieldConfigMap { const fields: GraphQLInputFieldConfigMap = {}; - objectMetadata.fields.forEach((fieldMetadata: FieldMetadataEntity) => { + objectMetadata.fields.forEach((fieldMetadata: FieldMetadata) => { const type = this.orderByTypeFactory.create(fieldMetadata, options, { nullable: fieldMetadata.isNullable, }); diff --git a/server/src/tenant/schema-builder/graphql-schema.factory.ts b/server/src/tenant/schema-builder/graphql-schema.factory.ts index f563f5b16..70d8cc14f 100644 --- a/server/src/tenant/schema-builder/graphql-schema.factory.ts +++ b/server/src/tenant/schema-builder/graphql-schema.factory.ts @@ -4,7 +4,7 @@ import { GraphQLSchema } from 'graphql'; import { ResolverBuilderMethods } from 'src/tenant/resolver-builder/interfaces/resolvers-builder.interface'; -import { ObjectMetadataService } from 'src/metadata/object-metadata/object-metadata.service'; +import { ObjectMetadataService } from 'src/metadata/object-metadata/services/object-metadata.service'; import { TypeDefinitionsGenerator } from './type-definitions.generator'; diff --git a/server/src/tenant/schema-builder/interfaces/field-metadata.interface.ts b/server/src/tenant/schema-builder/interfaces/field-metadata.interface.ts index 5b36f26ef..3ea023842 100644 --- a/server/src/tenant/schema-builder/interfaces/field-metadata.interface.ts +++ b/server/src/tenant/schema-builder/interfaces/field-metadata.interface.ts @@ -1,6 +1,6 @@ -import { FieldMetadataType } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; +import { FieldMetadataTargetColumnMap } from 'src/metadata/field-metadata/interfaces/field-metadata-target-column-map.interface'; -import { FieldMetadataTargetColumnMap } from './field-metadata-target-column-map.interface'; +import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; export interface FieldMetadataInterface< T extends FieldMetadataType | 'default' = 'default', diff --git a/server/src/tenant/schema-builder/interfaces/param-metadata.interface.ts b/server/src/tenant/schema-builder/interfaces/param-metadata.interface.ts index 196dba8c2..79f7df810 100644 --- a/server/src/tenant/schema-builder/interfaces/param-metadata.interface.ts +++ b/server/src/tenant/schema-builder/interfaces/param-metadata.interface.ts @@ -1,5 +1,5 @@ import { InputTypeDefinitionKind } from 'src/tenant/schema-builder/factories/input-type-definition.factory'; -import { FieldMetadataType } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; +import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; import { ObjectMetadataInterface } from './object-metadata.interface'; diff --git a/server/src/tenant/schema-builder/object-definitions/money.object-definition.ts b/server/src/tenant/schema-builder/object-definitions/money.object-definition.ts index cfc8e8c77..86975033b 100644 --- a/server/src/tenant/schema-builder/object-definitions/money.object-definition.ts +++ b/server/src/tenant/schema-builder/object-definitions/money.object-definition.ts @@ -1,6 +1,6 @@ import { ObjectMetadataInterface } from 'src/tenant/schema-builder/interfaces/object-metadata.interface'; -import { FieldMetadataType } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; +import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; export const moneyObjectDefinition = { id: FieldMetadataType.MONEY.toString(), diff --git a/server/src/tenant/schema-builder/object-definitions/url.object-definition.ts b/server/src/tenant/schema-builder/object-definitions/url.object-definition.ts index 169c9b242..e10bc1155 100644 --- a/server/src/tenant/schema-builder/object-definitions/url.object-definition.ts +++ b/server/src/tenant/schema-builder/object-definitions/url.object-definition.ts @@ -1,6 +1,6 @@ import { ObjectMetadataInterface } from 'src/tenant/schema-builder/interfaces/object-metadata.interface'; -import { FieldMetadataType } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; +import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; export const urlObjectDefinition = { id: FieldMetadataType.URL.toString(), diff --git a/server/src/tenant/schema-builder/services/type-mapper.service.ts b/server/src/tenant/schema-builder/services/type-mapper.service.ts index 5e61d9c78..3ef70a3e8 100644 --- a/server/src/tenant/schema-builder/services/type-mapper.service.ts +++ b/server/src/tenant/schema-builder/services/type-mapper.service.ts @@ -21,6 +21,7 @@ import { NumberScalarMode, } from 'src/tenant/schema-builder/interfaces/build-schema-optionts.interface'; +import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; import { UUIDFilterType, StringFilterType, @@ -30,7 +31,6 @@ import { IntFilterType, } from 'src/tenant/schema-builder/graphql-types/input'; import { OrderByDirectionType } from 'src/tenant/schema-builder/graphql-types/enum'; -import { FieldMetadataType } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; export interface TypeOptions { nullable?: boolean; diff --git a/server/src/tenant/schema-builder/storages/type-definitions.storage.ts b/server/src/tenant/schema-builder/storages/type-definitions.storage.ts index 7fbcae7c4..34a221c58 100644 --- a/server/src/tenant/schema-builder/storages/type-definitions.storage.ts +++ b/server/src/tenant/schema-builder/storages/type-definitions.storage.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import { GraphQLInputObjectType, GraphQLObjectType } from 'graphql'; -import { FieldMetadataType } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; +import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; import { InputTypeDefinition, InputTypeDefinitionKind, diff --git a/server/src/tenant/schema-builder/type-definitions.generator.ts b/server/src/tenant/schema-builder/type-definitions.generator.ts index 395e71d0d..2ce205961 100644 --- a/server/src/tenant/schema-builder/type-definitions.generator.ts +++ b/server/src/tenant/schema-builder/type-definitions.generator.ts @@ -1,7 +1,7 @@ import { Injectable, Logger } from '@nestjs/common'; -import { customTableDefaultColumns } from 'src/tenant-migration-runner/utils/custom-table-default-column.util'; -import { FieldMetadataEntity } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; +import { FieldMetadata } from 'src/metadata/field-metadata/field-metadata.entity'; +import { customTableDefaultColumns } from 'src/metadata/migration-runner/custom-table-default-column.util'; import { TypeDefinitionsStorage } from './storages/type-definitions.storage'; import { @@ -29,7 +29,7 @@ const defaultFields = customTableDefaultColumns.map((column) => { type: getFieldMetadataType(column.type), name: column.name, isNullable: true, - } as FieldMetadataEntity; + } as FieldMetadata; }); @Injectable() diff --git a/server/src/tenant/schema-builder/utils/__tests__/get-field-metadata-type.spec.ts b/server/src/tenant/schema-builder/utils/__tests__/get-field-metadata-type.spec.ts index 6ab3b011b..27b1761dc 100644 --- a/server/src/tenant/schema-builder/utils/__tests__/get-field-metadata-type.spec.ts +++ b/server/src/tenant/schema-builder/utils/__tests__/get-field-metadata-type.spec.ts @@ -1,4 +1,4 @@ -import { FieldMetadataType } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; +import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; import { getFieldMetadataType } from 'src/tenant/schema-builder/utils/get-field-metadata-type.util'; describe('getFieldMetadataType', () => { diff --git a/server/src/tenant/schema-builder/utils/__tests__/get-resolver-args.spec.ts b/server/src/tenant/schema-builder/utils/__tests__/get-resolver-args.spec.ts index 7bec3613c..86271e8c3 100644 --- a/server/src/tenant/schema-builder/utils/__tests__/get-resolver-args.spec.ts +++ b/server/src/tenant/schema-builder/utils/__tests__/get-resolver-args.spec.ts @@ -1,6 +1,6 @@ import { ResolverBuilderMethodNames } from 'src/tenant/resolver-builder/interfaces/resolvers-builder.interface'; -import { FieldMetadataType } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; +import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; import { InputTypeDefinitionKind } from 'src/tenant/schema-builder/factories/input-type-definition.factory'; import { getResolverArgs } from 'src/tenant/schema-builder/utils/get-resolver-args.util'; diff --git a/server/src/tenant/schema-builder/utils/get-field-metadata-type.util.ts b/server/src/tenant/schema-builder/utils/get-field-metadata-type.util.ts index c8fdaee00..0de04521f 100644 --- a/server/src/tenant/schema-builder/utils/get-field-metadata-type.util.ts +++ b/server/src/tenant/schema-builder/utils/get-field-metadata-type.util.ts @@ -1,4 +1,4 @@ -import { FieldMetadataType } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; +import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; const typeOrmTypeMapping = new Map([ ['uuid', FieldMetadataType.UUID], diff --git a/server/src/tenant/schema-builder/utils/get-resolver-args.util.ts b/server/src/tenant/schema-builder/utils/get-resolver-args.util.ts index 91222a733..3ccaa73fc 100644 --- a/server/src/tenant/schema-builder/utils/get-resolver-args.util.ts +++ b/server/src/tenant/schema-builder/utils/get-resolver-args.util.ts @@ -1,8 +1,8 @@ import { ResolverBuilderMethodNames } from 'src/tenant/resolver-builder/interfaces/resolvers-builder.interface'; import { ArgMetadata } from 'src/tenant/schema-builder/interfaces/param-metadata.interface'; +import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; import { InputTypeDefinitionKind } from 'src/tenant/schema-builder/factories/input-type-definition.factory'; -import { FieldMetadataType } from 'src/database/typeorm/metadata/entities/field-metadata.entity'; export const getResolverArgs = ( type: ResolverBuilderMethodNames, diff --git a/server/src/tenant/tenant.service.spec.ts b/server/src/tenant/tenant.service.spec.ts index 8a9e6ccf4..a8c64dd97 100644 --- a/server/src/tenant/tenant.service.spec.ts +++ b/server/src/tenant/tenant.service.spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { DataSourceMetadataService } from 'src/metadata/data-source-metadata/data-source-metadata.service'; -import { ObjectMetadataService } from 'src/metadata/object-metadata/object-metadata.service'; +import { ObjectMetadataService } from 'src/metadata/object-metadata/services/object-metadata.service'; import { TenantService } from './tenant.service'; diff --git a/server/src/tenant/tenant.service.ts b/server/src/tenant/tenant.service.ts index fc8b9086a..679e09e11 100644 --- a/server/src/tenant/tenant.service.ts +++ b/server/src/tenant/tenant.service.ts @@ -6,7 +6,7 @@ import { makeExecutableSchema } from '@graphql-tools/schema'; import { gql } from 'graphql-tag'; import { DataSourceMetadataService } from 'src/metadata/data-source-metadata/data-source-metadata.service'; -import { ObjectMetadataService } from 'src/metadata/object-metadata/object-metadata.service'; +import { ObjectMetadataService } from 'src/metadata/object-metadata/services/object-metadata.service'; import { GraphQLSchemaFactory } from './schema-builder/graphql-schema.factory'; import { resolverBuilderMethodNames } from './resolver-builder/factories/factories'; @@ -31,7 +31,7 @@ export class TenantService { workspaceId, ); - // Can't find any data sources for this workspace + // Can'f find any data sources for this workspace if (!dataSourcesMetadata || dataSourcesMetadata.length === 0) { return new GraphQLSchema({}); }