@signaltree/core 1.1.7 β 2.0.0
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/README.md +118 -86
- package/fesm2022/signaltree-core.mjs +679 -345
- package/fesm2022/signaltree-core.mjs.map +1 -1
- package/index.d.ts +105 -22
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
#
|
|
1
|
+
# SignalTree Core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Foundation package for SignalTree. Provides recursive typing, deep nesting support, and strong performance.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## What is @signaltree/core?
|
|
6
6
|
|
|
7
|
-
SignalTree Core is
|
|
7
|
+
SignalTree Core is a lightweight (about 7.25KB gzipped) package that provides:
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
9
|
+
- Recursive typing with deep nesting and accurate type inference
|
|
10
|
+
- Fast operations with subβmillisecond measurements at 5β20+ levels
|
|
11
|
+
- Strong TypeScript safety across nested structures
|
|
12
|
+
- Memory efficiency via structural sharing and lazy signals
|
|
13
|
+
- Small API surface with zero-cost abstractions
|
|
14
|
+
- Compact bundle size suited for production
|
|
15
15
|
|
|
16
|
-
###
|
|
16
|
+
### Depth performance (Sept 2025, averaged)
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
Indicative measurements across different depths:
|
|
19
19
|
|
|
20
|
-
|
|
|
21
|
-
|
|
|
22
|
-
|
|
|
23
|
-
|
|
|
24
|
-
|
|
|
25
|
-
|
|
|
20
|
+
| Depth level | Avg time | Type safety | Range |
|
|
21
|
+
| ----------- | -------- | ----------- | ------------- |
|
|
22
|
+
| 5 levels | 0.061ms | β
| 0.041β0.133ms |
|
|
23
|
+
| 10 levels | 0.109ms | β
| 0.060β0.181ms |
|
|
24
|
+
| 15 levels | 0.098ms | β
| 0.088β0.126ms |
|
|
25
|
+
| 20+ levels | 0.103ms | β
| 0.100β0.106ms |
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Note: Results vary by environment; figures are averaged across multiple runs.
|
|
28
28
|
|
|
29
|
-
##
|
|
29
|
+
## Quick start
|
|
30
30
|
|
|
31
31
|
### Installation
|
|
32
32
|
|
|
@@ -34,12 +34,12 @@ _Revolutionary achievement: Performance remains sub-millisecond with consistent
|
|
|
34
34
|
npm install @signaltree/core
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
###
|
|
37
|
+
### Deep nesting example
|
|
38
38
|
|
|
39
39
|
```typescript
|
|
40
40
|
import { signalTree } from '@signaltree/core';
|
|
41
41
|
|
|
42
|
-
//
|
|
42
|
+
// Strong type inference at deep nesting levels
|
|
43
43
|
const tree = signalTree({
|
|
44
44
|
enterprise: {
|
|
45
45
|
divisions: {
|
|
@@ -58,7 +58,7 @@ const tree = signalTree({
|
|
|
58
58
|
tests: {
|
|
59
59
|
extreme: {
|
|
60
60
|
depth: 15,
|
|
61
|
-
performance: 0.
|
|
61
|
+
performance: 0.098, // ms (averaged)
|
|
62
62
|
typeInference: true,
|
|
63
63
|
},
|
|
64
64
|
},
|
|
@@ -78,19 +78,24 @@ const tree = signalTree({
|
|
|
78
78
|
},
|
|
79
79
|
});
|
|
80
80
|
|
|
81
|
-
//
|
|
81
|
+
// Type inference at deep nesting levels
|
|
82
82
|
const performance = tree.$.enterprise.divisions.technology.departments.engineering.teams.frontend.projects.signaltree.releases.v1.features.recursiveTyping.validation.tests.extreme.performance();
|
|
83
83
|
|
|
84
|
-
console.log(`
|
|
84
|
+
console.log(`Performance: ${performance}ms`); // ~0.098ms (averaged)
|
|
85
85
|
|
|
86
86
|
// Type-safe updates at unlimited depth
|
|
87
87
|
tree.$.enterprise.divisions.technology.departments.engineering.teams.frontend.projects.signaltree.releases.v1.features.recursiveTyping.validation.tests.extreme.depth.set(25); // Perfect type safety!
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
-
### Basic
|
|
90
|
+
### Basic usage
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
```typescript
|
|
93
|
+
import { signalTree } from '@signaltree/core';
|
|
94
|
+
|
|
95
|
+
// Create a simple tree
|
|
96
|
+
const tree = signalTree({
|
|
97
|
+
count: 0,
|
|
98
|
+
message: 'Hello World',
|
|
94
99
|
});
|
|
95
100
|
|
|
96
101
|
// Read values (these are Angular signals)
|
|
@@ -101,23 +106,22 @@ console.log(tree.$.message()); // 'Hello World'
|
|
|
101
106
|
tree.$.count.set(5);
|
|
102
107
|
tree.$.message.set('Updated!');
|
|
103
108
|
|
|
104
|
-
// Use in Angular
|
|
109
|
+
// Use in an Angular component
|
|
105
110
|
@Component({
|
|
106
|
-
template: `
|
|
111
|
+
template: ` <div>Count: {{ tree.$.count() }}</div>
|
|
107
112
|
<div>Message: {{ tree.$.message() }}</div>
|
|
108
113
|
<button (click)="increment()">+1</button>`,
|
|
109
114
|
})
|
|
110
115
|
class SimpleComponent {
|
|
111
|
-
tree = tree;
|
|
116
|
+
tree = tree;
|
|
112
117
|
|
|
113
|
-
increment() {
|
|
114
|
-
this.tree.$.count.update((n) => n + 1);
|
|
115
|
-
}
|
|
118
|
+
increment() {
|
|
119
|
+
this.tree.$.count.update((n) => n + 1);
|
|
120
|
+
}
|
|
116
121
|
}
|
|
122
|
+
```
|
|
117
123
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
### Intermediate Usage (Nested State)
|
|
124
|
+
### Intermediate usage (nested state)
|
|
121
125
|
|
|
122
126
|
```typescript
|
|
123
127
|
// Create hierarchical state
|
|
@@ -153,9 +157,9 @@ effect(() => {
|
|
|
153
157
|
console.log('Loading started...');
|
|
154
158
|
}
|
|
155
159
|
});
|
|
156
|
-
|
|
160
|
+
```
|
|
157
161
|
|
|
158
|
-
### Advanced
|
|
162
|
+
### Advanced usage (full state tree)
|
|
159
163
|
|
|
160
164
|
```typescript
|
|
161
165
|
interface AppState {
|
|
@@ -213,9 +217,9 @@ const currentState = tree.unwrap();
|
|
|
213
217
|
console.log('Current app state:', currentState);
|
|
214
218
|
```
|
|
215
219
|
|
|
216
|
-
##
|
|
220
|
+
## Core features
|
|
217
221
|
|
|
218
|
-
### 1
|
|
222
|
+
### 1) Hierarchical signal trees
|
|
219
223
|
|
|
220
224
|
Create deeply nested reactive state with automatic type inference:
|
|
221
225
|
|
|
@@ -232,7 +236,7 @@ tree.$.settings.theme.set('light'); // type-checked value
|
|
|
232
236
|
tree.$.todos.update((todos) => [...todos, newTodo]); // array operations
|
|
233
237
|
```
|
|
234
238
|
|
|
235
|
-
### 2
|
|
239
|
+
### 2) TypeScript inference
|
|
236
240
|
|
|
237
241
|
SignalTree provides complete type inference without manual typing:
|
|
238
242
|
|
|
@@ -258,7 +262,7 @@ tree.$.config.theme.set('light'); // β Type error ('dark' const)
|
|
|
258
262
|
tree.$.config.settings.nested.set(false); // β
boolean
|
|
259
263
|
```
|
|
260
264
|
|
|
261
|
-
### 3
|
|
265
|
+
### 3) Manual state management
|
|
262
266
|
|
|
263
267
|
Core provides basic state updates - entity management requires `@signaltree/entities`:
|
|
264
268
|
|
|
@@ -292,7 +296,7 @@ const userById = (id: string) => computed(() => tree.$.users().find((user) => us
|
|
|
292
296
|
const activeUsers = computed(() => tree.$.users().filter((user) => user.active));
|
|
293
297
|
```
|
|
294
298
|
|
|
295
|
-
### 4
|
|
299
|
+
### 4) Manual async state management
|
|
296
300
|
|
|
297
301
|
Core provides basic state updates - async helpers require `@signaltree/async`:
|
|
298
302
|
|
|
@@ -337,7 +341,35 @@ class UsersComponent {
|
|
|
337
341
|
}
|
|
338
342
|
```
|
|
339
343
|
|
|
340
|
-
### 5
|
|
344
|
+
### 5) Performance considerations
|
|
345
|
+
|
|
346
|
+
### 6) Enhancers and composition
|
|
347
|
+
|
|
348
|
+
Enhancers are optional, treeβshakable extensions that augment a `SignalTree` via `tree.with(...)`.
|
|
349
|
+
|
|
350
|
+
- `createEnhancer(meta, fn)` attaches metadata to an enhancer function
|
|
351
|
+
- Metadata fields: `name`, `requires`, `provides`
|
|
352
|
+
- Enhancers may mutate the passed tree (preferred) or return a new object
|
|
353
|
+
- A topological sort orders enhancers that declare metadata; on cycles, fallback to user order in debug mode
|
|
354
|
+
|
|
355
|
+
Examples:
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
import { signalTree } from '@signaltree/core';
|
|
359
|
+
import { withBatching } from '@signaltree/batching';
|
|
360
|
+
import { withDevtools } from '@signaltree/devtools';
|
|
361
|
+
|
|
362
|
+
// Apply in explicit order
|
|
363
|
+
const tree = signalTree({ count: 0 }).with(withBatching, withDevtools);
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Presets can provide composed enhancers for quicker onboarding:
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
import { createDevTree } from '@signaltree/presets';
|
|
370
|
+
const { enhancer } = createDevTree();
|
|
371
|
+
const tree = signalTree({ count: 0 }).with(enhancer);
|
|
372
|
+
```
|
|
341
373
|
|
|
342
374
|
Core includes several performance optimizations:
|
|
343
375
|
|
|
@@ -372,9 +404,9 @@ tree.update((state) => ({
|
|
|
372
404
|
}));
|
|
373
405
|
```
|
|
374
406
|
|
|
375
|
-
##
|
|
407
|
+
## Error handling examples
|
|
376
408
|
|
|
377
|
-
### Manual
|
|
409
|
+
### Manual async error handling
|
|
378
410
|
|
|
379
411
|
```typescript
|
|
380
412
|
const tree = signalTree({
|
|
@@ -435,7 +467,7 @@ class ErrorHandlingComponent {
|
|
|
435
467
|
}
|
|
436
468
|
```
|
|
437
469
|
|
|
438
|
-
### State
|
|
470
|
+
### State update error handling
|
|
439
471
|
|
|
440
472
|
```typescript
|
|
441
473
|
const tree = signalTree({
|
|
@@ -473,7 +505,7 @@ function safeUpdateItem(id: string, updates: Partial<Item>) {
|
|
|
473
505
|
}
|
|
474
506
|
```
|
|
475
507
|
|
|
476
|
-
##
|
|
508
|
+
## Package composition patterns
|
|
477
509
|
|
|
478
510
|
### Basic Composition
|
|
479
511
|
|
|
@@ -485,33 +517,33 @@ const tree = signalTree({
|
|
|
485
517
|
state: 'initial',
|
|
486
518
|
});
|
|
487
519
|
|
|
488
|
-
// Extend with additional packages via
|
|
489
|
-
const enhancedTree = tree.
|
|
520
|
+
// Extend with additional packages via .with(...)
|
|
521
|
+
const enhancedTree = tree.with(
|
|
490
522
|
// Add features as needed
|
|
491
523
|
someFeatureFunction()
|
|
492
524
|
);
|
|
493
525
|
```
|
|
494
526
|
|
|
495
|
-
### Modular
|
|
527
|
+
### Modular enhancement pattern
|
|
496
528
|
|
|
497
529
|
```typescript
|
|
498
530
|
// Start minimal, add features as needed
|
|
499
531
|
let tree = signalTree(initialState);
|
|
500
532
|
|
|
501
533
|
if (isDevelopment) {
|
|
502
|
-
tree = tree.
|
|
534
|
+
tree = tree.with(withDevTools());
|
|
503
535
|
}
|
|
504
536
|
|
|
505
537
|
if (needsPerformance) {
|
|
506
|
-
tree = tree.
|
|
538
|
+
tree = tree.with(withBatching(), withMemoization());
|
|
507
539
|
}
|
|
508
540
|
|
|
509
541
|
if (needsTimeTravel) {
|
|
510
|
-
tree = tree.
|
|
542
|
+
tree = tree.with(withTimeTravel());
|
|
511
543
|
}
|
|
512
544
|
```
|
|
513
545
|
|
|
514
|
-
### Service-
|
|
546
|
+
### Service-based pattern
|
|
515
547
|
|
|
516
548
|
```typescript
|
|
517
549
|
@Injectable()
|
|
@@ -544,11 +576,11 @@ class AppStateService {
|
|
|
544
576
|
}
|
|
545
577
|
```
|
|
546
578
|
|
|
547
|
-
##
|
|
579
|
+
## Performance benchmarks
|
|
548
580
|
|
|
549
|
-
>
|
|
581
|
+
> Subβmillisecond operations across common core functions
|
|
550
582
|
|
|
551
|
-
### Recursive
|
|
583
|
+
### Recursive depth scaling (illustrative)
|
|
552
584
|
|
|
553
585
|
| **Depth Level** | **Execution Time** | **Scaling Factor** | **Type Inference** | **Memory Usage** |
|
|
554
586
|
| -------------------------- | ------------------ | ------------------ | ------------------ | ---------------- |
|
|
@@ -557,9 +589,9 @@ class AppStateService {
|
|
|
557
589
|
| **Extreme (15 levels)** | **0.021ms** | **1.75x** | β
Perfect | ~1.3MB |
|
|
558
590
|
| **Unlimited (20+ levels)** | 0.023ms | 1.92x | β
Perfect | ~1.4MB |
|
|
559
591
|
|
|
560
|
-
|
|
592
|
+
Note: Scaling depends on state shape and hardware.
|
|
561
593
|
|
|
562
|
-
###
|
|
594
|
+
### Example operation timings
|
|
563
595
|
|
|
564
596
|
| Operation | SignalTree Core | Notes |
|
|
565
597
|
| --------------------------- | --------------- | ---------------- |
|
|
@@ -570,16 +602,16 @@ _Exceptional scaling: Only 92% performance overhead for 4x depth increase_
|
|
|
570
602
|
| Computation (cached) | **0.094ms** | Memoized result |
|
|
571
603
|
| Memory per 1K entities | **1.2MB** | Measured usage |
|
|
572
604
|
|
|
573
|
-
###
|
|
605
|
+
### Feature impact
|
|
574
606
|
|
|
575
607
|
| Feature | SignalTree Core | With Extensions | Notes |
|
|
576
608
|
| ------------------- | ----------------- | ---------------------- | ---------------------- |
|
|
577
609
|
| Batching efficiency | Standard | **455.8x improvement** | vs non-batched |
|
|
578
610
|
| Memoization speedup | Basic | **197.9x speedup** | vs non-memoized |
|
|
579
611
|
| Memory efficiency | **Optimized** | **Further optimized** | Lazy signals + cleanup |
|
|
580
|
-
| Bundle impact | **
|
|
612
|
+
| Bundle impact | **7.1KB gzipped** | **+15KB max** | Tree-shakeable |
|
|
581
613
|
|
|
582
|
-
### Developer
|
|
614
|
+
### Developer experience (core)
|
|
583
615
|
|
|
584
616
|
| Metric | SignalTree Core | Traditional State Mgmt | **Improvement** |
|
|
585
617
|
| ----------------------- | --------------- | ---------------------- | --------------- |
|
|
@@ -588,7 +620,7 @@ _Exceptional scaling: Only 92% performance overhead for 4x depth increase_
|
|
|
588
620
|
| Setup complexity | **Minimal** | Complex | **Simplified** |
|
|
589
621
|
| API surface | **Small** | Large | **Focused** |
|
|
590
622
|
|
|
591
|
-
### Memory
|
|
623
|
+
### Memory usage comparison
|
|
592
624
|
|
|
593
625
|
| Operation | SignalTree Core | NgRx | Akita | Native Signals |
|
|
594
626
|
| ------------------------ | --------------- | ------ | ------ | -------------- |
|
|
@@ -596,7 +628,7 @@ _Exceptional scaling: Only 92% performance overhead for 4x depth increase_
|
|
|
596
628
|
| 10K entities | 8.1MB | 28.5MB | 22.1MB | 15.2MB |
|
|
597
629
|
| Deep nesting (10 levels) | 145KB | 890KB | 720KB | 340KB |
|
|
598
630
|
|
|
599
|
-
### TypeScript
|
|
631
|
+
### TypeScript inference speed
|
|
600
632
|
|
|
601
633
|
```typescript
|
|
602
634
|
// SignalTree: Instant inference
|
|
@@ -610,7 +642,7 @@ interface State { deeply: { nested: { state: { with: { types: string } } } } }
|
|
|
610
642
|
const store: Store<State> = ...; // Requires manual interface definition
|
|
611
643
|
```
|
|
612
644
|
|
|
613
|
-
##
|
|
645
|
+
## Example
|
|
614
646
|
|
|
615
647
|
```typescript
|
|
616
648
|
// Complete user management component
|
|
@@ -735,9 +767,9 @@ console.log('Current app state:', currentState);
|
|
|
735
767
|
});
|
|
736
768
|
```
|
|
737
769
|
|
|
738
|
-
##
|
|
770
|
+
## Core features
|
|
739
771
|
|
|
740
|
-
### Hierarchical
|
|
772
|
+
### Hierarchical signal trees
|
|
741
773
|
|
|
742
774
|
```typescript
|
|
743
775
|
const tree = signalTree({
|
|
@@ -752,7 +784,7 @@ tree.$.settings.theme.set('light');
|
|
|
752
784
|
tree.$.todos.update((todos) => [...todos, newTodo]);
|
|
753
785
|
```
|
|
754
786
|
|
|
755
|
-
### Manual
|
|
787
|
+
### Manual entity management
|
|
756
788
|
|
|
757
789
|
```typescript
|
|
758
790
|
// Manual CRUD operations
|
|
@@ -778,7 +810,7 @@ const allTodos = computed(() => tree.$.todos());
|
|
|
778
810
|
const todoCount = computed(() => tree.$.todos().length);
|
|
779
811
|
```
|
|
780
812
|
|
|
781
|
-
### Manual
|
|
813
|
+
### Manual async state management
|
|
782
814
|
|
|
783
815
|
```typescript
|
|
784
816
|
async function loadUsers() {
|
|
@@ -800,7 +832,7 @@ async function handleLoadUsers() {
|
|
|
800
832
|
}
|
|
801
833
|
```
|
|
802
834
|
|
|
803
|
-
### Reactive
|
|
835
|
+
### Reactive effects
|
|
804
836
|
|
|
805
837
|
```typescript
|
|
806
838
|
// Create reactive effects
|
|
@@ -814,7 +846,7 @@ const unsubscribe = tree.subscribe((state) => {
|
|
|
814
846
|
});
|
|
815
847
|
```
|
|
816
848
|
|
|
817
|
-
##
|
|
849
|
+
## Core API reference
|
|
818
850
|
|
|
819
851
|
### signalTree()
|
|
820
852
|
|
|
@@ -842,7 +874,7 @@ tree.asyncAction(fn, config?); // Async actions (requires @signaltree/async)
|
|
|
842
874
|
tree.asyncAction(fn, config?); // Create async action
|
|
843
875
|
```
|
|
844
876
|
|
|
845
|
-
##
|
|
877
|
+
## Extending with optional packages
|
|
846
878
|
|
|
847
879
|
SignalTree Core can be extended with additional features:
|
|
848
880
|
|
|
@@ -852,11 +884,11 @@ import { withBatching } from '@signaltree/batching';
|
|
|
852
884
|
import { withMemoization } from '@signaltree/memoization';
|
|
853
885
|
import { withTimeTravel } from '@signaltree/time-travel';
|
|
854
886
|
|
|
855
|
-
// Compose features using
|
|
856
|
-
const tree = signalTree(initialState).
|
|
887
|
+
// Compose features using .with(...)
|
|
888
|
+
const tree = signalTree(initialState).with(withBatching(), withMemoization(), withTimeTravel());
|
|
857
889
|
```
|
|
858
890
|
|
|
859
|
-
### Available
|
|
891
|
+
### Available extensions
|
|
860
892
|
|
|
861
893
|
- **@signaltree/batching** (+1.1KB gzipped) - Batch multiple updates
|
|
862
894
|
- **@signaltree/memoization** (+1.7KB gzipped) - Intelligent caching & performance
|
|
@@ -867,9 +899,9 @@ const tree = signalTree(initialState).pipe(withBatching(), withMemoization(), wi
|
|
|
867
899
|
- **@signaltree/time-travel** (+1.5KB gzipped) - Undo/redo functionality
|
|
868
900
|
- **@signaltree/ng-forms** (+3.4KB gzipped) - Complete Angular forms integration
|
|
869
901
|
- **@signaltree/serialization** (+3.6KB gzipped) - State persistence & SSR support
|
|
870
|
-
- **@signaltree/presets** (+0.
|
|
902
|
+
- **@signaltree/presets** (+0.8KB gzipped) - Environment-based configurations
|
|
871
903
|
|
|
872
|
-
##
|
|
904
|
+
## When to use core only
|
|
873
905
|
|
|
874
906
|
Perfect for:
|
|
875
907
|
|
|
@@ -886,7 +918,7 @@ Consider extensions when you need:
|
|
|
886
918
|
- π Complex forms (ng-forms)
|
|
887
919
|
- π§ Middleware patterns (middleware)
|
|
888
920
|
|
|
889
|
-
##
|
|
921
|
+
## Migration from NgRx
|
|
890
922
|
|
|
891
923
|
```typescript
|
|
892
924
|
// Step 1: Create parallel tree
|
|
@@ -902,7 +934,7 @@ users = this.tree.$.users;
|
|
|
902
934
|
// Step 3: Replace effects with manual async operations
|
|
903
935
|
// Before (NgRx)
|
|
904
936
|
loadUsers$ = createEffect(() =>
|
|
905
|
-
this.actions$.
|
|
937
|
+
this.actions$.with(
|
|
906
938
|
ofType(loadUsers),
|
|
907
939
|
switchMap(() => this.api.getUsers())
|
|
908
940
|
)
|
|
@@ -924,7 +956,7 @@ loadUsers = tree.asyncAction(() => api.getUsers(), {
|
|
|
924
956
|
});
|
|
925
957
|
```
|
|
926
958
|
|
|
927
|
-
##
|
|
959
|
+
## Examples
|
|
928
960
|
|
|
929
961
|
### Simple Counter
|
|
930
962
|
|
|
@@ -994,7 +1026,7 @@ class UsersComponent {
|
|
|
994
1026
|
}
|
|
995
1027
|
```
|
|
996
1028
|
|
|
997
|
-
##
|
|
1029
|
+
## Available extension packages
|
|
998
1030
|
|
|
999
1031
|
Extend the core with optional feature packages:
|
|
1000
1032
|
|
|
@@ -1016,7 +1048,7 @@ Extend the core with optional feature packages:
|
|
|
1016
1048
|
|
|
1017
1049
|
### Integration & Convenience
|
|
1018
1050
|
|
|
1019
|
-
- **[@signaltree/presets](../presets)** (+0.
|
|
1051
|
+
- **[@signaltree/presets](../presets)** (+0.8KB gzipped) - Pre-configured setups for common patterns
|
|
1020
1052
|
- **[@signaltree/ng-forms](../ng-forms)** (+3.4KB gzipped) - Complete Angular Forms integration
|
|
1021
1053
|
|
|
1022
1054
|
### Quick Start with Extensions
|
|
@@ -1032,7 +1064,7 @@ npm install @signaltree/core @signaltree/batching @signaltree/memoization @signa
|
|
|
1032
1064
|
npm install @signaltree/core @signaltree/batching @signaltree/memoization @signaltree/middleware @signaltree/async @signaltree/entities @signaltree/devtools @signaltree/time-travel @signaltree/presets @signaltree/ng-forms
|
|
1033
1065
|
```
|
|
1034
1066
|
|
|
1035
|
-
##
|
|
1067
|
+
## Links
|
|
1036
1068
|
|
|
1037
1069
|
- [SignalTree Documentation](https://signaltree.io)
|
|
1038
1070
|
- [GitHub Repository](https://github.com/JBorgia/signaltree)
|
|
@@ -1041,7 +1073,7 @@ npm install @signaltree/core @signaltree/batching @signaltree/memoization @signa
|
|
|
1041
1073
|
|
|
1042
1074
|
## π License
|
|
1043
1075
|
|
|
1044
|
-
MIT License - see the [LICENSE](../../LICENSE) file for details.
|
|
1076
|
+
MIT License with AI Training Restriction - see the [LICENSE](../../LICENSE) file for details.
|
|
1045
1077
|
|
|
1046
1078
|
---
|
|
1047
1079
|
|