mirror of
https://github.com/twentyhq/twenty
synced 2026-04-21 13:37:22 +00:00
ObjectMetadata and FieldMetadata agnostic workspace migration runner (#17572)
# Introduction
Important note: This PR officially deprecates the `standardId`, about to
drop col and entity property after this has been merged
Important note2: Haven't updated the optimistic tool to also update the
universal identifier aggregators only the ids one, they should not be
consumed in the runner context -> need to improve typing or either the
optimistic tooling
In this PR we're introducing all the devxp allowing future metadata
incremental universal migration -> this has an impact on all existing
metadata actions handler ( explaining its size )
This PR also introduce workspace agnostic create update actions runner
for both field and object metadata in order to battle test the described
above devxp
Noting that these two metadata are the most complex to handle
Notes:
- A workspace migration is now highly bind to a
`applicationUniversalIdentifier`. Though we don't strictly validate
application scope for the moment
## Next
Migrate both object and field builder to universal comparison
## Universal Actions vs Flat Actions Architecture
### Concept
The migration system uses a two-phase action model:
1. **Universal Actions** - Actions defined using `universalIdentifier`
(stable, portable identifiers like `standardId` + `applicationId`)
2. **Flat Actions** - Actions defined using database `entityId` (UUIDs
specific to a workspace)
### Why This Separation?
- **Universal actions are portable**: They can be serialized, stored,
and replayed across different workspaces
- **Flat actions are executable**: They contain the actual database IDs
needed to perform operations
- **Decoupling**: The builder produces universal actions; the runner
transpiles them to flat actions at execution time
### Transpiler Pattern
Each action handler must implement
`transpileUniversalActionToFlatAction()`:
```typescript
@Injectable()
export class CreateFieldActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
'create',
'fieldMetadata',
) {
override async transpileUniversalActionToFlatAction(
context: WorkspaceMigrationActionRunnerArgs<UniversalCreateFieldAction>,
): Promise<FlatCreateFieldAction> {
// Resolve universal identifiers to database IDs
const flatObjectMetadata = findFlatEntityByUniversalIdentifierOrThrow({
flatEntityMaps: allFlatEntityMaps.flatObjectMetadataMaps,
universalIdentifier: action.objectMetadataUniversalIdentifier,
});
return {
type: action.type,
metadataName: action.metadataName,
objectMetadataId: flatObjectMetadata.id, // Resolved ID
flatFieldMetadatas: /* ... transpiled entities ... */,
};
}
}
```
### Action Handler Base Class
`BaseWorkspaceMigrationRunnerActionHandlerService<TActionType,
TMetadataName>` provides:
- **`transpileUniversalActionToFlatAction()`** - Abstract method each
handler must implement
- **`transpileUniversalDeleteActionToFlatDeleteAction()`** - Shared
helper for delete actions
## FlatEntityMaps custom properties
Introduced a `TWithCustomMapsProperties` generic parameter to control
whether custom indexing structures are included:
- **`false` (default)**: Returns `FlatEntityMaps<MetadataFlatEntity<T>>`
- used in builder/runner contexts
- **`true`**: Returns the full maps type with custom properties (e.g.,
`byUserWorkspaceIdAndFolderId`) - used in cache contexts
## Create Field Actions Refactor
Refactored create-field actions to support relation field pairs
bundling.
**Problem:** Relation fields (e.g., `Attachment.targetTask` ↔
`Task.attachments`) couldn't resolve each other's IDs during
transpilation because they were in separate actions with independent
`fieldIdByUniversalIdentifier` maps.
**Solution:**
- Removed `objectMetadataUniversalIdentifier` from
`UniversalCreateFieldAction` and `objectMetadataId` from
`FlatCreateFieldAction` - each field now carries its own
- Runner groups fields by object internally and processes each table
separately
- Split aggregator into two focused utilities:
- `aggregateNonRelationFieldsIntoObjectActions` - merges non-relation
fields into object actions
- `aggregateRelationFieldPairs` - bundles relation pairs with shared
`fieldIdByUniversalIdentifier`
This commit is contained in:
parent
f0bc9fcb43
commit
bd9688421f
235 changed files with 4536 additions and 2739 deletions
|
|
@ -672,7 +672,7 @@ import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
|||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { isStandardMetadata } from 'src/engine/metadata-modules/utils/is-standard-metadata.util';
|
||||
import { belongsToTwentyStandardApp } from 'src/engine/metadata-modules/utils/is-standard-metadata.util';
|
||||
import { MyEntityExceptionCode } from 'src/engine/metadata-modules/my-entity/my-entity.exception';
|
||||
import { type FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/types/failed-flat-entity-validation.type';
|
||||
import { getEmptyFlatEntityValidationError } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/utils/get-flat-entity-validation-error.util';
|
||||
|
|
@ -740,7 +740,7 @@ export class FlatMyEntityValidatorService {
|
|||
}
|
||||
|
||||
// Prevent deletion of standard entities unless it's a system build
|
||||
if (!buildOptions.isSystemBuild && isStandardMetadata(existingEntity)) {
|
||||
if (!buildOptions.isSystemBuild && belongsToTwentyStandardApp(existingEntity)) {
|
||||
validationResult.errors.push({
|
||||
code: MyEntityExceptionCode.MY_ENTITY_IS_STANDARD,
|
||||
message: t`Cannot delete standard entity`,
|
||||
|
|
|
|||
|
|
@ -1,113 +0,0 @@
|
|||
import { Logger } from '@nestjs/common';
|
||||
|
||||
import { writeFileSync } from 'fs';
|
||||
|
||||
import { Command, CommandRunner } from 'nest-commander';
|
||||
import { WorkspaceMigrationV2ExceptionCode } from 'twenty-shared/metadata';
|
||||
|
||||
import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant';
|
||||
import { AdditionalCacheDataMaps } from 'src/engine/workspace-cache/types/workspace-cache-key.type';
|
||||
import { computeTwentyStandardApplicationAllFlatEntityMaps } from 'src/engine/workspace-manager/twenty-standard-application/utils/twenty-standard-application-all-flat-entity-maps.constant';
|
||||
import { WorkspaceMigrationV2Exception } from 'src/engine/workspace-manager/workspace-migration.exception';
|
||||
import { WorkspaceMigrationBuildOrchestratorService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-build-orchestrator.service';
|
||||
|
||||
@Command({
|
||||
name: 'workspace:compute-twenty-standard-migration',
|
||||
description: 'Compute Twenty standard workspace migration.',
|
||||
})
|
||||
export class ComputeTwentyStandardWorkspaceMigrationCommand extends CommandRunner {
|
||||
private readonly logger = new Logger(
|
||||
ComputeTwentyStandardWorkspaceMigrationCommand.name,
|
||||
);
|
||||
|
||||
constructor(
|
||||
private readonly workspaceMigrationBuildOrchestratorService: WorkspaceMigrationBuildOrchestratorService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
this.logger.log('Starting compute Twenty standard workspace migration...');
|
||||
|
||||
// TODO: Implement migration logic here
|
||||
const workspaceId = '20202020-ef6f-4118-953c-2b027324b54a';
|
||||
const twentyStandardApplicationId = '20202020-5adb-4091-81b7-d5be86a8bdd2';
|
||||
const twentyStandardAllFlatEntityMaps =
|
||||
computeTwentyStandardApplicationAllFlatEntityMaps({
|
||||
now: new Date().toISOString(),
|
||||
workspaceId,
|
||||
twentyStandardApplicationId,
|
||||
});
|
||||
|
||||
writeFileSync(
|
||||
`${Date.now()}-all-flat-entity-maps.json`,
|
||||
JSON.stringify(twentyStandardAllFlatEntityMaps, null, 2),
|
||||
);
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationBuildOrchestratorService
|
||||
.buildWorkspaceMigration({
|
||||
buildOptions: {
|
||||
isSystemBuild: true,
|
||||
},
|
||||
fromToAllFlatEntityMaps: {
|
||||
flatObjectMetadataMaps: {
|
||||
from: createEmptyFlatEntityMaps(),
|
||||
to: twentyStandardAllFlatEntityMaps.flatObjectMetadataMaps,
|
||||
},
|
||||
flatFieldMetadataMaps: {
|
||||
from: createEmptyFlatEntityMaps(),
|
||||
to: twentyStandardAllFlatEntityMaps.flatFieldMetadataMaps,
|
||||
},
|
||||
flatIndexMaps: {
|
||||
from: createEmptyFlatEntityMaps(),
|
||||
to: twentyStandardAllFlatEntityMaps.flatIndexMaps,
|
||||
},
|
||||
flatViewFieldMaps: {
|
||||
from: createEmptyFlatEntityMaps(),
|
||||
to: twentyStandardAllFlatEntityMaps.flatViewFieldMaps,
|
||||
},
|
||||
flatViewFilterMaps: {
|
||||
from: createEmptyFlatEntityMaps(),
|
||||
to: twentyStandardAllFlatEntityMaps.flatViewFilterMaps,
|
||||
},
|
||||
flatViewGroupMaps: {
|
||||
from: createEmptyFlatEntityMaps(),
|
||||
to: twentyStandardAllFlatEntityMaps.flatViewGroupMaps,
|
||||
},
|
||||
flatViewMaps: {
|
||||
from: createEmptyFlatEntityMaps(),
|
||||
to: twentyStandardAllFlatEntityMaps.flatViewMaps,
|
||||
},
|
||||
flatAgentMaps: {
|
||||
from: createEmptyFlatEntityMaps(),
|
||||
to: twentyStandardAllFlatEntityMaps.flatAgentMaps,
|
||||
},
|
||||
flatRoleMaps: {
|
||||
from: createEmptyFlatEntityMaps(),
|
||||
to: twentyStandardAllFlatEntityMaps.flatRoleMaps,
|
||||
},
|
||||
},
|
||||
additionalCacheDataMaps: {
|
||||
featureFlagsMap: {} as AdditionalCacheDataMaps['featureFlagsMap'],
|
||||
},
|
||||
workspaceId,
|
||||
})
|
||||
.catch((error) => {
|
||||
this.logger.error(error);
|
||||
throw new WorkspaceMigrationV2Exception(
|
||||
WorkspaceMigrationV2ExceptionCode.BUILDER_INTERNAL_SERVER_ERROR,
|
||||
error.message,
|
||||
);
|
||||
});
|
||||
|
||||
writeFileSync(
|
||||
`${Date.now()}validate-and-build-result.json`,
|
||||
JSON.stringify(validateAndBuildResult, null, 2),
|
||||
);
|
||||
|
||||
this.logger.log(
|
||||
'Compute Twenty standard workspace migration completed successfully.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ComputeTwentyStandardWorkspaceMigrationCommand } from 'src/database/commands/compute-twenty-standard-workspace-migration.command';
|
||||
import { CronRegisterAllCommand } from 'src/database/commands/cron-register-all.command';
|
||||
import { DataSeedWorkspaceCommand } from 'src/database/commands/data-seed-dev-workspace.command';
|
||||
import { ListOrphanedWorkspaceEntitiesCommand } from 'src/database/commands/list-and-delete-orphaned-workspace-entities.command';
|
||||
|
|
@ -55,7 +54,6 @@ import { AutomatedTriggerModule } from 'src/modules/workflow/workflow-trigger/au
|
|||
PublicDomainModule,
|
||||
],
|
||||
providers: [
|
||||
ComputeTwentyStandardWorkspaceMigrationCommand,
|
||||
DataSeedWorkspaceCommand,
|
||||
ConfirmationQuestion,
|
||||
CronRegisterAllCommand,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-
|
|||
import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/services/field-metadata.service';
|
||||
import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { isStandardMetadata } from 'src/engine/metadata-modules/utils/is-standard-metadata.util';
|
||||
import { belongsToTwentyStandardApp } from 'src/engine/metadata-modules/utils/belongs-to-twenty-standard-app.util';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
import {
|
||||
|
|
@ -100,7 +100,7 @@ export class BackfillUpdatedByFieldCommand extends ActiveOrSuspendedWorkspacesMi
|
|||
const createFieldInputs: CreateFieldInput[] = [];
|
||||
|
||||
for (const flatObjectMetadata of objectMetadataList) {
|
||||
const isStandardObject = isStandardMetadata(flatObjectMetadata);
|
||||
const isStandardObject = belongsToTwentyStandardApp(flatObjectMetadata);
|
||||
const updatedByStandardId = !isStandardObject
|
||||
? CUSTOM_OBJECT_STANDARD_FIELD_IDS.updatedBy
|
||||
: isDefined(flatObjectMetadata.standardId)
|
||||
|
|
|
|||
|
|
@ -161,6 +161,8 @@ export class BackfillStandardPageLayoutsCommand extends ActiveOrSuspendedWorkspa
|
|||
dependencyAllFlatEntityMaps: {
|
||||
flatObjectMetadataMaps,
|
||||
},
|
||||
applicationUniversalIdentifier:
|
||||
twentyStandardFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-
|
|||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
|
||||
import { getMetadataRelatedMetadataNames } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-related-metadata-names.util';
|
||||
import { isStandardMetadata } from 'src/engine/metadata-modules/utils/is-standard-metadata.util';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant';
|
||||
|
|
@ -106,9 +105,11 @@ export class IdentifyFieldMetadataCommand extends WorkspacesMigrationCommandRunn
|
|||
const exceptions: FieldMetadataException[] = [];
|
||||
|
||||
for (const fieldMetadataEntity of allFieldMetadataEntities) {
|
||||
const isStandardMetadataResult = isStandardMetadata(fieldMetadataEntity);
|
||||
const shouldBelongToTwentyStandardApp =
|
||||
!fieldMetadataEntity.isCustom &&
|
||||
isDefined(fieldMetadataEntity.standardId);
|
||||
|
||||
if (!isStandardMetadataResult) {
|
||||
if (!shouldBelongToTwentyStandardApp) {
|
||||
customFieldMetadataEntities.push({
|
||||
fieldMetadataEntity,
|
||||
fromStandard: false,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-
|
|||
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
|
||||
import { getMetadataRelatedMetadataNames } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-related-metadata-names.util';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { isStandardMetadata } from 'src/engine/metadata-modules/utils/is-standard-metadata.util';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant';
|
||||
|
|
@ -101,9 +100,11 @@ export class IdentifyObjectMetadataCommand extends WorkspacesMigrationCommandRun
|
|||
const exceptions: ObjectMetadataException[] = [];
|
||||
|
||||
for (const objectMetadataEntity of allObjectMetadataEntities) {
|
||||
const isStandardMetadataResult = isStandardMetadata(objectMetadataEntity);
|
||||
const shouldBelongToTwentyStandardApp =
|
||||
!objectMetadataEntity.isCustom &&
|
||||
isDefined(objectMetadataEntity.standardId);
|
||||
|
||||
if (!isStandardMetadataResult) {
|
||||
if (!shouldBelongToTwentyStandardApp) {
|
||||
customObjectMetadataEntities.push({
|
||||
objectMetadataEntity,
|
||||
fromStandard: false,
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import { IsNull, Repository } from 'typeorm';
|
|||
|
||||
import { ActiveOrSuspendedWorkspacesMigrationCommandRunner } from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
||||
import { RunOnWorkspaceArgs } from 'src/database/commands/command-runners/workspaces-migration.command-runner';
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/services/application.service';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
|
|
@ -36,6 +37,7 @@ export class UpdateTaskOnDeleteActionCommand extends ActiveOrSuspendedWorkspaces
|
|||
protected readonly dataSourceService: DataSourceService,
|
||||
private readonly workspaceCacheService: WorkspaceCacheService,
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {
|
||||
super(workspaceRepository, globalWorkspaceOrmManager, dataSourceService);
|
||||
}
|
||||
|
|
@ -177,6 +179,11 @@ export class UpdateTaskOnDeleteActionCommand extends ActiveOrSuspendedWorkspaces
|
|||
);
|
||||
|
||||
try {
|
||||
const { twentyStandardFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
|
|
@ -189,6 +196,8 @@ export class UpdateTaskOnDeleteActionCommand extends ActiveOrSuspendedWorkspaces
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: true,
|
||||
applicationUniversalIdentifier:
|
||||
twentyStandardFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -114,9 +114,18 @@ export class ApplicationResolver {
|
|||
);
|
||||
}
|
||||
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
await this.workspaceMigrationRunnerService.run({
|
||||
actions,
|
||||
workspaceId,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
});
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import {
|
|||
} from 'src/engine/core-modules/application/application.exception';
|
||||
import { ApplicationInput } from 'src/engine/core-modules/application/dtos/application.input';
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/services/application.service';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { ApplicationVariableEntityService } from 'src/engine/core-modules/applicationVariable/application-variable.service';
|
||||
import { LogicFunctionLayerService } from 'src/engine/core-modules/logic-function/logic-function-layer/services/logic-function-layer.service';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
|
|
@ -74,23 +75,25 @@ export class ApplicationSyncService {
|
|||
yarnLock,
|
||||
});
|
||||
|
||||
const ownerFlatApplication: FlatApplication = application;
|
||||
|
||||
await this.syncObjects({
|
||||
objectsToSync: manifest.objects,
|
||||
workspaceId,
|
||||
applicationId: application.id,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
|
||||
await this.syncObjectRelations({
|
||||
objectsToSync: manifest.objects,
|
||||
workspaceId,
|
||||
applicationId: application.id,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
|
||||
if (manifest.fields.length > 0) {
|
||||
await this.syncFieldsOrThrow({
|
||||
fieldsToSync: manifest.fields,
|
||||
workspaceId,
|
||||
applicationId: application.id,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -106,7 +109,7 @@ export class ApplicationSyncService {
|
|||
logicFunctionsToSync: manifest.logicFunctions,
|
||||
code: manifest.sources,
|
||||
workspaceId,
|
||||
applicationId: application.id,
|
||||
ownerFlatApplication,
|
||||
logicFunctionLayerId: application.logicFunctionLayerId,
|
||||
});
|
||||
}
|
||||
|
|
@ -114,7 +117,7 @@ export class ApplicationSyncService {
|
|||
await this.syncRoles({
|
||||
manifest,
|
||||
workspaceId,
|
||||
applicationId: application.id,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
|
||||
this.logger.log('✅ Application sync from manifest completed');
|
||||
|
|
@ -190,11 +193,11 @@ export class ApplicationSyncService {
|
|||
private async syncRoles({
|
||||
manifest,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
manifest: Manifest;
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
ownerFlatApplication: FlatApplication;
|
||||
}) {
|
||||
let defaultRoleId: string | null = null;
|
||||
|
||||
|
|
@ -211,12 +214,13 @@ export class ApplicationSyncService {
|
|||
update: role,
|
||||
},
|
||||
workspaceId,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
} else {
|
||||
existingRole = await this.roleService.createRole({
|
||||
input: role,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -235,7 +239,7 @@ export class ApplicationSyncService {
|
|||
}
|
||||
|
||||
if (isDefined(defaultRoleId)) {
|
||||
await this.applicationService.update(applicationId, {
|
||||
await this.applicationService.update(ownerFlatApplication.id, {
|
||||
defaultRoleId: defaultRoleId,
|
||||
});
|
||||
}
|
||||
|
|
@ -348,11 +352,11 @@ export class ApplicationSyncService {
|
|||
objectId,
|
||||
fieldsToSync,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
objectId: string;
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
ownerFlatApplication: FlatApplication;
|
||||
fieldsToSync: ObjectFieldManifest[];
|
||||
}) {
|
||||
const fieldsWithoutRelation = fieldsToSync.filter(
|
||||
|
|
@ -414,10 +418,12 @@ export class ApplicationSyncService {
|
|||
isActive: false,
|
||||
},
|
||||
workspaceId,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
await this.fieldMetadataService.deleteOneField({
|
||||
deleteOneFieldInput: { id: fieldToDelete.id },
|
||||
workspaceId,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -448,6 +454,7 @@ export class ApplicationSyncService {
|
|||
await this.fieldMetadataService.updateOneField({
|
||||
updateFieldInput,
|
||||
workspaceId,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -465,7 +472,7 @@ export class ApplicationSyncService {
|
|||
objectMetadataId: objectId,
|
||||
universalIdentifier: fieldToCreate.universalIdentifier,
|
||||
standardId: fieldToCreate.universalIdentifier,
|
||||
applicationId,
|
||||
applicationId: ownerFlatApplication.id,
|
||||
isCustom: true,
|
||||
workspaceId,
|
||||
};
|
||||
|
|
@ -473,7 +480,7 @@ export class ApplicationSyncService {
|
|||
await this.fieldMetadataService.createOneField({
|
||||
createFieldInput,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -482,13 +489,13 @@ export class ApplicationSyncService {
|
|||
objectId,
|
||||
fieldsToSync,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
flatObjectMetadataMaps,
|
||||
}: {
|
||||
objectId: string;
|
||||
fieldsToSync: ObjectFieldManifest[];
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
ownerFlatApplication: FlatApplication;
|
||||
flatObjectMetadataMaps: {
|
||||
idByUniversalIdentifier: Partial<Record<string, string>>;
|
||||
};
|
||||
|
|
@ -539,7 +546,7 @@ export class ApplicationSyncService {
|
|||
objectMetadataId: objectId,
|
||||
universalIdentifier: relation.universalIdentifier,
|
||||
standardId: relation.universalIdentifier,
|
||||
applicationId,
|
||||
applicationId: ownerFlatApplication.id,
|
||||
isCustom: true,
|
||||
workspaceId,
|
||||
relationCreationPayload: {
|
||||
|
|
@ -553,7 +560,7 @@ export class ApplicationSyncService {
|
|||
await this.fieldMetadataService.createOneField({
|
||||
createFieldInput,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -561,11 +568,11 @@ export class ApplicationSyncService {
|
|||
private async syncObjects({
|
||||
objectsToSync,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
objectsToSync: ObjectManifest[];
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
ownerFlatApplication: FlatApplication;
|
||||
}) {
|
||||
const { flatObjectMetadataMaps: existingFlatObjectMetadataMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
|
|
@ -578,7 +585,7 @@ export class ApplicationSyncService {
|
|||
const applicationObjects = Object.values(
|
||||
existingFlatObjectMetadataMaps.byId,
|
||||
).filter(
|
||||
(obj) => isDefined(obj) && obj.applicationId === applicationId,
|
||||
(obj) => isDefined(obj) && obj.applicationId === ownerFlatApplication.id,
|
||||
// TODO handle when migrating to trinite usage
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
) as any[];
|
||||
|
|
@ -615,6 +622,7 @@ export class ApplicationSyncService {
|
|||
deleteObjectInput: { id: objectToDelete.id },
|
||||
workspaceId,
|
||||
isSystemBuild: true,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -645,13 +653,14 @@ export class ApplicationSyncService {
|
|||
await this.objectMetadataService.updateOneObject({
|
||||
updateObjectInput,
|
||||
workspaceId,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
|
||||
await this.syncObjectFieldsWithoutRelations({
|
||||
fieldsToSync: objectToSync.fields,
|
||||
objectId: objectToUpdate.id,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -671,12 +680,12 @@ export class ApplicationSyncService {
|
|||
standardId: objectToCreate.universalIdentifier,
|
||||
dataSourceId: dataSourceMetadata.id,
|
||||
universalIdentifier: objectToCreate.universalIdentifier,
|
||||
applicationId,
|
||||
applicationId: ownerFlatApplication.id,
|
||||
};
|
||||
|
||||
const createdObject = await this.objectMetadataService.createOneObject({
|
||||
createObjectInput,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
|
|
@ -684,7 +693,7 @@ export class ApplicationSyncService {
|
|||
fieldsToSync: objectToCreate.fields,
|
||||
objectId: createdObject.id,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -692,11 +701,11 @@ export class ApplicationSyncService {
|
|||
private async syncObjectRelations({
|
||||
objectsToSync,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
objectsToSync: ObjectManifest[];
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
ownerFlatApplication: FlatApplication;
|
||||
}) {
|
||||
const { flatObjectMetadataMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
|
|
@ -723,7 +732,7 @@ export class ApplicationSyncService {
|
|||
objectId: sourceObjectId,
|
||||
fieldsToSync: objectToSync.fields,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
flatObjectMetadataMaps,
|
||||
});
|
||||
}
|
||||
|
|
@ -732,11 +741,11 @@ export class ApplicationSyncService {
|
|||
private async syncFieldsOrThrow({
|
||||
fieldsToSync,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
fieldsToSync: FieldManifest[];
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
ownerFlatApplication: FlatApplication;
|
||||
}) {
|
||||
const { flatObjectMetadataMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
|
|
@ -763,14 +772,14 @@ export class ApplicationSyncService {
|
|||
objectId: targetObjectId,
|
||||
fieldsToSync: [fieldToSync],
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
|
||||
await this.syncObjectFieldsRelationOnly({
|
||||
objectId: targetObjectId,
|
||||
fieldsToSync: [fieldToSync],
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
flatObjectMetadataMaps,
|
||||
});
|
||||
}
|
||||
|
|
@ -780,13 +789,13 @@ export class ApplicationSyncService {
|
|||
logicFunctionsToSync,
|
||||
code,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
logicFunctionLayerId,
|
||||
}: {
|
||||
logicFunctionsToSync: LogicFunctionManifest[];
|
||||
workspaceId: string;
|
||||
code: Sources;
|
||||
applicationId: string;
|
||||
ownerFlatApplication: FlatApplication;
|
||||
logicFunctionLayerId: string;
|
||||
}) {
|
||||
const { flatLogicFunctionMaps } =
|
||||
|
|
@ -802,7 +811,7 @@ export class ApplicationSyncService {
|
|||
).filter(
|
||||
(logicFunction) =>
|
||||
isDefined(logicFunction) &&
|
||||
logicFunction.applicationId === applicationId,
|
||||
logicFunction.applicationId === ownerFlatApplication.id,
|
||||
) as FlatLogicFunction[];
|
||||
|
||||
const logicFunctionsToSyncUniversalIdentifiers = logicFunctionsToSync.map(
|
||||
|
|
@ -841,8 +850,8 @@ export class ApplicationSyncService {
|
|||
await this.logicFunctionService.destroyOne({
|
||||
id: logicFunctionToDelete.id,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
isSystemBuild: true,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -876,7 +885,7 @@ export class ApplicationSyncService {
|
|||
isTool: logicFunctionToSync.isTool,
|
||||
},
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
|
||||
// Trigger settings are now embedded in the logic function entity
|
||||
|
|
@ -902,7 +911,7 @@ export class ApplicationSyncService {
|
|||
isTool: logicFunctionToCreate.isTool,
|
||||
},
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -986,6 +995,7 @@ export class ApplicationSyncService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: true,
|
||||
applicationUniversalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -142,6 +142,8 @@ export class AgentService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -175,6 +177,13 @@ export class AgentService {
|
|||
input: UpdateAgentInput;
|
||||
workspaceId: string;
|
||||
}): Promise<FlatAgentWithRoleId> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatRoleTargetByAgentIdMaps, flatAgentMaps } =
|
||||
await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
'flatRoleTargetByAgentIdMaps',
|
||||
|
|
@ -215,6 +224,8 @@ export class AgentService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -281,6 +292,13 @@ export class AgentService {
|
|||
return [];
|
||||
}
|
||||
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatAgentMaps, flatRoleTargetByAgentIdMaps } =
|
||||
await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
'flatAgentMaps',
|
||||
|
|
@ -321,6 +339,8 @@ export class AgentService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -112,6 +112,8 @@ export class CommandMenuItemService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -142,6 +144,11 @@ export class CommandMenuItemService {
|
|||
input: UpdateCommandMenuItemInput,
|
||||
workspaceId: string,
|
||||
): Promise<CommandMenuItemDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatCommandMenuItemMaps: existingFlatCommandMenuItemMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -168,6 +175,8 @@ export class CommandMenuItemService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -195,6 +204,11 @@ export class CommandMenuItemService {
|
|||
}
|
||||
|
||||
async delete(id: string, workspaceId: string): Promise<CommandMenuItemDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatCommandMenuItemMaps: existingFlatCommandMenuItemMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -221,6 +235,8 @@ export class CommandMenuItemService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { isDefined } from 'twenty-shared/utils';
|
|||
import { type FindOneOptions, type Repository } from 'typeorm';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/services/application.service';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
import { type DeleteOneFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/delete-field.input';
|
||||
import { type UpdateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/update-field.input';
|
||||
|
|
@ -43,20 +44,16 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
|||
async createOneField({
|
||||
createFieldInput,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
createFieldInput: Omit<CreateFieldInput, 'workspaceId'>;
|
||||
workspaceId: string;
|
||||
/**
|
||||
* @deprecated do not use call validateBuildAndRunWorkspaceMigration contextually
|
||||
* when interacting with another application than workspace custom one
|
||||
* */
|
||||
applicationId?: string;
|
||||
ownerFlatApplication?: FlatApplication;
|
||||
}): Promise<FlatFieldMetadata> {
|
||||
const [createdFieldMetadata] = await this.createManyFields({
|
||||
workspaceId,
|
||||
createFieldInputs: [createFieldInput],
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
|
||||
if (!isDefined(createdFieldMetadata)) {
|
||||
|
|
@ -73,11 +70,21 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
|||
deleteOneFieldInput,
|
||||
workspaceId,
|
||||
isSystemBuild = false,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
deleteOneFieldInput: DeleteOneFieldInput;
|
||||
workspaceId: string;
|
||||
isSystemBuild?: boolean;
|
||||
ownerFlatApplication?: FlatApplication;
|
||||
}): Promise<FlatFieldMetadata> {
|
||||
const resolvedOwnerFlatApplication =
|
||||
ownerFlatApplication ??
|
||||
(
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
)
|
||||
).workspaceCustomFlatApplication;
|
||||
|
||||
const {
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
flatIndexMaps: existingFlatIndexMaps,
|
||||
|
|
@ -121,6 +128,8 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild,
|
||||
applicationUniversalIdentifier:
|
||||
resolvedOwnerFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -138,11 +147,21 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
|||
updateFieldInput,
|
||||
workspaceId,
|
||||
isSystemBuild = false,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
updateFieldInput: Omit<UpdateFieldInput, 'workspaceId'>;
|
||||
workspaceId: string;
|
||||
isSystemBuild?: boolean;
|
||||
ownerFlatApplication?: FlatApplication;
|
||||
}): Promise<FlatFieldMetadata> {
|
||||
const resolvedOwnerFlatApplication =
|
||||
ownerFlatApplication ??
|
||||
(
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
)
|
||||
).workspaceCustomFlatApplication;
|
||||
|
||||
const {
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
flatIndexMaps: existingFlatIndexMaps,
|
||||
|
|
@ -166,13 +185,6 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
|||
},
|
||||
);
|
||||
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const inputTranspilationResult = fromUpdateFieldInputToFlatFieldMetadata({
|
||||
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
|
||||
flatIndexMaps: existingFlatIndexMaps,
|
||||
|
|
@ -182,7 +194,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
|||
flatViewGroupMaps: existingFlatViewGroupMaps,
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
flatViewFieldMaps: existingFlatViewFieldMaps,
|
||||
flatApplication: workspaceCustomFlatApplication,
|
||||
flatApplication: resolvedOwnerFlatApplication,
|
||||
isSystemBuild,
|
||||
});
|
||||
|
||||
|
|
@ -261,6 +273,8 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild,
|
||||
applicationUniversalIdentifier:
|
||||
resolvedOwnerFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -288,50 +302,34 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
|||
async createManyFields({
|
||||
createFieldInputs,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
isSystemBuild = false,
|
||||
}: {
|
||||
createFieldInputs: Omit<CreateFieldInput, 'workspaceId'>[];
|
||||
workspaceId: string;
|
||||
/**
|
||||
* @deprecated do not use call validateBuildAndRunWorkspaceMigration contextually
|
||||
* when interacting with another application than workspace custom one
|
||||
* */
|
||||
applicationId?: string;
|
||||
ownerFlatApplication?: FlatApplication;
|
||||
isSystemBuild?: boolean;
|
||||
}): Promise<FlatFieldMetadata[]> {
|
||||
if (createFieldInputs.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
const resolvedOwnerFlatApplication =
|
||||
ownerFlatApplication ??
|
||||
(
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
)
|
||||
).workspaceCustomFlatApplication;
|
||||
|
||||
const {
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
|
||||
flatApplicationMaps,
|
||||
} = await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
'flatObjectMetadataMaps',
|
||||
'flatFieldMetadataMaps',
|
||||
'flatApplicationMaps',
|
||||
]);
|
||||
|
||||
const ownerFlatApplication = isDefined(applicationId)
|
||||
? flatApplicationMaps.byId[applicationId]
|
||||
: workspaceCustomFlatApplication;
|
||||
|
||||
if (!isDefined(ownerFlatApplication)) {
|
||||
throw new FieldMetadataException(
|
||||
`Could not find related application ${applicationId}`,
|
||||
FieldMetadataExceptionCode.APPLICATION_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const allTranspiledTranspilationInputs: Awaited<
|
||||
ReturnType<typeof fromCreateFieldInputToFlatFieldMetadatasToCreate>
|
||||
>[] = [];
|
||||
|
|
@ -343,7 +341,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
|||
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
|
||||
createFieldInput,
|
||||
workspaceId,
|
||||
flatApplication: ownerFlatApplication,
|
||||
flatApplication: resolvedOwnerFlatApplication,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
|
@ -384,6 +382,8 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild,
|
||||
applicationUniversalIdentifier:
|
||||
resolvedOwnerFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import {
|
|||
} from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type UniversalFlatFieldMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-field-metadata.type';
|
||||
|
||||
export const isFieldMetadataSettingsOfType = <
|
||||
T extends keyof FieldMetadataSettingsMapping,
|
||||
>(
|
||||
|
|
@ -23,3 +25,22 @@ export const isFieldMetadataSettingsOfType = <
|
|||
|
||||
return true;
|
||||
};
|
||||
|
||||
export const isUniversalFieldMetadataSettingsOftype = <
|
||||
T extends keyof FieldMetadataSettingsMapping,
|
||||
>(
|
||||
settings: UniversalFlatFieldMetadata['universalSettings'],
|
||||
fieldMetadataType: T,
|
||||
): settings is UniversalFlatFieldMetadata<T>['universalSettings'] => {
|
||||
// Settings don't have a discriminator - the type is determined by fieldMetadataType
|
||||
// For required settings types (RELATION, MORPH_RELATION, FILES), ensure settings is defined
|
||||
if (
|
||||
fieldMetadataType === FieldMetadataType.RELATION ||
|
||||
fieldMetadataType === FieldMetadataType.MORPH_RELATION ||
|
||||
fieldMetadataType === FieldMetadataType.FILES
|
||||
) {
|
||||
return isDefined(settings);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,13 +10,14 @@ export class WorkspaceManyOrAllFlatEntityMapsCacheService {
|
|||
|
||||
public async getOrRecomputeManyOrAllFlatEntityMaps<
|
||||
T extends (keyof AllFlatEntityMaps)[] = (keyof AllFlatEntityMaps)[],
|
||||
TWithCustomMapsProperties extends boolean = true,
|
||||
>({
|
||||
flatMapsKeys,
|
||||
workspaceId,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
flatMapsKeys?: T;
|
||||
}): Promise<Pick<AllFlatEntityMaps, T[number]>> {
|
||||
}): Promise<Pick<AllFlatEntityMaps<TWithCustomMapsProperties>, T[number]>> {
|
||||
return await this.workspaceCacheService.getOrRecompute(
|
||||
workspaceId,
|
||||
flatMapsKeys ?? ALL_FLAT_ENTITY_MAPS_PROPERTIES,
|
||||
|
|
|
|||
|
|
@ -1,20 +1,25 @@
|
|||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
import { type Expect } from 'twenty-shared/testing';
|
||||
import { type Equal, type Expect } from 'twenty-shared/testing';
|
||||
|
||||
import { type AllFlatEntityTypesByMetadataName } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-types-by-metadata-name';
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { type WorkspaceMigrationActionType } from 'src/engine/metadata-modules/flat-entity/types/metadata-workspace-migration-action.type';
|
||||
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
|
||||
import { type UniversalSyncableFlatEntity } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
|
||||
import { type WorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration-action-common';
|
||||
import { type UniversalFlatObjectMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-object-metadata.type';
|
||||
import { type BaseFlatCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-flat-create-workspace-migration-action.type';
|
||||
import { type BaseUniversalCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-universal-create-workspace-migration-action.type';
|
||||
|
||||
type ExpectedGenericFlatEntityInformation = {
|
||||
actions: {
|
||||
[P in WorkspaceMigrationActionType]:
|
||||
| WorkspaceMigrationAction
|
||||
| WorkspaceMigrationAction[];
|
||||
universalActions: {
|
||||
[P in WorkspaceMigrationActionType]: unknown;
|
||||
};
|
||||
flatActions: {
|
||||
[P in WorkspaceMigrationActionType]: unknown;
|
||||
};
|
||||
flatEntity: SyncableFlatEntity;
|
||||
universalFlatEntity: UniversalSyncableFlatEntity;
|
||||
entity: unknown;
|
||||
};
|
||||
|
||||
type ExpectedGenericAllFlatEntityInformationByMetadataEngine = {
|
||||
|
|
@ -38,4 +43,16 @@ type Assertions = [
|
|||
? true
|
||||
: false
|
||||
>,
|
||||
Expect<
|
||||
Equal<
|
||||
BaseUniversalCreateWorkspaceMigrationAction<'objectMetadata'>['flatEntity'],
|
||||
UniversalFlatObjectMetadata
|
||||
>
|
||||
>,
|
||||
Expect<
|
||||
Equal<
|
||||
BaseFlatCreateWorkspaceMigrationAction<'view'>['flatEntity'],
|
||||
FlatView
|
||||
>
|
||||
>,
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import { type AllFlatEntityTypesByMetadataName } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-types-by-metadata-name';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
|
||||
import { type MetadataToFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/types/metadata-to-flat-entity-maps-key';
|
||||
import { type FlatNavigationMenuItemMaps } from 'src/engine/metadata-modules/flat-navigation-menu-item/types/flat-navigation-menu-item-maps.type';
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
export type AllFlatEntityMaps = {
|
||||
[P in keyof AllFlatEntityTypesByMetadataName as MetadataToFlatEntityMapsKey<P>]: FlatEntityMaps<
|
||||
MetadataFlatEntity<P>
|
||||
import { type MetadataFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity-maps.type';
|
||||
import { type MetadataToFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/types/metadata-to-flat-entity-maps-key';
|
||||
|
||||
export type AllFlatEntityMaps<
|
||||
TWithCustomMapsProperties extends boolean = false,
|
||||
> = {
|
||||
[P in AllMetadataName as MetadataToFlatEntityMapsKey<P>]: MetadataFlatEntityMaps<
|
||||
P,
|
||||
TWithCustomMapsProperties
|
||||
>;
|
||||
} & {
|
||||
flatNavigationMenuItemMaps: FlatNavigationMenuItemMaps;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,166 +1,216 @@
|
|||
import { type AgentEntity } from 'src/engine/metadata-modules/ai/ai-agent/entities/agent.entity';
|
||||
import { type CommandMenuItemEntity } from 'src/engine/metadata-modules/command-menu-item/entities/command-menu-item.entity';
|
||||
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { type FlatAgentMaps } from 'src/engine/metadata-modules/flat-agent/types/flat-agent-maps.type';
|
||||
import { type FlatAgent } from 'src/engine/metadata-modules/flat-agent/types/flat-agent.type';
|
||||
import { type FlatCommandMenuItemMaps } from 'src/engine/metadata-modules/flat-command-menu-item/types/flat-command-menu-item-maps.type';
|
||||
import { type FlatCommandMenuItem } from 'src/engine/metadata-modules/flat-command-menu-item/types/flat-command-menu-item.type';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type MetadataEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-entity.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatFrontComponentMaps } from 'src/engine/metadata-modules/flat-front-component/types/flat-front-component-maps.type';
|
||||
import { type FlatFrontComponent } from 'src/engine/metadata-modules/flat-front-component/types/flat-front-component.type';
|
||||
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
|
||||
import { type FlatNavigationMenuItemMaps } from 'src/engine/metadata-modules/flat-navigation-menu-item/types/flat-navigation-menu-item-maps.type';
|
||||
import { type FlatNavigationMenuItem } from 'src/engine/metadata-modules/flat-navigation-menu-item/types/flat-navigation-menu-item.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { type FlatPageLayoutTabMaps } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab-maps.type';
|
||||
import { type FlatPageLayoutTab } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab.type';
|
||||
import { type FlatPageLayoutWidgetMaps } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-maps.type';
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { type FlatPageLayoutMaps } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout-maps.type';
|
||||
import { type FlatPageLayout } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout.type';
|
||||
import { type FlatRoleTargetMaps } from 'src/engine/metadata-modules/flat-role-target/types/flat-role-target-maps.type';
|
||||
import { type FlatRoleTarget } from 'src/engine/metadata-modules/flat-role-target/types/flat-role-target.type';
|
||||
import { type FlatRole } from 'src/engine/metadata-modules/flat-role/types/flat-role.type';
|
||||
import { type FlatSkillMaps } from 'src/engine/metadata-modules/flat-skill/types/flat-skill-maps.type';
|
||||
import { type FlatSkill } from 'src/engine/metadata-modules/flat-skill/types/flat-skill.type';
|
||||
import { type FlatViewFieldMaps } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field-maps.type';
|
||||
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
|
||||
import { type FlatViewFilterGroupMaps } from 'src/engine/metadata-modules/flat-view-filter-group/types/flat-view-filter-group-maps.type';
|
||||
import { type FlatViewFilterGroup } from 'src/engine/metadata-modules/flat-view-filter-group/types/flat-view-filter-group.type';
|
||||
import { type FlatViewFilterMaps } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter-maps.type';
|
||||
import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type';
|
||||
import { type FlatViewGroupMaps } from 'src/engine/metadata-modules/flat-view-group/types/flat-view-group-maps.type';
|
||||
import { type FlatViewGroup } from 'src/engine/metadata-modules/flat-view-group/types/flat-view-group.type';
|
||||
import { type FlatViewMaps } from 'src/engine/metadata-modules/flat-view/types/flat-view-maps.type';
|
||||
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
|
||||
import { type FlatWebhookMaps } from 'src/engine/metadata-modules/flat-webhook/types/flat-webhook-maps.type';
|
||||
import { type FlatWebhook } from 'src/engine/metadata-modules/flat-webhook/types/flat-webhook.type';
|
||||
import { type FrontComponentEntity } from 'src/engine/metadata-modules/front-component/entities/front-component.entity';
|
||||
import { type IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
|
||||
import { type FlatLogicFunction } from 'src/engine/metadata-modules/logic-function/types/flat-logic-function.type';
|
||||
import { type LogicFunctionEntity } from 'src/engine/metadata-modules/logic-function/logic-function.entity';
|
||||
import { type FlatLogicFunction } from 'src/engine/metadata-modules/logic-function/types/flat-logic-function.type';
|
||||
import { type NavigationMenuItemEntity } from 'src/engine/metadata-modules/navigation-menu-item/entities/navigation-menu-item.entity';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
|
||||
import { type PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout-tab/entities/page-layout-tab.entity';
|
||||
import { type PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout-widget/entities/page-layout-widget.entity';
|
||||
import { type RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
import { type PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
|
||||
import { type RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
|
||||
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
|
||||
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.type';
|
||||
import { type RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
|
||||
import { type RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
import { type RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
|
||||
import { type RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
|
||||
import { type FlatRowLevelPermissionPredicateGroupMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group-maps.type';
|
||||
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
|
||||
import { type FlatRowLevelPermissionPredicateMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-maps.type';
|
||||
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.type';
|
||||
import { type SkillEntity } from 'src/engine/metadata-modules/skill/entities/skill.entity';
|
||||
import { type ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
|
||||
import { type ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
|
||||
import { type ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
|
||||
import { type ViewFilterGroupEntity } from 'src/engine/metadata-modules/view-filter-group/entities/view-filter-group.entity';
|
||||
import { type ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
|
||||
import { type ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity';
|
||||
import { type ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
|
||||
import { type WebhookEntity } from 'src/engine/metadata-modules/webhook/entities/webhook.entity';
|
||||
import { type UniversalFlatEntityFrom } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
|
||||
import { type UniversalFlatObjectMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-object-metadata.type';
|
||||
import {
|
||||
type CreateAgentAction,
|
||||
type DeleteAgentAction,
|
||||
type UpdateAgentAction,
|
||||
type FlatCreateAgentAction,
|
||||
type FlatDeleteAgentAction,
|
||||
type FlatUpdateAgentAction,
|
||||
type UniversalDeleteAgentAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/agent/types/workspace-migration-agent-action-builder.service';
|
||||
import {
|
||||
type CreateCommandMenuItemAction,
|
||||
type DeleteCommandMenuItemAction,
|
||||
type UpdateCommandMenuItemAction,
|
||||
type FlatCreateCommandMenuItemAction,
|
||||
type FlatDeleteCommandMenuItemAction,
|
||||
type FlatUpdateCommandMenuItemAction,
|
||||
type UniversalDeleteCommandMenuItemAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/command-menu-item/types/workspace-migration-command-menu-item-action.type';
|
||||
import {
|
||||
type CreateFieldAction,
|
||||
type DeleteFieldAction,
|
||||
type UpdateFieldAction,
|
||||
type FlatCreateFieldAction,
|
||||
type FlatDeleteFieldAction,
|
||||
type FlatUpdateFieldAction,
|
||||
type UniversalCreateFieldAction,
|
||||
type UniversalDeleteFieldAction,
|
||||
type UniversalUpdateFieldAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
import {
|
||||
type CreateFrontComponentAction,
|
||||
type DeleteFrontComponentAction,
|
||||
type UpdateFrontComponentAction,
|
||||
type FlatCreateFrontComponentAction,
|
||||
type FlatDeleteFrontComponentAction,
|
||||
type FlatUpdateFrontComponentAction,
|
||||
type UniversalDeleteFrontComponentAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/front-component/types/workspace-migration-front-component-action.type';
|
||||
import {
|
||||
type CreateIndexAction,
|
||||
type DeleteIndexAction,
|
||||
type UpdateIndexAction,
|
||||
type FlatCreateIndexAction,
|
||||
type FlatDeleteIndexAction,
|
||||
type FlatUpdateIndexAction,
|
||||
type UniversalDeleteIndexAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/index/types/workspace-migration-index-action';
|
||||
import {
|
||||
type CreateNavigationMenuItemAction,
|
||||
type DeleteNavigationMenuItemAction,
|
||||
type UpdateNavigationMenuItemAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/navigation-menu-item/types/workspace-migration-navigation-menu-item-action.type';
|
||||
import {
|
||||
type CreateObjectAction,
|
||||
type DeleteObjectAction,
|
||||
type UpdateObjectAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/object/types/workspace-migration-object-action';
|
||||
import {
|
||||
type CreatePageLayoutTabAction,
|
||||
type DeletePageLayoutTabAction,
|
||||
type UpdatePageLayoutTabAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/page-layout-tab/types/workspace-migration-page-layout-tab-action.type';
|
||||
import {
|
||||
type CreatePageLayoutWidgetAction,
|
||||
type DeletePageLayoutWidgetAction,
|
||||
type UpdatePageLayoutWidgetAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/page-layout-widget/types/workspace-migration-page-layout-widget-action.type';
|
||||
import {
|
||||
type CreatePageLayoutAction,
|
||||
type DeletePageLayoutAction,
|
||||
type UpdatePageLayoutAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/page-layout/types/workspace-migration-page-layout-action.type';
|
||||
import {
|
||||
type CreateRoleTargetAction,
|
||||
type DeleteRoleTargetAction,
|
||||
type UpdateRoleTargetAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/role-target/types/workspace-migration-role-target-action.type';
|
||||
import {
|
||||
type CreateRoleAction,
|
||||
type DeleteRoleAction,
|
||||
type UpdateRoleAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/role/types/workspace-migration-role-action.type';
|
||||
import {
|
||||
type CreateRowLevelPermissionPredicateGroupAction,
|
||||
type DeleteRowLevelPermissionPredicateGroupAction,
|
||||
type UpdateRowLevelPermissionPredicateGroupAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/row-level-permission-predicate-group/types/workspace-migration-row-level-permission-predicate-group-action.type';
|
||||
import {
|
||||
type CreateRowLevelPermissionPredicateAction,
|
||||
type DeleteRowLevelPermissionPredicateAction,
|
||||
type UpdateRowLevelPermissionPredicateAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/row-level-permission-predicate/types/workspace-migration-row-level-permission-predicate-action.type';
|
||||
import {
|
||||
type CreateLogicFunctionAction,
|
||||
type DeleteLogicFunctionAction,
|
||||
type UpdateLogicFunctionAction,
|
||||
type FlatCreateLogicFunctionAction,
|
||||
type FlatDeleteLogicFunctionAction,
|
||||
type FlatUpdateLogicFunctionAction,
|
||||
type UniversalDeleteLogicFunctionAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/logic-function/types/workspace-migration-logic-function-action.type';
|
||||
import {
|
||||
type CreateSkillAction,
|
||||
type DeleteSkillAction,
|
||||
type UpdateSkillAction,
|
||||
type FlatCreateNavigationMenuItemAction,
|
||||
type FlatDeleteNavigationMenuItemAction,
|
||||
type FlatUpdateNavigationMenuItemAction,
|
||||
type UniversalDeleteNavigationMenuItemAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/navigation-menu-item/types/workspace-migration-navigation-menu-item-action.type';
|
||||
import {
|
||||
type FlatCreateObjectAction,
|
||||
type FlatDeleteObjectAction,
|
||||
type FlatUpdateObjectAction,
|
||||
type UniversalCreateObjectAction,
|
||||
type UniversalDeleteObjectAction,
|
||||
type UniversalUpdateObjectAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/object/types/workspace-migration-object-action';
|
||||
import {
|
||||
type FlatCreatePageLayoutTabAction,
|
||||
type FlatDeletePageLayoutTabAction,
|
||||
type FlatUpdatePageLayoutTabAction,
|
||||
type UniversalDeletePageLayoutTabAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/page-layout-tab/types/workspace-migration-page-layout-tab-action.type';
|
||||
import {
|
||||
type FlatCreatePageLayoutWidgetAction,
|
||||
type FlatDeletePageLayoutWidgetAction,
|
||||
type FlatUpdatePageLayoutWidgetAction,
|
||||
type UniversalDeletePageLayoutWidgetAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/page-layout-widget/types/workspace-migration-page-layout-widget-action.type';
|
||||
import {
|
||||
type FlatCreatePageLayoutAction,
|
||||
type FlatDeletePageLayoutAction,
|
||||
type FlatUpdatePageLayoutAction,
|
||||
type UniversalDeletePageLayoutAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/page-layout/types/workspace-migration-page-layout-action.type';
|
||||
import {
|
||||
type FlatCreateRoleTargetAction,
|
||||
type FlatDeleteRoleTargetAction,
|
||||
type FlatUpdateRoleTargetAction,
|
||||
type UniversalDeleteRoleTargetAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/role-target/types/workspace-migration-role-target-action.type';
|
||||
import {
|
||||
type FlatCreateRoleAction,
|
||||
type FlatDeleteRoleAction,
|
||||
type FlatUpdateRoleAction,
|
||||
type UniversalDeleteRoleAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/role/types/workspace-migration-role-action.type';
|
||||
import {
|
||||
type FlatCreateRowLevelPermissionPredicateGroupAction,
|
||||
type FlatDeleteRowLevelPermissionPredicateGroupAction,
|
||||
type FlatUpdateRowLevelPermissionPredicateGroupAction,
|
||||
type UniversalDeleteRowLevelPermissionPredicateGroupAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/row-level-permission-predicate-group/types/workspace-migration-row-level-permission-predicate-group-action.type';
|
||||
import {
|
||||
type FlatCreateRowLevelPermissionPredicateAction,
|
||||
type FlatDeleteRowLevelPermissionPredicateAction,
|
||||
type FlatUpdateRowLevelPermissionPredicateAction,
|
||||
type UniversalDeleteRowLevelPermissionPredicateAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/row-level-permission-predicate/types/workspace-migration-row-level-permission-predicate-action.type';
|
||||
import {
|
||||
type FlatCreateSkillAction,
|
||||
type FlatDeleteSkillAction,
|
||||
type FlatUpdateSkillAction,
|
||||
type UniversalDeleteSkillAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/skill/types/workspace-migration-skill-action.type';
|
||||
import {
|
||||
type CreateViewFieldAction,
|
||||
type DeleteViewFieldAction,
|
||||
type UpdateViewFieldAction,
|
||||
type FlatCreateViewFieldAction,
|
||||
type FlatDeleteViewFieldAction,
|
||||
type FlatUpdateViewFieldAction,
|
||||
type UniversalDeleteViewFieldAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-field/types/workspace-migration-view-field-action.type';
|
||||
import {
|
||||
type CreateViewFilterGroupAction,
|
||||
type DeleteViewFilterGroupAction,
|
||||
type UpdateViewFilterGroupAction,
|
||||
type FlatCreateViewFilterGroupAction,
|
||||
type FlatDeleteViewFilterGroupAction,
|
||||
type FlatUpdateViewFilterGroupAction,
|
||||
type UniversalDeleteViewFilterGroupAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-filter-group/types/workspace-migration-view-filter-group-action.type';
|
||||
import {
|
||||
type CreateViewFilterAction,
|
||||
type DeleteViewFilterAction,
|
||||
type UpdateViewFilterAction,
|
||||
type FlatCreateViewFilterAction,
|
||||
type FlatDeleteViewFilterAction,
|
||||
type FlatUpdateViewFilterAction,
|
||||
type UniversalDeleteViewFilterAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-filter/types/workspace-migration-view-filter-action.type';
|
||||
import {
|
||||
type CreateViewGroupAction,
|
||||
type DeleteViewGroupAction,
|
||||
type UpdateViewGroupAction,
|
||||
type FlatCreateViewGroupAction,
|
||||
type FlatDeleteViewGroupAction,
|
||||
type FlatUpdateViewGroupAction,
|
||||
type UniversalDeleteViewGroupAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-group/types/workspace-migration-view-group-action.type';
|
||||
import {
|
||||
type CreateViewAction,
|
||||
type DeleteViewAction,
|
||||
type UpdateViewAction,
|
||||
type FlatCreateViewAction,
|
||||
type FlatDeleteViewAction,
|
||||
type FlatUpdateViewAction,
|
||||
type UniversalDeleteViewAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view/types/workspace-migration-view-action.type';
|
||||
import {
|
||||
type CreateWebhookAction,
|
||||
type DeleteWebhookAction,
|
||||
type UpdateWebhookAction,
|
||||
type FlatCreateWebhookAction,
|
||||
type FlatDeleteWebhookAction,
|
||||
type FlatUpdateWebhookAction,
|
||||
type UniversalDeleteWebhookAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/webhook/types/workspace-migration-webhook-action.type';
|
||||
|
||||
export type AllFlatEntityTypesByMetadataName = {
|
||||
fieldMetadata: {
|
||||
actions: {
|
||||
create: CreateFieldAction;
|
||||
update: UpdateFieldAction;
|
||||
delete: DeleteFieldAction;
|
||||
flatEntityMaps: FlatEntityMaps<FlatFieldMetadata>;
|
||||
universalActions: {
|
||||
create: UniversalCreateFieldAction;
|
||||
update: UniversalUpdateFieldAction;
|
||||
delete: UniversalDeleteFieldAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreateFieldAction;
|
||||
update: FlatUpdateFieldAction;
|
||||
delete: FlatDeleteFieldAction;
|
||||
};
|
||||
flatEntity: FlatFieldMetadata;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<
|
||||
|
|
@ -170,180 +220,288 @@ export type AllFlatEntityTypesByMetadataName = {
|
|||
entity: MetadataEntity<'fieldMetadata'>;
|
||||
};
|
||||
objectMetadata: {
|
||||
actions: {
|
||||
create: CreateObjectAction;
|
||||
update: UpdateObjectAction;
|
||||
delete: DeleteObjectAction;
|
||||
flatEntityMaps: FlatEntityMaps<FlatObjectMetadata>;
|
||||
universalActions: {
|
||||
create: UniversalCreateObjectAction;
|
||||
update: UniversalUpdateObjectAction;
|
||||
delete: UniversalDeleteObjectAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreateObjectAction;
|
||||
update: FlatUpdateObjectAction;
|
||||
delete: FlatDeleteObjectAction;
|
||||
};
|
||||
flatEntity: FlatObjectMetadata;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<ObjectMetadataEntity>;
|
||||
universalFlatEntity: UniversalFlatObjectMetadata;
|
||||
entity: MetadataEntity<'objectMetadata'>;
|
||||
};
|
||||
view: {
|
||||
actions: {
|
||||
create: CreateViewAction;
|
||||
update: UpdateViewAction;
|
||||
delete: DeleteViewAction;
|
||||
flatEntityMaps: FlatViewMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateViewAction;
|
||||
update: FlatUpdateViewAction;
|
||||
delete: UniversalDeleteViewAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreateViewAction;
|
||||
update: FlatUpdateViewAction;
|
||||
delete: FlatDeleteViewAction;
|
||||
};
|
||||
flatEntity: FlatView;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<ViewEntity>;
|
||||
entity: MetadataEntity<'view'>;
|
||||
};
|
||||
viewField: {
|
||||
actions: {
|
||||
create: CreateViewFieldAction;
|
||||
update: UpdateViewFieldAction;
|
||||
delete: DeleteViewFieldAction;
|
||||
flatEntityMaps: FlatViewFieldMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateViewFieldAction;
|
||||
update: FlatUpdateViewFieldAction;
|
||||
delete: UniversalDeleteViewFieldAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreateViewFieldAction;
|
||||
update: FlatUpdateViewFieldAction;
|
||||
delete: FlatDeleteViewFieldAction;
|
||||
};
|
||||
flatEntity: FlatViewField;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<ViewFieldEntity>;
|
||||
entity: MetadataEntity<'viewField'>;
|
||||
};
|
||||
viewGroup: {
|
||||
actions: {
|
||||
create: CreateViewGroupAction;
|
||||
update: UpdateViewGroupAction;
|
||||
delete: DeleteViewGroupAction;
|
||||
flatEntityMaps: FlatViewGroupMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateViewGroupAction;
|
||||
update: FlatUpdateViewGroupAction;
|
||||
delete: UniversalDeleteViewGroupAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreateViewGroupAction;
|
||||
update: FlatUpdateViewGroupAction;
|
||||
delete: FlatDeleteViewGroupAction;
|
||||
};
|
||||
flatEntity: FlatViewGroup;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<ViewGroupEntity>;
|
||||
entity: MetadataEntity<'viewGroup'>;
|
||||
};
|
||||
rowLevelPermissionPredicate: {
|
||||
actions: {
|
||||
create: CreateRowLevelPermissionPredicateAction;
|
||||
update: UpdateRowLevelPermissionPredicateAction;
|
||||
delete: DeleteRowLevelPermissionPredicateAction;
|
||||
flatEntityMaps: FlatRowLevelPermissionPredicateMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateRowLevelPermissionPredicateAction;
|
||||
update: FlatUpdateRowLevelPermissionPredicateAction;
|
||||
delete: UniversalDeleteRowLevelPermissionPredicateAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreateRowLevelPermissionPredicateAction;
|
||||
update: FlatUpdateRowLevelPermissionPredicateAction;
|
||||
delete: FlatDeleteRowLevelPermissionPredicateAction;
|
||||
};
|
||||
flatEntity: FlatRowLevelPermissionPredicate;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<RowLevelPermissionPredicateEntity>;
|
||||
entity: MetadataEntity<'rowLevelPermissionPredicate'>;
|
||||
};
|
||||
rowLevelPermissionPredicateGroup: {
|
||||
actions: {
|
||||
create: CreateRowLevelPermissionPredicateGroupAction;
|
||||
update: UpdateRowLevelPermissionPredicateGroupAction;
|
||||
delete: DeleteRowLevelPermissionPredicateGroupAction;
|
||||
flatEntityMaps: FlatRowLevelPermissionPredicateGroupMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateRowLevelPermissionPredicateGroupAction;
|
||||
update: FlatUpdateRowLevelPermissionPredicateGroupAction;
|
||||
delete: UniversalDeleteRowLevelPermissionPredicateGroupAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreateRowLevelPermissionPredicateGroupAction;
|
||||
update: FlatUpdateRowLevelPermissionPredicateGroupAction;
|
||||
delete: FlatDeleteRowLevelPermissionPredicateGroupAction;
|
||||
};
|
||||
flatEntity: FlatRowLevelPermissionPredicateGroup;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<RowLevelPermissionPredicateGroupEntity>;
|
||||
entity: MetadataEntity<'rowLevelPermissionPredicateGroup'>;
|
||||
};
|
||||
viewFilterGroup: {
|
||||
actions: {
|
||||
create: CreateViewFilterGroupAction;
|
||||
update: UpdateViewFilterGroupAction;
|
||||
delete: DeleteViewFilterGroupAction;
|
||||
flatEntityMaps: FlatViewFilterGroupMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateViewFilterGroupAction;
|
||||
update: FlatUpdateViewFilterGroupAction;
|
||||
delete: UniversalDeleteViewFilterGroupAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreateViewFilterGroupAction;
|
||||
update: FlatUpdateViewFilterGroupAction;
|
||||
delete: FlatDeleteViewFilterGroupAction;
|
||||
};
|
||||
flatEntity: FlatViewFilterGroup;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<ViewFilterGroupEntity>;
|
||||
entity: MetadataEntity<'viewFilterGroup'>;
|
||||
};
|
||||
index: {
|
||||
actions: {
|
||||
create: CreateIndexAction;
|
||||
update: UpdateIndexAction;
|
||||
delete: DeleteIndexAction;
|
||||
flatEntityMaps: FlatEntityMaps<FlatIndexMetadata>;
|
||||
universalActions: {
|
||||
create: FlatCreateIndexAction;
|
||||
update: FlatUpdateIndexAction;
|
||||
delete: UniversalDeleteIndexAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreateIndexAction;
|
||||
update: FlatUpdateIndexAction;
|
||||
delete: FlatDeleteIndexAction;
|
||||
};
|
||||
flatEntity: FlatIndexMetadata;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<IndexMetadataEntity>;
|
||||
entity: MetadataEntity<'index'>;
|
||||
};
|
||||
logicFunction: {
|
||||
actions: {
|
||||
create: CreateLogicFunctionAction;
|
||||
update: UpdateLogicFunctionAction;
|
||||
delete: DeleteLogicFunctionAction;
|
||||
flatEntityMaps: FlatEntityMaps<FlatLogicFunction>;
|
||||
universalActions: {
|
||||
create: FlatCreateLogicFunctionAction;
|
||||
update: FlatUpdateLogicFunctionAction;
|
||||
delete: UniversalDeleteLogicFunctionAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreateLogicFunctionAction;
|
||||
update: FlatUpdateLogicFunctionAction;
|
||||
delete: FlatDeleteLogicFunctionAction;
|
||||
};
|
||||
flatEntity: FlatLogicFunction;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<LogicFunctionEntity>;
|
||||
entity: MetadataEntity<'logicFunction'>;
|
||||
};
|
||||
viewFilter: {
|
||||
actions: {
|
||||
create: CreateViewFilterAction;
|
||||
update: UpdateViewFilterAction;
|
||||
delete: DeleteViewFilterAction;
|
||||
flatEntityMaps: FlatViewFilterMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateViewFilterAction;
|
||||
update: FlatUpdateViewFilterAction;
|
||||
delete: UniversalDeleteViewFilterAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreateViewFilterAction;
|
||||
update: FlatUpdateViewFilterAction;
|
||||
delete: FlatDeleteViewFilterAction;
|
||||
};
|
||||
flatEntity: FlatViewFilter;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<ViewFilterEntity>;
|
||||
entity: MetadataEntity<'viewFilter'>;
|
||||
};
|
||||
role: {
|
||||
actions: {
|
||||
create: CreateRoleAction;
|
||||
update: UpdateRoleAction;
|
||||
delete: DeleteRoleAction;
|
||||
flatEntityMaps: FlatEntityMaps<FlatRole>;
|
||||
universalActions: {
|
||||
create: FlatCreateRoleAction;
|
||||
update: FlatUpdateRoleAction;
|
||||
delete: UniversalDeleteRoleAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreateRoleAction;
|
||||
update: FlatUpdateRoleAction;
|
||||
delete: FlatDeleteRoleAction;
|
||||
};
|
||||
flatEntity: FlatRole;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<RoleEntity>;
|
||||
entity: MetadataEntity<'role'>;
|
||||
};
|
||||
roleTarget: {
|
||||
actions: {
|
||||
create: CreateRoleTargetAction;
|
||||
update: UpdateRoleTargetAction;
|
||||
delete: DeleteRoleTargetAction;
|
||||
flatEntityMaps: FlatRoleTargetMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateRoleTargetAction;
|
||||
update: FlatUpdateRoleTargetAction;
|
||||
delete: UniversalDeleteRoleTargetAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreateRoleTargetAction;
|
||||
update: FlatUpdateRoleTargetAction;
|
||||
delete: FlatDeleteRoleTargetAction;
|
||||
};
|
||||
flatEntity: FlatRoleTarget;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<RoleTargetEntity>;
|
||||
entity: MetadataEntity<'roleTarget'>;
|
||||
};
|
||||
agent: {
|
||||
actions: {
|
||||
create: CreateAgentAction;
|
||||
update: UpdateAgentAction;
|
||||
delete: DeleteAgentAction;
|
||||
flatEntityMaps: FlatAgentMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateAgentAction;
|
||||
update: FlatUpdateAgentAction;
|
||||
delete: UniversalDeleteAgentAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreateAgentAction;
|
||||
update: FlatUpdateAgentAction;
|
||||
delete: FlatDeleteAgentAction;
|
||||
};
|
||||
flatEntity: FlatAgent;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<AgentEntity>;
|
||||
entity: MetadataEntity<'agent'>;
|
||||
};
|
||||
skill: {
|
||||
actions: {
|
||||
create: CreateSkillAction;
|
||||
update: UpdateSkillAction;
|
||||
delete: DeleteSkillAction;
|
||||
flatEntityMaps: FlatSkillMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateSkillAction;
|
||||
update: FlatUpdateSkillAction;
|
||||
delete: UniversalDeleteSkillAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreateSkillAction;
|
||||
update: FlatUpdateSkillAction;
|
||||
delete: FlatDeleteSkillAction;
|
||||
};
|
||||
flatEntity: FlatSkill;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<SkillEntity>;
|
||||
entity: MetadataEntity<'skill'>;
|
||||
};
|
||||
commandMenuItem: {
|
||||
actions: {
|
||||
create: CreateCommandMenuItemAction;
|
||||
update: UpdateCommandMenuItemAction;
|
||||
delete: DeleteCommandMenuItemAction;
|
||||
flatEntityMaps: FlatCommandMenuItemMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateCommandMenuItemAction;
|
||||
update: FlatUpdateCommandMenuItemAction;
|
||||
delete: UniversalDeleteCommandMenuItemAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreateCommandMenuItemAction;
|
||||
update: FlatUpdateCommandMenuItemAction;
|
||||
delete: FlatDeleteCommandMenuItemAction;
|
||||
};
|
||||
flatEntity: FlatCommandMenuItem;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<CommandMenuItemEntity>;
|
||||
entity: MetadataEntity<'commandMenuItem'>;
|
||||
};
|
||||
navigationMenuItem: {
|
||||
actions: {
|
||||
create: CreateNavigationMenuItemAction;
|
||||
update: UpdateNavigationMenuItemAction;
|
||||
delete: DeleteNavigationMenuItemAction;
|
||||
flatEntityMaps: FlatNavigationMenuItemMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateNavigationMenuItemAction;
|
||||
update: FlatUpdateNavigationMenuItemAction;
|
||||
delete: UniversalDeleteNavigationMenuItemAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreateNavigationMenuItemAction;
|
||||
update: FlatUpdateNavigationMenuItemAction;
|
||||
delete: FlatDeleteNavigationMenuItemAction;
|
||||
};
|
||||
flatEntity: FlatNavigationMenuItem;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<NavigationMenuItemEntity>;
|
||||
entity: NavigationMenuItemEntity;
|
||||
};
|
||||
pageLayout: {
|
||||
actions: {
|
||||
create: CreatePageLayoutAction;
|
||||
update: UpdatePageLayoutAction;
|
||||
delete: DeletePageLayoutAction;
|
||||
flatEntityMaps: FlatPageLayoutMaps;
|
||||
universalActions: {
|
||||
create: FlatCreatePageLayoutAction;
|
||||
update: FlatUpdatePageLayoutAction;
|
||||
delete: UniversalDeletePageLayoutAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreatePageLayoutAction;
|
||||
update: FlatUpdatePageLayoutAction;
|
||||
delete: FlatDeletePageLayoutAction;
|
||||
};
|
||||
flatEntity: FlatPageLayout;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<PageLayoutEntity>;
|
||||
entity: MetadataEntity<'pageLayout'>;
|
||||
};
|
||||
pageLayoutWidget: {
|
||||
actions: {
|
||||
create: CreatePageLayoutWidgetAction;
|
||||
update: UpdatePageLayoutWidgetAction;
|
||||
delete: DeletePageLayoutWidgetAction;
|
||||
flatEntityMaps: FlatPageLayoutWidgetMaps;
|
||||
universalActions: {
|
||||
create: FlatCreatePageLayoutWidgetAction;
|
||||
update: FlatUpdatePageLayoutWidgetAction;
|
||||
delete: UniversalDeletePageLayoutWidgetAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreatePageLayoutWidgetAction;
|
||||
update: FlatUpdatePageLayoutWidgetAction;
|
||||
delete: FlatDeletePageLayoutWidgetAction;
|
||||
};
|
||||
flatEntity: FlatPageLayoutWidget;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<
|
||||
|
|
@ -353,30 +511,48 @@ export type AllFlatEntityTypesByMetadataName = {
|
|||
entity: MetadataEntity<'pageLayoutWidget'>;
|
||||
};
|
||||
pageLayoutTab: {
|
||||
actions: {
|
||||
create: CreatePageLayoutTabAction;
|
||||
update: UpdatePageLayoutTabAction;
|
||||
delete: DeletePageLayoutTabAction;
|
||||
flatEntityMaps: FlatPageLayoutTabMaps;
|
||||
universalActions: {
|
||||
create: FlatCreatePageLayoutTabAction;
|
||||
update: FlatUpdatePageLayoutTabAction;
|
||||
delete: UniversalDeletePageLayoutTabAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreatePageLayoutTabAction;
|
||||
update: FlatUpdatePageLayoutTabAction;
|
||||
delete: FlatDeletePageLayoutTabAction;
|
||||
};
|
||||
flatEntity: FlatPageLayoutTab;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<PageLayoutTabEntity>;
|
||||
entity: MetadataEntity<'pageLayoutTab'>;
|
||||
};
|
||||
frontComponent: {
|
||||
actions: {
|
||||
create: CreateFrontComponentAction;
|
||||
update: UpdateFrontComponentAction;
|
||||
delete: DeleteFrontComponentAction;
|
||||
flatEntityMaps: FlatFrontComponentMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateFrontComponentAction;
|
||||
update: FlatUpdateFrontComponentAction;
|
||||
delete: UniversalDeleteFrontComponentAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreateFrontComponentAction;
|
||||
update: FlatUpdateFrontComponentAction;
|
||||
delete: FlatDeleteFrontComponentAction;
|
||||
};
|
||||
flatEntity: FlatFrontComponent;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<FrontComponentEntity>;
|
||||
entity: MetadataEntity<'frontComponent'>;
|
||||
};
|
||||
webhook: {
|
||||
actions: {
|
||||
create: CreateWebhookAction;
|
||||
update: UpdateWebhookAction;
|
||||
delete: DeleteWebhookAction;
|
||||
flatEntityMaps: FlatWebhookMaps;
|
||||
universalActions: {
|
||||
create: FlatCreateWebhookAction;
|
||||
update: FlatUpdateWebhookAction;
|
||||
delete: UniversalDeleteWebhookAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreateWebhookAction;
|
||||
update: FlatUpdateWebhookAction;
|
||||
delete: FlatDeleteWebhookAction;
|
||||
};
|
||||
flatEntity: FlatWebhook;
|
||||
universalFlatEntity: UniversalFlatEntityFrom<WebhookEntity>;
|
||||
|
|
|
|||
|
|
@ -14,15 +14,17 @@ export type SyncableFlatEntity = Omit<
|
|||
id: string;
|
||||
};
|
||||
|
||||
type AtomicFlatEntity<TEntity> = Omit<
|
||||
TEntity,
|
||||
| ExtractEntityRelatedEntityProperties<TEntity>
|
||||
| keyof CastRecordTypeOrmDatePropertiesToString<TEntity>
|
||||
>;
|
||||
|
||||
export type FlatEntityFrom<
|
||||
TEntity,
|
||||
// Required to be passed for narrowed type
|
||||
TMetadataName extends AllMetadataName | undefined = undefined,
|
||||
> = Omit<
|
||||
TEntity,
|
||||
| ExtractEntityRelatedEntityProperties<TEntity>
|
||||
| keyof CastRecordTypeOrmDatePropertiesToString<TEntity>
|
||||
> &
|
||||
> = AtomicFlatEntity<TEntity> &
|
||||
CastRecordTypeOrmDatePropertiesToString<TEntity> &
|
||||
AddSuffixToEntityOneToManyProperties<TEntity, 'ids'> &
|
||||
(TEntity extends SyncableEntity
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type AllFlatEntityTypesByMetadataName } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-types-by-metadata-name';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
|
||||
|
||||
export type MetadataFlatEntityMaps<T extends AllMetadataName> = FlatEntityMaps<
|
||||
MetadataFlatEntity<T>
|
||||
>;
|
||||
export type MetadataFlatEntityMaps<
|
||||
T extends AllMetadataName,
|
||||
TWithCustomMapsProperties extends boolean = false,
|
||||
> = TWithCustomMapsProperties extends true
|
||||
? AllFlatEntityTypesByMetadataName[T]['flatEntityMaps']
|
||||
: FlatEntityMaps<MetadataFlatEntity<T>>;
|
||||
|
|
|
|||
|
|
@ -1,28 +1,27 @@
|
|||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type AllFlatEntityTypesByMetadataName } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-types-by-metadata-name';
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
import { type WORKSPACE_MIGRATION_ACTION_TYPE } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/constants/workspace-migration-action-type.constant';
|
||||
|
||||
export type WorkspaceMigrationActionType =
|
||||
| BaseCreateWorkspaceMigrationAction<AllMetadataName>['type']
|
||||
| BaseUpdateWorkspaceMigrationAction<AllMetadataName>['type']
|
||||
| BaseDeleteWorkspaceMigrationAction<AllMetadataName>['type'];
|
||||
keyof typeof WORKSPACE_MIGRATION_ACTION_TYPE;
|
||||
|
||||
export type MetadataWorkspaceMigrationActionsRecord<T extends AllMetadataName> =
|
||||
{
|
||||
[K in WorkspaceMigrationActionType]: MetadataWorkspaceMigrationAction<
|
||||
T,
|
||||
K
|
||||
>[];
|
||||
};
|
||||
// Universal action types (use universal identifiers)
|
||||
export type MetadataUniversalWorkspaceMigrationActionsRecord<
|
||||
T extends AllMetadataName,
|
||||
> = {
|
||||
[K in WorkspaceMigrationActionType]: MetadataUniversalWorkspaceMigrationAction<
|
||||
T,
|
||||
K
|
||||
>[];
|
||||
};
|
||||
|
||||
export type MetadataWorkspaceMigrationAction<
|
||||
export type MetadataUniversalWorkspaceMigrationAction<
|
||||
TMetadataName extends AllMetadataName,
|
||||
TActionType extends WorkspaceMigrationActionType,
|
||||
> = AllFlatEntityTypesByMetadataName[TMetadataName]['actions'][TActionType] extends infer Action
|
||||
? Action extends Array<unknown>
|
||||
? Action[number]
|
||||
: Action
|
||||
: never;
|
||||
> = AllFlatEntityTypesByMetadataName[TMetadataName]['universalActions'][TActionType];
|
||||
|
||||
export type MetadataFlatWorkspaceMigrationAction<
|
||||
TMetadataName extends AllMetadataName,
|
||||
TActionType extends WorkspaceMigrationActionType,
|
||||
> = AllFlatEntityTypesByMetadataName[TMetadataName]['flatActions'][TActionType];
|
||||
|
|
|
|||
|
|
@ -8,19 +8,17 @@ import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity
|
|||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
|
||||
export type FindFlatEntityByUniversalIdentifierOrThrowArgs<
|
||||
T extends SyncableFlatEntity,
|
||||
> = {
|
||||
flatEntityMaps: FlatEntityMaps<T>;
|
||||
universalIdentifier: string;
|
||||
};
|
||||
|
||||
export const findFlatEntityByUniversalIdentifierOrThrow = <
|
||||
T extends SyncableFlatEntity,
|
||||
>({
|
||||
flatEntityMaps,
|
||||
universalIdentifier,
|
||||
}: FindFlatEntityByUniversalIdentifierOrThrowArgs<T>): T => {
|
||||
}: {
|
||||
flatEntityMaps: FlatEntityMaps<T>;
|
||||
universalIdentifier: string;
|
||||
}): T & {
|
||||
id: string;
|
||||
} => {
|
||||
const flatEntity = findFlatEntityByUniversalIdentifier({
|
||||
flatEntityMaps,
|
||||
universalIdentifier,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ export const findFlatEntityByUniversalIdentifier = <
|
|||
}: {
|
||||
flatEntityMaps: FlatEntityMaps<T>;
|
||||
universalIdentifier: string;
|
||||
}): T | undefined => {
|
||||
}): (T & { id: string }) | undefined => {
|
||||
const flatEntityId =
|
||||
flatEntityMaps.idByUniversalIdentifier[universalIdentifier];
|
||||
|
||||
|
|
@ -19,5 +19,12 @@ export const findFlatEntityByUniversalIdentifier = <
|
|||
return;
|
||||
}
|
||||
|
||||
return flatEntityMaps.byId[flatEntityId];
|
||||
const result = flatEntityMaps.byId[flatEntityId];
|
||||
|
||||
return isDefined(result)
|
||||
? {
|
||||
...result,
|
||||
id: flatEntityId,
|
||||
}
|
||||
: undefined;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { findRelationFlatFieldMetadataTargetFlatFieldMetadataOrThrow } from 'src
|
|||
import { isFlatFieldMetadataOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util';
|
||||
import { sanitizeRawUpdateFieldInput } from 'src/engine/metadata-modules/flat-field-metadata/utils/sanitize-raw-update-field-input';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { isStandardMetadata } from 'src/engine/metadata-modules/utils/is-standard-metadata.util';
|
||||
import { belongsToTwentyStandardApp } from 'src/engine/metadata-modules/utils/belongs-to-twenty-standard-app.util';
|
||||
import { mergeUpdateInExistingRecord } from 'src/utils/merge-update-in-existing-record.util';
|
||||
|
||||
type ComputeFlatFieldToUpdateAndRelatedFlatFieldToUpdateReturnType = {
|
||||
|
|
@ -44,7 +44,7 @@ export const computeFlatFieldToUpdateAndRelatedFlatFieldToUpdate = ({
|
|||
isSystemBuild,
|
||||
});
|
||||
|
||||
const isStandardField = isStandardMetadata(fromFlatFieldMetadata);
|
||||
const isStandardField = belongsToTwentyStandardApp(fromFlatFieldMetadata);
|
||||
|
||||
const toFlatFieldMetadata = {
|
||||
...mergeUpdateInExistingRecord({
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({
|
|||
settings: null,
|
||||
defaultValue: commonFlatFieldMetadata.defaultValue as string, // Could this be improved ?
|
||||
options: generateRatingOptions(),
|
||||
universalSettings: null,
|
||||
} satisfies FlatFieldMetadata<typeof createFieldInput.type>,
|
||||
],
|
||||
indexMetadatas: [],
|
||||
|
|
@ -150,6 +151,7 @@ export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({
|
|||
options,
|
||||
defaultValue: commonFlatFieldMetadata.defaultValue as string, // Could this be improved ?
|
||||
settings: null,
|
||||
universalSettings: null,
|
||||
} satisfies FlatFieldMetadata<typeof createFieldInput.type>,
|
||||
],
|
||||
indexMetadatas: [],
|
||||
|
|
|
|||
|
|
@ -73,6 +73,6 @@ export const getDefaultFlatFieldMetadata = ({
|
|||
kanbanAggregateOperationViewUniversalIdentifiers: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
universalSettings: null,
|
||||
universalSettings: settings ?? null,
|
||||
} as const satisfies FlatFieldMetadata;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,8 +4,14 @@ import {
|
|||
} from 'src/engine/metadata-modules/field-metadata/types/composite-field-metadata-type.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isFlatFieldMetadataOfTypes } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-types.util';
|
||||
import { type UniversalFlatFieldMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-field-metadata.type';
|
||||
|
||||
export const isCompositeFlatFieldMetadata = (
|
||||
flatFieldMetadata: FlatFieldMetadata,
|
||||
): flatFieldMetadata is FlatFieldMetadata<CompositeFieldMetadataType> =>
|
||||
isFlatFieldMetadataOfTypes(flatFieldMetadata, COMPOSITE_FIELD_TYPES);
|
||||
|
||||
export const isCompositeUniversalFlatFieldMetadata = (
|
||||
universalFlatFieldMetadata: UniversalFlatFieldMetadata,
|
||||
): universalFlatFieldMetadata is UniversalFlatFieldMetadata<CompositeFieldMetadataType> =>
|
||||
isFlatFieldMetadataOfTypes(universalFlatFieldMetadata, COMPOSITE_FIELD_TYPES);
|
||||
|
|
|
|||
|
|
@ -4,8 +4,14 @@ import {
|
|||
} from 'src/engine/metadata-modules/field-metadata/types/enum-field-metadata-type.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isFlatFieldMetadataOfTypes } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-types.util';
|
||||
import { type UniversalFlatFieldMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-field-metadata.type';
|
||||
|
||||
export const isEnumFlatFieldMetadata = (
|
||||
flatFieldMetadata: FlatFieldMetadata,
|
||||
): flatFieldMetadata is FlatFieldMetadata<EnumFieldMetadataType> =>
|
||||
isFlatFieldMetadataOfTypes(flatFieldMetadata, ENUM_FIELD_TYPES);
|
||||
|
||||
export const isEnumUniversalFlatFieldMetadata = (
|
||||
universalFlatFieldMetadata: UniversalFlatFieldMetadata,
|
||||
): universalFlatFieldMetadata is UniversalFlatFieldMetadata<EnumFieldMetadataType> =>
|
||||
isFlatFieldMetadataOfTypes(universalFlatFieldMetadata, ENUM_FIELD_TYPES);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import {
|
|||
} from 'src/engine/metadata-modules/field-metadata/types/morph-or-relation-field-metadata-type.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isFlatFieldMetadataOfTypes } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-types.util';
|
||||
import { type UniversalFlatFieldMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-field-metadata.type';
|
||||
|
||||
export const isMorphOrRelationFlatFieldMetadata = (
|
||||
flatFieldMetadata: FlatFieldMetadata,
|
||||
|
|
@ -11,3 +12,10 @@ export const isMorphOrRelationFlatFieldMetadata = (
|
|||
isFlatFieldMetadataOfTypes(flatFieldMetadata, [
|
||||
...MORPH_OR_RELATION_FIELD_TYPES,
|
||||
]);
|
||||
|
||||
export const isMorphOrRelationUniversalFlatFieldMetadata = (
|
||||
universalFlatFieldMetadata: UniversalFlatFieldMetadata,
|
||||
): universalFlatFieldMetadata is UniversalFlatFieldMetadata<MorphOrRelationFieldMetadataType> =>
|
||||
isFlatFieldMetadataOfTypes(universalFlatFieldMetadata, [
|
||||
...MORPH_OR_RELATION_FIELD_TYPES,
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import {
|
|||
import { FLAT_FIELD_METADATA_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-field-metadata/constants/flat-field-metadata-editable-properties.constant';
|
||||
import { type FlatFieldMetadataEditableProperties } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata-editable-properties.constant';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isStandardMetadata } from 'src/engine/metadata-modules/utils/is-standard-metadata.util';
|
||||
import { belongsToTwentyStandardApp } from 'src/engine/metadata-modules/utils/belongs-to-twenty-standard-app.util';
|
||||
|
||||
type SanitizeRawUpdateFieldInputArgs = {
|
||||
rawUpdateFieldInput: UpdateFieldInput;
|
||||
|
|
@ -25,7 +25,7 @@ export const sanitizeRawUpdateFieldInput = ({
|
|||
rawUpdateFieldInput,
|
||||
isSystemBuild,
|
||||
}: SanitizeRawUpdateFieldInputArgs) => {
|
||||
const isStandardField = isStandardMetadata(existingFlatFieldMetadata);
|
||||
const isStandardField = belongsToTwentyStandardApp(existingFlatFieldMetadata);
|
||||
const updatedEditableFieldProperties = extractAndSanitizeObjectStringFields(
|
||||
rawUpdateFieldInput,
|
||||
[
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
import { type FlatNavigationMenuItemMaps } from 'src/engine/metadata-modules/flat-navigation-menu-item/types/flat-navigation-menu-item-maps.type';
|
||||
import { type FlatNavigationMenuItem } from 'src/engine/metadata-modules/flat-navigation-menu-item/types/flat-navigation-menu-item.type';
|
||||
import { removeFlatNavigationMenuItemFromIndex } from 'src/engine/metadata-modules/flat-navigation-menu-item/utils/remove-flat-navigation-menu-item-from-index.util';
|
||||
import { deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/delete-flat-entity-from-flat-entity-maps-through-mutation-or-throw.util';
|
||||
|
||||
export const deleteFlatNavigationMenuItemFromMapsAndIndex = ({
|
||||
flatNavigationMenuItem,
|
||||
flatNavigationMenuItemMaps,
|
||||
}: {
|
||||
flatNavigationMenuItem: FlatNavigationMenuItem;
|
||||
flatNavigationMenuItemMaps: FlatNavigationMenuItemMaps;
|
||||
}): void => {
|
||||
removeFlatNavigationMenuItemFromIndex({
|
||||
flatNavigationMenuItem,
|
||||
flatNavigationMenuItemMaps,
|
||||
});
|
||||
|
||||
deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow({
|
||||
entityToDeleteId: flatNavigationMenuItem.id,
|
||||
flatEntityMapsToMutate: flatNavigationMenuItemMaps,
|
||||
});
|
||||
};
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type MetadataFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { type FlatNavigationMenuItemMaps } from 'src/engine/metadata-modules/flat-navigation-menu-item/types/flat-navigation-menu-item-maps.type';
|
||||
import { type FlatNavigationMenuItem } from 'src/engine/metadata-modules/flat-navigation-menu-item/types/flat-navigation-menu-item.type';
|
||||
import {
|
||||
NavigationMenuItemException,
|
||||
|
|
@ -13,7 +13,7 @@ export const fromDeleteNavigationMenuItemInputToFlatNavigationMenuItemOrThrow =
|
|||
flatNavigationMenuItemMaps,
|
||||
navigationMenuItemId,
|
||||
}: {
|
||||
flatNavigationMenuItemMaps: FlatNavigationMenuItemMaps;
|
||||
flatNavigationMenuItemMaps: MetadataFlatEntityMaps<'navigationMenuItem'>;
|
||||
navigationMenuItemId: string;
|
||||
}): FlatNavigationMenuItem => {
|
||||
const existingFlatNavigationMenuItem = findFlatEntityByIdInFlatEntityMaps({
|
||||
|
|
|
|||
|
|
@ -1,51 +0,0 @@
|
|||
import { type FlatNavigationMenuItemMaps } from 'src/engine/metadata-modules/flat-navigation-menu-item/types/flat-navigation-menu-item-maps.type';
|
||||
import { type FlatNavigationMenuItem } from 'src/engine/metadata-modules/flat-navigation-menu-item/types/flat-navigation-menu-item.type';
|
||||
|
||||
export const removeFlatNavigationMenuItemFromIndex = ({
|
||||
flatNavigationMenuItem,
|
||||
flatNavigationMenuItemMaps,
|
||||
}: {
|
||||
flatNavigationMenuItem: FlatNavigationMenuItem;
|
||||
flatNavigationMenuItemMaps: FlatNavigationMenuItemMaps;
|
||||
}): void => {
|
||||
const userWorkspaceIdKey = flatNavigationMenuItem.userWorkspaceId ?? 'null';
|
||||
const folderIdKey = flatNavigationMenuItem.folderId ?? 'null';
|
||||
|
||||
const itemsArray =
|
||||
flatNavigationMenuItemMaps.byUserWorkspaceIdAndFolderId[
|
||||
userWorkspaceIdKey
|
||||
]?.[folderIdKey];
|
||||
|
||||
if (!itemsArray) {
|
||||
return;
|
||||
}
|
||||
|
||||
const index = itemsArray.findIndex(
|
||||
(item) => item.id === flatNavigationMenuItem.id,
|
||||
);
|
||||
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
itemsArray.splice(index, 1);
|
||||
|
||||
if (itemsArray.length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const userWorkspaceMap =
|
||||
flatNavigationMenuItemMaps.byUserWorkspaceIdAndFolderId[userWorkspaceIdKey];
|
||||
|
||||
if (!userWorkspaceMap) {
|
||||
return;
|
||||
}
|
||||
|
||||
delete userWorkspaceMap[folderIdKey];
|
||||
|
||||
if (Object.keys(userWorkspaceMap).length === 0) {
|
||||
delete flatNavigationMenuItemMaps.byUserWorkspaceIdAndFolderId[
|
||||
userWorkspaceIdKey
|
||||
];
|
||||
}
|
||||
};
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatNavigationMenuItemMaps } from 'src/engine/metadata-modules/flat-navigation-menu-item/types/flat-navigation-menu-item-maps.type';
|
||||
import { type FlatNavigationMenuItem } from 'src/engine/metadata-modules/flat-navigation-menu-item/types/flat-navigation-menu-item.type';
|
||||
import { removeFlatNavigationMenuItemFromIndex } from 'src/engine/metadata-modules/flat-navigation-menu-item/utils/remove-flat-navigation-menu-item-from-index.util';
|
||||
import { replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/replace-flat-entity-in-flat-entity-maps-through-mutation-or-throw.util';
|
||||
|
||||
export const replaceFlatNavigationMenuItemInMapsAndUpdateIndex = ({
|
||||
fromFlatNavigationMenuItem,
|
||||
toFlatNavigationMenuItem,
|
||||
flatNavigationMenuItemMaps,
|
||||
}: {
|
||||
fromFlatNavigationMenuItem: FlatNavigationMenuItem;
|
||||
toFlatNavigationMenuItem: FlatNavigationMenuItem;
|
||||
flatNavigationMenuItemMaps: FlatNavigationMenuItemMaps;
|
||||
}): void => {
|
||||
const oldUserWorkspaceIdKey =
|
||||
fromFlatNavigationMenuItem.userWorkspaceId ?? 'null';
|
||||
const oldFolderIdKey = fromFlatNavigationMenuItem.folderId ?? 'null';
|
||||
const newUserWorkspaceIdKey =
|
||||
toFlatNavigationMenuItem.userWorkspaceId ?? 'null';
|
||||
const newFolderIdKey = toFlatNavigationMenuItem.folderId ?? 'null';
|
||||
|
||||
const groupChanged =
|
||||
oldUserWorkspaceIdKey !== newUserWorkspaceIdKey ||
|
||||
oldFolderIdKey !== newFolderIdKey;
|
||||
|
||||
if (groupChanged) {
|
||||
removeFlatNavigationMenuItemFromIndex({
|
||||
flatNavigationMenuItem: fromFlatNavigationMenuItem,
|
||||
flatNavigationMenuItemMaps,
|
||||
});
|
||||
}
|
||||
|
||||
replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow({
|
||||
flatEntity: toFlatNavigationMenuItem,
|
||||
flatEntityMapsToMutate: flatNavigationMenuItemMaps,
|
||||
});
|
||||
|
||||
if (groupChanged) {
|
||||
if (
|
||||
!flatNavigationMenuItemMaps.byUserWorkspaceIdAndFolderId[
|
||||
newUserWorkspaceIdKey
|
||||
]
|
||||
) {
|
||||
flatNavigationMenuItemMaps.byUserWorkspaceIdAndFolderId[
|
||||
newUserWorkspaceIdKey
|
||||
] = {};
|
||||
}
|
||||
|
||||
if (
|
||||
!flatNavigationMenuItemMaps.byUserWorkspaceIdAndFolderId[
|
||||
newUserWorkspaceIdKey
|
||||
][newFolderIdKey]
|
||||
) {
|
||||
flatNavigationMenuItemMaps.byUserWorkspaceIdAndFolderId[
|
||||
newUserWorkspaceIdKey
|
||||
][newFolderIdKey] = [];
|
||||
}
|
||||
|
||||
flatNavigationMenuItemMaps.byUserWorkspaceIdAndFolderId[
|
||||
newUserWorkspaceIdKey
|
||||
][newFolderIdKey].push(toFlatNavigationMenuItem);
|
||||
} else {
|
||||
const itemsArray =
|
||||
flatNavigationMenuItemMaps.byUserWorkspaceIdAndFolderId[
|
||||
newUserWorkspaceIdKey
|
||||
]?.[newFolderIdKey];
|
||||
|
||||
if (!itemsArray) {
|
||||
return;
|
||||
}
|
||||
|
||||
const index = itemsArray.findIndex(
|
||||
(item) => item.id === toFlatNavigationMenuItem.id,
|
||||
);
|
||||
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedItem =
|
||||
flatNavigationMenuItemMaps.byId[toFlatNavigationMenuItem.id];
|
||||
|
||||
if (!isDefined(updatedItem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
itemsArray[index] = updatedItem;
|
||||
}
|
||||
};
|
||||
|
|
@ -17,7 +17,7 @@ import {
|
|||
ObjectMetadataException,
|
||||
ObjectMetadataExceptionCode,
|
||||
} from 'src/engine/metadata-modules/object-metadata/object-metadata.exception';
|
||||
import { isStandardMetadata } from 'src/engine/metadata-modules/utils/is-standard-metadata.util';
|
||||
import { belongsToTwentyStandardApp } from 'src/engine/metadata-modules/utils/belongs-to-twenty-standard-app.util';
|
||||
import { mergeUpdateInExistingRecord } from 'src/utils/merge-update-in-existing-record.util';
|
||||
|
||||
type FromUpdateObjectInputToFlatObjectMetadataArgs = {
|
||||
|
|
@ -60,7 +60,9 @@ export const fromUpdateObjectInputToFlatObjectMetadataAndRelatedFlatEntities =
|
|||
);
|
||||
}
|
||||
|
||||
const isStandardObject = isStandardMetadata(existingFlatObjectMetadata);
|
||||
const isStandardObject = belongsToTwentyStandardApp(
|
||||
existingFlatObjectMetadata,
|
||||
);
|
||||
const { standardOverrides, updatedEditableObjectProperties } =
|
||||
sanitizeRawUpdateObjectInput({
|
||||
existingFlatObjectMetadata,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import {
|
|||
ObjectMetadataExceptionCode,
|
||||
} from 'src/engine/metadata-modules/object-metadata/object-metadata.exception';
|
||||
import { type ObjectMetadataStandardOverridesProperties } from 'src/engine/metadata-modules/object-metadata/types/object-metadata-standard-overrides-properties.types';
|
||||
import { isStandardMetadata } from 'src/engine/metadata-modules/utils/is-standard-metadata.util';
|
||||
import { belongsToTwentyStandardApp } from 'src/engine/metadata-modules/utils/belongs-to-twenty-standard-app.util';
|
||||
|
||||
type SanitizeRawUpdateObjectInputArgs = {
|
||||
rawUpdateObjectInput: UpdateOneObjectInput;
|
||||
|
|
@ -23,7 +23,9 @@ export const sanitizeRawUpdateObjectInput = ({
|
|||
existingFlatObjectMetadata,
|
||||
rawUpdateObjectInput,
|
||||
}: SanitizeRawUpdateObjectInputArgs) => {
|
||||
const isStandardObject = isStandardMetadata(existingFlatObjectMetadata);
|
||||
const isStandardObject = belongsToTwentyStandardApp(
|
||||
existingFlatObjectMetadata,
|
||||
);
|
||||
const updatedEditableObjectProperties = extractAndSanitizeObjectStringFields(
|
||||
rawUpdateObjectInput.update,
|
||||
[
|
||||
|
|
|
|||
|
|
@ -9,10 +9,7 @@ import {
|
|||
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
|
||||
|
||||
@Entity('frontComponent')
|
||||
export class FrontComponentEntity
|
||||
extends SyncableEntity
|
||||
implements Required<FrontComponentEntity>
|
||||
{
|
||||
export class FrontComponentEntity extends SyncableEntity {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
|
|
|
|||
|
|
@ -95,6 +95,8 @@ export class FrontComponentService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -125,6 +127,11 @@ export class FrontComponentService {
|
|||
input: UpdateFrontComponentInput,
|
||||
workspaceId: string,
|
||||
): Promise<FrontComponentDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatFrontComponentMaps: existingFlatFrontComponentMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -151,6 +158,8 @@ export class FrontComponentService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -178,6 +187,11 @@ export class FrontComponentService {
|
|||
}
|
||||
|
||||
async delete(id: string, workspaceId: string): Promise<FrontComponentDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatFrontComponentMaps: existingFlatFrontComponentMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -204,6 +218,8 @@ export class FrontComponentService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { FileFolder } from 'twenty-shared/types';
|
|||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/services/application.service';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service';
|
||||
import { getLogicFunctionBaseFolderPath } from 'src/engine/core-modules/logic-function/logic-function-build/utils/get-logic-function-base-folder-path.util';
|
||||
import { LogicFunctionLayerService } from 'src/engine/core-modules/logic-function/logic-function-layer/services/logic-function-layer.service';
|
||||
|
|
@ -37,14 +38,23 @@ export class LogicFunctionService {
|
|||
async createOne({
|
||||
input,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
input: Omit<CreateLogicFunctionInput, 'applicationId'> & {
|
||||
logicFunctionLayerId?: string;
|
||||
};
|
||||
ownerFlatApplication?: FlatApplication;
|
||||
workspaceId: string;
|
||||
applicationId?: string;
|
||||
}) {
|
||||
const resolvedOwnerFlatApplication =
|
||||
ownerFlatApplication ??
|
||||
(
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
)
|
||||
).workspaceCustomFlatApplication;
|
||||
|
||||
let logicFunctionToCreateLayerId = input.logicFunctionLayerId;
|
||||
|
||||
if (!isDefined(logicFunctionToCreateLayerId)) {
|
||||
|
|
@ -56,13 +66,6 @@ export class LogicFunctionService {
|
|||
logicFunctionToCreateLayerId = commonLogicFunctionLayerId;
|
||||
}
|
||||
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const flatLogicFunctionToCreate =
|
||||
fromCreateLogicFunctionInputToFlatLogicFunction({
|
||||
createLogicFunctionInput: {
|
||||
|
|
@ -70,8 +73,7 @@ export class LogicFunctionService {
|
|||
logicFunctionLayerId: logicFunctionToCreateLayerId,
|
||||
},
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId:
|
||||
applicationId ?? workspaceCustomFlatApplication.id,
|
||||
ownerFlatApplication: resolvedOwnerFlatApplication,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
|
@ -86,6 +88,8 @@ export class LogicFunctionService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
resolvedOwnerFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -114,13 +118,21 @@ export class LogicFunctionService {
|
|||
id,
|
||||
update,
|
||||
workspaceId,
|
||||
applicationId: _applicationId,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
id: string;
|
||||
update: UpdateLogicFunctionInput['update'];
|
||||
workspaceId: string;
|
||||
applicationId?: string;
|
||||
ownerFlatApplication?: FlatApplication;
|
||||
}) {
|
||||
const resolvedOwnerFlatApplication =
|
||||
ownerFlatApplication ??
|
||||
(
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
)
|
||||
).workspaceCustomFlatApplication;
|
||||
|
||||
const { flatLogicFunctionMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -147,6 +159,8 @@ export class LogicFunctionService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
resolvedOwnerFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -176,12 +190,22 @@ export class LogicFunctionService {
|
|||
workspaceId,
|
||||
applicationId: _applicationId,
|
||||
isSystemBuild = false,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
id: string;
|
||||
workspaceId: string;
|
||||
applicationId?: string;
|
||||
isSystemBuild?: boolean;
|
||||
ownerFlatApplication?: FlatApplication;
|
||||
}): Promise<FlatLogicFunction> {
|
||||
const resolvedOwnerFlatApplication =
|
||||
ownerFlatApplication ??
|
||||
(
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
)
|
||||
).workspaceCustomFlatApplication;
|
||||
|
||||
const { flatLogicFunctionMaps: existingFlatLogicFunctionMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -211,6 +235,8 @@ export class LogicFunctionService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild,
|
||||
applicationUniversalIdentifier:
|
||||
resolvedOwnerFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { DEFAULT_TOOL_INPUT_SCHEMA } from 'src/engine/metadata-modules/logic-function/constants/default-tool-input-schema.constant';
|
||||
import { type CreateLogicFunctionInput } from 'src/engine/metadata-modules/logic-function/dtos/create-logic-function.input';
|
||||
import {
|
||||
|
|
@ -19,13 +20,13 @@ export type FromCreateLogicFunctionInputToFlatLogicFunctionArgs = {
|
|||
logicFunctionLayerId: string;
|
||||
};
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
ownerFlatApplication: FlatApplication;
|
||||
};
|
||||
|
||||
export const fromCreateLogicFunctionInputToFlatLogicFunction = ({
|
||||
createLogicFunctionInput: rawCreateLogicFunctionInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
ownerFlatApplication,
|
||||
}: FromCreateLogicFunctionInputToFlatLogicFunctionArgs): FlatLogicFunction => {
|
||||
const id = v4();
|
||||
const currentDate = new Date();
|
||||
|
|
@ -39,6 +40,9 @@ export const fromCreateLogicFunctionInputToFlatLogicFunction = ({
|
|||
rawCreateLogicFunctionInput.builtHandlerPath ??
|
||||
`${baseFolder}/${DEFAULT_BUILT_HANDLER_PATH}`;
|
||||
|
||||
const universalIdentifier =
|
||||
rawCreateLogicFunctionInput.universalIdentifier ?? v4();
|
||||
|
||||
return {
|
||||
id,
|
||||
cronTriggerSettings: null,
|
||||
|
|
@ -50,12 +54,11 @@ export const fromCreateLogicFunctionInputToFlatLogicFunction = ({
|
|||
handlerName:
|
||||
rawCreateLogicFunctionInput.handlerName ?? DEFAULT_HANDLER_NAME,
|
||||
builtHandlerPath,
|
||||
universalIdentifier:
|
||||
rawCreateLogicFunctionInput.universalIdentifier ?? v4(),
|
||||
universalIdentifier,
|
||||
createdAt: currentDate.toISOString(),
|
||||
updatedAt: currentDate.toISOString(),
|
||||
deletedAt: null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
applicationId: ownerFlatApplication.id,
|
||||
runtime: LogicFunctionRuntime.NODE22,
|
||||
timeoutSeconds: rawCreateLogicFunctionInput.timeoutSeconds ?? 300,
|
||||
logicFunctionLayerId: rawCreateLogicFunctionInput.logicFunctionLayerId,
|
||||
|
|
@ -74,5 +77,9 @@ export const fromCreateLogicFunctionInputToFlatLogicFunction = ({
|
|||
? DEFAULT_TOOL_INPUT_SCHEMA
|
||||
: null,
|
||||
isTool: rawCreateLogicFunctionInput?.isTool ?? false,
|
||||
__universal: {
|
||||
applicationUniversalIdentifier: ownerFlatApplication.universalIdentifier,
|
||||
universalIdentifier,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -184,6 +184,8 @@ export class NavigationMenuItemService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -223,6 +225,11 @@ export class NavigationMenuItemService {
|
|||
authApiKeyId?: string;
|
||||
authApplicationId?: string;
|
||||
}): Promise<NavigationMenuItemDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatNavigationMenuItemMaps: existingFlatNavigationMenuItemMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -266,6 +273,8 @@ export class NavigationMenuItemService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -305,6 +314,11 @@ export class NavigationMenuItemService {
|
|||
authApiKeyId?: string;
|
||||
authApplicationId?: string;
|
||||
}): Promise<NavigationMenuItemDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatNavigationMenuItemMaps: existingFlatNavigationMenuItemMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -339,6 +353,8 @@ export class NavigationMenuItemService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
|
|||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/services/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { fromDeleteNavigationMenuItemInputToFlatNavigationMenuItemOrThrow } from 'src/engine/metadata-modules/flat-navigation-menu-item/utils/from-delete-navigation-menu-item-input-to-flat-navigation-menu-item-or-throw.util';
|
||||
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
|
||||
|
|
@ -12,12 +13,18 @@ export class NavigationMenuItemDeletionService {
|
|||
constructor(
|
||||
private readonly workspaceManyOrAllFlatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
async deleteNavigationMenuItemsForDeletedRecords(
|
||||
deletedRecordIds: string[],
|
||||
workspaceId: string,
|
||||
): Promise<void> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatNavigationMenuItemMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -62,6 +69,8 @@ export class NavigationMenuItemDeletionService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: true,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { fromArrayToUniqueKeyRecord, isDefined } from 'twenty-shared/utils';
|
|||
import { FindManyOptions, FindOneOptions, Repository } from 'typeorm';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/services/application.service';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
|
|
@ -56,10 +57,20 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
|||
async updateOneObject({
|
||||
updateObjectInput,
|
||||
workspaceId,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
updateObjectInput: UpdateOneObjectInput;
|
||||
ownerFlatApplication?: FlatApplication;
|
||||
}): Promise<FlatObjectMetadata> {
|
||||
const resolvedOwnerFlatApplication =
|
||||
ownerFlatApplication ??
|
||||
(
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
)
|
||||
).workspaceCustomFlatApplication;
|
||||
|
||||
const {
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
flatIndexMaps: existingFlatIndexMaps,
|
||||
|
|
@ -125,6 +136,8 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
resolvedOwnerFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -166,15 +179,18 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
|||
deleteObjectInput,
|
||||
workspaceId,
|
||||
isSystemBuild = false,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
deleteObjectInput: DeleteOneObjectInput;
|
||||
workspaceId: string;
|
||||
isSystemBuild?: boolean;
|
||||
ownerFlatApplication?: FlatApplication;
|
||||
}): Promise<FlatObjectMetadata> {
|
||||
const deletedObjectMetadataDtos = await this.deleteManyObjectMetadatas({
|
||||
deleteObjectInputs: [deleteObjectInput],
|
||||
workspaceId,
|
||||
isSystemBuild,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
|
||||
if (deletedObjectMetadataDtos.length !== 1) {
|
||||
|
|
@ -193,15 +209,25 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
|||
workspaceId,
|
||||
deleteObjectInputs,
|
||||
isSystemBuild = false,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
deleteObjectInputs: DeleteOneObjectInput[];
|
||||
workspaceId: string;
|
||||
isSystemBuild?: boolean;
|
||||
ownerFlatApplication?: FlatApplication;
|
||||
}): Promise<FlatObjectMetadata[]> {
|
||||
if (deleteObjectInputs.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const resolvedOwnerFlatApplication =
|
||||
ownerFlatApplication ??
|
||||
(
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
)
|
||||
).workspaceCustomFlatApplication;
|
||||
|
||||
const { flatObjectMetadataMaps, flatFieldMetadataMaps, flatIndexMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -296,6 +322,8 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild,
|
||||
applicationUniversalIdentifier:
|
||||
resolvedOwnerFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -312,15 +340,11 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
|||
async createOneObject({
|
||||
createObjectInput,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
createObjectInput: CreateObjectInput;
|
||||
workspaceId: string;
|
||||
/**
|
||||
* @deprecated do not use call validateBuildAndRunWorkspaceMigration contextually
|
||||
* when interacting with another application than workspace custom one
|
||||
* */
|
||||
applicationId?: string;
|
||||
ownerFlatApplication?: FlatApplication;
|
||||
}): Promise<FlatObjectMetadata> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
|
|
@ -328,27 +352,18 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
|||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const resolvedOwnerFlatApplication =
|
||||
ownerFlatApplication ?? workspaceCustomFlatApplication;
|
||||
|
||||
const {
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
featureFlagsMap: existingFeatureFlagsMap,
|
||||
flatApplicationMaps,
|
||||
} = await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
'flatObjectMetadataMaps',
|
||||
'featureFlagsMap',
|
||||
'flatApplicationMaps',
|
||||
]);
|
||||
|
||||
const ownerFlatApplication = isDefined(applicationId)
|
||||
? flatApplicationMaps.byId[applicationId]
|
||||
: workspaceCustomFlatApplication;
|
||||
|
||||
if (!isDefined(ownerFlatApplication)) {
|
||||
throw new ObjectMetadataException(
|
||||
`Could not find related application ${applicationId}`,
|
||||
ObjectMetadataExceptionCode.APPLICATION_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const {
|
||||
flatObjectMetadataToCreate,
|
||||
flatIndexMetadataToCreate,
|
||||
|
|
@ -357,7 +372,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
|||
} = fromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCreate({
|
||||
createObjectInput,
|
||||
workspaceId,
|
||||
flatApplication: ownerFlatApplication,
|
||||
flatApplication: resolvedOwnerFlatApplication,
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
existingFeatureFlagsMap,
|
||||
});
|
||||
|
|
@ -426,6 +441,8 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
resolvedOwnerFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import {
|
||||
type FieldMetadataSettingsMapping,
|
||||
FieldMetadataType,
|
||||
type NonNullableRequired,
|
||||
} from 'twenty-shared/types';
|
||||
|
|
@ -419,6 +420,12 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
|||
};
|
||||
|
||||
const searchVectorFieldId = v4();
|
||||
const searchVectorSettings: FieldMetadataSettingsMapping['TS_VECTOR'] = {
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
nameField ? [nameField] : [],
|
||||
),
|
||||
generatedType: 'STORED',
|
||||
};
|
||||
const searchVectorField: FlatFieldMetadata<FieldMetadataType.TS_VECTOR> = {
|
||||
type: FieldMetadataType.TS_VECTOR,
|
||||
mainGroupByFieldMetadataViewIds: [],
|
||||
|
|
@ -450,12 +457,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
|||
standardOverrides: null,
|
||||
relationTargetFieldMetadataId: null,
|
||||
relationTargetObjectMetadataId: null,
|
||||
settings: {
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
nameField ? [nameField] : [],
|
||||
),
|
||||
generatedType: 'STORED',
|
||||
},
|
||||
settings: searchVectorSettings,
|
||||
morphId: null,
|
||||
applicationId,
|
||||
applicationUniversalIdentifier,
|
||||
|
|
@ -467,7 +469,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
|||
kanbanAggregateOperationViewUniversalIdentifiers: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
universalSettings: null,
|
||||
universalSettings: searchVectorSettings,
|
||||
};
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -155,6 +155,8 @@ export class PageLayoutTabService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -196,6 +198,11 @@ export class PageLayoutTabService {
|
|||
workspaceId: string;
|
||||
updateData: UpdatePageLayoutTabInput;
|
||||
}): Promise<Omit<PageLayoutTabDTO, 'widgets'>> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatPageLayoutTabMaps: existingFlatPageLayoutTabMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -227,6 +234,8 @@ export class PageLayoutTabService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -266,6 +275,11 @@ export class PageLayoutTabService {
|
|||
id: string;
|
||||
workspaceId: string;
|
||||
}): Promise<boolean> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatPageLayoutTabMaps: existingFlatPageLayoutTabMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -292,6 +306,8 @@ export class PageLayoutTabService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,11 @@ export class PageLayoutWidgetService {
|
|||
operations: WidgetMigrationOperations;
|
||||
errorMessage: string;
|
||||
}): Promise<void> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
|
|
@ -74,6 +79,8 @@ export class PageLayoutWidgetService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -112,6 +112,8 @@ export class PageLayoutDuplicationService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -137,6 +137,8 @@ export class PageLayoutUpdateService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -192,6 +192,8 @@ export class PageLayoutService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -227,6 +229,11 @@ export class PageLayoutService {
|
|||
workspaceId: string;
|
||||
updateData: UpdatePageLayoutInput;
|
||||
}): Promise<Omit<PageLayoutDTO, 'tabs'>> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatPageLayoutMaps: existingFlatPageLayoutMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -258,6 +265,8 @@ export class PageLayoutService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -301,6 +310,11 @@ export class PageLayoutService {
|
|||
workspaceId: string;
|
||||
isLinkedDashboardAlreadyDestroyed?: boolean;
|
||||
}): Promise<boolean> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatPageLayoutMaps: existingFlatPageLayoutMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -327,6 +341,8 @@ export class PageLayoutService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -361,6 +377,11 @@ export class PageLayoutService {
|
|||
return true;
|
||||
}
|
||||
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatPageLayoutMaps: existingFlatPageLayoutMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -388,6 +409,8 @@ export class PageLayoutService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -102,6 +102,8 @@ export class RoleTargetService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -129,6 +131,13 @@ export class RoleTargetService {
|
|||
}
|
||||
|
||||
async delete({ id, workspaceId }: DeleteRoleTargetInput): Promise<void> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatRoleTargetMaps: existingFlatRoleTargetMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -154,6 +163,8 @@ export class RoleTargetService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ export class RoleResolver {
|
|||
return await this.roleService.createRole({
|
||||
workspaceId,
|
||||
input: createRoleInput,
|
||||
applicationId: workspaceCustomFlatApplication.id,
|
||||
ownerFlatApplication: workspaceCustomFlatApplication,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import { msg } from '@lingui/core/macro';
|
|||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/services/application.service';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
|
|
@ -37,6 +39,7 @@ export class RoleService {
|
|||
@InjectRepository(RoleEntity)
|
||||
private readonly roleRepository: Repository<RoleEntity>,
|
||||
private readonly userRoleService: UserRoleService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
public async getWorkspaceRoles(workspaceId: string): Promise<RoleEntity[]> {
|
||||
|
|
@ -99,16 +102,16 @@ export class RoleService {
|
|||
public async createRole({
|
||||
input,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
input: CreateRoleInput;
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
ownerFlatApplication: FlatApplication;
|
||||
}): Promise<RoleDTO> {
|
||||
const flatRoleToCreate = fromCreateRoleInputToFlatRoleToCreate({
|
||||
createRoleInput: input,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
applicationId: ownerFlatApplication.id,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
|
@ -123,6 +126,8 @@ export class RoleService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
ownerFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -152,10 +157,20 @@ export class RoleService {
|
|||
public async updateRole({
|
||||
input,
|
||||
workspaceId,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
input: UpdateRoleInput;
|
||||
workspaceId: string;
|
||||
ownerFlatApplication?: FlatApplication;
|
||||
}): Promise<RoleDTO> {
|
||||
const resolvedOwnerFlatApplication =
|
||||
ownerFlatApplication ??
|
||||
(
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
)
|
||||
).workspaceCustomFlatApplication;
|
||||
|
||||
const { flatRoleMaps: existingFlatRoleMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -181,6 +196,8 @@ export class RoleService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
resolvedOwnerFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -210,14 +227,17 @@ export class RoleService {
|
|||
public async deleteRole({
|
||||
roleId,
|
||||
workspaceId,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
roleId: string;
|
||||
workspaceId: string;
|
||||
ownerFlatApplication?: FlatApplication;
|
||||
}): Promise<RoleDTO> {
|
||||
const deletedRoles = await this.deleteManyRoles({
|
||||
ids: [roleId],
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
|
||||
const [deletedRole] = deletedRoles;
|
||||
|
|
@ -229,15 +249,25 @@ export class RoleService {
|
|||
ids,
|
||||
workspaceId,
|
||||
isSystemBuild = false,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
ids: string[];
|
||||
workspaceId: string;
|
||||
isSystemBuild?: boolean;
|
||||
ownerFlatApplication?: FlatApplication;
|
||||
}): Promise<RoleDTO[]> {
|
||||
if (ids.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const resolvedOwnerFlatApplication =
|
||||
ownerFlatApplication ??
|
||||
(
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
)
|
||||
).workspaceCustomFlatApplication;
|
||||
|
||||
const { flatRoleMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -303,6 +333,8 @@ export class RoleService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild,
|
||||
applicationUniversalIdentifier:
|
||||
resolvedOwnerFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -318,9 +350,9 @@ export class RoleService {
|
|||
|
||||
public async createMemberRole({
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
applicationId: string;
|
||||
ownerFlatApplication: FlatApplication;
|
||||
workspaceId: string;
|
||||
}): Promise<RoleDTO> {
|
||||
return this.createRole({
|
||||
|
|
@ -338,17 +370,17 @@ export class RoleService {
|
|||
canBeAssignedToAgents: false,
|
||||
canBeAssignedToApiKeys: false,
|
||||
},
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
public async createGuestRole({
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
ownerFlatApplication: FlatApplication;
|
||||
}): Promise<RoleDTO> {
|
||||
return this.createRole({
|
||||
input: {
|
||||
|
|
@ -366,7 +398,7 @@ export class RoleService {
|
|||
canBeAssignedToApiKeys: false,
|
||||
},
|
||||
workspaceId,
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -459,6 +459,11 @@ export class RowLevelPermissionPredicateService {
|
|||
groupsToUpdate: FlatRowLevelPermissionPredicateGroup[];
|
||||
groupsToDelete: FlatRowLevelPermissionPredicateGroup[];
|
||||
}): Promise<void> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
|
|
@ -479,6 +484,8 @@ export class RowLevelPermissionPredicateService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -92,6 +92,8 @@ export class SkillService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -122,6 +124,11 @@ export class SkillService {
|
|||
input: UpdateSkillInput,
|
||||
workspaceId: string,
|
||||
): Promise<SkillDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatSkillMaps: existingFlatSkillMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -147,6 +154,8 @@ export class SkillService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -174,6 +183,11 @@ export class SkillService {
|
|||
}
|
||||
|
||||
async delete(id: string, workspaceId: string): Promise<SkillDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatSkillMaps: existingFlatSkillMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -199,6 +213,8 @@ export class SkillService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -251,6 +267,11 @@ export class SkillService {
|
|||
}
|
||||
|
||||
async activate(id: string, workspaceId: string): Promise<SkillDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatSkillMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -282,6 +303,8 @@ export class SkillService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -309,6 +332,11 @@ export class SkillService {
|
|||
}
|
||||
|
||||
async deactivate(id: string, workspaceId: string): Promise<SkillDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatSkillMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -340,6 +368,8 @@ export class SkillService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications';
|
||||
import { type UniversalSyncableFlatEntity } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
|
||||
|
||||
export const belongsToTwentyStandardApp = <
|
||||
T extends UniversalSyncableFlatEntity,
|
||||
>({
|
||||
applicationUniversalIdentifier,
|
||||
}: T) =>
|
||||
applicationUniversalIdentifier ===
|
||||
TWENTY_STANDARD_APPLICATION.universalIdentifier;
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
|
||||
export const isStandardMetadata = (
|
||||
metadata:
|
||||
| Pick<FlatObjectMetadata, 'standardId' | 'isCustom'>
|
||||
| Pick<FlatFieldMetadata, 'standardId' | 'isCustom'>,
|
||||
) => !metadata.isCustom && isDefined(metadata.standardId);
|
||||
|
|
@ -97,6 +97,8 @@ export class ViewFieldV2Service {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -128,6 +130,13 @@ export class ViewFieldV2Service {
|
|||
workspaceId: string;
|
||||
updateViewFieldInput: UpdateViewFieldInput;
|
||||
}): Promise<ViewFieldDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatViewFieldMaps: existingFlatViewFieldMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -154,6 +163,8 @@ export class ViewFieldV2Service {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -187,6 +198,13 @@ export class ViewFieldV2Service {
|
|||
deleteViewFieldInput: DeleteViewFieldInput;
|
||||
workspaceId: string;
|
||||
}): Promise<ViewFieldDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatViewFieldMaps: existingFlatViewFieldMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -213,6 +231,8 @@ export class ViewFieldV2Service {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -246,6 +266,13 @@ export class ViewFieldV2Service {
|
|||
destroyViewFieldInput: DestroyViewFieldInput;
|
||||
workspaceId: string;
|
||||
}): Promise<ViewFieldDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatViewFieldMaps: existingFlatViewFieldMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -272,6 +299,8 @@ export class ViewFieldV2Service {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ export class ViewFilterGroupService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -101,6 +103,13 @@ export class ViewFilterGroupService {
|
|||
workspaceId: string;
|
||||
updateViewFilterGroupInput: UpdateViewFilterGroupInput;
|
||||
}): Promise<ViewFilterGroupDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatViewFilterGroupMaps: existingFlatViewFilterGroupMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -127,6 +136,8 @@ export class ViewFilterGroupService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -162,6 +173,13 @@ export class ViewFilterGroupService {
|
|||
deleteViewFilterGroupInput: DeleteViewFilterGroupInput;
|
||||
workspaceId: string;
|
||||
}): Promise<ViewFilterGroupDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatViewFilterGroupMaps: existingFlatViewFilterGroupMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -190,6 +208,8 @@ export class ViewFilterGroupService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -225,6 +245,13 @@ export class ViewFilterGroupService {
|
|||
destroyViewFilterGroupInput: DestroyViewFilterGroupInput;
|
||||
workspaceId: string;
|
||||
}): Promise<ViewFilterGroupDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatViewFilterGroupMaps: existingFlatViewFilterGroupMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -251,6 +278,8 @@ export class ViewFilterGroupService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ export class ViewFilterService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -97,6 +99,13 @@ export class ViewFilterService {
|
|||
workspaceId: string;
|
||||
updateViewFilterInput: UpdateViewFilterInput;
|
||||
}): Promise<ViewFilterDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatViewFilterMaps: existingFlatViewFilterMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -123,6 +132,8 @@ export class ViewFilterService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -156,6 +167,13 @@ export class ViewFilterService {
|
|||
deleteViewFilterInput: DeleteViewFilterInput;
|
||||
workspaceId: string;
|
||||
}): Promise<ViewFilterDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatViewFilterMaps: existingFlatViewFilterMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -184,6 +202,8 @@ export class ViewFilterService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -217,6 +237,13 @@ export class ViewFilterService {
|
|||
destroyViewFilterInput: DestroyViewFilterInput;
|
||||
workspaceId: string;
|
||||
}): Promise<ViewFilterDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatViewFilterMaps: existingFlatViewFilterMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -243,6 +270,8 @@ export class ViewFilterService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -117,6 +117,8 @@ export class ViewGroupService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -148,6 +150,13 @@ export class ViewGroupService {
|
|||
workspaceId: string;
|
||||
updateViewGroupInput: UpdateViewGroupInput;
|
||||
}): Promise<ViewGroupDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatViewGroupMaps: existingFlatViewGroupMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -174,6 +183,8 @@ export class ViewGroupService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -207,6 +218,13 @@ export class ViewGroupService {
|
|||
deleteViewGroupInput: DeleteViewGroupInput;
|
||||
workspaceId: string;
|
||||
}): Promise<ViewGroupDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatViewGroupMaps: existingFlatViewGroupMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -235,6 +253,8 @@ export class ViewGroupService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -268,6 +288,13 @@ export class ViewGroupService {
|
|||
destroyViewGroupInput: DestroyViewGroupInput;
|
||||
workspaceId: string;
|
||||
}): Promise<ViewGroupDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatViewGroupMaps: existingFlatViewGroupMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -294,6 +321,8 @@ export class ViewGroupService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,8 @@ export class ViewService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -122,6 +124,13 @@ export class ViewService {
|
|||
workspaceId: string;
|
||||
userWorkspaceId?: string;
|
||||
}): Promise<ViewDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const {
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
|
||||
|
|
@ -163,6 +172,8 @@ export class ViewService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -196,6 +207,13 @@ export class ViewService {
|
|||
deleteViewInput: DeleteViewInput;
|
||||
workspaceId: string;
|
||||
}): Promise<ViewDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatViewMaps: existingFlatViewMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -222,6 +240,8 @@ export class ViewService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -255,6 +275,13 @@ export class ViewService {
|
|||
destroyViewInput: DestroyViewInput;
|
||||
workspaceId: string;
|
||||
}): Promise<ViewDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatViewMaps: existingFlatViewMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -280,6 +307,8 @@ export class ViewService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -125,6 +125,8 @@ export class WebhookService {
|
|||
},
|
||||
},
|
||||
workspaceId,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -155,6 +157,11 @@ export class WebhookService {
|
|||
input: UpdateWebhookInput,
|
||||
workspaceId: string,
|
||||
): Promise<WebhookDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const normalizedInput = {
|
||||
...input,
|
||||
update: {
|
||||
|
|
@ -190,6 +197,8 @@ export class WebhookService {
|
|||
},
|
||||
},
|
||||
workspaceId,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -217,6 +226,11 @@ export class WebhookService {
|
|||
}
|
||||
|
||||
async delete(id: string, workspaceId: string): Promise<WebhookDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatWebhookMaps: existingFlatWebhookMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
|
|
@ -241,6 +255,8 @@ export class WebhookService {
|
|||
},
|
||||
},
|
||||
workspaceId,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { type UniversalFlatObjectMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-object-metadata.type';
|
||||
|
||||
import { computeTableName } from './compute-table-name.util';
|
||||
|
||||
export const computeObjectTargetTable = (
|
||||
objectMetadata: Pick<FlatObjectMetadata, 'nameSingular' | 'isCustom'>,
|
||||
objectMetadata: Pick<
|
||||
UniversalFlatObjectMetadata,
|
||||
'nameSingular' | 'isCustom'
|
||||
>,
|
||||
) => {
|
||||
return computeTableName(objectMetadata.nameSingular, objectMetadata.isCustom);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ import { type FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/
|
|||
import { type FlatWorkspaceMemberMaps } from 'src/engine/core-modules/user/types/flat-workspace-member-maps.type';
|
||||
import { type FlatRoleTargetByAgentIdMaps } from 'src/engine/metadata-modules/flat-agent/types/flat-role-target-by-agent-id-maps.type';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { type LogicFunctionLayerCacheMaps } from 'src/engine/metadata-modules/logic-function-layer/types/logic-function-layer-cache-maps.type';
|
||||
import { type UserWorkspaceRoleMap } from 'src/engine/metadata-modules/role-target/services/workspace-user-workspace-role-map-cache.service';
|
||||
import { type FlatRowLevelPermissionPredicateGroupMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group-maps.type';
|
||||
import { type FlatRowLevelPermissionPredicateMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-maps.type';
|
||||
import { type LogicFunctionLayerCacheMaps } from 'src/engine/metadata-modules/logic-function-layer/types/logic-function-layer-cache-maps.type';
|
||||
|
||||
export const WORKSPACE_CACHE_KEYS_V2 = {
|
||||
flatObjectMetadataMaps: 'flat-maps:object-metadata',
|
||||
|
|
@ -64,7 +64,8 @@ export type AdditionalCacheDataMaps = {
|
|||
applicationVariableMaps: ApplicationVariableCacheMaps;
|
||||
};
|
||||
|
||||
export type WorkspaceCacheDataMap = AllFlatEntityMaps & AdditionalCacheDataMaps;
|
||||
export type WorkspaceCacheDataMap = AllFlatEntityMaps<true> &
|
||||
AdditionalCacheDataMaps;
|
||||
|
||||
export type WorkspaceCacheKeyName = keyof WorkspaceCacheDataMap;
|
||||
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ export class DevSeederPermissionsService {
|
|||
|
||||
const guestRole = await this.roleService.createGuestRole({
|
||||
workspaceId,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
ownerFlatApplication: twentyStandardFlatApplication,
|
||||
});
|
||||
|
||||
await this.userRoleService.assignRoleToManyUserWorkspace({
|
||||
|
|
@ -99,7 +99,7 @@ export class DevSeederPermissionsService {
|
|||
|
||||
const limitedRole = await this.createLimitedRoleForSeedWorkspace({
|
||||
workspaceId,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
ownerFlatApplication: twentyStandardFlatApplication,
|
||||
});
|
||||
|
||||
await this.userRoleService.assignRoleToManyUserWorkspace({
|
||||
|
|
@ -130,7 +130,7 @@ export class DevSeederPermissionsService {
|
|||
|
||||
const memberRole = await this.roleService.createMemberRole({
|
||||
workspaceId,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
ownerFlatApplication: twentyStandardFlatApplication,
|
||||
});
|
||||
|
||||
await this.coreDataSource
|
||||
|
|
@ -150,14 +150,14 @@ export class DevSeederPermissionsService {
|
|||
}
|
||||
|
||||
private async createLimitedRoleForSeedWorkspace({
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
workspaceId,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
ownerFlatApplication: FlatApplication;
|
||||
}) {
|
||||
const customRole = await this.roleService.createRole({
|
||||
applicationId,
|
||||
ownerFlatApplication,
|
||||
workspaceId,
|
||||
input: {
|
||||
label: 'Object-restricted',
|
||||
|
|
|
|||
|
|
@ -123,6 +123,8 @@ export class TwentyStandardApplicationService {
|
|||
},
|
||||
workspaceId,
|
||||
isSystemBuild: true,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -194,6 +196,8 @@ export class TwentyStandardApplicationService {
|
|||
additionalCacheDataMaps: {
|
||||
featureFlagsMap,
|
||||
},
|
||||
applicationUniversalIdentifier:
|
||||
twentyStandardFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import {
|
||||
type FieldMetadataDefaultValue,
|
||||
type FieldMetadataSettings,
|
||||
type FieldMetadataComplexOption,
|
||||
type FieldMetadataDefaultOption,
|
||||
type FieldMetadataDefaultValue,
|
||||
type FieldMetadataSettings,
|
||||
type FieldMetadataType,
|
||||
} from 'twenty-shared/types';
|
||||
import { v4 } from 'uuid';
|
||||
|
|
@ -110,6 +110,6 @@ export const createStandardFieldFlatMetadata = <
|
|||
kanbanAggregateOperationViewUniversalIdentifiers: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
universalSettings: null,
|
||||
universalSettings: settings ?? null,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -133,6 +133,6 @@ export const createStandardRelationFieldFlatMetadata = <
|
|||
kanbanAggregateOperationViewUniversalIdentifiers: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
universalSettings: null,
|
||||
universalSettings: settings,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ export class WorkspaceManagerService {
|
|||
|
||||
const memberRole = await this.roleService.createMemberRole({
|
||||
workspaceId,
|
||||
applicationId: workspaceCustomFlatApplication.id,
|
||||
ownerFlatApplication: workspaceCustomFlatApplication,
|
||||
});
|
||||
|
||||
await this.workspaceRepository.update(workspaceId, {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,14 @@ export const workspaceMigrationRunnerExceptionFormatter = (
|
|||
...(isExecutionFailed && {
|
||||
action: error.action,
|
||||
errors: {
|
||||
...(error.errors?.actionTranspilation && {
|
||||
actionTranspilation: {
|
||||
message: error.errors.actionTranspilation.message,
|
||||
code:
|
||||
(error.errors.actionTranspilation as { code?: string })?.code ??
|
||||
'INTERNAL_SERVER_ERROR',
|
||||
},
|
||||
}),
|
||||
...(error.errors?.metadata && {
|
||||
metadata: {
|
||||
message: error.errors.metadata.message,
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
|||
fromToAllFlatEntityMaps,
|
||||
dependencyAllFlatEntityMaps,
|
||||
additionalCacheDataMaps,
|
||||
applicationUniversalIdentifier,
|
||||
}: WorkspaceMigrationOrchestratorBuildArgs): Promise<
|
||||
| WorkspaceMigrationOrchestratorFailedResult
|
||||
| WorkspaceMigrationOrchestratorSuccessfulResult
|
||||
|
|
@ -985,6 +986,7 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
|||
return {
|
||||
status: 'success',
|
||||
workspaceMigration: {
|
||||
applicationUniversalIdentifier,
|
||||
actions: [
|
||||
// Object and fields and indexes
|
||||
...aggregatedOrchestratorActionsReport.index.delete,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ type ValidateBuildAndRunWorkspaceMigrationFromMatriceArgs = {
|
|||
[P in AllMetadataName]?: FlatEntityToCreateDeleteUpdate<P>;
|
||||
};
|
||||
isSystemBuild?: boolean;
|
||||
applicationUniversalIdentifier: string;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
|
|
@ -123,6 +124,7 @@ export class WorkspaceMigrationValidateBuildAndRunService {
|
|||
private async computeFromToAllFlatEntityMapsAndBuildOptions({
|
||||
allFlatEntityOperationByMetadataName,
|
||||
workspaceId,
|
||||
applicationUniversalIdentifier,
|
||||
}: ValidateBuildAndRunWorkspaceMigrationFromMatriceArgs): Promise<{
|
||||
fromToAllFlatEntityMaps: FromToAllFlatEntityMaps;
|
||||
inferDeletionFromMissingEntities: InferDeletionFromMissingEntities;
|
||||
|
|
@ -136,6 +138,7 @@ export class WorkspaceMigrationValidateBuildAndRunService {
|
|||
} = await this.computeAllRelatedFlatEntityMaps({
|
||||
allFlatEntityOperationByMetadataName,
|
||||
workspaceId,
|
||||
applicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
const fromToAllFlatEntityMaps: FromToAllFlatEntityMaps = {};
|
||||
|
|
@ -216,6 +219,7 @@ export class WorkspaceMigrationValidateBuildAndRunService {
|
|||
allFlatEntityOperationByMetadataName: allFlatEntities,
|
||||
workspaceId,
|
||||
isSystemBuild = false,
|
||||
applicationUniversalIdentifier,
|
||||
}: ValidateBuildAndRunWorkspaceMigrationFromMatriceArgs): Promise<
|
||||
WorkspaceMigrationOrchestratorFailedResult | undefined
|
||||
> {
|
||||
|
|
@ -227,9 +231,11 @@ export class WorkspaceMigrationValidateBuildAndRunService {
|
|||
} = await this.computeFromToAllFlatEntityMapsAndBuildOptions({
|
||||
allFlatEntityOperationByMetadataName: allFlatEntities,
|
||||
workspaceId,
|
||||
applicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
return await this.validateBuildAndRunWorkspaceMigrationFromTo({
|
||||
applicationUniversalIdentifier,
|
||||
buildOptions: {
|
||||
isSystemBuild,
|
||||
inferDeletionFromMissingEntities,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type MetadataFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity-maps.type';
|
||||
import { type OrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
|
||||
export type AggregateOrchestratorActionsReportArgs = {
|
||||
orchestratorActionsReport: OrchestratorActionsReport;
|
||||
flatFieldMetadataMaps?: FlatEntityMaps<FlatFieldMetadata>;
|
||||
flatFieldMetadataMaps?: MetadataFlatEntityMaps<'fieldMetadata'>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@ import { type FromTo } from 'twenty-shared/types';
|
|||
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import {
|
||||
type MetadataWorkspaceMigrationActionsRecord,
|
||||
type MetadataUniversalWorkspaceMigrationActionsRecord,
|
||||
type WorkspaceMigrationActionType,
|
||||
} from 'src/engine/metadata-modules/flat-entity/types/metadata-workspace-migration-action.type';
|
||||
import { type WorkspaceMigrationBuilderAdditionalCacheDataMaps } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-builder-additional-cache-data-maps.type';
|
||||
import { type FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/types/failed-flat-entity-validation.type';
|
||||
import { type WorkspaceMigrationBuilderOptions } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration-builder-options.type';
|
||||
import { type WorkspaceMigration } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration';
|
||||
import { type WorkspaceMigrationBuilderOptions } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration-builder-options.type';
|
||||
|
||||
export type FromToAllFlatEntityMaps = {
|
||||
[P in keyof AllFlatEntityMaps]?: FromTo<AllFlatEntityMaps[P]>;
|
||||
|
|
@ -21,6 +21,7 @@ export type WorkspaceMigrationOrchestratorBuildArgs = {
|
|||
fromToAllFlatEntityMaps: FromToAllFlatEntityMaps;
|
||||
dependencyAllFlatEntityMaps?: Partial<AllFlatEntityMaps>;
|
||||
additionalCacheDataMaps: WorkspaceMigrationBuilderAdditionalCacheDataMaps;
|
||||
applicationUniversalIdentifier: string;
|
||||
};
|
||||
|
||||
export type OrchestratorFailureReport = {
|
||||
|
|
@ -31,7 +32,7 @@ export type OrchestratorFailureReport = {
|
|||
};
|
||||
|
||||
export type OrchestratorActionsReport = {
|
||||
[P in AllMetadataName]: MetadataWorkspaceMigrationActionsRecord<P>;
|
||||
[P in AllMetadataName]: MetadataUniversalWorkspaceMigrationActionsRecord<P>;
|
||||
};
|
||||
|
||||
export type WorkspaceMigrationOrchestratorFailedResult = {
|
||||
|
|
|
|||
|
|
@ -1,146 +0,0 @@
|
|||
import { type Equal, type Expect } from 'twenty-shared/testing';
|
||||
import { type SerializedRelation } from 'twenty-shared/types';
|
||||
|
||||
import { type ContainsSerializedRelation } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/contains-serialized-relation.type';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||
type EmptyObject = {};
|
||||
|
||||
// ContainsSerializedRelation checks for SerializedRelation in object properties
|
||||
// It recurses into nested objects and arrays, but stops at primitives
|
||||
|
||||
// Direct property tests
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars
|
||||
type DirectPropertyAssertions = [
|
||||
// Direct SerializedRelation property
|
||||
Expect<
|
||||
Equal<ContainsSerializedRelation<{ targetId: SerializedRelation }>, true>
|
||||
>,
|
||||
|
||||
// Nullable SerializedRelation property
|
||||
Expect<
|
||||
Equal<
|
||||
ContainsSerializedRelation<{ targetId: SerializedRelation | null }>,
|
||||
true
|
||||
>
|
||||
>,
|
||||
|
||||
// Optional SerializedRelation property
|
||||
Expect<
|
||||
Equal<ContainsSerializedRelation<{ targetId?: SerializedRelation }>, true>
|
||||
>,
|
||||
|
||||
// Array of SerializedRelation
|
||||
Expect<
|
||||
Equal<ContainsSerializedRelation<{ ids: SerializedRelation[] }>, true>
|
||||
>,
|
||||
|
||||
// Plain properties only - no SerializedRelation
|
||||
Expect<
|
||||
Equal<ContainsSerializedRelation<{ name: string; count: number }>, false>
|
||||
>,
|
||||
|
||||
// Empty object
|
||||
Expect<Equal<ContainsSerializedRelation<EmptyObject>, false>>,
|
||||
];
|
||||
|
||||
// Nested object tests - should recurse
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars
|
||||
type NestedObjectAssertions = [
|
||||
// Nested object with SerializedRelation
|
||||
Expect<
|
||||
Equal<
|
||||
ContainsSerializedRelation<{
|
||||
nested: { targetId: SerializedRelation };
|
||||
}>,
|
||||
true
|
||||
>
|
||||
>,
|
||||
|
||||
// Deeply nested SerializedRelation
|
||||
Expect<
|
||||
Equal<
|
||||
ContainsSerializedRelation<{
|
||||
level1: { level2: { level3: { id: SerializedRelation } } };
|
||||
}>,
|
||||
true
|
||||
>
|
||||
>,
|
||||
|
||||
// Nested object without SerializedRelation
|
||||
Expect<
|
||||
Equal<
|
||||
ContainsSerializedRelation<{
|
||||
nested: { name: string; count: number };
|
||||
}>,
|
||||
false
|
||||
>
|
||||
>,
|
||||
];
|
||||
|
||||
// Nested array tests - should recurse
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars
|
||||
type NestedArrayAssertions = [
|
||||
// Array of objects with SerializedRelation
|
||||
Expect<
|
||||
Equal<
|
||||
ContainsSerializedRelation<{
|
||||
items: { targetId: SerializedRelation }[];
|
||||
}>,
|
||||
true
|
||||
>
|
||||
>,
|
||||
|
||||
// 2D array of SerializedRelation
|
||||
Expect<
|
||||
Equal<ContainsSerializedRelation<{ matrix: SerializedRelation[][] }>, true>
|
||||
>,
|
||||
|
||||
// Array of plain objects
|
||||
Expect<
|
||||
Equal<
|
||||
ContainsSerializedRelation<{
|
||||
items: { name: string }[];
|
||||
}>,
|
||||
false
|
||||
>
|
||||
>,
|
||||
|
||||
// 2D array of strings
|
||||
Expect<Equal<ContainsSerializedRelation<{ matrix: string[][] }>, false>>,
|
||||
];
|
||||
|
||||
// Primitive types - should return false (not objects)
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars
|
||||
type PrimitiveAssertions = [
|
||||
Expect<Equal<ContainsSerializedRelation<string>, false>>,
|
||||
Expect<Equal<ContainsSerializedRelation<number>, false>>,
|
||||
Expect<Equal<ContainsSerializedRelation<boolean>, false>>,
|
||||
Expect<Equal<ContainsSerializedRelation<null>, false>>,
|
||||
Expect<Equal<ContainsSerializedRelation<undefined>, false>>,
|
||||
];
|
||||
|
||||
// Real-world tests
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars
|
||||
type RealWorldAssertions = [
|
||||
// Settings with SerializedRelation
|
||||
Expect<
|
||||
Equal<
|
||||
ContainsSerializedRelation<{
|
||||
relationType?: string;
|
||||
junctionTargetFieldId?: SerializedRelation;
|
||||
}>,
|
||||
true
|
||||
>
|
||||
>,
|
||||
|
||||
// Workflow config with nested SerializedRelation in array
|
||||
Expect<
|
||||
Equal<
|
||||
ContainsSerializedRelation<{
|
||||
steps: { assigneeId: SerializedRelation; action: string }[];
|
||||
}>,
|
||||
true
|
||||
>
|
||||
>,
|
||||
];
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
import {
|
||||
type IsEmptyObject,
|
||||
type IsNever,
|
||||
type IsSerializedRelation,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
type ContainsSerializedRelationInner<T> = T extends unknown
|
||||
? IsNever<T> extends true
|
||||
? false
|
||||
: unknown extends T
|
||||
? false
|
||||
: IsSerializedRelation<T> extends true
|
||||
? true
|
||||
: T extends readonly (infer U)[]
|
||||
? ContainsSerializedRelationInner<U>
|
||||
: T extends object
|
||||
? IsEmptyObject<T> extends true
|
||||
? false
|
||||
: ContainsSerializedRelationInner<T[keyof T]>
|
||||
: false
|
||||
: never;
|
||||
|
||||
export type ContainsSerializedRelation<T> =
|
||||
true extends ContainsSerializedRelationInner<T> ? true : false;
|
||||
|
|
@ -8,7 +8,6 @@ import { type FromMetadataEntityToMetadataName } from 'src/engine/metadata-modul
|
|||
import { type MetadataManyToOneJoinColumn } from 'src/engine/metadata-modules/flat-entity/types/metadata-many-to-one-join-column.type';
|
||||
import { type SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
|
||||
import { type AllJsonbPropertiesWithSerializedPropertiesForMetadataName } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/constants/all-jsonb-properties-with-serialized-relation-by-metadata-name.constant';
|
||||
import { type ContainsSerializedRelation } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/contains-serialized-relation.type';
|
||||
import { type FormatRecordSerializedRelationProperties } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/format-record-serialized-relation-properties.type';
|
||||
|
||||
export type UniversalSyncableFlatEntity = Omit<
|
||||
|
|
@ -33,11 +32,9 @@ export type UniversalFlatEntityExtraProperties<
|
|||
} & {
|
||||
[P in AllJsonbPropertiesWithSerializedPropertiesForMetadataName<TMetadataName> &
|
||||
keyof TEntity &
|
||||
string as `universal${Capitalize<P>}`]: true extends ContainsSerializedRelation<
|
||||
NonNullable<TEntity[P]>
|
||||
>
|
||||
? FormatRecordSerializedRelationProperties<TEntity[P]>
|
||||
: null;
|
||||
string as `universal${Capitalize<P>}`]: FormatRecordSerializedRelationProperties<
|
||||
TEntity[P]
|
||||
>;
|
||||
};
|
||||
|
||||
export type UniversalFlatEntityFrom<
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type UniversalFlatEntityFrom } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
|
||||
|
||||
export type UniversalFlatObjectMetadata = UniversalFlatEntityFrom<
|
||||
Omit<ObjectMetadataEntity, 'targetRelationFields' | 'dataSourceId'>,
|
||||
'objectMetadata'
|
||||
> & {
|
||||
// NOTE: below fields are not reflected on the final UniversalFlatEntity either they should we should define a common source
|
||||
// TODO remove once https://github.com/twentyhq/core-team-issues/issues/2172 has been resolved
|
||||
labelIdentifierFieldMetadataUniversalIdentifier: string | null;
|
||||
imageIdentifierFieldMetadataUniversalIdentifier: string | null;
|
||||
};
|
||||
|
|
@ -153,6 +153,7 @@ exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect an upd
|
|||
"updatedFlatEntityMaps": {
|
||||
"byId": {
|
||||
"field-id-1": {
|
||||
"universalIdentifier": "universal-identifier-1",
|
||||
"updates": [
|
||||
{
|
||||
"from": false,
|
||||
|
|
@ -283,6 +284,7 @@ exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect create
|
|||
"updatedFlatEntityMaps": {
|
||||
"byId": {
|
||||
"field-id-1": {
|
||||
"universalIdentifier": "universal-identifier-1",
|
||||
"updates": [
|
||||
{
|
||||
"from": true,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,278 @@
|
|||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
|
||||
import { createEmptyOrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/constant/empty-orchestrator-actions-report.constant';
|
||||
import { type OrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
import { aggregateNonRelationFieldsIntoObjectActions } from 'src/engine/workspace-manager/workspace-migration/utils/aggregate-non-relation-fields-into-object-actions.util';
|
||||
import { type UniversalCreateFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
import { type UniversalCreateObjectAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/object/types/workspace-migration-object-action';
|
||||
|
||||
describe('aggregateNonRelationFieldsIntoObjectActions', () => {
|
||||
it('should merge non-relation fields into matching create-object actions', () => {
|
||||
const objectUniversalId = 'object-1';
|
||||
const fieldUniversalId = 'field-1';
|
||||
|
||||
const input: OrchestratorActionsReport = {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
objectMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntity: getFlatObjectMetadataMock({
|
||||
universalIdentifier: objectUniversalId,
|
||||
nameSingular: 'testObject',
|
||||
namePlural: 'testObjects',
|
||||
}),
|
||||
universalFlatFieldMetadatas: [],
|
||||
} satisfies UniversalCreateObjectAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
fieldMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
universalFlatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: fieldUniversalId,
|
||||
objectMetadataId: 'object-metadata-id',
|
||||
objectMetadataUniversalIdentifier: objectUniversalId,
|
||||
type: FieldMetadataType.TEXT,
|
||||
name: 'testField',
|
||||
}),
|
||||
],
|
||||
fieldIdByUniversalIdentifier: {
|
||||
[fieldUniversalId]: 'generated-field-id',
|
||||
},
|
||||
} satisfies UniversalCreateFieldAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
};
|
||||
|
||||
const result = aggregateNonRelationFieldsIntoObjectActions({
|
||||
orchestratorActionsReport: input,
|
||||
});
|
||||
|
||||
// Field should be merged into object action
|
||||
expect(result.objectMetadata.create).toMatchObject([
|
||||
{
|
||||
universalFlatFieldMetadatas: [
|
||||
{ universalIdentifier: fieldUniversalId },
|
||||
],
|
||||
fieldIdByUniversalIdentifier: {
|
||||
[fieldUniversalId]: 'generated-field-id',
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
// No remaining field actions
|
||||
expect(result.fieldMetadata.create).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should keep relation fields in separate create-field actions', () => {
|
||||
const objectUniversalId = 'object-1';
|
||||
const relationFieldUniversalId = 'relation-field-1';
|
||||
const targetFieldUniversalId = 'target-field-1';
|
||||
|
||||
const input: OrchestratorActionsReport = {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
objectMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntity: getFlatObjectMetadataMock({
|
||||
universalIdentifier: objectUniversalId,
|
||||
nameSingular: 'testObject',
|
||||
namePlural: 'testObjects',
|
||||
}),
|
||||
universalFlatFieldMetadatas: [],
|
||||
} satisfies UniversalCreateObjectAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
fieldMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
universalFlatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: relationFieldUniversalId,
|
||||
objectMetadataId: 'object-metadata-id',
|
||||
objectMetadataUniversalIdentifier: objectUniversalId,
|
||||
type: FieldMetadataType.RELATION,
|
||||
name: 'relationField',
|
||||
relationTargetFieldMetadataUniversalIdentifier:
|
||||
targetFieldUniversalId,
|
||||
relationTargetObjectMetadataUniversalIdentifier: 'other-object',
|
||||
}),
|
||||
],
|
||||
fieldIdByUniversalIdentifier: {
|
||||
[relationFieldUniversalId]: 'generated-relation-field-id',
|
||||
},
|
||||
} satisfies UniversalCreateFieldAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
};
|
||||
|
||||
const result = aggregateNonRelationFieldsIntoObjectActions({
|
||||
orchestratorActionsReport: input,
|
||||
});
|
||||
|
||||
// Object action should have no fields merged
|
||||
expect(result.objectMetadata.create).toMatchObject([
|
||||
{ universalFlatFieldMetadatas: [] },
|
||||
]);
|
||||
|
||||
// Relation field should remain in field actions
|
||||
expect(result.fieldMetadata.create).toMatchObject([
|
||||
{
|
||||
universalFlatFieldMetadatas: [
|
||||
{ universalIdentifier: relationFieldUniversalId },
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should keep fields for existing objects in separate create-field actions', () => {
|
||||
const existingObjectUniversalId = 'existing-object';
|
||||
const fieldUniversalId = 'field-for-existing-object';
|
||||
|
||||
const input: OrchestratorActionsReport = {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
objectMetadata: {
|
||||
create: [], // No objects being created
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
fieldMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
universalFlatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: fieldUniversalId,
|
||||
objectMetadataId: 'existing-object-metadata-id',
|
||||
objectMetadataUniversalIdentifier: existingObjectUniversalId,
|
||||
type: FieldMetadataType.TEXT,
|
||||
name: 'fieldForExistingObject',
|
||||
}),
|
||||
],
|
||||
fieldIdByUniversalIdentifier: {
|
||||
[fieldUniversalId]: 'generated-field-id',
|
||||
},
|
||||
} satisfies UniversalCreateFieldAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
};
|
||||
|
||||
const result = aggregateNonRelationFieldsIntoObjectActions({
|
||||
orchestratorActionsReport: input,
|
||||
});
|
||||
|
||||
// No object actions
|
||||
expect(result.objectMetadata.create).toHaveLength(0);
|
||||
|
||||
// Field should remain in field actions (no matching object to merge into)
|
||||
expect(result.fieldMetadata.create).toMatchObject([
|
||||
{
|
||||
universalFlatFieldMetadatas: [
|
||||
{ universalIdentifier: fieldUniversalId },
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handle mixed relation and non-relation fields', () => {
|
||||
const objectUniversalId = 'object-1';
|
||||
const textFieldUniversalId = 'text-field';
|
||||
const relationFieldUniversalId = 'relation-field';
|
||||
|
||||
const input: OrchestratorActionsReport = {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
objectMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntity: getFlatObjectMetadataMock({
|
||||
universalIdentifier: objectUniversalId,
|
||||
nameSingular: 'testObject',
|
||||
namePlural: 'testObjects',
|
||||
}),
|
||||
universalFlatFieldMetadatas: [],
|
||||
} satisfies UniversalCreateObjectAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
fieldMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
universalFlatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: textFieldUniversalId,
|
||||
objectMetadataId: 'object-metadata-id',
|
||||
objectMetadataUniversalIdentifier: objectUniversalId,
|
||||
type: FieldMetadataType.TEXT,
|
||||
name: 'textField',
|
||||
}),
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: relationFieldUniversalId,
|
||||
objectMetadataId: 'object-metadata-id',
|
||||
objectMetadataUniversalIdentifier: objectUniversalId,
|
||||
type: FieldMetadataType.RELATION,
|
||||
name: 'relationField',
|
||||
relationTargetFieldMetadataUniversalIdentifier: 'target-field',
|
||||
relationTargetObjectMetadataUniversalIdentifier: 'other-object',
|
||||
}),
|
||||
],
|
||||
fieldIdByUniversalIdentifier: {
|
||||
[textFieldUniversalId]: 'text-field-id',
|
||||
[relationFieldUniversalId]: 'relation-field-id',
|
||||
},
|
||||
} satisfies UniversalCreateFieldAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
};
|
||||
|
||||
const result = aggregateNonRelationFieldsIntoObjectActions({
|
||||
orchestratorActionsReport: input,
|
||||
});
|
||||
|
||||
// Text field should be merged into object action
|
||||
expect(result.objectMetadata.create).toMatchObject([
|
||||
{
|
||||
universalFlatFieldMetadatas: [
|
||||
{ universalIdentifier: textFieldUniversalId },
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
// Relation field should remain in field actions
|
||||
expect(result.fieldMetadata.create).toMatchObject([
|
||||
{
|
||||
universalFlatFieldMetadatas: [
|
||||
{ universalIdentifier: relationFieldUniversalId },
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
@ -1,491 +0,0 @@
|
|||
import {
|
||||
eachTestingContextFilter,
|
||||
type EachTestingContext,
|
||||
} from 'twenty-shared/testing';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
|
||||
import { createEmptyOrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/constant/empty-orchestrator-actions-report.constant';
|
||||
import { type OrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
import { aggregateOrchestratorActionsReportCreateObjectAndCreateFieldActions } from 'src/engine/workspace-manager/workspace-migration/utils/aggregate-orchestrator-actions-report-create-object-and-create-field-actions.util';
|
||||
import { type CreateFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
import { type CreateObjectAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/object/types/workspace-migration-object-action';
|
||||
|
||||
type CreateAggregationTestCase = EachTestingContext<{
|
||||
input: OrchestratorActionsReport;
|
||||
expected: {
|
||||
expectCreateFieldActionPerObjectMetadataId: Record<string, number>;
|
||||
expectCreateObjectActionPerObjectMetadataId: Record<string, number>;
|
||||
};
|
||||
}>;
|
||||
describe('aggregateOrchestratorActionsReportCreateObjectAndCreateFieldActions', () => {
|
||||
const testCases: CreateAggregationTestCase[] = [
|
||||
{
|
||||
title:
|
||||
'should aggregate single object with multiple fields into one object action',
|
||||
context: {
|
||||
input: {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
objectMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntity: getFlatObjectMetadataMock({
|
||||
universalIdentifier: 'object-1',
|
||||
id: 'object-1',
|
||||
nameSingular: 'user',
|
||||
namePlural: 'users',
|
||||
}),
|
||||
flatFieldMetadatas: [],
|
||||
} satisfies CreateObjectAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
fieldMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-1',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-1',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-1',
|
||||
name: 'firstName',
|
||||
}),
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-2',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-2',
|
||||
name: 'lastName',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
} satisfies OrchestratorActionsReport,
|
||||
expected: {
|
||||
expectCreateFieldActionPerObjectMetadataId: {},
|
||||
expectCreateObjectActionPerObjectMetadataId: {
|
||||
'object-1': 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title:
|
||||
'should keep separate field actions when no matching object action exists',
|
||||
context: {
|
||||
input: {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
objectMetadata: {
|
||||
create: [],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
fieldMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-1',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-1',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-1',
|
||||
name: 'firstName',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-1',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-2',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-2',
|
||||
name: 'secondName',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-1',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-3',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-3',
|
||||
name: 'lastName',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
} satisfies OrchestratorActionsReport,
|
||||
expected: {
|
||||
expectCreateFieldActionPerObjectMetadataId: {
|
||||
'object-1': 1,
|
||||
},
|
||||
expectCreateObjectActionPerObjectMetadataId: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'should handle multiple objects with their respective fields',
|
||||
context: {
|
||||
input: {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
objectMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntity: getFlatObjectMetadataMock({
|
||||
universalIdentifier: 'object-1',
|
||||
id: 'object-1',
|
||||
nameSingular: 'user',
|
||||
namePlural: 'users',
|
||||
}),
|
||||
flatFieldMetadatas: [],
|
||||
} satisfies CreateObjectAction,
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntity: getFlatObjectMetadataMock({
|
||||
universalIdentifier: 'object-2',
|
||||
id: 'object-2',
|
||||
nameSingular: 'company',
|
||||
namePlural: 'companies',
|
||||
}),
|
||||
flatFieldMetadatas: [],
|
||||
} satisfies CreateObjectAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
fieldMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-1',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-1',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-1',
|
||||
name: 'firstName',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-2',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-2',
|
||||
objectMetadataId: 'object-2',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-2',
|
||||
name: 'name',
|
||||
}),
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-3',
|
||||
objectMetadataId: 'object-2',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-3',
|
||||
name: 'industry',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
} satisfies OrchestratorActionsReport,
|
||||
expected: {
|
||||
expectCreateFieldActionPerObjectMetadataId: {},
|
||||
expectCreateObjectActionPerObjectMetadataId: {
|
||||
'object-1': 1,
|
||||
'object-2': 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title:
|
||||
'should handle mixed scenario with some fields merged and some kept separate',
|
||||
context: {
|
||||
input: {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
objectMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntity: getFlatObjectMetadataMock({
|
||||
universalIdentifier: 'object-1',
|
||||
id: 'object-1',
|
||||
nameSingular: 'user',
|
||||
namePlural: 'users',
|
||||
}),
|
||||
flatFieldMetadatas: [],
|
||||
} satisfies CreateObjectAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
fieldMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-1',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-1',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-1',
|
||||
name: 'firstName',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-2',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-2',
|
||||
objectMetadataId: 'object-2',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-2',
|
||||
name: 'orphanField',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
} satisfies OrchestratorActionsReport,
|
||||
expected: {
|
||||
expectCreateFieldActionPerObjectMetadataId: {
|
||||
'object-2': 1,
|
||||
},
|
||||
expectCreateObjectActionPerObjectMetadataId: {
|
||||
'object-1': 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title:
|
||||
'should aggregate multiple field actions for the same object when no create object action exists',
|
||||
context: {
|
||||
input: {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
objectMetadata: {
|
||||
create: [],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
fieldMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-1',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-1',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-1',
|
||||
name: 'firstName',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-1',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-2',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-2',
|
||||
name: 'lastName',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-1',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-3',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: 'field-3',
|
||||
name: 'email',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
} satisfies OrchestratorActionsReport,
|
||||
expected: {
|
||||
expectCreateFieldActionPerObjectMetadataId: {
|
||||
'object-1': 1,
|
||||
},
|
||||
expectCreateObjectActionPerObjectMetadataId: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'should handle empty actions report',
|
||||
context: {
|
||||
input: createEmptyOrchestratorActionsReport(),
|
||||
expected: {
|
||||
expectCreateFieldActionPerObjectMetadataId: {},
|
||||
expectCreateObjectActionPerObjectMetadataId: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title:
|
||||
'should not merge create_field actions containing relation fields into create_object',
|
||||
context: {
|
||||
input: {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
objectMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntity: getFlatObjectMetadataMock({
|
||||
universalIdentifier: 'object-1',
|
||||
id: 'object-1',
|
||||
nameSingular: 'attachment',
|
||||
namePlural: 'attachments',
|
||||
}),
|
||||
flatFieldMetadatas: [],
|
||||
} satisfies CreateObjectAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
fieldMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: 'object-1',
|
||||
flatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: 'field-1',
|
||||
objectMetadataId: 'object-1',
|
||||
type: FieldMetadataType.RELATION,
|
||||
id: 'field-1',
|
||||
name: 'author',
|
||||
}),
|
||||
],
|
||||
} satisfies CreateFieldAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
} satisfies OrchestratorActionsReport,
|
||||
expected: {
|
||||
expectCreateFieldActionPerObjectMetadataId: {
|
||||
'object-1': 1,
|
||||
},
|
||||
expectCreateObjectActionPerObjectMetadataId: {
|
||||
'object-1': 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
test.each(eachTestingContextFilter(testCases))(
|
||||
'$title',
|
||||
({ context: { input, expected } }) => {
|
||||
const result =
|
||||
aggregateOrchestratorActionsReportCreateObjectAndCreateFieldActions({
|
||||
orchestratorActionsReport: input,
|
||||
});
|
||||
|
||||
const fieldActions = result.fieldMetadata.create as CreateFieldAction[];
|
||||
const fieldActionCounts = fieldActions.reduce(
|
||||
(acc, action) => {
|
||||
acc[action.objectMetadataId] =
|
||||
(acc[action.objectMetadataId] || 0) + 1;
|
||||
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, number>,
|
||||
);
|
||||
|
||||
const objectActions = result.objectMetadata
|
||||
.create as CreateObjectAction[];
|
||||
const objectActionCounts = objectActions.reduce(
|
||||
(acc, action) => {
|
||||
acc[action.flatEntity.id] = (acc[action.flatEntity.id] || 0) + 1;
|
||||
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, number>,
|
||||
);
|
||||
|
||||
Object.entries(
|
||||
expected.expectCreateFieldActionPerObjectMetadataId,
|
||||
).forEach(([objectId, expectedCount]) => {
|
||||
expect(fieldActionCounts[objectId]).toBe(expectedCount);
|
||||
});
|
||||
|
||||
Object.entries(
|
||||
expected.expectCreateObjectActionPerObjectMetadataId,
|
||||
).forEach(([objectId, expectedCount]) => {
|
||||
expect(objectActionCounts[objectId]).toBe(expectedCount);
|
||||
});
|
||||
|
||||
// Check total counts
|
||||
const expectedTotalFieldActions = Object.values(
|
||||
expected.expectCreateFieldActionPerObjectMetadataId,
|
||||
).reduce((sum, count) => sum + count, 0);
|
||||
const expectedTotalObjectActions = Object.values(
|
||||
expected.expectCreateObjectActionPerObjectMetadataId,
|
||||
).reduce((sum, count) => sum + count, 0);
|
||||
|
||||
expect(fieldActions).toHaveLength(expectedTotalFieldActions);
|
||||
expect(objectActions).toHaveLength(expectedTotalObjectActions);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
@ -8,7 +8,7 @@ import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-m
|
|||
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-metadata/constants/search-vector-field.constants';
|
||||
import { createEmptyOrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/constant/empty-orchestrator-actions-report.constant';
|
||||
import { aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFieldActions } from 'src/engine/workspace-manager/workspace-migration/utils/aggregate-orchestrator-actions-report-deprioritize-search-vector-update-field-actions.util';
|
||||
import { type UpdateFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
import { type UniversalUpdateFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
|
||||
describe('aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFieldActions', () => {
|
||||
it('should move searchVector update actions to the end of the update list', () => {
|
||||
|
|
@ -20,7 +20,7 @@ describe('aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFieldA
|
|||
{
|
||||
type: 'update',
|
||||
metadataName: 'fieldMetadata',
|
||||
entityId: 'search-vector-field-1',
|
||||
universalIdentifier: 'search-vector-field-1',
|
||||
updates: [
|
||||
{
|
||||
property: 'label',
|
||||
|
|
@ -28,11 +28,11 @@ describe('aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFieldA
|
|||
to: 'Updated Search Vector',
|
||||
},
|
||||
],
|
||||
} satisfies UpdateFieldAction,
|
||||
} satisfies UniversalUpdateFieldAction,
|
||||
{
|
||||
type: 'update',
|
||||
metadataName: 'fieldMetadata',
|
||||
entityId: 'regular-field-1',
|
||||
universalIdentifier: 'regular-field-1',
|
||||
updates: [
|
||||
{
|
||||
property: 'label',
|
||||
|
|
@ -40,11 +40,11 @@ describe('aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFieldA
|
|||
to: 'Updated First Name',
|
||||
},
|
||||
],
|
||||
} satisfies UpdateFieldAction,
|
||||
} satisfies UniversalUpdateFieldAction,
|
||||
{
|
||||
type: 'update',
|
||||
metadataName: 'fieldMetadata',
|
||||
entityId: 'regular-field-2',
|
||||
universalIdentifier: 'regular-field-2',
|
||||
updates: [
|
||||
{
|
||||
property: 'label',
|
||||
|
|
@ -52,7 +52,7 @@ describe('aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFieldA
|
|||
to: 'Updated Last Name',
|
||||
},
|
||||
],
|
||||
} satisfies UpdateFieldAction,
|
||||
} satisfies UniversalUpdateFieldAction,
|
||||
],
|
||||
delete: [],
|
||||
},
|
||||
|
|
@ -98,11 +98,13 @@ describe('aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFieldA
|
|||
);
|
||||
|
||||
const updateFieldActions = result.fieldMetadata
|
||||
.update as UpdateFieldAction[];
|
||||
.update as UniversalUpdateFieldAction[];
|
||||
|
||||
const actualEntityIds = updateFieldActions.map((action) => action.entityId);
|
||||
const actualUniversalIdentifiers = updateFieldActions.map(
|
||||
(action) => action.universalIdentifier,
|
||||
);
|
||||
|
||||
expect(actualEntityIds).toEqual([
|
||||
expect(actualUniversalIdentifiers).toEqual([
|
||||
'regular-field-1',
|
||||
'regular-field-2',
|
||||
'search-vector-field-1',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,282 @@
|
|||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { createEmptyOrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/constant/empty-orchestrator-actions-report.constant';
|
||||
import { type OrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
import { aggregateRelationFieldPairs } from 'src/engine/workspace-manager/workspace-migration/utils/aggregate-relation-field-pairs.util';
|
||||
import { type UniversalCreateFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
|
||||
describe('aggregateRelationFieldPairs', () => {
|
||||
it('should bundle relation field pairs into single action with merged fieldIdByUniversalIdentifier', () => {
|
||||
const attachmentObjectId = 'attachment-object';
|
||||
const taskObjectId = 'task-object';
|
||||
const targetTaskFieldId = 'target-task-field';
|
||||
const attachmentsFieldId = 'attachments-field';
|
||||
|
||||
const input: OrchestratorActionsReport = {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
fieldMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
universalFlatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: targetTaskFieldId,
|
||||
objectMetadataId: 'attachment-object-metadata-id',
|
||||
objectMetadataUniversalIdentifier: attachmentObjectId,
|
||||
type: FieldMetadataType.RELATION,
|
||||
name: 'targetTask',
|
||||
relationTargetFieldMetadataUniversalIdentifier:
|
||||
attachmentsFieldId,
|
||||
relationTargetObjectMetadataUniversalIdentifier: taskObjectId,
|
||||
}),
|
||||
],
|
||||
fieldIdByUniversalIdentifier: {
|
||||
[targetTaskFieldId]: 'target-task-generated-id',
|
||||
},
|
||||
} satisfies UniversalCreateFieldAction,
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
universalFlatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: attachmentsFieldId,
|
||||
objectMetadataId: 'task-object-metadata-id',
|
||||
objectMetadataUniversalIdentifier: taskObjectId,
|
||||
type: FieldMetadataType.RELATION,
|
||||
name: 'attachments',
|
||||
relationTargetFieldMetadataUniversalIdentifier:
|
||||
targetTaskFieldId,
|
||||
relationTargetObjectMetadataUniversalIdentifier:
|
||||
attachmentObjectId,
|
||||
}),
|
||||
],
|
||||
fieldIdByUniversalIdentifier: {
|
||||
[attachmentsFieldId]: 'attachments-generated-id',
|
||||
},
|
||||
} satisfies UniversalCreateFieldAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
};
|
||||
|
||||
const result = aggregateRelationFieldPairs({
|
||||
orchestratorActionsReport: input,
|
||||
});
|
||||
|
||||
// Should be bundled into a single action with both fields and merged ID map
|
||||
expect(result.fieldMetadata.create).toMatchObject([
|
||||
{
|
||||
universalFlatFieldMetadatas: [
|
||||
{ universalIdentifier: targetTaskFieldId },
|
||||
{ universalIdentifier: attachmentsFieldId },
|
||||
],
|
||||
fieldIdByUniversalIdentifier: {
|
||||
[targetTaskFieldId]: 'target-task-generated-id',
|
||||
[attachmentsFieldId]: 'attachments-generated-id',
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should keep standalone fields (no relation target) as separate actions', () => {
|
||||
const fieldUniversalId = 'standalone-field';
|
||||
const objectUniversalId = 'some-object';
|
||||
|
||||
const input: OrchestratorActionsReport = {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
fieldMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
universalFlatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: fieldUniversalId,
|
||||
objectMetadataId: 'some-object-metadata-id',
|
||||
objectMetadataUniversalIdentifier: objectUniversalId,
|
||||
type: FieldMetadataType.TEXT,
|
||||
name: 'standaloneField',
|
||||
}),
|
||||
],
|
||||
fieldIdByUniversalIdentifier: {
|
||||
[fieldUniversalId]: 'standalone-field-id',
|
||||
},
|
||||
} satisfies UniversalCreateFieldAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
};
|
||||
|
||||
const result = aggregateRelationFieldPairs({
|
||||
orchestratorActionsReport: input,
|
||||
});
|
||||
|
||||
// Should remain as single action
|
||||
expect(result.fieldMetadata.create).toMatchObject([
|
||||
{
|
||||
universalFlatFieldMetadatas: [
|
||||
{ universalIdentifier: fieldUniversalId },
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handle relation field with target not being created (existing field)', () => {
|
||||
const relationFieldId = 'new-relation-field';
|
||||
const existingTargetFieldId = 'existing-target-field';
|
||||
const objectUniversalId = 'some-object';
|
||||
|
||||
const input: OrchestratorActionsReport = {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
fieldMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
universalFlatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: relationFieldId,
|
||||
objectMetadataId: 'some-object-metadata-id',
|
||||
objectMetadataUniversalIdentifier: objectUniversalId,
|
||||
type: FieldMetadataType.RELATION,
|
||||
name: 'relationToExisting',
|
||||
relationTargetFieldMetadataUniversalIdentifier:
|
||||
existingTargetFieldId,
|
||||
relationTargetObjectMetadataUniversalIdentifier: 'other-object',
|
||||
}),
|
||||
],
|
||||
fieldIdByUniversalIdentifier: {
|
||||
[relationFieldId]: 'new-relation-field-id',
|
||||
},
|
||||
} satisfies UniversalCreateFieldAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
};
|
||||
|
||||
const result = aggregateRelationFieldPairs({
|
||||
orchestratorActionsReport: input,
|
||||
});
|
||||
|
||||
// Should remain as single action (target not being created)
|
||||
expect(result.fieldMetadata.create).toMatchObject([
|
||||
{
|
||||
universalFlatFieldMetadatas: [{ universalIdentifier: relationFieldId }],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handle multiple independent relation pairs', () => {
|
||||
const pair1FieldA = 'pair1-field-a';
|
||||
const pair1FieldB = 'pair1-field-b';
|
||||
const pair2FieldA = 'pair2-field-a';
|
||||
const pair2FieldB = 'pair2-field-b';
|
||||
|
||||
const input: OrchestratorActionsReport = {
|
||||
...createEmptyOrchestratorActionsReport(),
|
||||
fieldMetadata: {
|
||||
create: [
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
universalFlatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: pair1FieldA,
|
||||
objectMetadataId: 'object-1-metadata-id',
|
||||
objectMetadataUniversalIdentifier: 'object-1',
|
||||
type: FieldMetadataType.RELATION,
|
||||
name: 'pair1FieldA',
|
||||
relationTargetFieldMetadataUniversalIdentifier: pair1FieldB,
|
||||
relationTargetObjectMetadataUniversalIdentifier: 'object-2',
|
||||
}),
|
||||
],
|
||||
fieldIdByUniversalIdentifier: { [pair1FieldA]: 'id-1a' },
|
||||
} satisfies UniversalCreateFieldAction,
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
universalFlatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: pair1FieldB,
|
||||
objectMetadataId: 'object-2-metadata-id',
|
||||
objectMetadataUniversalIdentifier: 'object-2',
|
||||
type: FieldMetadataType.RELATION,
|
||||
name: 'pair1FieldB',
|
||||
relationTargetFieldMetadataUniversalIdentifier: pair1FieldA,
|
||||
relationTargetObjectMetadataUniversalIdentifier: 'object-1',
|
||||
}),
|
||||
],
|
||||
fieldIdByUniversalIdentifier: { [pair1FieldB]: 'id-1b' },
|
||||
} satisfies UniversalCreateFieldAction,
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
universalFlatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: pair2FieldA,
|
||||
objectMetadataId: 'object-3-metadata-id',
|
||||
objectMetadataUniversalIdentifier: 'object-3',
|
||||
type: FieldMetadataType.RELATION,
|
||||
name: 'pair2FieldA',
|
||||
relationTargetFieldMetadataUniversalIdentifier: pair2FieldB,
|
||||
relationTargetObjectMetadataUniversalIdentifier: 'object-4',
|
||||
}),
|
||||
],
|
||||
fieldIdByUniversalIdentifier: { [pair2FieldA]: 'id-2a' },
|
||||
} satisfies UniversalCreateFieldAction,
|
||||
{
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
universalFlatFieldMetadatas: [
|
||||
getFlatFieldMetadataMock({
|
||||
universalIdentifier: pair2FieldB,
|
||||
objectMetadataId: 'object-4-metadata-id',
|
||||
objectMetadataUniversalIdentifier: 'object-4',
|
||||
type: FieldMetadataType.RELATION,
|
||||
name: 'pair2FieldB',
|
||||
relationTargetFieldMetadataUniversalIdentifier: pair2FieldA,
|
||||
relationTargetObjectMetadataUniversalIdentifier: 'object-3',
|
||||
}),
|
||||
],
|
||||
fieldIdByUniversalIdentifier: { [pair2FieldB]: 'id-2b' },
|
||||
} satisfies UniversalCreateFieldAction,
|
||||
],
|
||||
update: [],
|
||||
delete: [],
|
||||
},
|
||||
};
|
||||
|
||||
const result = aggregateRelationFieldPairs({
|
||||
orchestratorActionsReport: input,
|
||||
});
|
||||
|
||||
// Should result in 2 bundled actions (one per pair), each with merged fieldIdByUniversalIdentifier
|
||||
expect(result.fieldMetadata.create).toMatchObject([
|
||||
{
|
||||
universalFlatFieldMetadatas: [
|
||||
{ universalIdentifier: pair1FieldA },
|
||||
{ universalIdentifier: pair1FieldB },
|
||||
],
|
||||
fieldIdByUniversalIdentifier: {
|
||||
[pair1FieldA]: 'id-1a',
|
||||
[pair1FieldB]: 'id-1b',
|
||||
},
|
||||
},
|
||||
{
|
||||
universalFlatFieldMetadatas: [
|
||||
{ universalIdentifier: pair2FieldA },
|
||||
{ universalIdentifier: pair2FieldB },
|
||||
],
|
||||
fieldIdByUniversalIdentifier: {
|
||||
[pair2FieldA]: 'id-2a',
|
||||
[pair2FieldB]: 'id-2b',
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { isMorphOrRelationUniversalFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util';
|
||||
import { type AggregateOrchestratorActionsReportArgs } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-aggregate-orchestrator-actions-report-args.type';
|
||||
import { type OrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
import { type UniversalFlatFieldMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-field-metadata.type';
|
||||
import { mergeFieldIdByUniversalIdentifier } from 'src/engine/workspace-manager/workspace-migration/utils/merge-field-id-by-universal-identifier.util';
|
||||
import { type UniversalCreateFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
import { type UniversalCreateObjectAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/object/types/workspace-migration-object-action';
|
||||
|
||||
export const aggregateNonRelationFieldsIntoObjectActions = ({
|
||||
orchestratorActionsReport,
|
||||
}: AggregateOrchestratorActionsReportArgs): OrchestratorActionsReport => {
|
||||
const createObjectActions = orchestratorActionsReport.objectMetadata.create;
|
||||
const createFieldActions = orchestratorActionsReport.fieldMetadata.create;
|
||||
|
||||
const createObjectActionByObjectUniversalIdentifier = new Map<
|
||||
string,
|
||||
UniversalCreateObjectAction
|
||||
>();
|
||||
|
||||
for (const createObjectAction of createObjectActions) {
|
||||
createObjectActionByObjectUniversalIdentifier.set(
|
||||
createObjectAction.flatEntity.universalIdentifier,
|
||||
createObjectAction,
|
||||
);
|
||||
}
|
||||
|
||||
const remainingCreateFieldActions: UniversalCreateFieldAction[] = [];
|
||||
|
||||
for (const createFieldAction of createFieldActions) {
|
||||
const nonRelationFields: UniversalFlatFieldMetadata[] = [];
|
||||
const relationFields: UniversalFlatFieldMetadata[] = [];
|
||||
|
||||
for (const field of createFieldAction.universalFlatFieldMetadatas) {
|
||||
if (isMorphOrRelationUniversalFlatFieldMetadata(field)) {
|
||||
relationFields.push(field);
|
||||
} else {
|
||||
nonRelationFields.push(field);
|
||||
}
|
||||
}
|
||||
|
||||
const nonRelationFieldsByObjectUniversalIdentifier = new Map<
|
||||
string,
|
||||
UniversalFlatFieldMetadata[]
|
||||
>();
|
||||
|
||||
for (const field of nonRelationFields) {
|
||||
const objectUniversalId = field.objectMetadataUniversalIdentifier;
|
||||
const existing =
|
||||
nonRelationFieldsByObjectUniversalIdentifier.get(objectUniversalId);
|
||||
|
||||
if (isDefined(existing)) {
|
||||
existing.push(field);
|
||||
} else {
|
||||
nonRelationFieldsByObjectUniversalIdentifier.set(objectUniversalId, [
|
||||
field,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
const unmergedNonRelationFields: UniversalFlatFieldMetadata[] = [];
|
||||
|
||||
for (const [
|
||||
objectUniversalId,
|
||||
fields,
|
||||
] of nonRelationFieldsByObjectUniversalIdentifier) {
|
||||
const matchingObjectAction =
|
||||
createObjectActionByObjectUniversalIdentifier.get(objectUniversalId);
|
||||
|
||||
if (isDefined(matchingObjectAction)) {
|
||||
matchingObjectAction.universalFlatFieldMetadatas.push(...fields);
|
||||
matchingObjectAction.fieldIdByUniversalIdentifier =
|
||||
mergeFieldIdByUniversalIdentifier(
|
||||
matchingObjectAction.fieldIdByUniversalIdentifier,
|
||||
createFieldAction.fieldIdByUniversalIdentifier,
|
||||
);
|
||||
} else {
|
||||
unmergedNonRelationFields.push(...fields);
|
||||
}
|
||||
}
|
||||
|
||||
const remainingFields = [...unmergedNonRelationFields, ...relationFields];
|
||||
|
||||
if (remainingFields.length > 0) {
|
||||
remainingCreateFieldActions.push({
|
||||
...createFieldAction,
|
||||
universalFlatFieldMetadatas: remainingFields,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...orchestratorActionsReport,
|
||||
objectMetadata: {
|
||||
...orchestratorActionsReport.objectMetadata,
|
||||
create: Array.from(
|
||||
createObjectActionByObjectUniversalIdentifier.values(),
|
||||
),
|
||||
},
|
||||
fieldMetadata: {
|
||||
...orchestratorActionsReport.fieldMetadata,
|
||||
create: remainingCreateFieldActions,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
@ -1,189 +0,0 @@
|
|||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util';
|
||||
import { type AggregateOrchestratorActionsReportArgs } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-aggregate-orchestrator-actions-report-args.type';
|
||||
import { type OrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
import { type CreateFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
import { type CreateObjectAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/object/types/workspace-migration-object-action';
|
||||
|
||||
type AggregatedActions = {
|
||||
createdFieldActionByObjectMetadataId: Record<string, CreateFieldAction>;
|
||||
createdObjectActionByObjectMetadataId: Record<string, CreateObjectAction>;
|
||||
};
|
||||
|
||||
export const aggregateOrchestratorActionsReportCreateObjectAndCreateFieldActions =
|
||||
({
|
||||
orchestratorActionsReport,
|
||||
}: AggregateOrchestratorActionsReportArgs): OrchestratorActionsReport => {
|
||||
const initialCreatedObjectActionByObjectMetadataId = (
|
||||
orchestratorActionsReport.objectMetadata.create as CreateObjectAction[]
|
||||
).reduce(
|
||||
(acc, createObjectAction) => ({
|
||||
...acc,
|
||||
[createObjectAction.flatEntity.id]: createObjectAction,
|
||||
}),
|
||||
{} as Record<string, CreateObjectAction>,
|
||||
);
|
||||
const initialAccumulator: AggregatedActions = {
|
||||
createdFieldActionByObjectMetadataId: {},
|
||||
createdObjectActionByObjectMetadataId:
|
||||
initialCreatedObjectActionByObjectMetadataId,
|
||||
};
|
||||
|
||||
const {
|
||||
createdFieldActionByObjectMetadataId,
|
||||
createdObjectActionByObjectMetadataId,
|
||||
} = (
|
||||
orchestratorActionsReport.fieldMetadata.create as CreateFieldAction[]
|
||||
).reduce<AggregatedActions>(
|
||||
(
|
||||
{
|
||||
createdObjectActionByObjectMetadataId,
|
||||
createdFieldActionByObjectMetadataId,
|
||||
},
|
||||
createFieldAction,
|
||||
) => {
|
||||
const existingCreateObjectAction =
|
||||
createdObjectActionByObjectMetadataId[
|
||||
createFieldAction.objectMetadataId
|
||||
];
|
||||
|
||||
const existingCreateFieldAction =
|
||||
createdFieldActionByObjectMetadataId[
|
||||
createFieldAction.objectMetadataId
|
||||
];
|
||||
|
||||
const initialAccumulator: {
|
||||
morphOrRelationFlatFieldMetadatas: FlatFieldMetadata[];
|
||||
otherFlatFieldMetadatas: FlatFieldMetadata[];
|
||||
} = {
|
||||
morphOrRelationFlatFieldMetadatas: [],
|
||||
otherFlatFieldMetadatas: [],
|
||||
};
|
||||
const { morphOrRelationFlatFieldMetadatas, otherFlatFieldMetadatas } =
|
||||
createFieldAction.flatFieldMetadatas.reduce(
|
||||
(acc, flatFieldMetadata) => {
|
||||
if (isMorphOrRelationFlatFieldMetadata(flatFieldMetadata)) {
|
||||
return {
|
||||
...acc,
|
||||
morphOrRelationFlatFieldMetadatas: [
|
||||
...acc.morphOrRelationFlatFieldMetadatas,
|
||||
flatFieldMetadata,
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...acc,
|
||||
otherFlatFieldMetadatas: [
|
||||
...acc.otherFlatFieldMetadatas,
|
||||
flatFieldMetadata,
|
||||
],
|
||||
};
|
||||
},
|
||||
initialAccumulator,
|
||||
);
|
||||
|
||||
if (isDefined(existingCreateObjectAction)) {
|
||||
if (isDefined(existingCreateFieldAction)) {
|
||||
return {
|
||||
createdObjectActionByObjectMetadataId: {
|
||||
...createdObjectActionByObjectMetadataId,
|
||||
[createFieldAction.objectMetadataId]: {
|
||||
...existingCreateObjectAction,
|
||||
flatFieldMetadatas: [
|
||||
...existingCreateObjectAction.flatFieldMetadatas,
|
||||
...otherFlatFieldMetadatas,
|
||||
],
|
||||
},
|
||||
},
|
||||
createdFieldActionByObjectMetadataId: {
|
||||
...createdFieldActionByObjectMetadataId,
|
||||
[createFieldAction.objectMetadataId]: {
|
||||
...existingCreateFieldAction,
|
||||
flatFieldMetadatas: [
|
||||
...existingCreateFieldAction.flatFieldMetadatas,
|
||||
...morphOrRelationFlatFieldMetadatas,
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (morphOrRelationFlatFieldMetadatas.length > 0) {
|
||||
return {
|
||||
createdObjectActionByObjectMetadataId: {
|
||||
...createdObjectActionByObjectMetadataId,
|
||||
[createFieldAction.objectMetadataId]: {
|
||||
...existingCreateObjectAction,
|
||||
flatFieldMetadatas: [
|
||||
...existingCreateObjectAction.flatFieldMetadatas,
|
||||
...otherFlatFieldMetadatas,
|
||||
],
|
||||
},
|
||||
},
|
||||
createdFieldActionByObjectMetadataId: {
|
||||
...createdFieldActionByObjectMetadataId,
|
||||
[createFieldAction.objectMetadataId]: {
|
||||
...createFieldAction,
|
||||
flatFieldMetadatas: morphOrRelationFlatFieldMetadatas,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
createdObjectActionByObjectMetadataId: {
|
||||
...createdObjectActionByObjectMetadataId,
|
||||
[createFieldAction.objectMetadataId]: {
|
||||
...existingCreateObjectAction,
|
||||
flatFieldMetadatas: [
|
||||
...existingCreateObjectAction.flatFieldMetadatas,
|
||||
...otherFlatFieldMetadatas,
|
||||
],
|
||||
},
|
||||
},
|
||||
createdFieldActionByObjectMetadataId,
|
||||
};
|
||||
}
|
||||
|
||||
if (isDefined(existingCreateFieldAction)) {
|
||||
return {
|
||||
createdFieldActionByObjectMetadataId: {
|
||||
...createdFieldActionByObjectMetadataId,
|
||||
[createFieldAction.objectMetadataId]: {
|
||||
...existingCreateFieldAction,
|
||||
flatFieldMetadatas: [
|
||||
...existingCreateFieldAction.flatFieldMetadatas,
|
||||
...createFieldAction.flatFieldMetadatas,
|
||||
],
|
||||
},
|
||||
},
|
||||
createdObjectActionByObjectMetadataId,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
createdFieldActionByObjectMetadataId: {
|
||||
...createdFieldActionByObjectMetadataId,
|
||||
[createFieldAction.objectMetadataId]: createFieldAction,
|
||||
},
|
||||
createdObjectActionByObjectMetadataId,
|
||||
};
|
||||
},
|
||||
initialAccumulator,
|
||||
);
|
||||
|
||||
return {
|
||||
...orchestratorActionsReport,
|
||||
fieldMetadata: {
|
||||
...orchestratorActionsReport.fieldMetadata,
|
||||
create: Object.values(createdFieldActionByObjectMetadataId),
|
||||
},
|
||||
objectMetadata: {
|
||||
...orchestratorActionsReport.objectMetadata,
|
||||
create: Object.values(createdObjectActionByObjectMetadataId),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
|
||||
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
|
||||
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-metadata/constants/search-vector-field.constants';
|
||||
import { type AggregateOrchestratorActionsReportArgs } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-aggregate-orchestrator-actions-report-args.type';
|
||||
import { type OrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
import { type UpdateFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
import { type UniversalUpdateFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
|
||||
export const aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFieldActions =
|
||||
({
|
||||
|
|
@ -13,22 +13,21 @@ export const aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFie
|
|||
}: AggregateOrchestratorActionsReportArgs): OrchestratorActionsReport => {
|
||||
assertIsDefinedOrThrow(flatFieldMetadataMaps);
|
||||
|
||||
const updateFieldActions = orchestratorActionsReport.fieldMetadata
|
||||
.update as UpdateFieldAction[];
|
||||
const updateFieldActions = orchestratorActionsReport.fieldMetadata.update;
|
||||
|
||||
const { searchVectorUpdateFieldActions, otherUpdateFieldActions } =
|
||||
updateFieldActions.reduce<{
|
||||
searchVectorUpdateFieldActions: UpdateFieldAction[];
|
||||
otherUpdateFieldActions: UpdateFieldAction[];
|
||||
searchVectorUpdateFieldActions: UniversalUpdateFieldAction[];
|
||||
otherUpdateFieldActions: UniversalUpdateFieldAction[];
|
||||
}>(
|
||||
(acc, updateFieldAction) => {
|
||||
const flatFieldMetadata = findFlatEntityByIdInFlatEntityMaps({
|
||||
const flatFieldMetadata = findFlatEntityByUniversalIdentifierOrThrow({
|
||||
flatEntityMaps: flatFieldMetadataMaps,
|
||||
flatEntityId: updateFieldAction.entityId,
|
||||
universalIdentifier: updateFieldAction.universalIdentifier,
|
||||
});
|
||||
|
||||
const isSearchVectorUpdateFieldAction =
|
||||
flatFieldMetadata?.name === SEARCH_VECTOR_FIELD.name;
|
||||
flatFieldMetadata.name === SEARCH_VECTOR_FIELD.name;
|
||||
|
||||
if (isSearchVectorUpdateFieldAction) {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
import { type AggregateOrchestratorActionsReportArgs } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-aggregate-orchestrator-actions-report-args.type';
|
||||
import { aggregateOrchestratorActionsReportCreateObjectAndCreateFieldActions } from 'src/engine/workspace-manager/workspace-migration/utils/aggregate-orchestrator-actions-report-create-object-and-create-field-actions.util';
|
||||
import { aggregateNonRelationFieldsIntoObjectActions } from 'src/engine/workspace-manager/workspace-migration/utils/aggregate-non-relation-fields-into-object-actions.util';
|
||||
import { aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFieldActions } from 'src/engine/workspace-manager/workspace-migration/utils/aggregate-orchestrator-actions-report-deprioritize-search-vector-update-field-actions.util';
|
||||
import { aggregateRelationFieldPairs } from 'src/engine/workspace-manager/workspace-migration/utils/aggregate-relation-field-pairs.util';
|
||||
|
||||
export const aggregateOrchestratorActionsReport = ({
|
||||
orchestratorActionsReport,
|
||||
flatFieldMetadataMaps,
|
||||
}: AggregateOrchestratorActionsReportArgs) => {
|
||||
const aggregatedOrchestratorActionsReport = [
|
||||
aggregateOrchestratorActionsReportCreateObjectAndCreateFieldActions,
|
||||
aggregateNonRelationFieldsIntoObjectActions,
|
||||
aggregateRelationFieldPairs,
|
||||
aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFieldActions,
|
||||
].reduce(
|
||||
(currentOrchestratorActionsReport, aggregator) =>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type AggregateOrchestratorActionsReportArgs } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-aggregate-orchestrator-actions-report-args.type';
|
||||
import { type OrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
import { type UniversalFlatFieldMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-field-metadata.type';
|
||||
import { mergeFieldIdByUniversalIdentifier } from 'src/engine/workspace-manager/workspace-migration/utils/merge-field-id-by-universal-identifier.util';
|
||||
import { type UniversalCreateFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
|
||||
type FieldWithActionContext = {
|
||||
field: UniversalFlatFieldMetadata;
|
||||
fieldIdByUniversalIdentifier: Record<string, string> | undefined;
|
||||
};
|
||||
|
||||
export const aggregateRelationFieldPairs = ({
|
||||
orchestratorActionsReport,
|
||||
}: AggregateOrchestratorActionsReportArgs): OrchestratorActionsReport => {
|
||||
const createFieldActions = orchestratorActionsReport.fieldMetadata.create;
|
||||
|
||||
const fieldByUniversalIdentifier = new Map<string, FieldWithActionContext>();
|
||||
|
||||
for (const action of createFieldActions) {
|
||||
for (const field of action.universalFlatFieldMetadatas) {
|
||||
fieldByUniversalIdentifier.set(field.universalIdentifier, {
|
||||
field,
|
||||
fieldIdByUniversalIdentifier: action.fieldIdByUniversalIdentifier,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const processedFieldUniversalIdentifiers = new Set<string>();
|
||||
const aggregatedCreateFieldActions: UniversalCreateFieldAction[] = [];
|
||||
|
||||
for (const [
|
||||
universalIdentifier,
|
||||
fieldContext,
|
||||
] of fieldByUniversalIdentifier) {
|
||||
if (processedFieldUniversalIdentifiers.has(universalIdentifier)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const { field, fieldIdByUniversalIdentifier } = fieldContext;
|
||||
|
||||
processedFieldUniversalIdentifiers.add(universalIdentifier);
|
||||
|
||||
const fieldsToBundle: UniversalFlatFieldMetadata[] = [field];
|
||||
let mergedFieldIdMap = fieldIdByUniversalIdentifier;
|
||||
|
||||
const targetUniversalIdentifier =
|
||||
field.relationTargetFieldMetadataUniversalIdentifier;
|
||||
|
||||
if (isDefined(targetUniversalIdentifier)) {
|
||||
const targetFieldContext = fieldByUniversalIdentifier.get(
|
||||
targetUniversalIdentifier,
|
||||
);
|
||||
|
||||
if (
|
||||
isDefined(targetFieldContext) &&
|
||||
!processedFieldUniversalIdentifiers.has(targetUniversalIdentifier)
|
||||
) {
|
||||
fieldsToBundle.push(targetFieldContext.field);
|
||||
processedFieldUniversalIdentifiers.add(targetUniversalIdentifier);
|
||||
mergedFieldIdMap = mergeFieldIdByUniversalIdentifier(
|
||||
mergedFieldIdMap,
|
||||
targetFieldContext.fieldIdByUniversalIdentifier,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
aggregatedCreateFieldActions.push({
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
universalFlatFieldMetadatas: fieldsToBundle,
|
||||
fieldIdByUniversalIdentifier: mergedFieldIdMap,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
...orchestratorActionsReport,
|
||||
fieldMetadata: {
|
||||
...orchestratorActionsReport.fieldMetadata,
|
||||
create: aggregatedCreateFieldActions,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
@ -22,6 +22,8 @@ export type DeletedCreatedUpdatedMatrix<T extends AllMetadataName> = {
|
|||
string,
|
||||
{
|
||||
updates: FlatEntityPropertiesUpdates<T>;
|
||||
// TMP remove when maps is universal based
|
||||
universalIdentifier: string;
|
||||
}
|
||||
>;
|
||||
};
|
||||
|
|
@ -104,6 +106,7 @@ export const flatEntityDeletedCreatedUpdatedMatrixDispatcher = <
|
|||
}
|
||||
|
||||
initialDispatcher.updatedFlatEntityMaps.byId[toFlatEntity.id] = {
|
||||
universalIdentifier: fromFlatEntity.universalIdentifier,
|
||||
updates,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type MetadataWorkspaceMigrationActionsRecord } from 'src/engine/metadata-modules/flat-entity/types/metadata-workspace-migration-action.type';
|
||||
import { type MetadataUniversalWorkspaceMigrationActionsRecord } from 'src/engine/metadata-modules/flat-entity/types/metadata-workspace-migration-action.type';
|
||||
|
||||
export const getMetadataEmptyWorkspaceMigrationActionRecord = <
|
||||
T extends AllMetadataName,
|
||||
|
|
@ -11,4 +11,4 @@ export const getMetadataEmptyWorkspaceMigrationActionRecord = <
|
|||
create: [],
|
||||
delete: [],
|
||||
update: [],
|
||||
}) as MetadataWorkspaceMigrationActionsRecord<T>;
|
||||
}) as MetadataUniversalWorkspaceMigrationActionsRecord<T>;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const mergeFieldIdByUniversalIdentifier = (
|
||||
existing: Record<string, string> | undefined,
|
||||
incoming: Record<string, string> | undefined,
|
||||
): Record<string, string> | undefined => {
|
||||
if (!isDefined(existing) && !isDefined(incoming)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
...existing,
|
||||
...incoming,
|
||||
};
|
||||
};
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
import { type BaseFlatCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-flat-create-workspace-migration-action.type';
|
||||
import { type BaseFlatDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-flat-delete-workspace-migration-action.type';
|
||||
import { type BaseFlatUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-flat-update-workspace-migration-action.type';
|
||||
import { type BaseUniversalDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-universal-delete-workspace-migration-action.type';
|
||||
|
||||
export type CreateAgentAction = BaseCreateWorkspaceMigrationAction<'agent'>;
|
||||
export type FlatCreateAgentAction =
|
||||
BaseFlatCreateWorkspaceMigrationAction<'agent'>;
|
||||
|
||||
export type UpdateAgentAction = BaseUpdateWorkspaceMigrationAction<'agent'>;
|
||||
export type FlatUpdateAgentAction =
|
||||
BaseFlatUpdateWorkspaceMigrationAction<'agent'>;
|
||||
|
||||
export type DeleteAgentAction = BaseDeleteWorkspaceMigrationAction<'agent'>;
|
||||
export type UniversalDeleteAgentAction =
|
||||
BaseUniversalDeleteWorkspaceMigrationAction<'agent'>;
|
||||
|
||||
export type FlatDeleteAgentAction =
|
||||
BaseFlatDeleteWorkspaceMigrationAction<'agent'>;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
|
|||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdateAgentAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/agent/types/workspace-migration-agent-action-builder.service';
|
||||
import { FlatUpdateAgentAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/agent/types/workspace-migration-agent-action-builder.service';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
|
|
@ -84,7 +84,7 @@ export class WorkspaceMigrationAgentActionsBuilderService extends WorkspaceEntit
|
|||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateAgentAction: UpdateAgentAction = {
|
||||
const updateAgentAction: FlatUpdateAgentAction = {
|
||||
type: 'update',
|
||||
metadataName: 'agent',
|
||||
entityId: flatEntityId,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
import { type BaseFlatCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-flat-create-workspace-migration-action.type';
|
||||
import { type BaseFlatDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-flat-delete-workspace-migration-action.type';
|
||||
import { type BaseFlatUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-flat-update-workspace-migration-action.type';
|
||||
import { type BaseUniversalDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-universal-delete-workspace-migration-action.type';
|
||||
|
||||
export type CreateCommandMenuItemAction =
|
||||
BaseCreateWorkspaceMigrationAction<'commandMenuItem'>;
|
||||
export type FlatCreateCommandMenuItemAction =
|
||||
BaseFlatCreateWorkspaceMigrationAction<'commandMenuItem'>;
|
||||
|
||||
export type UpdateCommandMenuItemAction =
|
||||
BaseUpdateWorkspaceMigrationAction<'commandMenuItem'>;
|
||||
export type FlatUpdateCommandMenuItemAction =
|
||||
BaseFlatUpdateWorkspaceMigrationAction<'commandMenuItem'>;
|
||||
|
||||
export type DeleteCommandMenuItemAction =
|
||||
BaseDeleteWorkspaceMigrationAction<'commandMenuItem'>;
|
||||
export type UniversalDeleteCommandMenuItemAction =
|
||||
BaseUniversalDeleteWorkspaceMigrationAction<'commandMenuItem'>;
|
||||
|
||||
export type FlatDeleteCommandMenuItemAction =
|
||||
BaseFlatDeleteWorkspaceMigrationAction<'commandMenuItem'>;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
|
|||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdateCommandMenuItemAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/command-menu-item/types/workspace-migration-command-menu-item-action.type';
|
||||
import { FlatUpdateCommandMenuItemAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/command-menu-item/types/workspace-migration-command-menu-item-action.type';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
|
|
@ -101,7 +101,7 @@ export class WorkspaceMigrationCommandMenuItemActionsBuilderService extends Work
|
|||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateCommandMenuItemAction: UpdateCommandMenuItemAction = {
|
||||
const updateCommandMenuItemAction: FlatUpdateCommandMenuItemAction = {
|
||||
type: 'update',
|
||||
metadataName: 'commandMenuItem',
|
||||
entityId: flatEntityId,
|
||||
|
|
|
|||
|
|
@ -1,18 +1,38 @@
|
|||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
import { type UniversalFlatFieldMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-field-metadata.type';
|
||||
import { type BaseFlatCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-flat-create-workspace-migration-action.type';
|
||||
import { type BaseFlatDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-flat-delete-workspace-migration-action.type';
|
||||
import { type BaseFlatUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-flat-update-workspace-migration-action.type';
|
||||
import { type BaseUniversalCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-universal-create-workspace-migration-action.type';
|
||||
import { type BaseUniversalDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-universal-delete-workspace-migration-action.type';
|
||||
import { type BaseUniversalUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-universal-update-workspace-migration-action.type';
|
||||
|
||||
export type CreateFieldAction = Omit<
|
||||
BaseCreateWorkspaceMigrationAction<'fieldMetadata'>,
|
||||
// Universal action types (always use universal identifiers)
|
||||
export type UniversalCreateFieldAction = Omit<
|
||||
BaseUniversalCreateWorkspaceMigrationAction<'fieldMetadata'>,
|
||||
'flatEntity'
|
||||
> & {
|
||||
universalFlatFieldMetadatas: UniversalFlatFieldMetadata[];
|
||||
// Optional map to provide specific IDs for field creation (for API metadata).
|
||||
fieldIdByUniversalIdentifier?: Record<string, string>;
|
||||
};
|
||||
|
||||
export type UniversalUpdateFieldAction =
|
||||
BaseUniversalUpdateWorkspaceMigrationAction<'fieldMetadata'>;
|
||||
|
||||
export type UniversalDeleteFieldAction =
|
||||
BaseUniversalDeleteWorkspaceMigrationAction<'fieldMetadata'>;
|
||||
|
||||
// Flat action types (always use entity IDs)
|
||||
export type FlatCreateFieldAction = Omit<
|
||||
BaseFlatCreateWorkspaceMigrationAction<'fieldMetadata'>,
|
||||
'flatEntity'
|
||||
> & {
|
||||
objectMetadataId: string;
|
||||
flatFieldMetadatas: FlatFieldMetadata[];
|
||||
};
|
||||
|
||||
export type UpdateFieldAction =
|
||||
BaseUpdateWorkspaceMigrationAction<'fieldMetadata'>;
|
||||
export type FlatUpdateFieldAction =
|
||||
BaseFlatUpdateWorkspaceMigrationAction<'fieldMetadata'>;
|
||||
|
||||
export type DeleteFieldAction =
|
||||
BaseDeleteWorkspaceMigrationAction<'fieldMetadata'>;
|
||||
export type FlatDeleteFieldAction =
|
||||
BaseFlatDeleteWorkspaceMigrationAction<'fieldMetadata'>;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
|
|||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdateFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
import { UniversalUpdateFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
|
|
@ -37,13 +37,20 @@ export class WorkspaceMigrationFieldActionsBuilderService extends WorkspaceEntit
|
|||
|
||||
const { flatEntityToValidate: flatFieldMetadataToValidate } = args;
|
||||
|
||||
const fieldIdByUniversalIdentifier = flatFieldMetadataToValidate.id
|
||||
? {
|
||||
[flatFieldMetadataToValidate.universalIdentifier]:
|
||||
flatFieldMetadataToValidate.id,
|
||||
}
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'fieldMetadata',
|
||||
objectMetadataId: flatFieldMetadataToValidate.objectMetadataId,
|
||||
flatFieldMetadatas: [flatFieldMetadataToValidate],
|
||||
universalFlatFieldMetadatas: [flatFieldMetadataToValidate],
|
||||
fieldIdByUniversalIdentifier,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
@ -94,12 +101,12 @@ export class WorkspaceMigrationFieldActionsBuilderService extends WorkspaceEntit
|
|||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
const { universalIdentifier, flatEntityUpdates } = args;
|
||||
|
||||
const updateFieldAction: UpdateFieldAction = {
|
||||
const updateFieldAction: UniversalUpdateFieldAction = {
|
||||
type: 'update',
|
||||
metadataName: 'fieldMetadata',
|
||||
entityId: flatEntityId,
|
||||
universalIdentifier,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-update-workspace-migration-action.type';
|
||||
import { type BaseFlatCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-flat-create-workspace-migration-action.type';
|
||||
import { type BaseFlatDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-flat-delete-workspace-migration-action.type';
|
||||
import { type BaseFlatUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-flat-update-workspace-migration-action.type';
|
||||
import { type BaseUniversalDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-universal-delete-workspace-migration-action.type';
|
||||
|
||||
export type CreateFrontComponentAction =
|
||||
BaseCreateWorkspaceMigrationAction<'frontComponent'>;
|
||||
export type FlatCreateFrontComponentAction =
|
||||
BaseFlatCreateWorkspaceMigrationAction<'frontComponent'>;
|
||||
|
||||
export type UpdateFrontComponentAction =
|
||||
BaseUpdateWorkspaceMigrationAction<'frontComponent'>;
|
||||
export type FlatUpdateFrontComponentAction =
|
||||
BaseFlatUpdateWorkspaceMigrationAction<'frontComponent'>;
|
||||
|
||||
export type DeleteFrontComponentAction =
|
||||
BaseDeleteWorkspaceMigrationAction<'frontComponent'>;
|
||||
export type UniversalDeleteFrontComponentAction =
|
||||
BaseUniversalDeleteWorkspaceMigrationAction<'frontComponent'>;
|
||||
|
||||
export type FlatDeleteFrontComponentAction =
|
||||
BaseFlatDeleteWorkspaceMigrationAction<'frontComponent'>;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
|
|||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdateFrontComponentAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/front-component/types/workspace-migration-front-component-action.type';
|
||||
import { FlatUpdateFrontComponentAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/front-component/types/workspace-migration-front-component-action.type';
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/flat-entity-validation-args.type';
|
||||
|
|
@ -101,7 +101,7 @@ export class WorkspaceMigrationFrontComponentActionsBuilderService extends Works
|
|||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateFrontComponentAction: UpdateFrontComponentAction = {
|
||||
const updateFrontComponentAction: FlatUpdateFrontComponentAction = {
|
||||
type: 'update',
|
||||
metadataName: 'frontComponent',
|
||||
entityId: flatEntityId,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,18 @@
|
|||
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
|
||||
import { type BaseCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-create-workspace-migration-action.type';
|
||||
import { type BaseDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-delete-workspace-migration-action.type';
|
||||
import { type BaseFlatCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-flat-create-workspace-migration-action.type';
|
||||
import { type BaseFlatDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-flat-delete-workspace-migration-action.type';
|
||||
import { type BaseUniversalDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-universal-delete-workspace-migration-action.type';
|
||||
|
||||
export type CreateIndexAction = BaseCreateWorkspaceMigrationAction<'index'>;
|
||||
export type FlatCreateIndexAction =
|
||||
BaseFlatCreateWorkspaceMigrationAction<'index'>;
|
||||
|
||||
export type DeleteIndexAction = BaseDeleteWorkspaceMigrationAction<'index'>;
|
||||
export type UniversalDeleteIndexAction =
|
||||
BaseUniversalDeleteWorkspaceMigrationAction<'index'>;
|
||||
|
||||
export type UpdateIndexAction = {
|
||||
export type FlatDeleteIndexAction =
|
||||
BaseFlatDeleteWorkspaceMigrationAction<'index'>;
|
||||
|
||||
export type FlatUpdateIndexAction = {
|
||||
type: 'update';
|
||||
metadataName: 'index';
|
||||
entityId: string;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue