@signaltree/core 8.0.2 → 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 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) {
@@ -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, memoization, withTimeTravel } from '@signaltree/core';
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(), memoization(), withTimeTravel());
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, memoization)
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, memoization)
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
+ ````
@@ -0,0 +1 @@
1
+ export { createEditSession } from './lib/edit-session.js';
@@ -1,9 +1,10 @@
1
1
  import { copyTreeProperties } from '../utils/copy-tree-properties.js';
2
+ import { ENHANCER_META } from '../../lib/types.js';
2
3
 
3
4
  function batching(config = {}) {
4
5
  const enabled = config.enabled ?? true;
5
6
  const notificationDelayMs = config.notificationDelayMs ?? 0;
6
- return tree => {
7
+ const enhancerFn = tree => {
7
8
  if (!enabled) {
8
9
  const passthrough = {
9
10
  batch: fn => fn(),
@@ -200,8 +201,24 @@ function batching(config = {}) {
200
201
  });
201
202
  });
202
203
  };
204
+ if (typeof tree.registerCleanup === 'function') {
205
+ tree.registerCleanup(() => {
206
+ if (notificationTimeoutId !== undefined) {
207
+ clearTimeout(notificationTimeoutId);
208
+ notificationTimeoutId = undefined;
209
+ }
210
+ coalescedUpdates.clear();
211
+ });
212
+ }
203
213
  return enhancedTree;
204
214
  };
215
+ const meta = {
216
+ name: 'batching',
217
+ provides: ['batching']
218
+ };
219
+ enhancerFn.metadata = meta;
220
+ enhancerFn[ENHANCER_META] = meta;
221
+ return enhancerFn;
205
222
  }
