syncable-entity-types-and-constants

安装量: 35
排名: #19599

安装

npx skills add https://github.com/twentyhq/twenty --skill syncable-entity-types-and-constants
Syncable Entity: Types & Constants (Step 1/6)
Purpose
Define all types, entities, and register in central constants. This is the foundation - everything else depends on these types being correct.
When to use
First step when creating any new syncable entity. Must be completed before other steps.
Quick Start
This step creates:
Metadata name constant (twenty-shared)
TypeORM entity (extends
SyncableEntity
)
Flat entity types
Action types (universal + flat)
Central constant registrations (5 constants)
Step 1: Add Metadata Name
File
:
packages/twenty-shared/src/metadata/all-metadata-name.constant.ts
export
const
ALL_METADATA_NAME
=
{
// ... existing entries
myEntity
:
'myEntity'
,
}
as
const
;
Step 2: Create TypeORM Entity
File
:
src/engine/metadata-modules/my-entity/entities/my-entity.entity.ts
import
{
Entity
,
Column
,
ManyToOne
,
JoinColumn
}
from
'typeorm'
;
import
{
SyncableEntity
}
from
'src/engine/workspace-manager/types/syncable-entity.interface'
;
@
Entity
(
{
name
:
'myEntity'
}
)
export
class
MyEntityEntity
extends
SyncableEntity
{
@
Column
(
{
type
:
'varchar'
}
)
name
:
string
;
@
Column
(
{
type
:
'varchar'
}
)
label
:
string
;
@
Column
(
{
type
:
'boolean'
,
default
:
true
}
)
isCustom
:
boolean
;
// Foreign key example (optional)
@
Column
(
{
type
:
'uuid'
,
nullable
:
true
}
)
parentEntityId
:
string
|
null
;
@
ManyToOne
(
(
)
=>
ParentEntityEntity
,
{
nullable
:
true
}
)
@
JoinColumn
(
{
name
:
'parentEntityId'
}
)
parentEntity
:
ParentEntityEntity
|
null
;
// JSONB column example (optional)
@
Column
(
{
type
:
'jsonb'
,
nullable
:
true
}
)
settings
:
Record
<
string
,
any
>
|
null
;
}
Key rules
:
Must extend
SyncableEntity
(provides
id
,
universalIdentifier
,
applicationId
, etc.)
Must have
isCustom
boolean column
Use
@Column({ type: 'jsonb' })
for JSON data
Step 3: Define Flat Entity Types
File
:
src/engine/metadata-modules/flat-my-entity/types/flat-my-entity.type.ts
import
{
type
FlatEntityFrom
}
from
'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type'
;
import
{
type
MyEntityEntity
}
from
'src/engine/metadata-modules/my-entity/entities/my-entity.entity'
;
export
type
FlatMyEntity
=
FlatEntityFrom
<
MyEntityEntity
>
;
Maps file
(if entity has indexed lookups):
// flat-my-entity-maps.type.ts
export
type
FlatMyEntityMaps
=
{
byId
:
Record
<
string
,
FlatMyEntity
>
;
byName
:
Record
<
string
,
FlatMyEntity
>
;
// Add other indexes as needed
}
;
Step 4: Define Editable Properties
File
:
src/engine/metadata-modules/flat-my-entity/constants/editable-flat-my-entity-properties.constant.ts
export
const
EDITABLE_FLAT_MY_ENTITY_PROPERTIES
=
[
'name'
,
'label'
,
'description'
,
'parentEntityId'
,
'settings'
,
]
as
const
satisfies ReadonlyArray
<
keyof
FlatMyEntity
>
;
Rule
Only include properties that can be updated (exclude id , createdAt , universalIdentifier , etc.) Step 5: Define Action Types File : src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/my-entity/types/workspace-migration-my-entity-action.type.ts import { type FlatMyEntity } from 'src/engine/metadata-modules/flat-my-entity/types/flat-my-entity.type' ; import { type UniversalFlatMyEntity } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-my-entity.type' ; // Universal actions (used by builder/runner) export type UniversalCreateMyEntityAction = { type : 'create' ; metadataName : 'myEntity' ; universalFlatEntity : UniversalFlatMyEntity ; } ; export type UniversalUpdateMyEntityAction = { type : 'update' ; metadataName : 'myEntity' ; universalFlatEntity : UniversalFlatMyEntity ; universalUpdates : Partial < UniversalFlatMyEntity

; } ; export type UniversalDeleteMyEntityAction = { type : 'delete' ; metadataName : 'myEntity' ; universalFlatEntity : UniversalFlatMyEntity ; } ; // Flat actions (internal to runner) export type FlatCreateMyEntityAction = { type : 'create' ; metadataName : 'myEntity' ; flatEntity : FlatMyEntity ; } ; export type FlatUpdateMyEntityAction = { type : 'update' ; metadataName : 'myEntity' ; flatEntity : FlatMyEntity ; updates : Partial < FlatMyEntity

