Deprecate old relations completely (#12482)
# What Fully deprecate old relations because we have one bug tied to it and it make the codebase complex # How I've made this PR: 1. remove metadata datasource (we only keep 'core') => this was causing extra complexity in the refactor + flaky reset 2. merge dev and demo datasets => as I needed to update the tests which is very painful, I don't want to do it twice 3. remove all code tied to RELATION_METADATA / relation-metadata.resolver, or anything tied to the old relation system 4. Remove ONE_TO_ONE and MANY_TO_MANY that are not supported 5. fix impacts on the different areas : see functional testing below # Functional testing ## Functional testing from the front-end: 1. Database Reset ✅ 2. Sign In ✅ 3. Workspace sign-up ✅ 5. Browsing table / kanban / show ✅ 6. Assigning a record in a one to many / in a many to one ✅ 7. Deleting a record involved in a relation ✅ => broken but not tied to this PR 8. "Add new" from relation picker ✅ => broken but not tied to this PR 9. Creating a Task / Note, Updating a Task / Note relations, Deleting a Task / Note (from table, show page, right drawer) ✅ => broken but not tied to this PR 10. creating a relation from settings (custom / standard x oneToMany / manyToOne) ✅ 11. updating a relation from settings should not be possible ✅ 12. deleting a relation from settings (custom / standard x oneToMany / manyToOne) ✅ 13. Make sure timeline activity still work (relation were involved there), espacially with Task / Note => to be double checked ✅ => Cannot convert undefined or null to object 14. Workspace deletion / User deletion ✅ 15. CSV Import should keep working ✅ 16. Permissions: I have tested without permissions V2 as it's still hard to test v2 work and it's not in prod yet ✅ 17. Workflows global test ✅ ## From the API: 1. Review open-api documentation (REST) ✅ 2. Make sure REST Api are still able to fetch relations ==> won't do, we have a coupling Get/Update/Create there, this requires refactoring 3. Make sure REST Api is still able to update / remove relation => won't do same ## Automated tests 1. lint + typescript ✅ 2. front unit tests: ✅ 3. server unit tests 2 ✅ 4. front stories: ✅ 5. server integration: ✅ 6. chromatic check : expected 0 7. e2e check : expected no more that current failures ## Remove // Todos 1. All are captured by functional tests above, nothing additional to do ## (Un)related regressions 1. Table loading state is not working anymore, we see the empty state before table content 2. Filtering by Creator Tim Ap return empty results 3. Not possible to add Tasks / Notes / Files from show page # Result ## New seeds that can be easily extended <img width="1920" alt="image" src="https://github.com/user-attachments/assets/d290d130-2a5f-44e6-b419-7e42a89eec4b" /> ## -5k lines of code ## No more 'metadata' dataSource (we only have 'core) ## No more relationMetadata (I haven't drop the table yet it's not referenced in the code anymore) ## We are ready to fix the 6 months lag between current API results and our mocked tests ## No more bug on relation creation / deletion --------- Co-authored-by: Weiko <corentin@twenty.com> Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
@ -1,18 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { DataSeedDemoWorkspaceService } from 'src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service';
|
||||
import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
WorkspaceManagerModule,
|
||||
TwentyConfigModule,
|
||||
TypeOrmModule.forFeature([Workspace], 'core'),
|
||||
],
|
||||
providers: [DataSeedDemoWorkspaceService],
|
||||
exports: [DataSeedDemoWorkspaceService],
|
||||
})
|
||||
export class DataSeedDemoWorkspaceModule {}
|
||||
@ -1,64 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { seedCoreSchema } from 'src/database/typeorm-seeds/core';
|
||||
import { deleteCoreSchema } from 'src/database/typeorm-seeds/core/demo';
|
||||
import { rawDataSource } from 'src/database/typeorm/raw/raw.datasource';
|
||||
import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator';
|
||||
import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service';
|
||||
import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum';
|
||||
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { WorkspaceManagerService } from 'src/engine/workspace-manager/workspace-manager.service';
|
||||
|
||||
@Injectable()
|
||||
export class DataSeedDemoWorkspaceService {
|
||||
constructor(
|
||||
private readonly workspaceManagerService: WorkspaceManagerService,
|
||||
@InjectRepository(Workspace, 'core')
|
||||
protected readonly workspaceRepository: Repository<Workspace>,
|
||||
@InjectCacheStorage(CacheStorageNamespace.EngineWorkspace)
|
||||
private readonly workspaceSchemaCache: CacheStorageService,
|
||||
private readonly twentyConfigService: TwentyConfigService,
|
||||
) {}
|
||||
|
||||
async seedDemo(): Promise<void> {
|
||||
try {
|
||||
await rawDataSource.initialize();
|
||||
|
||||
// TODO: migrate demo seeds to dev seeds
|
||||
const demoWorkspaceIds = ['', ''];
|
||||
|
||||
await this.workspaceSchemaCache.flush();
|
||||
|
||||
for (const workspaceId of demoWorkspaceIds) {
|
||||
const existingWorkspaces = await this.workspaceRepository.findBy({
|
||||
id: workspaceId,
|
||||
});
|
||||
|
||||
if (existingWorkspaces.length > 0) {
|
||||
await this.workspaceManagerService.delete(workspaceId);
|
||||
await deleteCoreSchema(rawDataSource, workspaceId);
|
||||
}
|
||||
|
||||
const appVersion = this.twentyConfigService.get('APP_VERSION');
|
||||
|
||||
await seedCoreSchema({
|
||||
dataSource: rawDataSource,
|
||||
workspaceId,
|
||||
appVersion,
|
||||
seedBilling: false,
|
||||
seedFeatureFlags: false,
|
||||
});
|
||||
await this.workspaceManagerService.initDemo(workspaceId);
|
||||
}
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(error);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,54 +1,12 @@
|
||||
import { Logger } from '@nestjs/common';
|
||||
|
||||
import { Command, CommandRunner } from 'nest-commander';
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { seedCoreSchema } from 'src/database/typeorm-seeds/core';
|
||||
import {
|
||||
SEED_ACME_WORKSPACE_ID,
|
||||
SEED_APPLE_WORKSPACE_ID,
|
||||
} from 'src/database/typeorm-seeds/core/workspaces';
|
||||
import {
|
||||
getDevSeedCompanyCustomFields,
|
||||
getDevSeedPeopleCustomFields,
|
||||
} from 'src/database/typeorm-seeds/metadata/fieldsMetadata';
|
||||
import { seedApiKey } from 'src/database/typeorm-seeds/workspace/api-key';
|
||||
import { seedCalendarChannels } from 'src/database/typeorm-seeds/workspace/calendar-channel';
|
||||
import { seedCalendarChannelEventAssociations } from 'src/database/typeorm-seeds/workspace/calendar-channel-event-association';
|
||||
import { seedCalendarEventParticipants } from 'src/database/typeorm-seeds/workspace/calendar-event-participants';
|
||||
import { seedCalendarEvents } from 'src/database/typeorm-seeds/workspace/calendar-events';
|
||||
import { seedCompanies } from 'src/database/typeorm-seeds/workspace/companies';
|
||||
import { seedConnectedAccount } from 'src/database/typeorm-seeds/workspace/connected-account';
|
||||
import { seedWorkspaceFavorites } from 'src/database/typeorm-seeds/workspace/favorites';
|
||||
import { seedMessageChannelMessageAssociation } from 'src/database/typeorm-seeds/workspace/message-channel-message-associations';
|
||||
import { seedMessageChannel } from 'src/database/typeorm-seeds/workspace/message-channels';
|
||||
import { seedMessageParticipant } from 'src/database/typeorm-seeds/workspace/message-participants';
|
||||
import { seedMessageThread } from 'src/database/typeorm-seeds/workspace/message-threads';
|
||||
import { seedMessage } from 'src/database/typeorm-seeds/workspace/messages';
|
||||
import { seedOpportunity } from 'src/database/typeorm-seeds/workspace/opportunities';
|
||||
import { seedPeople } from 'src/database/typeorm-seeds/workspace/seedPeople';
|
||||
import { seedWorkspaceMember } from 'src/database/typeorm-seeds/workspace/workspace-members';
|
||||
import { rawDataSource } from 'src/database/typeorm/raw/raw.datasource';
|
||||
import { TypeORMService } from 'src/database/typeorm/typeorm.service';
|
||||
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
|
||||
import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service';
|
||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||
import { PETS_DATA_SEEDS } from 'src/engine/seeder/data-seeds/pets-data-seeds';
|
||||
import { SURVEY_RESULTS_DATA_SEEDS } from 'src/engine/seeder/data-seeds/survey-results-data-seeds';
|
||||
import { PETS_METADATA_SEEDS } from 'src/engine/seeder/metadata-seeds/pets-metadata-seeds';
|
||||
import { SURVEY_RESULTS_METADATA_SEEDS } from 'src/engine/seeder/metadata-seeds/survey-results-metadata-seeds';
|
||||
import { SeederService } from 'src/engine/seeder/seeder.service';
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
import { shouldSeedWorkspaceFavorite } from 'src/engine/utils/should-seed-workspace-favorite';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
import { createWorkspaceViews } from 'src/engine/workspace-manager/standard-objects-prefill-data/create-workspace-views';
|
||||
import { seedViewWithDemoData } from 'src/engine/workspace-manager/standard-objects-prefill-data/seed-view-with-demo-data';
|
||||
import { opportunitiesTableByStageView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/opportunity-table-by-stage.view';
|
||||
import { WorkspaceManagerService } from 'src/engine/workspace-manager/workspace-manager.service';
|
||||
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
||||
// TODO: implement dry-run
|
||||
} from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-workspaces.util';
|
||||
import { DevSeederService } from 'src/engine/workspace-manager/dev-seeder/services/dev-seeder.service';
|
||||
@Command({
|
||||
name: 'workspace:seed:dev',
|
||||
description:
|
||||
@ -58,265 +16,18 @@ export class DataSeedWorkspaceCommand extends CommandRunner {
|
||||
workspaceIds = [SEED_APPLE_WORKSPACE_ID, SEED_ACME_WORKSPACE_ID];
|
||||
private readonly logger = new Logger(DataSeedWorkspaceCommand.name);
|
||||
|
||||
constructor(
|
||||
private readonly dataSourceService: DataSourceService,
|
||||
private readonly typeORMService: TypeORMService,
|
||||
private readonly fieldMetadataService: FieldMetadataService,
|
||||
private readonly objectMetadataService: ObjectMetadataService,
|
||||
private readonly seederService: SeederService,
|
||||
private readonly workspaceManagerService: WorkspaceManagerService,
|
||||
private readonly twentyConfigService: TwentyConfigService,
|
||||
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
|
||||
) {
|
||||
constructor(private readonly devSeederService: DevSeederService) {
|
||||
super();
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
try {
|
||||
for (const workspaceId of this.workspaceIds) {
|
||||
await this.createWorkspaceSchema(workspaceId);
|
||||
await this.devSeederService.seedDev(workspaceId);
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
|
||||
return;
|
||||
this.logger.error(error.stack);
|
||||
}
|
||||
|
||||
for (const workspaceId of this.workspaceIds) {
|
||||
await this.seedWorkspace(workspaceId);
|
||||
}
|
||||
}
|
||||
|
||||
async createWorkspaceSchema(workspaceId: string) {
|
||||
const workspaceCachedMetadataVersion =
|
||||
await this.workspaceCacheStorageService.getMetadataVersion(workspaceId);
|
||||
|
||||
await this.workspaceCacheStorageService.flush(
|
||||
workspaceId,
|
||||
workspaceCachedMetadataVersion,
|
||||
);
|
||||
|
||||
await rawDataSource.initialize();
|
||||
|
||||
const isBillingEnabled = this.twentyConfigService.get('IS_BILLING_ENABLED');
|
||||
const appVersion = this.twentyConfigService.get('APP_VERSION');
|
||||
|
||||
await seedCoreSchema({
|
||||
dataSource: rawDataSource,
|
||||
workspaceId,
|
||||
seedBilling: isBillingEnabled,
|
||||
appVersion,
|
||||
});
|
||||
|
||||
await rawDataSource.destroy();
|
||||
|
||||
await this.workspaceManagerService.initDev(workspaceId);
|
||||
}
|
||||
|
||||
async seedWorkspace(workspaceId: string) {
|
||||
const dataSourceMetadata =
|
||||
await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceIdOrFail(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
const mainDataSource = this.typeORMService.getMainDataSource();
|
||||
|
||||
if (!mainDataSource) {
|
||||
throw new Error('Could not connect to workspace data source');
|
||||
}
|
||||
|
||||
try {
|
||||
const { objectMetadataStandardIdToIdMap } =
|
||||
await this.objectMetadataService.getObjectMetadataStandardIdToIdMap(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await this.seedCompanyCustomFields(
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.company].id,
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await this.seedPeopleCustomFields(
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.person].id,
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await this.seedCustomObjects({
|
||||
dataSourceMetadata,
|
||||
});
|
||||
|
||||
await this.seedRecords({
|
||||
mainDataSource,
|
||||
dataSourceMetadata,
|
||||
});
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async seedCustomObjects({
|
||||
dataSourceMetadata,
|
||||
}: {
|
||||
dataSourceMetadata: DataSourceEntity;
|
||||
}) {
|
||||
await this.seederService.seedCustomObjects(
|
||||
dataSourceMetadata.id,
|
||||
dataSourceMetadata.workspaceId,
|
||||
PETS_METADATA_SEEDS,
|
||||
);
|
||||
|
||||
await this.seederService.seedCustomObjects(
|
||||
dataSourceMetadata.id,
|
||||
dataSourceMetadata.workspaceId,
|
||||
SURVEY_RESULTS_METADATA_SEEDS,
|
||||
);
|
||||
}
|
||||
|
||||
async seedRecords({
|
||||
mainDataSource,
|
||||
dataSourceMetadata,
|
||||
}: {
|
||||
mainDataSource: DataSource;
|
||||
dataSourceMetadata: DataSourceEntity;
|
||||
}) {
|
||||
await this.seedStandardObjectRecords(mainDataSource, dataSourceMetadata);
|
||||
|
||||
await this.seederService.seedCustomObjectRecords(
|
||||
dataSourceMetadata.workspaceId,
|
||||
PETS_METADATA_SEEDS,
|
||||
PETS_DATA_SEEDS,
|
||||
);
|
||||
|
||||
await this.seederService.seedCustomObjectRecords(
|
||||
dataSourceMetadata.workspaceId,
|
||||
SURVEY_RESULTS_METADATA_SEEDS,
|
||||
SURVEY_RESULTS_DATA_SEEDS,
|
||||
);
|
||||
}
|
||||
|
||||
async seedStandardObjectRecords(
|
||||
mainDataSource: DataSource,
|
||||
dataSourceMetadata: DataSourceEntity,
|
||||
) {
|
||||
await mainDataSource.transaction(
|
||||
async (entityManager: WorkspaceEntityManager) => {
|
||||
const { objectMetadataStandardIdToIdMap } =
|
||||
await this.objectMetadataService.getObjectMetadataStandardIdToIdMap(
|
||||
dataSourceMetadata.workspaceId,
|
||||
);
|
||||
|
||||
await seedCompanies(entityManager, dataSourceMetadata.schema);
|
||||
await seedPeople(entityManager, dataSourceMetadata.schema);
|
||||
await seedOpportunity(entityManager, dataSourceMetadata.schema);
|
||||
await seedWorkspaceMember(
|
||||
entityManager,
|
||||
dataSourceMetadata.schema,
|
||||
dataSourceMetadata.workspaceId,
|
||||
);
|
||||
|
||||
if (dataSourceMetadata.workspaceId === SEED_APPLE_WORKSPACE_ID) {
|
||||
await seedApiKey(entityManager, dataSourceMetadata.schema);
|
||||
await seedMessageThread(entityManager, dataSourceMetadata.schema);
|
||||
await seedConnectedAccount(entityManager, dataSourceMetadata.schema);
|
||||
|
||||
await seedMessage(entityManager, dataSourceMetadata.schema);
|
||||
await seedMessageChannel(entityManager, dataSourceMetadata.schema);
|
||||
await seedMessageChannelMessageAssociation(
|
||||
entityManager,
|
||||
dataSourceMetadata.schema,
|
||||
);
|
||||
await seedMessageParticipant(
|
||||
entityManager,
|
||||
dataSourceMetadata.schema,
|
||||
);
|
||||
|
||||
await seedCalendarEvents(entityManager, dataSourceMetadata.schema);
|
||||
await seedCalendarChannels(entityManager, dataSourceMetadata.schema);
|
||||
await seedCalendarChannelEventAssociations(
|
||||
entityManager,
|
||||
dataSourceMetadata.schema,
|
||||
);
|
||||
await seedCalendarEventParticipants(
|
||||
entityManager,
|
||||
dataSourceMetadata.schema,
|
||||
);
|
||||
}
|
||||
|
||||
const viewDefinitionsWithId = await seedViewWithDemoData(
|
||||
entityManager,
|
||||
dataSourceMetadata.schema,
|
||||
objectMetadataStandardIdToIdMap,
|
||||
);
|
||||
|
||||
const devViewDefinitionsWithId = await createWorkspaceViews(
|
||||
entityManager,
|
||||
dataSourceMetadata.schema,
|
||||
[opportunitiesTableByStageView(objectMetadataStandardIdToIdMap)],
|
||||
);
|
||||
|
||||
viewDefinitionsWithId.push(...devViewDefinitionsWithId);
|
||||
|
||||
await seedWorkspaceFavorites(
|
||||
viewDefinitionsWithId
|
||||
.filter(
|
||||
(view) =>
|
||||
view.key === 'INDEX' &&
|
||||
shouldSeedWorkspaceFavorite(
|
||||
view.objectMetadataId,
|
||||
objectMetadataStandardIdToIdMap,
|
||||
),
|
||||
)
|
||||
.map((view) => view.id),
|
||||
entityManager,
|
||||
dataSourceMetadata.schema,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async seedCompanyCustomFields(
|
||||
companyObjectMetadataId: string,
|
||||
workspaceId: string,
|
||||
) {
|
||||
if (!companyObjectMetadataId) {
|
||||
throw new Error(
|
||||
`Company object metadata not found for workspace ${workspaceId}, can't seed custom fields`,
|
||||
);
|
||||
}
|
||||
|
||||
const DEV_SEED_COMPANY_CUSTOM_FIELDS = getDevSeedCompanyCustomFields(
|
||||
companyObjectMetadataId,
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await this.fieldMetadataService.createMany(
|
||||
DEV_SEED_COMPANY_CUSTOM_FIELDS.map((customField) => ({
|
||||
...customField,
|
||||
isCustom: true,
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
async seedPeopleCustomFields(
|
||||
personObjectMetadataId: string,
|
||||
workspaceId: string,
|
||||
) {
|
||||
if (!personObjectMetadataId) {
|
||||
throw new Error(
|
||||
`Person object metadata not found for workspace ${workspaceId}, can't seed custom fields`,
|
||||
);
|
||||
}
|
||||
|
||||
const DEV_SEED_PERSON_CUSTOM_FIELDS = getDevSeedPeopleCustomFields(
|
||||
personObjectMetadataId,
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await this.fieldMetadataService.createMany(
|
||||
DEV_SEED_PERSON_CUSTOM_FIELDS.map((customField) => ({
|
||||
...customField,
|
||||
isCustom: true,
|
||||
})),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,8 +7,8 @@ import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||
import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module';
|
||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||
import { SeederModule } from 'src/engine/seeder/seeder.module';
|
||||
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
|
||||
import { DevSeederModule } from 'src/engine/workspace-manager/dev-seeder/dev-seeder.module';
|
||||
import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module';
|
||||
|
||||
@Module({
|
||||
@ -19,7 +19,7 @@ import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-m
|
||||
TypeORMModule,
|
||||
FieldMetadataModule,
|
||||
ObjectMetadataModule,
|
||||
SeederModule,
|
||||
DevSeederModule,
|
||||
WorkspaceManagerModule,
|
||||
DataSourceModule,
|
||||
WorkspaceCacheStorageModule,
|
||||
|
||||
@ -1,232 +0,0 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import chalk from 'chalk';
|
||||
import { Command } from 'nest-commander';
|
||||
import { Repository } from 'typeorm';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
ActiveOrSuspendedWorkspacesMigrationCommandOptions,
|
||||
ActiveOrSuspendedWorkspacesMigrationCommandRunner,
|
||||
RunOnWorkspaceArgs,
|
||||
} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
||||
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { ADMIN_ROLE_LABEL } from 'src/engine/metadata-modules/permissions/constants/admin-role-label.constants';
|
||||
import { MEMBER_ROLE_LABEL } from 'src/engine/metadata-modules/permissions/constants/member-role-label.constants';
|
||||
import { RoleService } from 'src/engine/metadata-modules/role/role.service';
|
||||
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:0-44:initialize-permissions',
|
||||
description: 'Initialize permissions',
|
||||
})
|
||||
export class InitializePermissionsCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(Workspace, 'core')
|
||||
protected readonly workspaceRepository: Repository<Workspace>,
|
||||
@InjectRepository(UserWorkspace, 'core')
|
||||
protected readonly userWorkspaceRepository: Repository<UserWorkspace>,
|
||||
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
private readonly roleService: RoleService,
|
||||
private readonly userRoleService: UserRoleService,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
index,
|
||||
total,
|
||||
workspaceId,
|
||||
options,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
try {
|
||||
this.logger.log(
|
||||
`Running command for workspace ${workspaceId} ${index + 1}/${total}`,
|
||||
);
|
||||
|
||||
let adminRoleId: string | undefined;
|
||||
|
||||
const workspaceRoles =
|
||||
await this.roleService.getWorkspaceRoles(workspaceId);
|
||||
|
||||
adminRoleId = workspaceRoles.find(
|
||||
(role) => role.label === ADMIN_ROLE_LABEL,
|
||||
)?.id;
|
||||
|
||||
if (!isDefined(adminRoleId)) {
|
||||
adminRoleId = await this.createAdminRole({
|
||||
workspaceId,
|
||||
options,
|
||||
});
|
||||
}
|
||||
|
||||
await this.assignAdminRoleToMembers({
|
||||
workspaceId,
|
||||
adminRoleId,
|
||||
options,
|
||||
});
|
||||
|
||||
await this.setAdminRoleAsDefaultRole({
|
||||
workspaceId,
|
||||
adminRoleId,
|
||||
options,
|
||||
});
|
||||
|
||||
const memberRole = workspaceRoles.find(
|
||||
(role) => role.label === MEMBER_ROLE_LABEL,
|
||||
);
|
||||
|
||||
if (!isDefined(memberRole)) {
|
||||
await this.createMemberRole({
|
||||
workspaceId,
|
||||
options,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.log(
|
||||
chalk.red(`Error in workspace ${workspaceId} - ${error.message}`),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async createAdminRole({
|
||||
workspaceId,
|
||||
options,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
options: ActiveOrSuspendedWorkspacesMigrationCommandOptions;
|
||||
}) {
|
||||
this.logger.log(
|
||||
chalk.green(`Creating admin role ${options.dryRun ? '(dry run)' : ''}`),
|
||||
);
|
||||
|
||||
if (options.dryRun) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const adminRole = await this.roleService.createAdminRole({
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
return adminRole.id;
|
||||
}
|
||||
|
||||
private async createMemberRole({
|
||||
workspaceId,
|
||||
options,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
options: ActiveOrSuspendedWorkspacesMigrationCommandOptions;
|
||||
}) {
|
||||
this.logger.log(
|
||||
chalk.green(`Creating member role ${options.dryRun ? '(dry run)' : ''}`),
|
||||
);
|
||||
|
||||
if (options.dryRun) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const memberRole = await this.roleService.createMemberRole({
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
return memberRole.id;
|
||||
}
|
||||
|
||||
private async setAdminRoleAsDefaultRole({
|
||||
workspaceId,
|
||||
adminRoleId,
|
||||
options,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
adminRoleId: string;
|
||||
options: ActiveOrSuspendedWorkspacesMigrationCommandOptions;
|
||||
}) {
|
||||
const workspaceDefaultRole = await this.workspaceRepository.findOne({
|
||||
where: {
|
||||
id: workspaceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (isDefined(workspaceDefaultRole?.defaultRoleId)) {
|
||||
this.logger.log(
|
||||
chalk.green(
|
||||
'Workspace already has a default role. Skipping setting admin role as default role',
|
||||
),
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
chalk.green(
|
||||
`Setting admin role as default role ${options.dryRun ? '(dry run)' : ''}`,
|
||||
),
|
||||
);
|
||||
|
||||
if (options.dryRun) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.workspaceRepository.update(workspaceId, {
|
||||
defaultRoleId: adminRoleId,
|
||||
});
|
||||
}
|
||||
|
||||
private async assignAdminRoleToMembers({
|
||||
workspaceId,
|
||||
adminRoleId,
|
||||
options,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
adminRoleId: string;
|
||||
options: ActiveOrSuspendedWorkspacesMigrationCommandOptions;
|
||||
}) {
|
||||
const userWorkspaces = await this.userWorkspaceRepository.find({
|
||||
where: {
|
||||
workspaceId,
|
||||
},
|
||||
});
|
||||
|
||||
const rolesByUserWorkspace =
|
||||
await this.userRoleService.getRolesByUserWorkspaces({
|
||||
userWorkspaceIds: userWorkspaces.map(
|
||||
(userWorkspace) => userWorkspace.id,
|
||||
),
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
for (const userWorkspace of userWorkspaces) {
|
||||
if (
|
||||
rolesByUserWorkspace
|
||||
.get(userWorkspace.id)
|
||||
?.some((role) => isDefined(role))
|
||||
) {
|
||||
this.logger.log(
|
||||
chalk.green(
|
||||
`User workspace ${userWorkspace.id} already has a role. Skipping role assignation`,
|
||||
),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
chalk.green(
|
||||
`Assigning admin role to workspace member ${userWorkspace.id} ${options.dryRun ? '(dry run)' : ''}`,
|
||||
),
|
||||
);
|
||||
|
||||
if (options.dryRun) {
|
||||
continue;
|
||||
}
|
||||
|
||||
await this.userRoleService.assignRoleToUserWorkspace({
|
||||
roleId: adminRoleId,
|
||||
userWorkspaceId: userWorkspace.id,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,272 +0,0 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import chalk from 'chalk';
|
||||
import { Command } from 'nest-commander';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import {
|
||||
ActiveOrSuspendedWorkspacesMigrationCommandRunner,
|
||||
RunOnWorkspaceArgs,
|
||||
} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service';
|
||||
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
||||
import {
|
||||
WorkspaceMigrationColumnActionType,
|
||||
WorkspaceMigrationTableAction,
|
||||
WorkspaceMigrationTableActionType,
|
||||
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||
import { WorkspaceMigrationFactory } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.factory';
|
||||
import { WorkspaceMigrationService } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.service';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
||||
import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service';
|
||||
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
||||
|
||||
const AGGREGATE_OPERATION_OPTIONS = [
|
||||
{
|
||||
value: AggregateOperations.AVG,
|
||||
label: 'Average',
|
||||
position: 0,
|
||||
color: 'red',
|
||||
},
|
||||
{
|
||||
value: AggregateOperations.COUNT,
|
||||
label: 'Count',
|
||||
position: 1,
|
||||
color: 'purple',
|
||||
},
|
||||
{
|
||||
value: AggregateOperations.MAX,
|
||||
label: 'Maximum',
|
||||
position: 2,
|
||||
color: 'sky',
|
||||
},
|
||||
{
|
||||
value: AggregateOperations.MIN,
|
||||
label: 'Minimum',
|
||||
position: 3,
|
||||
color: 'turquoise',
|
||||
},
|
||||
{
|
||||
value: AggregateOperations.SUM,
|
||||
label: 'Sum',
|
||||
position: 4,
|
||||
color: 'yellow',
|
||||
},
|
||||
{
|
||||
value: AggregateOperations.COUNT_EMPTY,
|
||||
label: 'Count empty',
|
||||
position: 5,
|
||||
color: 'red',
|
||||
},
|
||||
{
|
||||
value: AggregateOperations.COUNT_NOT_EMPTY,
|
||||
label: 'Count not empty',
|
||||
position: 6,
|
||||
color: 'purple',
|
||||
},
|
||||
{
|
||||
value: AggregateOperations.COUNT_UNIQUE_VALUES,
|
||||
label: 'Count unique values',
|
||||
position: 7,
|
||||
color: 'sky',
|
||||
},
|
||||
{
|
||||
value: AggregateOperations.PERCENTAGE_EMPTY,
|
||||
label: 'Percent empty',
|
||||
position: 8,
|
||||
color: 'turquoise',
|
||||
},
|
||||
{
|
||||
value: AggregateOperations.PERCENTAGE_NOT_EMPTY,
|
||||
label: 'Percent not empty',
|
||||
position: 9,
|
||||
color: 'yellow',
|
||||
},
|
||||
{
|
||||
value: AggregateOperations.COUNT_TRUE,
|
||||
label: 'Count true',
|
||||
position: 10,
|
||||
color: 'red',
|
||||
},
|
||||
{
|
||||
value: AggregateOperations.COUNT_FALSE,
|
||||
label: 'Count false',
|
||||
position: 11,
|
||||
color: 'purple',
|
||||
},
|
||||
];
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:0-44:update-view-aggregate-operations',
|
||||
description:
|
||||
'Update View and ViewField entities with new aggregate operations (countTrue, countFalse)',
|
||||
})
|
||||
export class UpdateViewAggregateOperationsCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(Workspace, 'core')
|
||||
protected readonly workspaceRepository: Repository<Workspace>,
|
||||
@InjectRepository(ObjectMetadataEntity, 'metadata')
|
||||
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
|
||||
@InjectRepository(FieldMetadataEntity, 'metadata')
|
||||
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
|
||||
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||
private readonly workspaceMigrationService: WorkspaceMigrationService,
|
||||
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
||||
private readonly workspaceMigrationFactory: WorkspaceMigrationFactory,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
index,
|
||||
total,
|
||||
workspaceId,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
this.logger.log(
|
||||
`Running command for workspace ${workspaceId} ${index + 1}/${total}`,
|
||||
);
|
||||
|
||||
await this.updateViewAggregateOperations(workspaceId);
|
||||
await this.updateViewFieldAggregateOperations(workspaceId);
|
||||
|
||||
await this.workspaceMigrationRunnerService.executeMigrationFromPendingMigrations(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
this.logger.log(
|
||||
chalk.green(`Command completed for workspace ${workspaceId}.`),
|
||||
);
|
||||
}
|
||||
|
||||
private async updateViewAggregateOperations(
|
||||
workspaceId: string,
|
||||
): Promise<void> {
|
||||
const viewObjectMetadata = await this.objectMetadataRepository.findOne({
|
||||
where: {
|
||||
workspaceId,
|
||||
standardId: STANDARD_OBJECT_IDS.view,
|
||||
},
|
||||
relations: ['fields'],
|
||||
});
|
||||
|
||||
if (!viewObjectMetadata) {
|
||||
this.logger.warn(
|
||||
`View object metadata not found for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const kanbanAggregateOperationField = viewObjectMetadata.fields.find(
|
||||
(field) => field.name === 'kanbanAggregateOperation',
|
||||
);
|
||||
|
||||
if (!kanbanAggregateOperationField) {
|
||||
this.logger.warn(
|
||||
`kanbanAggregateOperation field not found for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await this.fieldMetadataRepository.update(
|
||||
{ id: kanbanAggregateOperationField.id },
|
||||
{ options: AGGREGATE_OPERATION_OPTIONS },
|
||||
);
|
||||
|
||||
this.logger.log(
|
||||
`Updated kanbanAggregateOperation options for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
await this.workspaceMigrationService.createCustomMigration(
|
||||
generateMigrationName(`update-view-operations`),
|
||||
workspaceId,
|
||||
[
|
||||
{
|
||||
name: computeObjectTargetTable(viewObjectMetadata),
|
||||
action: WorkspaceMigrationTableActionType.ALTER,
|
||||
columns: this.workspaceMigrationFactory.createColumnActions(
|
||||
WorkspaceMigrationColumnActionType.ALTER,
|
||||
{ ...kanbanAggregateOperationField, options: undefined },
|
||||
{
|
||||
...kanbanAggregateOperationField,
|
||||
options: AGGREGATE_OPERATION_OPTIONS,
|
||||
},
|
||||
),
|
||||
} satisfies WorkspaceMigrationTableAction,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
private async updateViewFieldAggregateOperations(
|
||||
workspaceId: string,
|
||||
): Promise<void> {
|
||||
const viewFieldObjectMetadata = await this.objectMetadataRepository.findOne(
|
||||
{
|
||||
where: {
|
||||
workspaceId,
|
||||
standardId: STANDARD_OBJECT_IDS.viewField,
|
||||
},
|
||||
relations: ['fields'],
|
||||
},
|
||||
);
|
||||
|
||||
if (!viewFieldObjectMetadata) {
|
||||
this.logger.warn(
|
||||
`ViewField object metadata not found for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const aggregateOperationField = viewFieldObjectMetadata.fields.find(
|
||||
(field) => field.name === 'aggregateOperation',
|
||||
);
|
||||
|
||||
if (!aggregateOperationField) {
|
||||
this.logger.warn(
|
||||
`aggregateOperation field not found for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await this.fieldMetadataRepository.update(
|
||||
{ id: aggregateOperationField.id },
|
||||
{ options: AGGREGATE_OPERATION_OPTIONS },
|
||||
);
|
||||
|
||||
this.logger.log(
|
||||
`Updated aggregateOperation options for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
await this.workspaceMigrationService.createCustomMigration(
|
||||
generateMigrationName(`update-view-field-operations`),
|
||||
workspaceId,
|
||||
[
|
||||
{
|
||||
name: computeObjectTargetTable(viewFieldObjectMetadata),
|
||||
action: WorkspaceMigrationTableActionType.ALTER,
|
||||
columns: this.workspaceMigrationFactory.createColumnActions(
|
||||
WorkspaceMigrationColumnActionType.ALTER,
|
||||
{ ...aggregateOperationField, options: undefined },
|
||||
{
|
||||
...aggregateOperationField,
|
||||
options: AGGREGATE_OPERATION_OPTIONS,
|
||||
},
|
||||
),
|
||||
} satisfies WorkspaceMigrationTableAction,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { InitializePermissionsCommand } from 'src/database/commands/upgrade-version-command/0-44/0-44-initialize-permissions.command';
|
||||
import { UpdateViewAggregateOperationsCommand } from 'src/database/commands/upgrade-version-command/0-44/0-44-update-view-aggregate-operations.command';
|
||||
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { RoleModule } from 'src/engine/metadata-modules/role/role.module';
|
||||
import { UserRoleModule } from 'src/engine/metadata-modules/user-role/user-role.module';
|
||||
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Workspace, UserWorkspace], 'core'),
|
||||
TypeOrmModule.forFeature(
|
||||
[FieldMetadataEntity, ObjectMetadataEntity],
|
||||
'metadata',
|
||||
),
|
||||
WorkspaceDataSourceModule,
|
||||
RoleModule,
|
||||
UserRoleModule,
|
||||
WorkspaceMigrationModule,
|
||||
WorkspaceMigrationRunnerModule,
|
||||
WorkspaceMetadataVersionModule,
|
||||
],
|
||||
providers: [
|
||||
InitializePermissionsCommand,
|
||||
UpdateViewAggregateOperationsCommand,
|
||||
],
|
||||
exports: [InitializePermissionsCommand, UpdateViewAggregateOperationsCommand],
|
||||
})
|
||||
export class V0_44_UpgradeVersionCommandModule {}
|
||||
@ -1,32 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { RoleModule } from 'src/engine/metadata-modules/role/role.module';
|
||||
import { UserRoleModule } from 'src/engine/metadata-modules/user-role/user-role.module';
|
||||
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Workspace, UserWorkspace], 'core'),
|
||||
TypeOrmModule.forFeature(
|
||||
[FieldMetadataEntity, ObjectMetadataEntity],
|
||||
'metadata',
|
||||
),
|
||||
WorkspaceDataSourceModule,
|
||||
RoleModule,
|
||||
UserRoleModule,
|
||||
WorkspaceMigrationModule,
|
||||
WorkspaceMigrationRunnerModule,
|
||||
WorkspaceMetadataVersionModule,
|
||||
],
|
||||
providers: [],
|
||||
exports: [],
|
||||
})
|
||||
export class V0_50_UpgradeVersionCommandModule {}
|
||||
@ -1,112 +0,0 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Command } from 'nest-commander';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import {
|
||||
ActiveOrSuspendedWorkspacesMigrationCommandRunner,
|
||||
RunOnWorkspaceArgs,
|
||||
} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import { computeTableName } from 'src/engine/utils/compute-table-name.util';
|
||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:0-51:upgrade-created-by-enum',
|
||||
description: 'Upgrade created by enum',
|
||||
})
|
||||
export class UpgradeCreatedByEnumCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(Workspace, 'core')
|
||||
protected readonly workspaceRepository: Repository<Workspace>,
|
||||
@InjectRepository(ObjectMetadataEntity, 'metadata')
|
||||
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
|
||||
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
index,
|
||||
total,
|
||||
workspaceId,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
this.logger.log(
|
||||
`Running command for workspace ${workspaceId} ${index + 1}/${total}`,
|
||||
);
|
||||
|
||||
const schemaName =
|
||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||
|
||||
const workspaceDataSource =
|
||||
await this.twentyORMGlobalManager.getDataSourceForWorkspace({
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
const objectMetadatas = await this.objectMetadataRepository.find({
|
||||
where: {
|
||||
workspaceId,
|
||||
},
|
||||
relations: ['fields'],
|
||||
});
|
||||
|
||||
const queryRunner = workspaceDataSource?.createQueryRunner();
|
||||
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
try {
|
||||
for (const objectMetadata of objectMetadatas) {
|
||||
if (
|
||||
!isDefined(
|
||||
objectMetadata.fields.find((field) => field.name === 'createdBy'),
|
||||
)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const tableToUpdate = computeTableName(
|
||||
objectMetadata.nameSingular,
|
||||
objectMetadata.isCustom,
|
||||
);
|
||||
|
||||
// Set current column as text
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "${schemaName}"."${tableToUpdate}"
|
||||
ALTER COLUMN "createdBySource" SET DATA TYPE text USING "createdBySource"::text`,
|
||||
);
|
||||
|
||||
// Drop default value
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "${schemaName}"."${tableToUpdate}"
|
||||
ALTER COLUMN "createdBySource" DROP DEFAULT`,
|
||||
);
|
||||
|
||||
// Drop the old enum type
|
||||
await queryRunner.query(
|
||||
`DROP TYPE "${schemaName}"."${tableToUpdate}_createdBySource_enum"`,
|
||||
);
|
||||
|
||||
await queryRunner.query(
|
||||
`CREATE TYPE "${schemaName}"."${tableToUpdate}_createdBySource_enum" AS ENUM ('EMAIL', 'CALENDAR', 'WORKFLOW', 'API', 'IMPORT', 'MANUAL', 'SYSTEM', 'WEBHOOK')`,
|
||||
);
|
||||
|
||||
// Re-apply the enum type
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "${schemaName}"."${tableToUpdate}"
|
||||
ALTER COLUMN "createdBySource" SET DATA TYPE "${schemaName}"."${tableToUpdate}_createdBySource_enum" USING "createdBySource"::"${schemaName}"."${tableToUpdate}_createdBySource_enum"`,
|
||||
);
|
||||
}
|
||||
await queryRunner.commitTransaction();
|
||||
} catch (error) {
|
||||
await queryRunner.rollbackTransaction();
|
||||
throw error;
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||
import { UpgradeCreatedByEnumCommand } from 'src/database/commands/upgrade-version-command/0-51/0-51-update-workflow-trigger-type-enum.command';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Workspace], 'core'),
|
||||
TypeOrmModule.forFeature(
|
||||
[ObjectMetadataEntity, FieldMetadataEntity],
|
||||
'metadata',
|
||||
),
|
||||
WorkspaceDataSourceModule,
|
||||
],
|
||||
providers: [UpgradeCreatedByEnumCommand],
|
||||
exports: [UpgradeCreatedByEnumCommand],
|
||||
})
|
||||
export class V0_51_UpgradeVersionCommandModule {}
|
||||
@ -1,145 +0,0 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import chalk from 'chalk';
|
||||
import { Command } from 'nest-commander';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { In, Repository } from 'typeorm';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import {
|
||||
ActiveOrSuspendedWorkspacesMigrationCommandRunner,
|
||||
RunOnWorkspaceArgs,
|
||||
} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import {
|
||||
RelationDirection,
|
||||
deduceRelationDirection,
|
||||
} from 'src/engine/utils/deduce-relation-direction.util';
|
||||
import { isFieldMetadataEntityOfType } from 'src/engine/utils/is-field-metadata-of-type.util';
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:0-52:migrate-relations-to-field-metadata',
|
||||
description: 'Migrate relations to field metadata',
|
||||
})
|
||||
export class MigrateRelationsToFieldMetadataCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(Workspace, 'core')
|
||||
protected readonly workspaceRepository: Repository<Workspace>,
|
||||
@InjectRepository(FieldMetadataEntity, 'metadata')
|
||||
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
|
||||
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
index,
|
||||
total,
|
||||
workspaceId,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
this.logger.log(
|
||||
`Running command for workspace ${workspaceId} ${index + 1}/${total}`,
|
||||
);
|
||||
|
||||
const fieldMetadataCollection = await this.fieldMetadataRepository.find({
|
||||
where: {
|
||||
workspaceId,
|
||||
type: In([FieldMetadataType.RELATION, FieldMetadataType.UUID]),
|
||||
},
|
||||
relations: ['fromRelationMetadata', 'toRelationMetadata'],
|
||||
});
|
||||
|
||||
if (!fieldMetadataCollection.length) {
|
||||
this.logger.log(
|
||||
chalk.yellow(
|
||||
`No relation field metadata found for workspace ${workspaceId}.`,
|
||||
),
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const joinColumnFieldMetadataCollection = fieldMetadataCollection.filter(
|
||||
(fieldMetadata) =>
|
||||
isFieldMetadataEntityOfType(fieldMetadata, FieldMetadataType.UUID),
|
||||
// TODO: Fix this, it's working in other places but not here
|
||||
) as FieldMetadataEntity<FieldMetadataType.UUID>[];
|
||||
|
||||
const fieldMetadataToUpdateCollection = fieldMetadataCollection
|
||||
.filter((fieldMetadata) =>
|
||||
isFieldMetadataEntityOfType(fieldMetadata, FieldMetadataType.RELATION),
|
||||
)
|
||||
.map((fieldMetadata) =>
|
||||
this.updateRelationFieldMetadata(
|
||||
joinColumnFieldMetadataCollection,
|
||||
// TODO: Fix this, it's working in other places but not here
|
||||
fieldMetadata as FieldMetadataEntity<FieldMetadataType.RELATION>,
|
||||
),
|
||||
);
|
||||
|
||||
if (fieldMetadataToUpdateCollection.length > 0) {
|
||||
await this.fieldMetadataRepository.save(fieldMetadataToUpdateCollection);
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
chalk.green(`Command completed for workspace ${workspaceId}.`),
|
||||
);
|
||||
}
|
||||
|
||||
private updateRelationFieldMetadata(
|
||||
joinColumnFieldMetadataCollection: FieldMetadataEntity<FieldMetadataType.UUID>[],
|
||||
fieldMetadata: FieldMetadataEntity<FieldMetadataType.RELATION>,
|
||||
): FieldMetadataEntity<FieldMetadataType.RELATION> {
|
||||
const relationMetadata =
|
||||
fieldMetadata.fromRelationMetadata ?? fieldMetadata.toRelationMetadata;
|
||||
const joinColumnFieldMetadata = joinColumnFieldMetadataCollection.find(
|
||||
(joinColumnFieldMetadata) =>
|
||||
// We're deducing the field based on the name of the relation field
|
||||
// This is not the best way to do this but we don't have a better way
|
||||
joinColumnFieldMetadata.name === `${fieldMetadata.name}Id`,
|
||||
);
|
||||
|
||||
const relationDirection = deduceRelationDirection(
|
||||
fieldMetadata,
|
||||
relationMetadata,
|
||||
);
|
||||
let relationType = relationMetadata.relationType as unknown as RelationType;
|
||||
|
||||
if (
|
||||
relationDirection === RelationDirection.TO &&
|
||||
relationType === RelationType.ONE_TO_MANY
|
||||
) {
|
||||
relationType = RelationType.MANY_TO_ONE;
|
||||
}
|
||||
|
||||
const relationTargetFieldMetadataId =
|
||||
relationDirection === RelationDirection.FROM
|
||||
? relationMetadata.toFieldMetadataId
|
||||
: relationMetadata.fromFieldMetadataId;
|
||||
|
||||
const relationTargetObjectMetadataId =
|
||||
relationDirection === RelationDirection.FROM
|
||||
? relationMetadata.toObjectMetadataId
|
||||
: relationMetadata.fromObjectMetadataId;
|
||||
|
||||
return {
|
||||
...fieldMetadata,
|
||||
settings: {
|
||||
relationType,
|
||||
onDelete:
|
||||
relationType === RelationType.MANY_TO_ONE
|
||||
? relationMetadata.onDeleteAction
|
||||
: undefined,
|
||||
joinColumnName:
|
||||
relationType === RelationType.MANY_TO_ONE
|
||||
? joinColumnFieldMetadata?.name
|
||||
: undefined,
|
||||
},
|
||||
relationTargetFieldMetadataId,
|
||||
relationTargetObjectMetadataId,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1,90 +0,0 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import chalk from 'chalk';
|
||||
import { Command } from 'nest-commander';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { In, Repository } from 'typeorm';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
|
||||
import {
|
||||
ActiveOrSuspendedWorkspacesMigrationCommandRunner,
|
||||
RunOnWorkspaceArgs,
|
||||
} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||
|
||||
type DeprecatedFieldMetadataDateSettings = {
|
||||
displayAsRelativeDate?: boolean;
|
||||
};
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:0-52:upgrade-date-and-date-time-field-settings',
|
||||
description: 'Upgrade settings column on all date and date time fields',
|
||||
})
|
||||
export class UpgradeDateAndDateTimeFieldsSettingsJsonCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(Workspace, 'core')
|
||||
protected readonly workspaceRepository: Repository<Workspace>,
|
||||
@InjectRepository(ObjectMetadataEntity, 'metadata')
|
||||
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
|
||||
@InjectRepository(FieldMetadataEntity, 'metadata')
|
||||
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
|
||||
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
index,
|
||||
total,
|
||||
workspaceId,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
this.logger.log(
|
||||
`Running command for workspace ${workspaceId} ${index + 1}/${total}`,
|
||||
);
|
||||
|
||||
const fieldMetadataCollection = (await this.fieldMetadataRepository.find({
|
||||
where: {
|
||||
workspaceId,
|
||||
type: In([FieldMetadataType.DATE, FieldMetadataType.DATE_TIME]),
|
||||
},
|
||||
})) as FieldMetadataEntity<FieldMetadataType.DATE>[];
|
||||
|
||||
const updatedFieldMetadataCollection = fieldMetadataCollection.map(
|
||||
(field) => this.updateDateAndDateTimeFieldMetadata(field),
|
||||
);
|
||||
|
||||
if (updatedFieldMetadataCollection.length > 0) {
|
||||
await this.fieldMetadataRepository.save(updatedFieldMetadataCollection);
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
chalk.green(`Command completed for workspace ${workspaceId}.`),
|
||||
);
|
||||
}
|
||||
|
||||
private updateDateAndDateTimeFieldMetadata(
|
||||
field: FieldMetadataEntity<FieldMetadataType.DATE>,
|
||||
): FieldMetadataEntity<FieldMetadataType.DATE> {
|
||||
const settings = field.settings as DeprecatedFieldMetadataDateSettings;
|
||||
|
||||
if (!isDefined(settings?.displayAsRelativeDate)) {
|
||||
return field;
|
||||
}
|
||||
|
||||
return {
|
||||
...field,
|
||||
settings: {
|
||||
displayFormat: settings.displayAsRelativeDate
|
||||
? DateDisplayFormat.RELATIVE
|
||||
: DateDisplayFormat.USER_SETTINGS,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { MigrateRelationsToFieldMetadataCommand } from 'src/database/commands/upgrade-version-command/0-52/0-52-migrate-relations-to-field-metadata.command';
|
||||
import { UpgradeDateAndDateTimeFieldsSettingsJsonCommand } from 'src/database/commands/upgrade-version-command/0-52/0-52-upgrade-settings-field';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Workspace], 'core'),
|
||||
TypeOrmModule.forFeature(
|
||||
[ObjectMetadataEntity, FieldMetadataEntity],
|
||||
'metadata',
|
||||
),
|
||||
WorkspaceDataSourceModule,
|
||||
],
|
||||
providers: [
|
||||
UpgradeDateAndDateTimeFieldsSettingsJsonCommand,
|
||||
MigrateRelationsToFieldMetadataCommand,
|
||||
],
|
||||
exports: [
|
||||
UpgradeDateAndDateTimeFieldsSettingsJsonCommand,
|
||||
MigrateRelationsToFieldMetadataCommand,
|
||||
],
|
||||
})
|
||||
export class V0_52_UpgradeVersionCommandModule {}
|
||||
@ -1,151 +0,0 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Command } from 'nest-commander';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import {
|
||||
ActiveOrSuspendedWorkspacesMigrationCommandRunner,
|
||||
RunOnWorkspaceArgs,
|
||||
} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import { WorkflowRunWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity';
|
||||
import { WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity';
|
||||
import { WorkflowTrigger } from 'src/modules/workflow/workflow-trigger/types/workflow-trigger.type';
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:0-53:backfill-workflow-next-step-ids',
|
||||
description: 'Backfill workflow next step ids',
|
||||
})
|
||||
export class BackfillWorkflowNextStepIdsCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(Workspace, 'core')
|
||||
protected readonly workspaceRepository: Repository<Workspace>,
|
||||
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
index,
|
||||
total,
|
||||
workspaceId,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
this.logger.log(
|
||||
`Running command for workspace ${workspaceId} ${index + 1}/${total}`,
|
||||
);
|
||||
|
||||
const workflowVersionRepository =
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkflowVersionWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'workflowVersion',
|
||||
);
|
||||
|
||||
const workflowRunRepository =
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkflowRunWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'workflowRun',
|
||||
);
|
||||
|
||||
const workflowVersions = await workflowVersionRepository.find();
|
||||
|
||||
this.logger.log(`Number of workflow versions: ${workflowVersions.length}`);
|
||||
|
||||
for (const workflowVersion of workflowVersions) {
|
||||
this.logger.log(`Processing workflow version: ${workflowVersion.id}`);
|
||||
const updatedSteps: WorkflowVersionWorkspaceEntity['steps'] = [];
|
||||
const workflowSteps = workflowVersion.steps;
|
||||
|
||||
if (!workflowSteps) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// for each step, add the next step id which is the next index
|
||||
for (let stepIndex = 0; stepIndex < workflowSteps.length; stepIndex++) {
|
||||
const updatedStep = {
|
||||
...workflowSteps[stepIndex],
|
||||
nextStepIds:
|
||||
stepIndex < workflowSteps.length - 1 &&
|
||||
workflowSteps[stepIndex + 1]?.id
|
||||
? [workflowSteps[stepIndex + 1].id]
|
||||
: undefined,
|
||||
};
|
||||
|
||||
updatedSteps.push(updatedStep);
|
||||
}
|
||||
|
||||
// update workflow run flows by batch of 500
|
||||
const batchSize = 500;
|
||||
const totalWorkflowRuns = await workflowRunRepository.count({
|
||||
where: {
|
||||
workflowVersionId: workflowVersion.id,
|
||||
},
|
||||
});
|
||||
|
||||
const totalBatches = Math.ceil(totalWorkflowRuns / batchSize);
|
||||
|
||||
this.logger.log(`Total batches: ${totalBatches}`);
|
||||
|
||||
for (let batchIndex = 0; batchIndex < totalBatches; batchIndex++) {
|
||||
const updatedWorkflowRuns: WorkflowRunWorkspaceEntity[] = [];
|
||||
|
||||
this.logger.log(`Processing batch ${batchIndex + 1}/${totalBatches}`);
|
||||
const workflowRuns = await workflowRunRepository.find({
|
||||
where: {
|
||||
workflowVersionId: workflowVersion.id,
|
||||
},
|
||||
take: batchSize,
|
||||
skip: batchIndex * batchSize,
|
||||
order: {
|
||||
id: 'ASC',
|
||||
},
|
||||
});
|
||||
|
||||
for (const workflowRun of workflowRuns) {
|
||||
const flow = workflowRun.output?.flow;
|
||||
|
||||
if (!flow?.steps || flow.steps.length < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const updatedStepsMap = new Map(
|
||||
updatedSteps.map((step) => [step.id, step]),
|
||||
);
|
||||
|
||||
const updatedFlow = flow.steps.map((step) => {
|
||||
const updatedStep = updatedStepsMap.get(step.id);
|
||||
|
||||
return {
|
||||
...step,
|
||||
nextStepIds: updatedStep?.nextStepIds,
|
||||
};
|
||||
});
|
||||
|
||||
const updatedWorkflowRun: WorkflowRunWorkspaceEntity = {
|
||||
...workflowRun,
|
||||
output: {
|
||||
...workflowRun.output,
|
||||
flow: {
|
||||
trigger: workflowRun.output?.flow?.trigger as WorkflowTrigger,
|
||||
steps: updatedFlow,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
updatedWorkflowRuns.push(updatedWorkflowRun);
|
||||
}
|
||||
|
||||
await workflowRunRepository.save(updatedWorkflowRuns);
|
||||
}
|
||||
|
||||
await workflowVersionRepository.save({
|
||||
...workflowVersion,
|
||||
steps: updatedSteps,
|
||||
});
|
||||
|
||||
this.logger.log(
|
||||
`Updated workflow version ${workflowVersion.id} for workspace ${workspaceId}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,108 +0,0 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Command } from 'nest-commander';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import {
|
||||
MigrationCommandOptions,
|
||||
MigrationCommandRunner,
|
||||
} from 'src/database/commands/command-runners/migration.command-runner';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:0-53:copy-typeorm-migrations',
|
||||
description: 'Copy _typeorm_migrations from metadata schema to core schema',
|
||||
})
|
||||
export class CopyTypeormMigrationsCommand extends MigrationCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(Workspace, 'core')
|
||||
protected readonly workspaceRepository: Repository<Workspace>,
|
||||
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
override async runMigrationCommand(
|
||||
_passedParams: string[],
|
||||
options: MigrationCommandOptions,
|
||||
): Promise<void> {
|
||||
this.logger.log(
|
||||
'Starting to copy _typeorm_migrations from metadata to core',
|
||||
);
|
||||
|
||||
const queryRunner =
|
||||
this.workspaceRepository.manager.connection.createQueryRunner();
|
||||
|
||||
try {
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
// Check if metadata._typeorm_migrations table exists
|
||||
const tableExists = await queryRunner.query(
|
||||
`SELECT EXISTS (
|
||||
SELECT FROM information_schema.tables
|
||||
WHERE table_schema = 'metadata'
|
||||
AND table_name = '_typeorm_migrations'
|
||||
)`,
|
||||
);
|
||||
|
||||
if (!tableExists[0].exists) {
|
||||
this.logger.log(
|
||||
'metadata._typeorm_migrations table does not exist, skipping migration',
|
||||
);
|
||||
await queryRunner.commitTransaction();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const metadataMigrations = await queryRunner.query(
|
||||
'SELECT * FROM metadata._typeorm_migrations ORDER BY id ASC',
|
||||
);
|
||||
|
||||
this.logger.log(
|
||||
`Found ${metadataMigrations.length} migrations in metadata schema`,
|
||||
);
|
||||
|
||||
if (options?.dryRun) {
|
||||
this.logger.log('Dry run mode - no changes will be applied');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const existingCoreMigrations = await queryRunner.query(
|
||||
'SELECT name FROM core._typeorm_migrations',
|
||||
);
|
||||
|
||||
const existingMigrationNames = new Set(
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
existingCoreMigrations.map((migration) => migration.name),
|
||||
);
|
||||
|
||||
for (const migration of metadataMigrations) {
|
||||
if (!existingMigrationNames.has(migration.name)) {
|
||||
await queryRunner.query(
|
||||
'INSERT INTO core._typeorm_migrations ("timestamp", name) VALUES ($1, $2)',
|
||||
[migration.timestamp, migration.name],
|
||||
);
|
||||
this.logger.log(`Copied migration: ${migration.name}`);
|
||||
} else {
|
||||
this.logger.log(
|
||||
`Migration ${migration.name} already exists in core schema`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await queryRunner.commitTransaction();
|
||||
this.logger.log(
|
||||
'Successfully copied all migrations from metadata to core schema',
|
||||
);
|
||||
} catch (error) {
|
||||
await queryRunner.rollbackTransaction();
|
||||
this.logger.error(`Failed to copy migrations: ${error.message}`);
|
||||
throw error;
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Command } from 'nest-commander';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import {
|
||||
ActiveOrSuspendedWorkspacesMigrationCommandRunner,
|
||||
RunOnWorkspaceArgs,
|
||||
} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import {
|
||||
AutomatedTriggerType,
|
||||
WorkflowAutomatedTriggerWorkspaceEntity,
|
||||
} from 'src/modules/workflow/common/standard-objects/workflow-automated-trigger.workspace-entity';
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:0-53:migrate-workflow-event-listeners-to-automated-triggers',
|
||||
description: 'Migrate workflow event listeners to automated triggers',
|
||||
})
|
||||
export class MigrateWorkflowEventListenersToAutomatedTriggersCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(Workspace, 'core')
|
||||
protected readonly workspaceRepository: Repository<Workspace>,
|
||||
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
index,
|
||||
total,
|
||||
workspaceId,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
this.logger.log(
|
||||
`Running command for workspace ${workspaceId} ${index + 1}/${total}`,
|
||||
);
|
||||
|
||||
const workflowEventListenerRepository =
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace(
|
||||
workspaceId,
|
||||
'workflowEventListener',
|
||||
);
|
||||
|
||||
const workflowAutomatedTriggerRepository =
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkflowAutomatedTriggerWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'workflowAutomatedTrigger',
|
||||
);
|
||||
|
||||
const workflowEventListeners = await workflowEventListenerRepository.find();
|
||||
|
||||
await workflowAutomatedTriggerRepository.delete({
|
||||
type: AutomatedTriggerType.DATABASE_EVENT,
|
||||
});
|
||||
|
||||
for (const eventListener of workflowEventListeners) {
|
||||
const { eventName, ...rest } = eventListener;
|
||||
|
||||
await workflowAutomatedTriggerRepository.save({
|
||||
...rest,
|
||||
type: AutomatedTriggerType.DATABASE_EVENT,
|
||||
settings: { eventName },
|
||||
});
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
`Migrated ${workflowEventListeners.length} workflow event listeners to automated triggers`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,84 +0,0 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import chalk from 'chalk';
|
||||
import { Command } from 'nest-commander';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { In, Like, Repository } from 'typeorm';
|
||||
|
||||
import {
|
||||
ActiveOrSuspendedWorkspacesMigrationCommandRunner,
|
||||
RunOnWorkspaceArgs,
|
||||
} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
||||
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:0-53:remove-relation-foreign-key-field-metadata',
|
||||
description: 'Remove relation foreign key from field metadata',
|
||||
})
|
||||
export class RemoveRelationForeignKeyFieldMetadataCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(Workspace, 'core')
|
||||
protected readonly workspaceRepository: Repository<Workspace>,
|
||||
protected readonly featureFlagService: FeatureFlagService,
|
||||
@InjectRepository(FieldMetadataEntity, 'metadata')
|
||||
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
|
||||
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
index,
|
||||
total,
|
||||
workspaceId,
|
||||
options,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
this.logger.log(
|
||||
`Running command for workspace ${workspaceId} ${index + 1}/${total}`,
|
||||
);
|
||||
|
||||
const fieldMetadataCollection = await this.fieldMetadataRepository.find({
|
||||
where: {
|
||||
workspaceId,
|
||||
type: In([FieldMetadataType.UUID]),
|
||||
label: Like('%(foreign key)%'),
|
||||
},
|
||||
});
|
||||
|
||||
if (!fieldMetadataCollection.length) {
|
||||
this.logger.log(
|
||||
chalk.yellow(
|
||||
`No relation field metadata found for workspace ${workspaceId}.`,
|
||||
),
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.dryRun) {
|
||||
this.logger.log(
|
||||
chalk.yellow(
|
||||
`Dry run, would delete ${fieldMetadataCollection.length} relation field metadata for workspace ${workspaceId}.`,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
await this.featureFlagService.enableFeatureFlags(
|
||||
['IS_NEW_RELATION_ENABLED' as FeatureFlagKey],
|
||||
workspaceId,
|
||||
);
|
||||
await this.fieldMetadataRepository.delete({
|
||||
id: In(
|
||||
fieldMetadataCollection.map((fieldMetadata) => fieldMetadata.id),
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
chalk.green(`Command completed for workspace ${workspaceId}.`),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,76 +0,0 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Command } from 'nest-commander';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import {
|
||||
ActiveOrSuspendedWorkspacesMigrationCommandRunner,
|
||||
RunOnWorkspaceArgs,
|
||||
} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { SearchVectorService } from 'src/engine/metadata-modules/search-vector/search-vector.service';
|
||||
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service';
|
||||
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
||||
import { SEARCH_FIELDS_FOR_PERSON } from 'src/modules/person/standard-objects/person.workspace-entity';
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:0-53:upgrade-search-vector-on-person-entity',
|
||||
description: 'Upgrade search vector on person entity',
|
||||
})
|
||||
export class UpgradeSearchVectorOnPersonEntityCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(Workspace, 'core')
|
||||
protected readonly workspaceRepository: Repository<Workspace>,
|
||||
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
@InjectRepository(ObjectMetadataEntity, 'metadata')
|
||||
protected readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
|
||||
private readonly searchVectorService: SearchVectorService,
|
||||
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
||||
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
index,
|
||||
total,
|
||||
workspaceId,
|
||||
options,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
this.logger.log(
|
||||
`Running command for workspace ${workspaceId} ${index + 1}/${total}`,
|
||||
);
|
||||
|
||||
const personObjectMetadata =
|
||||
await this.objectMetadataRepository.findOneOrFail({
|
||||
select: ['id'],
|
||||
where: {
|
||||
workspaceId,
|
||||
standardId: STANDARD_OBJECT_IDS.person,
|
||||
},
|
||||
});
|
||||
|
||||
if (!options.dryRun) {
|
||||
await this.searchVectorService.updateSearchVector(
|
||||
personObjectMetadata.id,
|
||||
SEARCH_FIELDS_FOR_PERSON,
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await this.workspaceMigrationRunnerService.executeMigrationFromPendingMigrations(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||
workspaceId,
|
||||
);
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
`Migrated search vector on person entity for workspace ${workspaceId}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { BackfillWorkflowNextStepIdsCommand } from 'src/database/commands/upgrade-version-command/0-53/0-53-backfill-workflow-next-step-ids.command';
|
||||
import { CopyTypeormMigrationsCommand } from 'src/database/commands/upgrade-version-command/0-53/0-53-copy-typeorm-migrations.command';
|
||||
import { MigrateWorkflowEventListenersToAutomatedTriggersCommand } from 'src/database/commands/upgrade-version-command/0-53/0-53-migrate-workflow-event-listeners-to-automated-triggers.command';
|
||||
import { RemoveRelationForeignKeyFieldMetadataCommand } from 'src/database/commands/upgrade-version-command/0-53/0-53-remove-relation-foreign-key-field-metadata.command';
|
||||
import { UpgradeSearchVectorOnPersonEntityCommand } from 'src/database/commands/upgrade-version-command/0-53/0-53-upgrade-search-vector-on-person-entity.command';
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { SearchVectorModule } from 'src/engine/metadata-modules/search-vector/search-vector.module';
|
||||
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Workspace], 'core'),
|
||||
TypeOrmModule.forFeature(
|
||||
[FieldMetadataEntity, ObjectMetadataEntity],
|
||||
'metadata',
|
||||
),
|
||||
WorkspaceDataSourceModule,
|
||||
SearchVectorModule,
|
||||
WorkspaceMigrationRunnerModule,
|
||||
WorkspaceMetadataVersionModule,
|
||||
FeatureFlagModule,
|
||||
],
|
||||
providers: [
|
||||
MigrateWorkflowEventListenersToAutomatedTriggersCommand,
|
||||
CopyTypeormMigrationsCommand,
|
||||
BackfillWorkflowNextStepIdsCommand,
|
||||
RemoveRelationForeignKeyFieldMetadataCommand,
|
||||
UpgradeSearchVectorOnPersonEntityCommand,
|
||||
],
|
||||
exports: [
|
||||
MigrateWorkflowEventListenersToAutomatedTriggersCommand,
|
||||
RemoveRelationForeignKeyFieldMetadataCommand,
|
||||
BackfillWorkflowNextStepIdsCommand,
|
||||
CopyTypeormMigrationsCommand,
|
||||
UpgradeSearchVectorOnPersonEntityCommand,
|
||||
],
|
||||
})
|
||||
export class V0_53_UpgradeVersionCommandModule {}
|
||||
@ -25,7 +25,7 @@ export class FixCreatedByDefaultValueCommand extends ActiveOrSuspendedWorkspaces
|
||||
@InjectRepository(Workspace, 'core')
|
||||
protected readonly workspaceRepository: Repository<Workspace>,
|
||||
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
@InjectRepository(ObjectMetadataEntity, 'metadata')
|
||||
@InjectRepository(ObjectMetadataEntity, 'core')
|
||||
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
|
||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||
) {
|
||||
|
||||
@ -22,7 +22,7 @@ export class FixStandardSelectFieldsPositionCommand extends ActiveOrSuspendedWor
|
||||
@InjectRepository(Workspace, 'core')
|
||||
protected readonly workspaceRepository: Repository<Workspace>,
|
||||
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
@InjectRepository(FieldMetadataEntity, 'metadata')
|
||||
@InjectRepository(FieldMetadataEntity, 'core')
|
||||
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
|
||||
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||
) {
|
||||
|
||||
@ -26,7 +26,7 @@ import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/wor
|
||||
),
|
||||
TypeOrmModule.forFeature(
|
||||
[FieldMetadataEntity, ObjectMetadataEntity],
|
||||
'metadata',
|
||||
'core',
|
||||
),
|
||||
WorkspaceDataSourceModule,
|
||||
WorkspaceMigrationRunnerModule,
|
||||
|
||||
@ -15,13 +15,16 @@ import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/wor
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature(
|
||||
[Workspace, AppToken, User, UserWorkspace],
|
||||
[
|
||||
Workspace,
|
||||
AppToken,
|
||||
User,
|
||||
UserWorkspace,
|
||||
FieldMetadataEntity,
|
||||
ObjectMetadataEntity,
|
||||
],
|
||||
'core',
|
||||
),
|
||||
TypeOrmModule.forFeature(
|
||||
[FieldMetadataEntity, ObjectMetadataEntity],
|
||||
'metadata',
|
||||
),
|
||||
WorkspaceDataSourceModule,
|
||||
WorkspaceMigrationRunnerModule,
|
||||
WorkspaceMetadataVersionModule,
|
||||
|
||||
@ -1,11 +1,6 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { V0_44_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/0-44/0-44-upgrade-version-command.module';
|
||||
import { V0_50_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/0-50/0-50-upgrade-version-command.module';
|
||||
import { V0_51_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/0-51/0-51-upgrade-version-command.module';
|
||||
import { V0_52_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/0-52/0-52-upgrade-version-command.module';
|
||||
import { V0_53_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/0-53/0-53-upgrade-version-command.module';
|
||||
import { V0_54_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/0-54/0-54-upgrade-version-command.module';
|
||||
import { V0_55_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/0-55/0-55-upgrade-version-command.module';
|
||||
import {
|
||||
@ -18,11 +13,6 @@ import { WorkspaceSyncMetadataModule } from 'src/engine/workspace-manager/worksp
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Workspace], 'core'),
|
||||
V0_44_UpgradeVersionCommandModule,
|
||||
V0_50_UpgradeVersionCommandModule,
|
||||
V0_51_UpgradeVersionCommandModule,
|
||||
V0_52_UpgradeVersionCommandModule,
|
||||
V0_53_UpgradeVersionCommandModule,
|
||||
V0_54_UpgradeVersionCommandModule,
|
||||
V0_55_UpgradeVersionCommandModule,
|
||||
WorkspaceSyncMetadataModule,
|
||||
|
||||
@ -15,16 +15,6 @@ import {
|
||||
UpgradeCommandRunner,
|
||||
VersionCommands,
|
||||
} from 'src/database/commands/command-runners/upgrade.command-runner';
|
||||
import { InitializePermissionsCommand } from 'src/database/commands/upgrade-version-command/0-44/0-44-initialize-permissions.command';
|
||||
import { UpdateViewAggregateOperationsCommand } from 'src/database/commands/upgrade-version-command/0-44/0-44-update-view-aggregate-operations.command';
|
||||
import { UpgradeCreatedByEnumCommand } from 'src/database/commands/upgrade-version-command/0-51/0-51-update-workflow-trigger-type-enum.command';
|
||||
import { MigrateRelationsToFieldMetadataCommand } from 'src/database/commands/upgrade-version-command/0-52/0-52-migrate-relations-to-field-metadata.command';
|
||||
import { UpgradeDateAndDateTimeFieldsSettingsJsonCommand } from 'src/database/commands/upgrade-version-command/0-52/0-52-upgrade-settings-field';
|
||||
import { BackfillWorkflowNextStepIdsCommand } from 'src/database/commands/upgrade-version-command/0-53/0-53-backfill-workflow-next-step-ids.command';
|
||||
import { CopyTypeormMigrationsCommand } from 'src/database/commands/upgrade-version-command/0-53/0-53-copy-typeorm-migrations.command';
|
||||
import { MigrateWorkflowEventListenersToAutomatedTriggersCommand } from 'src/database/commands/upgrade-version-command/0-53/0-53-migrate-workflow-event-listeners-to-automated-triggers.command';
|
||||
import { RemoveRelationForeignKeyFieldMetadataCommand } from 'src/database/commands/upgrade-version-command/0-53/0-53-remove-relation-foreign-key-field-metadata.command';
|
||||
import { UpgradeSearchVectorOnPersonEntityCommand } from 'src/database/commands/upgrade-version-command/0-53/0-53-upgrade-search-vector-on-person-entity.command';
|
||||
import { CleanNotFoundFilesCommand } from 'src/database/commands/upgrade-version-command/0-54/0-54-clean-not-found-files.command';
|
||||
import { FixCreatedByDefaultValueCommand } from 'src/database/commands/upgrade-version-command/0-54/0-54-created-by-default-value.command';
|
||||
import { FixStandardSelectFieldsPositionCommand } from 'src/database/commands/upgrade-version-command/0-54/0-54-fix-standard-select-fields-position.command';
|
||||
@ -45,7 +35,6 @@ export class DatabaseMigrationService {
|
||||
constructor(
|
||||
@InjectRepository(Workspace, 'core')
|
||||
private readonly workspaceRepository: Repository<Workspace>,
|
||||
protected readonly copyTypeormMigrationsCommand: CopyTypeormMigrationsCommand,
|
||||
) {}
|
||||
|
||||
// TODO centralize with ActiveOrSuspendedRunner method
|
||||
@ -75,17 +64,6 @@ export class DatabaseMigrationService {
|
||||
this.logger.log('Running global database migrations');
|
||||
|
||||
try {
|
||||
this.logger.log('Running metadata datasource migrations...');
|
||||
await this.copyTypeormMigrationsCommand.runMigrationCommand([], {
|
||||
dryRun: false,
|
||||
verbose: false,
|
||||
});
|
||||
const metadataResult = await execPromise(
|
||||
'npx -y typeorm migration:run -d dist/src/database/typeorm/metadata/metadata.datasource',
|
||||
);
|
||||
|
||||
this.logger.log(metadataResult.stdout);
|
||||
|
||||
this.logger.log('Running core datasource migrations...');
|
||||
const coreResult = await execPromise(
|
||||
'npx -y typeorm migration:run -d dist/src/database/typeorm/core/core.datasource',
|
||||
@ -147,24 +125,6 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
|
||||
private readonly databaseMigrationService: DatabaseMigrationService,
|
||||
|
||||
// 0.44 Commands
|
||||
protected readonly initializePermissionsCommand: InitializePermissionsCommand,
|
||||
protected readonly updateViewAggregateOperationsCommand: UpdateViewAggregateOperationsCommand,
|
||||
|
||||
// 0.51 Commands
|
||||
protected readonly upgradeCreatedByEnumCommand: UpgradeCreatedByEnumCommand,
|
||||
|
||||
// 0.52 Commands
|
||||
protected readonly upgradeDateAndDateTimeFieldsSettingsJsonCommand: UpgradeDateAndDateTimeFieldsSettingsJsonCommand,
|
||||
protected readonly migrateRelationsToFieldMetadataCommand: MigrateRelationsToFieldMetadataCommand,
|
||||
|
||||
// 0.53 Commands
|
||||
protected readonly migrateWorkflowEventListenersToAutomatedTriggersCommand: MigrateWorkflowEventListenersToAutomatedTriggersCommand,
|
||||
protected readonly backfillWorkflowNextStepIdsCommand: BackfillWorkflowNextStepIdsCommand,
|
||||
protected readonly copyTypeormMigrationsCommand: CopyTypeormMigrationsCommand,
|
||||
protected readonly upgradeSearchVectorOnPersonEntityCommand: UpgradeSearchVectorOnPersonEntityCommand,
|
||||
protected readonly removeRelationForeignKeyFieldMetadataCommand: RemoveRelationForeignKeyFieldMetadataCommand,
|
||||
|
||||
// 0.54 Commands
|
||||
protected readonly fixStandardSelectFieldsPositionCommand: FixStandardSelectFieldsPositionCommand,
|
||||
protected readonly fixCreatedByDefaultValueCommand: FixCreatedByDefaultValueCommand,
|
||||
@ -179,41 +139,6 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
syncWorkspaceMetadataCommand,
|
||||
);
|
||||
|
||||
const commands_044: VersionCommands = {
|
||||
beforeSyncMetadata: [
|
||||
this.initializePermissionsCommand,
|
||||
this.updateViewAggregateOperationsCommand,
|
||||
],
|
||||
afterSyncMetadata: [],
|
||||
};
|
||||
|
||||
const commands_050: VersionCommands = {
|
||||
beforeSyncMetadata: [],
|
||||
afterSyncMetadata: [],
|
||||
};
|
||||
|
||||
const commands_051: VersionCommands = {
|
||||
beforeSyncMetadata: [this.upgradeCreatedByEnumCommand],
|
||||
afterSyncMetadata: [],
|
||||
};
|
||||
|
||||
const commands_052: VersionCommands = {
|
||||
beforeSyncMetadata: [
|
||||
this.upgradeDateAndDateTimeFieldsSettingsJsonCommand,
|
||||
this.migrateRelationsToFieldMetadataCommand,
|
||||
],
|
||||
afterSyncMetadata: [],
|
||||
};
|
||||
|
||||
const commands_053: VersionCommands = {
|
||||
beforeSyncMetadata: [this.removeRelationForeignKeyFieldMetadataCommand],
|
||||
afterSyncMetadata: [
|
||||
this.migrateWorkflowEventListenersToAutomatedTriggersCommand,
|
||||
this.backfillWorkflowNextStepIdsCommand,
|
||||
this.upgradeSearchVectorOnPersonEntityCommand,
|
||||
],
|
||||
};
|
||||
|
||||
const commands_054: VersionCommands = {
|
||||
beforeSyncMetadata: [
|
||||
this.fixStandardSelectFieldsPositionCommand,
|
||||
@ -227,11 +152,6 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
};
|
||||
|
||||
this.allCommands = {
|
||||
'0.44.0': commands_044,
|
||||
'0.50.0': commands_050,
|
||||
'0.51.0': commands_051,
|
||||
'0.52.0': commands_052,
|
||||
'0.53.0': commands_053,
|
||||
'0.54.0': commands_054,
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,33 +0,0 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
const tableName = 'billingSubscription';
|
||||
|
||||
export const seedBillingSubscriptions = async (
|
||||
dataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'workspaceId',
|
||||
'stripeCustomerId',
|
||||
'stripeSubscriptionId',
|
||||
'status',
|
||||
'metadata',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
workspaceId,
|
||||
stripeCustomerId: 'cus_default0',
|
||||
stripeSubscriptionId: 'sub_default0',
|
||||
status: 'active',
|
||||
metadata: {
|
||||
workspaceId,
|
||||
},
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
@ -1,16 +0,0 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
const tableName = 'featureFlag';
|
||||
|
||||
export const deleteFeatureFlags = async (
|
||||
dataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from(`${schemaName}.${tableName}`)
|
||||
.where(`"${tableName}"."workspaceId" = :workspaceId`, { workspaceId })
|
||||
.execute();
|
||||
};
|
||||
@ -1,19 +0,0 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { deleteFeatureFlags } from 'src/database/typeorm-seeds/core/demo/feature-flags';
|
||||
import { deleteUserWorkspaces } from 'src/database/typeorm-seeds/core/demo/user-workspaces';
|
||||
import { deleteUsersByWorkspace } from 'src/database/typeorm-seeds/core/demo/users';
|
||||
import { deleteWorkspaces } from 'src/database/typeorm-seeds/core/demo/workspaces';
|
||||
|
||||
export const deleteCoreSchema = async (
|
||||
workspaceDataSource: DataSource,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
const schemaName = 'core';
|
||||
|
||||
await deleteUserWorkspaces(workspaceDataSource, schemaName, workspaceId);
|
||||
await deleteUsersByWorkspace(workspaceDataSource, schemaName, workspaceId);
|
||||
await deleteFeatureFlags(workspaceDataSource, schemaName, workspaceId);
|
||||
// deleteWorkspaces should be last
|
||||
await deleteWorkspaces(workspaceDataSource, schemaName, workspaceId);
|
||||
};
|
||||
@ -1,56 +0,0 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { DEMO_SEED_USER_IDS } from 'src/database/typeorm-seeds/core/demo/users';
|
||||
|
||||
const tableName = 'userWorkspace';
|
||||
|
||||
export const DEV_SEED_USER_WORKSPACE_IDS = {
|
||||
NOAH: '20202020-9e3b-46d4-a556-88b9ddc2b534',
|
||||
HUGO: '20202020-3957-4908-9c36-2929a23f8457',
|
||||
TIM: '20202020-9e3b-46d4-a556-88b9ddc2b015',
|
||||
};
|
||||
|
||||
export const seedUserWorkspaces = async (
|
||||
dataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, ['id', 'userId', 'workspaceId'])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: DEV_SEED_USER_WORKSPACE_IDS.NOAH,
|
||||
userId: DEMO_SEED_USER_IDS.NOAH,
|
||||
workspaceId: workspaceId,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_USER_WORKSPACE_IDS.HUGO,
|
||||
userId: DEMO_SEED_USER_IDS.HUGO,
|
||||
workspaceId: workspaceId,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_USER_WORKSPACE_IDS.TIM,
|
||||
userId: DEMO_SEED_USER_IDS.TIM,
|
||||
workspaceId: workspaceId,
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
|
||||
export const deleteUserWorkspaces = async (
|
||||
dataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from(`${schemaName}.${tableName}`)
|
||||
.where(`"${tableName}"."workspaceId" = :workspaceId`, {
|
||||
workspaceId,
|
||||
})
|
||||
.execute();
|
||||
};
|
||||
@ -1,77 +0,0 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
// import { SeedWorkspaceId } from 'src/database/typeorm-seeds/core/workspaces';
|
||||
|
||||
const tableName = 'user';
|
||||
|
||||
export const DEMO_SEED_USER_IDS = {
|
||||
NOAH: '20202020-9e3b-46d4-a556-88b9ddc2b035',
|
||||
HUGO: '20202020-3957-4908-9c36-2929a23f8358',
|
||||
TIM: '20202020-9e3b-46d4-a556-88b9ddc2b034',
|
||||
};
|
||||
|
||||
export const seedUsers = async (dataSource: DataSource, schemaName: string) => {
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'id',
|
||||
'firstName',
|
||||
'lastName',
|
||||
'email',
|
||||
'passwordHash',
|
||||
'isEmailVerified',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: DEMO_SEED_USER_IDS.NOAH,
|
||||
firstName: 'Noah',
|
||||
lastName: 'A',
|
||||
email: 'noah@demo.dev',
|
||||
passwordHash:
|
||||
'$2b$10$3LwXjJRtLsfx4hLuuXhxt.3mWgismTiZFCZSG3z9kDrSfsrBl0fT6', // tim@apple.dev
|
||||
isEmailVerified: true,
|
||||
},
|
||||
{
|
||||
id: DEMO_SEED_USER_IDS.HUGO,
|
||||
firstName: 'Hugo',
|
||||
lastName: 'I',
|
||||
email: 'hugo@demo.dev',
|
||||
passwordHash:
|
||||
'$2b$10$3LwXjJRtLsfx4hLuuXhxt.3mWgismTiZFCZSG3z9kDrSfsrBl0fT6', // tim@apple.dev
|
||||
isEmailVerified: true,
|
||||
},
|
||||
{
|
||||
id: DEMO_SEED_USER_IDS.TIM,
|
||||
firstName: 'Tim',
|
||||
lastName: 'Apple',
|
||||
email: 'tim@apple.dev',
|
||||
passwordHash:
|
||||
'$2b$10$3LwXjJRtLsfx4hLuuXhxt.3mWgismTiZFCZSG3z9kDrSfsrBl0fT6', // tim@apple.dev
|
||||
isEmailVerified: true,
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
|
||||
export const deleteUsersByWorkspace = async (
|
||||
dataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
const user = await dataSource
|
||||
.createQueryBuilder(`${schemaName}.${tableName}`, 'user')
|
||||
.leftJoinAndSelect('user.workspaces', 'userWorkspace')
|
||||
.where(`userWorkspace."workspaceId" = :workspaceId`, {
|
||||
workspaceId,
|
||||
})
|
||||
.getMany();
|
||||
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from(`${schemaName}.${tableName}`)
|
||||
.where(`"${tableName}"."id" IN (:...ids)`, { ids: user.map((u) => u.id) })
|
||||
.execute();
|
||||
};
|
||||
@ -1,49 +0,0 @@
|
||||
import { WorkspaceActivationStatus } from 'twenty-shared/workspace';
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
const tableName = 'workspace';
|
||||
|
||||
export const seedWorkspaces = async (
|
||||
dataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'id',
|
||||
'displayName',
|
||||
'domainName',
|
||||
'inviteHash',
|
||||
'logo',
|
||||
'subdomain',
|
||||
'activationStatus',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: workspaceId,
|
||||
displayName: 'Demo',
|
||||
domainName: 'demo.dev',
|
||||
inviteHash: 'demo.dev-invite-hash',
|
||||
logo: 'https://twentyhq.github.io/placeholder-images/workspaces/apple-logo.png',
|
||||
subdomain: 'demo',
|
||||
activationStatus: WorkspaceActivationStatus.ACTIVE,
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
|
||||
export const deleteWorkspaces = async (
|
||||
dataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from(`${schemaName}.${tableName}`)
|
||||
.where(`${tableName}."id" = :id`, { id: workspaceId })
|
||||
.execute();
|
||||
};
|
||||
@ -1,63 +0,0 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
|
||||
const tableName = 'featureFlag';
|
||||
|
||||
export const seedFeatureFlags = async (
|
||||
dataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, ['key', 'workspaceId', 'value'])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
key: FeatureFlagKey.IS_AIRTABLE_INTEGRATION_ENABLED,
|
||||
workspaceId: workspaceId,
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKey.IS_POSTGRESQL_INTEGRATION_ENABLED,
|
||||
workspaceId: workspaceId,
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKey.IS_STRIPE_INTEGRATION_ENABLED,
|
||||
workspaceId: workspaceId,
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKey.IS_WORKFLOW_ENABLED,
|
||||
workspaceId: workspaceId,
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKey.IS_UNIQUE_INDEXES_ENABLED,
|
||||
workspaceId: workspaceId,
|
||||
value: false,
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKey.IS_AI_ENABLED,
|
||||
workspaceId: workspaceId,
|
||||
value: true,
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
|
||||
export const deleteFeatureFlags = async (
|
||||
dataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from(`${schemaName}.${tableName}`)
|
||||
.where(`"${tableName}"."workspaceId" = :workspaceId`, { workspaceId })
|
||||
.execute();
|
||||
};
|
||||
@ -1,42 +0,0 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { seedBillingSubscriptions } from 'src/database/typeorm-seeds/core/billing/billing-subscription';
|
||||
import { seedFeatureFlags } from 'src/database/typeorm-seeds/core/feature-flags';
|
||||
import { seedUserWorkspaces } from 'src/database/typeorm-seeds/core/user-workspaces';
|
||||
import { seedUsers } from 'src/database/typeorm-seeds/core/users';
|
||||
import { seedWorkspaces } from 'src/database/typeorm-seeds/core/workspaces';
|
||||
|
||||
type SeedCoreSchemaArgs = {
|
||||
dataSource: DataSource;
|
||||
workspaceId: string;
|
||||
appVersion: string | undefined;
|
||||
seedBilling?: boolean;
|
||||
seedFeatureFlags?: boolean;
|
||||
};
|
||||
|
||||
export const seedCoreSchema = async ({
|
||||
appVersion,
|
||||
dataSource,
|
||||
workspaceId,
|
||||
seedBilling = true,
|
||||
seedFeatureFlags: shouldSeedFeatureFlags = true,
|
||||
}: SeedCoreSchemaArgs) => {
|
||||
const schemaName = 'core';
|
||||
|
||||
await seedWorkspaces({
|
||||
dataSource,
|
||||
schemaName,
|
||||
workspaceId,
|
||||
appVersion,
|
||||
});
|
||||
await seedUsers(dataSource, schemaName);
|
||||
await seedUserWorkspaces(dataSource, schemaName, workspaceId);
|
||||
|
||||
if (shouldSeedFeatureFlags) {
|
||||
await seedFeatureFlags(dataSource, schemaName, workspaceId);
|
||||
}
|
||||
|
||||
if (seedBilling) {
|
||||
await seedBillingSubscriptions(dataSource, schemaName, workspaceId);
|
||||
}
|
||||
};
|
||||
@ -1,78 +0,0 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { DEV_SEED_USER_IDS } from 'src/database/typeorm-seeds/core/users';
|
||||
import {
|
||||
SEED_ACME_WORKSPACE_ID,
|
||||
SEED_APPLE_WORKSPACE_ID,
|
||||
} from 'src/database/typeorm-seeds/core/workspaces';
|
||||
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
|
||||
const tableName = 'userWorkspace';
|
||||
|
||||
export const DEV_SEED_USER_WORKSPACE_IDS = {
|
||||
TIM: '20202020-9e3b-46d4-a556-88b9ddc2b035',
|
||||
JONY: '20202020-3957-4908-9c36-2929a23f8353',
|
||||
PHIL: '20202020-7169-42cf-bc47-1cfef15264b1',
|
||||
TIM_ACME: '20202020-e10a-4c27-a90b-b08c57b02d44',
|
||||
};
|
||||
|
||||
export const seedUserWorkspaces = async (
|
||||
dataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
let userWorkspaces: Pick<UserWorkspace, 'id' | 'userId' | 'workspaceId'>[] =
|
||||
[];
|
||||
|
||||
if (workspaceId === SEED_APPLE_WORKSPACE_ID) {
|
||||
userWorkspaces = [
|
||||
{
|
||||
id: DEV_SEED_USER_WORKSPACE_IDS.TIM,
|
||||
userId: DEV_SEED_USER_IDS.TIM,
|
||||
workspaceId,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_USER_WORKSPACE_IDS.JONY,
|
||||
userId: DEV_SEED_USER_IDS.JONY,
|
||||
workspaceId,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_USER_WORKSPACE_IDS.PHIL,
|
||||
userId: DEV_SEED_USER_IDS.PHIL,
|
||||
workspaceId,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
if (workspaceId === SEED_ACME_WORKSPACE_ID) {
|
||||
userWorkspaces = [
|
||||
{
|
||||
id: DEV_SEED_USER_WORKSPACE_IDS.TIM_ACME,
|
||||
userId: DEV_SEED_USER_IDS.TIM,
|
||||
workspaceId,
|
||||
},
|
||||
];
|
||||
}
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, ['id', 'userId', 'workspaceId'])
|
||||
.orIgnore()
|
||||
.values(userWorkspaces)
|
||||
.execute();
|
||||
};
|
||||
|
||||
export const deleteUserWorkspaces = async (
|
||||
dataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from(`${schemaName}.${tableName}`)
|
||||
.where(`"${tableName}"."workspaceId" = :workspaceId`, {
|
||||
workspaceId,
|
||||
})
|
||||
.execute();
|
||||
};
|
||||
@ -1,62 +0,0 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
const tableName = 'user';
|
||||
|
||||
export const DEV_SEED_USER_IDS = {
|
||||
TIM: '20202020-9e3b-46d4-a556-88b9ddc2b034',
|
||||
JONY: '20202020-3957-4908-9c36-2929a23f8357',
|
||||
PHIL: '20202020-7169-42cf-bc47-1cfef15264b8',
|
||||
};
|
||||
|
||||
export const seedUsers = async (dataSource: DataSource, schemaName: string) => {
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'id',
|
||||
'firstName',
|
||||
'lastName',
|
||||
'email',
|
||||
'passwordHash',
|
||||
'canImpersonate',
|
||||
'canAccessFullAdminPanel',
|
||||
'isEmailVerified',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: DEV_SEED_USER_IDS.TIM,
|
||||
firstName: 'Tim',
|
||||
lastName: 'Apple',
|
||||
email: 'tim@apple.dev',
|
||||
passwordHash:
|
||||
'$2b$10$3LwXjJRtLsfx4hLuuXhxt.3mWgismTiZFCZSG3z9kDrSfsrBl0fT6', // tim@apple.dev
|
||||
canImpersonate: true,
|
||||
canAccessFullAdminPanel: true,
|
||||
isEmailVerified: true,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_USER_IDS.JONY,
|
||||
firstName: 'Jony',
|
||||
lastName: 'Ive',
|
||||
email: 'jony.ive@apple.dev',
|
||||
passwordHash:
|
||||
'$2b$10$3LwXjJRtLsfx4hLuuXhxt.3mWgismTiZFCZSG3z9kDrSfsrBl0fT6', // tim@apple.dev
|
||||
canImpersonate: true,
|
||||
canAccessFullAdminPanel: true,
|
||||
isEmailVerified: true,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_USER_IDS.PHIL,
|
||||
firstName: 'Phil',
|
||||
lastName: 'Schiler',
|
||||
email: 'phil.schiler@apple.dev',
|
||||
passwordHash:
|
||||
'$2b$10$3LwXjJRtLsfx4hLuuXhxt.3mWgismTiZFCZSG3z9kDrSfsrBl0fT6', // tim@apple.dev
|
||||
canImpersonate: true,
|
||||
canAccessFullAdminPanel: true,
|
||||
isEmailVerified: true,
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
@ -1,83 +0,0 @@
|
||||
import { WorkspaceActivationStatus } from 'twenty-shared/workspace';
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { extractVersionMajorMinorPatch } from 'src/utils/version/extract-version-major-minor-patch';
|
||||
|
||||
const tableName = 'workspace';
|
||||
|
||||
export const SEED_APPLE_WORKSPACE_ID = '20202020-1c25-4d02-bf25-6aeccf7ea419';
|
||||
export const SEED_ACME_WORKSPACE_ID = '3b8e6458-5fc1-4e63-8563-008ccddaa6db';
|
||||
|
||||
export type SeedWorkspaceArgs = {
|
||||
dataSource: DataSource;
|
||||
schemaName: string;
|
||||
workspaceId: string;
|
||||
appVersion: string | undefined;
|
||||
};
|
||||
|
||||
const workspaceSeederFields = [
|
||||
'id',
|
||||
'displayName',
|
||||
'subdomain',
|
||||
'inviteHash',
|
||||
'logo',
|
||||
'activationStatus',
|
||||
'version',
|
||||
] as const satisfies (keyof Workspace)[];
|
||||
|
||||
type WorkspaceSeederFields = Pick<
|
||||
Workspace,
|
||||
(typeof workspaceSeederFields)[number]
|
||||
>;
|
||||
|
||||
export const seedWorkspaces = async ({
|
||||
schemaName,
|
||||
dataSource,
|
||||
workspaceId,
|
||||
appVersion,
|
||||
}: SeedWorkspaceArgs) => {
|
||||
const version = extractVersionMajorMinorPatch(appVersion);
|
||||
|
||||
const workspaces: Record<string, WorkspaceSeederFields> = {
|
||||
[SEED_APPLE_WORKSPACE_ID]: {
|
||||
id: SEED_APPLE_WORKSPACE_ID,
|
||||
displayName: 'Apple',
|
||||
subdomain: 'apple',
|
||||
inviteHash: 'apple.dev-invite-hash',
|
||||
logo: 'https://twentyhq.github.io/placeholder-images/workspaces/apple-logo.png',
|
||||
activationStatus: WorkspaceActivationStatus.PENDING_CREATION, // will be set to active after default role creation
|
||||
version: version,
|
||||
},
|
||||
[SEED_ACME_WORKSPACE_ID]: {
|
||||
id: SEED_ACME_WORKSPACE_ID,
|
||||
displayName: 'Acme',
|
||||
subdomain: 'acme',
|
||||
inviteHash: 'acme.dev-invite-hash',
|
||||
logo: 'https://logos-world.net/wp-content/uploads/2022/05/Acme-Logo-700x394.png',
|
||||
activationStatus: WorkspaceActivationStatus.PENDING_CREATION, // will be set to active after default role creation
|
||||
version: version,
|
||||
},
|
||||
};
|
||||
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, workspaceSeederFields)
|
||||
.orIgnore()
|
||||
.values(workspaces[workspaceId])
|
||||
.execute();
|
||||
};
|
||||
|
||||
export const deleteWorkspaces = async (
|
||||
dataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from(`${schemaName}.${tableName}`)
|
||||
.where(`${tableName}."id" = :id`, { id: workspaceId })
|
||||
.execute();
|
||||
};
|
||||
@ -1,190 +0,0 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
|
||||
export const getDevSeedCompanyCustomFields = (
|
||||
objectMetadataId: string,
|
||||
workspaceId: string,
|
||||
): CreateFieldInput[] => {
|
||||
return [
|
||||
{
|
||||
workspaceId,
|
||||
type: FieldMetadataType.TEXT,
|
||||
name: 'tagline',
|
||||
label: 'Tagline',
|
||||
description: "Company's Tagline",
|
||||
icon: 'IconAdCircle',
|
||||
isActive: true,
|
||||
isNullable: false,
|
||||
isUnique: false,
|
||||
defaultValue: "''",
|
||||
objectMetadataId,
|
||||
},
|
||||
{
|
||||
workspaceId,
|
||||
type: FieldMetadataType.LINKS,
|
||||
name: 'introVideo',
|
||||
label: 'Intro Video',
|
||||
description: "Company's Intro Video",
|
||||
icon: 'IconVideo',
|
||||
isActive: true,
|
||||
isNullable: true,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
},
|
||||
{
|
||||
workspaceId,
|
||||
type: FieldMetadataType.MULTI_SELECT,
|
||||
name: 'workPolicy',
|
||||
label: 'Work Policy',
|
||||
description: "Company's Work Policy",
|
||||
icon: 'IconHome',
|
||||
isActive: true,
|
||||
isNullable: true,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
options: [
|
||||
{
|
||||
color: 'green',
|
||||
label: 'On-Site',
|
||||
position: 0,
|
||||
value: 'ON_SITE',
|
||||
},
|
||||
{
|
||||
color: 'turquoise',
|
||||
label: 'Hybrid',
|
||||
position: 1,
|
||||
value: 'HYBRID',
|
||||
},
|
||||
{
|
||||
color: 'sky',
|
||||
label: 'Remote Work',
|
||||
position: 2,
|
||||
value: 'REMOTE_WORK',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
workspaceId,
|
||||
type: FieldMetadataType.BOOLEAN,
|
||||
name: 'visaSponsorship',
|
||||
label: 'Visa Sponsorship',
|
||||
description: "Company's Visa Sponsorship Policy",
|
||||
icon: 'IconBrandVisa',
|
||||
isActive: true,
|
||||
isNullable: true,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
defaultValue: false,
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
export const getDevSeedPeopleCustomFields = (
|
||||
objectMetadataId: string,
|
||||
workspaceId: string,
|
||||
): CreateFieldInput[] => {
|
||||
return [
|
||||
{
|
||||
workspaceId,
|
||||
type: FieldMetadataType.TEXT,
|
||||
name: 'intro',
|
||||
label: 'Intro',
|
||||
description: "Contact's Intro",
|
||||
icon: 'IconNote',
|
||||
isActive: true,
|
||||
isNullable: true,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
},
|
||||
{
|
||||
workspaceId,
|
||||
type: FieldMetadataType.PHONES,
|
||||
name: 'whatsapp',
|
||||
label: 'Whatsapp',
|
||||
description: "Contact's Whatsapp Number",
|
||||
icon: 'IconBrandWhatsapp',
|
||||
isActive: true,
|
||||
isNullable: false,
|
||||
isUnique: false,
|
||||
defaultValue: {
|
||||
primaryPhoneNumber: "''",
|
||||
primaryPhoneCountryCode: "'FR'",
|
||||
primaryPhoneCallingCode: "'+33'",
|
||||
additionalPhones: null,
|
||||
},
|
||||
objectMetadataId,
|
||||
},
|
||||
{
|
||||
workspaceId,
|
||||
type: FieldMetadataType.MULTI_SELECT,
|
||||
name: 'workPreference',
|
||||
label: 'Work Preference',
|
||||
description: "Person's Work Preference",
|
||||
icon: 'IconHome',
|
||||
isActive: true,
|
||||
isNullable: true,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
options: [
|
||||
{
|
||||
color: 'green',
|
||||
label: 'On-Site',
|
||||
position: 0,
|
||||
value: 'ON_SITE',
|
||||
},
|
||||
{
|
||||
color: 'turquoise',
|
||||
label: 'Hybrid',
|
||||
position: 1,
|
||||
value: 'HYBRID',
|
||||
},
|
||||
{
|
||||
color: 'sky',
|
||||
label: 'Remote Work',
|
||||
position: 2,
|
||||
value: 'REMOTE_WORK',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
workspaceId,
|
||||
type: FieldMetadataType.RATING,
|
||||
name: 'performanceRating',
|
||||
label: 'Performance Rating',
|
||||
description: "Person's Performance Rating",
|
||||
icon: 'IconStars',
|
||||
isActive: true,
|
||||
isNullable: true,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
options: [
|
||||
{
|
||||
label: '1',
|
||||
value: 'RATING_1',
|
||||
position: 0,
|
||||
},
|
||||
{
|
||||
label: '2',
|
||||
value: 'RATING_2',
|
||||
position: 1,
|
||||
},
|
||||
{
|
||||
label: '3',
|
||||
value: 'RATING_3',
|
||||
position: 2,
|
||||
},
|
||||
{
|
||||
label: '4',
|
||||
value: 'RATING_4',
|
||||
position: 3,
|
||||
},
|
||||
{
|
||||
label: '5',
|
||||
value: 'RATING_5',
|
||||
position: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
};
|
||||
@ -1,20 +0,0 @@
|
||||
import { CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input';
|
||||
|
||||
export const getDevSeedCustomObjects = (
|
||||
workspaceId: string,
|
||||
dataSourceId: string,
|
||||
): CreateObjectInput[] => {
|
||||
return [
|
||||
{
|
||||
workspaceId,
|
||||
dataSourceId,
|
||||
labelPlural: 'Rockets',
|
||||
labelSingular: 'Rocket',
|
||||
namePlural: 'rockets',
|
||||
nameSingular: 'rocket',
|
||||
description: 'A rocket',
|
||||
icon: 'IconRocket',
|
||||
isRemote: false,
|
||||
},
|
||||
];
|
||||
};
|
||||
@ -1,28 +0,0 @@
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
|
||||
const tableName = 'apiKey';
|
||||
|
||||
const API_KEY_ID = '20202020-f401-4d8a-a731-64d007c27bad';
|
||||
|
||||
export const seedApiKey = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, ['id', 'name', 'expiresAt'])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: API_KEY_ID,
|
||||
name: 'My api key',
|
||||
expiresAt: new Date(
|
||||
new Date().getTime() + 1000 * 60 * 60 * 24 * 365 * 100, // In 100 years
|
||||
),
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
@ -1,32 +0,0 @@
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
|
||||
const tableName = 'calendarChannelEventAssociation';
|
||||
|
||||
export const seedCalendarChannelEventAssociations = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'id',
|
||||
'calendarChannelId',
|
||||
'calendarEventId',
|
||||
'eventExternalId',
|
||||
'recurringEventExternalId',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: 'e1ab9e1b-df6e-438e-a788-11c96dcecdd3',
|
||||
calendarChannelId: '59efdefe-a40f-4faf-bb9f-c6f9945b8203',
|
||||
calendarEventId: '86083141-1c0e-494c-a1b6-85b1c6fefaa5',
|
||||
eventExternalId: 'exampleExternalId',
|
||||
recurringEventExternalId: 'exampleRecurringExternalId',
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
@ -1,36 +0,0 @@
|
||||
import { DEV_SEED_CONNECTED_ACCOUNT_IDS } from 'src/database/typeorm-seeds/workspace/connected-account';
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
import { CalendarChannelVisibility } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
|
||||
|
||||
const tableName = 'calendarChannel';
|
||||
|
||||
export const seedCalendarChannels = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'id',
|
||||
'connectedAccountId',
|
||||
'handle',
|
||||
'visibility',
|
||||
'isContactAutoCreationEnabled',
|
||||
'isSyncEnabled',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: '59efdefe-a40f-4faf-bb9f-c6f9945b8203',
|
||||
connectedAccountId: DEV_SEED_CONNECTED_ACCOUNT_IDS.TIM,
|
||||
handle: 'tim@apple.com',
|
||||
visibility: CalendarChannelVisibility.SHARE_EVERYTHING,
|
||||
isContactAutoCreationEnabled: true,
|
||||
isSyncEnabled: true,
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
@ -1,51 +0,0 @@
|
||||
import { DEV_SEED_PERSON_IDS } from 'src/database/typeorm-seeds/workspace/seedPeople';
|
||||
import { DEV_SEED_WORKSPACE_MEMBER_IDS } from 'src/database/typeorm-seeds/workspace/workspace-members';
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
import { CalendarEventParticipantResponseStatus } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity';
|
||||
|
||||
const tableName = 'calendarEventParticipant';
|
||||
|
||||
export const seedCalendarEventParticipants = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'id',
|
||||
'calendarEventId',
|
||||
'handle',
|
||||
'displayName',
|
||||
'isOrganizer',
|
||||
'responseStatus',
|
||||
'personId',
|
||||
'workspaceMemberId',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: 'da8f47c3-8055-49ad-b7e4-9c9d5bbc1ecc',
|
||||
calendarEventId: '86083141-1c0e-494c-a1b6-85b1c6fefaa5',
|
||||
handle: 'christoph.calisto@linkedin.com',
|
||||
displayName: 'Christoph Calisto',
|
||||
isOrganizer: true,
|
||||
responseStatus: CalendarEventParticipantResponseStatus.ACCEPTED,
|
||||
personId: DEV_SEED_PERSON_IDS.CHRISTOPH,
|
||||
workspaceMemberId: null,
|
||||
},
|
||||
{
|
||||
id: 'e1ab9e1b-df6e-438e-a788-11c96dcecdd3',
|
||||
calendarEventId: '86083141-1c0e-494c-a1b6-85b1c6fefaa5',
|
||||
handle: 'tim@apple.com',
|
||||
displayName: 'Tim Apple',
|
||||
isOrganizer: false,
|
||||
responseStatus: CalendarEventParticipantResponseStatus.ACCEPTED,
|
||||
personId: null,
|
||||
workspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
@ -1,54 +0,0 @@
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
|
||||
const tableName = 'calendarEvent';
|
||||
|
||||
export const DEV_SEED_CALENDAR_EVENT_IDS = {
|
||||
CALENDAR_EVENT_1: '86083141-1c0e-494c-a1b6-85b1c6fefaa5',
|
||||
};
|
||||
|
||||
export const seedCalendarEvents = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'id',
|
||||
'title',
|
||||
'isCanceled',
|
||||
'isFullDay',
|
||||
'startsAt',
|
||||
'endsAt',
|
||||
'externalCreatedAt',
|
||||
'externalUpdatedAt',
|
||||
'description',
|
||||
'location',
|
||||
'iCalUID',
|
||||
'conferenceSolution',
|
||||
'conferenceLinkPrimaryLinkLabel',
|
||||
'conferenceLinkPrimaryLinkUrl',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: DEV_SEED_CALENDAR_EVENT_IDS.CALENDAR_EVENT_1,
|
||||
title: 'Meeting with Christoph',
|
||||
isCanceled: false,
|
||||
isFullDay: false,
|
||||
startsAt: new Date(new Date().setHours(10, 0)).toISOString(),
|
||||
endsAt: new Date(new Date().setHours(11, 0)).toISOString(),
|
||||
externalCreatedAt: new Date().toISOString(),
|
||||
externalUpdatedAt: new Date().toISOString(),
|
||||
description: 'Discuss project progress',
|
||||
location: 'Seattle',
|
||||
iCalUID: 'event1@calendar.com',
|
||||
conferenceSolution: 'Zoom',
|
||||
conferenceLinkPrimaryLinkLabel: 'https://zoom.us/j/1234567890',
|
||||
conferenceLinkPrimaryLinkUrl: 'https://zoom.us/j/1234567890',
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
@ -1,273 +0,0 @@
|
||||
import { DEV_SEED_WORKSPACE_MEMBER_IDS } from 'src/database/typeorm-seeds/workspace/workspace-members';
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
|
||||
const tableName = 'company';
|
||||
|
||||
export const DEV_SEED_COMPANY_IDS = {
|
||||
LINKEDIN: '20202020-3ec3-4fe3-8997-b76aa0bfa408',
|
||||
FACEBOOK: '20202020-5d81-46d6-bf83-f7fd33ea6102',
|
||||
ANTHROPIC: '20202020-0713-40a5-8216-82802401d33e',
|
||||
MICROSOFT: '20202020-ed89-413a-b31a-962986e67bb4',
|
||||
AIRBNB: '20202020-171e-4bcc-9cf7-43448d6fb278',
|
||||
GOOGLE: '20202020-c21e-4ec2-873b-de4264d89025',
|
||||
NETFLIX: '20202020-707e-44dc-a1d2-30030bf1a944',
|
||||
LIBEO: '20202020-3f74-492d-a101-2a70f50a1645',
|
||||
CLAAP: '20202020-cfbf-4156-a790-e39854dcd4eb',
|
||||
HASURA: '20202020-f86b-419f-b794-02319abe8637',
|
||||
WEWORK: '20202020-5518-4553-9433-42d8eb82834b',
|
||||
SAMSUNG: '20202020-f79e-40dd-bd06-c36e6abb4678',
|
||||
ALGOLIA: '20202020-1455-4c57-afaf-dd5dc086361d',
|
||||
};
|
||||
|
||||
export const seedCompanies = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'id',
|
||||
'name',
|
||||
'domainNamePrimaryLinkUrl',
|
||||
'addressAddressStreet1',
|
||||
'addressAddressStreet2',
|
||||
'addressAddressCity',
|
||||
'addressAddressState',
|
||||
'addressAddressPostcode',
|
||||
'addressAddressCountry',
|
||||
'position',
|
||||
'tagline',
|
||||
'workPolicy',
|
||||
'createdBySource',
|
||||
'createdByWorkspaceMemberId',
|
||||
'createdByName',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: DEV_SEED_COMPANY_IDS.LINKEDIN,
|
||||
name: 'Linkedin',
|
||||
domainNamePrimaryLinkUrl: 'https://linkedin.com',
|
||||
addressAddressStreet1: 'Eutaw Street',
|
||||
addressAddressStreet2: null,
|
||||
addressAddressCity: 'Dublin',
|
||||
addressAddressState: null,
|
||||
addressAddressPostcode: null,
|
||||
addressAddressCountry: 'Ireland',
|
||||
position: 1,
|
||||
tagline: "Linkedin's tagline",
|
||||
workPolicy: ['ON_SITE'],
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_COMPANY_IDS.FACEBOOK,
|
||||
name: 'Facebook',
|
||||
domainNamePrimaryLinkUrl: 'https://facebook.com',
|
||||
addressAddressStreet1: null,
|
||||
addressAddressStreet2: null,
|
||||
addressAddressCity: null,
|
||||
addressAddressState: null,
|
||||
addressAddressPostcode: null,
|
||||
addressAddressCountry: null,
|
||||
position: 2,
|
||||
tagline: "Facebook's tagline",
|
||||
workPolicy: ['REMOTE_WORK'],
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_COMPANY_IDS.ANTHROPIC,
|
||||
name: 'Anthropic',
|
||||
domainNamePrimaryLinkUrl: 'https://anthropic.com',
|
||||
addressAddressStreet1: '548 Market Street',
|
||||
addressAddressStreet2: null,
|
||||
addressAddressCity: 'San Francisco',
|
||||
addressAddressState: null,
|
||||
addressAddressPostcode: '94104',
|
||||
addressAddressCountry: 'United States',
|
||||
position: 3,
|
||||
tagline: "Anthropic's tagline",
|
||||
workPolicy: ['ON_SITE'],
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_COMPANY_IDS.MICROSOFT,
|
||||
name: 'Microsoft',
|
||||
domainNamePrimaryLinkUrl: 'https://microsoft.com',
|
||||
addressAddressStreet1: null,
|
||||
addressAddressStreet2: null,
|
||||
addressAddressCity: null,
|
||||
addressAddressState: null,
|
||||
addressAddressPostcode: null,
|
||||
addressAddressCountry: null,
|
||||
position: 4,
|
||||
tagline: "Microsoft's tagline",
|
||||
workPolicy: ['ON_SITE', 'HYBRID'],
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_COMPANY_IDS.AIRBNB,
|
||||
name: 'Airbnb',
|
||||
domainNamePrimaryLinkUrl: 'https://airbnb.com',
|
||||
addressAddressStreet1: '888 Brannan St',
|
||||
addressAddressStreet2: null,
|
||||
addressAddressCity: 'San Francisco',
|
||||
addressAddressState: 'CA',
|
||||
addressAddressPostcode: '94103',
|
||||
addressAddressCountry: 'United States',
|
||||
position: 5,
|
||||
tagline: "Airbnb's tagline",
|
||||
workPolicy: ['ON_SITE'],
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_COMPANY_IDS.GOOGLE,
|
||||
name: 'Google',
|
||||
domainNamePrimaryLinkUrl: 'https://google.com',
|
||||
addressAddressStreet1: '760 Market St',
|
||||
addressAddressStreet2: 'Floor 10',
|
||||
addressAddressCity: 'San Francisco',
|
||||
addressAddressState: null,
|
||||
addressAddressPostcode: '94102',
|
||||
addressAddressCountry: 'United States',
|
||||
position: 6,
|
||||
tagline: "Google's tagline",
|
||||
workPolicy: ['HYBRID', 'REMOTE_WORK'],
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_COMPANY_IDS.NETFLIX,
|
||||
name: 'Netflix',
|
||||
domainNamePrimaryLinkUrl: 'https://netflix.com',
|
||||
addressAddressStreet1: '2300 Harrison St',
|
||||
addressAddressStreet2: null,
|
||||
addressAddressCity: 'San Francisco',
|
||||
addressAddressState: 'CA',
|
||||
addressAddressPostcode: '94110',
|
||||
addressAddressCountry: 'United States',
|
||||
position: 7,
|
||||
tagline: "Netflix's tagline",
|
||||
workPolicy: ['REMOTE_WORK'],
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_COMPANY_IDS.LIBEO,
|
||||
name: 'Libeo',
|
||||
domainNamePrimaryLinkUrl: 'https://libeo.io',
|
||||
addressAddressStreet1: null,
|
||||
addressAddressStreet2: null,
|
||||
addressAddressCity: null,
|
||||
addressAddressState: null,
|
||||
addressAddressPostcode: null,
|
||||
addressAddressCountry: null,
|
||||
position: 8,
|
||||
tagline: "Libeo's tagline",
|
||||
workPolicy: ['HYBRID'],
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_COMPANY_IDS.CLAAP,
|
||||
name: 'Claap',
|
||||
domainNamePrimaryLinkUrl: 'https://claap.io',
|
||||
addressAddressStreet1: null,
|
||||
addressAddressStreet2: null,
|
||||
addressAddressCity: null,
|
||||
addressAddressState: null,
|
||||
addressAddressPostcode: null,
|
||||
addressAddressCountry: null,
|
||||
position: 9,
|
||||
tagline: "Claap's tagline",
|
||||
workPolicy: ['ON_SITE', 'REMOTE_WORK'],
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_COMPANY_IDS.HASURA,
|
||||
name: 'Hasura',
|
||||
domainNamePrimaryLinkUrl: 'https://hasura.io',
|
||||
addressAddressStreet1: null,
|
||||
addressAddressStreet2: null,
|
||||
addressAddressCity: null,
|
||||
addressAddressState: null,
|
||||
addressAddressPostcode: null,
|
||||
addressAddressCountry: null,
|
||||
position: 10,
|
||||
tagline: "Hasura's tagline",
|
||||
workPolicy: ['HYBRID'],
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_COMPANY_IDS.WEWORK,
|
||||
name: 'Wework',
|
||||
domainNamePrimaryLinkUrl: 'https://wework.com',
|
||||
addressAddressStreet1: null,
|
||||
addressAddressStreet2: null,
|
||||
addressAddressCity: null,
|
||||
addressAddressState: null,
|
||||
addressAddressPostcode: null,
|
||||
addressAddressCountry: null,
|
||||
position: 11,
|
||||
tagline: "Wework's tagline",
|
||||
workPolicy: ['ON_SITE'],
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_COMPANY_IDS.SAMSUNG,
|
||||
name: 'Samsung',
|
||||
domainNamePrimaryLinkUrl: 'https://samsung.com',
|
||||
addressAddressStreet1: null,
|
||||
addressAddressStreet2: null,
|
||||
addressAddressCity: null,
|
||||
addressAddressState: null,
|
||||
addressAddressPostcode: null,
|
||||
addressAddressCountry: null,
|
||||
position: 12,
|
||||
tagline: "Samsung's tagline",
|
||||
workPolicy: ['HYBRID'],
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_COMPANY_IDS.ALGOLIA,
|
||||
name: 'Algolia',
|
||||
domainNamePrimaryLinkUrl: 'https://algolia.com',
|
||||
addressAddressStreet1: null,
|
||||
addressAddressStreet2: null,
|
||||
addressAddressCity: null,
|
||||
addressAddressState: null,
|
||||
addressAddressPostcode: null,
|
||||
addressAddressCountry: null,
|
||||
position: 13,
|
||||
tagline: "Algolia's tagline",
|
||||
workPolicy: ['ON_SITE'],
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
@ -1,73 +0,0 @@
|
||||
import { DEV_SEED_WORKSPACE_MEMBER_IDS } from 'src/database/typeorm-seeds/workspace/workspace-members';
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
|
||||
const tableName = 'connectedAccount';
|
||||
|
||||
export const DEV_SEED_CONNECTED_ACCOUNT_IDS = {
|
||||
TIM: '20202020-9ac0-4390-9a1a-ab4d2c4e1bb7',
|
||||
JONY: '20202020-0cc8-4d60-a3a4-803245698908',
|
||||
PHIL: '20202020-cafc-4323-908d-e5b42ad69fdf',
|
||||
};
|
||||
|
||||
export const seedConnectedAccount = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'id',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
'deletedAt',
|
||||
'lastSyncHistoryId',
|
||||
'accountOwnerId',
|
||||
'refreshToken',
|
||||
'accessToken',
|
||||
'provider',
|
||||
'handle',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: DEV_SEED_CONNECTED_ACCOUNT_IDS.TIM,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
lastSyncHistoryId: 'exampleLastSyncHistory',
|
||||
accountOwnerId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
refreshToken: 'exampleRefreshToken',
|
||||
accessToken: 'exampleAccessToken',
|
||||
provider: 'google',
|
||||
handle: 'tim@apple.dev',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_CONNECTED_ACCOUNT_IDS.JONY,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
lastSyncHistoryId: 'exampleLastSyncHistory',
|
||||
accountOwnerId: DEV_SEED_WORKSPACE_MEMBER_IDS.JONY,
|
||||
refreshToken: 'exampleRefreshToken',
|
||||
accessToken: 'exampleAccessToken',
|
||||
provider: 'google',
|
||||
handle: 'jony.ive@apple.dev',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_CONNECTED_ACCOUNT_IDS.PHIL,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
lastSyncHistoryId: 'exampleLastSyncHistory',
|
||||
accountOwnerId: DEV_SEED_WORKSPACE_MEMBER_IDS.PHIL,
|
||||
refreshToken: 'exampleRefreshToken',
|
||||
accessToken: 'exampleAccessToken',
|
||||
provider: 'google',
|
||||
handle: 'phil.schiler@apple.dev',
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
@ -1,26 +0,0 @@
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
|
||||
const tableName = 'favorite';
|
||||
|
||||
export const seedWorkspaceFavorites = async (
|
||||
viewIds: string[],
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, ['id', 'viewId', 'position'])
|
||||
.values(
|
||||
viewIds.map((viewId, index) => ({
|
||||
id: v4(),
|
||||
viewId,
|
||||
position: index,
|
||||
})),
|
||||
)
|
||||
.execute();
|
||||
};
|
||||
@ -1,71 +0,0 @@
|
||||
import { DEV_SEED_MESSAGE_CHANNEL_IDS } from 'src/database/typeorm-seeds/workspace/message-channels';
|
||||
import { DEV_SEED_MESSAGE_IDS } from 'src/database/typeorm-seeds/workspace/messages';
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
import { MessageDirection } from 'src/modules/messaging/common/enums/message-direction.enum';
|
||||
|
||||
const tableName = 'messageChannelMessageAssociation';
|
||||
|
||||
export const DEV_SEED_MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_IDS = {
|
||||
MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_1: '20202020-cc69-44ef-a82c-600c0dbf39ba',
|
||||
MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_2: '20202020-d80e-4a13-b10b-72ba09082668',
|
||||
MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_3: '20202020-e6ec-4c8a-b431-0901eaf395a9',
|
||||
};
|
||||
|
||||
export const seedMessageChannelMessageAssociation = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'id',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
'deletedAt',
|
||||
'messageThreadExternalId',
|
||||
'messageExternalId',
|
||||
'messageId',
|
||||
'messageChannelId',
|
||||
'direction',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_IDS.MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_1,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
messageThreadExternalId: null,
|
||||
messageExternalId: null,
|
||||
messageId: DEV_SEED_MESSAGE_IDS.MESSAGE_1,
|
||||
messageChannelId: DEV_SEED_MESSAGE_CHANNEL_IDS.TIM,
|
||||
direction: MessageDirection.OUTGOING,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_IDS.MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_2,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
messageThreadExternalId: null,
|
||||
messageExternalId: null,
|
||||
messageId: DEV_SEED_MESSAGE_IDS.MESSAGE_2,
|
||||
messageChannelId: DEV_SEED_MESSAGE_CHANNEL_IDS.TIM,
|
||||
direction: MessageDirection.OUTGOING,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_IDS.MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_3,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
messageThreadExternalId: null,
|
||||
messageExternalId: null,
|
||||
messageId: DEV_SEED_MESSAGE_IDS.MESSAGE_3,
|
||||
messageChannelId: DEV_SEED_MESSAGE_CHANNEL_IDS.TIM,
|
||||
direction: MessageDirection.INCOMING,
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
@ -1,81 +0,0 @@
|
||||
import { DEV_SEED_CONNECTED_ACCOUNT_IDS } from 'src/database/typeorm-seeds/workspace/connected-account';
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
import {
|
||||
MessageChannelSyncStage,
|
||||
MessageChannelVisibility,
|
||||
} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||
|
||||
const tableName = 'messageChannel';
|
||||
|
||||
export const DEV_SEED_MESSAGE_CHANNEL_IDS = {
|
||||
TIM: '20202020-9b80-4c2c-a597-383db48de1d6',
|
||||
JONY: '20202020-5ffe-4b32-814a-983d5e4911cd',
|
||||
PHIL: '20202020-e2f1-49b5-85d2-5d3a3386990c',
|
||||
};
|
||||
|
||||
export const seedMessageChannel = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'id',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
'deletedAt',
|
||||
'isContactAutoCreationEnabled',
|
||||
'type',
|
||||
'connectedAccountId',
|
||||
'handle',
|
||||
'isSyncEnabled',
|
||||
'visibility',
|
||||
'syncStage',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_CHANNEL_IDS.TIM,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
isContactAutoCreationEnabled: true,
|
||||
type: 'email',
|
||||
connectedAccountId: DEV_SEED_CONNECTED_ACCOUNT_IDS.TIM,
|
||||
handle: 'tim@apple.dev',
|
||||
isSyncEnabled: false,
|
||||
visibility: MessageChannelVisibility.SHARE_EVERYTHING,
|
||||
syncStage: MessageChannelSyncStage.FULL_MESSAGE_LIST_FETCH_PENDING,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_CHANNEL_IDS.JONY,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
isContactAutoCreationEnabled: true,
|
||||
type: 'email',
|
||||
connectedAccountId: DEV_SEED_CONNECTED_ACCOUNT_IDS.JONY,
|
||||
handle: 'jony.ive@apple.dev',
|
||||
isSyncEnabled: false,
|
||||
visibility: MessageChannelVisibility.SHARE_EVERYTHING,
|
||||
syncStage: MessageChannelSyncStage.FULL_MESSAGE_LIST_FETCH_PENDING,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_CHANNEL_IDS.PHIL,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
isContactAutoCreationEnabled: true,
|
||||
type: 'email',
|
||||
connectedAccountId: DEV_SEED_CONNECTED_ACCOUNT_IDS.PHIL,
|
||||
handle: 'phil.schiler@apple.dev',
|
||||
isSyncEnabled: false,
|
||||
visibility: MessageChannelVisibility.SHARE_EVERYTHING,
|
||||
syncStage: MessageChannelSyncStage.FULL_MESSAGE_LIST_FETCH_PENDING,
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
@ -1,114 +0,0 @@
|
||||
import { DEV_SEED_MESSAGE_IDS } from 'src/database/typeorm-seeds/workspace/messages';
|
||||
import { DEV_SEED_PERSON_IDS } from 'src/database/typeorm-seeds/workspace/seedPeople';
|
||||
import { DEV_SEED_WORKSPACE_MEMBER_IDS } from 'src/database/typeorm-seeds/workspace/workspace-members';
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
|
||||
const tableName = 'messageParticipant';
|
||||
|
||||
export const DEV_SEED_MESSAGE_PARTICIPANT_IDS = {
|
||||
MESSAGE_PARTICIPANT_1: '20202020-0f2a-49d8-8aa2-ec8786153a0b',
|
||||
MESSAGE_PARTICIPANT_2: '20202020-4e83-41ec-93e2-fd70ff09f68c',
|
||||
MESSAGE_PARTICIPANT_3: '20202020-e716-4dd5-ac61-3315bc559e2d',
|
||||
MESSAGE_PARTICIPANT_4: '20202020-fc7d-4ad8-9aea-b78bcbf79cdd',
|
||||
MESSAGE_PARTICIPANT_5: '20202020-564c-4a3c-abbf-e942e8c3f9c9',
|
||||
MESSAGE_PARTICIPANT_6: '20202020-7e4a-489a-ba6b-1ae6b7d721ac',
|
||||
};
|
||||
|
||||
export const seedMessageParticipant = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'id',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
'deletedAt',
|
||||
'workspaceMemberId',
|
||||
'personId',
|
||||
'displayName',
|
||||
'handle',
|
||||
'role',
|
||||
'messageId',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_PARTICIPANT_IDS.MESSAGE_PARTICIPANT_1,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
workspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
personId: DEV_SEED_PERSON_IDS.CHRISTOPH,
|
||||
displayName: 'Christoph',
|
||||
handle: 'outgoing',
|
||||
role: 'from',
|
||||
messageId: DEV_SEED_MESSAGE_IDS.MESSAGE_1,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_PARTICIPANT_IDS.MESSAGE_PARTICIPANT_2,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
workspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
personId: DEV_SEED_PERSON_IDS.SYLVIE,
|
||||
displayName: 'Sylvie',
|
||||
handle: 'incoming',
|
||||
role: 'to',
|
||||
messageId: DEV_SEED_MESSAGE_IDS.MESSAGE_1,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_PARTICIPANT_IDS.MESSAGE_PARTICIPANT_3,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
workspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
personId: DEV_SEED_PERSON_IDS.CHRISTOPHER_G,
|
||||
displayName: 'Christopher',
|
||||
handle: 'incoming',
|
||||
role: 'to',
|
||||
messageId: DEV_SEED_MESSAGE_IDS.MESSAGE_1,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_PARTICIPANT_IDS.MESSAGE_PARTICIPANT_4,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
workspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
personId: DEV_SEED_PERSON_IDS.CHRISTOPH,
|
||||
displayName: 'Christoph',
|
||||
handle: 'outgoing',
|
||||
role: 'from',
|
||||
messageId: DEV_SEED_MESSAGE_IDS.MESSAGE_2,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_PARTICIPANT_IDS.MESSAGE_PARTICIPANT_5,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
workspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
personId: DEV_SEED_PERSON_IDS.SYLVIE,
|
||||
displayName: 'Sylvie',
|
||||
handle: 'incoming',
|
||||
role: 'to',
|
||||
messageId: DEV_SEED_MESSAGE_IDS.MESSAGE_2,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_PARTICIPANT_IDS.MESSAGE_PARTICIPANT_6,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
workspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
personId: DEV_SEED_PERSON_IDS.CHRISTOPHER_G,
|
||||
displayName: 'Christopher',
|
||||
handle: 'incoming',
|
||||
role: 'to',
|
||||
messageId: DEV_SEED_MESSAGE_IDS.MESSAGE_2,
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
@ -1,105 +0,0 @@
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
|
||||
const tableName = 'messageThreadSubscriber';
|
||||
|
||||
export const DEV_SEED_MESSAGE_THREAD_SUBSCRIBERS_IDS = {
|
||||
MESSAGE_THREAD_SUBSCRIBER_1: '20202020-cc69-44ef-a82c-600c0dbf39ba',
|
||||
MESSAGE_THREAD_SUBSCRIBER_2: '20202020-d80e-4a13-b10b-72ba09082668',
|
||||
MESSAGE_THREAD_SUBSCRIBER_3: '20202020-e6ec-4c8a-b431-0901eaf395a9',
|
||||
MESSAGE_THREAD_SUBSCRIBER_4: '20202020-1455-4c57-afaf-dd5dc086361d',
|
||||
MESSAGE_THREAD_SUBSCRIBER_5: '20202020-f79e-40dd-bd06-c36e6abb4678',
|
||||
MESSAGE_THREAD_SUBSCRIBER_6: '20202020-3ec3-4fe3-8997-b76aa0bfa408',
|
||||
MESSAGE_THREAD_SUBSCRIBER_7: '20202020-c21e-4ec2-873b-de4264d89025',
|
||||
};
|
||||
|
||||
export const DEV_SEED_MESSAGE_THREAD_IDS = {
|
||||
MESSAGE_THREAD_1: '20202020-8bfa-453b-b99b-bc435a7d4da8',
|
||||
MESSAGE_THREAD_2: '20202020-634a-4fde-aa7c-28a0eaf203ca',
|
||||
MESSAGE_THREAD_3: '20202020-1b56-4f10-a2fa-2ccaddf81f6c',
|
||||
MESSAGE_THREAD_4: '20202020-d51c-485a-b1b6-ed7c63e05d72',
|
||||
};
|
||||
|
||||
export const DEV_SEED_USER_IDS = {
|
||||
TIM: '20202020-0687-4c41-b707-ed1bfca972a7',
|
||||
PHIL: '20202020-1553-45c6-a028-5a9064cce07f',
|
||||
JONY: '20202020-77d5-4cb6-b60a-f4a835a85d61',
|
||||
};
|
||||
|
||||
export const seedMessageThreadSubscribers = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'id',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
'deletedAt',
|
||||
'messageThreadId',
|
||||
'workspaceMemberId',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_THREAD_SUBSCRIBERS_IDS.MESSAGE_THREAD_SUBSCRIBER_1,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
messageThreadId: DEV_SEED_MESSAGE_THREAD_IDS.MESSAGE_THREAD_1,
|
||||
workspaceMemberId: DEV_SEED_USER_IDS.PHIL,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_THREAD_SUBSCRIBERS_IDS.MESSAGE_THREAD_SUBSCRIBER_2,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
messageThreadId: DEV_SEED_MESSAGE_THREAD_IDS.MESSAGE_THREAD_1,
|
||||
workspaceMemberId: DEV_SEED_USER_IDS.JONY,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_THREAD_SUBSCRIBERS_IDS.MESSAGE_THREAD_SUBSCRIBER_3,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
messageThreadId: DEV_SEED_MESSAGE_THREAD_IDS.MESSAGE_THREAD_2,
|
||||
workspaceMemberId: DEV_SEED_USER_IDS.TIM,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_THREAD_SUBSCRIBERS_IDS.MESSAGE_THREAD_SUBSCRIBER_4,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
messageThreadId: DEV_SEED_MESSAGE_THREAD_IDS.MESSAGE_THREAD_3,
|
||||
workspaceMemberId: DEV_SEED_USER_IDS.JONY,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_THREAD_SUBSCRIBERS_IDS.MESSAGE_THREAD_SUBSCRIBER_5,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
messageThreadId: DEV_SEED_MESSAGE_THREAD_IDS.MESSAGE_THREAD_4,
|
||||
workspaceMemberId: DEV_SEED_USER_IDS.TIM,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_THREAD_SUBSCRIBERS_IDS.MESSAGE_THREAD_SUBSCRIBER_6,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
messageThreadId: DEV_SEED_MESSAGE_THREAD_IDS.MESSAGE_THREAD_4,
|
||||
workspaceMemberId: DEV_SEED_USER_IDS.PHIL,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_THREAD_SUBSCRIBERS_IDS.MESSAGE_THREAD_SUBSCRIBER_7,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
messageThreadId: DEV_SEED_MESSAGE_THREAD_IDS.MESSAGE_THREAD_4,
|
||||
workspaceMemberId: DEV_SEED_USER_IDS.JONY,
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
@ -1,56 +0,0 @@
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
|
||||
const tableName = 'messageThread';
|
||||
|
||||
export const DEV_SEED_MESSAGE_THREAD_IDS = {
|
||||
MESSAGE_THREAD_1: '20202020-8bfa-453b-b99b-bc435a7d4da8',
|
||||
MESSAGE_THREAD_2: '20202020-634a-4fde-aa7c-28a0eaf203ca',
|
||||
MESSAGE_THREAD_3: '20202020-1b56-4f10-a2fa-2ccaddf81f6c',
|
||||
MESSAGE_THREAD_4: '20202020-d51c-485a-b1b6-ed7c63e05d72',
|
||||
MESSAGE_THREAD_5: '20202020-3f74-492d-a101-2a70f50a1645',
|
||||
};
|
||||
|
||||
export const seedMessageThread = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'id',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
'deletedAt',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_THREAD_IDS.MESSAGE_THREAD_1,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_THREAD_IDS.MESSAGE_THREAD_2,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_THREAD_IDS.MESSAGE_THREAD_3,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_THREAD_IDS.MESSAGE_THREAD_4,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
@ -1,69 +0,0 @@
|
||||
import { DEV_SEED_MESSAGE_THREAD_IDS } from 'src/database/typeorm-seeds/workspace/message-threads';
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
|
||||
const tableName = 'message';
|
||||
|
||||
export const DEV_SEED_MESSAGE_IDS = {
|
||||
MESSAGE_1: '20202020-2b8a-405d-8f42-e820ca921421',
|
||||
MESSAGE_2: '20202020-04c8-4f24-93f2-764948e95014',
|
||||
MESSAGE_3: '20202020-ac6b-4f86-87a2-5f5f9d1b6481',
|
||||
};
|
||||
|
||||
export const seedMessage = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'id',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
'deletedAt',
|
||||
'receivedAt',
|
||||
'text',
|
||||
'subject',
|
||||
'messageThreadId',
|
||||
'headerMessageId',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_IDS.MESSAGE_1,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
receivedAt: new Date(),
|
||||
text: 'Hello, \n I hope this email finds you well. I am writing to request a meeting. I believe it would be beneficial for both parties to collaborate and explore potential opportunities. Would you be available for a meeting sometime next week? Please let me know your availability, and I will arrange a suitable time. \n Looking forward to your response.\n Best regards',
|
||||
subject: 'Meeting Request',
|
||||
messageThreadId: DEV_SEED_MESSAGE_THREAD_IDS.MESSAGE_THREAD_1,
|
||||
headerMessageId: '99ef24a8-2b8a-405d-8f42-e820ca921421',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_IDS.MESSAGE_2,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
receivedAt: new Date(),
|
||||
text: 'Good Morning,\n I am writing to inquire about information. Could you please provide me with details regarding this topic? \n Your assistance in this matter would be greatly appreciated. Thank you in advance for your prompt response. \n Best regards,Tim',
|
||||
subject: 'Inquiry Regarding Topic',
|
||||
messageThreadId: DEV_SEED_MESSAGE_THREAD_IDS.MESSAGE_THREAD_2,
|
||||
headerMessageId: '8f804a9a-04c8-4f24-93f2-764948e95014',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_MESSAGE_IDS.MESSAGE_3,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
receivedAt: new Date(),
|
||||
text: 'Good Evening,\nI wanted to extend my sincere gratitude for taking the time to meet with me earlier today. It was a pleasure discussing with you, and I am excited about the potential opportunities for collaboration. \n Please feel free to reach out if you have any further questions or require additional information. I look forward to our continued communication. Best regards.',
|
||||
subject: 'Thank You for the Meeting',
|
||||
messageThreadId: DEV_SEED_MESSAGE_THREAD_IDS.MESSAGE_THREAD_1,
|
||||
headerMessageId: '3939d68a-ac6b-4f86-87a2-5f5f9d1b6481',
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
@ -1,98 +0,0 @@
|
||||
import { DEV_SEED_COMPANY_IDS } from 'src/database/typeorm-seeds/workspace/companies';
|
||||
import { DEV_SEED_PERSON_IDS } from 'src/database/typeorm-seeds/workspace/seedPeople';
|
||||
import { DEV_SEED_WORKSPACE_MEMBER_IDS } from 'src/database/typeorm-seeds/workspace/workspace-members';
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
|
||||
const tableName = 'opportunity';
|
||||
|
||||
export const DEV_SEED_OPPORTUNITY_IDS = {
|
||||
OPPORTUNITY_1: '20202020-be10-422b-a663-16bd3c2228e1',
|
||||
OPPORTUNITY_2: '20202020-0543-4cc2-9f96-95cc699960f2',
|
||||
OPPORTUNITY_3: '20202020-2f89-406f-90ea-180f433b2445',
|
||||
OPPORTUNITY_4: '20202020-35b1-4045-9cde-42f715148954',
|
||||
};
|
||||
|
||||
export const seedOpportunity = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'id',
|
||||
'name',
|
||||
'amountAmountMicros',
|
||||
'amountCurrencyCode',
|
||||
'closeDate',
|
||||
'stage',
|
||||
'position',
|
||||
'pointOfContactId',
|
||||
'companyId',
|
||||
'createdBySource',
|
||||
'createdByWorkspaceMemberId',
|
||||
'createdByName',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: DEV_SEED_OPPORTUNITY_IDS.OPPORTUNITY_1,
|
||||
name: 'Opportunity 1',
|
||||
amountAmountMicros: 100000,
|
||||
amountCurrencyCode: 'USD',
|
||||
closeDate: new Date(),
|
||||
stage: 'NEW',
|
||||
position: 1,
|
||||
pointOfContactId: DEV_SEED_PERSON_IDS.CHRISTOPH,
|
||||
companyId: DEV_SEED_COMPANY_IDS.LINKEDIN,
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Cook',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_OPPORTUNITY_IDS.OPPORTUNITY_2,
|
||||
name: 'Opportunity 2',
|
||||
amountAmountMicros: 2000000,
|
||||
amountCurrencyCode: 'USD',
|
||||
closeDate: new Date(),
|
||||
stage: 'MEETING',
|
||||
position: 2,
|
||||
pointOfContactId: DEV_SEED_PERSON_IDS.CHRISTOPHER_G,
|
||||
companyId: DEV_SEED_COMPANY_IDS.FACEBOOK,
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Cook',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_OPPORTUNITY_IDS.OPPORTUNITY_3,
|
||||
name: 'Opportunity 3',
|
||||
amountAmountMicros: 300000,
|
||||
amountCurrencyCode: 'USD',
|
||||
closeDate: new Date(),
|
||||
stage: 'PROPOSAL',
|
||||
position: 3,
|
||||
pointOfContactId: DEV_SEED_PERSON_IDS.NICHOLAS,
|
||||
companyId: DEV_SEED_COMPANY_IDS.MICROSOFT,
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Cook',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_OPPORTUNITY_IDS.OPPORTUNITY_4,
|
||||
name: 'Opportunity 4',
|
||||
amountAmountMicros: 4000000,
|
||||
amountCurrencyCode: 'USD',
|
||||
closeDate: new Date(),
|
||||
stage: 'PROPOSAL',
|
||||
position: 4,
|
||||
pointOfContactId: DEV_SEED_PERSON_IDS.MATTHEW,
|
||||
companyId: DEV_SEED_COMPANY_IDS.MICROSOFT,
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: null,
|
||||
createdByName: '',
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
@ -1,326 +0,0 @@
|
||||
import { DEV_SEED_COMPANY_IDS } from 'src/database/typeorm-seeds/workspace/companies';
|
||||
import { DEV_SEED_WORKSPACE_MEMBER_IDS } from 'src/database/typeorm-seeds/workspace/workspace-members';
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
|
||||
const tableName = 'person';
|
||||
|
||||
export const DEV_SEED_PERSON_IDS = {
|
||||
CHRISTOPH: '20202020-1c0e-494c-a1b6-85b1c6fefaa5',
|
||||
SYLVIE: '20202020-ac73-4797-824e-87a1f5aea9e0',
|
||||
CHRISTOPHER_G: '20202020-f517-42fd-80ae-14173b3b70ae',
|
||||
ASHLEY: '20202020-eee1-4690-ad2c-8619e5b56a2e',
|
||||
NICHOLAS: '20202020-6784-4449-afdf-dc62cb8702f2',
|
||||
ISABELLA: '20202020-490f-4466-8391-733cfd66a0c8',
|
||||
MATTHEW: '20202020-80f1-4dff-b570-a74942528de3',
|
||||
ELIZABETH: '20202020-338b-46df-8811-fa08c7d19d35',
|
||||
CHRISTOPHER_N: '20202020-64ad-4b0e-bbfd-e9fd795b7016',
|
||||
AVERY: '20202020-5d54-41b7-ba36-f0d20e1417ae',
|
||||
ETHAN: '20202020-623d-41fe-92e7-dd45b7c568e1',
|
||||
MADISON: '20202020-2d40-4e49-8df4-9c6a049190ef',
|
||||
BERTRAND: '20202020-2d40-4e49-8df4-9c6a049190df',
|
||||
LOUIS: '20202020-2d40-4e49-8df4-9c6a049191de',
|
||||
LORIE: '20202020-2d40-4e49-8df4-9c6a049191df',
|
||||
};
|
||||
|
||||
export const seedPeople = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'id',
|
||||
'nameFirstName',
|
||||
'nameLastName',
|
||||
'phonesPrimaryPhoneCountryCode',
|
||||
'phonesPrimaryPhoneCallingCode',
|
||||
'phonesPrimaryPhoneNumber',
|
||||
'city',
|
||||
'companyId',
|
||||
'emailsPrimaryEmail',
|
||||
'position',
|
||||
'whatsappPrimaryPhoneCountryCode',
|
||||
'whatsappPrimaryPhoneCallingCode',
|
||||
'whatsappPrimaryPhoneNumber',
|
||||
'createdBySource',
|
||||
'createdByWorkspaceMemberId',
|
||||
'createdByName',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: DEV_SEED_PERSON_IDS.CHRISTOPH,
|
||||
nameFirstName: 'Christoph',
|
||||
nameLastName: 'Callisto',
|
||||
phonesPrimaryPhoneCountryCode: 'FR',
|
||||
phonesPrimaryPhoneCallingCode: '+33',
|
||||
phonesPrimaryPhoneNumber: '789012345',
|
||||
city: 'Seattle',
|
||||
companyId: DEV_SEED_COMPANY_IDS.LINKEDIN,
|
||||
emailsPrimaryEmail: 'christoph.calisto@linkedin.com',
|
||||
position: 1,
|
||||
whatsappPrimaryPhoneCountryCode: 'FR',
|
||||
whatsappPrimaryPhoneCallingCode: '+33',
|
||||
whatsappPrimaryPhoneNumber: '789012345',
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_PERSON_IDS.SYLVIE,
|
||||
nameFirstName: 'Sylvie',
|
||||
nameLastName: 'Palmer',
|
||||
phonesPrimaryPhoneCountryCode: 'FR',
|
||||
phonesPrimaryPhoneCallingCode: '+33',
|
||||
phonesPrimaryPhoneNumber: '780123456',
|
||||
city: 'Los Angeles',
|
||||
companyId: DEV_SEED_COMPANY_IDS.LINKEDIN,
|
||||
emailsPrimaryEmail: 'sylvie.palmer@linkedin.com',
|
||||
position: 2,
|
||||
whatsappPrimaryPhoneCountryCode: 'FR',
|
||||
whatsappPrimaryPhoneCallingCode: '+33',
|
||||
whatsappPrimaryPhoneNumber: '780123456',
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_PERSON_IDS.CHRISTOPHER_G,
|
||||
nameFirstName: 'Christopher',
|
||||
nameLastName: 'Gonzalez',
|
||||
phonesPrimaryPhoneCountryCode: 'FR',
|
||||
phonesPrimaryPhoneCallingCode: '+33',
|
||||
phonesPrimaryPhoneNumber: '789012345',
|
||||
city: 'San Francisco',
|
||||
companyId: DEV_SEED_COMPANY_IDS.ANTHROPIC,
|
||||
emailsPrimaryEmail: 'christopher.gonzalez@anthropic.com',
|
||||
position: 3,
|
||||
whatsappPrimaryPhoneCountryCode: 'FR',
|
||||
whatsappPrimaryPhoneCallingCode: '+33',
|
||||
whatsappPrimaryPhoneNumber: '789012345',
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_PERSON_IDS.ASHLEY,
|
||||
nameFirstName: 'Ashley',
|
||||
nameLastName: 'Parker',
|
||||
phonesPrimaryPhoneCountryCode: 'FR',
|
||||
phonesPrimaryPhoneCallingCode: '+33',
|
||||
phonesPrimaryPhoneNumber: '780123456',
|
||||
city: 'Los Angeles',
|
||||
companyId: DEV_SEED_COMPANY_IDS.ANTHROPIC,
|
||||
emailsPrimaryEmail: 'ashley.parker@anthropic.com',
|
||||
position: 4,
|
||||
whatsappPrimaryPhoneCountryCode: 'FR',
|
||||
whatsappPrimaryPhoneCallingCode: '+33',
|
||||
whatsappPrimaryPhoneNumber: '780123456',
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_PERSON_IDS.NICHOLAS,
|
||||
nameFirstName: 'Nicholas',
|
||||
nameLastName: 'Wright',
|
||||
phonesPrimaryPhoneCountryCode: 'FR',
|
||||
phonesPrimaryPhoneCallingCode: '+33',
|
||||
phonesPrimaryPhoneNumber: '781234567',
|
||||
city: 'Seattle',
|
||||
companyId: DEV_SEED_COMPANY_IDS.MICROSOFT,
|
||||
emailsPrimaryEmail: 'nicholas.wright@microsoft.com',
|
||||
position: 5,
|
||||
whatsappPrimaryPhoneCountryCode: 'FR',
|
||||
whatsappPrimaryPhoneCallingCode: '+33',
|
||||
whatsappPrimaryPhoneNumber: '781234567',
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_PERSON_IDS.ISABELLA,
|
||||
nameFirstName: 'Isabella',
|
||||
nameLastName: 'Scott',
|
||||
phonesPrimaryPhoneCountryCode: 'FR',
|
||||
phonesPrimaryPhoneCallingCode: '+33',
|
||||
phonesPrimaryPhoneNumber: '782345678',
|
||||
city: 'New York',
|
||||
companyId: DEV_SEED_COMPANY_IDS.MICROSOFT,
|
||||
emailsPrimaryEmail: 'isabella.scott@microsoft.com',
|
||||
position: 6,
|
||||
whatsappPrimaryPhoneCountryCode: 'FR',
|
||||
whatsappPrimaryPhoneCallingCode: '+33',
|
||||
whatsappPrimaryPhoneNumber: '782345678',
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_PERSON_IDS.MATTHEW,
|
||||
nameFirstName: 'Matthew',
|
||||
nameLastName: 'Green',
|
||||
phonesPrimaryPhoneCountryCode: 'FR',
|
||||
phonesPrimaryPhoneCallingCode: '+33',
|
||||
phonesPrimaryPhoneNumber: '783456789',
|
||||
city: 'Seattle',
|
||||
companyId: DEV_SEED_COMPANY_IDS.MICROSOFT,
|
||||
emailsPrimaryEmail: 'matthew.green@microsoft.com',
|
||||
position: 7,
|
||||
whatsappPrimaryPhoneCountryCode: 'FR',
|
||||
whatsappPrimaryPhoneCallingCode: '+33',
|
||||
whatsappPrimaryPhoneNumber: '783456789',
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_PERSON_IDS.ELIZABETH,
|
||||
nameFirstName: 'Elizabeth',
|
||||
nameLastName: 'Baker',
|
||||
phonesPrimaryPhoneCountryCode: 'FR',
|
||||
phonesPrimaryPhoneCallingCode: '+33',
|
||||
phonesPrimaryPhoneNumber: '784567890',
|
||||
city: 'New York',
|
||||
companyId: DEV_SEED_COMPANY_IDS.AIRBNB,
|
||||
emailsPrimaryEmail: 'elizabeth.baker@airbnb.com',
|
||||
position: 8,
|
||||
whatsappPrimaryPhoneCountryCode: 'FR',
|
||||
whatsappPrimaryPhoneCallingCode: '+33',
|
||||
whatsappPrimaryPhoneNumber: '784567890',
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_PERSON_IDS.CHRISTOPHER_N,
|
||||
nameFirstName: 'Christopher',
|
||||
nameLastName: 'Nelson',
|
||||
phonesPrimaryPhoneCountryCode: 'FR',
|
||||
phonesPrimaryPhoneCallingCode: '+33',
|
||||
phonesPrimaryPhoneNumber: '785678901',
|
||||
city: 'San Francisco',
|
||||
companyId: DEV_SEED_COMPANY_IDS.AIRBNB,
|
||||
emailsPrimaryEmail: 'christopher.nelson@airbnb.com',
|
||||
position: 9,
|
||||
whatsappPrimaryPhoneCountryCode: 'FR',
|
||||
whatsappPrimaryPhoneCallingCode: '+33',
|
||||
whatsappPrimaryPhoneNumber: '785678901',
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_PERSON_IDS.AVERY,
|
||||
nameFirstName: 'Avery',
|
||||
nameLastName: 'Carter',
|
||||
phonesPrimaryPhoneCountryCode: 'FR',
|
||||
phonesPrimaryPhoneCallingCode: '+33',
|
||||
phonesPrimaryPhoneNumber: '786789012',
|
||||
city: 'New York',
|
||||
companyId: DEV_SEED_COMPANY_IDS.AIRBNB,
|
||||
emailsPrimaryEmail: 'avery.carter@airbnb.com',
|
||||
position: 10,
|
||||
whatsappPrimaryPhoneCountryCode: 'FR',
|
||||
whatsappPrimaryPhoneCallingCode: '+33',
|
||||
whatsappPrimaryPhoneNumber: '786789012',
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_PERSON_IDS.ETHAN,
|
||||
nameFirstName: 'Ethan',
|
||||
nameLastName: 'Mitchell',
|
||||
phonesPrimaryPhoneCountryCode: 'FR',
|
||||
phonesPrimaryPhoneCallingCode: '+33',
|
||||
phonesPrimaryPhoneNumber: '787890123',
|
||||
city: 'Los Angeles',
|
||||
companyId: DEV_SEED_COMPANY_IDS.GOOGLE,
|
||||
emailsPrimaryEmail: 'ethan.mitchell@google.com',
|
||||
position: 11,
|
||||
whatsappPrimaryPhoneCountryCode: 'FR',
|
||||
whatsappPrimaryPhoneCallingCode: '+33',
|
||||
whatsappPrimaryPhoneNumber: '787890123',
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_PERSON_IDS.MADISON,
|
||||
nameFirstName: 'Madison',
|
||||
nameLastName: 'Perez',
|
||||
phonesPrimaryPhoneCountryCode: 'FR',
|
||||
phonesPrimaryPhoneCallingCode: '+33',
|
||||
phonesPrimaryPhoneNumber: '788901234',
|
||||
city: 'Seattle',
|
||||
companyId: DEV_SEED_COMPANY_IDS.GOOGLE,
|
||||
emailsPrimaryEmail: 'madison.perez@google.com',
|
||||
position: 12,
|
||||
whatsappPrimaryPhoneCountryCode: 'FR',
|
||||
whatsappPrimaryPhoneCallingCode: '+33',
|
||||
whatsappPrimaryPhoneNumber: '788901234',
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_PERSON_IDS.BERTRAND,
|
||||
nameFirstName: 'Bertrand',
|
||||
nameLastName: 'Voulzy',
|
||||
phonesPrimaryPhoneCountryCode: 'FR',
|
||||
phonesPrimaryPhoneCallingCode: '+33',
|
||||
phonesPrimaryPhoneNumber: '788901234',
|
||||
city: 'Seattle',
|
||||
companyId: DEV_SEED_COMPANY_IDS.GOOGLE,
|
||||
emailsPrimaryEmail: 'bertrand.voulzy@google.com',
|
||||
position: 13,
|
||||
whatsappPrimaryPhoneCountryCode: 'FR',
|
||||
whatsappPrimaryPhoneCallingCode: '+33',
|
||||
whatsappPrimaryPhoneNumber: '788901234',
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_PERSON_IDS.LOUIS,
|
||||
nameFirstName: 'Louis',
|
||||
nameLastName: 'Duss',
|
||||
phonesPrimaryPhoneCountryCode: 'FR',
|
||||
phonesPrimaryPhoneCallingCode: '+33',
|
||||
phonesPrimaryPhoneNumber: '789012345',
|
||||
city: 'Seattle',
|
||||
companyId: DEV_SEED_COMPANY_IDS.GOOGLE,
|
||||
emailsPrimaryEmail: 'louis.duss@google.com',
|
||||
position: 14,
|
||||
whatsappPrimaryPhoneCountryCode: 'FR',
|
||||
whatsappPrimaryPhoneCallingCode: '+33',
|
||||
whatsappPrimaryPhoneNumber: '789012345',
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_PERSON_IDS.LORIE,
|
||||
nameFirstName: 'Lorie',
|
||||
nameLastName: 'Vladim',
|
||||
phonesPrimaryPhoneCountryCode: 'FR',
|
||||
phonesPrimaryPhoneCallingCode: '+33',
|
||||
phonesPrimaryPhoneNumber: '788901235',
|
||||
city: 'Seattle',
|
||||
companyId: DEV_SEED_COMPANY_IDS.GOOGLE,
|
||||
emailsPrimaryEmail: 'lorie.vladim@google.com',
|
||||
position: 15,
|
||||
whatsappPrimaryPhoneCountryCode: 'FR',
|
||||
whatsappPrimaryPhoneCallingCode: '+33',
|
||||
whatsappPrimaryPhoneNumber: '788901235',
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
createdByName: 'Tim Apple',
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
@ -1,96 +0,0 @@
|
||||
import { DEV_SEED_USER_IDS } from 'src/database/typeorm-seeds/core/users';
|
||||
import {
|
||||
SEED_ACME_WORKSPACE_ID,
|
||||
SEED_APPLE_WORKSPACE_ID,
|
||||
} from 'src/database/typeorm-seeds/core/workspaces';
|
||||
import { WorkspaceMember } from 'src/engine/core-modules/user/dtos/workspace-member.dto';
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
|
||||
const tableName = 'workspaceMember';
|
||||
|
||||
export const DEV_SEED_WORKSPACE_MEMBER_IDS = {
|
||||
TIM: '20202020-0687-4c41-b707-ed1bfca972a7',
|
||||
JONY: '20202020-77d5-4cb6-b60a-f4a835a85d61',
|
||||
PHIL: '20202020-1553-45c6-a028-5a9064cce07f',
|
||||
};
|
||||
|
||||
type WorkspaceMembers = Pick<
|
||||
WorkspaceMember,
|
||||
'id' | 'locale' | 'colorScheme'
|
||||
> & {
|
||||
nameFirstName: string;
|
||||
nameLastName: string;
|
||||
userEmail: string;
|
||||
userId: string;
|
||||
};
|
||||
|
||||
export const seedWorkspaceMember = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
let workspaceMembers: WorkspaceMembers[] = [];
|
||||
|
||||
if (workspaceId === SEED_APPLE_WORKSPACE_ID) {
|
||||
workspaceMembers = [
|
||||
{
|
||||
id: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
nameFirstName: 'Tim',
|
||||
nameLastName: 'Apple',
|
||||
locale: 'en',
|
||||
colorScheme: 'Light',
|
||||
userEmail: 'tim@apple.dev',
|
||||
userId: DEV_SEED_USER_IDS.TIM,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_WORKSPACE_MEMBER_IDS.JONY,
|
||||
nameFirstName: 'Jony',
|
||||
nameLastName: 'Ive',
|
||||
locale: 'en',
|
||||
colorScheme: 'Light',
|
||||
userEmail: 'jony.ive@apple.dev',
|
||||
userId: DEV_SEED_USER_IDS.JONY,
|
||||
},
|
||||
{
|
||||
id: DEV_SEED_WORKSPACE_MEMBER_IDS.PHIL,
|
||||
nameFirstName: 'Phil',
|
||||
nameLastName: 'Schiler',
|
||||
locale: 'en',
|
||||
colorScheme: 'Light',
|
||||
userEmail: 'phil.schiler@apple.dev',
|
||||
userId: DEV_SEED_USER_IDS.PHIL,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
if (workspaceId === SEED_ACME_WORKSPACE_ID) {
|
||||
workspaceMembers = [
|
||||
{
|
||||
id: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
nameFirstName: 'Tim',
|
||||
nameLastName: 'Apple',
|
||||
locale: 'en',
|
||||
colorScheme: 'Light',
|
||||
userEmail: 'tim@apple.dev',
|
||||
userId: DEV_SEED_USER_IDS.TIM,
|
||||
},
|
||||
];
|
||||
}
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'id',
|
||||
'nameFirstName',
|
||||
'nameLastName',
|
||||
'locale',
|
||||
'colorScheme',
|
||||
'userEmail',
|
||||
'userId',
|
||||
])
|
||||
.orIgnore()
|
||||
.values(workspaceMembers)
|
||||
.execute();
|
||||
};
|
||||
@ -16,9 +16,13 @@ export const typeORMCoreModuleOptions: TypeOrmModuleOptions = {
|
||||
schema: 'core',
|
||||
entities:
|
||||
process.env.IS_BILLING_ENABLED === 'true'
|
||||
? [`${isJest ? '' : 'dist/'}src/engine/core-modules/**/*.entity{.ts,.js}`]
|
||||
? [
|
||||
`${isJest ? '' : 'dist/'}src/engine/core-modules/**/*.entity{.ts,.js}`,
|
||||
`${isJest ? '' : 'dist/'}src/engine/metadata-modules/**/*.entity{.ts,.js}`,
|
||||
]
|
||||
: [
|
||||
`${isJest ? '' : 'dist/'}src/engine/core-modules/**/!(billing-*).entity{.ts,.js}`,
|
||||
`${isJest ? '' : 'dist/'}src/engine/core-modules/**/!(billing-*).entity.{ts,js}`,
|
||||
`${isJest ? '' : 'dist/'}src/engine/metadata-modules/**/*.entity{.ts,.js}`,
|
||||
],
|
||||
synchronize: false,
|
||||
migrationsRun: false,
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
|
||||
|
||||
import { config } from 'dotenv';
|
||||
import { DataSource, DataSourceOptions } from 'typeorm';
|
||||
config({
|
||||
path: process.env.NODE_ENV === 'test' ? '.env.test' : '.env',
|
||||
override: true,
|
||||
});
|
||||
|
||||
const isJest = process.argv.some((arg) => arg.includes('jest'));
|
||||
|
||||
export const typeORMMetadataModuleOptions: TypeOrmModuleOptions = {
|
||||
url: process.env.PG_DATABASE_URL,
|
||||
type: 'postgres',
|
||||
logging: ['error'],
|
||||
schema: 'core',
|
||||
entities: [
|
||||
`${isJest ? '' : 'dist/'}src/engine/metadata-modules/**/*.entity{.ts,.js}`,
|
||||
],
|
||||
synchronize: false,
|
||||
migrationsRun: false,
|
||||
migrationsTableName: '_typeorm_migrations',
|
||||
migrations: [
|
||||
`${isJest ? '' : 'dist/'}src/database/typeorm/metadata/migrations/*{.ts,.js}`,
|
||||
],
|
||||
ssl:
|
||||
process.env.PG_SSL_ALLOW_SELF_SIGNED === 'true'
|
||||
? {
|
||||
rejectUnauthorized: false,
|
||||
}
|
||||
: undefined,
|
||||
extra: {
|
||||
query_timeout: 10000,
|
||||
},
|
||||
};
|
||||
|
||||
export const connectionSource = new DataSource(
|
||||
typeORMMetadataModuleOptions as DataSourceOptions,
|
||||
);
|
||||
@ -6,13 +6,6 @@ import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty
|
||||
|
||||
import { TypeORMService } from './typeorm.service';
|
||||
|
||||
import { typeORMMetadataModuleOptions } from './metadata/metadata.datasource';
|
||||
|
||||
const metadataTypeORMFactory = async (): Promise<TypeOrmModuleOptions> => ({
|
||||
...typeORMMetadataModuleOptions,
|
||||
name: 'metadata',
|
||||
});
|
||||
|
||||
const coreTypeORMFactory = async (): Promise<TypeOrmModuleOptions> => ({
|
||||
...typeORMCoreModuleOptions,
|
||||
name: 'core',
|
||||
@ -21,10 +14,6 @@ const coreTypeORMFactory = async (): Promise<TypeOrmModuleOptions> => ({
|
||||
@Module({
|
||||
imports: [
|
||||
TwentyConfigModule,
|
||||
TypeOrmModule.forRootAsync({
|
||||
useFactory: metadataTypeORMFactory,
|
||||
name: 'metadata',
|
||||
}),
|
||||
TypeOrmModule.forRootAsync({
|
||||
useFactory: coreTypeORMFactory,
|
||||
name: 'core',
|
||||
|
||||
Reference in New Issue
Block a user