@@ -133,8 +133,8 @@ export class Memory {
133133 }
134134}
135135
136- export interface DeepEvent {
137- name : 'change' ;
136+ export interface Event {
137+ name : 'change' | 'new' | 'kill' | 'add' | 'remove' ;
138138 deep : Deep ;
139139 prev : {
140140 id ?: string ;
@@ -890,8 +890,8 @@ export class Deep {
890890 field ?: 'id' | 'type' | 'from' | 'to' | 'value' ,
891891 previousValue ?: any ,
892892 currentValue ?: any
893- ) : DeepEvent {
894- const event : DeepEvent = {
893+ ) : Event {
894+ const event : Event = {
895895 name : 'change' ,
896896 deep : this ,
897897 prev : { } ,
@@ -909,7 +909,7 @@ export class Deep {
909909 /**
910910 * Gets the deep.Id instance .to this Deep instance .from current this.deep agent. If no ID is set, one will be created.
911911 * @param value - Optional ID value
912- * @param agent - Optional agent Deep instance
912+ * @param agent - Optional agent Deep instance, default this.deep
913913 * @returns ID value
914914 */
915915 id ( value ?: string , agent : Deep = this . deep ) : string {
@@ -1483,7 +1483,7 @@ export class Deep {
14831483 relation . from = selection ;
14841484 relation . to = nestedSelection ;
14851485 relation . value = i ;
1486- relation . on ( ( e ) => selection . emit ( e ) ) ;
1486+ relation . on ( ( e : Event ) => selection . emit ( e ) ) ;
14871487 }
14881488 } else {
14891489 exp = this . deep . Exp . new ( { } ) ;
@@ -1493,7 +1493,7 @@ export class Deep {
14931493 const relation = this . deep . __id . new ( ) ;
14941494 relation . from = selection ;
14951495 relation . to = input . id ;
1496- relation . on ( ( e ) => selection . emit ( e ) ) ;
1496+ relation . on ( ( e : Event ) => selection . emit ( e ) ) ;
14971497 } else throw new Error ( ` Only Deep or string can be value in exp (id)!` ) ;
14981498 }
14991499 for ( let key in this . deep . contains . relations . call ) {
@@ -1503,11 +1503,11 @@ export class Deep {
15031503 const nestedSelection = this . selection ( ) ;
15041504 this . exp ( input [ key ] , nestedSelection ) ;
15051505 exp . call [ key ] = nestedSelection ;
1506- nestedSelection . on ( ( e ) => relation . emit ( e ) ) ;
1506+ nestedSelection . on ( ( e : Event ) => relation . emit ( e ) ) ;
15071507 } else throw new Error ( ` Only Deep or plain objects Exp can be value in exp (${ key } )!` ) ;
15081508 relation . from = selection ;
15091509 relation . to = exp . call [ key ] ; // nestedSelection
1510- relation . on ( ( e ) => selection . emit ( e ) ) ;
1510+ relation . on ( ( e : Event ) => selection . emit ( e ) ) ;
15111511 }
15121512 }
15131513 for ( let logic of this . deep . Logic . typed ) {
@@ -1519,7 +1519,7 @@ export class Deep {
15191519 exp . call [ logic . name ] = nestedSelection ;
15201520 relation . from = selection ;
15211521 relation . to = exp . call [ logic . name ] ;
1522- relation . on ( ( e ) => selection . emit ( e ) ) ;
1522+ relation . on ( ( e : Event ) => selection . emit ( e ) ) ;
15231523 }
15241524 }
15251525 }
@@ -1533,52 +1533,56 @@ export class Deep {
15331533 selection ( ) {
15341534 const rels = this . deep . contains . relations . call ;
15351535 const selection = this . deep . Selection . new ( ( ) => {
1536- const relations = selection . out ;
1536+ const inRelations = selection . inof ( this . deep . Relation ) ;
1537+ const outRelations = selection . outof ( this . deep . Relation ) ;
15371538 let set ;
1538- for ( let relation of relations ) {
1539- if ( relation . typeof ( this . deep . Relation ) ) {
1540- if ( relation . typeof ( this . deep . __id ) ) {
1541- if ( isDeep ( relation . to ) ) {
1542- set = set ? set . intersection ( new Set ( [ relation . to ] ) ) : new Set ( [ relation . to ] ) ;
1543- } else if ( isString ( relation . to . call ) ) {
1544- throw new Error ( ' Sorry not relized yet.' ) ;
1545- } else throw new Error ( ' Only Deep and string can be .id' ) ;
1546- } else if ( relation . typeof ( this . deep . Many ) ) {
1547- const nextSet = relation . to . call ( ) [ `${ rels [ relation . type . name ] . invert } s` ] . call ;
1548- set = set ? set . intersection ( nextSet ) : nextSet ;
1549- } else if ( relation . typeof ( this . deep . One ) ) {
1550- const nextSet = relation . to . type === this . deep . Selection ?
1551- relation . to . call ( ) . reduce ( ( result , d ) => result . union ( d [ rels [ relation . type . name ] . invert ] . call ) , new Set ( ) ) :
1552- relation . to [ rels [ relation . type . name ] . invert ] . call ;
1553- set = set ? set . intersection ( nextSet ) : nextSet ;
1554- } else if ( relation . typeof ( this . deep . Condition ) ) {
1555-
1556- } else if ( relation . typeof ( this . deep . Logic ) ) {
1557- if ( relation . typeof ( this . deep . contains . not ) ) {
1558- const currentSet = set || this . deep . Everything . call ;
1559- const notSet = relation . to . call ( ) . call ;
1560- set = currentSet . difference ( notSet ) ;
1561- } else if ( relation . typeof ( this . deep . contains . and ) ) {
1562- const currentSet = set || this . deep . Everything . call ;
1563- const arrayOfSets = relation . to . call ( ) ;
1564- set = arrayOfSets . reduce ( ( result , set ) => {
1565- return result . intersection ( set . call ) ;
1566- } , currentSet ) ;
1567- } else if ( relation . typeof ( this . deep . contains . or ) ) {
1568- const arrayOfSets = relation . to . call ( ) ;
1569- set = arrayOfSets . reduce ( ( result , item ) => {
1570- const itemSet = item . call ;
1571- return result ? new Set ( [ ...result , ...itemSet ] ) : itemSet ;
1572- } , set ) ;
1573- }
1574- } else if ( relation . typeof ( this . deep . Order ) ) {
1575- const nextSet = relation . to . call ( ) ;
1576- set = set ? ( set . push ( nextSet ) , set ) : [ nextSet ] ;
1539+ for ( let relation of outRelations ) {
1540+ if ( relation . typeof ( this . deep . __id ) ) {
1541+ if ( isDeep ( relation . to ) ) {
1542+ set = set ? set . intersection ( new Set ( [ relation . to ] ) ) : new Set ( [ relation . to ] ) ;
1543+ } else if ( isString ( relation . to . call ) ) {
1544+ throw new Error ( ' Sorry not relized yet.' ) ;
1545+ } else throw new Error ( ' Only Deep and string can be .id' ) ;
1546+ } else if ( relation . typeof ( this . deep . Many ) ) {
1547+ const nextSet = relation . to . call ( ) [ `${ rels [ relation . type . name ] . invert } s` ] . call ;
1548+ set = set ? set . intersection ( nextSet ) : nextSet ;
1549+ } else if ( relation . typeof ( this . deep . One ) ) {
1550+ const nextSet = relation . to . type === this . deep . Selection ?
1551+ relation . to . call ( ) . reduce ( ( result , d ) => result . union ( d [ rels [ relation . type . name ] . invert ] . call ) , new Set ( ) ) :
1552+ relation . to [ rels [ relation . type . name ] . invert ] . call ;
1553+ set = set ? set . intersection ( nextSet ) : nextSet ;
1554+ } else if ( relation . typeof ( this . deep . Condition ) ) {
1555+
1556+ } else if ( relation . typeof ( this . deep . Logic ) ) {
1557+ if ( relation . typeof ( this . deep . contains . not ) ) {
1558+ const currentSet = set || this . deep . Everything . call ;
1559+ const notSet = relation . to . call ( ) . call ;
1560+ set = currentSet . difference ( notSet ) ;
1561+ } else if ( relation . typeof ( this . deep . contains . and ) ) {
1562+ const currentSet = set || this . deep . Everything . call ;
1563+ const arrayOfSets = relation . to . call ( ) ;
1564+ set = arrayOfSets . reduce ( ( result , set ) => {
1565+ return result . intersection ( set . call ) ;
1566+ } , currentSet ) ;
1567+ } else if ( relation . typeof ( this . deep . contains . or ) ) {
1568+ const arrayOfSets = relation . to . call ( ) ;
1569+ set = arrayOfSets . reduce ( ( result , item ) => {
1570+ const itemSet = item . call ;
1571+ return result ? new Set ( [ ...result , ...itemSet ] ) : itemSet ;
1572+ } , set ) ;
15771573 }
1574+ } else if ( relation . typeof ( this . deep . Order ) ) {
1575+ const nextSet = relation . to . call ( ) ;
1576+ set = set ? ( set . push ( nextSet ) , set ) : [ nextSet ] ;
15781577 }
15791578 }
15801579 if ( ! set ) set = this . deep . Everything . call ;
15811580 const result = this . wrap ( set ) ;
1581+ if ( ! inRelations . size ) {
1582+ const oldSet = selection . to ?. call || new Set ( ) ;
1583+ const newSet = result . call ;
1584+ this . emitDifference ( oldSet , newSet , selection ) ;
1585+ }
15821586 selection . to = result ;
15831587 return selection . to ;
15841588 } ) ;
@@ -1603,6 +1607,40 @@ export class Deep {
16031607 return selection ;
16041608 }
16051609
1610+ /**
1611+ * Emits difference events between two sets
1612+ * @param before - Set of items before change
1613+ * @param after - Set of items after change
1614+ * @param target - Deep instance to emit events on
1615+ */
1616+ public emitDifference ( before : Set < Deep > , after : Set < Deep > , target : Deep ) : void {
1617+ // Find added elements (present in after, not in before)
1618+ for ( const item of after ) {
1619+ if ( ! before . has ( item ) ) {
1620+ const event : Event = {
1621+ name : 'add' ,
1622+ deep : item ,
1623+ prev : { value : null } ,
1624+ next : { value : item }
1625+ } ;
1626+ target . emit ( event ) ;
1627+ }
1628+ }
1629+
1630+ // Find removed elements (present in before, not in after)
1631+ for ( const item of before ) {
1632+ if ( ! after . has ( item ) ) {
1633+ const event : Event = {
1634+ name : 'remove' ,
1635+ deep : item ,
1636+ prev : { value : item } ,
1637+ next : { value : null }
1638+ } ;
1639+ target . emit ( event ) ;
1640+ }
1641+ }
1642+ }
1643+
16061644 /**
16071645 * Gets, or creates if not exists the event emitter for this Deep instance
16081646 * @returns Event emitter instance
@@ -1616,8 +1654,14 @@ export class Deep {
16161654 * Emits an event from this Deep instance
16171655 * @param args - Event arguments
16181656 */
1619- emit ( ...args ) {
1620- if ( this . _on ) this . _on . emit ( ...args ) ;
1657+ emit ( ...args : any [ ] ) : void {
1658+ if ( this . _on ) {
1659+ const event = args [ 0 ] ;
1660+ if ( typeof event === 'object' && ! event . deep ) {
1661+ event . deep = this ;
1662+ }
1663+ this . _on . emit ( ...args ) ;
1664+ }
16211665 }
16221666
16231667 /**
@@ -1628,7 +1672,7 @@ export class Deep {
16281672 inof ( type : Deep ) : Deep {
16291673 const result = new Set < Deep > ( ) ;
16301674 for ( const link of this . in . call ) {
1631- if ( link . type === type ) {
1675+ if ( link . typeof ( type ) ) {
16321676 result . add ( link ) ;
16331677 }
16341678 }
@@ -1643,7 +1687,7 @@ export class Deep {
16431687 outof ( type : Deep ) : Deep {
16441688 const result = new Set < Deep > ( ) ;
16451689 for ( const link of this . out . call ) {
1646- if ( link . type === type ) {
1690+ if ( link . typeof ( type ) ) {
16471691 result . add ( link ) ;
16481692 }
16491693 }
@@ -1925,9 +1969,9 @@ export class Deep {
19251969 }
19261970
19271971 /**
1928- * Проходит по пути из строк через contains и возвращает найденный deep или undefined
1929- * @param paths массив строк, представляющих путь через contains
1930- * @returns найденный deep или undefined
1972+ * Proceeds along the path through strings through contains and returns the found deep or undefined
1973+ * @param paths array of strings representing the path through contains
1974+ * @returns found deep or undefined
19311975 */
19321976 go ( ...paths : string [ ] ) : Deep | undefined {
19331977 let current : Deep = this ;
@@ -1939,8 +1983,8 @@ export class Deep {
19391983 }
19401984
19411985 /**
1942- * Возвращает путь к текущему deep через входящие Contain связи
1943- * @returns массив строк - путь через contains
1986+ * Returns the path to the current deep through incoming Contain connections
1987+ * @returns array of strings - path through contains
19441988 */
19451989 path ( ) : string [ ] {
19461990 const result : string [ ] = [ ] ;
@@ -1954,7 +1998,7 @@ export class Deep {
19541998 const contain = contains . first ;
19551999 if ( ! contain ) break ;
19562000
1957- // Находим ключ в contains, по которому хранится текущий deep
2001+ // Find the key in contains where the current deep is stored
19582002 const from = contain . from ;
19592003 if ( ! from ) break ;
19602004
@@ -2013,3 +2057,7 @@ export class Contains {
20132057 this . deep = deep ;
20142058 }
20152059}
2060+
2061+ // Global instance of Deep
2062+ export const deep = new Deep ( ) ;
2063+ export default deep ;
0 commit comments