@rs-x/state-manager 0.4.12 → 0.4.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/readme.md +594 -505
package/readme.md
CHANGED
|
@@ -226,8 +226,8 @@ Monitors only assignment of a **new value** to the index.
|
|
|
226
226
|
```ts
|
|
227
227
|
import { InjectionContainer, printValue } from '@rs-x/core';
|
|
228
228
|
import {
|
|
229
|
-
IStateChange,
|
|
230
|
-
IStateManager,
|
|
229
|
+
type IStateChange,
|
|
230
|
+
type IStateManager,
|
|
231
231
|
RsXStateManagerInjectionTokens,
|
|
232
232
|
RsXStateManagerModule,
|
|
233
233
|
} from '@rs-x/state-manager';
|
|
@@ -240,7 +240,7 @@ export const run = (() => {
|
|
|
240
240
|
RsXStateManagerInjectionTokens.IStateManager,
|
|
241
241
|
);
|
|
242
242
|
|
|
243
|
-
const
|
|
243
|
+
const model = {
|
|
244
244
|
x: { y: 10 },
|
|
245
245
|
};
|
|
246
246
|
|
|
@@ -254,24 +254,24 @@ export const run = (() => {
|
|
|
254
254
|
|
|
255
255
|
try {
|
|
256
256
|
// This will emit the new value { y: 10 }
|
|
257
|
-
stateManager.watchState(
|
|
257
|
+
stateManager.watchState(model, 'x');
|
|
258
258
|
|
|
259
259
|
console.log('Changed value:');
|
|
260
260
|
// This will emit the new value { y: 10 }
|
|
261
|
-
|
|
261
|
+
model.x = {
|
|
262
262
|
y: 20,
|
|
263
263
|
};
|
|
264
264
|
|
|
265
265
|
console.log(`Latest value:`);
|
|
266
|
-
printValue(stateManager.getState(
|
|
266
|
+
printValue(stateManager.getState(model, 'x'));
|
|
267
267
|
|
|
268
268
|
// This will emit no change because the state is not recursive.
|
|
269
|
-
console.log('\
|
|
270
|
-
|
|
269
|
+
console.log('\nmodel.x.y = 30 will not emit any change:\n---\n');
|
|
270
|
+
model.x.y = 30;
|
|
271
271
|
} finally {
|
|
272
272
|
changedSubsription.unsubscribe();
|
|
273
273
|
// Always release the state when it is no longer needed.
|
|
274
|
-
stateManager.releaseState(
|
|
274
|
+
stateManager.releaseState(model, 'x');
|
|
275
275
|
}
|
|
276
276
|
})();
|
|
277
277
|
```
|
|
@@ -305,12 +305,13 @@ Monitors assignments **and** changes _inside_ the value.
|
|
|
305
305
|
Example: if the value is an object, internal object changes are also observed. You can make a state item recursive by passing in a **mustProxify** predicate to a **watchState** call. The mustProxify will be called for every nested index. If you return true it will watch the index otherwise not.
|
|
306
306
|
|
|
307
307
|
```ts
|
|
308
|
-
import { InjectionContainer, printValue
|
|
308
|
+
import { InjectionContainer, printValue } from '@rs-x/core';
|
|
309
309
|
import {
|
|
310
|
-
IStateChange,
|
|
311
|
-
IStateManager,
|
|
310
|
+
type IStateChange,
|
|
311
|
+
type IStateManager,
|
|
312
312
|
RsXStateManagerInjectionTokens,
|
|
313
313
|
RsXStateManagerModule,
|
|
314
|
+
watchIndexRecursiveRule,
|
|
314
315
|
} from '@rs-x/state-manager';
|
|
315
316
|
|
|
316
317
|
// Load the state manager module into the injection container
|
|
@@ -320,7 +321,7 @@ export const run = (() => {
|
|
|
320
321
|
const stateManager: IStateManager = InjectionContainer.get(
|
|
321
322
|
RsXStateManagerInjectionTokens.IStateManager,
|
|
322
323
|
);
|
|
323
|
-
const
|
|
324
|
+
const model = {
|
|
324
325
|
x: { y: 10 },
|
|
325
326
|
};
|
|
326
327
|
const changedSubscription = stateManager.changed.subscribe(
|
|
@@ -336,25 +337,25 @@ export const run = (() => {
|
|
|
336
337
|
// so we pass a predicate that always returns true.
|
|
337
338
|
// This will emit an initial value { y: 10 }
|
|
338
339
|
console.log('Initial value:');
|
|
339
|
-
stateManager.watchState(
|
|
340
|
+
stateManager.watchState(model, 'x', watchIndexRecursiveRule);
|
|
340
341
|
|
|
341
342
|
console.log('Changed value:');
|
|
342
343
|
// This will emit the new value { y: 10 }
|
|
343
|
-
|
|
344
|
+
model.x = {
|
|
344
345
|
y: 20,
|
|
345
346
|
};
|
|
346
347
|
|
|
347
348
|
console.log('Changed (recursive) value:');
|
|
348
349
|
// This will emit the new value { y: 30 } because x
|
|
349
350
|
// is registered as a recursive state.
|
|
350
|
-
|
|
351
|
+
model.x.y = 30;
|
|
351
352
|
|
|
352
353
|
console.log(`Latest value:`);
|
|
353
|
-
printValue(stateManager.getState(
|
|
354
|
+
printValue(stateManager.getState(model, 'x'));
|
|
354
355
|
} finally {
|
|
355
356
|
changedSubscription.unsubscribe();
|
|
356
357
|
// Always release the state when it is no longer needed.
|
|
357
|
-
stateManager.releaseState(
|
|
358
|
+
stateManager.releaseState(model, 'x', watchIndexRecursiveRule);
|
|
358
359
|
}
|
|
359
360
|
})();
|
|
360
361
|
```
|
|
@@ -381,8 +382,8 @@ Besides that you can register a watched stated (calling `watchedState`) you can
|
|
|
381
382
|
```ts
|
|
382
383
|
import { InjectionContainer, printValue } from '@rs-x/core';
|
|
383
384
|
import {
|
|
384
|
-
IStateChange,
|
|
385
|
-
IStateManager,
|
|
385
|
+
type IStateChange,
|
|
386
|
+
type IStateManager,
|
|
386
387
|
RsXStateManagerInjectionTokens,
|
|
387
388
|
RsXStateManagerModule,
|
|
388
389
|
} from '@rs-x/state-manager';
|
|
@@ -395,7 +396,7 @@ export const run = (() => {
|
|
|
395
396
|
RsXStateManagerInjectionTokens.IStateManager,
|
|
396
397
|
);
|
|
397
398
|
|
|
398
|
-
class
|
|
399
|
+
class MyModel {
|
|
399
400
|
private readonly _aPlusBId = 'a+b';
|
|
400
401
|
private _a = 10;
|
|
401
402
|
private _b = 20;
|
|
@@ -435,7 +436,7 @@ export const run = (() => {
|
|
|
435
436
|
}
|
|
436
437
|
}
|
|
437
438
|
|
|
438
|
-
const
|
|
439
|
+
const model = new MyModel();
|
|
439
440
|
const changeSubscription = stateManager.changed.subscribe(
|
|
440
441
|
(change: IStateChange) => {
|
|
441
442
|
printValue(change.newValue);
|
|
@@ -444,23 +445,23 @@ export const run = (() => {
|
|
|
444
445
|
|
|
445
446
|
try {
|
|
446
447
|
console.log(`Initial value for readonly property 'aPlusB':`);
|
|
447
|
-
console.log(
|
|
448
|
+
console.log(model.aPlusB);
|
|
448
449
|
|
|
449
450
|
console.log(
|
|
450
|
-
`set '
|
|
451
|
+
`set 'model.a' to '100' will emit a change event for readonly property 'aPlusB'`,
|
|
451
452
|
);
|
|
452
453
|
console.log(`Changed value for readonly property 'aPlusB':`);
|
|
453
|
-
|
|
454
|
+
model.a = 100;
|
|
454
455
|
|
|
455
456
|
console.log(
|
|
456
|
-
`set '
|
|
457
|
+
`set 'model.b' to '200' will emit a change event for readonly property 'aPlusB'`,
|
|
457
458
|
);
|
|
458
459
|
console.log(`Changed value for readonly property 'aPlusB':`);
|
|
459
|
-
|
|
460
|
+
model.b = 200;
|
|
460
461
|
} finally {
|
|
461
462
|
changeSubscription.unsubscribe();
|
|
462
463
|
// Always release the state when it is no longer needed.
|
|
463
|
-
|
|
464
|
+
model.dispose();
|
|
464
465
|
}
|
|
465
466
|
})();
|
|
466
467
|
```
|
|
@@ -492,8 +493,8 @@ When done, release the state:
|
|
|
492
493
|
```ts
|
|
493
494
|
import { InjectionContainer, printValue } from '@rs-x/core';
|
|
494
495
|
import {
|
|
495
|
-
IStateChange,
|
|
496
|
-
IStateManager,
|
|
496
|
+
type IStateChange,
|
|
497
|
+
type IStateManager,
|
|
497
498
|
RsXStateManagerInjectionTokens,
|
|
498
499
|
RsXStateManagerModule,
|
|
499
500
|
} from '@rs-x/state-manager';
|
|
@@ -505,7 +506,7 @@ export const run = (() => {
|
|
|
505
506
|
const stateManager: IStateManager = InjectionContainer.get(
|
|
506
507
|
RsXStateManagerInjectionTokens.IStateManager,
|
|
507
508
|
);
|
|
508
|
-
const
|
|
509
|
+
const model = {
|
|
509
510
|
x: { y: 10 },
|
|
510
511
|
};
|
|
511
512
|
const changedSubscription = stateManager.changed.subscribe(
|
|
@@ -518,28 +519,28 @@ export const run = (() => {
|
|
|
518
519
|
// Register is idempotent: you can register the same state multiple times.
|
|
519
520
|
// For every register call, make sure you call unregister when you're done.
|
|
520
521
|
console.log('Initial value:');
|
|
521
|
-
stateManager.watchState(
|
|
522
|
-
stateManager.watchState(
|
|
522
|
+
stateManager.watchState(model, 'x');
|
|
523
|
+
stateManager.watchState(model, 'x');
|
|
523
524
|
|
|
524
525
|
console.log('Changed value:');
|
|
525
|
-
|
|
526
|
+
model.x = { y: 20 };
|
|
526
527
|
|
|
527
|
-
stateManager.releaseState(
|
|
528
|
+
stateManager.releaseState(model, 'x');
|
|
528
529
|
|
|
529
530
|
console.log(
|
|
530
531
|
'Changed event is still emitted after unregister because one observer remains.',
|
|
531
532
|
);
|
|
532
533
|
console.log('Changed value:');
|
|
533
|
-
|
|
534
|
+
model.x = { y: 30 };
|
|
534
535
|
|
|
535
|
-
stateManager.releaseState(
|
|
536
|
+
stateManager.releaseState(model, 'x');
|
|
536
537
|
|
|
537
538
|
console.log(
|
|
538
539
|
'Changed event is no longer emitted after the last observer unregisters.',
|
|
539
540
|
);
|
|
540
541
|
console.log('Changed value:');
|
|
541
542
|
console.log('---');
|
|
542
|
-
|
|
543
|
+
model.x = { y: 30 };
|
|
543
544
|
} finally {
|
|
544
545
|
changedSubscription.unsubscribe();
|
|
545
546
|
}
|
|
@@ -596,12 +597,13 @@ The following example illustrates the different state types:
|
|
|
596
597
|
**Example**
|
|
597
598
|
|
|
598
599
|
```ts
|
|
599
|
-
import { InjectionContainer, printValue,
|
|
600
|
+
import { InjectionContainer, printValue, Type } from '@rs-x/core';
|
|
600
601
|
import {
|
|
601
|
-
IStateChange,
|
|
602
|
-
IStateManager,
|
|
602
|
+
type IStateChange,
|
|
603
|
+
type IStateManager,
|
|
603
604
|
RsXStateManagerInjectionTokens,
|
|
604
605
|
RsXStateManagerModule,
|
|
606
|
+
watchIndexRecursiveRule,
|
|
605
607
|
} from '@rs-x/state-manager';
|
|
606
608
|
|
|
607
609
|
// Load the state manager module into the injection container
|
|
@@ -612,7 +614,7 @@ interface INestStateConext {
|
|
|
612
614
|
nested?: INestStateConext;
|
|
613
615
|
}
|
|
614
616
|
|
|
615
|
-
class
|
|
617
|
+
class MyModel {
|
|
616
618
|
private _b: INestStateConext = {
|
|
617
619
|
a: 10,
|
|
618
620
|
nested: {
|
|
@@ -640,7 +642,7 @@ export const run = (() => {
|
|
|
640
642
|
RsXStateManagerInjectionTokens.IStateManager,
|
|
641
643
|
);
|
|
642
644
|
|
|
643
|
-
const
|
|
645
|
+
const model = new MyModel();
|
|
644
646
|
|
|
645
647
|
const changeSubscription = stateManager.changed.subscribe(
|
|
646
648
|
(change: IStateChange) => {
|
|
@@ -650,17 +652,15 @@ export const run = (() => {
|
|
|
650
652
|
|
|
651
653
|
try {
|
|
652
654
|
// Observe property `b` recursively.
|
|
653
|
-
// Otherwise, only assigning a new value to
|
|
655
|
+
// Otherwise, only assigning a new value to model.b would emit a change event.
|
|
654
656
|
// This will emit a change event with the initial (current) value.
|
|
655
657
|
console.log('Initial value:');
|
|
656
|
-
stateManager.watchState(
|
|
658
|
+
stateManager.watchState(model, 'b', watchIndexRecursiveRule);
|
|
657
659
|
|
|
658
|
-
console.log(
|
|
659
|
-
'\nReplacing stateContext.b.nested.nested will emit a change event',
|
|
660
|
-
);
|
|
660
|
+
console.log('\nReplacing model.b.nested.nested will emit a change event');
|
|
661
661
|
console.log('Changed value:');
|
|
662
662
|
|
|
663
|
-
|
|
663
|
+
(Type.toObject(model.b.nested) ?? {}).nested = {
|
|
664
664
|
a: -30,
|
|
665
665
|
nested: {
|
|
666
666
|
a: -40,
|
|
@@ -668,11 +668,11 @@ export const run = (() => {
|
|
|
668
668
|
};
|
|
669
669
|
|
|
670
670
|
console.log(`Latest value:`);
|
|
671
|
-
printValue(stateManager.getState(
|
|
671
|
+
printValue(stateManager.getState(model, 'b'));
|
|
672
672
|
} finally {
|
|
673
673
|
changeSubscription.unsubscribe();
|
|
674
674
|
// Always release the state when it is no longer needed.
|
|
675
|
-
stateManager.releaseState(
|
|
675
|
+
stateManager.releaseState(model, 'b', watchIndexRecursiveRule);
|
|
676
676
|
}
|
|
677
677
|
})();
|
|
678
678
|
```
|
|
@@ -729,13 +729,14 @@ Latest value:
|
|
|
729
729
|
**Example**
|
|
730
730
|
|
|
731
731
|
```ts
|
|
732
|
-
import { InjectionContainer,
|
|
732
|
+
import { InjectionContainer, utCDate } from '@rs-x/core';
|
|
733
733
|
import {
|
|
734
|
-
IProxyRegistry,
|
|
735
|
-
IStateChange,
|
|
736
|
-
IStateManager,
|
|
734
|
+
type IProxyRegistry,
|
|
735
|
+
type IStateChange,
|
|
736
|
+
type IStateManager,
|
|
737
737
|
RsXStateManagerInjectionTokens,
|
|
738
738
|
RsXStateManagerModule,
|
|
739
|
+
watchIndexRecursiveRule,
|
|
739
740
|
} from '@rs-x/state-manager';
|
|
740
741
|
|
|
741
742
|
// Load the state manager module into the injection container
|
|
@@ -746,32 +747,32 @@ function watchDate(stateManager: IStateManager) {
|
|
|
746
747
|
console.log('* Watching date');
|
|
747
748
|
console.log('******************************************\n');
|
|
748
749
|
|
|
749
|
-
const
|
|
750
|
+
const model = {
|
|
750
751
|
date: utCDate(2021, 2, 5),
|
|
751
752
|
};
|
|
752
753
|
const changeSubscription = stateManager.changed.subscribe(
|
|
753
754
|
(change: IStateChange) => {
|
|
754
|
-
console.log(
|
|
755
|
+
console.log(
|
|
756
|
+
`${change.index}: ${(change.newValue as Date).toUTCString()}`,
|
|
757
|
+
);
|
|
755
758
|
},
|
|
756
759
|
);
|
|
757
760
|
try {
|
|
758
761
|
console.log('Initial value:');
|
|
759
|
-
stateManager.watchState(
|
|
762
|
+
stateManager.watchState(model, 'date', watchIndexRecursiveRule);
|
|
760
763
|
|
|
761
764
|
console.log('Changed value:');
|
|
762
|
-
|
|
765
|
+
model.date.setFullYear(2023);
|
|
763
766
|
|
|
764
767
|
console.log('Set value:');
|
|
765
|
-
|
|
768
|
+
model.date = new Date(2024, 5, 6);
|
|
766
769
|
|
|
767
770
|
console.log('Latest value:');
|
|
768
|
-
console.log(
|
|
769
|
-
stateManager.getState<Date>(stateContext, 'date').toUTCString(),
|
|
770
|
-
);
|
|
771
|
+
console.log(stateManager.getState<Date>(model, 'date').toUTCString());
|
|
771
772
|
} finally {
|
|
772
773
|
changeSubscription.unsubscribe();
|
|
773
774
|
// Always release the state when it is no longer needed.
|
|
774
|
-
stateManager.releaseState(
|
|
775
|
+
stateManager.releaseState(model, 'date', watchIndexRecursiveRule);
|
|
775
776
|
}
|
|
776
777
|
}
|
|
777
778
|
|
|
@@ -849,12 +850,13 @@ Latest value:
|
|
|
849
850
|
**Example**
|
|
850
851
|
|
|
851
852
|
```ts
|
|
852
|
-
import { InjectionContainer, printValue
|
|
853
|
+
import { InjectionContainer, printValue } from '@rs-x/core';
|
|
853
854
|
import {
|
|
854
|
-
IStateChange,
|
|
855
|
-
IStateManager,
|
|
855
|
+
type IStateChange,
|
|
856
|
+
type IStateManager,
|
|
856
857
|
RsXStateManagerInjectionTokens,
|
|
857
858
|
RsXStateManagerModule,
|
|
859
|
+
watchIndexRecursiveRule,
|
|
858
860
|
} from '@rs-x/state-manager';
|
|
859
861
|
|
|
860
862
|
// Load the state manager module into the injection container
|
|
@@ -865,7 +867,7 @@ export const run = (() => {
|
|
|
865
867
|
RsXStateManagerInjectionTokens.IStateManager,
|
|
866
868
|
);
|
|
867
869
|
|
|
868
|
-
const
|
|
870
|
+
const model = {
|
|
869
871
|
array: [
|
|
870
872
|
[1, 2],
|
|
871
873
|
[3, 4],
|
|
@@ -881,17 +883,17 @@ export const run = (() => {
|
|
|
881
883
|
try {
|
|
882
884
|
// This will emit a change event with the initial (current) value.
|
|
883
885
|
console.log('Initial value:');
|
|
884
|
-
stateManager.watchState(
|
|
886
|
+
stateManager.watchState(model, 'array', watchIndexRecursiveRule);
|
|
885
887
|
|
|
886
888
|
console.log('Changed value:');
|
|
887
|
-
|
|
889
|
+
model.array[1].push(5);
|
|
888
890
|
|
|
889
891
|
console.log('Latest value:');
|
|
890
|
-
printValue(stateManager.getState(
|
|
892
|
+
printValue(stateManager.getState(model, 'array'));
|
|
891
893
|
} finally {
|
|
892
894
|
changeSubscription.unsubscribe();
|
|
893
895
|
// Always release the state when it is no longer needed.
|
|
894
|
-
stateManager.releaseState(
|
|
896
|
+
stateManager.releaseState(model, 'array', watchIndexRecursiveRule);
|
|
895
897
|
}
|
|
896
898
|
})();
|
|
897
899
|
```
|
|
@@ -942,12 +944,13 @@ Latest value:
|
|
|
942
944
|
**Example**
|
|
943
945
|
|
|
944
946
|
```ts
|
|
945
|
-
import { InjectionContainer, printValue
|
|
947
|
+
import { InjectionContainer, printValue } from '@rs-x/core';
|
|
946
948
|
import {
|
|
947
|
-
IStateChange,
|
|
948
|
-
IStateManager,
|
|
949
|
+
type IStateChange,
|
|
950
|
+
type IStateManager,
|
|
949
951
|
RsXStateManagerInjectionTokens,
|
|
950
952
|
RsXStateManagerModule,
|
|
953
|
+
watchIndexRecursiveRule,
|
|
951
954
|
} from '@rs-x/state-manager';
|
|
952
955
|
|
|
953
956
|
// Load the state manager module into the injection container
|
|
@@ -958,7 +961,7 @@ const stateManager: IStateManager = InjectionContainer.get(
|
|
|
958
961
|
);
|
|
959
962
|
|
|
960
963
|
export const run = (() => {
|
|
961
|
-
const
|
|
964
|
+
const model = {
|
|
962
965
|
map: new Map([
|
|
963
966
|
['a', [1, 2]],
|
|
964
967
|
['b', [3, 4]],
|
|
@@ -974,17 +977,17 @@ export const run = (() => {
|
|
|
974
977
|
try {
|
|
975
978
|
// This will emit a change event with the initial (current) value.
|
|
976
979
|
console.log('Initial value:');
|
|
977
|
-
stateManager.watchState(
|
|
980
|
+
stateManager.watchState(model, 'map', watchIndexRecursiveRule);
|
|
978
981
|
|
|
979
982
|
console.log('Changed value:');
|
|
980
|
-
|
|
983
|
+
model.map.get('b')?.push(5);
|
|
981
984
|
|
|
982
985
|
console.log('Latest value:');
|
|
983
|
-
printValue(stateManager.getState(
|
|
986
|
+
printValue(stateManager.getState(model, 'map'));
|
|
984
987
|
} finally {
|
|
985
988
|
changeSubscription.unsubscribe();
|
|
986
989
|
// Always release the state when it is no longer needed.
|
|
987
|
-
stateManager.releaseState(
|
|
990
|
+
stateManager.releaseState(model, 'array', watchIndexRecursiveRule);
|
|
988
991
|
}
|
|
989
992
|
})();
|
|
990
993
|
```
|
|
@@ -1053,13 +1056,14 @@ Latest value:
|
|
|
1053
1056
|
**Example**
|
|
1054
1057
|
|
|
1055
1058
|
```ts
|
|
1056
|
-
import { InjectionContainer, printValue
|
|
1059
|
+
import { InjectionContainer, printValue } from '@rs-x/core';
|
|
1057
1060
|
import {
|
|
1058
|
-
IProxyRegistry,
|
|
1059
|
-
IStateChange,
|
|
1060
|
-
IStateManager,
|
|
1061
|
+
type IProxyRegistry,
|
|
1062
|
+
type IStateChange,
|
|
1063
|
+
type IStateManager,
|
|
1061
1064
|
RsXStateManagerInjectionTokens,
|
|
1062
1065
|
RsXStateManagerModule,
|
|
1066
|
+
watchIndexRecursiveRule,
|
|
1063
1067
|
} from '@rs-x/state-manager';
|
|
1064
1068
|
|
|
1065
1069
|
// Load the state manager module into the injection container
|
|
@@ -1071,7 +1075,7 @@ export const run = (() => {
|
|
|
1071
1075
|
);
|
|
1072
1076
|
const item1 = [1, 2];
|
|
1073
1077
|
const item2 = [3, 4];
|
|
1074
|
-
const
|
|
1078
|
+
const model = {
|
|
1075
1079
|
set: new Set([item1, item2]),
|
|
1076
1080
|
};
|
|
1077
1081
|
const changeSubscription = stateManager.changed.subscribe(
|
|
@@ -1083,7 +1087,7 @@ export const run = (() => {
|
|
|
1083
1087
|
try {
|
|
1084
1088
|
// This will emit a change event with the initial (current) value.
|
|
1085
1089
|
console.log('Initial value:');
|
|
1086
|
-
stateManager.watchState(
|
|
1090
|
+
stateManager.watchState(model, 'set', watchIndexRecursiveRule);
|
|
1087
1091
|
|
|
1088
1092
|
console.log('Changed value:');
|
|
1089
1093
|
const proxyRegister: IProxyRegistry = InjectionContainer.get(
|
|
@@ -1092,11 +1096,11 @@ export const run = (() => {
|
|
|
1092
1096
|
proxyRegister.getProxy<number[]>(item2).push(5);
|
|
1093
1097
|
|
|
1094
1098
|
console.log('Latest value:');
|
|
1095
|
-
printValue(stateManager.getState(
|
|
1099
|
+
printValue(stateManager.getState(model, 'set'));
|
|
1096
1100
|
} finally {
|
|
1097
1101
|
changeSubscription.unsubscribe();
|
|
1098
1102
|
// Always release the state when it is no longer needed.
|
|
1099
|
-
stateManager.releaseState(
|
|
1103
|
+
stateManager.releaseState(model, 'set', watchIndexRecursiveRule);
|
|
1100
1104
|
}
|
|
1101
1105
|
})();
|
|
1102
1106
|
```
|
|
@@ -1149,8 +1153,8 @@ Latest value:
|
|
|
1149
1153
|
```ts
|
|
1150
1154
|
import { InjectionContainer, WaitForEvent } from '@rs-x/core';
|
|
1151
1155
|
import {
|
|
1152
|
-
IStateChange,
|
|
1153
|
-
IStateManager,
|
|
1156
|
+
type IStateChange,
|
|
1157
|
+
type IStateManager,
|
|
1154
1158
|
RsXStateManagerInjectionTokens,
|
|
1155
1159
|
RsXStateManagerModule,
|
|
1156
1160
|
} from '@rs-x/state-manager';
|
|
@@ -1163,7 +1167,7 @@ export const run = (async () => {
|
|
|
1163
1167
|
RsXStateManagerInjectionTokens.IStateManager,
|
|
1164
1168
|
);
|
|
1165
1169
|
|
|
1166
|
-
const
|
|
1170
|
+
const model = {
|
|
1167
1171
|
promise: Promise.resolve(10),
|
|
1168
1172
|
};
|
|
1169
1173
|
const changeSubscription = stateManager.changed.subscribe(
|
|
@@ -1176,25 +1180,25 @@ export const run = (async () => {
|
|
|
1176
1180
|
await new WaitForEvent(stateManager, 'changed').wait(() => {
|
|
1177
1181
|
// This will emit a change event with the initial (current) value.
|
|
1178
1182
|
console.log('Initial value:');
|
|
1179
|
-
stateManager.watchState(
|
|
1183
|
+
stateManager.watchState(model, 'promise');
|
|
1180
1184
|
});
|
|
1181
1185
|
|
|
1182
1186
|
await new WaitForEvent(stateManager, 'changed').wait(() => {
|
|
1183
1187
|
console.log('Changed value:');
|
|
1184
|
-
let resolveHandler
|
|
1185
|
-
|
|
1188
|
+
let resolveHandler!: (value: number) => void;
|
|
1189
|
+
|
|
1190
|
+
model.promise = new Promise<number>((resolve) => {
|
|
1186
1191
|
resolveHandler = resolve;
|
|
1187
1192
|
});
|
|
1193
|
+
|
|
1188
1194
|
resolveHandler(30);
|
|
1189
1195
|
});
|
|
1190
1196
|
|
|
1191
|
-
console.log(
|
|
1192
|
-
`Latest value: ${stateManager.getState(stateContext, 'promise')}`,
|
|
1193
|
-
);
|
|
1197
|
+
console.log(`Latest value: ${stateManager.getState(model, 'promise')}`);
|
|
1194
1198
|
} finally {
|
|
1195
1199
|
changeSubscription.unsubscribe();
|
|
1196
1200
|
// Always release the state when it is no longer needed.
|
|
1197
|
-
stateManager.releaseState(
|
|
1201
|
+
stateManager.releaseState(model, 'promise');
|
|
1198
1202
|
}
|
|
1199
1203
|
})();
|
|
1200
1204
|
```
|
|
@@ -1215,14 +1219,15 @@ Latest value: 30
|
|
|
1215
1219
|
**Example**
|
|
1216
1220
|
|
|
1217
1221
|
```ts
|
|
1222
|
+
import { of, Subject } from 'rxjs';
|
|
1223
|
+
|
|
1218
1224
|
import { InjectionContainer, WaitForEvent } from '@rs-x/core';
|
|
1219
1225
|
import {
|
|
1220
|
-
IStateChange,
|
|
1221
|
-
IStateManager,
|
|
1226
|
+
type IStateChange,
|
|
1227
|
+
type IStateManager,
|
|
1222
1228
|
RsXStateManagerInjectionTokens,
|
|
1223
1229
|
RsXStateManagerModule,
|
|
1224
1230
|
} from '@rs-x/state-manager';
|
|
1225
|
-
import { of, Subject } from 'rxjs';
|
|
1226
1231
|
|
|
1227
1232
|
// Load the state manager module into the injection container
|
|
1228
1233
|
InjectionContainer.load(RsXStateManagerModule);
|
|
@@ -1232,7 +1237,7 @@ export const run = (async () => {
|
|
|
1232
1237
|
RsXStateManagerInjectionTokens.IStateManager,
|
|
1233
1238
|
);
|
|
1234
1239
|
|
|
1235
|
-
const
|
|
1240
|
+
const model = {
|
|
1236
1241
|
observable: of(10),
|
|
1237
1242
|
};
|
|
1238
1243
|
|
|
@@ -1248,23 +1253,21 @@ export const run = (async () => {
|
|
|
1248
1253
|
await new WaitForEvent(stateManager, 'changed').wait(() => {
|
|
1249
1254
|
// This will emit a change event with the initial (current) value.
|
|
1250
1255
|
console.log('Initial value:');
|
|
1251
|
-
stateManager.watchState(
|
|
1256
|
+
stateManager.watchState(model, 'observable');
|
|
1252
1257
|
});
|
|
1253
1258
|
|
|
1254
1259
|
await new WaitForEvent(stateManager, 'changed').wait(() => {
|
|
1255
1260
|
console.log('Changed value:');
|
|
1256
1261
|
const subject = new Subject<number>();
|
|
1257
|
-
|
|
1262
|
+
model.observable = subject;
|
|
1258
1263
|
subject.next(30);
|
|
1259
1264
|
});
|
|
1260
1265
|
|
|
1261
|
-
console.log(
|
|
1262
|
-
`Latest value: ${stateManager.getState(stateContext, 'observable')}`,
|
|
1263
|
-
);
|
|
1266
|
+
console.log(`Latest value: ${stateManager.getState(model, 'observable')}`);
|
|
1264
1267
|
} finally {
|
|
1265
1268
|
changeSubscription.unsubscribe();
|
|
1266
1269
|
// Always release the state when it is no longer needed.
|
|
1267
|
-
stateManager.releaseState(
|
|
1270
|
+
stateManager.releaseState(model, 'observable');
|
|
1268
1271
|
}
|
|
1269
1272
|
})();
|
|
1270
1273
|
```
|
|
@@ -1291,500 +1294,586 @@ The following example demonstrates adding support for a custom `TextDocument` cl
|
|
|
1291
1294
|
**Example**
|
|
1292
1295
|
|
|
1293
1296
|
````ts
|
|
1297
|
+
import { ReplaySubject, Subscription } from 'rxjs';
|
|
1298
|
+
|
|
1294
1299
|
import {
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1300
|
+
ContainerModule,
|
|
1301
|
+
defaultIndexValueAccessorList,
|
|
1302
|
+
type IDisposableOwner,
|
|
1303
|
+
type IErrorLog,
|
|
1304
|
+
type IGuidFactory,
|
|
1305
|
+
type IIndexValueAccessor,
|
|
1306
|
+
Inject,
|
|
1307
|
+
Injectable,
|
|
1308
|
+
InjectionContainer,
|
|
1309
|
+
type IPropertyChange,
|
|
1310
|
+
type IValueMetadata,
|
|
1311
|
+
overrideMultiInjectServices,
|
|
1312
|
+
RsXCoreInjectionTokens,
|
|
1313
|
+
SingletonFactory,
|
|
1314
|
+
Type,
|
|
1309
1315
|
} from '@rs-x/core';
|
|
1310
1316
|
import {
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1317
|
+
AbstractObserver,
|
|
1318
|
+
defaultObjectObserverProxyPairFactoryList,
|
|
1319
|
+
defaultPropertyObserverProxyPairFactoryList,
|
|
1320
|
+
type IIndexObserverInfo,
|
|
1321
|
+
IndexObserverProxyPairFactory,
|
|
1322
|
+
type IObjectObserverProxyPairFactory,
|
|
1323
|
+
type IObjectObserverProxyPairManager,
|
|
1324
|
+
type IObserverProxyPair,
|
|
1325
|
+
type IPropertyInfo,
|
|
1326
|
+
type IProxyRegistry,
|
|
1327
|
+
type IProxyTarget,
|
|
1328
|
+
type IStateChange,
|
|
1329
|
+
type IStateManager,
|
|
1330
|
+
RsXStateManagerInjectionTokens,
|
|
1331
|
+
RsXStateManagerModule,
|
|
1332
|
+
watchIndexRecursiveRule,
|
|
1326
1333
|
} from '@rs-x/state-manager';
|
|
1327
|
-
import { ReplaySubject, Subscription } from 'rxjs';
|
|
1328
1334
|
|
|
1329
1335
|
const MyInjectTokens = {
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
+
TextDocumentObserverManager: Symbol('TextDocumentObserverManager'),
|
|
1337
|
+
TextDocumenIndexObserverManager: Symbol('TextDocumenIndexObserverManager'),
|
|
1338
|
+
TextDocumentIndexAccessor: Symbol('TextDocumentIndexAccessor'),
|
|
1339
|
+
TextDocumentObserverProxyPairFactory: Symbol(
|
|
1340
|
+
'TextDocumentObserverProxyPairFactory',
|
|
1341
|
+
),
|
|
1342
|
+
TextDocumentInxdexObserverProxyPairFactory: Symbol(
|
|
1343
|
+
'TextDocumentInxdexObserverProxyPairFactory',
|
|
1344
|
+
),
|
|
1336
1345
|
};
|
|
1337
1346
|
|
|
1338
|
-
class IndexForTextDocumentxObserverManager
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1347
|
+
class IndexForTextDocumentxObserverManager extends SingletonFactory<
|
|
1348
|
+
number,
|
|
1349
|
+
IIndexObserverInfo<ITextDocumentIndex>,
|
|
1350
|
+
TextDocumentIndexObserver
|
|
1351
|
+
> {
|
|
1352
|
+
constructor(
|
|
1353
|
+
private readonly _textDocument: TextDocument,
|
|
1354
|
+
private readonly _textDocumentObserverManager: TextDocumentObserverManager,
|
|
1355
|
+
private readonly releaseOwner: () => void,
|
|
1356
|
+
) {
|
|
1357
|
+
super();
|
|
1358
|
+
}
|
|
1350
1359
|
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1360
|
+
public override getId(
|
|
1361
|
+
indexObserverInfo: IIndexObserverInfo<ITextDocumentIndex>,
|
|
1362
|
+
): number {
|
|
1363
|
+
return this.createId(indexObserverInfo);
|
|
1364
|
+
}
|
|
1354
1365
|
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1366
|
+
protected override createInstance(
|
|
1367
|
+
indexObserverInfo: IIndexObserverInfo<ITextDocumentIndex>,
|
|
1368
|
+
id: number,
|
|
1369
|
+
): TextDocumentIndexObserver {
|
|
1370
|
+
const textDocumentObserver = this._textDocumentObserverManager.create(
|
|
1371
|
+
this._textDocument,
|
|
1372
|
+
).instance;
|
|
1373
|
+
return new TextDocumentIndexObserver(
|
|
1374
|
+
{
|
|
1375
|
+
canDispose: () => this.getReferenceCount(id) === 1,
|
|
1376
|
+
release: () => {
|
|
1377
|
+
textDocumentObserver.dispose();
|
|
1378
|
+
this.release(id);
|
|
1379
|
+
},
|
|
1380
|
+
},
|
|
1381
|
+
textDocumentObserver,
|
|
1382
|
+
indexObserverInfo.index,
|
|
1383
|
+
);
|
|
1384
|
+
}
|
|
1368
1385
|
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
}
|
|
1386
|
+
protected override createId(
|
|
1387
|
+
indexObserverInfo: IIndexObserverInfo<ITextDocumentIndex>,
|
|
1388
|
+
): number {
|
|
1389
|
+
// Using Cantor pairing to create a unique id from page and line index
|
|
1390
|
+
const { pageIndex, lineIndex } = indexObserverInfo.index;
|
|
1391
|
+
return (
|
|
1392
|
+
((pageIndex + lineIndex) * (pageIndex + lineIndex + 1)) / 2 + lineIndex
|
|
1393
|
+
);
|
|
1394
|
+
}
|
|
1374
1395
|
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
}
|
|
1396
|
+
protected override onReleased(): void {
|
|
1397
|
+
if (this.isEmpty) {
|
|
1398
|
+
this.releaseOwner();
|
|
1379
1399
|
}
|
|
1400
|
+
}
|
|
1380
1401
|
}
|
|
1381
1402
|
|
|
1382
1403
|
// We want to ensure that for the same TextDocument we always have the same observer
|
|
1383
1404
|
@Injectable()
|
|
1384
|
-
class TextDocumentObserverManager extends SingletonFactory<
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1405
|
+
class TextDocumentObserverManager extends SingletonFactory<
|
|
1406
|
+
TextDocument,
|
|
1407
|
+
TextDocument,
|
|
1408
|
+
TextDocumentObserver
|
|
1409
|
+
> {
|
|
1410
|
+
constructor(
|
|
1411
|
+
@Inject(RsXStateManagerInjectionTokens.IProxyRegistry)
|
|
1412
|
+
private readonly _proxyRegister: IProxyRegistry,
|
|
1413
|
+
) {
|
|
1414
|
+
super();
|
|
1415
|
+
}
|
|
1390
1416
|
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1417
|
+
public override getId(textDocument: TextDocument): TextDocument {
|
|
1418
|
+
return textDocument;
|
|
1419
|
+
}
|
|
1394
1420
|
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
}
|
|
1421
|
+
protected override createInstance(
|
|
1422
|
+
textDocument: TextDocument,
|
|
1423
|
+
id: TextDocument,
|
|
1424
|
+
): TextDocumentObserver {
|
|
1425
|
+
return new TextDocumentObserver(textDocument, this._proxyRegister, {
|
|
1426
|
+
canDispose: () => this.getReferenceCount(id) === 1,
|
|
1427
|
+
release: () => this.release(id),
|
|
1428
|
+
});
|
|
1429
|
+
}
|
|
1405
1430
|
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1431
|
+
protected override createId(textDocument: TextDocument): TextDocument {
|
|
1432
|
+
return textDocument;
|
|
1433
|
+
}
|
|
1409
1434
|
}
|
|
1410
1435
|
|
|
1411
1436
|
// We want to ensure we create only one index-manager per TextDocument
|
|
1412
1437
|
@Injectable()
|
|
1413
|
-
export class TextDocumenIndexObserverManager
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
)
|
|
1423
|
-
|
|
1424
|
-
}
|
|
1425
|
-
|
|
1426
|
-
public override getId(textDocument: TextDocument): TextDocument {
|
|
1427
|
-
return textDocument;
|
|
1428
|
-
}
|
|
1438
|
+
export class TextDocumenIndexObserverManager extends SingletonFactory<
|
|
1439
|
+
TextDocument,
|
|
1440
|
+
TextDocument,
|
|
1441
|
+
IndexForTextDocumentxObserverManager
|
|
1442
|
+
> {
|
|
1443
|
+
constructor(
|
|
1444
|
+
@Inject(MyInjectTokens.TextDocumentObserverManager)
|
|
1445
|
+
private readonly _textDocumentObserverManager: TextDocumentObserverManager,
|
|
1446
|
+
) {
|
|
1447
|
+
super();
|
|
1448
|
+
}
|
|
1429
1449
|
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1450
|
+
public override getId(textDocument: TextDocument): TextDocument {
|
|
1451
|
+
return textDocument;
|
|
1452
|
+
}
|
|
1433
1453
|
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1454
|
+
protected override createId(textDocument: TextDocument): TextDocument {
|
|
1455
|
+
return textDocument;
|
|
1456
|
+
}
|
|
1437
1457
|
|
|
1438
|
-
|
|
1439
|
-
|
|
1458
|
+
protected override createInstance(
|
|
1459
|
+
textDocument: TextDocument,
|
|
1460
|
+
): IndexForTextDocumentxObserverManager {
|
|
1461
|
+
return new IndexForTextDocumentxObserverManager(
|
|
1462
|
+
textDocument,
|
|
1463
|
+
this._textDocumentObserverManager,
|
|
1464
|
+
() => this.release(textDocument),
|
|
1465
|
+
);
|
|
1466
|
+
}
|
|
1440
1467
|
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1468
|
+
protected override releaseInstance(
|
|
1469
|
+
indexForTextDocumentxObserverManager: IndexForTextDocumentxObserverManager,
|
|
1470
|
+
): void {
|
|
1471
|
+
indexForTextDocumentxObserverManager.dispose();
|
|
1472
|
+
}
|
|
1446
1473
|
}
|
|
1447
1474
|
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
1475
|
@Injectable()
|
|
1452
|
-
export class TextDocumentIndexAccessor implements IIndexValueAccessor<
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1476
|
+
export class TextDocumentIndexAccessor implements IIndexValueAccessor<
|
|
1477
|
+
TextDocument,
|
|
1478
|
+
ITextDocumentIndex
|
|
1479
|
+
> {
|
|
1480
|
+
public readonly priority!: 200;
|
|
1481
|
+
|
|
1482
|
+
public hasValue(
|
|
1483
|
+
textDocument: TextDocument,
|
|
1484
|
+
index: ITextDocumentIndex,
|
|
1485
|
+
): boolean {
|
|
1486
|
+
return textDocument.getLine(index) !== undefined;
|
|
1487
|
+
}
|
|
1463
1488
|
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1489
|
+
// We don’t have any properties that can be iterated through.
|
|
1490
|
+
public getIndexes(): IterableIterator<ITextDocumentIndex> {
|
|
1491
|
+
return [].values();
|
|
1492
|
+
}
|
|
1468
1493
|
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1494
|
+
// Here it is the same as getValue.
|
|
1495
|
+
// For example, for a Promise accessor getValue returns the promise
|
|
1496
|
+
// and getResolvedValue returns the resolved promise value
|
|
1497
|
+
public getResolvedValue(
|
|
1498
|
+
textDocument: TextDocument,
|
|
1499
|
+
index: ITextDocumentIndex,
|
|
1500
|
+
): string | undefined {
|
|
1501
|
+
return this.getValue(textDocument, index);
|
|
1502
|
+
}
|
|
1475
1503
|
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1504
|
+
public getValue(
|
|
1505
|
+
textDocument: TextDocument,
|
|
1506
|
+
index: ITextDocumentIndex,
|
|
1507
|
+
): string | undefined {
|
|
1508
|
+
return textDocument.getLine(index);
|
|
1509
|
+
}
|
|
1479
1510
|
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1511
|
+
public setValue(
|
|
1512
|
+
textDocument: TextDocument,
|
|
1513
|
+
index: ITextDocumentIndex,
|
|
1514
|
+
value: string,
|
|
1515
|
+
): void {
|
|
1516
|
+
textDocument.setLine(index, value);
|
|
1517
|
+
}
|
|
1483
1518
|
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1519
|
+
public applies(textDocument: unknown, _index: ITextDocumentIndex): boolean {
|
|
1520
|
+
return textDocument instanceof TextDocument;
|
|
1521
|
+
}
|
|
1487
1522
|
}
|
|
1488
1523
|
|
|
1489
1524
|
@Injectable()
|
|
1490
|
-
export class TextDocumentInxdexObserverProxyPairFactory extends IndexObserverProxyPairFactory<
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1525
|
+
export class TextDocumentInxdexObserverProxyPairFactory extends IndexObserverProxyPairFactory<
|
|
1526
|
+
TextDocument,
|
|
1527
|
+
unknown
|
|
1528
|
+
> {
|
|
1529
|
+
constructor(
|
|
1530
|
+
@Inject(RsXStateManagerInjectionTokens.IObjectObserverProxyPairManager)
|
|
1531
|
+
objectObserverManager: IObjectObserverProxyPairManager,
|
|
1532
|
+
@Inject(MyInjectTokens.TextDocumenIndexObserverManager)
|
|
1533
|
+
textDocumenIndexObserverManager: TextDocumenIndexObserverManager,
|
|
1534
|
+
@Inject(RsXCoreInjectionTokens.IErrorLog)
|
|
1535
|
+
errorLog: IErrorLog,
|
|
1536
|
+
@Inject(RsXCoreInjectionTokens.IGuidFactory)
|
|
1537
|
+
guidFactory: IGuidFactory,
|
|
1538
|
+
@Inject(RsXCoreInjectionTokens.IIndexValueAccessor)
|
|
1539
|
+
indexValueAccessor: IIndexValueAccessor,
|
|
1540
|
+
@Inject(RsXStateManagerInjectionTokens.IProxyRegistry)
|
|
1541
|
+
proxyRegister: IProxyRegistry,
|
|
1542
|
+
@Inject(RsXCoreInjectionTokens.IValueMetadata)
|
|
1543
|
+
valueMetadata: IValueMetadata,
|
|
1544
|
+
) {
|
|
1545
|
+
super(
|
|
1546
|
+
objectObserverManager,
|
|
1547
|
+
Type.cast(textDocumenIndexObserverManager),
|
|
1548
|
+
errorLog,
|
|
1549
|
+
guidFactory,
|
|
1550
|
+
indexValueAccessor,
|
|
1551
|
+
proxyRegister,
|
|
1552
|
+
valueMetadata,
|
|
1553
|
+
);
|
|
1554
|
+
}
|
|
1514
1555
|
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1556
|
+
public applies(object: unknown, propertyInfo: IPropertyInfo): boolean {
|
|
1557
|
+
const documentKey = propertyInfo.index as ITextDocumentIndex;
|
|
1558
|
+
return (
|
|
1559
|
+
object instanceof TextDocument &&
|
|
1560
|
+
documentKey?.lineIndex >= 0 &&
|
|
1561
|
+
documentKey?.pageIndex >= 0
|
|
1562
|
+
);
|
|
1563
|
+
}
|
|
1519
1564
|
}
|
|
1520
1565
|
|
|
1521
1566
|
@Injectable()
|
|
1522
1567
|
export class TextDocumentObserverProxyPairFactory implements IObjectObserverProxyPairFactory {
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
constructor(
|
|
1526
|
-
@Inject( MyInjectTokens.TextDocumentObserverManager)
|
|
1527
|
-
private readonly _textDocumentObserverManager: TextDocumentObserverManager) { }
|
|
1528
|
-
|
|
1529
|
-
public create(
|
|
1530
|
-
_: IDisposableOwner,
|
|
1531
|
-
proxyTarget: IProxyTarget<TextDocument>): IObserverProxyPair<TextDocument> {
|
|
1532
|
-
|
|
1533
|
-
const observer = this._textDocumentObserverManager.create(proxyTarget.target).instance;
|
|
1534
|
-
return {
|
|
1535
|
-
observer,
|
|
1536
|
-
proxy: observer.target as TextDocument,
|
|
1537
|
-
proxyTarget: proxyTarget.target,
|
|
1538
|
-
};
|
|
1539
|
-
}
|
|
1568
|
+
public readonly priority = 100;
|
|
1540
1569
|
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1570
|
+
constructor(
|
|
1571
|
+
@Inject(MyInjectTokens.TextDocumentObserverManager)
|
|
1572
|
+
private readonly _textDocumentObserverManager: TextDocumentObserverManager,
|
|
1573
|
+
) {}
|
|
1574
|
+
|
|
1575
|
+
public create(
|
|
1576
|
+
_: IDisposableOwner,
|
|
1577
|
+
proxyTarget: IProxyTarget<TextDocument>,
|
|
1578
|
+
): IObserverProxyPair<TextDocument> {
|
|
1579
|
+
const observer = this._textDocumentObserverManager.create(
|
|
1580
|
+
proxyTarget.target,
|
|
1581
|
+
).instance;
|
|
1582
|
+
return {
|
|
1583
|
+
observer,
|
|
1584
|
+
proxy: observer.target as TextDocument,
|
|
1585
|
+
proxyTarget: proxyTarget.target,
|
|
1586
|
+
};
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
public applies(object: unknown): boolean {
|
|
1590
|
+
return object instanceof TextDocument;
|
|
1591
|
+
}
|
|
1544
1592
|
}
|
|
1545
1593
|
|
|
1546
1594
|
interface ITextDocumentIndex {
|
|
1547
|
-
|
|
1548
|
-
|
|
1595
|
+
pageIndex: number;
|
|
1596
|
+
lineIndex: number;
|
|
1549
1597
|
}
|
|
1550
1598
|
|
|
1551
1599
|
class TextDocument {
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
});
|
|
1564
|
-
});
|
|
1565
|
-
}
|
|
1566
|
-
|
|
1567
|
-
public toString(): string {
|
|
1568
|
-
const pages: string[] = [];
|
|
1600
|
+
private readonly _pages = new Map<number, Map<number, string>>();
|
|
1601
|
+
constructor(pages?: string[][]) {
|
|
1602
|
+
pages?.forEach((page, pageIndex) => {
|
|
1603
|
+
const pageText = new Map<number, string>();
|
|
1604
|
+
|
|
1605
|
+
this._pages.set(pageIndex, pageText);
|
|
1606
|
+
page.forEach((lineText, lineIndex) => {
|
|
1607
|
+
pageText.set(lineIndex, lineText);
|
|
1608
|
+
});
|
|
1609
|
+
});
|
|
1610
|
+
}
|
|
1569
1611
|
|
|
1570
|
-
|
|
1571
|
-
|
|
1612
|
+
public toString(): string {
|
|
1613
|
+
const pages: string[] = [];
|
|
1572
1614
|
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
}
|
|
1615
|
+
// Sort pages by pageIndex
|
|
1616
|
+
const sortedPageIndexes = Array.from(this._pages.keys()).sort(
|
|
1617
|
+
(a, b) => a - b,
|
|
1618
|
+
);
|
|
1578
1619
|
|
|
1579
|
-
|
|
1580
|
-
|
|
1620
|
+
for (const pageIndex of sortedPageIndexes) {
|
|
1621
|
+
const page = this._pages.get(pageIndex);
|
|
1622
|
+
if (!page) {
|
|
1623
|
+
continue;
|
|
1624
|
+
}
|
|
1581
1625
|
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
}
|
|
1626
|
+
// Sort lines by lineIndex
|
|
1627
|
+
const sortedLineIndexes = Array.from(page.keys()).sort((a, b) => a - b);
|
|
1585
1628
|
|
|
1586
|
-
|
|
1629
|
+
const lines = sortedLineIndexes.map(
|
|
1630
|
+
(lineIndex) => ` ${lineIndex}: ${page.get(lineIndex)}`,
|
|
1631
|
+
);
|
|
1632
|
+
pages.push(`Page ${pageIndex}:\n${lines.join('\n')}`);
|
|
1587
1633
|
}
|
|
1588
1634
|
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
let page = this._pages.get(pageIndex);
|
|
1592
|
-
if (!page) {
|
|
1593
|
-
page = new Map();
|
|
1594
|
-
this._pages.set(pageIndex, page);
|
|
1595
|
-
}
|
|
1635
|
+
return pages.join('\n\n');
|
|
1636
|
+
}
|
|
1596
1637
|
|
|
1597
|
-
|
|
1638
|
+
public setLine(index: ITextDocumentIndex, text: string): void {
|
|
1639
|
+
const { pageIndex, lineIndex } = index;
|
|
1640
|
+
let page = this._pages.get(pageIndex);
|
|
1641
|
+
if (!page) {
|
|
1642
|
+
page = new Map();
|
|
1643
|
+
this._pages.set(pageIndex, page);
|
|
1598
1644
|
}
|
|
1599
1645
|
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1646
|
+
page.set(lineIndex, text);
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1649
|
+
public getLine(index: ITextDocumentIndex): string | undefined {
|
|
1650
|
+
const { pageIndex, lineIndex } = index;
|
|
1651
|
+
return this._pages.get(pageIndex)?.get(lineIndex);
|
|
1652
|
+
}
|
|
1604
1653
|
}
|
|
1605
1654
|
|
|
1606
|
-
class TextDocumentIndexObserver extends AbstractObserver<
|
|
1607
|
-
|
|
1655
|
+
class TextDocumentIndexObserver extends AbstractObserver<
|
|
1656
|
+
TextDocument,
|
|
1657
|
+
string,
|
|
1658
|
+
ITextDocumentIndex
|
|
1659
|
+
> {
|
|
1660
|
+
private readonly _changeSubscription: Subscription;
|
|
1608
1661
|
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1662
|
+
constructor(
|
|
1663
|
+
owner: IDisposableOwner,
|
|
1664
|
+
private readonly _observer: TextDocumentObserver,
|
|
1665
|
+
index: ITextDocumentIndex,
|
|
1666
|
+
) {
|
|
1667
|
+
super(
|
|
1668
|
+
owner,
|
|
1669
|
+
_observer.target,
|
|
1670
|
+
_observer.target.getLine(index),
|
|
1671
|
+
new ReplaySubject(),
|
|
1672
|
+
index,
|
|
1673
|
+
);
|
|
1674
|
+
this._changeSubscription = _observer.changed.subscribe(this.onChange);
|
|
1675
|
+
}
|
|
1617
1676
|
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1677
|
+
protected override disposeInternal(): void {
|
|
1678
|
+
this._changeSubscription.unsubscribe();
|
|
1679
|
+
this._observer.dispose();
|
|
1680
|
+
}
|
|
1622
1681
|
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1682
|
+
private readonly onChange = (change: IPropertyChange) => {
|
|
1683
|
+
const changeIndex = change.index as ITextDocumentIndex;
|
|
1684
|
+
if (
|
|
1685
|
+
changeIndex.lineIndex === this.id?.lineIndex &&
|
|
1686
|
+
changeIndex.pageIndex === this.id?.pageIndex
|
|
1687
|
+
) {
|
|
1688
|
+
this.emitChange(change);
|
|
1628
1689
|
}
|
|
1690
|
+
};
|
|
1629
1691
|
}
|
|
1630
1692
|
|
|
1631
1693
|
class TextDocumentObserver extends AbstractObserver<TextDocument> {
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1694
|
+
constructor(
|
|
1695
|
+
textDocument: TextDocument,
|
|
1696
|
+
private readonly _proxyRegister: IProxyRegistry,
|
|
1697
|
+
owner?: IDisposableOwner,
|
|
1698
|
+
) {
|
|
1699
|
+
super(owner, Type.cast(undefined), textDocument);
|
|
1637
1700
|
|
|
1638
|
-
|
|
1701
|
+
this.target = new Proxy(textDocument, this);
|
|
1639
1702
|
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1703
|
+
// Always register a proxy at the proxy registry
|
|
1704
|
+
// so we can determine if an instance is a proxy or not.
|
|
1705
|
+
this._proxyRegister.register(textDocument, this.target);
|
|
1706
|
+
}
|
|
1644
1707
|
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1708
|
+
protected override disposeInternal(): void {
|
|
1709
|
+
this._proxyRegister.unregister(this.value);
|
|
1710
|
+
}
|
|
1648
1711
|
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
return Reflect.get(textDocument, property, receiver);
|
|
1667
|
-
}
|
|
1712
|
+
public get(
|
|
1713
|
+
textDocument: TextDocument,
|
|
1714
|
+
property: PropertyKey,
|
|
1715
|
+
receiver: unknown,
|
|
1716
|
+
): unknown {
|
|
1717
|
+
if (property == 'setLine') {
|
|
1718
|
+
return (index: ITextDocumentIndex, text: string) => {
|
|
1719
|
+
textDocument.setLine(index, text);
|
|
1720
|
+
this.emitChange({
|
|
1721
|
+
arguments: [],
|
|
1722
|
+
index: index,
|
|
1723
|
+
target: textDocument,
|
|
1724
|
+
newValue: text,
|
|
1725
|
+
});
|
|
1726
|
+
};
|
|
1727
|
+
} else {
|
|
1728
|
+
return Reflect.get(textDocument, property, receiver);
|
|
1668
1729
|
}
|
|
1730
|
+
}
|
|
1669
1731
|
}
|
|
1670
1732
|
|
|
1671
1733
|
// Load the state manager module into the injection container
|
|
1672
1734
|
InjectionContainer.load(RsXStateManagerModule);
|
|
1673
1735
|
|
|
1674
1736
|
const MyModule = new ContainerModule((options) => {
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
]
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1737
|
+
options
|
|
1738
|
+
.bind<TextDocumentObserverManager>(
|
|
1739
|
+
MyInjectTokens.TextDocumentObserverManager,
|
|
1740
|
+
)
|
|
1741
|
+
.to(TextDocumentObserverManager)
|
|
1742
|
+
.inSingletonScope();
|
|
1743
|
+
|
|
1744
|
+
options
|
|
1745
|
+
.bind<TextDocumenIndexObserverManager>(
|
|
1746
|
+
MyInjectTokens.TextDocumenIndexObserverManager,
|
|
1747
|
+
)
|
|
1748
|
+
.to(TextDocumenIndexObserverManager)
|
|
1749
|
+
.inSingletonScope();
|
|
1750
|
+
|
|
1751
|
+
overrideMultiInjectServices(
|
|
1752
|
+
options,
|
|
1753
|
+
RsXCoreInjectionTokens.IIndexValueAccessorList,
|
|
1754
|
+
[
|
|
1755
|
+
{
|
|
1756
|
+
target: TextDocumentIndexAccessor,
|
|
1757
|
+
token: MyInjectTokens.TextDocumentIndexAccessor,
|
|
1758
|
+
},
|
|
1759
|
+
...defaultIndexValueAccessorList,
|
|
1760
|
+
],
|
|
1761
|
+
);
|
|
1762
|
+
|
|
1763
|
+
overrideMultiInjectServices(
|
|
1764
|
+
options,
|
|
1765
|
+
RsXStateManagerInjectionTokens.IObjectObserverProxyPairFactoryList,
|
|
1766
|
+
[
|
|
1767
|
+
{
|
|
1768
|
+
target: TextDocumentObserverProxyPairFactory,
|
|
1769
|
+
token: MyInjectTokens.TextDocumentObserverProxyPairFactory,
|
|
1770
|
+
},
|
|
1771
|
+
...defaultObjectObserverProxyPairFactoryList,
|
|
1772
|
+
],
|
|
1773
|
+
);
|
|
1774
|
+
|
|
1775
|
+
overrideMultiInjectServices(
|
|
1776
|
+
options,
|
|
1777
|
+
RsXStateManagerInjectionTokens.IPropertyObserverProxyPairFactoryList,
|
|
1778
|
+
[
|
|
1779
|
+
{
|
|
1780
|
+
target: TextDocumentInxdexObserverProxyPairFactory,
|
|
1781
|
+
token: MyInjectTokens.TextDocumentInxdexObserverProxyPairFactory,
|
|
1782
|
+
},
|
|
1783
|
+
...defaultPropertyObserverProxyPairFactoryList,
|
|
1784
|
+
],
|
|
1785
|
+
);
|
|
1704
1786
|
});
|
|
1705
1787
|
|
|
1706
1788
|
InjectionContainer.load(MyModule);
|
|
1707
1789
|
|
|
1708
|
-
function testMonitorTextDocument(
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1790
|
+
function testMonitorTextDocument(
|
|
1791
|
+
stateManager: IStateManager,
|
|
1792
|
+
model: { myBook: TextDocument },
|
|
1793
|
+
): void {
|
|
1794
|
+
const bookSubscription = stateManager.changed.subscribe(() => {
|
|
1795
|
+
console.log(model.myBook.toString());
|
|
1796
|
+
});
|
|
1712
1797
|
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1798
|
+
// We observe the whole book
|
|
1799
|
+
// This will use TextDocumentObserverProxyPairFactory
|
|
1800
|
+
try {
|
|
1801
|
+
console.log('\n***********************************************');
|
|
1802
|
+
console.log('Start watching the whole book\n');
|
|
1803
|
+
console.log('My initial book:\n');
|
|
1804
|
+
stateManager.watchState(model, 'myBook', watchIndexRecursiveRule);
|
|
1805
|
+
|
|
1806
|
+
console.log('\nUpdate second line on the first page:\n');
|
|
1807
|
+
console.log('My book after change:\n');
|
|
1808
|
+
model.myBook.setLine(
|
|
1809
|
+
{ pageIndex: 0, lineIndex: 1 },
|
|
1810
|
+
'In a far far away land',
|
|
1811
|
+
);
|
|
1812
|
+
} finally {
|
|
1813
|
+
// Stop monitoring the whole book
|
|
1814
|
+
stateManager.releaseState(model, 'myBook', watchIndexRecursiveRule);
|
|
1815
|
+
bookSubscription.unsubscribe();
|
|
1816
|
+
}
|
|
1730
1817
|
}
|
|
1731
1818
|
|
|
1732
|
-
function testMonitoreSpecificLineInDocument(
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1819
|
+
function testMonitoreSpecificLineInDocument(
|
|
1820
|
+
stateManager: IStateManager,
|
|
1821
|
+
model: { myBook: TextDocument },
|
|
1822
|
+
): void {
|
|
1823
|
+
const line3OnPage1Index = { pageIndex: 0, lineIndex: 2 };
|
|
1824
|
+
const lineSubscription = stateManager.changed.subscribe(
|
|
1825
|
+
(change: IStateChange) => {
|
|
1826
|
+
const documentIndex = change.index as ITextDocumentIndex;
|
|
1827
|
+
console.log(
|
|
1828
|
+
`Line ${documentIndex.lineIndex + 1} on page ${documentIndex.pageIndex + 1} has changed to '${change.newValue}'`,
|
|
1829
|
+
);
|
|
1830
|
+
console.log('My book after change:\n');
|
|
1831
|
+
console.log(model.myBook.toString());
|
|
1832
|
+
},
|
|
1833
|
+
);
|
|
1747
1834
|
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1835
|
+
try {
|
|
1836
|
+
// Here we only watch line 3 on page 1.
|
|
1837
|
+
// Notice that the line does not have to exist yet.
|
|
1838
|
+
// The initial book does not have a line 3 on page 1.
|
|
1839
|
+
//
|
|
1840
|
+
// TextDocumentInxdexObserverProxyPairFactory is used here
|
|
1751
1841
|
|
|
1752
|
-
|
|
1753
|
-
|
|
1842
|
+
console.log('\n***********************************************');
|
|
1843
|
+
console.log('Start watching line 3 on page 1\n');
|
|
1844
|
+
stateManager.watchState(model.myBook, line3OnPage1Index);
|
|
1754
1845
|
|
|
1755
|
-
|
|
1846
|
+
const proxRegistry: IProxyRegistry = InjectionContainer.get(
|
|
1847
|
+
RsXStateManagerInjectionTokens.IProxyRegistry,
|
|
1848
|
+
);
|
|
1849
|
+
const bookProxy: TextDocument = proxRegistry.getProxy(model.myBook);
|
|
1756
1850
|
|
|
1757
|
-
|
|
1758
|
-
console.log('---');
|
|
1759
|
-
bookProxy.setLine({ pageIndex: 0, lineIndex: 0 }, 'a troll was born');
|
|
1851
|
+
bookProxy.setLine(line3OnPage1Index, 'a prince was born');
|
|
1760
1852
|
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1853
|
+
console.log('\nChanging line 1 on page 1 does not emit change:');
|
|
1854
|
+
console.log('---');
|
|
1855
|
+
bookProxy.setLine({ pageIndex: 0, lineIndex: 0 }, 'a troll was born');
|
|
1856
|
+
} finally {
|
|
1857
|
+
// Stop monitoring line 3 on page 1.
|
|
1858
|
+
stateManager.releaseState(model.myBook, line3OnPage1Index);
|
|
1859
|
+
lineSubscription.unsubscribe();
|
|
1860
|
+
}
|
|
1766
1861
|
}
|
|
1767
1862
|
|
|
1768
1863
|
export const run = (() => {
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
'They lived happily ever after.',
|
|
1781
|
-
'The end'
|
|
1782
|
-
]
|
|
1783
|
-
])
|
|
1784
|
-
};
|
|
1785
|
-
testMonitorTextDocument(stateManager, stateContext);
|
|
1786
|
-
testMonitoreSpecificLineInDocument(stateManager, stateContext);
|
|
1864
|
+
const stateManager: IStateManager = InjectionContainer.get(
|
|
1865
|
+
RsXStateManagerInjectionTokens.IStateManager,
|
|
1866
|
+
);
|
|
1867
|
+
const model = {
|
|
1868
|
+
myBook: new TextDocument([
|
|
1869
|
+
['Once upon a time', 'bla bla'],
|
|
1870
|
+
['bla bla', 'They lived happily ever after.', 'The end'],
|
|
1871
|
+
]),
|
|
1872
|
+
};
|
|
1873
|
+
testMonitorTextDocument(stateManager, model);
|
|
1874
|
+
testMonitoreSpecificLineInDocument(stateManager, model);
|
|
1787
1875
|
})();
|
|
1876
|
+
|
|
1788
1877
|
```nclude_relative ../demo/src/rs-x-state-manager/register-set.ts %}
|
|
1789
1878
|
````
|
|
1790
1879
|
|