Solo transaction application synchronization service refactor (#17864)
# Introduction Refactoring the application sync service to be making a single validate build and run transaction instead of calling all the services n times thanks to the universal workspace migration refactor that allow doing so ## What's next Migrating all below entities to by syncableEntities so they can be universalised too ( right now they're still calling the services n times and won't be returned in the workspace migration ) - [objectPermission](https://github.com/twentyhq/core-team-issues/issues/2223) - [fieldPermission](https://github.com/twentyhq/core-team-issues/issues/2224) - [permissionFlag](https://github.com/twentyhq/core-team-issues/issues/2225)
This commit is contained in:
@@ -1,17 +1,16 @@
|
||||
import {
|
||||
type FieldMetadataType,
|
||||
type FieldMetadataSettings,
|
||||
type FieldMetadataOptions,
|
||||
type FieldMetadataDefaultValue,
|
||||
} from '@/types';
|
||||
import { type SyncableEntityOptions } from '@/application/syncableEntityOptionsType';
|
||||
import { type RelationOnDeleteAction } from '@/types/RelationOnDeleteAction.type';
|
||||
import { type RelationType } from '@/types/RelationType';
|
||||
import {
|
||||
type FieldMetadataDefaultValue,
|
||||
type FieldMetadataOptions,
|
||||
type FieldMetadataType,
|
||||
type FieldMetadataUniversalSettings,
|
||||
type RelationAndMorphRelationFieldMetadataType,
|
||||
} from '@/types';
|
||||
|
||||
export type RegularFieldManifest<
|
||||
T extends FieldMetadataType = Exclude<
|
||||
FieldMetadataType,
|
||||
FieldMetadataType.RELATION
|
||||
RelationAndMorphRelationFieldMetadataType
|
||||
>,
|
||||
> = SyncableEntityOptions & {
|
||||
type: T;
|
||||
@@ -21,23 +20,24 @@ export type RegularFieldManifest<
|
||||
icon?: string;
|
||||
defaultValue?: FieldMetadataDefaultValue<T>;
|
||||
options?: FieldMetadataOptions<T>;
|
||||
settings?: FieldMetadataSettings<T>;
|
||||
universalSettings?: FieldMetadataUniversalSettings<T>;
|
||||
isNullable?: boolean;
|
||||
objectUniversalIdentifier: string;
|
||||
};
|
||||
|
||||
export type RelationFieldManifest =
|
||||
RegularFieldManifest<FieldMetadataType.RELATION> & {
|
||||
relationType: RelationType;
|
||||
targetObjectUniversalIdentifier: string;
|
||||
targetFieldLabel: string;
|
||||
targetFieldIcon?: string;
|
||||
onDelete?: RelationOnDeleteAction;
|
||||
};
|
||||
// Both sides of a relation must be declared explicitly in the manifest.
|
||||
// Relation-specific universal settings (relationType, onDelete, joinColumnName)
|
||||
// are provided through the `universalSettings` field.
|
||||
export type RelationFieldManifest<
|
||||
T extends RelationAndMorphRelationFieldMetadataType = RelationAndMorphRelationFieldMetadataType,
|
||||
> = RegularFieldManifest<T> & {
|
||||
relationTargetFieldMetadataUniversalIdentifier: string;
|
||||
relationTargetObjectMetadataUniversalIdentifier: string;
|
||||
};
|
||||
|
||||
export type FieldManifest<
|
||||
T extends FieldMetadataType = Exclude<
|
||||
FieldMetadataType,
|
||||
FieldMetadataType.RELATION
|
||||
RelationAndMorphRelationFieldMetadataType
|
||||
>,
|
||||
> = RegularFieldManifest<T> | RelationFieldManifest;
|
||||
|
||||
@@ -36,5 +36,9 @@ export type {
|
||||
export type { Manifest } from './manifestType';
|
||||
export type { ObjectFieldManifest } from './objectFieldManifest.type';
|
||||
export type { ObjectManifest } from './objectManifestType';
|
||||
export type { RoleManifest } from './roleManifestType';
|
||||
export type {
|
||||
ObjectPermissionManifest,
|
||||
FieldPermissionManifest,
|
||||
RoleManifest,
|
||||
} from './roleManifestType';
|
||||
export type { SyncableEntityOptions } from './syncableEntityOptionsType';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { type PermissionFlagType } from '@/constants';
|
||||
import { type SyncableEntityOptions } from '@/application/syncableEntityOptionsType';
|
||||
|
||||
type ObjectPermission = {
|
||||
export type ObjectPermissionManifest = {
|
||||
objectUniversalIdentifier: string;
|
||||
canReadObjectRecords?: boolean;
|
||||
canUpdateObjectRecords?: boolean;
|
||||
@@ -9,7 +9,7 @@ type ObjectPermission = {
|
||||
canDestroyObjectRecords?: boolean;
|
||||
};
|
||||
|
||||
type FieldPermission = {
|
||||
export type FieldPermissionManifest = {
|
||||
objectUniversalIdentifier: string;
|
||||
fieldUniversalIdentifier: string;
|
||||
canReadFieldValue?: boolean;
|
||||
@@ -29,7 +29,7 @@ export type RoleManifest = SyncableEntityOptions & {
|
||||
canBeAssignedToUsers?: boolean;
|
||||
canBeAssignedToAgents?: boolean;
|
||||
canBeAssignedToApiKeys?: boolean;
|
||||
objectPermissions?: ObjectPermission[];
|
||||
fieldPermissions?: FieldPermission[];
|
||||
objectPermissions?: ObjectPermissionManifest[];
|
||||
fieldPermissions?: FieldPermissionManifest[];
|
||||
permissionFlags?: PermissionFlagType[];
|
||||
};
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { type FieldMetadataType } from '@/types/FieldMetadataType';
|
||||
import { type FieldMetadataSettings } from '@/types/FieldMetadataSettings';
|
||||
import { type FormatRecordSerializedRelationProperties } from '@/types/FormatRecordSerializedRelationProperties.type';
|
||||
|
||||
export type FieldMetadataUniversalSettings<
|
||||
T extends FieldMetadataType = FieldMetadataType,
|
||||
> = FormatRecordSerializedRelationProperties<FieldMetadataSettings<T>>;
|
||||
@@ -0,0 +1,38 @@
|
||||
import { type ExtractSerializedRelationProperties } from '@/types/ExtractSerializedRelationProperties.type';
|
||||
import { type IsSerializedRelation } from '@/types/IsSerializedRelation.type';
|
||||
import { type RemoveSuffix } from '@/types/RemoveSuffix.type';
|
||||
|
||||
// Determines if a property should be transformed to a universal identifier
|
||||
// A property is transformed only if:
|
||||
// 1. It matches ExtractSerializedRelationProperties (has the serialized relation brand)
|
||||
// 2. Its value does NOT have a string index signature (not a Record<string, X>)
|
||||
type ShouldTransformToUniversalIdentifier<T, P extends keyof T> = [P] extends [
|
||||
ExtractSerializedRelationProperties<T>,
|
||||
]
|
||||
? string extends keyof NonNullable<T[P]>
|
||||
? false
|
||||
: true
|
||||
: false;
|
||||
|
||||
export type FormatRecordSerializedRelationProperties<T> = T extends unknown
|
||||
? T extends (infer U)[]
|
||||
? FormatRecordSerializedRelationProperties<U>[]
|
||||
: T extends string
|
||||
? // By definition we assume that any SerializedRelation are not enforced at pg scope through an FK
|
||||
// Which mean that SerializedRelation might resolve to non-existent entities ( null )
|
||||
IsSerializedRelation<T> extends true
|
||||
? T | null
|
||||
: T
|
||||
: T extends object
|
||||
? {
|
||||
[P in keyof T as ShouldTransformToUniversalIdentifier<
|
||||
T,
|
||||
P
|
||||
> extends true
|
||||
? P extends string
|
||||
? `${RemoveSuffix<P, 'Id'>}UniversalIdentifier`
|
||||
: P
|
||||
: P]: FormatRecordSerializedRelationProperties<T[P]>;
|
||||
}
|
||||
: T
|
||||
: never;
|
||||
@@ -0,0 +1,4 @@
|
||||
export type RemoveSuffix<
|
||||
T extends string,
|
||||
P extends string,
|
||||
> = T extends `${infer Prefix}${P}` ? Prefix : T;
|
||||
@@ -94,6 +94,7 @@ export type {
|
||||
} from './FieldMetadataSettings';
|
||||
export { NumberDataType, DateDisplayFormat } from './FieldMetadataSettings';
|
||||
export { FieldMetadataType } from './FieldMetadataType';
|
||||
export type { FieldMetadataUniversalSettings } from './FieldMetadataUniversalSettings';
|
||||
export type { FieldRatingValue } from './FieldRatingValue';
|
||||
export type { FileCategory } from './FileCategory';
|
||||
export { FILE_CATEGORIES } from './FileCategory';
|
||||
@@ -104,6 +105,7 @@ export type {
|
||||
} from './FilterableFieldType';
|
||||
export { FILTERABLE_FIELD_TYPES } from './FilterableFieldType';
|
||||
export { FirstDayOfTheWeek } from './FirstDayOfTheWeek';
|
||||
export type { FormatRecordSerializedRelationProperties } from './FormatRecordSerializedRelationProperties.type';
|
||||
export type { FromTo } from './FromToType';
|
||||
export { HTTPMethod } from './HttpMethod';
|
||||
export type { IsEmptyObject } from './IsEmptyObject.type';
|
||||
@@ -190,6 +192,7 @@ export type { RelationCreationPayload } from './RelationCreationPayload';
|
||||
export { RelationOnDeleteAction } from './RelationOnDeleteAction.type';
|
||||
export { RelationType } from './RelationType';
|
||||
export type { RelationUpdatePayload } from './RelationUpdatePayload';
|
||||
export type { RemoveSuffix } from './RemoveSuffix.type';
|
||||
export type { RestrictedFieldPermissions } from './RestrictedFieldPermissions';
|
||||
export type { RestrictedFieldsPermissions } from './RestrictedFieldsPermissions';
|
||||
export type { RowLevelPermissionPredicate } from './RowLevelPermissionPredicate';
|
||||
|
||||
Reference in New Issue
Block a user