[BREAKING_CHANGE_NESTED_WORKSPACE]Refactor FlatEntity typing in aim of introducing UniversalFlatEntity (#16701)
# Introduction
Added a `WorkspaceRelated` and `AllNonWorkspaceRelatedEntity` to
simplify the `FlatEntityFrom` that now do not expect a string literal to
omit and itself builds the related many to one entities foreign key
aggregators
We now have the type grain over relation to syncable or just workspace
related entities
Added a migrations that sets the fk on missing entities
## Next
In upcoming PR we will be able to introduce such below type
```ts
import { type CastRecordTypeOrmDatePropertiesToString } from 'src/engine/metadata-modules/flat-entity/types/cast-record-typeorm-date-properties-to-string.type';
import { type ExtractEntityManyToOneEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/types/extract-entity-many-to-one-entity-relation-properties.type';
import { type ExtractEntityOneToManyEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/types/extract-entity-one-to-many-entity-relation-properties.type';
import { type ExtractEntityRelatedEntityProperties } from 'src/engine/metadata-modules/flat-entity/types/extract-entity-related-entity-properties.type';
import { type RemoveSuffix } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/remove-suffix.type';
import { type SyncableEntity } from 'src/engine/workspace-manager/workspace-sync/types/syncable-entity.interface';
export type UniversalFlatEntityFrom<TEntity extends SyncableEntity> = Omit<
TEntity,
| `${ExtractEntityManyToOneEntityRelationProperties<TEntity> & string}Id`
| ExtractEntityRelatedEntityProperties<TEntity>
| 'application'
| 'workspaceId'
| 'applicationId'
| keyof CastRecordTypeOrmDatePropertiesToString<TEntity>
> &
CastRecordTypeOrmDatePropertiesToString<TEntity> & {
[P in ExtractEntityManyToOneEntityRelationProperties<TEntity> &
string as `${RemoveSuffix<P, 's'>}UniversalIdentifier`]: string;
} & {
[P in ExtractEntityOneToManyEntityRelationProperties<
TEntity,
SyncableEntity
> &
string as `${RemoveSuffix<P, 's'>}UniversalIdentifiers`]: string[];
};
```
This commit is contained in:
-12
@@ -1,12 +0,0 @@
|
||||
import { type Relation } from 'typeorm';
|
||||
|
||||
export type ExtractRecordTypeOrmRelationProperties<T, TRelationTargets> =
|
||||
NonNullable<
|
||||
{
|
||||
[P in keyof T]: NonNullable<T[P]> extends Relation<
|
||||
TRelationTargets | TRelationTargets[]
|
||||
>
|
||||
? P
|
||||
: never;
|
||||
}[keyof T]
|
||||
>;
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
import { type ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { type DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity';
|
||||
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { type IndexFieldMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-field-metadata.entity';
|
||||
import { type IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type FieldPermissionEntity } from 'src/engine/metadata-modules/object-permission/field-permission/field-permission.entity';
|
||||
import { type ObjectPermissionEntity } from 'src/engine/metadata-modules/object-permission/object-permission.entity';
|
||||
import { type ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
|
||||
|
||||
export type MetadataEntitiesRelationTarget =
|
||||
| ObjectMetadataEntity
|
||||
| FieldMetadataEntity
|
||||
| IndexFieldMetadataEntity
|
||||
| FieldPermissionEntity
|
||||
| DataSourceEntity
|
||||
| ApplicationEntity
|
||||
| IndexMetadataEntity
|
||||
| ObjectPermissionEntity
|
||||
| ViewEntity;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
export type RemoveSuffix<
|
||||
T extends string,
|
||||
P extends string,
|
||||
> = T extends `${infer Prefix}${P}` ? Prefix : T;
|
||||
+1
@@ -10,6 +10,7 @@ export type PartialIndexMetadata = Omit<
|
||||
| 'universalIdentifier'
|
||||
| 'application'
|
||||
| 'applicationId'
|
||||
| 'workspace'
|
||||
> & {
|
||||
columns: string[];
|
||||
};
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
import { type ApplicationVariableEntity } from 'src/engine/core-modules/applicationVariable/application-variable.entity';
|
||||
import { type BillingMeterEntity } from 'src/engine/core-modules/billing/entities/billing-meter.entity';
|
||||
import { type BillingPriceEntity } from 'src/engine/core-modules/billing/entities/billing-price.entity';
|
||||
import { type BillingProductEntity } from 'src/engine/core-modules/billing/entities/billing-product.entity';
|
||||
import { type BillingSubscriptionItemEntity } from 'src/engine/core-modules/billing/entities/billing-subscription-item.entity';
|
||||
import { type TwoFactorAuthenticationMethodEntity } from 'src/engine/core-modules/two-factor-authentication/entities/two-factor-authentication-method.entity';
|
||||
import { type UserEntity } from 'src/engine/core-modules/user/user.entity';
|
||||
import { type WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { type AgentMessagePartEntity } from 'src/engine/metadata-modules/ai/ai-agent-execution/entities/agent-message-part.entity';
|
||||
import { type AgentMessageEntity } from 'src/engine/metadata-modules/ai/ai-agent-execution/entities/agent-message.entity';
|
||||
import { type AgentTurnEntity } from 'src/engine/metadata-modules/ai/ai-agent-execution/entities/agent-turn.entity';
|
||||
import { type AgentTurnEvaluationEntity } from 'src/engine/metadata-modules/ai/ai-agent-monitor/entities/agent-turn-evaluation.entity';
|
||||
import { type AgentChatThreadEntity } from 'src/engine/metadata-modules/ai/ai-chat/entities/agent-chat-thread.entity';
|
||||
import { type IndexFieldMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-field-metadata.entity';
|
||||
|
||||
/**
|
||||
* Union of all entities that don't have a direct `workspaceId` field
|
||||
* (i.e., they don't extend `WorkspaceRelatedEntity`).
|
||||
*
|
||||
* This type is used alongside `WorkspaceRelatedEntity` to enable TypeScript
|
||||
* to properly extract entity relation properties for dynamic typing purposes.
|
||||
*
|
||||
* @see ExtractEntityRelatedEntityProperties
|
||||
* @see ExtractEntityManyToOneEntityRelationProperties
|
||||
* @see ExtractEntityOneToManyEntityRelationProperties
|
||||
*/
|
||||
export type AllNonWorkspaceRelatedEntity =
|
||||
| AgentChatThreadEntity
|
||||
| AgentMessagePartEntity
|
||||
| AgentMessageEntity
|
||||
| AgentTurnEntity
|
||||
| AgentTurnEvaluationEntity
|
||||
| IndexFieldMetadataEntity
|
||||
| ApplicationVariableEntity
|
||||
| BillingMeterEntity
|
||||
| BillingPriceEntity
|
||||
| BillingProductEntity
|
||||
| BillingSubscriptionItemEntity
|
||||
| TwoFactorAuthenticationMethodEntity
|
||||
| UserEntity
|
||||
| WorkspaceEntity;
|
||||
+2
-1
@@ -1,11 +1,12 @@
|
||||
import { Column, Index, JoinColumn, ManyToOne, Relation } from 'typeorm';
|
||||
|
||||
import type { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { WorkspaceRelatedEntity } from 'src/engine/workspace-manager/workspace-sync/types/workspace-related-entity';
|
||||
|
||||
@Index(['workspaceId', 'universalIdentifier'], {
|
||||
unique: true,
|
||||
})
|
||||
export abstract class SyncableEntity {
|
||||
export abstract class SyncableEntity extends WorkspaceRelatedEntity {
|
||||
@Column({ nullable: true, type: 'uuid' })
|
||||
// TODO should not be nullable
|
||||
universalIdentifier: string;
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { Column, JoinColumn, ManyToOne, Relation } from 'typeorm';
|
||||
|
||||
import type { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
|
||||
export abstract class WorkspaceRelatedEntity {
|
||||
@Column({ nullable: false, type: 'uuid' })
|
||||
workspaceId: string;
|
||||
|
||||
@ManyToOne('WorkspaceEntity', { onDelete: 'CASCADE' })
|
||||
@JoinColumn({ name: 'workspaceId' })
|
||||
workspace: Relation<WorkspaceEntity>;
|
||||
}
|
||||
Reference in New Issue
Block a user