; } ; export type FlatDeleteMyEntityAction = { type : 'delete' ; metadataName : 'myEntity' ; flatEntity : FlatMyEntity ; } ; Step 6: Register in Central Constants 6a. AllFlatEntityTypesByMetadataName File : src/engine/metadata-modules/flat-entity/types/all-flat-entity-types-by-metadata-name.ts export type AllFlatEntityTypesByMetadataName = { // ... existing entries myEntity : { flatEntityMaps : FlatMyEntityMaps ; universalActions : { create : UniversalCreateMyEntityAction ; update : UniversalUpdateMyEntityAction ; delete : UniversalDeleteMyEntityAction ; } ; flatActions : { create : FlatCreateMyEntityAction ; update : FlatUpdateMyEntityAction ; delete : FlatDeleteMyEntityAction ; } ; flatEntity : FlatMyEntity ; universalFlatEntity : UniversalFlatMyEntity ; entity : MyEntityEntity ; } ; } ; 6b. ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME File : src/engine/metadata-modules/flat-entity/constant/all-entity-properties-configuration-by-metadata-name.constant.ts export const ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME = { // ... existing entries myEntity : { name : { toCompare : true } , label : { toCompare : true } , description : { toCompare : true } , parentEntityId : { toCompare : true , universalProperty : 'parentEntityUniversalIdentifier' , } , settings : { toCompare : true , toStringify : true , universalProperty : 'universalSettings' , } , } , } as const ; Rules : toCompare: true → Editable property (checked for changes) toStringify: true → JSONB/object property (needs JSON serialization) universalProperty → Maps to universal version (for foreign keys & JSONB with SerializedRelation ) 6c. ALL_ONE_TO_MANY_METADATA_RELATIONS File : src/engine/metadata-modules/flat-entity/constant/all-one-to-many-metadata-relations.constant.ts This constant is type-checked — values for metadataName , flatEntityForeignKeyAggregator , and universalFlatEntityForeignKeyAggregator are derived from entity type definitions. The aggregator names follow the pattern: remove trailing 's' from the relation property name, then append Ids or UniversalIdentifiers . export const ALL_ONE_TO_MANY_METADATA_RELATIONS = { // ... existing entries myEntity : { // If myEntity has a childEntities: ChildEntityEntity[] property: childEntities : { metadataName : 'childEntity' , flatEntityForeignKeyAggregator : 'childEntityIds' , universalFlatEntityForeignKeyAggregator : 'childEntityUniversalIdentifiers' , } , // null for relations to non-syncable entities someNonSyncableRelation : null , } , } as const ; 6d. ALL_MANY_TO_ONE_METADATA_FOREIGN_KEY File : src/engine/metadata-modules/flat-entity/constant/all-many-to-one-metadata-foreign-key.constant.ts Low-level primitive constant. Only contains foreignKey — the column name ending in Id that stores the foreign key. Type-checked against entity properties. export const ALL_MANY_TO_ONE_METADATA_FOREIGN_KEY = { // ... existing entries myEntity : { workspace : null , application : null , parentEntity : { foreignKey : 'parentEntityId' , } , } , } as const ; 6e. ALL_MANY_TO_ONE_METADATA_RELATIONS File : src/engine/metadata-modules/flat-entity/constant/all-many-to-one-metadata-relations.constant.ts Derived from both ALL_MANY_TO_ONE_METADATA_FOREIGN_KEY (for foreignKey type and universalForeignKey derivation) and ALL_ONE_TO_MANY_METADATA_RELATIONS (for inverseOneToManyProperty key constraint). This is the main constant consumed by utils and optimistic tooling. export const ALL_MANY_TO_ONE_METADATA_RELATIONS = { // ... existing entries myEntity : { workspace : null , application : null , parentEntity : { metadataName : 'parentEntity' , foreignKey : 'parentEntityId' , inverseOneToManyProperty : 'myEntities' , // key in ALL_ONE_TO_MANY_METADATA_RELATIONS['parentEntity'], or null if no inverse isNullable : false , universalForeignKey : 'parentEntityUniversalIdentifier' , } , } , } as const ; Derivation dependency graph : ALL_MANY_TO_ONE_METADATA_FOREIGN_KEY ALL_ONE_TO_MANY_METADATA_RELATIONS (foreignKey only) (metadataName, aggregators) │ │ │ FK type + universalFK derivation │ inverseOneToManyProperty keys │ │ └────────────────┬───────────────────────┘ ▼ ALL_MANY_TO_ONE_METADATA_RELATIONS (metadataName, foreignKey, inverseOneToManyProperty, isNullable, universalForeignKey) Rules : workspace: null , application: null — always present, always null (non-syncable relations) inverseOneToManyProperty — must be a key in ALL_ONE_TO_MANY_METADATA_RELATIONS[targetMetadataName] , or null if the target entity doesn't expose an inverse one-to-many relation universalForeignKey — derived from foreignKey by replacing the Id suffix with UniversalIdentifier Optimistic utils resolve flatEntityForeignKeyAggregator / universalFlatEntityForeignKeyAggregator at runtime by looking up inverseOneToManyProperty in ALL_ONE_TO_MANY_METADATA_RELATIONS Checklist Before moving to Step 2: Metadata name added to ALL_METADATA_NAME TypeORM entity created (extends SyncableEntity ) isCustom column added Flat entity type defined Flat entity maps type defined (if needed) Editable properties constant defined Universal and flat action types defined Registered in AllFlatEntityTypesByMetadataName Registered in ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME Registered in ALL_ONE_TO_MANY_METADATA_RELATIONS (if entity has one-to-many relations) Registered in ALL_MANY_TO_ONE_METADATA_FOREIGN_KEY Registered in ALL_MANY_TO_ONE_METADATA_RELATIONS TypeScript compiles without errors Next Step Once all types and constants are defined, proceed to: Syncable Entity: Cache & Transform (Step 2/6) For complete workflow, see @creating-syncable-entity rule.

返回排行榜