@signaltree/core 9.0.0 → 9.0.1
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 +52 -66
- package/dist/index.js +0 -1
- package/package.json +1 -6
- package/src/enhancers/types.d.ts +1 -1
- package/src/enhancers/typing/helpers-types.d.ts +1 -1
- package/src/index.d.ts +1 -2
- package/src/lib/types.d.ts +0 -26
- package/dist/enhancers/effects/effects.js +0 -74
- package/dist/enhancers/memoization/memoization.js +0 -325
- package/dist/enhancers/presets/lib/presets.js +0 -27
- package/dist/lib/presets.js +0 -30
- package/dist/presets.js +0 -2
- package/src/enhancers/memoization/index.d.ts +0 -1
- package/src/enhancers/memoization/memoization.d.ts +0 -54
- package/src/enhancers/memoization/memoization.types.d.ts +0 -1
- package/src/enhancers/memoization/test-setup.d.ts +0 -3
- package/src/enhancers/presets/index.d.ts +0 -1
- package/src/enhancers/presets/lib/presets.d.ts +0 -8
- package/src/lib/presets.d.ts +0 -34
- package/src/presets.d.ts +0 -2
package/README.md
CHANGED
|
@@ -118,7 +118,7 @@ Performance and bundle size vary by app shape, build tooling, device, and runtim
|
|
|
118
118
|
|
|
119
119
|
## Best Practices (SignalTree-First)
|
|
120
120
|
|
|
121
|
-
> 📖 **
|
|
121
|
+
> 📖 **Production app structure**: For anything beyond a single-component prototype, follow the [Recommended Default Architecture](https://github.com/JBorgia/signaltree/blob/main/docs/architecture/signaltree-architecture-guide.md#recommended-default-architecture) — it wraps the patterns below in an `AppStore` facade with a `$ + ops` split, derived tiers, and an ESLint guard against direct tree mutation from components/services. The snippets in this README are deliberately minimal and use the low-level core API directly so they stay self-contained; in real apps the mutations shown here belong inside `*Ops` classes.
|
|
122
122
|
|
|
123
123
|
Follow these principles for idiomatic SignalTree code:
|
|
124
124
|
|
|
@@ -416,17 +416,18 @@ effect(() => {
|
|
|
416
416
|
// Best Practices:
|
|
417
417
|
// 1. Use computed() for derived state that depends on signals
|
|
418
418
|
// 2. Keep computations pure - no side effects
|
|
419
|
-
// 3.
|
|
419
|
+
// 3. Angular's computed() automatically caches results
|
|
420
420
|
// 4. Chain computed values for complex transformations
|
|
421
421
|
// 5. Use factory functions for parameterized computations
|
|
422
422
|
```
|
|
423
423
|
|
|
424
|
-
### Performance optimization with
|
|
424
|
+
### Performance optimization with computed()
|
|
425
425
|
|
|
426
|
-
|
|
426
|
+
Angular's built-in `computed()` provides automatic memoization — a result is cached until one of the signals it reads from changes. No additional enhancer is required:
|
|
427
427
|
|
|
428
428
|
```typescript
|
|
429
|
-
import {
|
|
429
|
+
import { computed } from '@angular/core';
|
|
430
|
+
import { signalTree } from '@signaltree/core';
|
|
430
431
|
|
|
431
432
|
const tree = signalTree({
|
|
432
433
|
items: Array.from({ length: 10000 }, (_, i) => ({
|
|
@@ -434,9 +435,9 @@ const tree = signalTree({
|
|
|
434
435
|
value: Math.random(),
|
|
435
436
|
category: `cat-${i % 10}`,
|
|
436
437
|
})),
|
|
437
|
-
})
|
|
438
|
+
});
|
|
438
439
|
|
|
439
|
-
// Expensive computation - automatically cached by
|
|
440
|
+
// Expensive computation - automatically cached by Angular's computed()
|
|
440
441
|
const expensiveComputation = computed(() => {
|
|
441
442
|
return tree.$.items()
|
|
442
443
|
.filter((item) => item.value > 0.5)
|
|
@@ -444,9 +445,11 @@ const expensiveComputation = computed(() => {
|
|
|
444
445
|
});
|
|
445
446
|
|
|
446
447
|
// The computation only runs when tree.$.items() actually changes
|
|
447
|
-
// Subsequent calls return cached result
|
|
448
|
+
// Subsequent calls return the cached result
|
|
448
449
|
```
|
|
449
450
|
|
|
451
|
+
> **9.0.1 note:** The `memoization()` enhancer was removed. Angular's `computed()` already memoizes; the enhancer added no value on top of it.
|
|
452
|
+
|
|
450
453
|
### Advanced usage (full state tree)
|
|
451
454
|
|
|
452
455
|
```typescript
|
|
@@ -644,9 +647,8 @@ All enhancers are exported directly from `@signaltree/core`:
|
|
|
644
647
|
**Performance Enhancers:**
|
|
645
648
|
|
|
646
649
|
- `batching()` - Batch updates to reduce recomputation and rendering
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
- `withHighPerformanceMemoization()` - Optimized memoization for large state trees
|
|
650
|
+
|
|
651
|
+
> **9.0.1 note:** The `memoization()` enhancer and all preset variants were removed. Use Angular's built-in `computed()` — it provides equivalent memoization with zero additional runtime cost.
|
|
650
652
|
|
|
651
653
|
**Data Management:**
|
|
652
654
|
|
|
@@ -661,11 +663,6 @@ All enhancers are exported directly from `@signaltree/core`:
|
|
|
661
663
|
- `devTools()` - Redux DevTools auto-connect, path actions, and time-travel dispatch
|
|
662
664
|
- `withTimeTravel()` - Undo/redo functionality
|
|
663
665
|
|
|
664
|
-
**Presets:**
|
|
665
|
-
|
|
666
|
-
- `createDevTree()` - Pre-configured development setup
|
|
667
|
-
- `TREE_PRESETS` - Common configuration patterns
|
|
668
|
-
|
|
669
666
|
#### Additional Packages
|
|
670
667
|
|
|
671
668
|
These are the **only** separate packages in the SignalTree ecosystem:
|
|
@@ -691,7 +688,7 @@ const tree = signalTree({ count: 0 }).with(
|
|
|
691
688
|
**Performance-Focused Stack:**
|
|
692
689
|
|
|
693
690
|
```typescript
|
|
694
|
-
import { signalTree, batching,
|
|
691
|
+
import { signalTree, batching, entities } from '@signaltree/core';
|
|
695
692
|
|
|
696
693
|
const tree = signalTree({
|
|
697
694
|
products: entityMap<Product>(),
|
|
@@ -756,27 +753,9 @@ Enhancers can declare metadata for automatic dependency resolution:
|
|
|
756
753
|
// Enhancers are automatically ordered based on requirements
|
|
757
754
|
const tree = signalTree(state).with(
|
|
758
755
|
devTools(), // Requires: core, provides: debugging
|
|
759
|
-
batching()
|
|
760
|
-
memoization() // Requires: batching, provides: caching
|
|
756
|
+
batching() // Requires: core, provides: batching
|
|
761
757
|
);
|
|
762
|
-
// Automatically ordered: batching ->
|
|
763
|
-
```
|
|
764
|
-
|
|
765
|
-
#### Quick Start with Presets
|
|
766
|
-
|
|
767
|
-
For common patterns, use presets that combine multiple enhancers:
|
|
768
|
-
|
|
769
|
-
```typescript
|
|
770
|
-
import { createDevTree, TREE_PRESETS } from '@signaltree/core';
|
|
771
|
-
|
|
772
|
-
// Development preset includes: batching, memoization, devtools, time-travel
|
|
773
|
-
const devTree = createDevTree({
|
|
774
|
-
products: [] as Product[],
|
|
775
|
-
cart: { items: [], total: 0 },
|
|
776
|
-
});
|
|
777
|
-
|
|
778
|
-
// Or use preset configurations
|
|
779
|
-
const customTree = signalTree(state, TREE_PRESETS.DASHBOARD);
|
|
758
|
+
// Automatically ordered: batching -> devtools
|
|
780
759
|
```
|
|
781
760
|
|
|
782
761
|
#### Core Stubs
|
|
@@ -1548,15 +1527,14 @@ tree.effect(() => console.log('State changed'));
|
|
|
1548
1527
|
### Performance-Enhanced Composition
|
|
1549
1528
|
|
|
1550
1529
|
```typescript
|
|
1551
|
-
import { signalTree, batching
|
|
1530
|
+
import { signalTree, batching } from '@signaltree/core';
|
|
1552
1531
|
|
|
1553
1532
|
// Add performance optimizations
|
|
1554
1533
|
const tree = signalTree({
|
|
1555
1534
|
products: [] as Product[],
|
|
1556
1535
|
filters: { category: '', search: '' },
|
|
1557
1536
|
}).with(
|
|
1558
|
-
batching()
|
|
1559
|
-
memoization() // Cache expensive computations
|
|
1537
|
+
batching() // Batch updates for optimal rendering
|
|
1560
1538
|
);
|
|
1561
1539
|
|
|
1562
1540
|
// Now supports batched updates
|
|
@@ -1565,7 +1543,7 @@ tree.batchUpdate((state) => ({
|
|
|
1565
1543
|
filters: { category: 'electronics', search: '' },
|
|
1566
1544
|
}));
|
|
1567
1545
|
|
|
1568
|
-
//
|
|
1546
|
+
// Angular's computed() automatically caches derived values
|
|
1569
1547
|
const filteredProducts = computed(() => {
|
|
1570
1548
|
return tree.$.products()
|
|
1571
1549
|
.filter((p) => p.category.includes(tree.$.filters.category()))
|
|
@@ -1671,7 +1649,8 @@ tree.save(); // Persistence
|
|
|
1671
1649
|
```
|
|
1672
1650
|
|
|
1673
1651
|
### Aggregated Redux DevTools Instance
|
|
1674
|
-
|
|
1652
|
+
|
|
1653
|
+
````
|
|
1675
1654
|
When using multiple independent trees (e.g. per lazy-loaded feature module), each `devTools()` call creates a separate Redux DevTools instance by default. Use `aggregatedReduxInstance` to group multiple trees under a **single Redux DevTools instance**:
|
|
1676
1655
|
|
|
1677
1656
|
```typescript
|
|
@@ -1770,21 +1749,21 @@ const tree = signalTree(state).with(
|
|
|
1770
1749
|
### Preset-Based Composition
|
|
1771
1750
|
|
|
1772
1751
|
```typescript
|
|
1773
|
-
import {
|
|
1752
|
+
import { signalTree, batching, devTools, withTimeTravel } from '@signaltree/core';
|
|
1774
1753
|
|
|
1775
|
-
//
|
|
1776
|
-
const devTree =
|
|
1754
|
+
// Compose the enhancers you actually need
|
|
1755
|
+
const devTree = signalTree({
|
|
1777
1756
|
products: [],
|
|
1778
1757
|
cart: { items: [], total: 0 },
|
|
1779
1758
|
user: null,
|
|
1780
|
-
})
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
const customTree = signalTree(state, TREE_PRESETS.PERFORMANCE);
|
|
1785
|
-
// Includes: batching, memoization optimizations
|
|
1759
|
+
})
|
|
1760
|
+
.with(batching())
|
|
1761
|
+
.with(devTools())
|
|
1762
|
+
.with(withTimeTravel());
|
|
1786
1763
|
```
|
|
1787
1764
|
|
|
1765
|
+
> **9.0.1 note:** Preset factories (`createDevTree`, `TREE_PRESETS`, etc.) were removed. Compose enhancers directly with `.with()`.
|
|
1766
|
+
|
|
1788
1767
|
### Measuring bundle size
|
|
1789
1768
|
|
|
1790
1769
|
Bundle sizes depend on your build, tree-shaking, and which enhancers you include. Use the scripts in `scripts/` to analyze min+gz for your configuration.
|
|
@@ -1818,7 +1797,7 @@ if (isDevelopment) {
|
|
|
1818
1797
|
}
|
|
1819
1798
|
|
|
1820
1799
|
if (needsPerformance) {
|
|
1821
|
-
tree = tree.with(batching()
|
|
1800
|
+
tree = tree.with(batching());
|
|
1822
1801
|
}
|
|
1823
1802
|
|
|
1824
1803
|
if (needsTimeTravel) {
|
|
@@ -2101,10 +2080,10 @@ tree.destroy(); // Cleanup resources
|
|
|
2101
2080
|
SignalTree Core includes all enhancers built-in:
|
|
2102
2081
|
|
|
2103
2082
|
```typescript
|
|
2104
|
-
import { signalTree, batching,
|
|
2083
|
+
import { signalTree, batching, withTimeTravel } from '@signaltree/core';
|
|
2105
2084
|
|
|
2106
2085
|
// All enhancers available from @signaltree/core
|
|
2107
|
-
const tree = signalTree(initialState).with(batching(),
|
|
2086
|
+
const tree = signalTree(initialState).with(batching(), withTimeTravel());
|
|
2108
2087
|
```
|
|
2109
2088
|
|
|
2110
2089
|
### Available enhancers
|
|
@@ -2112,13 +2091,10 @@ const tree = signalTree(initialState).with(batching(), memoization(), withTimeTr
|
|
|
2112
2091
|
All enhancers are included in `@signaltree/core`:
|
|
2113
2092
|
|
|
2114
2093
|
- **batching()** - Batch multiple updates for better performance
|
|
2115
|
-
- **memoization()** - Intelligent caching & performance optimization
|
|
2116
2094
|
- **entities()** - Advanced entity management & CRUD operations
|
|
2117
2095
|
- **devTools()** - Redux DevTools integration for debugging
|
|
2118
2096
|
- **withTimeTravel()** - Undo/redo functionality & state history
|
|
2119
2097
|
- **serialization()** - State persistence & SSR support
|
|
2120
|
-
- **createDevTree()** - Pre-configured development setup
|
|
2121
|
-
- **TREE_PRESETS** - Common configuration patterns (PERFORMANCE, DASHBOARD, etc.)
|
|
2122
2098
|
|
|
2123
2099
|
## When to use core only
|
|
2124
2100
|
|
|
@@ -2132,7 +2108,7 @@ Perfect for:
|
|
|
2132
2108
|
|
|
2133
2109
|
Consider enhancers when you need:
|
|
2134
2110
|
|
|
2135
|
-
- ⚡ Performance optimization (batching
|
|
2111
|
+
- ⚡ Performance optimization (batching)
|
|
2136
2112
|
- 🐛 Advanced debugging (devTools, withTimeTravel)
|
|
2137
2113
|
- 📦 Entity management (entities)
|
|
2138
2114
|
|
|
@@ -2144,6 +2120,21 @@ Consider separate packages when you need:
|
|
|
2144
2120
|
|
|
2145
2121
|
## Migration from NgRx
|
|
2146
2122
|
|
|
2123
|
+
### Case Study
|
|
2124
|
+
|
|
2125
|
+
Measured from a production Angular mobile application migrating from NgRx Signal Store to SignalTree. Results reflect one team's experience; your mileage will vary depending on app complexity and existing architecture.
|
|
2126
|
+
|
|
2127
|
+
| Metric | NgRx | SignalTree | Change |
|
|
2128
|
+
| --- | --- | --- | --- |
|
|
2129
|
+
| **App state code** | 11,735 lines / 45 files | 2,825 lines / 23 files | **-76%** |
|
|
2130
|
+
| **npm packages** | 4 (@ngrx/\*) | 1 (@signaltree/core) | **-75%** |
|
|
2131
|
+
| **State bundle (gzip)** | ~50KB | ~27KB | **-46%** |
|
|
2132
|
+
| **Boilerplate files** | 17 custom `withX` helpers | 0 (built-in) | **Eliminated** |
|
|
2133
|
+
|
|
2134
|
+
13 separate stores → 1 unified tree. `entityMap()` replaced a 222-line `withEntityCrud` wrapper. Derived tiers replaced scattered `withComputed` blocks.
|
|
2135
|
+
|
|
2136
|
+
### Migration Steps
|
|
2137
|
+
|
|
2147
2138
|
```typescript
|
|
2148
2139
|
// Step 1: Create parallel tree
|
|
2149
2140
|
const tree = signalTree(initialState);
|
|
@@ -2265,7 +2256,6 @@ All enhancers are now consolidated in the core package. The following features a
|
|
|
2265
2256
|
### Performance & Optimization
|
|
2266
2257
|
|
|
2267
2258
|
- **batching()** (+1.27KB gzipped) - Batch multiple updates for better performance
|
|
2268
|
-
- **memoization()** (+2.33KB gzipped) - Intelligent caching & performance optimization
|
|
2269
2259
|
|
|
2270
2260
|
### Advanced Features
|
|
2271
2261
|
|
|
@@ -2279,8 +2269,6 @@ All enhancers are now consolidated in the core package. The following features a
|
|
|
2279
2269
|
### Integration & Convenience
|
|
2280
2270
|
|
|
2281
2271
|
- **serialization()** (+0.84KB gzipped) - State persistence & SSR support
|
|
2282
|
-
- **ecommercePreset()** - Pre-configured setups for e-commerce applications
|
|
2283
|
-
- **dashboardPreset()** - Pre-configured setups for dashboard applications
|
|
2284
2272
|
|
|
2285
2273
|
### Quick Start with Extensions
|
|
2286
2274
|
|
|
@@ -2294,13 +2282,10 @@ npm install @signaltree/core
|
|
|
2294
2282
|
import {
|
|
2295
2283
|
signalTree,
|
|
2296
2284
|
batching,
|
|
2297
|
-
memoization,
|
|
2298
2285
|
entities,
|
|
2299
2286
|
devTools,
|
|
2300
2287
|
withTimeTravel,
|
|
2301
|
-
serialization
|
|
2302
|
-
ecommercePreset,
|
|
2303
|
-
dashboardPreset
|
|
2288
|
+
serialization
|
|
2304
2289
|
} from '@signaltree/core';
|
|
2305
2290
|
```
|
|
2306
2291
|
|
|
@@ -2626,7 +2611,7 @@ export default {
|
|
|
2626
2611
|
|
|
2627
2612
|
**Start with just `@signaltree/core`** - it includes comprehensive enhancers for most applications:
|
|
2628
2613
|
|
|
2629
|
-
- Performance optimization (batching
|
|
2614
|
+
- Performance optimization (batching)
|
|
2630
2615
|
- Data management (entities, async operations)
|
|
2631
2616
|
- Development tools (devtools, time-travel)
|
|
2632
2617
|
- State persistence (serialization)
|
|
@@ -2671,3 +2656,4 @@ MIT License with AI Training Restriction - see the [LICENSE](../../LICENSE) file
|
|
|
2671
2656
|
---
|
|
2672
2657
|
|
|
2673
2658
|
**Ready to get started?** This core package provides everything you need for most applications. Add extensions only when you need them! 🚀
|
|
2659
|
+
````
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,6 @@ export { composeEnhancers, isAnySignal, isNodeAccessor, toWritableSignal } from
|
|
|
10
10
|
export { getPathNotifier } from './lib/path-notifier.js';
|
|
11
11
|
export { createEnhancer, resolveEnhancerOrder } from './enhancers/index.js';
|
|
12
12
|
export { batching } from './enhancers/batching/batching.js';
|
|
13
|
-
export { memoization } from './enhancers/memoization/memoization.js';
|
|
14
13
|
export { timeTravel } from './enhancers/time-travel/time-travel.js';
|
|
15
14
|
export { persistence, serialization } from './enhancers/serialization/serialization.js';
|
|
16
15
|
export { devTools } from './enhancers/devtools/devtools.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@signaltree/core",
|
|
3
|
-
"version": "9.0.
|
|
3
|
+
"version": "9.0.1",
|
|
4
4
|
"description": "Reactive JSON for Angular. JSON branches, reactive leaves. No actions. No reducers. No selectors.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -14,11 +14,6 @@
|
|
|
14
14
|
"import": "./dist/index.js",
|
|
15
15
|
"default": "./dist/index.js"
|
|
16
16
|
},
|
|
17
|
-
"./presets": {
|
|
18
|
-
"types": "./src/presets.d.ts",
|
|
19
|
-
"import": "./dist/presets.js",
|
|
20
|
-
"default": "./dist/presets.js"
|
|
21
|
-
},
|
|
22
17
|
"./security": {
|
|
23
18
|
"types": "./src/security.d.ts",
|
|
24
19
|
"import": "./dist/security.js",
|
package/src/enhancers/types.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { BatchingMethods, BatchingConfig,
|
|
1
|
+
export { BatchingMethods, BatchingConfig, TimeTravelMethods, TimeTravelConfig, EffectsMethods, DevToolsMethods, DevToolsConfig, EntitiesEnabled, Enhancer, EnhancerWithMeta, EnhancerMeta, } from '../lib/types';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export type Equals<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;
|
|
1
|
+
export type Equals<A, B> = (<T>() => T extends A ? 1 : 2) extends (<T>() => T extends B ? 1 : 2) ? true : false;
|
|
2
2
|
export type Assert<T extends true> = T;
|
package/src/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { signalTree } from './lib/signal-tree';
|
|
2
|
-
export type { ISignalTree, SignalTree, SignalTreeBase,
|
|
2
|
+
export type { ISignalTree, SignalTree, SignalTreeBase, TreeNode, CallableWritableSignal, AccessibleNode, NodeAccessor, Primitive, NotFn, TreeConfig, Enhancer, EnhancerMeta, EnhancerWithMeta, EntitySignal, EntityMapMarker, EntityConfig, MutationOptions, AddOptions, AddManyOptions, TimeTravelEntry, TimeTravelMethods, EnhancerCleanup, } from './lib/types';
|
|
3
3
|
export { entityMap } from './lib/types';
|
|
4
4
|
export type { ProcessDerived, DeepMergeTree, DerivedFactory, WithDerived, } from './lib/internals/derived-types';
|
|
5
5
|
export { derivedFrom, externalDerived } from './lib/internals/derived-types';
|
|
@@ -15,7 +15,6 @@ export { createEnhancer, resolveEnhancerOrder } from './enhancers/index';
|
|
|
15
15
|
export { ENHANCER_META } from './lib/types';
|
|
16
16
|
export { batching } from './enhancers/batching/batching';
|
|
17
17
|
export type { BatchingConfig, BatchingMethods } from './lib/types';
|
|
18
|
-
export { memoization } from './enhancers/memoization/memoization';
|
|
19
18
|
export { timeTravel } from './enhancers/time-travel/time-travel';
|
|
20
19
|
export { serialization, persistence, } from './enhancers/serialization/serialization';
|
|
21
20
|
export { devTools } from './enhancers/devtools/devtools';
|
package/src/lib/types.d.ts
CHANGED
|
@@ -14,13 +14,6 @@ export interface TimeTravelConfig {
|
|
|
14
14
|
[key: string]: string | undefined;
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
|
-
export interface MemoizationConfig {
|
|
18
|
-
enabled?: boolean;
|
|
19
|
-
maxCacheSize?: number;
|
|
20
|
-
ttl?: number;
|
|
21
|
-
enableLRU?: boolean;
|
|
22
|
-
equality?: 'deep' | 'shallow' | 'reference';
|
|
23
|
-
}
|
|
24
17
|
export type Primitive = string | number | boolean | null | undefined | bigint | symbol;
|
|
25
18
|
export type NotFn<T> = T extends (...args: unknown[]) => unknown ? never : T;
|
|
26
19
|
declare module '@angular/core' {
|
|
@@ -61,20 +54,6 @@ export interface BatchingMethods<T = unknown> {
|
|
|
61
54
|
hasPendingNotifications(): boolean;
|
|
62
55
|
flushNotifications(): void;
|
|
63
56
|
}
|
|
64
|
-
export interface MemoizationMethods<T> {
|
|
65
|
-
memoize<R>(fn: (state: T) => R, cacheKey?: string): Signal<R>;
|
|
66
|
-
memoizedUpdate?: (updater: (current: T) => Partial<T>, cacheKey?: string) => void;
|
|
67
|
-
clearMemoCache(key?: string): void;
|
|
68
|
-
clearCache?: (key?: string) => void;
|
|
69
|
-
getCacheStats(): CacheStats;
|
|
70
|
-
}
|
|
71
|
-
export type CacheStats = {
|
|
72
|
-
size: number;
|
|
73
|
-
hitRate: number;
|
|
74
|
-
totalHits: number;
|
|
75
|
-
totalMisses: number;
|
|
76
|
-
keys: string[];
|
|
77
|
-
};
|
|
78
57
|
export interface TimeTravelMethods<T = unknown> {
|
|
79
58
|
undo(): void;
|
|
80
59
|
redo(): void;
|
|
@@ -125,10 +104,8 @@ export interface TimeTravelEntry<T> {
|
|
|
125
104
|
state: T;
|
|
126
105
|
payload?: unknown;
|
|
127
106
|
}
|
|
128
|
-
export type TreePreset = 'basic' | 'performance' | 'development' | 'production';
|
|
129
107
|
export interface TreeConfig {
|
|
130
108
|
batchUpdates?: boolean;
|
|
131
|
-
useMemoization?: boolean;
|
|
132
109
|
enableTimeTravel?: boolean;
|
|
133
110
|
useLazySignals?: boolean;
|
|
134
111
|
useShallowComparison?: boolean;
|
|
@@ -310,9 +287,6 @@ export interface EnhancerMeta {
|
|
|
310
287
|
provides?: string[];
|
|
311
288
|
description?: string;
|
|
312
289
|
}
|
|
313
|
-
export type FullSignalTree<T> = ISignalTree<T> & EffectsMethods<T> & BatchingMethods<T> & MemoizationMethods<T> & TimeTravelMethods<T> & DevToolsMethods & EntitiesEnabled & OptimizedUpdateMethods<T>;
|
|
314
|
-
export type ProdSignalTree<T> = ISignalTree<T> & EffectsMethods<T> & BatchingMethods<T> & MemoizationMethods<T> & EntitiesEnabled & OptimizedUpdateMethods<T>;
|
|
315
|
-
export type MinimalSignalTree<T> = ISignalTree<T> & EffectsMethods<T>;
|
|
316
290
|
export type SignalTree<T> = ISignalTree<T> & TreeNode<T>;
|
|
317
291
|
export type SignalTreeBase<T> = ISignalTree<T> & TreeNode<T>;
|
|
318
292
|
export declare function isSignalTree<T>(value: unknown): value is ISignalTree<T>;
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { effect, untracked } from '@angular/core';
|
|
2
|
-
import { ENHANCER_META } from '../../lib/types.js';
|
|
3
|
-
|
|
4
|
-
function effects(config = {}) {
|
|
5
|
-
const {
|
|
6
|
-
enabled = true
|
|
7
|
-
} = config;
|
|
8
|
-
const enhancerFn = tree => {
|
|
9
|
-
const cleanupFns = [];
|
|
10
|
-
const methods = {
|
|
11
|
-
effect(effectFn) {
|
|
12
|
-
if (!enabled) {
|
|
13
|
-
return () => {};
|
|
14
|
-
}
|
|
15
|
-
let innerCleanup;
|
|
16
|
-
const effectRef = effect(() => {
|
|
17
|
-
const state = tree();
|
|
18
|
-
if (innerCleanup) {
|
|
19
|
-
untracked(() => innerCleanup());
|
|
20
|
-
}
|
|
21
|
-
innerCleanup = untracked(() => effectFn(state));
|
|
22
|
-
});
|
|
23
|
-
const cleanup = () => {
|
|
24
|
-
if (innerCleanup) {
|
|
25
|
-
innerCleanup();
|
|
26
|
-
}
|
|
27
|
-
effectRef.destroy();
|
|
28
|
-
};
|
|
29
|
-
cleanupFns.push(cleanup);
|
|
30
|
-
return cleanup;
|
|
31
|
-
},
|
|
32
|
-
subscribe(fn) {
|
|
33
|
-
if (!enabled) {
|
|
34
|
-
return () => {};
|
|
35
|
-
}
|
|
36
|
-
const effectRef = effect(() => {
|
|
37
|
-
const state = tree();
|
|
38
|
-
untracked(() => fn(state));
|
|
39
|
-
});
|
|
40
|
-
const cleanup = () => {
|
|
41
|
-
effectRef.destroy();
|
|
42
|
-
};
|
|
43
|
-
cleanupFns.push(cleanup);
|
|
44
|
-
return cleanup;
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
const originalDestroy = tree.destroy?.bind(tree);
|
|
48
|
-
tree.destroy = () => {
|
|
49
|
-
cleanupFns.forEach(fn => fn());
|
|
50
|
-
cleanupFns.length = 0;
|
|
51
|
-
if (originalDestroy) {
|
|
52
|
-
originalDestroy();
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
return Object.assign(tree, methods);
|
|
56
|
-
};
|
|
57
|
-
const meta = {
|
|
58
|
-
name: 'effects',
|
|
59
|
-
provides: ['effects']
|
|
60
|
-
};
|
|
61
|
-
enhancerFn.metadata = meta;
|
|
62
|
-
enhancerFn[ENHANCER_META] = meta;
|
|
63
|
-
return enhancerFn;
|
|
64
|
-
}
|
|
65
|
-
function enableEffects() {
|
|
66
|
-
return effects({
|
|
67
|
-
enabled: true
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
Object.assign((config = {}) => effects(config), {
|
|
71
|
-
enable: enableEffects
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
export { effects, enableEffects };
|
|
@@ -1,325 +0,0 @@
|
|
|
1
|
-
import { computed } from '@angular/core';
|
|
2
|
-
import { isNodeAccessor } from '../../lib/utils.js';
|
|
3
|
-
import { ENHANCER_META } from '../../lib/types.js';
|
|
4
|
-
import { LRUCache } from '../../shared/lib/lru-cache.js';
|
|
5
|
-
import { deepEqual } from '../../shared/lib/deep-equal.js';
|
|
6
|
-
|
|
7
|
-
function isDevMode() {
|
|
8
|
-
if (typeof __DEV__ !== 'undefined') {
|
|
9
|
-
return __DEV__;
|
|
10
|
-
}
|
|
11
|
-
return false;
|
|
12
|
-
}
|
|
13
|
-
const MAX_CACHE_SIZE = 1000;
|
|
14
|
-
const memoizationCache = new Map();
|
|
15
|
-
function createMemoCacheStore(maxSize, enableLRU) {
|
|
16
|
-
if (enableLRU) {
|
|
17
|
-
const cache = new LRUCache(maxSize);
|
|
18
|
-
const shadow = new Map();
|
|
19
|
-
const pruneShadow = () => {
|
|
20
|
-
while (shadow.size > cache.size()) {
|
|
21
|
-
const oldestKey = shadow.keys().next().value;
|
|
22
|
-
if (oldestKey === undefined) {
|
|
23
|
-
break;
|
|
24
|
-
}
|
|
25
|
-
shadow.delete(oldestKey);
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
return {
|
|
29
|
-
get: key => {
|
|
30
|
-
const value = cache.get(key);
|
|
31
|
-
if (value !== undefined) {
|
|
32
|
-
shadow.set(key, value);
|
|
33
|
-
} else if (shadow.has(key)) {
|
|
34
|
-
shadow.delete(key);
|
|
35
|
-
}
|
|
36
|
-
return value;
|
|
37
|
-
},
|
|
38
|
-
set: (key, value) => {
|
|
39
|
-
cache.set(key, value);
|
|
40
|
-
shadow.set(key, value);
|
|
41
|
-
pruneShadow();
|
|
42
|
-
},
|
|
43
|
-
delete: key => {
|
|
44
|
-
cache.delete(key);
|
|
45
|
-
shadow.delete(key);
|
|
46
|
-
},
|
|
47
|
-
clear: () => {
|
|
48
|
-
cache.clear();
|
|
49
|
-
shadow.clear();
|
|
50
|
-
},
|
|
51
|
-
size: () => shadow.size,
|
|
52
|
-
forEach: callback => {
|
|
53
|
-
shadow.forEach((value, key) => callback(value, key));
|
|
54
|
-
},
|
|
55
|
-
keys: () => shadow.keys()
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
const store = new Map();
|
|
59
|
-
return {
|
|
60
|
-
get: key => store.get(key),
|
|
61
|
-
set: (key, value) => {
|
|
62
|
-
store.set(key, value);
|
|
63
|
-
},
|
|
64
|
-
delete: key => store.delete(key),
|
|
65
|
-
clear: () => store.clear(),
|
|
66
|
-
size: () => store.size,
|
|
67
|
-
forEach: callback => {
|
|
68
|
-
store.forEach((value, key) => callback(value, key));
|
|
69
|
-
},
|
|
70
|
-
keys: () => store.keys()
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
function getCleanupInterval(tree) {
|
|
74
|
-
return tree._memoCleanupInterval;
|
|
75
|
-
}
|
|
76
|
-
function setCleanupInterval(tree, interval) {
|
|
77
|
-
if (interval === undefined) {
|
|
78
|
-
delete tree._memoCleanupInterval;
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
tree._memoCleanupInterval = interval;
|
|
82
|
-
}
|
|
83
|
-
function clearCleanupInterval(tree) {
|
|
84
|
-
const interval = getCleanupInterval(tree);
|
|
85
|
-
if (!interval) {
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
try {
|
|
89
|
-
clearInterval(interval);
|
|
90
|
-
} catch {}
|
|
91
|
-
setCleanupInterval(tree);
|
|
92
|
-
}
|
|
93
|
-
function shallowEqual(a, b) {
|
|
94
|
-
if (a === b) return true;
|
|
95
|
-
if (a == null || b == null) return false;
|
|
96
|
-
if (typeof a !== typeof b) return false;
|
|
97
|
-
if (typeof a === 'object' && typeof b === 'object') {
|
|
98
|
-
const objA = a;
|
|
99
|
-
const objB = b;
|
|
100
|
-
let countA = 0;
|
|
101
|
-
for (const key in objA) {
|
|
102
|
-
if (!Object.prototype.hasOwnProperty.call(objA, key)) continue;
|
|
103
|
-
countA++;
|
|
104
|
-
if (!(key in objB) || objA[key] !== objB[key]) return false;
|
|
105
|
-
}
|
|
106
|
-
let countB = 0;
|
|
107
|
-
for (const key in objB) {
|
|
108
|
-
if (Object.prototype.hasOwnProperty.call(objB, key)) countB++;
|
|
109
|
-
}
|
|
110
|
-
return countA === countB;
|
|
111
|
-
}
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
function generateCacheKey(fn, args) {
|
|
115
|
-
try {
|
|
116
|
-
return `${fn.name || 'anonymous'}_${JSON.stringify(args)}`;
|
|
117
|
-
} catch {
|
|
118
|
-
return `${fn.name || 'anonymous'}_${args.length}`;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
function getEqualityFn(strategy) {
|
|
122
|
-
switch (strategy) {
|
|
123
|
-
case 'shallow':
|
|
124
|
-
return shallowEqual;
|
|
125
|
-
case 'reference':
|
|
126
|
-
return (a, b) => a === b;
|
|
127
|
-
case 'deep':
|
|
128
|
-
default:
|
|
129
|
-
return deepEqual;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
const MEMOIZATION_PRESETS = {
|
|
133
|
-
selector: {
|
|
134
|
-
equality: 'reference',
|
|
135
|
-
maxCacheSize: 10,
|
|
136
|
-
enableLRU: false,
|
|
137
|
-
ttl: undefined
|
|
138
|
-
},
|
|
139
|
-
computed: {
|
|
140
|
-
equality: 'shallow',
|
|
141
|
-
maxCacheSize: 100,
|
|
142
|
-
enableLRU: false,
|
|
143
|
-
ttl: undefined
|
|
144
|
-
},
|
|
145
|
-
deepState: {
|
|
146
|
-
equality: 'deep',
|
|
147
|
-
maxCacheSize: 1000,
|
|
148
|
-
enableLRU: true,
|
|
149
|
-
ttl: 5 * 60 * 1000
|
|
150
|
-
},
|
|
151
|
-
highFrequency: {
|
|
152
|
-
equality: 'reference',
|
|
153
|
-
maxCacheSize: 5,
|
|
154
|
-
enableLRU: false,
|
|
155
|
-
ttl: undefined
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
function selectorMemoization() {
|
|
159
|
-
return memoization(MEMOIZATION_PRESETS.selector);
|
|
160
|
-
}
|
|
161
|
-
function computedMemoization() {
|
|
162
|
-
return memoization(MEMOIZATION_PRESETS.computed);
|
|
163
|
-
}
|
|
164
|
-
function deepStateMemoization() {
|
|
165
|
-
return memoization(MEMOIZATION_PRESETS.deepState);
|
|
166
|
-
}
|
|
167
|
-
function highFrequencyMemoization() {
|
|
168
|
-
return memoization(MEMOIZATION_PRESETS.highFrequency);
|
|
169
|
-
}
|
|
170
|
-
Object.assign((config = {}) => memoization(config), {
|
|
171
|
-
selector: selectorMemoization,
|
|
172
|
-
computed: computedMemoization,
|
|
173
|
-
deep: deepStateMemoization,
|
|
174
|
-
fast: highFrequencyMemoization
|
|
175
|
-
});
|
|
176
|
-
function memoization(config = {}) {
|
|
177
|
-
const {
|
|
178
|
-
enabled = true,
|
|
179
|
-
maxCacheSize = 1000,
|
|
180
|
-
ttl,
|
|
181
|
-
equality = 'deep',
|
|
182
|
-
enableLRU = true
|
|
183
|
-
} = config;
|
|
184
|
-
const enhancer = tree => {
|
|
185
|
-
const originalTreeCall = tree.bind(tree);
|
|
186
|
-
const applyUpdateResult = result => {
|
|
187
|
-
Object.entries(result).forEach(([propKey, value]) => {
|
|
188
|
-
const property = tree.state[propKey];
|
|
189
|
-
if (property && 'set' in property) {
|
|
190
|
-
property.set(value);
|
|
191
|
-
} else if (isNodeAccessor(property)) {
|
|
192
|
-
property(value);
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
};
|
|
196
|
-
if (!enabled) {
|
|
197
|
-
const memoTree = tree;
|
|
198
|
-
memoTree.memoize = (fn, _cacheKey) => {
|
|
199
|
-
return computed(() => fn(originalTreeCall()));
|
|
200
|
-
};
|
|
201
|
-
memoTree.memoizedUpdate = updater => {
|
|
202
|
-
const currentState = originalTreeCall();
|
|
203
|
-
const result = updater(currentState);
|
|
204
|
-
applyUpdateResult(result);
|
|
205
|
-
};
|
|
206
|
-
memoTree.clearMemoCache = () => {};
|
|
207
|
-
memoTree.clearCache = memoTree.clearMemoCache;
|
|
208
|
-
memoTree.getCacheStats = () => ({
|
|
209
|
-
size: 0,
|
|
210
|
-
hitRate: 0,
|
|
211
|
-
totalHits: 0,
|
|
212
|
-
totalMisses: 0,
|
|
213
|
-
keys: []
|
|
214
|
-
});
|
|
215
|
-
return memoTree;
|
|
216
|
-
}
|
|
217
|
-
const cache = createMemoCacheStore(maxCacheSize, enableLRU);
|
|
218
|
-
memoizationCache.set(tree, cache);
|
|
219
|
-
const equalityFn = getEqualityFn(equality);
|
|
220
|
-
tree.memoizedUpdate = (updater, cacheKey) => {
|
|
221
|
-
const currentState = originalTreeCall();
|
|
222
|
-
const key = cacheKey || generateCacheKey(updater, [currentState]);
|
|
223
|
-
const cached = cache.get(key);
|
|
224
|
-
if (cached && equalityFn(cached.deps, [currentState])) {
|
|
225
|
-
const cachedUpdate = cached.value;
|
|
226
|
-
applyUpdateResult(cachedUpdate);
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
const result = updater(currentState);
|
|
230
|
-
cache.set(key, {
|
|
231
|
-
value: result,
|
|
232
|
-
deps: [currentState],
|
|
233
|
-
timestamp: Date.now(),
|
|
234
|
-
hitCount: 1
|
|
235
|
-
});
|
|
236
|
-
applyUpdateResult(result);
|
|
237
|
-
};
|
|
238
|
-
const memoizeResultCache = createMemoCacheStore(MAX_CACHE_SIZE, true);
|
|
239
|
-
tree.memoize = (fn, cacheKey) => {
|
|
240
|
-
return computed(() => {
|
|
241
|
-
const currentState = originalTreeCall();
|
|
242
|
-
const key = cacheKey || generateCacheKey(fn, [currentState]);
|
|
243
|
-
const cached = memoizeResultCache.get(key);
|
|
244
|
-
if (cached && equalityFn(cached.deps, [currentState])) {
|
|
245
|
-
return cached.value;
|
|
246
|
-
}
|
|
247
|
-
if (isDevMode() && tree.__devHooks?.onRecompute) {
|
|
248
|
-
try {
|
|
249
|
-
tree.__devHooks.onRecompute(key, 1);
|
|
250
|
-
} catch {}
|
|
251
|
-
}
|
|
252
|
-
const result = fn(currentState);
|
|
253
|
-
memoizeResultCache.set(key, {
|
|
254
|
-
value: result,
|
|
255
|
-
deps: [currentState],
|
|
256
|
-
timestamp: Date.now(),
|
|
257
|
-
hitCount: 1
|
|
258
|
-
});
|
|
259
|
-
return result;
|
|
260
|
-
});
|
|
261
|
-
};
|
|
262
|
-
tree.clearMemoCache = key => {
|
|
263
|
-
if (key) {
|
|
264
|
-
cache.delete(key);
|
|
265
|
-
} else {
|
|
266
|
-
cache.clear();
|
|
267
|
-
}
|
|
268
|
-
};
|
|
269
|
-
tree.clearCache = tree.clearMemoCache;
|
|
270
|
-
tree.getCacheStats = () => {
|
|
271
|
-
let totalHits = 0;
|
|
272
|
-
let totalMisses = 0;
|
|
273
|
-
cache.forEach(entry => {
|
|
274
|
-
totalHits += entry.hitCount || 0;
|
|
275
|
-
totalMisses += Math.floor((entry.hitCount || 0) / 2);
|
|
276
|
-
});
|
|
277
|
-
const hitRate = totalHits + totalMisses > 0 ? totalHits / (totalHits + totalMisses) : 0;
|
|
278
|
-
return {
|
|
279
|
-
size: cache.size(),
|
|
280
|
-
hitRate,
|
|
281
|
-
totalHits,
|
|
282
|
-
totalMisses,
|
|
283
|
-
keys: Array.from(cache.keys())
|
|
284
|
-
};
|
|
285
|
-
};
|
|
286
|
-
const maybeInterval = getCleanupInterval(tree);
|
|
287
|
-
if (maybeInterval) {
|
|
288
|
-
const origClear = tree.clearMemoCache.bind(tree);
|
|
289
|
-
tree.clearMemoCache = key => {
|
|
290
|
-
origClear(key);
|
|
291
|
-
clearCleanupInterval(tree);
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
tree.clearCache = tree.clearMemoCache;
|
|
295
|
-
if (ttl) {
|
|
296
|
-
const cleanup = () => {
|
|
297
|
-
const now = Date.now();
|
|
298
|
-
cache.forEach((entry, key) => {
|
|
299
|
-
if (entry.timestamp && now - entry.timestamp > ttl) {
|
|
300
|
-
cache.delete(key);
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
|
-
};
|
|
304
|
-
const intervalId = setInterval(cleanup, ttl);
|
|
305
|
-
setCleanupInterval(tree, intervalId);
|
|
306
|
-
}
|
|
307
|
-
if (typeof tree.registerCleanup === 'function') {
|
|
308
|
-
tree.registerCleanup(() => {
|
|
309
|
-
clearCleanupInterval(tree);
|
|
310
|
-
cache.clear();
|
|
311
|
-
memoizationCache.delete(tree);
|
|
312
|
-
});
|
|
313
|
-
}
|
|
314
|
-
return tree;
|
|
315
|
-
};
|
|
316
|
-
const meta = {
|
|
317
|
-
name: 'memoization',
|
|
318
|
-
provides: ['memoization']
|
|
319
|
-
};
|
|
320
|
-
enhancer.metadata = meta;
|
|
321
|
-
enhancer[ENHANCER_META] = meta;
|
|
322
|
-
return enhancer;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
export { MEMOIZATION_PRESETS, computedMemoization, deepStateMemoization, highFrequencyMemoization, memoization, selectorMemoization };
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
const TREE_PRESETS = {};
|
|
2
|
-
function createPresetConfig(preset, overrides = {}) {
|
|
3
|
-
return {
|
|
4
|
-
...overrides
|
|
5
|
-
};
|
|
6
|
-
}
|
|
7
|
-
function validatePreset(preset) {
|
|
8
|
-
return typeof preset === 'string';
|
|
9
|
-
}
|
|
10
|
-
function getAvailablePresets() {
|
|
11
|
-
return Object.keys(TREE_PRESETS);
|
|
12
|
-
}
|
|
13
|
-
function combinePresets(presets, overrides = {}) {
|
|
14
|
-
let combined = {};
|
|
15
|
-
for (const p of presets) {
|
|
16
|
-
combined = {
|
|
17
|
-
...combined,
|
|
18
|
-
...TREE_PRESETS[p]
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
return {
|
|
22
|
-
...combined,
|
|
23
|
-
...overrides
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export { TREE_PRESETS, combinePresets, createPresetConfig, getAvailablePresets, validatePreset };
|
package/dist/lib/presets.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { signalTree } from './signal-tree.js';
|
|
2
|
-
import { effects } from '../enhancers/effects/effects.js';
|
|
3
|
-
import { batching } from '../enhancers/batching/batching.js';
|
|
4
|
-
import { memoization } from '../enhancers/memoization/memoization.js';
|
|
5
|
-
import { timeTravel } from '../enhancers/time-travel/time-travel.js';
|
|
6
|
-
import { devTools } from '../enhancers/devtools/devtools.js';
|
|
7
|
-
|
|
8
|
-
function createDevTree(initialState, config = {}) {
|
|
9
|
-
if (arguments.length === 0) {
|
|
10
|
-
const enhancer = tree => tree.with(effects()).with(batching()).with(memoization()).with(timeTravel()).with(devTools());
|
|
11
|
-
return {
|
|
12
|
-
enhancer
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
const base = signalTree(initialState, config);
|
|
16
|
-
const enhanced = base.with(effects()).with(batching(config.batching)).with(memoization(config.memoization)).with(timeTravel(config.timeTravel)).with(devTools(config.devTools));
|
|
17
|
-
return enhanced;
|
|
18
|
-
}
|
|
19
|
-
function createProdTree(initialState, config = {}) {
|
|
20
|
-
const base = signalTree(initialState, config);
|
|
21
|
-
const enhanced = base.with(effects()).with(batching(config.batching)).with(memoization(config.memoization));
|
|
22
|
-
return enhanced;
|
|
23
|
-
}
|
|
24
|
-
function createMinimalTree(initialState, config = {}) {
|
|
25
|
-
const base = signalTree(initialState, config);
|
|
26
|
-
const enhanced = base.with(effects());
|
|
27
|
-
return enhanced;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export { createDevTree, createMinimalTree, createProdTree };
|
package/dist/presets.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './memoization';
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import type { ISignalTree } from '../../lib/types';
|
|
2
|
-
export declare function cleanupMemoizationCache(): void;
|
|
3
|
-
import type { MemoizationConfig, MemoizationMethods } from '../../lib/types';
|
|
4
|
-
export declare function memoize<TArgs extends unknown[], TReturn>(fn: (...args: TArgs) => TReturn, keyFn?: (...args: TArgs) => string, config?: MemoizationConfig): (...args: TArgs) => TReturn;
|
|
5
|
-
export declare function memoizeShallow<TArgs extends unknown[], TReturn>(fn: (...args: TArgs) => TReturn, keyFn?: (...args: TArgs) => string): (...args: TArgs) => TReturn;
|
|
6
|
-
export declare function memoizeReference<TArgs extends unknown[], TReturn>(fn: (...args: TArgs) => TReturn, keyFn?: (...args: TArgs) => string): (...args: TArgs) => TReturn;
|
|
7
|
-
export declare const MEMOIZATION_PRESETS: {
|
|
8
|
-
readonly selector: {
|
|
9
|
-
readonly equality: "reference";
|
|
10
|
-
readonly maxCacheSize: 10;
|
|
11
|
-
readonly enableLRU: false;
|
|
12
|
-
readonly ttl: undefined;
|
|
13
|
-
};
|
|
14
|
-
readonly computed: {
|
|
15
|
-
readonly equality: "shallow";
|
|
16
|
-
readonly maxCacheSize: 100;
|
|
17
|
-
readonly enableLRU: false;
|
|
18
|
-
readonly ttl: undefined;
|
|
19
|
-
};
|
|
20
|
-
readonly deepState: {
|
|
21
|
-
readonly equality: "deep";
|
|
22
|
-
readonly maxCacheSize: 1000;
|
|
23
|
-
readonly enableLRU: true;
|
|
24
|
-
readonly ttl: number;
|
|
25
|
-
};
|
|
26
|
-
readonly highFrequency: {
|
|
27
|
-
readonly equality: "reference";
|
|
28
|
-
readonly maxCacheSize: 5;
|
|
29
|
-
readonly enableLRU: false;
|
|
30
|
-
readonly ttl: undefined;
|
|
31
|
-
};
|
|
32
|
-
};
|
|
33
|
-
export declare function selectorMemoization(): <T>(tree: ISignalTree<T>) => ISignalTree<T> & MemoizationMethods<T>;
|
|
34
|
-
export declare function computedMemoization(): <T>(tree: ISignalTree<T>) => ISignalTree<T> & MemoizationMethods<T>;
|
|
35
|
-
export declare function deepStateMemoization(): <T>(tree: ISignalTree<T>) => ISignalTree<T> & MemoizationMethods<T>;
|
|
36
|
-
export declare function highFrequencyMemoization(): <T>(tree: ISignalTree<T>) => ISignalTree<T> & MemoizationMethods<T>;
|
|
37
|
-
export declare const withMemoization: ((config?: MemoizationConfig) => <T>(tree: ISignalTree<T>) => ISignalTree<T> & MemoizationMethods<T>) & {
|
|
38
|
-
selector: typeof selectorMemoization;
|
|
39
|
-
computed: typeof computedMemoization;
|
|
40
|
-
deep: typeof deepStateMemoization;
|
|
41
|
-
fast: typeof highFrequencyMemoization;
|
|
42
|
-
};
|
|
43
|
-
export declare function memoization(config?: MemoizationConfig): <T>(tree: ISignalTree<T>) => ISignalTree<T> & MemoizationMethods<T>;
|
|
44
|
-
export declare function enableMemoization(): <T>(tree: ISignalTree<T>) => ISignalTree<T> & MemoizationMethods<T>;
|
|
45
|
-
export declare function highPerformanceMemoization(): <T>(tree: ISignalTree<T>) => ISignalTree<T> & MemoizationMethods<T>;
|
|
46
|
-
export declare function lightweightMemoization(): <T>(tree: ISignalTree<T>) => ISignalTree<T> & MemoizationMethods<T>;
|
|
47
|
-
export declare function shallowMemoization(): <T>(tree: ISignalTree<T>) => ISignalTree<T> & MemoizationMethods<T>;
|
|
48
|
-
export declare function clearAllCaches(): void;
|
|
49
|
-
export declare function getGlobalCacheStats(): {
|
|
50
|
-
treeCount: number;
|
|
51
|
-
totalSize: number;
|
|
52
|
-
totalHits: number;
|
|
53
|
-
averageCacheSize: number;
|
|
54
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './lib/presets';
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { createDevTree, createMinimalTree, createProdTree } from '../../../lib/presets';
|
|
2
|
-
import type { TreeConfig, TreePreset } from '../../../lib/types';
|
|
3
|
-
export declare const TREE_PRESETS: Record<TreePreset, Partial<TreeConfig>>;
|
|
4
|
-
export declare function createPresetConfig(preset: TreePreset, overrides?: Partial<TreeConfig>): TreeConfig;
|
|
5
|
-
export declare function validatePreset(preset: TreePreset): boolean;
|
|
6
|
-
export declare function getAvailablePresets(): TreePreset[];
|
|
7
|
-
export declare function combinePresets(presets: TreePreset[], overrides?: Partial<TreeConfig>): TreeConfig;
|
|
8
|
-
export { createDevTree, createProdTree, createMinimalTree };
|
package/src/lib/presets.d.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type { ISignalTree, TreeConfig, BatchingConfig, MemoizationConfig, TimeTravelConfig, DevToolsConfig, BatchingMethods, MemoizationMethods, TimeTravelMethods, DevToolsMethods, EffectsMethods, EntitiesEnabled } from './types';
|
|
2
|
-
export interface DevTreeConfig extends TreeConfig {
|
|
3
|
-
effects?: Record<string, never>;
|
|
4
|
-
batching?: BatchingConfig;
|
|
5
|
-
memoization?: MemoizationConfig;
|
|
6
|
-
timeTravel?: TimeTravelConfig;
|
|
7
|
-
devTools?: DevToolsConfig;
|
|
8
|
-
entities?: Record<string, never>;
|
|
9
|
-
}
|
|
10
|
-
export interface ProdTreeConfig extends TreeConfig {
|
|
11
|
-
effects?: Record<string, never>;
|
|
12
|
-
batching?: BatchingConfig;
|
|
13
|
-
memoization?: MemoizationConfig;
|
|
14
|
-
entities?: Record<string, never>;
|
|
15
|
-
}
|
|
16
|
-
export interface MinimalTreeConfig extends TreeConfig {
|
|
17
|
-
effects?: Record<string, never>;
|
|
18
|
-
}
|
|
19
|
-
export type FullSignalTree<T> = ISignalTree<T> & EffectsMethods<T> & BatchingMethods & MemoizationMethods<T> & EntitiesEnabled & TimeTravelMethods & DevToolsMethods;
|
|
20
|
-
export type ProdSignalTree<T> = ISignalTree<T> & EffectsMethods<T> & BatchingMethods & MemoizationMethods<T> & EntitiesEnabled;
|
|
21
|
-
export type MinimalSignalTree<T> = ISignalTree<T> & EffectsMethods<T>;
|
|
22
|
-
export declare function createDevTree<T extends object>(initialState: T, config?: DevTreeConfig): FullSignalTree<T>;
|
|
23
|
-
export declare function createDevTree(): {
|
|
24
|
-
enhancer: <T>(tree: ISignalTree<T>) => ISignalTree<T> & EffectsMethods<T> & BatchingMethods<T> & MemoizationMethods<T> & EntitiesEnabled & TimeTravelMethods<T> & DevToolsMethods;
|
|
25
|
-
};
|
|
26
|
-
export declare function createProdTree<T extends object>(initialState: T, config?: ProdTreeConfig): ProdSignalTree<T>;
|
|
27
|
-
export declare function createMinimalTree<T extends object>(initialState: T, config?: MinimalTreeConfig): MinimalSignalTree<T>;
|
|
28
|
-
export declare const devTree: typeof createDevTree;
|
|
29
|
-
export declare const prodTree: typeof createProdTree;
|
|
30
|
-
export declare const minimalTree: typeof createMinimalTree;
|
|
31
|
-
export declare function buildTree<T extends object>(initialState: T, config?: TreeConfig): {
|
|
32
|
-
add<R>(enhancer: (t: ISignalTree<T>) => R): any;
|
|
33
|
-
done(): ISignalTree<T>;
|
|
34
|
-
};
|
package/src/presets.d.ts
DELETED