206
223
  function highPerformanceBatching() {
207
224
  return batching({
@@ -209,22 +226,8 @@ function highPerformanceBatching() {
209
226
  notificationDelayMs: 0
210
227
  });
211
228
  }
212
- function batchingWithConfig(config = {}) {
213
- return batching(config);
214
- }
215
- function flushBatchedUpdates() {
216
- console.warn('[SignalTree] flushBatchedUpdates() is deprecated. Use tree.flushNotifications() instead.');
217
- }
218
- function hasPendingUpdates() {
219
- console.warn('[SignalTree] hasPendingUpdates() is deprecated. Use tree.hasPendingNotifications() instead.');
220
- return false;
221
- }
222
- function getBatchQueueSize() {
223
- console.warn('[SignalTree] getBatchQueueSize() is deprecated. Signal writes are now synchronous.');
224
- return 0;
225
- }
226
229
  Object.assign((config = {}) => batching(config), {
227
230
  highPerformance: highPerformanceBatching
228
231
  });
229
232
 
230
- export { batching, batchingWithConfig, flushBatchedUpdates, getBatchQueueSize, hasPendingUpdates, highPerformanceBatching };
233
+ export { batching, highPerformanceBatching };
@@ -2,6 +2,7 @@ import { signal } from '@angular/core';
2
2
  import { copyTreeProperties } from '../utils/copy-tree-properties.js';
3
3
  import { applyState, snapshotState } from '../../lib/utils.js';
4
4
  import { getPathNotifier } from '../../lib/path-notifier.js';
5
+ import { ENHANCER_META } from '../../lib/types.js';
5
6
 
6
7
  function createActivityTracker(options) {
7
8
  const modules = new Map();
@@ -698,7 +699,7 @@ function devTools(config = {}) {
698
699
  const pathExclude = toArray(excludePaths);
699
700
  const sendRateLimitMs = maxSendsPerSecond && maxSendsPerSecond > 0 ? Math.ceil(1000 / maxSendsPerSecond) : rateLimitMs ?? 0;
700
701
  const formatPathFn = formatPath ?? defaultFormatPath;
701
- return tree => {
702
+ const enhancerFn = tree => {
702
703
  if (!enabled) {
703
704
  const noopMethods = {
704
705
  connectDevTools() {},
@@ -1306,8 +1307,20 @@ function devTools(config = {}) {
1306
1307
  if (enableBrowserDevTools) {
1307
1308
  initBrowserDevTools();
1308
1309
  }
1310
+ if (typeof tree.registerCleanup === 'function') {
1311
+ tree.registerCleanup(() => {
1312
+ result.disconnectDevTools();
1313
+ });
1314
+ }
1309
1315
  return result;
1310
1316
  };
1317
+ const meta = {
1318
+ name: 'devTools',
1319
+ provides: ['devTools']
1320
+ };
1321
+ enhancerFn.metadata = meta;
1322
+ enhancerFn[ENHANCER_META] = meta;
1323
+ return enhancerFn;
1311
1324
  }
1312
1325
  function enableDevTools(treeName = 'SignalTree') {
1313
1326
  return devTools({
@@ -1,4 +1,5 @@
1
1
  import { isSignal } from '@angular/core';
2
+ import { ENHANCER_META } from '../../lib/types.js';
2
3
  import { TYPE_MARKERS } from './constants.js';
3
4
 
4
5
  const DEFAULT_CONFIG = {
@@ -181,7 +182,7 @@ function resolveCircularReferences(obj, circularPaths) {
181
182
  }
182
183
  }
183
184
  function serialization(defaultConfig = {}) {
184
- return tree => {
185
+ const enhancerFn = tree => {
185
186
  const enhanced = tree;
186
187
  enhanced.toJSON = () => {
187
188
  return tree();
@@ -455,15 +456,15 @@ function serialization(defaultConfig = {}) {
455
456
  };
456
457
  return enhanced;
457
458
  };
459
+ const meta = {
460
+ name: 'serialization',
461
+ provides: ['serialization']
462
+ };
463
+ enhancerFn.metadata = meta;
464
+ enhancerFn[ENHANCER_META] = meta;
465
+ return enhancerFn;
458
466
  }
459
467
  Object.assign((defaultConfig = {}) => serialization(defaultConfig), {});
460
- function enableSerialization() {
461
- return serialization({
462
- includeMetadata: true,
463
- preserveTypes: true,
464
- handleCircular: true
465
- });
466
- }
467
468
  function persistence(config) {
468
469
  const {
469
470
  key,
@@ -477,7 +478,7 @@ function persistence(config) {
477
478
  throw new Error('No storage adapter available. Provide a storage adapter in the config.');
478
479
  }
479
480
  const storageAdapter = storage;
480
- return tree => {
481
+ const persistenceFn = tree => {
481
482
  const serializable = serialization(serializationConfig)(tree);
482
483
  const enhanced = serializable;
483
484
  let lastCacheKey = null;
@@ -553,8 +554,9 @@ function persistence(config) {
553
554
  });
554
555
  }, debounceMs);
555
556
  };
557
+ let unsubscribeAutoSave = null;
556
558
  try {
557
- tree.subscribe(() => {
559
+ unsubscribeAutoSave = tree.subscribe(() => {
558
560
  const currentState = JSON.stringify(tree());
559
561
  if (currentState !== previousState) {
560
562
  previousState = currentState;
@@ -575,6 +577,10 @@ function persistence(config) {
575
577
  }
576
578
  enhanced.__flushAutoSave = () => {
577
579
  pollingActive = false;
580
+ if (unsubscribeAutoSave) {
581
+ unsubscribeAutoSave();
582
+ unsubscribeAutoSave = null;
583
+ }
578
584
  if (saveTimeout) {
579
585
  clearTimeout(saveTimeout);
580
586
  saveTimeout = undefined;
@@ -582,9 +588,30 @@ function persistence(config) {
582
588
  }
583
589
  return Promise.resolve();
584
590
  };
591
+ if (typeof tree.registerCleanup === 'function') {
592
+ tree.registerCleanup(() => {
593
+ pollingActive = false;
594
+ if (unsubscribeAutoSave) {
595
+ unsubscribeAutoSave();
596
+ unsubscribeAutoSave = null;
597
+ }
598
+ if (saveTimeout) {
599
+ clearTimeout(saveTimeout);
600
+ saveTimeout = undefined;
601
+ }
602
+ });
603
+ }
585
604
  }
586
605
  return enhanced;
587
606
  };
607
+ const meta = {
608
+ name: 'persistence',
609
+ provides: ['persistence', 'serialization'],
610
+ requires: []
611
+ };
612
+ persistenceFn.metadata = meta;
613
+ persistenceFn[ENHANCER_META] = meta;
614
+ return persistenceFn;
588
615
  }
589
616
  Object.assign(cfg => persistence(cfg), {});
590
617
  function createStorageAdapter(getItem, setItem, removeItem) {
@@ -646,11 +673,5 @@ function createIndexedDBAdapter(dbName = 'SignalTreeDB', storeName = 'states') {
646
673
  }
647
674
  };
648
675
  }
649
- function applySerialization(tree) {
650
- return serialization()(tree);
651
- }
652
- function applyPersistence(tree, cfg) {
653
- return persistence(cfg)(tree);
654
- }
655
676
 
656
- export { applyPersistence, applySerialization, createIndexedDBAdapter, createStorageAdapter, enableSerialization, persistence, serialization };
677
+ export { createIndexedDBAdapter, createStorageAdapter, persistence, serialization };
@@ -1,5 +1,6 @@
1
1
  import { snapshotState } from '../../lib/utils.js';
2
2
  import { deepEqual, deepClone } from './utils.js';
3
+ import { ENHANCER_META } from '../../lib/types.js';
3
4
 
4
5
  class TimeTravelManager {
5
6
  tree;
@@ -130,7 +131,7 @@ function timeTravel(config = {}) {
130
131
  const {
131
132
  enabled = true
132
133
  } = config;
133
- return tree => {
134
+ const enhancerFn = tree => {
134
135
  if (!enabled) {
135
136
  const noopMethods = {
136
137
  undo() {},
@@ -255,13 +256,20 @@ function timeTravel(config = {}) {
255
256
  enhancedTree['canRedo'] = () => timeTravelManager.canRedo();
256
257
  enhancedTree['getCurrentIndex'] = () => timeTravelManager.getCurrentIndex();
257
258
  enhancedTree['__timeTravel'] = timeTravelManager;
259
+ if (typeof tree.registerCleanup === 'function') {
260
+ tree.registerCleanup(() => {
261
+ timeTravelManager.resetHistory();
262
+ });
263
+ }
258
264
  return enhancedTree;
259
265
  };
260
- }
261
- function enableTimeTravel() {
262
- return timeTravel({
263
- enabled: true
264
- });
266
+ const meta = {
267
+ name: 'timeTravel',
268
+ provides: ['timeTravel']
269
+ };
270
+ enhancerFn.metadata = meta;
271
+ enhancerFn[ENHANCER_META] = meta;
272
+ return enhancerFn;
265
273
  }
266
274
  function timeTravelHistory(maxHistorySize) {
267
275
  return timeTravel({
@@ -280,4 +288,4 @@ Object.assign((config = {}) => timeTravel(config), {
280
288
  history: timeTravelHistory
281
289
  });
282
290
 
283
- export { enableTimeTravel, timeTravel, timeTravelHistory };
291
+ export { timeTravel, timeTravelHistory };
package/dist/index.js CHANGED
@@ -6,22 +6,15 @@ export { LoadingState, isStatusMarker, status } from './lib/markers/status.js';
6
6
  export { clearStoragePrefix, createStorageKeys, isStoredMarker, stored } from './lib/markers/stored.js';
7
7
  export { FORM_MARKER, createFormSignal, form, isFormMarker, validators } from './lib/markers/form.js';
8
8
  export { registerMarkerProcessor } from './lib/internals/materialize-markers.js';
9
- export { composeEnhancers, createLazySignalTree, isAnySignal, isNodeAccessor, toWritableSignal } from './lib/utils.js';
10
- export { createEditSession } from './lib/edit-session.js';
9
+ export { composeEnhancers, isAnySignal, isNodeAccessor, toWritableSignal } from './lib/utils.js';
11
10
  export { getPathNotifier } from './lib/path-notifier.js';
12
- export { SecurityPresets, SecurityValidator } from './lib/security/security-validator.js';
13
11
  export { createEnhancer, resolveEnhancerOrder } from './enhancers/index.js';
14
- export { batching, batchingWithConfig, flushBatchedUpdates, getBatchQueueSize, hasPendingUpdates, highPerformanceBatching } from './enhancers/batching/batching.js';
15
- export { clearAllCaches, computedMemoization, deepStateMemoization, getGlobalCacheStats, highFrequencyMemoization, highPerformanceMemoization, lightweightMemoization, memoization, memoize, memoizeReference, memoizeShallow, selectorMemoization, shallowMemoization } from './enhancers/memoization/memoization.js';
16
- export { enableTimeTravel, timeTravel } from './enhancers/time-travel/time-travel.js';
17
- export { enableEntities, entities, highPerformanceEntities } from './enhancers/entities/entities.js';
18
- export { applyPersistence, applySerialization, createIndexedDBAdapter, createStorageAdapter, enableSerialization, persistence, serialization } from './enhancers/serialization/serialization.js';
19
- export { devTools, enableDevTools, fullDevTools, productionDevTools } from './enhancers/devtools/devtools.js';
20
- export { createAsyncOperation, trackAsync } from './lib/async-helpers.js';
21
- export { TREE_PRESETS, combinePresets, createPresetConfig, getAvailablePresets, validatePreset } from './enhancers/presets/lib/presets.js';
22
- export { SIGNAL_TREE_CONSTANTS, SIGNAL_TREE_MESSAGES } from './lib/constants.js';
12
+ export { batching } from './enhancers/batching/batching.js';
13
+ export { timeTravel } from './enhancers/time-travel/time-travel.js';
14
+ export { persistence, serialization } from './enhancers/serialization/serialization.js';
15
+ export { devTools } from './enhancers/devtools/devtools.js';
16
+ export { SIGNAL_TREE_CONSTANTS, SIGNAL_TREE_MESSAGES, isDev } from './lib/constants.js';
23
17
  export { entityMap } from './lib/markers/entity-map.js';
24
18
  export { deepEqual, deepEqual as equal } from './shared/lib/deep-equal.js';
25
19
  export { parsePath } from './shared/lib/parse-path.js';
26
20
  export { isBuiltInObject } from './shared/lib/is-built-in-object.js';
27
- export { createDevTree } from './lib/presets.js';
@@ -51,6 +51,7 @@ const PROD_MESSAGES = (() => {
51
51
  })();
52
52
  const _isProdByEnv = Boolean(typeof globalThis === 'object' && globalThis !== null && 'process' in globalThis && typeof globalThis.process === 'object' && 'env' in globalThis.process && globalThis.process.env.NODE_ENV === 'production');
53
53
  const _isDev = typeof ngDevMode !== 'undefined' ? Boolean(ngDevMode) : !_isProdByEnv;
54
+ const isDev = _isDev;
54
55
  const SIGNAL_TREE_MESSAGES = Object.freeze(_isDev ? DEV_MESSAGES : PROD_MESSAGES);
55
56
 
56
- export { SIGNAL_TREE_CONSTANTS, SIGNAL_TREE_MESSAGES };
57
+ export { SIGNAL_TREE_CONSTANTS, SIGNAL_TREE_MESSAGES, isDev };