UNPKG

@wearesage/schema

Version:

A flexible schema definition and validation system for TypeScript with multi-database support

146 lines (112 loc) 4.6 kB
import { Affordance } from './Affordance'; import { CodeFile } from './CodeFile'; import { ContextRule } from './ContextRule'; import { Entity, Property, Id, ManyToOne, OneToMany, ManyToMany, Index, Timestamp, Auth, Labels } from '../core/decorators'; import { Event } from './Event'; import { RelationshipType } from '../adapters/neo4j'; import { SpaceType, SpaceTypeString } from '../test-types/space.types'; import { Team } from './Team'; import { User } from './User'; @Entity() @Labels(['Space']) @Auth({ permissions: ['user'] }) // Users can access spaces they participate in export class Space { @Id() id!: string; @Property({ required: true }) @Index() name!: string; @Property() description?: string; @Property({ required: true }) @Index() spaceType!: SpaceTypeString; // Ownership can be by User or Team @Property({ required: true }) ownedByType!: 'user' | 'team'; @Property({ required: true }) ownedById!: string; // Direct relationship to owner (User) @ManyToOne({ target: () => User, inverse: 'ownedSpaces', neo4j: { type: 'OWNED_BY', direction: 'OUT' } }) @RelationshipType('OWNED_BY') owner?: User; // Direct relationship to team @ManyToOne({ target: () => Team, inverse: 'spaces', neo4j: { type: 'BELONGS_TO_TEAM', direction: 'OUT' } }) @RelationshipType('BELONGS_TO_TEAM') team?: Team; // Users who participate in this space @ManyToMany({ target: () => User, inverse: 'participatingSpaces', neo4j: { type: 'PARTICIPATES_IN', direction: 'IN' } }) @RelationshipType('PARTICIPATES_IN') participants!: User[]; @Property({ required: true }) visibility!: 'public' | 'private'; // Recursive relationship - parent space @ManyToOne({ target: () => Space, inverse: 'childSpaces', neo4j: { type: 'CONTAINED_BY', direction: 'OUT' } }) @RelationshipType('CONTAINED_BY') parentSpace?: Space; // Recursive relationship - child spaces @OneToMany({ target: () => Space, inverse: 'parentSpace', neo4j: { type: 'CONTAINS', direction: 'OUT' } }) @RelationshipType('CONTAINS') childSpaces!: Space[]; // Entrypoint properties - for spaces that serve as system entry points @Property() isEntrypoint?: boolean; @Property() entrypointType?: 'auth' | 'main' | 'admin' | 'guest' | 'api'; @Property() targetUserState?: 'unauthenticated' | 'authenticated' | 'admin' | 'any'; @Property() transitionRules?: { onSuccess?: { action: 'redirect' | 'stay', target?: string, message?: string }; onFailure?: { action: 'stay' | 'exit', message?: string }; }; // Status tracking for relevant space types @Property() status?: 'pending' | 'active' | 'blocked' | 'completed' | 'failed'; @Property() attemptCount: number = 0; // Universal Space features - Context System @OneToMany({ target: () => ContextRule, inverse: 'space' }) contextRules!: ContextRule[]; // Universal Space features - Affordance System @OneToMany({ target: () => Affordance, inverse: 'space' }) availableAffordances!: Affordance[]; // GRAPH RELATIONSHIPS - Code dependencies discovered via static analysis @ManyToMany({ target: () => Space, neo4j: { type: 'IMPORTS', direction: 'OUT' } }) @RelationshipType('IMPORTS') imports!: Space[]; @ManyToMany({ target: () => Space, neo4j: { type: 'EXPORTS_TO', direction: 'OUT' } }) @RelationshipType('EXPORTS_TO') exportedTo!: Space[]; @ManyToMany({ target: () => Space, neo4j: { type: 'CALLS', direction: 'OUT' } }) @RelationshipType('CALLS') calls!: Space[]; @ManyToMany({ target: () => Space, neo4j: { type: 'TESTS', direction: 'OUT' } }) @RelationshipType('TESTS') tests!: Space[]; @ManyToMany({ target: () => Space, neo4j: { type: 'DEPENDS_ON', direction: 'OUT' } }) @RelationshipType('DEPENDS_ON') dependencies!: Space[]; @ManyToMany({ target: () => Space, neo4j: { type: 'DEPLOYS_TO', direction: 'OUT' } }) @RelationshipType('DEPLOYS_TO') deploysTo!: Space[]; // Legacy: Context subscriptions - what events this space listens to @Property() subscribedEvents: string[] = []; // Absolute path for project-related spaces @Property() projectPath?: string; // Flexible metadata for type-specific data @Property() metadata: Record<string, any> = {}; // Events related to this space @OneToMany({ target: () => Event, inverse: 'space' }) events!: Event[]; // Code files in this space (for codebase spaces) @OneToMany({ target: () => CodeFile, inverse: 'space' }) files!: CodeFile[]; @Timestamp({ onCreate: true }) createdAt!: Date; @Timestamp({ onUpdate: true }) updatedAt!: Date; }