@@ -133,8 +133,8 @@ export class Memory {
133
133
}
134
134
}
135
135
136
- export interface DeepEvent {
137
- name : 'change' ;
136
+ export interface Event {
137
+ name : 'change' | 'new' | 'kill' | 'add' | 'remove' ;
138
138
deep : Deep ;
139
139
prev : {
140
140
id ?: string ;
@@ -890,8 +890,8 @@ export class Deep {
890
890
field ?: 'id' | 'type' | 'from' | 'to' | 'value' ,
891
891
previousValue ?: any ,
892
892
currentValue ?: any
893
- ) : DeepEvent {
894
- const event : DeepEvent = {
893
+ ) : Event {
894
+ const event : Event = {
895
895
name : 'change' ,
896
896
deep : this ,
897
897
prev : { } ,
@@ -909,7 +909,7 @@ export class Deep {
909
909
/**
910
910
* Gets the deep.Id instance .to this Deep instance .from current this.deep agent. If no ID is set, one will be created.
911
911
* @param value - Optional ID value
912
- * @param agent - Optional agent Deep instance
912
+ * @param agent - Optional agent Deep instance, default this.deep
913
913
* @returns ID value
914
914
*/
915
915
id ( value ?: string , agent : Deep = this . deep ) : string {
@@ -1483,7 +1483,7 @@ export class Deep {
1483
1483
relation . from = selection ;
1484
1484
relation . to = nestedSelection ;
1485
1485
relation . value = i ;
1486
- relation . on ( ( e ) => selection . emit ( e ) ) ;
1486
+ relation . on ( ( e : Event ) => selection . emit ( e ) ) ;
1487
1487
}
1488
1488
} else {
1489
1489
exp = this . deep . Exp . new ( { } ) ;
@@ -1493,7 +1493,7 @@ export class Deep {
1493
1493
const relation = this . deep . __id . new ( ) ;
1494
1494
relation . from = selection ;
1495
1495
relation . to = input . id ;
1496
- relation . on ( ( e ) => selection . emit ( e ) ) ;
1496
+ relation . on ( ( e : Event ) => selection . emit ( e ) ) ;
1497
1497
} else throw new Error ( ` Only Deep or string can be value in exp (id)!` ) ;
1498
1498
}
1499
1499
for ( let key in this . deep . contains . relations . call ) {
@@ -1503,11 +1503,11 @@ export class Deep {
1503
1503
const nestedSelection = this . selection ( ) ;
1504
1504
this . exp ( input [ key ] , nestedSelection ) ;
1505
1505
exp . call [ key ] = nestedSelection ;
1506
- nestedSelection . on ( ( e ) => relation . emit ( e ) ) ;
1506
+ nestedSelection . on ( ( e : Event ) => relation . emit ( e ) ) ;
1507
1507
} else throw new Error ( ` Only Deep or plain objects Exp can be value in exp (${ key } )!` ) ;
1508
1508
relation . from = selection ;
1509
1509
relation . to = exp . call [ key ] ; // nestedSelection
1510
- relation . on ( ( e ) => selection . emit ( e ) ) ;
1510
+ relation . on ( ( e : Event ) => selection . emit ( e ) ) ;
1511
1511
}
1512
1512
}
1513
1513
for ( let logic of this . deep . Logic . typed ) {
@@ -1519,7 +1519,7 @@ export class Deep {
1519
1519
exp . call [ logic . name ] = nestedSelection ;
1520
1520
relation . from = selection ;
1521
1521
relation . to = exp . call [ logic . name ] ;
1522
- relation . on ( ( e ) => selection . emit ( e ) ) ;
1522
+ relation . on ( ( e : Event ) => selection . emit ( e ) ) ;
1523
1523
}
1524
1524
}
1525
1525
}
@@ -1533,52 +1533,56 @@ export class Deep {
1533
1533
selection ( ) {
1534
1534
const rels = this . deep . contains . relations . call ;
1535
1535
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 ) ;
1537
1538
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 ) ;
1577
1573
}
1574
+ } else if ( relation . typeof ( this . deep . Order ) ) {
1575
+ const nextSet = relation . to . call ( ) ;
1576
+ set = set ? ( set . push ( nextSet ) , set ) : [ nextSet ] ;
1578
1577
}
1579
1578
}
1580
1579
if ( ! set ) set = this . deep . Everything . call ;
1581
1580
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
+ }
1582
1586
selection . to = result ;
1583
1587
return selection . to ;
1584
1588
} ) ;
@@ -1603,6 +1607,40 @@ export class Deep {
1603
1607
return selection ;
1604
1608
}
1605
1609
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
+
1606
1644
/**
1607
1645
* Gets, or creates if not exists the event emitter for this Deep instance
1608
1646
* @returns Event emitter instance
@@ -1616,8 +1654,14 @@ export class Deep {
1616
1654
* Emits an event from this Deep instance
1617
1655
* @param args - Event arguments
1618
1656
*/
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
+ }
1621
1665
}
1622
1666
1623
1667
/**
@@ -1628,7 +1672,7 @@ export class Deep {
1628
1672
inof ( type : Deep ) : Deep {
1629
1673
const result = new Set < Deep > ( ) ;
1630
1674
for ( const link of this . in . call ) {
1631
- if ( link . type === type ) {
1675
+ if ( link . typeof ( type ) ) {
1632
1676
result . add ( link ) ;
1633
1677
}
1634
1678
}
@@ -1643,7 +1687,7 @@ export class Deep {
1643
1687
outof ( type : Deep ) : Deep {
1644
1688
const result = new Set < Deep > ( ) ;
1645
1689
for ( const link of this . out . call ) {
1646
- if ( link . type === type ) {
1690
+ if ( link . typeof ( type ) ) {
1647
1691
result . add ( link ) ;
1648
1692
}
1649
1693
}
@@ -1925,9 +1969,9 @@ export class Deep {
1925
1969
}
1926
1970
1927
1971
/**
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
1931
1975
*/
1932
1976
go ( ...paths : string [ ] ) : Deep | undefined {
1933
1977
let current : Deep = this ;
@@ -1939,8 +1983,8 @@ export class Deep {
1939
1983
}
1940
1984
1941
1985
/**
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
1944
1988
*/
1945
1989
path ( ) : string [ ] {
1946
1990
const result : string [ ] = [ ] ;
@@ -1954,7 +1998,7 @@ export class Deep {
1954
1998
const contain = contains . first ;
1955
1999
if ( ! contain ) break ;
1956
2000
1957
- // Находим ключ в contains, по которому хранится текущий deep
2001
+ // Find the key in contains where the current deep is stored
1958
2002
const from = contain . from ;
1959
2003
if ( ! from ) break ;
1960
2004
@@ -2013,3 +2057,7 @@ export class Contains {
2013
2057
this . deep = deep ;
2014
2058
}
2015
2059
}
2060
+
2061
+ // Global instance of Deep
2062
+ export const deep = new Deep ( ) ;
2063
+ export default deep ;
0 commit comments