import assert = require ( 'assert' ) ; export interface Node { readonly name : string ; details : Map < string , object > ; } export abstract class NodeImpl implements Node { private readonly _name : string ; private readonly _details : Map < string , object > ; public get name ( ) : string { return this . _name ; } public get details ( ) : Map < string , object > { return this . _details ; } constructor ( name , details ) { this . _name = name ; this . _details = details ; } public abstract getAdjacency ( ) ; public abstract addEdge ( dest ) ; public abstract combineWith ( rhs ) ; } export class ScalarNode extends NodeImpl { private edges : Map < string , Node > = new Map < string , Node > ( ) ; constructor ( name , details ) { super ( name , details ) ; } public addEdge ( dest ) { if ( ! this . edges . has ( dest . name ) ) { this . edges . set ( dest . name , dest ) ; } } public getEdges ( ) { return this . edges . values ( ) ; } public getAdjacency ( ) { return this . edges ; } public combineWith ( rhs ) { if ( rhs instanceof NodeGroup ) { return rhs . combineWith ( this ) ; } const ng = new NodeGroup ( ) ; ng . addNode ( this ) ; ng . addNode ( rhs ) ; return ng ; } } export class NodeGroup extends NodeImpl { private readonly _nodes : Set < ScalarNode > = new Set < ScalarNode > ( ) ; private adjacencyCache : Map < string , ScalarNode > ; constructor ( ) { super ( 'NodeGroup' , undefined ) ; } public get name ( ) : string { return Array . from ( this . nodes ) . map ( node => node . name ) . sort ( ) . join ( ', ' ) ; } get nodes ( ) : Set < ScalarNode > { return this . _nodes ; } public get details ( ) : Map < string , object > { const ret = new Map < string , object > ( ) ; this . nodes . forEach ( element => { Array . from ( element . details . entries ( ) ) . forEach ( detail => { ret . set ( detail [ 0 ] , detail [ 1 ] ) ; } ) ; } ) ; return ret ; } public addEdge ( dest ) { throw new Error ( 'Don\'t add edges to combined nodes' ) ; } public getAdjacency ( ) { if ( this . adjacencyCache ) { return this . adjacencyCache as Map < string , Node > ; } this . adjacencyCache = new Map < string , ScalarNode > ( ) ; this . nodes . forEach ( element => { element . getAdjacency ( ) . forEach ( n => { if ( element === n || ! this . nodes . has ( n as ScalarNode ) ) { this . adjacencyCache . set ( n . name , n as ScalarNode ) ; } } ) ; } ) ; return this . adjacencyCache ; } public combineWith ( rhs ) { if ( rhs instanceof ScalarNode ) { this . addNode ( rhs ) ; this . adjacencyCache = null ; return this ; } assert . ok ( rhs instanceof NodeGroup ) ; ( rhs as NodeGroup ) . nodes . forEach ( element => { this . nodes . add ( element ) ; } ) ; return rhs as NodeGroup ; } public addNode ( node ) { assert . ok ( node as ScalarNode ) ; this . nodes . add ( node as ScalarNode ) ; } } export type Edge = { from : string ; to : string ; } ; export interface Record { Id ? : string ; } export interface MetadataComponentDependency extends Record { MetadataComponentId : string ; MetadataComponentName : string ; MetadataComponentType : string ; RefMetadataComponentId : string ; RefMetadataComponentName : string ; RefMetadataComponentType : string ; } export interface CustomField extends Record { TableEnumOrId : string ; } export interface ValidationRule extends Record { EntityDefinitionId : string ; } export interface CustomObject extends Record { DeveloperName : string ; } export interface QuickAction extends Record { SobjectType : string ; } export interface FieldDefinition { DurableId : string ; DataType : string ; EntityDefinitionId : string ; } export type ComponentNode = { id : string ; name : string ; type : string ; parent : string ; } ;