Twenty standard and workspace custom applications 1/3 (#15625)

# Introduction
related to https://github.com/twentyhq/core-team-issues/issues/1833
In this PR we're starting the sync-metadata and standardIds deprecation
by introducing `twenty-standard` application that will regroup every
standard object such as company and opportunities. But also the
`custom-workspace-application` which is an app created at the same time
as a workspace and that will regroup everything configure within the
workspace ( custom objects fields etc )

## What's done
On both new workspace and seeded workspace creation:
- Creating a custom workspace app
- Creating a twenty standard app
- Refactored the seed core schema and workspace creation to be run
within a transaction in order to handle circular dependency foreignkey
requirements ( which is deferred for app toward workspace )
- Updated workspace entity to have a custom workspace relation (
nullable for the moment until we implem an upgrade command to handle
retro comp )
- Integration testing on user, workspace creation deletion and expected
default apps creation
- ~~Soft deleted user on `deleteUser`~~ Done by marie and rebased on it

## What's next
- Update seeder to propagate the `twenty-standard` workspace
`applicationId` to every standard synchronized entities ( cheap and fast
iteration through the about to be deprecated sync-metadata as an easy
way to synchronize standards metadata entities ).
- Update seeder to propagate the `custom-workspace-application`
workspace `applicationId` to anything custom ( `pets` and `rockets` )
- Prepend `custom-workspace-application` `applicationId` to every
metadata API operations ( create a specific cache etc )
- Upgrade command on all existing workspace to create a custom app and
associate its applicationId to any existing custom entities
- Make `universalIdentifier` and `applicationId` required for any
syncable entity
This commit is contained in:
Paul Rastoin
2025-11-10 16:13:12 +01:00
committed by GitHub
parent 9a80164cf3
commit 7a1e699fc8
106 changed files with 2167 additions and 985 deletions
@@ -1,6 +1,6 @@
import { InjectRepository } from '@nestjs/typeorm';
import { IsNull, Repository } from 'typeorm';
import { type QueryRunner, IsNull, Repository } from 'typeorm';
import {
KeyValuePairEntity,
@@ -50,19 +50,22 @@ export class KeyValuePairService<
}));
}
async set<K extends keyof KeyValueTypesMap>({
userId,
workspaceId,
key,
value,
type,
}: {
userId?: string | null;
workspaceId?: string | null;
key: Extract<K, string>;
value: KeyValueTypesMap[K];
type: KeyValuePairType;
}) {
async set<K extends keyof KeyValueTypesMap>(
{
userId,
workspaceId,
key,
value,
type,
}: {
userId?: string | null;
workspaceId?: string | null;
key: Extract<K, string>;
value: KeyValueTypesMap[K];
type: KeyValuePairType;
},
queryRunner?: QueryRunner,
) {
const upsertData = {
userId,
workspaceId,
@@ -84,24 +87,36 @@ export class KeyValuePairService<
? '"workspaceId" is NULL'
: undefined;
await this.keyValuePairRepository.upsert(upsertData, {
conflictPaths,
indexPredicate,
});
if (queryRunner) {
await queryRunner.manager
.getRepository(KeyValuePairEntity)
.upsert(upsertData, {
conflictPaths,
indexPredicate,
});
} else {
await this.keyValuePairRepository.upsert(upsertData, {
conflictPaths,
indexPredicate,
});
}
}
async delete({
userId,
workspaceId,
type,
key,
}: {
userId?: string | null;
workspaceId?: string | null;
type: KeyValuePairType;
key: Extract<keyof KeyValueTypesMap, string>;
}) {
await this.keyValuePairRepository.delete({
async delete(
{
userId,
workspaceId,
type,
key,
}: {
userId?: string | null;
workspaceId?: string | null;
type: KeyValuePairType;
key: Extract<keyof KeyValueTypesMap, string>;
},
queryRunner?: QueryRunner,
) {
const deleteConditions = {
...(userId === undefined
? {}
: userId === null
@@ -114,6 +129,14 @@ export class KeyValuePairService<
: { workspaceId }),
type,
key,
});
};
if (queryRunner) {
await queryRunner.manager
.getRepository(KeyValuePairEntity)
.delete(deleteConditions);
} else {
await this.keyValuePairRepository.delete(deleteConditions);
}
}
}