@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 CHANGED
@@ -1,32 +1,32 @@
1
- # 🌳 SignalTree Core
1
+ # SignalTree Core
2
2
 
3
- The foundation package for SignalTree - featuring revolutionary recursive typing with deep nesting support and excellent performance.
3
+ Foundation package for SignalTree. Provides recursive typing, deep nesting support, and strong performance.
4
4
 
5
- ## ✨ What is @signaltree/core?
5
+ ## What is @signaltree/core?
6
6
 
7
- SignalTree Core is the lightweight (5.1KB gzipped) foundation that provides:
7
+ SignalTree Core is a lightweight (about 7.25KB gzipped) package that provides:
8
8
 
9
- - **πŸ”₯ Revolutionary Recursive Typing** with deep nesting support and strong type inference
10
- - **⚑ Excellent Performance** - 0.021ms at 15+ levels with consistent speed
11
- - **πŸ† Strong Type Safety** with TypeScript inference at 25+ recursive levels
12
- - **πŸ’Ύ Memory Efficient** through structural sharing and lazy signals
13
- - **🌳 Lightweight Abstractions** for recursive patterns
14
- - **πŸ“¦ Compact Bundle Size** - Complete recursive power in just 5.1KB gzipped
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
- ### πŸ”₯ Recursive Depth Performance Metrics
16
+ ### Depth performance (Sept 2025, averaged)
17
17
 
18
- Core performance scales exceptionally across all depth levels:
18
+ Indicative measurements across different depths:
19
19
 
20
- | **Depth Level** | **Execution Time** | **Type Safety** | **Performance Grade** |
21
- | -------------------------- | ------------------ | --------------- | --------------------- |
22
- | **Basic (5 levels)** | 0.012ms | βœ… Perfect | A+ Excellent |
23
- | **Medium (10 levels)** | 0.015ms | βœ… Perfect | A+ Excellent |
24
- | **Extreme (15 levels)** | **0.021ms** | βœ… Perfect | A+ **Outstanding** πŸ”₯ |
25
- | **Unlimited (20+ levels)** | 0.023ms | βœ… Perfect | A+ **Exceptional** πŸš€ |
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
- _Revolutionary achievement: Performance remains sub-millisecond with consistent scaling._
27
+ Note: Results vary by environment; figures are averaged across multiple runs.
28
28
 
29
- ## πŸš€ Quick Start
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
- ### Elegant Usage - Deep Nesting Support
37
+ ### Deep nesting example
38
38
 
39
39
  ```typescript
40
40
  import { signalTree } from '@signaltree/core';
41
41
 
42
- // Powerful: Strong type inference at deep nesting levels!
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.021, // ms - Excellent!
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
- // Perfect type inference at extreme depth - no 'any' types!
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(`Excellent performance: ${performance}ms`); // 0.021ms
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 Usage (Perfect for Getting Started)
90
+ ### Basic usage
91
91
 
92
- count: 0,
93
- message: 'Hello World',
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 components
109
+ // Use in an Angular component
105
110
  @Component({
106
- template: ` <div>Count: {{ tree.$.count() }}</div>
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 Usage (Full State Tree)
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
- ## πŸ“¦ Core Features
220
+ ## Core features
217
221
 
218
- ### 1. Hierarchical Signal Trees
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. TypeScript Inference Excellence
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. Manual State Management
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. Manual Async State Management
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. Performance Optimizations
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
- ## πŸš€ Error Handling Examples
407
+ ## Error handling examples
376
408
 
377
- ### Manual Async Error Handling
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 Update Error Handling
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
- ## πŸ”— Package Composition Patterns
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 pipe
489
- const enhancedTree = tree.pipe(
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 Enhancement Pattern
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.pipe(withDevtools());
534
+ tree = tree.with(withDevTools());
503
535
  }
504
536
 
505
537
  if (needsPerformance) {
506
- tree = tree.pipe(withBatching(), withMemoization());
538
+ tree = tree.with(withBatching(), withMemoization());
507
539
  }
508
540
 
509
541
  if (needsTimeTravel) {
510
- tree = tree.pipe(withTimeTravel());
542
+ tree = tree.with(withTimeTravel());
511
543
  }
512
544
  ```
513
545
 
514
- ### Service-Based Pattern
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
- ## ⚑ Performance Benchmarks
579
+ ## Performance benchmarks
548
580
 
549
- > **Performance Grade: A+** ⭐ - Sub-millisecond operations across all core functions
581
+ > Sub‑millisecond operations across common core functions
550
582
 
551
- ### Recursive Depth Scaling Performance
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
- _Exceptional scaling: Only 92% performance overhead for 4x depth increase_
592
+ Note: Scaling depends on state shape and hardware.
561
593
 
562
- ### SignalTree Core Performance Results (Measured)
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
- ### Advanced Performance Features
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 | **5.1KB gzipped** | **+15KB max** | Tree-shakeable |
612
+ | Bundle impact | **7.1KB gzipped** | **+15KB max** | Tree-shakeable |
581
613
 
582
- ### Developer Experience (Core Package)
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 Usage Comparison
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 Inference Speed
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
- ## 🎯 Real-World Example
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
- ## πŸ“¦ Core Features
770
+ ## Core features
739
771
 
740
- ### Hierarchical Signal Trees
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 Entity Management
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 Async State Management
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 Effects
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
- ## 🎯 Core API Reference
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
- ## πŸ”Œ Extending with Optional Packages
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 pipe
856
- const tree = signalTree(initialState).pipe(withBatching(), withMemoization(), withTimeTravel());
887
+ // Compose features using .with(...)
888
+ const tree = signalTree(initialState).with(withBatching(), withMemoization(), withTimeTravel());
857
889
  ```
858
890
 
859
- ### Available Extensions
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.5KB gzipped) - Environment-based configurations
902
+ - **@signaltree/presets** (+0.8KB gzipped) - Environment-based configurations
871
903
 
872
- ## 🎯 When to Use Core Only
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
- ## πŸ”„ Migration from NgRx
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$.pipe(
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
- ## πŸ“– Examples
959
+ ## Examples
928
960
 
929
961
  ### Simple Counter
930
962
 
@@ -994,7 +1026,7 @@ class UsersComponent {
994
1026
  }
995
1027
  ```
996
1028
 
997
- ## οΏ½ Available Extension Packages
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.5KB gzipped) - Pre-configured setups for common patterns
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
- ## οΏ½πŸ”— Links
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