import { FactRecord , FactReference , factReferenceEquals } from '../storage' ; type StoreInspector = { [ type ] : { count : number ; } ; } ; type FactInspector = { type : string ; fields : { } ; predecessors : PredecessorInspector ; } ; type PredecessorInspector = { [ role ] : ( { } | { } [ ] ) ; } ; type SuccessorInspector = { [ role ] : FactInspector [ ] ; } ; export class Inspector { constructor ( private factRecords ) { } inspect ( ) { return this . factRecords . reduce ( ( inspector , record ) => { let typeInspector = inspector [ record . type ] ; if ( ! typeInspector ) { typeInspector = this . createTypeInspector ( record . type ) ; inspector [ record . type ] = typeInspector ; } typeInspector . count ++ ; return inspector ; } , { } ) ; } private createTypeInspector ( type ) { const typeInspector = { count : 0 } ; Object . defineProperty ( typeInspector , 'facts' , { enumerable : true , get : ( ) => { return this . getFactsByType ( type ) ; } } ) ; return typeInspector ; } private getFactsByType ( type ) { return ( this . factRecords . filter ( record => record . type === type ) . map ( record => { return this . createFactInspector ( record ) ; } ) ) ; } private createFactInspector ( record ) { const factInspector = { type : record . type , fields : record . fields , predecessors : this . getPredecessors ( record ) } ; Object . defineProperty ( factInspector , 'successors' , { enumerable : true , get : ( ) => { return this . getSuccessors ( record ) ; } } ) ; return factInspector ; } private getPredecessors ( record ) { const inspector = { } ; for ( const role in record . predecessors ) { const predecessors = record . predecessors [ role ] ; if ( Array . isArray ( predecessors ) ) { inspector [ role ] = predecessors . map ( p => { return this . createReferenceInspector ( p ) ; } ) ; } else { inspector [ role ] = this . createReferenceInspector ( predecessors ) ; } } return inspector ; } private getSuccessors ( reference ) { return this . factRecords . reduce ( ( inspector , record ) => { for ( const role in record . predecessors ) { let predecessors = record . predecessors [ role ] ; if ( ! Array . isArray ( predecessors ) ) { predecessors = [ predecessors ] ; } if ( predecessors . some ( factReferenceEquals ( reference ) ) ) { let successors = inspector [ role ] ; if ( ! successors ) { successors = [ ] ; inspector [ role ] = successors ; } successors . push ( this . createFactInspector ( record ) ) ; } } return inspector ; } , { } ) ; } private createReferenceInspector ( reference ) { const inspector = { } ; Object . defineProperty ( inspector , 'fact' , { enumerable : true , get : ( ) => { return this . createFactInspector ( this . findFact ( reference ) ) ; } } ) ; return inspector ; } private findFact ( reference ) { return this . factRecords . find ( factReferenceEquals ( reference ) ) ; } }