@signaltree/core 9.0.0 → 9.1.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
@@ -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
- > 📖 **Full guide**: [Implementation Patterns](https://github.com/JBorgia/signaltree/blob/main/docs/IMPLEMENTATION_PATTERNS.md)
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. Leverage automatic memoization for expensive operations
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 memoization
424
+ ### Performance optimization with computed()
425
425
 
426
- Computed values become even more powerful with the built-in memoization enhancer:
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 { signalTree, memoization } from '@signaltree/core';
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
- }).with(memoization());
438
+ });
438
439
 
439
- // Expensive computation - automatically cached by memoization enhancer
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
- - `memoization()` - Intelligent caching for expensive computations
648
- - `highPerformanceBatching()` - Advanced batching for high-frequency updates
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, memoization, entities } from '@signaltree/core';
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(), // Requires: core, provides: batching
760
- memoization() // Requires: batching, provides: caching
756
+ batching() // Requires: core, provides: batching
761
757
  );
762
- // Automatically ordered: batching -> memoization -> devtools
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, memoization } from '@signaltree/core';
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(), // Batch updates for optimal rendering
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
- // Expensive computations are automatically cached
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 { createDevTree, TREE_PRESETS } from '@signaltree/core';
1752
+ import { signalTree, batching, devTools, withTimeTravel } from '@signaltree/core';
1774
1753
 
1775
- // Use presets for common patterns
1776
- const devTree = createDevTree({
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
- // Includes: batching, memoization, devtools, time-travel
1782
-
1783
- // Or use preset configurations directly
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(), memoization());
1800
+ tree = tree.with(batching());
1822
1801
  }
1823
1802
 
