Deprecate nullable syncableEntity (#17279)

# Introduction
As we've been identifying both standard and custom entities for all the
metadata that had standard
We now still need to identify all custom entities enforcing them to have
an `applicationId` and `universalIdentifier`

In this PR we've removed the `SyncableEntityRequired` in favor requiring
props directly in the `SyncableEntity`
Which means that all metadata in db will now expect non nullable
applicationId and universalIdentifier across the whole application

Will add some type cleanup later in
https://github.com/twentyhq/twenty/pull/17277
This commit is contained in:
Paul Rastoin
2026-01-21 11:23:55 +01:00
committed by GitHub
parent b56f45e871
commit 596b7cc62d
28 changed files with 934 additions and 63 deletions
@@ -0,0 +1,191 @@
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
import { Command } from 'nest-commander';
import { type AllMetadataName } from 'twenty-shared/metadata';
import { DataSource, IsNull, Repository } from 'typeorm';
import { v4 } from 'uuid';
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/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 { ALL_METADATA_ENTITY_BY_METADATA_NAME } from 'src/engine/metadata-modules/flat-entity/constant/all-metadata-entity-by-metadata-name.constant';
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 { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
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 { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
const REMAINING_ENTITIES_METADATA_NAMES = [
'roleTarget',
'rowLevelPermissionPredicate',
'rowLevelPermissionPredicateGroup',
'viewFilterGroup',
'cronTrigger',
'databaseEventTrigger',
'routeTrigger',
'serverlessFunction',
'skill',
'pageLayoutWidget',
'pageLayout',
'pageLayoutTab',
] as const satisfies AllMetadataName[];
@Command({
name: 'upgrade:1-16:identify-remaining-entities-metadata',
description:
'Identify remaining entities metadata (roleTarget, rowLevelPermissionPredicate, rowLevelPermissionPredicateGroup, viewFilterGroup, viewSort, cronTrigger, databaseEventTrigger, routeTrigger, serverlessFunction, skill, pageLayoutWidget, pageLayout, pageLayoutTab)',
})
export class IdentifyRemainingEntitiesMetadataCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
constructor(
@InjectRepository(WorkspaceEntity)
protected readonly workspaceRepository: Repository<WorkspaceEntity>,
protected readonly twentyORMGlobalManager: GlobalWorkspaceOrmManager,
protected readonly dataSourceService: DataSourceService,
protected readonly applicationService: ApplicationService,
protected readonly workspaceCacheService: WorkspaceCacheService,
@InjectDataSource()
private readonly coreDataSource: DataSource,
) {
super(workspaceRepository, twentyORMGlobalManager, dataSourceService);
}
override async runOnWorkspace({
workspaceId,
options,
}: RunOnWorkspaceArgs): Promise<void> {
this.logger.log(
`Running identify remaining entities metadata for workspace ${workspaceId}`,
);
const { workspaceCustomFlatApplication } =
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
{ workspaceId },
);
for (const metadataName of REMAINING_ENTITIES_METADATA_NAMES) {
await this.identifyEntitiesForMetadataName({
metadataName,
workspaceId,
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
dryRun: options.dryRun ?? false,
});
}
await this.identifyViewSortEntities({
workspaceId,
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
dryRun: options.dryRun ?? false,
});
}
private async identifyEntitiesForMetadataName({
metadataName,
workspaceId,
workspaceCustomApplicationId,
dryRun,
}: {
metadataName: AllMetadataName;
workspaceId: string;
workspaceCustomApplicationId: string;
dryRun: boolean;
}): Promise<void> {
const entityClass = ALL_METADATA_ENTITY_BY_METADATA_NAME[metadataName];
const repository = this.coreDataSource.getRepository(entityClass);
const entitiesWithoutApplicationId = await repository.find({
select: ['id', 'universalIdentifier', 'applicationId'],
where: {
workspaceId,
applicationId: IsNull(),
},
});
if (entitiesWithoutApplicationId.length === 0) {
this.logger.log(
`No ${metadataName} entities found without applicationId for workspace ${workspaceId}`,
);
return;
}
const updates = entitiesWithoutApplicationId.map(
(entity: SyncableEntity & { id: string }) => ({
id: entity.id,
universalIdentifier: entity.universalIdentifier ?? v4(),
applicationId: workspaceCustomApplicationId,
}),
);
this.logger.log(
`Found ${updates.length} ${metadataName} entities to update for workspace ${workspaceId}`,
);
if (!dryRun) {
await repository.save(updates);
}
const relatedMetadataNames = getMetadataRelatedMetadataNames(metadataName);
const relatedCacheKeysToInvalidate = relatedMetadataNames.map(
getMetadataFlatEntityMapsKey,
);
const flatEntityMapsKey = getMetadataFlatEntityMapsKey(metadataName);
this.logger.log(
`Invalidating caches: ${flatEntityMapsKey} ${relatedCacheKeysToInvalidate.join(' ')}`,
);
if (!dryRun) {
await this.workspaceCacheService.invalidateAndRecompute(workspaceId, [
flatEntityMapsKey,
...relatedCacheKeysToInvalidate,
]);
}
}
private async identifyViewSortEntities({
workspaceId,
workspaceCustomApplicationId,
dryRun,
}: {
workspaceId: string;
workspaceCustomApplicationId: string;
dryRun: boolean;
}): Promise<void> {
const viewSortRepository =
this.coreDataSource.getRepository(ViewSortEntity);
const viewSortsWithoutApplicationId = await viewSortRepository.find({
select: ['id', 'universalIdentifier', 'applicationId'],
where: {
workspaceId,
applicationId: IsNull(),
},
});
if (viewSortsWithoutApplicationId.length === 0) {
this.logger.log(
`No viewSort entities found without applicationId for workspace ${workspaceId}`,
);
return;
}
const updates = viewSortsWithoutApplicationId.map((viewSort) => ({
id: viewSort.id,
universalIdentifier: viewSort.universalIdentifier ?? v4(),
applicationId: workspaceCustomApplicationId,
}));
this.logger.log(
`Found ${updates.length} viewSort entities to update for workspace ${workspaceId}`,
);
if (!dryRun) {
await viewSortRepository.save(updates);
}
}
}
@@ -0,0 +1,71 @@
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
import { Command } from 'nest-commander';
import { DataSource, 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 { makeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableQueries } from 'src/database/typeorm/core/migrations/utils/1768916632478-makeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullable.util';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
@Command({
name: 'upgrade:1-16:make-remaining-entities-universal-identifier-and-application-id-not-nullable-migration',
description:
'Make universalIdentifier and applicationId columns NOT NULL on remaining entities (roleTarget, rowLevelPermissionPredicate, rowLevelPermissionPredicateGroup, viewFilterGroup, viewSort, cronTrigger, databaseEventTrigger, routeTrigger, serverlessFunction, skill, pageLayoutWidget, pageLayout, pageLayoutTab)',
})
export class MakeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableMigrationCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
private hasRunOnce = false;
constructor(
@InjectRepository(WorkspaceEntity)
protected readonly workspaceRepository: Repository<WorkspaceEntity>,
protected readonly twentyORMGlobalManager: GlobalWorkspaceOrmManager,
protected readonly dataSourceService: DataSourceService,
@InjectDataSource()
private readonly coreDataSource: DataSource,
) {
super(workspaceRepository, twentyORMGlobalManager, dataSourceService);
}
override async runOnWorkspace({
options,
}: RunOnWorkspaceArgs): Promise<void> {
if (this.hasRunOnce) {
this.logger.warn(
'Skipping has already been run once MakeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableMigrationCommand',
);
return;
}
if (options.dryRun) {
return;
}
const queryRunner = this.coreDataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
await makeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableQueries(
queryRunner,
);
await queryRunner.commitTransaction();
this.logger.log(
'Successfully run MakeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableMigrationCommand',
);
this.hasRunOnce = true;
} catch (error) {
await queryRunner.rollbackTransaction();
this.logger.error(
`Rolling back MakeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableMigrationCommand: ${error.message}`,
);
} finally {
await queryRunner.release();
}
}
}
@@ -16,6 +16,8 @@ import { MakeAgentUniversalIdentifierAndApplicationIdNotNullableMigrationCommand
import { MakeFieldMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-field-metadata-universal-identifier-and-application-id-not-nullable-migration.command';
import { MakeIndexMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-index-metadata-universal-identifier-and-application-id-not-nullable-migration.command';
import { MakeObjectMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-object-metadata-universal-identifier-and-application-id-not-nullable-migration.command';
import { IdentifyRemainingEntitiesMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-remaining-entities-metadata.command';
import { MakeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-remaining-entities-universal-identifier-and-application-id-not-nullable-migration.command';
import { MakeRoleUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-role-universal-identifier-and-application-id-not-nullable-migration.command';
import { MakeViewFieldUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-view-field-universal-identifier-and-application-id-not-nullable-migration.command';
import { MakeViewFilterUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-view-filter-universal-identifier-and-application-id-not-nullable-migration.command';
@@ -86,6 +88,8 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
MakeViewFilterUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
MakeViewGroupUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
MakeIndexMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
MakeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
IdentifyRemainingEntitiesMetadataCommand,
],
exports: [
UpdateTaskOnDeleteActionCommand,
@@ -109,6 +113,8 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
MakeViewFilterUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
MakeViewGroupUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
MakeIndexMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
MakeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
IdentifyRemainingEntitiesMetadataCommand,
],
})
export class V1_16_UpgradeVersionCommandModule {}
@@ -31,12 +31,14 @@ import { IdentifyObjectMetadataCommand } from 'src/database/commands/upgrade-ver
import { IdentifyRoleMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-role-metadata.command';
import { IdentifyViewFieldMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-view-field-metadata.command';
import { IdentifyViewFilterMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-view-filter-metadata.command';
import { IdentifyRemainingEntitiesMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-remaining-entities-metadata.command';
import { IdentifyViewGroupMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-view-group-metadata.command';
import { IdentifyViewMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-view-metadata.command';
import { MakeAgentUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-agent-universal-identifier-and-application-id-not-nullable-migration.command';
import { MakeFieldMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-field-metadata-universal-identifier-and-application-id-not-nullable-migration.command';
import { MakeIndexMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-index-metadata-universal-identifier-and-application-id-not-nullable-migration.command';
import { MakeObjectMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-object-metadata-universal-identifier-and-application-id-not-nullable-migration.command';
import { MakeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-remaining-entities-universal-identifier-and-application-id-not-nullable-migration.command';
import { MakeRoleUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-role-universal-identifier-and-application-id-not-nullable-migration.command';
import { MakeViewFieldUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-view-field-universal-identifier-and-application-id-not-nullable-migration.command';
import { MakeViewFilterUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-view-filter-universal-identifier-and-application-id-not-nullable-migration.command';
@@ -103,6 +105,8 @@ export class UpgradeCommand extends UpgradeCommandRunner {
protected readonly makeViewFilterUniversalIdentifierAndApplicationIdNotNullableMigrationCommand: MakeViewFilterUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
protected readonly makeViewGroupUniversalIdentifierAndApplicationIdNotNullableMigrationCommand: MakeViewGroupUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
protected readonly makeIndexMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand: MakeIndexMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
protected readonly identifyRemainingEntitiesMetadataCommand: IdentifyRemainingEntitiesMetadataCommand,
protected readonly makeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableMigrationCommand: MakeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
) {
super(
workspaceRepository,
@@ -167,6 +171,9 @@ export class UpgradeCommand extends UpgradeCommandRunner {
.makeViewGroupUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
this
.makeIndexMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
this.identifyRemainingEntitiesMetadataCommand,
this
.makeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
];
this.allCommands = {
@@ -0,0 +1,292 @@
import { type MigrationInterface, type QueryRunner } from 'typeorm';
import { makeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableQueries } from 'src/database/typeorm/core/migrations/utils/1768916632478-makeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullable.util';
export class MakeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullable1768916632478
implements MigrationInterface
{
name =
'MakeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullable1768916632478';
public async up(queryRunner: QueryRunner): Promise<void> {
const savepointName =
'sp_make_remaining_entities_universal_identifier_and_application_id_not_nullable';
try {
await queryRunner.query(`SAVEPOINT ${savepointName}`);
await makeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableQueries(
queryRunner,
);
await queryRunner.query(`RELEASE SAVEPOINT ${savepointName}`);
} catch (e) {
try {
await queryRunner.query(`ROLLBACK TO SAVEPOINT ${savepointName}`);
await queryRunner.query(`RELEASE SAVEPOINT ${savepointName}`);
} catch (rollbackError) {
// eslint-disable-next-line no-console
console.error(
'Failed to rollback to savepoint in MakeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullable1768916632478',
rollbackError,
);
throw rollbackError;
}
// eslint-disable-next-line no-console
console.error(
'Swallowing MakeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullable1768916632478 error',
e,
);
}
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutTab" DROP CONSTRAINT "FK_4493447c2e4029aa26cabf30460"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_3763c4e8f942ff1e24040a13a9"`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutTab" ALTER COLUMN "applicationId" DROP NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutTab" ALTER COLUMN "universalIdentifier" DROP NOT NULL`,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_3763c4e8f942ff1e24040a13a9" ON "core"."pageLayoutTab" ("workspaceId", "universalIdentifier") `,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutTab" ADD CONSTRAINT "FK_4493447c2e4029aa26cabf30460" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayout" DROP CONSTRAINT "FK_5e7f19b88c0864db19e2bad0fc5"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_256fabec226411154baba649df"`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayout" ALTER COLUMN "applicationId" DROP NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayout" ALTER COLUMN "universalIdentifier" DROP NOT NULL`,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_256fabec226411154baba649df" ON "core"."pageLayout" ("workspaceId", "universalIdentifier") `,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayout" ADD CONSTRAINT "FK_5e7f19b88c0864db19e2bad0fc5" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutWidget" DROP CONSTRAINT "FK_fb84d310b4cfe5916ced6fc3e2a"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_2a33a0e7e44c393ca7bb578dae"`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutWidget" ALTER COLUMN "applicationId" DROP NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutWidget" ALTER COLUMN "universalIdentifier" DROP NOT NULL`,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_2a33a0e7e44c393ca7bb578dae" ON "core"."pageLayoutWidget" ("workspaceId", "universalIdentifier") `,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutWidget" ADD CONSTRAINT "FK_fb84d310b4cfe5916ced6fc3e2a" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."skill" DROP CONSTRAINT "FK_46f69b93b58666bb388c5c7785a"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_e6398c21e6bb31b525272fac84"`,
);
await queryRunner.query(
`ALTER TABLE "core"."skill" ALTER COLUMN "applicationId" DROP NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."skill" ALTER COLUMN "universalIdentifier" DROP NOT NULL`,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_e6398c21e6bb31b525272fac84" ON "core"."skill" ("universalIdentifier", "workspaceId") `,
);
await queryRunner.query(
`ALTER TABLE "core"."skill" ADD CONSTRAINT "FK_46f69b93b58666bb388c5c7785a" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."serverlessFunction" DROP CONSTRAINT "FK_62cbd26626ff76df897181c7994"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_5b43e65e322d516c9307bed97a"`,
);
await queryRunner.query(
`ALTER TABLE "core"."serverlessFunction" ALTER COLUMN "applicationId" DROP NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."serverlessFunction" ALTER COLUMN "universalIdentifier" DROP NOT NULL`,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_5b43e65e322d516c9307bed97a" ON "core"."serverlessFunction" ("workspaceId", "universalIdentifier") `,
);
await queryRunner.query(
`ALTER TABLE "core"."serverlessFunction" ADD CONSTRAINT "FK_62cbd26626ff76df897181c7994" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."routeTrigger" DROP CONSTRAINT "FK_6edf47a8bfe17a5811998dc7162"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_e9c53b9ac5035d3202a8737020"`,
);
await queryRunner.query(
`ALTER TABLE "core"."routeTrigger" ALTER COLUMN "applicationId" DROP NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."routeTrigger" ALTER COLUMN "universalIdentifier" DROP NOT NULL`,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_e9c53b9ac5035d3202a8737020" ON "core"."routeTrigger" ("universalIdentifier", "workspaceId") `,
);
await queryRunner.query(
`ALTER TABLE "core"."routeTrigger" ADD CONSTRAINT "FK_6edf47a8bfe17a5811998dc7162" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."databaseEventTrigger" DROP CONSTRAINT "FK_9acc2804037a5c885633024368d"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_960465af116edf9ac501bfb3db"`,
);
await queryRunner.query(
`ALTER TABLE "core"."databaseEventTrigger" ALTER COLUMN "applicationId" DROP NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."databaseEventTrigger" ALTER COLUMN "universalIdentifier" DROP NOT NULL`,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_960465af116edf9ac501bfb3db" ON "core"."databaseEventTrigger" ("universalIdentifier", "workspaceId") `,
);
await queryRunner.query(
`ALTER TABLE "core"."databaseEventTrigger" ADD CONSTRAINT "FK_9acc2804037a5c885633024368d" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."cronTrigger" DROP CONSTRAINT "FK_817ea28e71e3b19acc258dd7dcd"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_8adc1fd6cb0dad2fbfd945954d"`,
);
await queryRunner.query(
`ALTER TABLE "core"."cronTrigger" ALTER COLUMN "applicationId" DROP NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."cronTrigger" ALTER COLUMN "universalIdentifier" DROP NOT NULL`,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_8adc1fd6cb0dad2fbfd945954d" ON "core"."cronTrigger" ("universalIdentifier", "workspaceId") `,
);
await queryRunner.query(
`ALTER TABLE "core"."cronTrigger" ADD CONSTRAINT "FK_817ea28e71e3b19acc258dd7dcd" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."viewSort" DROP CONSTRAINT "FK_ff8cbebe1704954120df82bf393"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_38232fc0c6567ed029c2b1a12c"`,
);
await queryRunner.query(
`ALTER TABLE "core"."viewSort" ALTER COLUMN "applicationId" DROP NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."viewSort" ALTER COLUMN "universalIdentifier" DROP NOT NULL`,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_38232fc0c6567ed029c2b1a12c" ON "core"."viewSort" ("universalIdentifier", "workspaceId") `,
);
await queryRunner.query(
`ALTER TABLE "core"."viewSort" ADD CONSTRAINT "FK_ff8cbebe1704954120df82bf393" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."viewFilterGroup" DROP CONSTRAINT "FK_bfc3498b964ef1bfc89b1f2bee3"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_e6ed40a61e4584e98584019a47"`,
);
await queryRunner.query(
`ALTER TABLE "core"."viewFilterGroup" ALTER COLUMN "applicationId" DROP NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."viewFilterGroup" ALTER COLUMN "universalIdentifier" DROP NOT NULL`,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_e6ed40a61e4584e98584019a47" ON "core"."viewFilterGroup" ("universalIdentifier", "workspaceId") `,
);
await queryRunner.query(
`ALTER TABLE "core"."viewFilterGroup" ADD CONSTRAINT "FK_bfc3498b964ef1bfc89b1f2bee3" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."rowLevelPermissionPredicateGroup" DROP CONSTRAINT "FK_1e82563accb67114f65a3993b86"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_a14b5665091e86d461fb585924"`,
);
await queryRunner.query(
`ALTER TABLE "core"."rowLevelPermissionPredicateGroup" ALTER COLUMN "applicationId" DROP NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."rowLevelPermissionPredicateGroup" ALTER COLUMN "universalIdentifier" DROP NOT NULL`,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_a14b5665091e86d461fb585924" ON "core"."rowLevelPermissionPredicateGroup" ("universalIdentifier", "workspaceId") `,
);
await queryRunner.query(
`ALTER TABLE "core"."rowLevelPermissionPredicateGroup" ADD CONSTRAINT "FK_1e82563accb67114f65a3993b86" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."rowLevelPermissionPredicate" DROP CONSTRAINT "FK_23b36d07d363f81200654fa1334"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_e46f3e01227f1c8ee0c8041821"`,
);
await queryRunner.query(
`ALTER TABLE "core"."rowLevelPermissionPredicate" ALTER COLUMN "applicationId" DROP NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."rowLevelPermissionPredicate" ALTER COLUMN "universalIdentifier" DROP NOT NULL`,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_e46f3e01227f1c8ee0c8041821" ON "core"."rowLevelPermissionPredicate" ("universalIdentifier", "workspaceId") `,
);
await queryRunner.query(
`ALTER TABLE "core"."rowLevelPermissionPredicate" ADD CONSTRAINT "FK_23b36d07d363f81200654fa1334" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."roleTarget" DROP CONSTRAINT "FK_b1db027b64f44029389ace305ac"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_0082568653b80c15903c5a2ba9"`,
);
await queryRunner.query(
`ALTER TABLE "core"."roleTarget" ALTER COLUMN "applicationId" DROP NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."roleTarget" ALTER COLUMN "universalIdentifier" DROP NOT NULL`,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_0082568653b80c15903c5a2ba9" ON "core"."roleTarget" ("workspaceId", "universalIdentifier") `,
);
await queryRunner.query(
`ALTER TABLE "core"."roleTarget" ADD CONSTRAINT "FK_b1db027b64f44029389ace305ac" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
}
}
@@ -0,0 +1,239 @@
import { type QueryRunner } from 'typeorm';
export const makeRemainingEntitiesUniversalIdentifierAndApplicationIdNotNullableQueries =
async (queryRunner: QueryRunner): Promise<void> => {
await queryRunner.query(
`ALTER TABLE "core"."roleTarget" DROP CONSTRAINT "FK_b1db027b64f44029389ace305ac"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_0082568653b80c15903c5a2ba9"`,
);
await queryRunner.query(
`ALTER TABLE "core"."roleTarget" ALTER COLUMN "universalIdentifier" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."roleTarget" ALTER COLUMN "applicationId" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."rowLevelPermissionPredicate" DROP CONSTRAINT "FK_23b36d07d363f81200654fa1334"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_e46f3e01227f1c8ee0c8041821"`,
);
await queryRunner.query(
`ALTER TABLE "core"."rowLevelPermissionPredicate" ALTER COLUMN "universalIdentifier" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."rowLevelPermissionPredicate" ALTER COLUMN "applicationId" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."rowLevelPermissionPredicateGroup" DROP CONSTRAINT "FK_1e82563accb67114f65a3993b86"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_a14b5665091e86d461fb585924"`,
);
await queryRunner.query(
`ALTER TABLE "core"."rowLevelPermissionPredicateGroup" ALTER COLUMN "universalIdentifier" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."rowLevelPermissionPredicateGroup" ALTER COLUMN "applicationId" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."viewFilterGroup" DROP CONSTRAINT "FK_bfc3498b964ef1bfc89b1f2bee3"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_e6ed40a61e4584e98584019a47"`,
);
await queryRunner.query(
`ALTER TABLE "core"."viewFilterGroup" ALTER COLUMN "universalIdentifier" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."viewFilterGroup" ALTER COLUMN "applicationId" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."viewSort" DROP CONSTRAINT "FK_ff8cbebe1704954120df82bf393"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_38232fc0c6567ed029c2b1a12c"`,
);
await queryRunner.query(
`ALTER TABLE "core"."viewSort" ALTER COLUMN "universalIdentifier" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."viewSort" ALTER COLUMN "applicationId" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."cronTrigger" DROP CONSTRAINT "FK_817ea28e71e3b19acc258dd7dcd"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_8adc1fd6cb0dad2fbfd945954d"`,
);
await queryRunner.query(
`ALTER TABLE "core"."cronTrigger" ALTER COLUMN "universalIdentifier" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."cronTrigger" ALTER COLUMN "applicationId" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."databaseEventTrigger" DROP CONSTRAINT "FK_9acc2804037a5c885633024368d"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_960465af116edf9ac501bfb3db"`,
);
await queryRunner.query(
`ALTER TABLE "core"."databaseEventTrigger" ALTER COLUMN "universalIdentifier" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."databaseEventTrigger" ALTER COLUMN "applicationId" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."routeTrigger" DROP CONSTRAINT "FK_6edf47a8bfe17a5811998dc7162"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_e9c53b9ac5035d3202a8737020"`,
);
await queryRunner.query(
`ALTER TABLE "core"."routeTrigger" ALTER COLUMN "universalIdentifier" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."routeTrigger" ALTER COLUMN "applicationId" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."serverlessFunction" DROP CONSTRAINT "FK_62cbd26626ff76df897181c7994"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_5b43e65e322d516c9307bed97a"`,
);
await queryRunner.query(
`ALTER TABLE "core"."serverlessFunction" ALTER COLUMN "universalIdentifier" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."serverlessFunction" ALTER COLUMN "applicationId" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."skill" DROP CONSTRAINT "FK_46f69b93b58666bb388c5c7785a"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_e6398c21e6bb31b525272fac84"`,
);
await queryRunner.query(
`ALTER TABLE "core"."skill" ALTER COLUMN "universalIdentifier" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."skill" ALTER COLUMN "applicationId" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutWidget" DROP CONSTRAINT "FK_fb84d310b4cfe5916ced6fc3e2a"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_2a33a0e7e44c393ca7bb578dae"`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutWidget" ALTER COLUMN "universalIdentifier" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutWidget" ALTER COLUMN "applicationId" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayout" DROP CONSTRAINT "FK_5e7f19b88c0864db19e2bad0fc5"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_256fabec226411154baba649df"`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayout" ALTER COLUMN "universalIdentifier" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayout" ALTER COLUMN "applicationId" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutTab" DROP CONSTRAINT "FK_4493447c2e4029aa26cabf30460"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_3763c4e8f942ff1e24040a13a9"`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutTab" ALTER COLUMN "universalIdentifier" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutTab" ALTER COLUMN "applicationId" SET NOT NULL`,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_0082568653b80c15903c5a2ba9" ON "core"."roleTarget" ("workspaceId", "universalIdentifier") `,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_e46f3e01227f1c8ee0c8041821" ON "core"."rowLevelPermissionPredicate" ("workspaceId", "universalIdentifier") `,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_a14b5665091e86d461fb585924" ON "core"."rowLevelPermissionPredicateGroup" ("workspaceId", "universalIdentifier") `,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_e6ed40a61e4584e98584019a47" ON "core"."viewFilterGroup" ("workspaceId", "universalIdentifier") `,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_38232fc0c6567ed029c2b1a12c" ON "core"."viewSort" ("workspaceId", "universalIdentifier") `,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_8adc1fd6cb0dad2fbfd945954d" ON "core"."cronTrigger" ("workspaceId", "universalIdentifier") `,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_960465af116edf9ac501bfb3db" ON "core"."databaseEventTrigger" ("workspaceId", "universalIdentifier") `,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_e9c53b9ac5035d3202a8737020" ON "core"."routeTrigger" ("workspaceId", "universalIdentifier") `,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_5b43e65e322d516c9307bed97a" ON "core"."serverlessFunction" ("workspaceId", "universalIdentifier") `,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_e6398c21e6bb31b525272fac84" ON "core"."skill" ("workspaceId", "universalIdentifier") `,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_2a33a0e7e44c393ca7bb578dae" ON "core"."pageLayoutWidget" ("workspaceId", "universalIdentifier") `,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_256fabec226411154baba649df" ON "core"."pageLayout" ("workspaceId", "universalIdentifier") `,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_3763c4e8f942ff1e24040a13a9" ON "core"."pageLayoutTab" ("workspaceId", "universalIdentifier") `,
);
await queryRunner.query(
`ALTER TABLE "core"."roleTarget" ADD CONSTRAINT "FK_b1db027b64f44029389ace305ac" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."rowLevelPermissionPredicate" ADD CONSTRAINT "FK_23b36d07d363f81200654fa1334" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."rowLevelPermissionPredicateGroup" ADD CONSTRAINT "FK_1e82563accb67114f65a3993b86" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."viewFilterGroup" ADD CONSTRAINT "FK_bfc3498b964ef1bfc89b1f2bee3" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."viewSort" ADD CONSTRAINT "FK_ff8cbebe1704954120df82bf393" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."cronTrigger" ADD CONSTRAINT "FK_817ea28e71e3b19acc258dd7dcd" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."databaseEventTrigger" ADD CONSTRAINT "FK_9acc2804037a5c885633024368d" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."routeTrigger" ADD CONSTRAINT "FK_6edf47a8bfe17a5811998dc7162" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."serverlessFunction" ADD CONSTRAINT "FK_62cbd26626ff76df897181c7994" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."skill" ADD CONSTRAINT "FK_46f69b93b58666bb388c5c7785a" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutWidget" ADD CONSTRAINT "FK_fb84d310b4cfe5916ced6fc3e2a" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayout" ADD CONSTRAINT "FK_5e7f19b88c0864db19e2bad0fc5" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutTab" ADD CONSTRAINT "FK_4493447c2e4029aa26cabf30460" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
};
@@ -14,7 +14,7 @@ import {
DEFAULT_SMART_MODEL,
ModelId,
} from 'src/engine/metadata-modules/ai/ai-models/constants/ai-models.const';
import { SyncableEntityRequired } from 'src/engine/workspace-manager/types/syncable-entity-required.interface';
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
@Entity('agent')
@Index('IDX_AGENT_ID_DELETED_AT', ['id', 'deletedAt'])
@@ -23,7 +23,7 @@ import { SyncableEntityRequired } from 'src/engine/workspace-manager/types/synca
where: '"deletedAt" IS NULL',
})
export class AgentEntity
extends SyncableEntityRequired
extends SyncableEntity
implements Required<AgentEntity>
{
@PrimaryGeneratedColumn('uuid')
@@ -11,7 +11,7 @@ import {
} from 'typeorm';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { SyncableEntityRequired } from 'src/engine/workspace-manager/types/syncable-entity-required.interface';
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
export enum CommandMenuItemAvailabilityType {
GLOBAL = 'GLOBAL',
@@ -28,7 +28,7 @@ export enum CommandMenuItemAvailabilityType {
'availabilityObjectMetadataId',
])
export class CommandMenuItemEntity
extends SyncableEntityRequired
extends SyncableEntity
implements Required<CommandMenuItemEntity>
{
@PrimaryGeneratedColumn('uuid')
@@ -30,7 +30,7 @@ import { FieldPermissionEntity } from 'src/engine/metadata-modules/object-permis
import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { SyncableEntityRequired } from 'src/engine/workspace-manager/types/syncable-entity-required.interface';
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
@Entity('fieldMetadata')
@Check(
@@ -56,7 +56,7 @@ import { SyncableEntityRequired } from 'src/engine/workspace-manager/types/synca
export class FieldMetadataEntity<
TFieldMetadataType extends FieldMetadataType = FieldMetadataType,
>
extends SyncableEntityRequired
extends SyncableEntity
implements Required<FieldMetadataEntity>
{
@PrimaryGeneratedColumn('uuid')
@@ -11,9 +11,11 @@ export const fromCreateRowLevelPermissionPredicateGroupInputToFlatRowLevelPermis
createRowLevelPermissionPredicateGroupInput:
rawCreateRowLevelPermissionPredicateGroupInput,
workspaceId,
workspaceCustomApplicationId,
}: {
createRowLevelPermissionPredicateGroupInput: CreateRowLevelPermissionPredicateGroupInput;
workspaceId: string;
workspaceCustomApplicationId: string;
}): FlatRowLevelPermissionPredicateGroup => {
const sanitizedInput = (
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties as unknown as (
@@ -55,6 +57,6 @@ export const fromCreateRowLevelPermissionPredicateGroupInputToFlatRowLevelPermis
positionInRowLevelPermissionPredicateGroup:
createRowLevelPermissionPredicateGroupInput.positionInRowLevelPermissionPredicateGroup ??
null,
applicationId: null,
applicationId: workspaceCustomApplicationId,
};
};
@@ -11,9 +11,11 @@ export const fromCreateRowLevelPermissionPredicateInputToFlatRowLevelPermissionP
createRowLevelPermissionPredicateInput:
rawCreateRowLevelPermissionPredicateInput,
workspaceId,
workspaceCustomApplicationId,
}: {
createRowLevelPermissionPredicateInput: CreateRowLevelPermissionPredicateInput;
workspaceId: string;
workspaceCustomApplicationId: string;
}): FlatRowLevelPermissionPredicate => {
const sanitizedInput = (
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties as unknown as (
@@ -67,6 +69,6 @@ export const fromCreateRowLevelPermissionPredicateInputToFlatRowLevelPermissionP
workspaceMemberSubFieldName:
createRowLevelPermissionPredicateInput.workspaceMemberSubFieldName ??
null,
applicationId: null,
applicationId: workspaceCustomApplicationId,
};
};
@@ -6,11 +6,11 @@ import {
UpdateDateColumn,
} from 'typeorm';
import { SyncableEntityRequired } from 'src/engine/workspace-manager/types/syncable-entity-required.interface';
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
@Entity('frontComponent')
export class FrontComponentEntity
extends SyncableEntityRequired
extends SyncableEntity
implements Required<FrontComponentEntity>
{
@PrimaryGeneratedColumn('uuid')
@@ -15,7 +15,7 @@ import {
import { IndexFieldMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-field-metadata.entity';
import { IndexType } from 'src/engine/metadata-modules/index-metadata/types/indexType.types';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { SyncableEntityRequired } from 'src/engine/workspace-manager/types/syncable-entity-required.interface';
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
@Unique('IDX_INDEX_METADATA_NAME_WORKSPACE_ID_OBJECT_METADATA_ID_UNIQUE', [
'name',
@@ -28,7 +28,7 @@ import { SyncableEntityRequired } from 'src/engine/workspace-manager/types/synca
])
@Entity('indexMetadata')
export class IndexMetadataEntity
extends SyncableEntityRequired
extends SyncableEntity
implements Required<IndexMetadataEntity>
{
@PrimaryGeneratedColumn('uuid')
@@ -19,7 +19,7 @@ import { type ObjectStandardOverridesDTO } from 'src/engine/metadata-modules/obj
import { FieldPermissionEntity } from 'src/engine/metadata-modules/object-permission/field-permission/field-permission.entity';
import { ObjectPermissionEntity } from 'src/engine/metadata-modules/object-permission/object-permission.entity';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { SyncableEntityRequired } from 'src/engine/workspace-manager/types/syncable-entity-required.interface';
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
@Entity('objectMetadata')
@Unique('IDX_OBJECT_METADATA_NAME_SINGULAR_WORKSPACE_ID_UNIQUE', [
@@ -32,7 +32,7 @@ import { SyncableEntityRequired } from 'src/engine/workspace-manager/types/synca
])
@Index('IDX_OBJECT_METADATA_DATA_SOURCE_ID', ['dataSourceId'])
export class ObjectMetadataEntity
extends SyncableEntityRequired
extends SyncableEntity
implements Required<ObjectMetadataEntity>
{
@PrimaryGeneratedColumn('uuid')
@@ -15,14 +15,11 @@ import { PermissionFlagEntity } from 'src/engine/metadata-modules/permission-fla
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
import { RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
import { SyncableEntityRequired } from 'src/engine/workspace-manager/types/syncable-entity-required.interface';
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
@Entity('role')
@Unique('IDX_ROLE_LABEL_WORKSPACE_ID_UNIQUE', ['label', 'workspaceId'])
export class RoleEntity
extends SyncableEntityRequired
implements Required<RoleEntity>
{
export class RoleEntity extends SyncableEntity implements Required<RoleEntity> {
@PrimaryGeneratedColumn('uuid')
id: string;
@@ -3,6 +3,7 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
import { BillingModule } from 'src/engine/core-modules/billing/billing.module';
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
@@ -24,6 +25,7 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
WorkspaceManyOrAllFlatEntityMapsCacheModule,
WorkspaceMigrationModule,
BillingModule,
ApplicationModule,
],
providers: [
RowLevelPermissionPredicateService,
@@ -7,6 +7,7 @@ import { InjectRepository } from '@nestjs/typeorm';
import { isDefined } from 'twenty-shared/utils';
import { Repository } from 'typeorm';
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
import { BillingEntitlementKey } from 'src/engine/core-modules/billing/enums/billing-entitlement-key.enum';
import { BillingService } from 'src/engine/core-modules/billing/services/billing.service';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
@@ -42,6 +43,7 @@ export class RowLevelPermissionPredicateGroupService {
@InjectRepository(RowLevelPermissionPredicateGroupEntity)
private readonly rowLevelPermissionPredicateGroupRepository: Repository<RowLevelPermissionPredicateGroupEntity>,
private readonly configService: ConfigService,
private readonly applicationService: ApplicationService,
) {}
async createOne({
@@ -52,12 +54,19 @@ export class RowLevelPermissionPredicateGroupService {
workspaceId: string;
}): Promise<RowLevelPermissionPredicateGroupDTO> {
await this.hasRowLevelPermissionFeatureOrThrow(workspaceId);
const { workspaceCustomFlatApplication } =
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
{
workspaceId,
},
);
const flatGroupToCreate =
fromCreateRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupToCreate(
{
createRowLevelPermissionPredicateGroupInput,
workspaceId,
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
},
);
@@ -6,6 +6,7 @@ import { ConfigService } from '@nestjs/config';
import { isDefined } from 'twenty-shared/utils';
import { v4 } from 'uuid';
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
import { BillingEntitlementKey } from 'src/engine/core-modules/billing/enums/billing-entitlement-key.enum';
import { BillingService } from 'src/engine/core-modules/billing/services/billing.service';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
@@ -47,6 +48,7 @@ export class RowLevelPermissionPredicateService {
private readonly workspaceCacheService: WorkspaceCacheService,
private readonly billingService: BillingService,
private readonly configService: ConfigService,
private readonly applicationService: ApplicationService,
) {}
async createOne({
@@ -58,11 +60,18 @@ export class RowLevelPermissionPredicateService {
}): Promise<RowLevelPermissionPredicateDTO> {
await this.hasRowLevelPermissionFeatureOrThrow(workspaceId);
const { workspaceCustomFlatApplication } =
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
{
workspaceId,
},
);
const flatPredicateToCreate =
fromCreateRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateToCreate(
{
createRowLevelPermissionPredicateInput,
workspaceId,
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
},
);
@@ -322,6 +331,12 @@ export class RowLevelPermissionPredicateService {
const { roleId, objectMetadataId, predicates, predicateGroups } = input;
const { workspaceCustomFlatApplication } =
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
{
workspaceId,
},
);
const {
flatRowLevelPermissionPredicateMaps,
flatRowLevelPermissionPredicateGroupMaps,
@@ -366,6 +381,7 @@ export class RowLevelPermissionPredicateService {
objectMetadataId,
workspaceId,
flatRowLevelPermissionPredicateGroupMaps,
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
});
const { predicatesToCreate, predicatesToUpdate, predicatesToDelete } =
@@ -376,6 +392,7 @@ export class RowLevelPermissionPredicateService {
objectMetadataId,
workspaceId,
flatRowLevelPermissionPredicateMaps,
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
});
await this.runUpsertMigration({
@@ -435,6 +452,7 @@ export class RowLevelPermissionPredicateService {
objectMetadataId,
workspaceId,
flatRowLevelPermissionPredicateGroupMaps,
workspaceCustomApplicationId,
}: {
existingGroups: FlatRowLevelPermissionPredicateGroup[];
inputGroups: RowLevelPermissionPredicateGroupInput[];
@@ -442,6 +460,7 @@ export class RowLevelPermissionPredicateService {
objectMetadataId: string;
workspaceId: string;
flatRowLevelPermissionPredicateGroupMaps: FlatEntityMaps<FlatRowLevelPermissionPredicateGroup>;
workspaceCustomApplicationId: string;
}): {
groupsToCreate: FlatRowLevelPermissionPredicateGroup[];
groupsToUpdate: FlatRowLevelPermissionPredicateGroup[];
@@ -488,7 +507,7 @@ export class RowLevelPermissionPredicateService {
updatedAt: createdAt,
deletedAt: null,
universalIdentifier: groupId,
applicationId: null,
applicationId: workspaceCustomApplicationId,
});
}
}
@@ -515,6 +534,7 @@ export class RowLevelPermissionPredicateService {
objectMetadataId,
workspaceId,
flatRowLevelPermissionPredicateMaps,
workspaceCustomApplicationId,
}: {
existingPredicates: FlatRowLevelPermissionPredicate[];
inputPredicates: RowLevelPermissionPredicateInput[];
@@ -522,6 +542,7 @@ export class RowLevelPermissionPredicateService {
objectMetadataId: string;
workspaceId: string;
flatRowLevelPermissionPredicateMaps: FlatEntityMaps<FlatRowLevelPermissionPredicate>;
workspaceCustomApplicationId: string;
}): {
predicatesToCreate: FlatRowLevelPermissionPredicate[];
predicatesToUpdate: FlatRowLevelPermissionPredicate[];
@@ -583,7 +604,7 @@ export class RowLevelPermissionPredicateService {
updatedAt: createdAt,
deletedAt: null,
universalIdentifier: predicateId,
applicationId: null,
applicationId: workspaceCustomApplicationId,
});
}
}
@@ -14,7 +14,7 @@ import {
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { SyncableEntityRequired } from 'src/engine/workspace-manager/types/syncable-entity-required.interface';
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
@Entity({ name: 'viewField', schema: 'core' })
@Index('IDX_VIEW_FIELD_WORKSPACE_ID_VIEW_ID', ['workspaceId', 'viewId'])
@@ -29,7 +29,7 @@ import { SyncableEntityRequired } from 'src/engine/workspace-manager/types/synca
},
)
export class ViewFieldEntity
extends SyncableEntityRequired
extends SyncableEntity
implements Required<ViewFieldEntity>
{
@PrimaryGeneratedColumn('uuid')
@@ -16,14 +16,14 @@ import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/
import { ViewFilterGroupEntity } from 'src/engine/metadata-modules/view-filter-group/entities/view-filter-group.entity';
import { type ViewFilterValue } from 'src/engine/metadata-modules/view-filter/types/view-filter-value.type';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { SyncableEntityRequired } from 'src/engine/workspace-manager/types/syncable-entity-required.interface';
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
@Entity({ name: 'viewFilter', schema: 'core' })
@Index('IDX_VIEW_FILTER_WORKSPACE_ID_VIEW_ID', ['workspaceId', 'viewId'])
@Index('IDX_VIEW_FILTER_VIEW_ID', ['viewId'])
@Index('IDX_VIEW_FILTER_FIELD_METADATA_ID', ['fieldMetadataId'])
export class ViewFilterEntity
extends SyncableEntityRequired
extends SyncableEntity
implements Required<ViewFilterEntity>
{
@PrimaryGeneratedColumn('uuid')
@@ -12,13 +12,13 @@ import {
} from 'typeorm';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { SyncableEntityRequired } from 'src/engine/workspace-manager/types/syncable-entity-required.interface';
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
@Entity({ name: 'viewGroup', schema: 'core' })
@Index('IDX_VIEW_GROUP_WORKSPACE_ID_VIEW_ID', ['workspaceId', 'viewId'])
@Index('IDX_VIEW_GROUP_VIEW_ID', ['viewId'])
export class ViewGroupEntity
extends SyncableEntityRequired
extends SyncableEntity
implements Required<ViewGroupEntity>
{
@PrimaryGeneratedColumn('uuid')
@@ -3,6 +3,7 @@ import { getRepositoryToken } from '@nestjs/typeorm';
import { type Repository } from 'typeorm';
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
import { ViewSortDirection } from 'src/engine/metadata-modules/view-sort/enums/view-sort-direction';
import {
@@ -18,6 +19,7 @@ import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage
describe('ViewSortService', () => {
let viewSortService: ViewSortService;
let viewSortRepository: Repository<ViewSortEntity>;
let applicationService: ApplicationService;
const mockViewSort = {
id: 'view-sort-id',
@@ -51,6 +53,12 @@ describe('ViewSortService', () => {
flushGraphQLOperation: jest.fn(),
},
},
{
provide: ApplicationService,
useValue: {
findWorkspaceTwentyStandardAndCustomApplicationOrThrow: jest.fn(),
},
},
],
}).compile();
@@ -58,6 +66,7 @@ describe('ViewSortService', () => {
viewSortRepository = module.get<Repository<ViewSortEntity>>(
getRepositoryToken(ViewSortEntity),
);
applicationService = module.get<ApplicationService>(ApplicationService);
});
it('should be defined', () => {
@@ -151,12 +160,26 @@ describe('ViewSortService', () => {
};
it('should create a view sort successfully', async () => {
const mockApplicationId = 'application-id';
jest
.spyOn(
applicationService,
'findWorkspaceTwentyStandardAndCustomApplicationOrThrow',
)
.mockResolvedValue({
workspaceCustomFlatApplication: { id: mockApplicationId },
} as any);
jest.spyOn(viewSortRepository, 'create').mockReturnValue(mockViewSort);
jest.spyOn(viewSortRepository, 'save').mockResolvedValue(mockViewSort);
const result = await viewSortService.create(validViewSortData);
expect(viewSortRepository.create).toHaveBeenCalledWith(validViewSortData);
expect(viewSortRepository.create).toHaveBeenCalledWith({
...validViewSortData,
universalIdentifier: expect.any(String),
applicationId: mockApplicationId,
});
expect(viewSortRepository.save).toHaveBeenCalledWith(mockViewSort);
expect(result).toEqual(mockViewSort);
});
@@ -182,6 +205,15 @@ describe('ViewSortService', () => {
it('should throw exception when viewId is missing', async () => {
const invalidData = { ...validViewSortData, viewId: undefined };
jest
.spyOn(
applicationService,
'findWorkspaceTwentyStandardAndCustomApplicationOrThrow',
)
.mockResolvedValue({
workspaceCustomFlatApplication: { id: 'application-id' },
} as any);
await expect(viewSortService.create(invalidData)).rejects.toThrow(
new ViewSortException(
generateViewSortExceptionMessage(
@@ -200,6 +232,15 @@ describe('ViewSortService', () => {
it('should throw exception when fieldMetadataId is missing', async () => {
const invalidData = { ...validViewSortData, fieldMetadataId: undefined };
jest
.spyOn(
applicationService,
'findWorkspaceTwentyStandardAndCustomApplicationOrThrow',
)
.mockResolvedValue({
workspaceCustomFlatApplication: { id: 'application-id' },
} as any);
await expect(viewSortService.create(invalidData)).rejects.toThrow(
new ViewSortException(
generateViewSortExceptionMessage(
@@ -3,7 +3,9 @@ import { InjectRepository } from '@nestjs/typeorm';
import { isDefined } from 'twenty-shared/utils';
import { IsNull, Repository } from 'typeorm';
import { v4 } from 'uuid';
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
import {
ViewSortException,
@@ -15,12 +17,14 @@ import {
import { FIND_ALL_CORE_VIEWS_GRAPHQL_OPERATION } from 'src/engine/metadata-modules/view/constants/find-all-core-views-graphql-operation.constant';
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
// TODO migrate to v2
@Injectable()
export class ViewSortService {
constructor(
@InjectRepository(ViewSortEntity)
private readonly viewSortRepository: Repository<ViewSortEntity>,
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
private readonly applicationService: ApplicationService,
) {}
async findByWorkspaceId(workspaceId: string): Promise<ViewSortEntity[]> {
@@ -78,6 +82,13 @@ export class ViewSortService {
);
}
const { workspaceCustomFlatApplication } =
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
{
workspaceId: viewSortData.workspaceId,
},
);
if (!isDefined(viewSortData.viewId)) {
throw new ViewSortException(
generateViewSortExceptionMessage(
@@ -106,7 +117,11 @@ export class ViewSortService {
);
}
const viewSort = this.viewSortRepository.create(viewSortData);
const viewSort = this.viewSortRepository.create({
...viewSortData,
universalIdentifier: v4(),
applicationId: workspaceCustomFlatApplication.id,
});
const savedViewSort = await this.viewSortRepository.save(viewSort);
@@ -1,6 +1,7 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
import { ViewPermissionsModule } from 'src/engine/metadata-modules/view-permissions/view-permissions.module';
import { ViewSortController } from 'src/engine/metadata-modules/view-sort/controllers/view-sort.controller';
@@ -16,6 +17,7 @@ import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/
PermissionsModule,
WorkspaceCacheStorageModule,
ViewPermissionsModule,
ApplicationModule,
],
controllers: [ViewSortController],
providers: [ViewSortService, ViewSortResolver],
@@ -27,7 +27,7 @@ import { ViewKey } from 'src/engine/metadata-modules/view/enums/view-key.enum';
import { ViewOpenRecordIn } from 'src/engine/metadata-modules/view/enums/view-open-record-in';
import { ViewType } from 'src/engine/metadata-modules/view/enums/view-type.enum';
import { ViewVisibility } from 'src/engine/metadata-modules/view/enums/view-visibility.enum';
import { SyncableEntityRequired } from 'src/engine/workspace-manager/types/syncable-entity-required.interface';
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
// We could refactor this type to be dynamic to view type
@Entity({ name: 'view', schema: 'core' })
@@ -46,10 +46,7 @@ import { SyncableEntityRequired } from 'src/engine/workspace-manager/types/synca
'CHK_VIEW_CALENDAR_INTEGRITY',
`("type" != 'CALENDAR' OR ("calendarLayout" IS NOT NULL AND "calendarFieldMetadataId" IS NOT NULL))`,
)
export class ViewEntity
extends SyncableEntityRequired
implements Required<ViewEntity>
{
export class ViewEntity extends SyncableEntity implements Required<ViewEntity> {
@PrimaryGeneratedColumn('uuid')
id: string;
@@ -1,22 +0,0 @@
import { Column, Index, JoinColumn, ManyToOne, type Relation } from 'typeorm';
import type { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
import { WorkspaceRelatedEntity } from 'src/engine/workspace-manager/types/workspace-related-entity';
@Index(['workspaceId', 'universalIdentifier'], {
unique: true,
})
export abstract class SyncableEntityRequired extends WorkspaceRelatedEntity {
@Column({ nullable: false, type: 'uuid' })
universalIdentifier: string;
@Column({ nullable: false, type: 'uuid' })
applicationId: string;
@ManyToOne('ApplicationEntity', {
onDelete: 'CASCADE',
nullable: false,
})
@JoinColumn({ name: 'applicationId' })
application: Relation<ApplicationEntity>;
}
@@ -7,16 +7,15 @@ import { WorkspaceRelatedEntity } from 'src/engine/workspace-manager/types/works
unique: true,
})
export abstract class SyncableEntity extends WorkspaceRelatedEntity {
@Column({ nullable: true, type: 'uuid' })
// TODO should not be nullable
@Column({ nullable: false, type: 'uuid' })
universalIdentifier: string;
@Column({ nullable: true, type: 'uuid' })
applicationId: string | null;
@Column({ nullable: false, type: 'uuid' })
applicationId: string;
@ManyToOne('ApplicationEntity', {
onDelete: 'CASCADE',
nullable: true,
nullable: false,
})
@JoinColumn({ name: 'applicationId' })
application: Relation<ApplicationEntity>;
@@ -258,7 +258,7 @@ describe('WorkflowVersionStepOperationsWorkspaceService', () => {
isTool: false,
serverlessFunctionLayerId: 'layer-id',
universalIdentifier: 'universal-id',
applicationId: null,
applicationId: 'application-id',
cronTriggerIds: [],
databaseEventTriggerIds: [],
routeTriggerIds: [],
@@ -337,7 +337,7 @@ describe('WorkflowVersionStepOperationsWorkspaceService', () => {
isTool: false,
serverlessFunctionLayerId: 'layer-id',
universalIdentifier: 'universal-id',
applicationId: null,
applicationId: 'application-id',
cronTriggerIds: [],
databaseEventTriggerIds: [],
routeTriggerIds: [],