chore: remove 1-19 upgrade commands and navigation menu item feature flags (#19083)
## Summary - Deletes the entire `1-19` upgrade version command directory (7 files, ~1500 lines) and removes all references from the upgrade module and command runner. - Removes `IS_NAVIGATION_MENU_ITEM_ENABLED` and `IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED` feature flags from the enum, seed data, generated schema files, and test mocks. These flags had no remaining feature-gated code — navigation menu items are now always enabled.
This commit is contained in:
@@ -1726,8 +1726,6 @@ enum FeatureFlagKey {
|
||||
IS_EMAILING_DOMAIN_ENABLED
|
||||
IS_JUNCTION_RELATIONS_ENABLED
|
||||
IS_COMMAND_MENU_ITEM_ENABLED
|
||||
IS_NAVIGATION_MENU_ITEM_ENABLED
|
||||
IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED
|
||||
IS_DRAFT_EMAIL_ENABLED
|
||||
IS_USAGE_ANALYTICS_ENABLED
|
||||
IS_RICH_TEXT_V1_MIGRATED
|
||||
|
||||
@@ -1422,7 +1422,7 @@ export interface PublicFeatureFlag {
|
||||
__typename: 'PublicFeatureFlag'
|
||||
}
|
||||
|
||||
export type FeatureFlagKey = 'IS_UNIQUE_INDEXES_ENABLED' | 'IS_JSON_FILTER_ENABLED' | 'IS_AI_ENABLED' | 'IS_MARKETPLACE_ENABLED' | 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED' | 'IS_PUBLIC_DOMAIN_ENABLED' | 'IS_EMAILING_DOMAIN_ENABLED' | 'IS_JUNCTION_RELATIONS_ENABLED' | 'IS_COMMAND_MENU_ITEM_ENABLED' | 'IS_NAVIGATION_MENU_ITEM_ENABLED' | 'IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED' | 'IS_DRAFT_EMAIL_ENABLED' | 'IS_USAGE_ANALYTICS_ENABLED' | 'IS_RICH_TEXT_V1_MIGRATED' | 'IS_DIRECT_GRAPHQL_EXECUTION_ENABLED' | 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED' | 'IS_CONNECTED_ACCOUNT_MIGRATED' | 'IS_GRAPHQL_QUERY_TIMING_ENABLED' | 'IS_RECORD_TABLE_WIDGET_ENABLED' | 'IS_DATASOURCE_MIGRATED'
|
||||
export type FeatureFlagKey = 'IS_UNIQUE_INDEXES_ENABLED' | 'IS_JSON_FILTER_ENABLED' | 'IS_AI_ENABLED' | 'IS_MARKETPLACE_ENABLED' | 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED' | 'IS_PUBLIC_DOMAIN_ENABLED' | 'IS_EMAILING_DOMAIN_ENABLED' | 'IS_JUNCTION_RELATIONS_ENABLED' | 'IS_COMMAND_MENU_ITEM_ENABLED' | 'IS_DRAFT_EMAIL_ENABLED' | 'IS_USAGE_ANALYTICS_ENABLED' | 'IS_RICH_TEXT_V1_MIGRATED' | 'IS_DIRECT_GRAPHQL_EXECUTION_ENABLED' | 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED' | 'IS_CONNECTED_ACCOUNT_MIGRATED' | 'IS_GRAPHQL_QUERY_TIMING_ENABLED' | 'IS_RECORD_TABLE_WIDGET_ENABLED' | 'IS_DATASOURCE_MIGRATED'
|
||||
|
||||
export interface ClientConfig {
|
||||
appVersion?: Scalars['String']
|
||||
@@ -8953,8 +8953,6 @@ export const enumFeatureFlagKey = {
|
||||
IS_EMAILING_DOMAIN_ENABLED: 'IS_EMAILING_DOMAIN_ENABLED' as const,
|
||||
IS_JUNCTION_RELATIONS_ENABLED: 'IS_JUNCTION_RELATIONS_ENABLED' as const,
|
||||
IS_COMMAND_MENU_ITEM_ENABLED: 'IS_COMMAND_MENU_ITEM_ENABLED' as const,
|
||||
IS_NAVIGATION_MENU_ITEM_ENABLED: 'IS_NAVIGATION_MENU_ITEM_ENABLED' as const,
|
||||
IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED: 'IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED' as const,
|
||||
IS_DRAFT_EMAIL_ENABLED: 'IS_DRAFT_EMAIL_ENABLED' as const,
|
||||
IS_USAGE_ANALYTICS_ENABLED: 'IS_USAGE_ANALYTICS_ENABLED' as const,
|
||||
IS_RICH_TEXT_V1_MIGRATED: 'IS_RICH_TEXT_V1_MIGRATED' as const,
|
||||
|
||||
@@ -1702,8 +1702,6 @@ export enum FeatureFlagKey {
|
||||
IS_JSON_FILTER_ENABLED = 'IS_JSON_FILTER_ENABLED',
|
||||
IS_JUNCTION_RELATIONS_ENABLED = 'IS_JUNCTION_RELATIONS_ENABLED',
|
||||
IS_MARKETPLACE_ENABLED = 'IS_MARKETPLACE_ENABLED',
|
||||
IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED = 'IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED',
|
||||
IS_NAVIGATION_MENU_ITEM_ENABLED = 'IS_NAVIGATION_MENU_ITEM_ENABLED',
|
||||
IS_PUBLIC_DOMAIN_ENABLED = 'IS_PUBLIC_DOMAIN_ENABLED',
|
||||
IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED = 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED',
|
||||
IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED = 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED',
|
||||
|
||||
-241
@@ -1,241 +0,0 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Command } from 'nest-commander';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { 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 { ADD_MISSING_SYSTEM_FIELDS_TO_STANDARD_OBJECTS_1771420702241 } from 'src/database/commands/upgrade-version-command/workspace-migrations/1771420702241-add-missing-system-fields-to-standard-objects';
|
||||
import { WorkspaceMigrationRunnerException } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/exceptions/workspace-migration-runner.exception';
|
||||
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';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
import { type WorkspaceMigration } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/workspace-migration.type';
|
||||
import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/services/workspace-migration-runner.service';
|
||||
|
||||
const { applicationUniversalIdentifier, actions: allActions } =
|
||||
ADD_MISSING_SYSTEM_FIELDS_TO_STANDARD_OBJECTS_1771420702241;
|
||||
|
||||
const NON_TS_VECTOR_MIGRATION: WorkspaceMigration = {
|
||||
applicationUniversalIdentifier,
|
||||
actions: allActions.filter(
|
||||
(action) => action.flatEntity.type !== FieldMetadataType.TS_VECTOR,
|
||||
),
|
||||
};
|
||||
|
||||
const TS_VECTOR_INDIVIDUAL_MIGRATIONS = allActions
|
||||
.filter((action) => action.flatEntity.type === FieldMetadataType.TS_VECTOR)
|
||||
.map((action) => ({
|
||||
universalIdentifier: action.flatEntity.universalIdentifier,
|
||||
fieldName: action.flatEntity.name,
|
||||
objectIdentifier: action.flatEntity.objectMetadataUniversalIdentifier,
|
||||
migration: {
|
||||
applicationUniversalIdentifier,
|
||||
actions: [action],
|
||||
} satisfies WorkspaceMigration,
|
||||
}));
|
||||
|
||||
const NON_TS_VECTOR_INDIVIDUAL_MIGRATIONS = allActions
|
||||
.filter((action) => action.flatEntity.type !== FieldMetadataType.TS_VECTOR)
|
||||
.map((action) => ({
|
||||
universalIdentifier: action.flatEntity.universalIdentifier,
|
||||
fieldName: action.flatEntity.name,
|
||||
objectIdentifier: action.flatEntity.objectMetadataUniversalIdentifier,
|
||||
migration: {
|
||||
applicationUniversalIdentifier,
|
||||
actions: [action],
|
||||
} satisfies WorkspaceMigration,
|
||||
}));
|
||||
|
||||
const FIRST_NON_TS_VECTOR_UNIVERSAL_IDENTIFIER =
|
||||
allActions[0].flatEntity.universalIdentifier;
|
||||
|
||||
const DUPLICATE_KEY_MESSAGE = 'duplicate key value violates unique constraint';
|
||||
|
||||
const getNestedErrorMessages = (
|
||||
error: WorkspaceMigrationRunnerException,
|
||||
): string | undefined => {
|
||||
const nestedErrors = error.errors;
|
||||
|
||||
if (!isDefined(nestedErrors)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const details = [
|
||||
nestedErrors.metadata && `metadata: ${nestedErrors.metadata.message}`,
|
||||
nestedErrors.workspaceSchema &&
|
||||
`workspaceSchema: ${nestedErrors.workspaceSchema.message}`,
|
||||
nestedErrors.actionTranspilation &&
|
||||
`actionTranspilation: ${nestedErrors.actionTranspilation.message}`,
|
||||
]
|
||||
.filter(isDefined)
|
||||
.join('; ');
|
||||
|
||||
return details || undefined;
|
||||
};
|
||||
|
||||
const isUniqueViolationError = (error: Error): boolean => {
|
||||
if (error.message.includes(DUPLICATE_KEY_MESSAGE)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (error instanceof WorkspaceMigrationRunnerException) {
|
||||
const nestedMessages = getNestedErrorMessages(error);
|
||||
|
||||
return nestedMessages?.includes(DUPLICATE_KEY_MESSAGE) === true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const enrichErrorMessage = (error: Error): Error => {
|
||||
if (!(error instanceof WorkspaceMigrationRunnerException)) {
|
||||
return error;
|
||||
}
|
||||
|
||||
const details = getNestedErrorMessages(error);
|
||||
|
||||
if (isDefined(details)) {
|
||||
error.message = `${error.message} (${details})`;
|
||||
}
|
||||
|
||||
return error;
|
||||
};
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:1-19:add-missing-system-fields-to-standard-objects',
|
||||
description:
|
||||
'Add missing system fields (position, searchVector, createdBy, updatedBy) to standard objects',
|
||||
})
|
||||
export class AddMissingSystemFieldsToStandardObjectsCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(WorkspaceEntity)
|
||||
protected readonly workspaceRepository: Repository<WorkspaceEntity>,
|
||||
protected readonly twentyORMGlobalManager: GlobalWorkspaceOrmManager,
|
||||
protected readonly dataSourceService: DataSourceService,
|
||||
private readonly workspaceCacheService: WorkspaceCacheService,
|
||||
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager, dataSourceService);
|
||||
}
|
||||
|
||||
private async runIndividualMigrations(
|
||||
workspaceId: string,
|
||||
migrations: {
|
||||
universalIdentifier: string;
|
||||
fieldName: string;
|
||||
objectIdentifier: string;
|
||||
migration: WorkspaceMigration;
|
||||
}[],
|
||||
): Promise<void> {
|
||||
for (const entry of migrations) {
|
||||
const alreadyCreated = await this.hasFieldBeenCreated(
|
||||
workspaceId,
|
||||
entry.universalIdentifier,
|
||||
);
|
||||
|
||||
if (alreadyCreated) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
`Adding field ${entry.fieldName} on object ${entry.objectIdentifier} in workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
try {
|
||||
await this.workspaceMigrationRunnerService.run({
|
||||
workspaceId,
|
||||
workspaceMigration: entry.migration,
|
||||
});
|
||||
} catch (error) {
|
||||
if (!isUniqueViolationError(error)) {
|
||||
throw enrichErrorMessage(error);
|
||||
}
|
||||
|
||||
this.logger.warn(
|
||||
`Field ${entry.fieldName} on object ${entry.objectIdentifier} already exists in workspace ${workspaceId}, skipping`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async hasFieldBeenCreated(
|
||||
workspaceId: string,
|
||||
universalIdentifier: string,
|
||||
): Promise<boolean> {
|
||||
const { flatFieldMetadataMaps } =
|
||||
await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
'flatFieldMetadataMaps',
|
||||
]);
|
||||
|
||||
return isDefined(
|
||||
flatFieldMetadataMaps.byUniversalIdentifier[universalIdentifier],
|
||||
);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
workspaceId,
|
||||
options,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
const dryRun = options?.dryRun ?? false;
|
||||
|
||||
this.logger.log(
|
||||
`${dryRun ? '[DRY RUN] ' : ''}Adding missing system fields to standard objects in workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
if (dryRun) {
|
||||
this.logger.log(
|
||||
`[DRY RUN] Would add ${NON_TS_VECTOR_MIGRATION.actions.length} non-tsVector fields and ${TS_VECTOR_INDIVIDUAL_MIGRATIONS.length} tsVector fields to standard objects in workspace ${workspaceId}. Skipping.`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const nonTsVectorAlreadyRan = await this.hasFieldBeenCreated(
|
||||
workspaceId,
|
||||
FIRST_NON_TS_VECTOR_UNIVERSAL_IDENTIFIER,
|
||||
);
|
||||
|
||||
if (!nonTsVectorAlreadyRan) {
|
||||
this.logger.log(
|
||||
`Adding ${NON_TS_VECTOR_MIGRATION.actions.length} non-tsVector fields (position, createdBy, updatedBy) in workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
try {
|
||||
await this.workspaceMigrationRunnerService.run({
|
||||
workspaceId,
|
||||
workspaceMigration: NON_TS_VECTOR_MIGRATION,
|
||||
});
|
||||
} catch (error) {
|
||||
if (!isUniqueViolationError(error)) {
|
||||
throw enrichErrorMessage(error);
|
||||
}
|
||||
|
||||
this.logger.warn(
|
||||
`Batch non-tsVector migration hit a duplicate field in workspace ${workspaceId}, falling back to individual field migrations`,
|
||||
);
|
||||
|
||||
await this.runIndividualMigrations(
|
||||
workspaceId,
|
||||
NON_TS_VECTOR_INDIVIDUAL_MIGRATIONS,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this.logger.log(
|
||||
`Non-tsVector fields already exist in workspace ${workspaceId}, skipping.`,
|
||||
);
|
||||
}
|
||||
|
||||
await this.runIndividualMigrations(
|
||||
workspaceId,
|
||||
TS_VECTOR_INDIVIDUAL_MIGRATIONS,
|
||||
);
|
||||
|
||||
this.logger.log(
|
||||
`Successfully added missing system fields to standard objects in workspace ${workspaceId}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
-157
@@ -1,157 +0,0 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Command } from 'nest-commander';
|
||||
import { STANDARD_OBJECTS } from 'twenty-shared/metadata';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { 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/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 { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
import { findManyFlatEntityByUniversalIdentifierInUniversalFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-universal-identifier-in-universal-flat-entity-maps-or-throw.util';
|
||||
import { isMorphOrRelationUniversalFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-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 { computeTwentyStandardApplicationAllFlatEntityMaps } from 'src/engine/workspace-manager/twenty-standard-application/utils/twenty-standard-application-all-flat-entity-maps.constant';
|
||||
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service';
|
||||
|
||||
const OBJECT_UNIVERSAL_IDENTIFIER_TO_CREATE =
|
||||
STANDARD_OBJECTS.messageChannelMessageAssociationMessageFolder
|
||||
.universalIdentifier;
|
||||
const FIELD_UNIVERSAL_IDENTIFIERS_TO_CREATE = Object.values(
|
||||
STANDARD_OBJECTS.messageChannelMessageAssociationMessageFolder.fields,
|
||||
).map((el) => el.universalIdentifier);
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:1-19:backfill-message-channel-message-association-message-folder',
|
||||
description:
|
||||
'Backfill messageChannelMessageAssociationMessageFolder standard object and its relation fields',
|
||||
})
|
||||
export class BackfillMessageChannelMessageAssociationMessageFolderCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(WorkspaceEntity)
|
||||
protected readonly workspaceRepository: Repository<WorkspaceEntity>,
|
||||
protected readonly twentyORMGlobalManager: GlobalWorkspaceOrmManager,
|
||||
protected readonly dataSourceService: DataSourceService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
private readonly workspaceCacheService: WorkspaceCacheService,
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager, dataSourceService);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
workspaceId,
|
||||
options,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
const isDryRun = options.dryRun ?? false;
|
||||
|
||||
this.logger.log(
|
||||
`${isDryRun ? '[DRY RUN] ' : ''}Starting backfill of messageChannelMessageAssociationMessageFolder for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
const { flatObjectMetadataMaps } =
|
||||
await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
'flatObjectMetadataMaps',
|
||||
]);
|
||||
|
||||
const existingObject = findFlatEntityByUniversalIdentifier({
|
||||
flatEntityMaps: flatObjectMetadataMaps,
|
||||
universalIdentifier: OBJECT_UNIVERSAL_IDENTIFIER_TO_CREATE,
|
||||
});
|
||||
|
||||
if (existingObject) {
|
||||
this.logger.log(
|
||||
`messageChannelMessageAssociationMessageFolder object already exists for workspace ${workspaceId}, skipping`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDryRun) {
|
||||
this.logger.log(
|
||||
`[DRY RUN] Would create messageChannelMessageAssociationMessageFolder object and relation fields for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const { twentyStandardFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { allFlatEntityMaps: standardAllFlatEntityMaps } =
|
||||
computeTwentyStandardApplicationAllFlatEntityMaps({
|
||||
now: new Date().toISOString(),
|
||||
workspaceId,
|
||||
twentyStandardApplicationId: twentyStandardFlatApplication.id,
|
||||
});
|
||||
|
||||
const flatObjectMetadataToCreate =
|
||||
findFlatEntityByUniversalIdentifierOrThrow({
|
||||
flatEntityMaps: standardAllFlatEntityMaps.flatObjectMetadataMaps,
|
||||
universalIdentifier: OBJECT_UNIVERSAL_IDENTIFIER_TO_CREATE,
|
||||
});
|
||||
|
||||
const flatFieldMetadataToCreateOnObject =
|
||||
findManyFlatEntityByUniversalIdentifierInUniversalFlatEntityMapsOrThrow({
|
||||
flatEntityMaps: standardAllFlatEntityMaps.flatFieldMetadataMaps,
|
||||
universalIdentifiers: FIELD_UNIVERSAL_IDENTIFIERS_TO_CREATE,
|
||||
});
|
||||
const relatedFlatFieldMetadataToCreate = flatFieldMetadataToCreateOnObject
|
||||
.map((flatFieldMetadata) => {
|
||||
if (!isMorphOrRelationUniversalFlatFieldMetadata(flatFieldMetadata)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return findFlatEntityByUniversalIdentifierOrThrow({
|
||||
flatEntityMaps: standardAllFlatEntityMaps.flatFieldMetadataMaps,
|
||||
universalIdentifier:
|
||||
flatFieldMetadata.relationTargetFieldMetadataUniversalIdentifier,
|
||||
});
|
||||
})
|
||||
.filter(isDefined);
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
allFlatEntityOperationByMetadataName: {
|
||||
objectMetadata: {
|
||||
flatEntityToCreate: [flatObjectMetadataToCreate],
|
||||
flatEntityToDelete: [],
|
||||
flatEntityToUpdate: [],
|
||||
},
|
||||
fieldMetadata: {
|
||||
flatEntityToCreate: [
|
||||
...flatFieldMetadataToCreateOnObject,
|
||||
...relatedFlatFieldMetadataToCreate,
|
||||
],
|
||||
flatEntityToDelete: [],
|
||||
flatEntityToUpdate: [],
|
||||
},
|
||||
},
|
||||
workspaceId,
|
||||
applicationUniversalIdentifier:
|
||||
twentyStandardFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
if (validateAndBuildResult.status === 'fail') {
|
||||
this.logger.error(
|
||||
`Failed to create messageChannelMessageAssociationMessageFolder:\n${JSON.stringify(validateAndBuildResult, null, 2)}`,
|
||||
);
|
||||
throw new Error(
|
||||
`Failed to create messageChannelMessageAssociationMessageFolder for workspace ${workspaceId}`,
|
||||
);
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
`Successfully created messageChannelMessageAssociationMessageFolder for workspace ${workspaceId}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
-185
@@ -1,185 +0,0 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Command } from 'nest-commander';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { 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/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 { 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 { computeTwentyStandardApplicationAllFlatEntityMaps } from 'src/engine/workspace-manager/twenty-standard-application/utils/twenty-standard-application-all-flat-entity-maps.constant';
|
||||
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service';
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:1-19:backfill-missing-standard-views',
|
||||
description:
|
||||
'Backfill missing standard views and their child entities (fields, groups, filters, field groups) for workspaces',
|
||||
})
|
||||
export class BackfillMissingStandardViewsCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(WorkspaceEntity)
|
||||
protected readonly workspaceRepository: Repository<WorkspaceEntity>,
|
||||
protected readonly twentyORMGlobalManager: GlobalWorkspaceOrmManager,
|
||||
protected readonly dataSourceService: DataSourceService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly workspaceCacheService: WorkspaceCacheService,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager, dataSourceService);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
workspaceId,
|
||||
options,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
const isDryRun = options.dryRun ?? false;
|
||||
|
||||
this.logger.log(
|
||||
`${isDryRun ? '[DRY RUN] ' : ''}Starting backfill of missing standard views for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
const { twentyStandardFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { allFlatEntityMaps: standardAllFlatEntityMaps } =
|
||||
computeTwentyStandardApplicationAllFlatEntityMaps({
|
||||
shouldIncludeRecordPageLayouts: true,
|
||||
now: new Date().toISOString(),
|
||||
workspaceId,
|
||||
twentyStandardApplicationId: twentyStandardFlatApplication.id,
|
||||
});
|
||||
|
||||
const { flatViewMaps: existingFlatViewMaps } =
|
||||
await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
'flatViewMaps',
|
||||
]);
|
||||
|
||||
const missingViewUniversalIdentifiers = new Set<string>();
|
||||
|
||||
const viewsToCreate = Object.values(
|
||||
standardAllFlatEntityMaps.flatViewMaps.byUniversalIdentifier,
|
||||
)
|
||||
.filter(isDefined)
|
||||
.filter((view) => {
|
||||
const alreadyExists = isDefined(
|
||||
existingFlatViewMaps.byUniversalIdentifier[view.universalIdentifier],
|
||||
);
|
||||
|
||||
if (alreadyExists) {
|
||||
return false;
|
||||
}
|
||||
|
||||
missingViewUniversalIdentifiers.add(view.universalIdentifier);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
if (viewsToCreate.length === 0) {
|
||||
this.logger.log(
|
||||
`No missing standard views for workspace ${workspaceId}, skipping`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
`Found ${viewsToCreate.length} missing standard view(s) for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
if (isDryRun) {
|
||||
this.logger.log(
|
||||
`[DRY RUN] Would create ${viewsToCreate.length} view(s) for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const viewFieldsToCreate = Object.values(
|
||||
standardAllFlatEntityMaps.flatViewFieldMaps.byUniversalIdentifier,
|
||||
)
|
||||
.filter(isDefined)
|
||||
.filter((viewField) =>
|
||||
missingViewUniversalIdentifiers.has(viewField.viewUniversalIdentifier),
|
||||
);
|
||||
|
||||
const viewGroupsToCreate = Object.values(
|
||||
standardAllFlatEntityMaps.flatViewGroupMaps.byUniversalIdentifier,
|
||||
)
|
||||
.filter(isDefined)
|
||||
.filter((viewGroup) =>
|
||||
missingViewUniversalIdentifiers.has(viewGroup.viewUniversalIdentifier),
|
||||
);
|
||||
|
||||
const viewFiltersToCreate = Object.values(
|
||||
standardAllFlatEntityMaps.flatViewFilterMaps.byUniversalIdentifier,
|
||||
)
|
||||
.filter(isDefined)
|
||||
.filter((viewFilter) =>
|
||||
missingViewUniversalIdentifiers.has(viewFilter.viewUniversalIdentifier),
|
||||
);
|
||||
|
||||
const viewFieldGroupsToCreate = Object.values(
|
||||
standardAllFlatEntityMaps.flatViewFieldGroupMaps.byUniversalIdentifier,
|
||||
)
|
||||
.filter(isDefined)
|
||||
.filter((viewFieldGroup) =>
|
||||
missingViewUniversalIdentifiers.has(
|
||||
viewFieldGroup.viewUniversalIdentifier,
|
||||
),
|
||||
);
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
allFlatEntityOperationByMetadataName: {
|
||||
view: {
|
||||
flatEntityToCreate: viewsToCreate,
|
||||
flatEntityToDelete: [],
|
||||
flatEntityToUpdate: [],
|
||||
},
|
||||
viewField: {
|
||||
flatEntityToCreate: viewFieldsToCreate,
|
||||
flatEntityToDelete: [],
|
||||
flatEntityToUpdate: [],
|
||||
},
|
||||
viewGroup: {
|
||||
flatEntityToCreate: viewGroupsToCreate,
|
||||
flatEntityToDelete: [],
|
||||
flatEntityToUpdate: [],
|
||||
},
|
||||
viewFilter: {
|
||||
flatEntityToCreate: viewFiltersToCreate,
|
||||
flatEntityToDelete: [],
|
||||
flatEntityToUpdate: [],
|
||||
},
|
||||
viewFieldGroup: {
|
||||
flatEntityToCreate: viewFieldGroupsToCreate,
|
||||
flatEntityToDelete: [],
|
||||
flatEntityToUpdate: [],
|
||||
},
|
||||
},
|
||||
workspaceId,
|
||||
applicationUniversalIdentifier:
|
||||
twentyStandardFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
if (validateAndBuildResult.status === 'fail') {
|
||||
this.logger.warn(
|
||||
`Failed to backfill missing standard views for workspace ${workspaceId}, skipping:\n${JSON.stringify(validateAndBuildResult)}`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
`Successfully backfilled ${viewsToCreate.length} standard view(s) for workspace ${workspaceId}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
-176
@@ -1,176 +0,0 @@
|
||||
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Command } from 'nest-commander';
|
||||
import { STANDARD_OBJECTS } from 'twenty-shared/metadata';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
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 { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
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 { PARTIAL_SYSTEM_FLAT_FIELD_METADATAS } from 'src/engine/metadata-modules/object-metadata/constants/partial-system-flat-field-metadatas.constant';
|
||||
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
import { type WorkspaceCacheKeyName } from 'src/engine/workspace-cache/types/workspace-cache-key.type';
|
||||
|
||||
const SYSTEM_FIELD_NAMES = Object.keys(PARTIAL_SYSTEM_FLAT_FIELD_METADATAS);
|
||||
|
||||
const POSITION_FIELDS_TO_FIX_TYPE = [
|
||||
STANDARD_OBJECTS.favorite.fields.position.universalIdentifier,
|
||||
STANDARD_OBJECTS.favoriteFolder.fields.position.universalIdentifier,
|
||||
];
|
||||
|
||||
const RELATION_FIELD_TYPES = [
|
||||
FieldMetadataType.RELATION,
|
||||
FieldMetadataType.MORPH_RELATION,
|
||||
];
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:1-19:backfill-system-fields-is-system',
|
||||
description:
|
||||
'Set isSystem to true for system field names, set isSystem to false for relation/morph_relation fields, and fix position field type for favorite/favoriteFolder',
|
||||
})
|
||||
export class BackfillSystemFieldsIsSystemCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(WorkspaceEntity)
|
||||
protected readonly workspaceRepository: Repository<WorkspaceEntity>,
|
||||
@InjectDataSource()
|
||||
private readonly coreDataSource: DataSource,
|
||||
protected readonly twentyORMGlobalManager: GlobalWorkspaceOrmManager,
|
||||
protected readonly dataSourceService: DataSourceService,
|
||||
private readonly workspaceCacheService: WorkspaceCacheService,
|
||||
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
|
||||
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager, dataSourceService);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
workspaceId,
|
||||
options,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
const dryRun = options?.dryRun ?? false;
|
||||
|
||||
this.logger.log(
|
||||
`${dryRun ? '[DRY RUN] ' : ''}Backfilling isSystem for system fields in workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
if (dryRun) {
|
||||
this.logger.log(
|
||||
`[DRY RUN] Would set isSystem=true for fields named [${SYSTEM_FIELD_NAMES.join(', ')}], set isSystem=false for relation fields, and fix position field types in workspace ${workspaceId}. Skipping.`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const queryRunner = this.coreDataSource.createQueryRunner();
|
||||
|
||||
await queryRunner.connect();
|
||||
|
||||
try {
|
||||
let needsCacheInvalidation = false;
|
||||
|
||||
const isSystemResult = await queryRunner.query(
|
||||
`UPDATE core."fieldMetadata"
|
||||
SET "isSystem" = true
|
||||
WHERE "workspaceId" = $1
|
||||
AND "name" = ANY($2)
|
||||
AND "isSystem" = false`,
|
||||
[workspaceId, SYSTEM_FIELD_NAMES],
|
||||
);
|
||||
|
||||
const isSystemUpdatedCount = isSystemResult?.[1] ?? 0;
|
||||
|
||||
if (isSystemUpdatedCount > 0) {
|
||||
this.logger.log(
|
||||
`Set isSystem=true for ${isSystemUpdatedCount} field(s) in workspace ${workspaceId}`,
|
||||
);
|
||||
needsCacheInvalidation = true;
|
||||
}
|
||||
|
||||
const relationIsSystemResult = await queryRunner.query(
|
||||
`UPDATE core."fieldMetadata"
|
||||
SET "isSystem" = false
|
||||
WHERE "workspaceId" = $1
|
||||
AND "type" = ANY($2)
|
||||
AND "isSystem" = true`,
|
||||
[workspaceId, RELATION_FIELD_TYPES],
|
||||
);
|
||||
|
||||
const relationIsSystemUpdatedCount = relationIsSystemResult?.[1] ?? 0;
|
||||
|
||||
if (relationIsSystemUpdatedCount > 0) {
|
||||
this.logger.log(
|
||||
`Set isSystem=false for ${relationIsSystemUpdatedCount} relation field(s) in workspace ${workspaceId}`,
|
||||
);
|
||||
needsCacheInvalidation = true;
|
||||
}
|
||||
|
||||
const positionTypeResult = await queryRunner.query(
|
||||
`UPDATE core."fieldMetadata"
|
||||
SET "type" = $1
|
||||
WHERE "workspaceId" = $2
|
||||
AND "universalIdentifier" = ANY($3)
|
||||
AND "type" = $4`,
|
||||
[
|
||||
FieldMetadataType.POSITION,
|
||||
workspaceId,
|
||||
POSITION_FIELDS_TO_FIX_TYPE,
|
||||
FieldMetadataType.NUMBER,
|
||||
],
|
||||
);
|
||||
|
||||
const positionTypeUpdatedCount = positionTypeResult?.[1] ?? 0;
|
||||
|
||||
if (positionTypeUpdatedCount > 0) {
|
||||
this.logger.log(
|
||||
`Fixed type from NUMBER to POSITION for ${positionTypeUpdatedCount} field(s) in workspace ${workspaceId}`,
|
||||
);
|
||||
needsCacheInvalidation = true;
|
||||
}
|
||||
|
||||
if (needsCacheInvalidation) {
|
||||
await this.invalidateCaches(workspaceId);
|
||||
} else {
|
||||
this.logger.log(
|
||||
`No fields needed updating in workspace ${workspaceId}`,
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
|
||||
private async invalidateCaches(workspaceId: string): Promise<void> {
|
||||
const modifiedMetadataNames = ['fieldMetadata'] as const;
|
||||
|
||||
const cacheKeysToInvalidate: WorkspaceCacheKeyName[] = [
|
||||
...new Set(
|
||||
modifiedMetadataNames
|
||||
.flatMap((name) => [name, ...getMetadataRelatedMetadataNames(name)])
|
||||
.map(getMetadataFlatEntityMapsKey),
|
||||
),
|
||||
'ORMEntityMetadatas',
|
||||
];
|
||||
|
||||
await this.workspaceCacheService.invalidateAndRecompute(
|
||||
workspaceId,
|
||||
cacheKeysToInvalidate,
|
||||
);
|
||||
|
||||
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await this.workspaceCacheStorageService.flush(workspaceId);
|
||||
|
||||
this.logger.log(
|
||||
`Cache invalidated and metadata version incremented for workspace ${workspaceId}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
-677
@@ -1,677 +0,0 @@
|
||||
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 { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
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 { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
import { type WorkspaceCacheKeyName } from 'src/engine/workspace-cache/types/workspace-cache-key.type';
|
||||
import { STANDARD_AGENT } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-agent.constant';
|
||||
import { STANDARD_ROLE } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-role.constant';
|
||||
import { STANDARD_SKILL } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-skill.constant';
|
||||
|
||||
const OLD_ROLE_ADMIN_UNIVERSAL_IDENTIFIER =
|
||||
'20202020-0001-0001-0001-000000000001';
|
||||
const OLD_AGENT_HELPER_UNIVERSAL_IDENTIFIER =
|
||||
'20202020-0002-0001-0001-000000000004';
|
||||
|
||||
const STANDARD_OBJECT_MISMATCHES = [
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: 'c9e5a0b4-1d36-4f8c-0a7b-3e4f5d6c7a81',
|
||||
newValue: '9d31ea73-13b6-4e06-84ee-c66c72bf7787',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: 'd0f6b1c5-2e47-4a9d-1b8c-4f5a6e7d8b92',
|
||||
newValue: '55637a5a-1edc-4351-8d76-d40020bf8944',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: 'e1a7c2d6-3f58-4b0e-2c9d-5a6b7f8e9c03',
|
||||
newValue: '4137ba06-184d-438f-b484-080f02a97659',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: 'f2b8d3e7-4a69-4c1f-3d0e-6b7c8a9f0d14',
|
||||
newValue: '8cc162d1-c127-4981-878d-f78622f8f12d',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '03c9e4f8-5b70-4d2a-4e1f-7c8d9b0a1e25',
|
||||
newValue: 'c10eba2d-ff1a-4eab-9285-50481c12a003',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '14d0f5a9-6c81-4e3b-5f2a-8d9e0c1b2f36',
|
||||
newValue: 'fadeab4b-79ee-4173-af79-72c51fbad888',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '25e1a6b0-7d92-4f4c-6a3b-9e0f1d2c3a47',
|
||||
newValue: '4daf320e-74d0-4f24-a45a-af3a09d741cb',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '36f2b7c1-8e03-4a5d-7b4c-0f1a2e3d4b58',
|
||||
newValue: 'ff6b86c1-3112-4dfa-b734-c4789111a716',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '69c5e0f4-1b36-4d8a-0e7f-3c4d5b6a7e81',
|
||||
newValue: 'c458ad97-8b95-43de-9003-88eb68576049',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '70d6f1a5-2c47-4e9b-1f8a-4d5e6c7b8f92',
|
||||
newValue: '30e9b75a-881f-4a85-aaf1-f2d2464be1cf',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '81e7a2b6-3d58-4f0c-2a9b-5e6f7d8c9003',
|
||||
newValue: '898aa202-428f-4a7a-a3b3-8f0a17a6658e',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '92f8b3c7-4e69-4a1d-3b0c-6f7a8e9d0114',
|
||||
newValue: 'ec2ebfc9-0c9b-4597-a87d-aa295e2d8bfe',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: 'a3a9c4d8-5f70-4b2e-4c1d-7a8b9f0e1225',
|
||||
newValue: 'dd300c61-f422-467a-91f4-de4f83c4175b',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: 'b4b0d5e9-6a81-4c3f-5d2e-8b9c0a1f2336',
|
||||
newValue: 'c3eb62df-2cc1-4cc3-b7aa-e96a4d65c633',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: 'c5c1e6f0-7b92-4d4a-6e3f-9c0d1b2a3447',
|
||||
newValue: '8e7ca28e-6002-4304-9dcc-0a8da93ca198',
|
||||
},
|
||||
{
|
||||
table: 'core."fieldMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '20202020-9b0c-5d6e-7f8a-9b0c1d2e3f4a',
|
||||
newValue: '99c330c0-5b7d-4276-a764-aed84499dfb5',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: 'd6d2f7a1-8c03-4e5b-7f4a-0d1e2c3b4558',
|
||||
newValue: 'e69f71aa-de0f-4b70-845f-7a8369c47928',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '0905c0d4-1f36-4b8e-0c7d-3a4b5f6e788b',
|
||||
newValue: '1f360393-a336-435d-966d-8ec2645f875c',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '1016d1e5-2a47-4c9f-1d8e-4b5c6a7f899c',
|
||||
newValue: 'c0369a13-49bd-48b0-a9f0-6ed0ee8e1b09',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '2127e2f6-3b58-4d0a-2e9f-5c6d7b80900d',
|
||||
newValue: 'b8e9f696-5be4-48cb-815c-7c0bb8b69d38',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '3238f3a7-4c69-4e1b-3f0a-6d7e8c91011e',
|
||||
newValue: 'd4f3ef9f-ae24-4cef-9d7a-684a24d4968b',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '4349a4b8-5d70-4f2c-4a1b-7e8f9d02122f',
|
||||
newValue: 'a257158e-3a89-4715-970c-7fc38ac22370',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '5450b5c9-6e81-4a3d-5b2c-8f90ae132340',
|
||||
newValue: 'd55711a3-3297-4fef-beab-48d733712a33',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '6561c6d0-7f92-4b4e-6c3d-90a1bf243451',
|
||||
newValue: 'f30c9a75-a563-45a2-93b8-84f59004de8f',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '7672d7e1-8003-4c5f-7d4e-01b2c0354562',
|
||||
newValue: 'dca73027-adbe-4078-ae47-8d17850b9f2b',
|
||||
},
|
||||
{
|
||||
table: 'core."fieldMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '20202020-c3d4-e5f6-a7b8-901234567890',
|
||||
newValue: '9bfc9da7-ae2d-44fd-9563-ede90c5d6222',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '0905a0b4-1336-4f8c-0a7b-34e5f3687895',
|
||||
newValue: '9bb24d40-60dd-4beb-8c64-a74e8c67f9ee',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '1a16b1c5-2447-4a9d-1b8c-45f6a47989a6',
|
||||
newValue: '1b86ece8-7ce3-4df3-8771-fd4b5d45b2f2',
|
||||
},
|
||||
{
|
||||
table: 'core."fieldMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '20202020-d4e5-f6a7-b8c9-012345678901',
|
||||
newValue: '7411cfa3-4fd9-4b90-a636-940015fd7243',
|
||||
},
|
||||
{
|
||||
table: 'core."fieldMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '20202020-e5f6-a7b8-c9d0-123456789012',
|
||||
newValue: 'b3369d31-3856-4a7a-b007-ee353918127c',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '2b38d3e7-5779-4c1f-4e0f-78c9d70d1de9',
|
||||
newValue: '8e6038aa-1f79-4a84-87b5-f33caa172e98',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '3c49e4f8-6880-4d2a-5f1a-89d0e81e2ef0',
|
||||
newValue: '905299c3-ca81-435d-901c-f68b87562516',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '4d50f5a9-7991-4e3b-6a2b-90e1f92f3f01',
|
||||
newValue: 'a3de1788-5dff-4849-ac5a-0dabe5fab216',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '2b27c2d6-3558-4b0e-2c9d-56a7b58a9ab7',
|
||||
newValue: 'ab09a386-4dcc-41f7-8dc6-a6071e9c64b7',
|
||||
},
|
||||
{
|
||||
table: 'core."fieldMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '20202020-f6a7-b8c9-d0e1-234567890123',
|
||||
newValue: 'cce5ce1e-31d0-42e6-83cd-90059244a484',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '3c38d3e7-4669-4c1f-3d0e-67b8c69b0bc8',
|
||||
newValue: '6217f2a5-28ac-4b88-8a2a-45eee4580e57',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '4d49e4f8-5770-4d2a-4e1f-78c9d70c1cd9',
|
||||
newValue: 'ab0863ba-f95e-493c-b86c-56e1bc7e5bc2',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '5e50f5a9-6881-4e3b-5f2a-89d0e81d2de0',
|
||||
newValue: 'df805c2e-3bfe-4d51-8309-75e5eb4052fe',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '6f61a6b0-7992-4f4c-6a3b-90e1f92e3ef1',
|
||||
newValue: 'ce1e3a9e-afe9-439d-abb7-6cc98a6fa405',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '7072b7c1-8003-4a5d-7b4c-01f2a03f4f02',
|
||||
newValue: '7a05b45e-7aa6-4a7e-9bbc-299cbed53c96',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '0305e0f4-1336-4d8a-0e7f-34c5d36c7c35',
|
||||
newValue: '7c069dc0-e83b-4cd5-aaa2-cac7f3e00d80',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '1416f1a5-2447-4e9b-1f8a-45d6e47d8d46',
|
||||
newValue: '2d83909a-a383-4e82-b00a-8b7739f3f906',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '2527a2b6-3558-4f0c-2a9b-56e7f58e9e57',
|
||||
newValue: '0d1a59b4-cc87-4b7d-804a-656e8504f371',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '3638b3c7-4669-4a1d-3b0c-67f8a69f0f68',
|
||||
newValue: 'b8c2a673-a981-4357-a43d-313a358e4daa',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '4749c4d8-5770-4b2e-4c1d-78a9b70a1a79',
|
||||
newValue: 'e161072d-37b1-477a-b944-ef0d65289574',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '5850d5e9-6881-4c3f-5d2e-89b0c81b2b80',
|
||||
newValue: 'ae60d580-b562-44f2-a24d-7b8040063f83',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '6961e6f0-7992-4d4a-6e3f-90c1d92c3c91',
|
||||
newValue: 'f53fdd28-a26b-47ba-81b5-6813ad622720',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '7072f7a1-8003-4e5b-7f4a-01d2e03d4d02',
|
||||
newValue: '8a265a5c-d3ae-47dc-bdf9-b42cfa2ba639',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '0305c0d4-1336-4b8e-0c7d-34a5b36a7a35',
|
||||
newValue: 'f48fa3b1-0cec-44da-a9e5-f8a5e766637e',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '1416d1e5-2447-4c9f-1d8e-45b6c47b8b46',
|
||||
newValue: 'a86b32b3-01d3-4302-a152-8b7f247db7b4',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '2527e2f6-3558-4d0a-2e9f-56c7d58c9c57',
|
||||
newValue: 'c882f7a4-b025-4d32-aa26-5ef2595bdbf9',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '3638f3a7-4669-4e1b-3f0a-67d8e69d0d68',
|
||||
newValue: 'b7d305d1-6fae-4ed6-9bdc-354fe9032c0e',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '4749a4b8-5770-4f2c-4a1b-78e9f70e1e79',
|
||||
newValue: 'c0af54c7-751b-4bb2-b102-677cc4e47402',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '5850b5c9-6881-4a3d-5b2c-89f0a81f2f80',
|
||||
newValue: '6942e0ba-90f6-4c33-bf40-7f00b1ec35ab',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '6961c6d0-7992-4b4e-6c3d-90a1b92a3a91',
|
||||
newValue: '5e0b2391-85ca-4a66-aef4-52d74245bec2',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '7072d7e1-8003-4c5f-7d4e-01b2c03b4b02',
|
||||
newValue: '3e89a914-7bec-47bd-9cf9-743c6b83d001',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '0305a0b4-1336-4f8c-0a7b-34e5f36e7e35',
|
||||
newValue: '995db1d8-0d3e-40f7-b0eb-5e6897bc9966',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '1416b1c5-2447-4a9d-1b8c-45f6a47f8f46',
|
||||
newValue: '609cf622-86ef-48d1-812b-e1cab610a46c',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '2527c2d6-3558-4b0e-2c9d-56a7b58a9a57',
|
||||
newValue: 'd6059ec2-92b0-4cfc-9fd8-78050f03108f',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '3638d3e7-4669-4c1f-3d0e-67b8c69b0b68',
|
||||
newValue: 'd94329b3-5dc8-4141-ae28-31afe28f7135',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '4749e4f8-5770-4d2a-4e1f-78c9d70c1c79',
|
||||
newValue: '1a2bd046-7c23-4e0a-9f8a-c3ca3a16d3b9',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '5850f5a9-6881-4e3b-5f2a-89d0e81d2d80',
|
||||
newValue: 'e8821da9-728d-470a-bf5b-5a981fff7880',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '6961a6b0-7992-4f4c-6a3b-90e1f92e3e91',
|
||||
newValue: 'c7e64c55-eb0c-4b93-b076-5cfcf2e2e042',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '7072b7c1-8003-4a5d-7b4c-01f2a03f4f03',
|
||||
newValue: '7331ff89-a3f9-4ac0-9fa9-0de5663ae7b2',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '0305e0f4-1336-4d8a-0e7f-34c5d36c7c36',
|
||||
newValue: 'e0ac5ad2-d0c8-4f72-b710-8e53b9dc18d9',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '1416f1a5-2447-4e9b-1f8a-45d6e47d8d47',
|
||||
newValue: '8138c3b3-0b14-4ee1-be0e-debdde6b3219',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '2527a2b6-3558-4f0c-2a9b-56e7f58e9e58',
|
||||
newValue: '6f3a65eb-2aee-4108-b8a0-c62da419d1dc',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '3638b3c7-4669-4a1d-3b0c-67f8a69f0f69',
|
||||
newValue: '76da5f27-523c-44b6-ad06-12954f6b949f',
|
||||
},
|
||||
{
|
||||
table: 'core."indexMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '4749c4d8-5770-4b2e-4c1d-78a9b70a1a7a',
|
||||
newValue: '8678dde9-a804-4a9e-80e3-9af35e471ec5',
|
||||
},
|
||||
{
|
||||
table: 'core."fieldMetadata"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '20202020-92d0-1d7f-a126-25ededa6b142',
|
||||
newValue: '20202020-1ecc-4562-84c9-ff3a2f6cce85',
|
||||
},
|
||||
{
|
||||
table: 'core."skill"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '20202020-6155-838a-b64e-44a791fbdc13',
|
||||
newValue: STANDARD_SKILL['workflow-building'].universalIdentifier,
|
||||
},
|
||||
{
|
||||
table: 'core."skill"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '20202020-e225-f5c7-3d56-45feaa36f2e6',
|
||||
newValue: STANDARD_SKILL['data-manipulation'].universalIdentifier,
|
||||
},
|
||||
{
|
||||
table: 'core."skill"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '20202020-398f-0d7a-82db-4f43bc7e7044',
|
||||
newValue: STANDARD_SKILL['dashboard-building'].universalIdentifier,
|
||||
},
|
||||
{
|
||||
table: 'core."skill"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '20202020-c66a-5fed-4a74-46e0b42a6332',
|
||||
newValue: STANDARD_SKILL['metadata-building'].universalIdentifier,
|
||||
},
|
||||
{
|
||||
table: 'core."skill"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '20202020-db75-4fca-6813-4c7db0f964a0',
|
||||
newValue: STANDARD_SKILL.research.universalIdentifier,
|
||||
},
|
||||
{
|
||||
table: 'core."skill"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '20202020-5eb9-e775-cf4e-4f22be7be362',
|
||||
newValue: STANDARD_SKILL['code-interpreter'].universalIdentifier,
|
||||
},
|
||||
{
|
||||
table: 'core."skill"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '20202020-2c7f-5b77-dfa4-494b84752ab7',
|
||||
newValue: STANDARD_SKILL.xlsx.universalIdentifier,
|
||||
},
|
||||
{
|
||||
table: 'core."skill"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '20202020-c3d1-e0c9-2f93-45648b8bbd26',
|
||||
newValue: STANDARD_SKILL.pdf.universalIdentifier,
|
||||
},
|
||||
{
|
||||
table: 'core."skill"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '20202020-6f15-2432-0537-4e23a2efd1cb',
|
||||
newValue: STANDARD_SKILL.docx.universalIdentifier,
|
||||
},
|
||||
{
|
||||
table: 'core."skill"',
|
||||
column: '"universalIdentifier"',
|
||||
oldValue: '20202020-c81b-baf8-5255-4c34bd0eac9b',
|
||||
newValue: STANDARD_SKILL.pptx.universalIdentifier,
|
||||
},
|
||||
];
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:1-19:fix-invalid-standard-universal-identifiers',
|
||||
description:
|
||||
'Fix invalid universalIdentifier values in core tables to comply with UUID v4 format',
|
||||
})
|
||||
export class FixInvalidStandardUniversalIdentifiersCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(WorkspaceEntity)
|
||||
protected readonly workspaceRepository: Repository<WorkspaceEntity>,
|
||||
@InjectDataSource()
|
||||
private readonly coreDataSource: DataSource,
|
||||
protected readonly twentyORMGlobalManager: GlobalWorkspaceOrmManager,
|
||||
protected readonly dataSourceService: DataSourceService,
|
||||
private readonly workspaceCacheService: WorkspaceCacheService,
|
||||
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
|
||||
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager, dataSourceService);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
workspaceId,
|
||||
options,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
const isDryRun = options?.dryRun ?? false;
|
||||
|
||||
this.logger.log(
|
||||
`${isDryRun ? '[DRY RUN] ' : ''}Fixing universal identifiers for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
if (isDryRun) {
|
||||
this.logger.log(
|
||||
`[DRY RUN] Would fix role, agent, skill, and ${STANDARD_OBJECT_MISMATCHES.length} standard object universal identifier mismatches in workspace ${workspaceId}. Skipping.`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const queryRunner = this.coreDataSource.createQueryRunner();
|
||||
|
||||
await queryRunner.connect();
|
||||
|
||||
try {
|
||||
let totalUpdated = 0;
|
||||
|
||||
const roleResult = await queryRunner.query(
|
||||
`UPDATE core."role"
|
||||
SET "universalIdentifier" = $1
|
||||
WHERE "workspaceId" = $2
|
||||
AND "universalIdentifier" = $3`,
|
||||
[
|
||||
STANDARD_ROLE.admin.universalIdentifier,
|
||||
workspaceId,
|
||||
OLD_ROLE_ADMIN_UNIVERSAL_IDENTIFIER,
|
||||
],
|
||||
);
|
||||
|
||||
const roleUpdatedCount = roleResult?.[1] ?? 0;
|
||||
|
||||
if (roleUpdatedCount > 0) {
|
||||
this.logger.log(
|
||||
`Updated ${roleUpdatedCount} role universalIdentifier in workspace ${workspaceId}`,
|
||||
);
|
||||
totalUpdated += roleUpdatedCount;
|
||||
}
|
||||
|
||||
const agentResult = await queryRunner.query(
|
||||
`UPDATE core."agent"
|
||||
SET "universalIdentifier" = $1
|
||||
WHERE "workspaceId" = $2
|
||||
AND "universalIdentifier" = $3`,
|
||||
[
|
||||
STANDARD_AGENT.helper.universalIdentifier,
|
||||
workspaceId,
|
||||
OLD_AGENT_HELPER_UNIVERSAL_IDENTIFIER,
|
||||
],
|
||||
);
|
||||
|
||||
const agentUpdatedCount = agentResult?.[1] ?? 0;
|
||||
|
||||
if (agentUpdatedCount > 0) {
|
||||
this.logger.log(
|
||||
`Updated ${agentUpdatedCount} agent universalIdentifier in workspace ${workspaceId}`,
|
||||
);
|
||||
totalUpdated += agentUpdatedCount;
|
||||
}
|
||||
|
||||
const updateCountsByTable: Record<string, number> = {};
|
||||
|
||||
for (const mismatch of STANDARD_OBJECT_MISMATCHES) {
|
||||
const result = await queryRunner.query(
|
||||
`UPDATE ${mismatch.table}
|
||||
SET ${mismatch.column} = $1
|
||||
WHERE "workspaceId" = $2
|
||||
AND ${mismatch.column} = $3`,
|
||||
[mismatch.newValue, workspaceId, mismatch.oldValue],
|
||||
);
|
||||
|
||||
const updatedCount = result?.[1] ?? 0;
|
||||
|
||||
if (updatedCount > 0) {
|
||||
const tableKey = `${mismatch.table}.${mismatch.column}`;
|
||||
|
||||
updateCountsByTable[tableKey] =
|
||||
(updateCountsByTable[tableKey] ?? 0) + updatedCount;
|
||||
totalUpdated += updatedCount;
|
||||
}
|
||||
}
|
||||
|
||||
for (const [tableKey, count] of Object.entries(updateCountsByTable)) {
|
||||
this.logger.log(
|
||||
`Updated ${count} rows in ${tableKey} for workspace ${workspaceId}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (totalUpdated === 0) {
|
||||
this.logger.log(
|
||||
`No universal identifiers needed updating in workspace ${workspaceId}`,
|
||||
);
|
||||
} else {
|
||||
this.logger.log(
|
||||
`Updated ${totalUpdated} total universal identifiers in workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
await this.invalidateCaches(workspaceId);
|
||||
}
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
|
||||
private async invalidateCaches(workspaceId: string): Promise<void> {
|
||||
const modifiedMetadataNames = [
|
||||
'fieldMetadata',
|
||||
'index',
|
||||
'role',
|
||||
'agent',
|
||||
'skill',
|
||||
] as const;
|
||||
|
||||
const cacheKeysToInvalidate: WorkspaceCacheKeyName[] = [
|
||||
...new Set(
|
||||
modifiedMetadataNames
|
||||
.flatMap((name) => [name, ...getMetadataRelatedMetadataNames(name)])
|
||||
.map(getMetadataFlatEntityMapsKey),
|
||||
),
|
||||
'ORMEntityMetadatas',
|
||||
'rolesPermissions',
|
||||
'userWorkspaceRoleMap',
|
||||
'apiKeyRoleMap',
|
||||
'flatRoleTargetByAgentIdMaps',
|
||||
];
|
||||
|
||||
await this.workspaceCacheService.invalidateAndRecompute(
|
||||
workspaceId,
|
||||
cacheKeysToInvalidate,
|
||||
);
|
||||
|
||||
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await this.workspaceCacheStorageService.flush(workspaceId);
|
||||
|
||||
this.logger.log(
|
||||
`Cache invalidated and metadata version incremented for workspace ${workspaceId}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
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 { 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';
|
||||
import { seedServerId } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-server-id.util';
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:1-19:seed-server-id',
|
||||
description:
|
||||
'Seed a unique SERVER_ID (UUID v4) into the keyValuePair table as a CONFIG_VARIABLE',
|
||||
})
|
||||
export class SeedServerIdCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
private hasRun = false;
|
||||
|
||||
constructor(
|
||||
@InjectRepository(WorkspaceEntity)
|
||||
protected readonly workspaceRepository: Repository<WorkspaceEntity>,
|
||||
@InjectDataSource()
|
||||
private readonly coreDataSource: DataSource,
|
||||
protected readonly twentyORMGlobalManager: GlobalWorkspaceOrmManager,
|
||||
protected readonly dataSourceService: DataSourceService,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager, dataSourceService);
|
||||
}
|
||||
|
||||
override async runOnWorkspace(): Promise<void> {
|
||||
if (this.hasRun) {
|
||||
return;
|
||||
}
|
||||
|
||||
const queryRunner = this.coreDataSource.createQueryRunner();
|
||||
|
||||
await seedServerId({ queryRunner, schemaName: 'core' });
|
||||
|
||||
this.hasRun = true;
|
||||
|
||||
await queryRunner.release();
|
||||
|
||||
this.logger.log(`SERVER_ID seeded successfully`);
|
||||
}
|
||||
}
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { AddMissingSystemFieldsToStandardObjectsCommand } from 'src/database/commands/upgrade-version-command/1-19/1-19-add-missing-system-fields-to-standard-objects.command';
|
||||
import { BackfillMessageChannelMessageAssociationMessageFolderCommand } from 'src/database/commands/upgrade-version-command/1-19/1-19-backfill-message-channel-message-association-message-folder.command';
|
||||
import { BackfillMissingStandardViewsCommand } from 'src/database/commands/upgrade-version-command/1-19/1-19-backfill-missing-standard-views.command';
|
||||
import { BackfillSystemFieldsIsSystemCommand } from 'src/database/commands/upgrade-version-command/1-19/1-19-backfill-system-fields-is-system.command';
|
||||
import { FixInvalidStandardUniversalIdentifiersCommand } from 'src/database/commands/upgrade-version-command/1-19/1-19-fix-invalid-standard-universal-identifiers.command';
|
||||
import { SeedServerIdCommand } from 'src/database/commands/upgrade-version-command/1-19/1-19-seed-server-id.command';
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
|
||||
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
|
||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/workspace-migration-runner.module';
|
||||
import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([WorkspaceEntity]),
|
||||
DataSourceModule,
|
||||
WorkspaceCacheModule,
|
||||
WorkspaceCacheStorageModule,
|
||||
WorkspaceMetadataVersionModule,
|
||||
WorkspaceMigrationRunnerModule,
|
||||
ApplicationModule,
|
||||
WorkspaceMigrationModule,
|
||||
FeatureFlagModule,
|
||||
],
|
||||
providers: [
|
||||
BackfillSystemFieldsIsSystemCommand,
|
||||
AddMissingSystemFieldsToStandardObjectsCommand,
|
||||
BackfillMessageChannelMessageAssociationMessageFolderCommand,
|
||||
BackfillMissingStandardViewsCommand,
|
||||
FixInvalidStandardUniversalIdentifiersCommand,
|
||||
SeedServerIdCommand,
|
||||
],
|
||||
exports: [
|
||||
BackfillSystemFieldsIsSystemCommand,
|
||||
AddMissingSystemFieldsToStandardObjectsCommand,
|
||||
BackfillMessageChannelMessageAssociationMessageFolderCommand,
|
||||
BackfillMissingStandardViewsCommand,
|
||||
FixInvalidStandardUniversalIdentifiersCommand,
|
||||
SeedServerIdCommand,
|
||||
],
|
||||
})
|
||||
export class V1_19_UpgradeVersionCommandModule {}
|
||||
-2
@@ -1,7 +1,6 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { V1_19_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/1-19/1-19-upgrade-version-command.module';
|
||||
import { V1_20_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/1-20/1-20-upgrade-version-command.module';
|
||||
import { UpgradeCommand } from 'src/database/commands/upgrade-version-command/upgrade.command';
|
||||
import { CoreEngineVersionModule } from 'src/engine/core-engine-version/core-engine-version.module';
|
||||
@@ -13,7 +12,6 @@ import { WorkspaceVersionModule } from 'src/engine/workspace-manager/workspace-v
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([WorkspaceEntity]),
|
||||
V1_19_UpgradeVersionCommandModule,
|
||||
V1_20_UpgradeVersionCommandModule,
|
||||
DataSourceModule,
|
||||
CoreEngineVersionModule,
|
||||
|
||||
+1
-25
@@ -10,12 +10,6 @@ import {
|
||||
type VersionCommands,
|
||||
} from 'src/database/commands/command-runners/upgrade.command-runner';
|
||||
import { CoreMigrationRunnerService } from 'src/database/commands/core-migration-runner/services/core-migration-runner.service';
|
||||
import { AddMissingSystemFieldsToStandardObjectsCommand } from 'src/database/commands/upgrade-version-command/1-19/1-19-add-missing-system-fields-to-standard-objects.command';
|
||||
import { BackfillMessageChannelMessageAssociationMessageFolderCommand } from 'src/database/commands/upgrade-version-command/1-19/1-19-backfill-message-channel-message-association-message-folder.command';
|
||||
import { BackfillMissingStandardViewsCommand } from 'src/database/commands/upgrade-version-command/1-19/1-19-backfill-missing-standard-views.command';
|
||||
import { BackfillSystemFieldsIsSystemCommand } from 'src/database/commands/upgrade-version-command/1-19/1-19-backfill-system-fields-is-system.command';
|
||||
import { FixInvalidStandardUniversalIdentifiersCommand } from 'src/database/commands/upgrade-version-command/1-19/1-19-fix-invalid-standard-universal-identifiers.command';
|
||||
import { SeedServerIdCommand } from 'src/database/commands/upgrade-version-command/1-19/1-19-seed-server-id.command';
|
||||
import { BackfillCommandMenuItemsCommand } from 'src/database/commands/upgrade-version-command/1-20/1-20-backfill-command-menu-items.command';
|
||||
import { BackfillNavigationMenuItemTypeCommand } from 'src/database/commands/upgrade-version-command/1-20/1-20-backfill-navigation-menu-item-type.command';
|
||||
import { BackfillPageLayoutsAndFieldsWidgetViewFieldsCommand } from 'src/database/commands/upgrade-version-command/1-20/1-20-backfill-page-layouts-and-fields-widget-view-fields.command';
|
||||
@@ -56,14 +50,6 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
protected readonly workspaceVersionService: WorkspaceVersionService,
|
||||
protected readonly coreMigrationRunnerService: CoreMigrationRunnerService,
|
||||
|
||||
// 1.19 Commands
|
||||
protected readonly backfillSystemFieldsIsSystemCommand: BackfillSystemFieldsIsSystemCommand,
|
||||
protected readonly addMissingSystemFieldsToStandardObjectsCommand: AddMissingSystemFieldsToStandardObjectsCommand,
|
||||
protected readonly backfillMessageChannelMessageAssociationMessageFolderCommand: BackfillMessageChannelMessageAssociationMessageFolderCommand,
|
||||
protected readonly backfillMissingStandardViewsCommand: BackfillMissingStandardViewsCommand,
|
||||
protected readonly fixRoleAndAgentUniversalIdentifiersCommand: FixInvalidStandardUniversalIdentifiersCommand,
|
||||
protected readonly seedServerIdCommand: SeedServerIdCommand,
|
||||
|
||||
// 1.20 Commands
|
||||
protected readonly identifyPermissionFlagMetadataCommand: IdentifyPermissionFlagMetadataCommand,
|
||||
protected readonly makePermissionFlagUniversalIdentifierAndApplicationIdNotNullableMigrationCommand: MakePermissionFlagUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
|
||||
@@ -92,16 +78,6 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
coreMigrationRunnerService,
|
||||
);
|
||||
|
||||
const commands_1190: VersionCommands = [
|
||||
this.fixRoleAndAgentUniversalIdentifiersCommand,
|
||||
this.backfillSystemFieldsIsSystemCommand,
|
||||
this.addMissingSystemFieldsToStandardObjectsCommand,
|
||||
this.backfillMessageChannelMessageAssociationMessageFolderCommand,
|
||||
this.backfillMissingStandardViewsCommand,
|
||||
this.fixRoleAndAgentUniversalIdentifiersCommand,
|
||||
this.seedServerIdCommand,
|
||||
];
|
||||
|
||||
const commands_1200: VersionCommands = [
|
||||
this.identifyPermissionFlagMetadataCommand,
|
||||
this
|
||||
@@ -125,7 +101,7 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
];
|
||||
|
||||
this.allCommands = {
|
||||
'1.19.0': commands_1190,
|
||||
'1.19.0': [],
|
||||
'1.20.0': commands_1200,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator';
|
||||
import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum';
|
||||
@@ -12,6 +12,8 @@ export type CacheLockOptions = {
|
||||
|
||||
@Injectable()
|
||||
export class CacheLockService {
|
||||
private readonly logger = new Logger(CacheLockService.name);
|
||||
|
||||
constructor(
|
||||
@InjectCacheStorage(CacheStorageNamespace.EngineLock)
|
||||
private readonly cacheStorageService: CacheStorageService,
|
||||
@@ -35,7 +37,13 @@ export class CacheLockService {
|
||||
try {
|
||||
return await fn();
|
||||
} finally {
|
||||
await this.cacheStorageService.releaseLock(key);
|
||||
try {
|
||||
await this.cacheStorageService.releaseLock(key);
|
||||
} catch (releaseError) {
|
||||
this.logger.warn(
|
||||
`Failed to release lock for key "${key}": ${releaseError}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ export class MetricsService {
|
||||
counter.add(1, attributes);
|
||||
|
||||
if (shouldStoreInCache && eventId) {
|
||||
this.metricsCacheService.updateCounter(key, [eventId]);
|
||||
await this.metricsCacheService.updateCounter(key, [eventId]);
|
||||
}
|
||||
|
||||
if (isDefined(debugLog)) {
|
||||
@@ -122,7 +122,7 @@ export class MetricsService {
|
||||
counter.add(eventIds.length, attributes);
|
||||
|
||||
if (shouldStoreInCache) {
|
||||
this.metricsCacheService.updateCounter(key, eventIds);
|
||||
await this.metricsCacheService.updateCounter(key, eventIds);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-2
@@ -239,8 +239,6 @@ describe('WorkspaceEntityManager', () => {
|
||||
IS_EMAILING_DOMAIN_ENABLED: false,
|
||||
IS_JUNCTION_RELATIONS_ENABLED: false,
|
||||
IS_COMMAND_MENU_ITEM_ENABLED: false,
|
||||
IS_NAVIGATION_MENU_ITEM_ENABLED: false,
|
||||
IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED: false,
|
||||
IS_DRAFT_EMAIL_ENABLED: false,
|
||||
IS_USAGE_ANALYTICS_ENABLED: false,
|
||||
IS_RICH_TEXT_V1_MIGRATED: false,
|
||||
|
||||
-10
@@ -45,16 +45,6 @@ export const seedFeatureFlags = async ({
|
||||
workspaceId: workspaceId,
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKey.IS_NAVIGATION_MENU_ITEM_ENABLED,
|
||||
workspaceId: workspaceId,
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKey.IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED,
|
||||
workspaceId: workspaceId,
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKey.IS_MARKETPLACE_ENABLED,
|
||||
workspaceId: workspaceId,
|
||||
|
||||
+18
-7
@@ -153,19 +153,30 @@ export class WorkflowRunEnqueueWorkspaceService {
|
||||
authContext,
|
||||
);
|
||||
} catch (error) {
|
||||
this.metricsService.incrementCounter({
|
||||
key: MetricsKeys.WorkflowRunFailedToEnqueue,
|
||||
eventId: workspaceId,
|
||||
});
|
||||
try {
|
||||
await this.metricsService.incrementCounter({
|
||||
key: MetricsKeys.WorkflowRunFailedToEnqueue,
|
||||
eventId: workspaceId,
|
||||
});
|
||||
} catch {
|
||||
// Metrics may fail if Redis is shutting down — safe to ignore
|
||||
}
|
||||
|
||||
this.logger.error(
|
||||
`Failed to enqueue workflow runs for workspace: ${workspaceId}`,
|
||||
error,
|
||||
);
|
||||
} finally {
|
||||
await this.workflowThrottlingWorkspaceService.releaseWorkflowEnqueueLock(
|
||||
workspaceId,
|
||||
);
|
||||
try {
|
||||
await this.workflowThrottlingWorkspaceService.releaseWorkflowEnqueueLock(
|
||||
workspaceId,
|
||||
);
|
||||
} catch (releaseError) {
|
||||
this.logger.warn(
|
||||
`Failed to release workflow enqueue lock for workspace: ${workspaceId}`,
|
||||
releaseError,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,6 @@ export enum FeatureFlagKey {
|
||||
IS_EMAILING_DOMAIN_ENABLED = 'IS_EMAILING_DOMAIN_ENABLED',
|
||||
IS_JUNCTION_RELATIONS_ENABLED = 'IS_JUNCTION_RELATIONS_ENABLED',
|
||||
IS_COMMAND_MENU_ITEM_ENABLED = 'IS_COMMAND_MENU_ITEM_ENABLED',
|
||||
IS_NAVIGATION_MENU_ITEM_ENABLED = 'IS_NAVIGATION_MENU_ITEM_ENABLED',
|
||||
IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED = 'IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED',
|
||||
IS_DRAFT_EMAIL_ENABLED = 'IS_DRAFT_EMAIL_ENABLED',
|
||||
IS_USAGE_ANALYTICS_ENABLED = 'IS_USAGE_ANALYTICS_ENABLED',
|
||||
IS_RICH_TEXT_V1_MIGRATED = 'IS_RICH_TEXT_V1_MIGRATED',
|
||||
|
||||
Reference in New Issue
Block a user