1824
1803
  if (needsTimeTravel) {
@@ -2085,6 +2064,7 @@ tree.unwrap(); // Get plain object
2085
2064
 
2086
2065
  // Tree operations
2087
2066
  tree.update(updater); // Update entire tree
2067
+ tree.updateAndReport(updater); // Update + return changed leaf paths (9.1+)
2088
2068
  tree.effect(fn); // Create reactive effects
2089
2069
  tree.subscribe(fn); // Manual subscriptions
2090
2070
  tree.destroy(); // Cleanup resources
@@ -2096,15 +2076,35 @@ tree.destroy(); // Cleanup resources
2096
2076
  // tree.$.users.selectBy(pred); // Filtered signal
2097
2077
  ```
2098
2078
 
2079
+ ### updateAndReport (9.1+)
2080
+
2081
+ Like `update`, but returns the dot-paths of every leaf signal whose value
2082
+ actually changed. Useful for diff logging, audit trails, optimistic-update
2083
+ rollback, and selective re-syncing to a server.
2084
+
2085
+ ```typescript
2086
+ const tree = signalTree({ user: { name: 'Ada', age: 36 }, count: 0 });
2087
+
2088
+ const changed = tree.updateAndReport({
2089
+ user: { name: 'Ada', age: 37 }, // age changes, name is ref-equal
2090
+ count: 0, // ref-equal, skipped
2091
+ });
2092
+ // changed === ['user.age']
2093
+ ```
2094
+
2095
+ Reference-equal values are skipped automatically by the underlying
2096
+ `update` path, so passing a server-returned partial that mostly matches
2097
+ local state is cheap (`O(changed)` instead of `O(N)`).
2098
+
2099
2099
  ## Extending with enhancers
2100
2100
 
2101
2101
  SignalTree Core includes all enhancers built-in:
2102
2102
 
2103
2103
  ```typescript
2104
- import { signalTree, batching, memoization, withTimeTravel } from '@signaltree/core';
2104
+ import { signalTree, batching, withTimeTravel } from '@signaltree/core';
2105
2105
 
2106
2106
  // All enhancers available from @signaltree/core
2107
- const tree = signalTree(initialState).with(batching(), memoization(), withTimeTravel());
2107
+ const tree = signalTree(initialState).with(batching(), withTimeTravel());
2108
2108
  ```
2109
2109
 
2110
2110
  ### Available enhancers
@@ -2112,13 +2112,10 @@ const tree = signalTree(initialState).with(batching(), memoization(), withTimeTr
2112
2112
  All enhancers are included in `@signaltree/core`:
2113
2113
 
2114
2114
  - **batching()** - Batch multiple updates for better performance
2115
- - **memoization()** - Intelligent caching & performance optimization
2116
2115
  - **entities()** - Advanced entity management & CRUD operations
2117
2116
  - **devTools()** - Redux DevTools integration for debugging
2118
2117
  - **withTimeTravel()** - Undo/redo functionality & state history
2119
2118
  - **serialization()** - State persistence & SSR support
2120
- - **createDevTree()** - Pre-configured development setup
2121
- - **TREE_PRESETS** - Common configuration patterns (PERFORMANCE, DASHBOARD, etc.)
2122
2119
 
2123
2120
  ## When to use core only
2124
2121
 
@@ -2132,7 +2129,7 @@ Perfect for:
2132
2129
 
2133
2130
  Consider enhancers when you need:
2134
2131
 
2135
- - ⚡ Performance optimization (batching, memoization)
2132
+ - ⚡ Performance optimization (batching)
2136
2133
  - 🐛 Advanced debugging (devTools, withTimeTravel)
2137
2134
  - 📦 Entity management (entities)
2138
2135
 
@@ -2144,6 +2141,21 @@ Consider separate packages when you need:
2144
2141
 
2145
2142
  ## Migration from NgRx
2146
2143
 
2144
+ ### Case Study
2145
+
2146
+ 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.
2147
+
2148
+ | Metric | NgRx | SignalTree | Change |
2149
+ | --- | --- | --- | --- |
2150
+ | **App state code** | 11,735 lines / 45 files | 2,825 lines / 23 files | **-76%** |
2151
+ | **npm packages** | 4 (@ngrx/\*) | 1 (@signaltree/core) | **-75%** |
2152
+ | **State bundle (gzip)** | ~50KB | ~27KB | **-46%** |
2153
+ | **Boilerplate files** | 17 custom `withX` helpers | 0 (built-in) | **Eliminated** |
2154
+
2155
+ 13 separate stores → 1 unified tree. `entityMap()` replaced a 222-line `withEntityCrud` wrapper. Derived tiers replaced scattered `withComputed` blocks.
2156
+
2157
+ ### Migration Steps
2158
+
2147
2159
  ```typescript
2148
2160
  // Step 1: Create parallel tree
2149
2161
  const tree = signalTree(initialState);
@@ -2265,7 +2277,6 @@ All enhancers are now consolidated in the core package. The following features a
2265
2277
  ### Performance & Optimization
2266
2278
 
2267
2279
  - **batching()** (+1.27KB gzipped) - Batch multiple updates for better performance
2268
- - **memoization()** (+2.33KB gzipped) - Intelligent caching & performance optimization
2269
2280
 
2270
2281
  ### Advanced Features
2271
2282
 
@@ -2279,8 +2290,6 @@ All enhancers are now consolidated in the core package. The following features a
2279
2290
  ### Integration & Convenience
2280
2291
 
2281
2292
  - **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
2293
 
2285
2294
  ### Quick Start with Extensions
2286
2295
 
@@ -2294,13 +2303,10 @@ npm install @signaltree/core
2294
2303
  import {
2295
2304
  signalTree,
2296
2305
  batching,
2297
- memoization,
2298
2306
  entities,
2299
2307
  devTools,
2300
2308
  withTimeTravel,
2301
- serialization,
2302
- ecommercePreset,
2303
- dashboardPreset
2309
+ serialization
2304
2310
  } from '@signaltree/core';
2305
2311
  ```
2306
2312
 
@@ -2626,7 +2632,7 @@ export default {
2626
2632
 
2627
2633
  **Start with just `@signaltree/core`** - it includes comprehensive enhancers for most applications:
2628
2634
 
2629
- - Performance optimization (batching, memoization)
2635
+ - Performance optimization (batching)
2630
2636
  - Data management (entities, async operations)
2631
2637
  - Development tools (devtools, time-travel)
2632
2638
  - State persistence (serialization)
@@ -2671,3 +2677,4 @@ MIT License with AI Training Restriction - see the [LICENSE](../../LICENSE) file
2671
2677
  ---
2672
2678
 
2673
2679
  **Ready to get started?** This core package provides everything you need for most applications. Add extensions only when you need them! 🚀
2680
+ ````
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';
@@ -1,4 +1,4 @@
1
- import { signal, isSignal } from '@angular/core';
1
+ import { signal, isSignal, untracked } from '@angular/core';
2
2
  import { SIGNAL_TREE_MESSAGES, SIGNAL_TREE_CONSTANTS } from './constants.js';
3
3
  import { batchScope } from './internals/batch-scope.js';
4
4
  import { isRegisteredMarker, materializeMarkers } from './internals/materialize-markers.js';
@@ -114,19 +114,25 @@ function makeNodeAccessor(store) {
114
114
  }
115
115
  return accessor;
116
116
  }
117
- function recursiveUpdate(target, updates) {
117
+ function recursiveUpdate(target, updates, out, pathPrefix = '') {
118
118
  if (!updates || typeof updates !== 'object') return;
119
119
  const targetObj = isNodeAccessor(target) ? target : target;
120
120
  for (const [key, value] of Object.entries(updates)) {
121
121
  const prop = targetObj[key];
122
122
  if (prop === undefined) continue;
123
+ const childPath = pathPrefix ? `${pathPrefix}.${key}` : key;
123
124
  if (isSignal(prop) && 'set' in prop) {
124
- prop.set(value);
125
+ const sig = prop;
126
+ const current = untracked(() => sig());
127
+ if (current === value) continue;
128
+ sig.set(value);
129
+ if (out) out.push(childPath);
125
130
  } else if (isNodeAccessor(prop)) {
126
131
  if (value && typeof value === 'object') {
127
- recursiveUpdate(prop, value);
132
+ recursiveUpdate(prop, value, out, childPath);
128
133
  } else {
129
134
  prop(value);
135
+ if (out) out.push(childPath);
130
136
  }
131
137
  }
132
138
  }
@@ -333,6 +339,25 @@ function create(initialState, config) {
333
339
  writable: true,
334
340
  configurable: true
335
341
  });
342
+ Object.defineProperty(tree, 'updateAndReport', {
343
+ value: function (arg) {
344
+ if (arguments.length === 0) return [];
345
+ const out = [];
346
+ if (typeof arg === 'function') {
347
+ const updater = arg;
348
+ const current = unwrap(signalState);
349
+ batchScope(() => recursiveUpdate(signalState, updater(current), out));
350
+ } else if (typeof arg === 'object' && arg !== null && !Array.isArray(arg)) {
351
+ batchScope(() => recursiveUpdate(signalState, arg, out));
352
+ } else {
353
+ recursiveUpdate(signalState, arg, out);
354
+ }
355
+ return out;
356
+ },
357
+ enumerable: false,
358
+ writable: true,
359
+ configurable: true
360
+ });
336
361
  for (const key of Object.keys(signalState)) {
337
362
  if (!(key in tree)) {
338
363
  Object.defineProperty(tree, key, {
@@ -453,6 +478,26 @@ function createBuilder(baseTree) {
453
478
  configurable: true
454
479
  });
455
480
  }
481
+ Object.defineProperty(builder, 'updateAndReport', {
482
+ value: function (arg) {
483
+ finalize();
484
+ const fn = baseTree['updateAndReport'];
485
+ return fn ? fn.call(baseTree, arg) : [];
486
+ },
487
+ enumerable: false,
488
+ writable: false,
489
+ configurable: true
490
+ });
491
+ Object.defineProperty(builder, 'batchUpdate', {
492
+ value: function (arg) {
493
+ finalize();
494
+ const fn = baseTree['batchUpdate'];
495
+ if (fn) fn.call(baseTree, arg);
496
+ },
497
+ enumerable: false,
498
+ writable: true,
499
+ configurable: true
500
+ });
456
501
  Object.defineProperty(builder, 'derived', {
457
502
  value: function (factory) {
458
503
  if (isFinalized) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signaltree/core",
3
- "version": "9.0.0",
3
+ "version": "9.1.0",
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",
@@ -1 +1 @@
1
- export { BatchingMethods, BatchingConfig, MemoizationMethods, MemoizationConfig, TimeTravelMethods, TimeTravelConfig, EffectsMethods, DevToolsMethods, DevToolsConfig, EntitiesEnabled, Enhancer, EnhancerWithMeta, EnhancerMeta, } from '../lib/types';
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, FullSignalTree, ProdSignalTree, TreeNode, CallableWritableSignal, AccessibleNode, NodeAccessor, Primitive, NotFn, TreeConfig, TreePreset, Enhancer, EnhancerMeta, EnhancerWithMeta, EntitySignal, EntityMapMarker, EntityConfig, MutationOptions, AddOptions, AddManyOptions, TimeTravelEntry, TimeTravelMethods, EnhancerCleanup, } from './lib/types';
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';
@@ -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' {
@@ -45,6 +38,7 @@ export interface ISignalTree<T> extends NodeAccessor<T> {
45
38
  destroy(): void;
46
39
  readonly destroyed: Signal<boolean>;
47
40
  registerCleanup(fn: EnhancerCleanup): void;
41
+ updateAndReport(updates: Partial<T> | ((current: T) => Partial<T>)): string[];
48
42
  }
49
43
  export type EnhancerCleanup = () => void;
50
44
  export interface EffectsMethods<T> {
@@ -61,20 +55,6 @@ export interface BatchingMethods<T = unknown> {
61
55
  hasPendingNotifications(): boolean;
62
56
  flushNotifications(): void;
63
57
  }
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
58
  export interface TimeTravelMethods<T = unknown> {
79
59
  undo(): void;
80
60
  redo(): void;
@@ -125,10 +105,8 @@ export interface TimeTravelEntry<T> {
125
105
  state: T;
126
106
  payload?: unknown;
127
107
  }
128
- export type TreePreset = 'basic' | 'performance' | 'development' | 'production';
129
108
  export interface TreeConfig {
130
109
  batchUpdates?: boolean;
131
- useMemoization?: boolean;
132
110
  enableTimeTravel?: boolean;
133
111
  useLazySignals?: boolean;
134
112
  useShallowComparison?: boolean;
@@ -310,9 +288,6 @@ export interface EnhancerMeta {
310
288
  provides?: string[];
311
289
  description?: string;
312
290
  }
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
291
  export type SignalTree<T> = ISignalTree<T> & TreeNode<T>;
317
292
  export type SignalTreeBase<T> = ISignalTree<T> & TreeNode<T>;
318
293
  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 };
@@ -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,2 +0,0 @@
1
- export { TREE_PRESETS, combinePresets, createPresetConfig, getAvailablePresets, validatePreset } from './enhancers/presets/lib/presets.js';
2
- export { createDevTree, createMinimalTree, createProdTree } from './lib/presets.js';
@@ -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,3 +0,0 @@
1
- import '@angular/compiler';
2
- import 'zone.js';
3
- import 'zone.js/testing';
@@ -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 };
@@ -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
@@ -1,2 +0,0 @@
1
- export { TREE_PRESETS, createPresetConfig, validatePreset, getAvailablePresets, combinePresets, createDevTree, createProdTree, createMinimalTree, } from './enhancers/presets/lib/presets';
2
- export type { TreePreset } from './lib/types';