@signaltree/core 4.0.15 → 4.0.16

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.
Files changed (102) hide show
  1. package/README.md +79 -38
  2. package/package.json +1 -1
  3. package/dist/enhancers/batching/index.d.ts +0 -1
  4. package/dist/enhancers/batching/index.js +0 -1
  5. package/dist/enhancers/batching/jest.config.d.ts +0 -15
  6. package/dist/enhancers/batching/jest.config.js +0 -21
  7. package/dist/enhancers/batching/lib/batching.d.ts +0 -16
  8. package/dist/enhancers/batching/lib/batching.js +0 -155
  9. package/dist/enhancers/batching/test-setup.d.ts +0 -1
  10. package/dist/enhancers/batching/test-setup.js +0 -5
  11. package/dist/enhancers/computed/index.d.ts +0 -1
  12. package/dist/enhancers/computed/index.js +0 -1
  13. package/dist/enhancers/computed/jest.config.d.ts +0 -15
  14. package/dist/enhancers/computed/jest.config.js +0 -21
  15. package/dist/enhancers/computed/lib/computed.d.ts +0 -12
  16. package/dist/enhancers/computed/lib/computed.js +0 -19
  17. package/dist/enhancers/devtools/index.d.ts +0 -1
  18. package/dist/enhancers/devtools/index.js +0 -1
  19. package/dist/enhancers/devtools/jest.config.d.ts +0 -15
  20. package/dist/enhancers/devtools/jest.config.js +0 -21
  21. package/dist/enhancers/devtools/lib/devtools.d.ts +0 -77
  22. package/dist/enhancers/devtools/lib/devtools.js +0 -278
  23. package/dist/enhancers/devtools/test-setup.d.ts +0 -1
  24. package/dist/enhancers/devtools/test-setup.js +0 -5
  25. package/dist/enhancers/entities/index.d.ts +0 -1
  26. package/dist/enhancers/entities/index.js +0 -1
  27. package/dist/enhancers/entities/jest.config.d.ts +0 -15
  28. package/dist/enhancers/entities/jest.config.js +0 -21
  29. package/dist/enhancers/entities/lib/entities.d.ts +0 -22
  30. package/dist/enhancers/entities/lib/entities.js +0 -110
  31. package/dist/enhancers/entities/test-setup.d.ts +0 -1
  32. package/dist/enhancers/entities/test-setup.js +0 -5
  33. package/dist/enhancers/index.d.ts +0 -3
  34. package/dist/enhancers/index.js +0 -84
  35. package/dist/enhancers/memoization/index.d.ts +0 -1
  36. package/dist/enhancers/memoization/index.js +0 -1
  37. package/dist/enhancers/memoization/jest.config.d.ts +0 -15
  38. package/dist/enhancers/memoization/jest.config.js +0 -21
  39. package/dist/enhancers/memoization/lib/memoization.d.ts +0 -65
  40. package/dist/enhancers/memoization/lib/memoization.js +0 -391
  41. package/dist/enhancers/memoization/test-setup.d.ts +0 -1
  42. package/dist/enhancers/memoization/test-setup.js +0 -5
  43. package/dist/enhancers/middleware/index.d.ts +0 -2
  44. package/dist/enhancers/middleware/index.js +0 -2
  45. package/dist/enhancers/middleware/jest.config.d.ts +0 -15
  46. package/dist/enhancers/middleware/jest.config.js +0 -21
  47. package/dist/enhancers/middleware/lib/async-helpers.d.ts +0 -8
  48. package/dist/enhancers/middleware/lib/async-helpers.js +0 -85
  49. package/dist/enhancers/middleware/lib/middleware.d.ts +0 -11
  50. package/dist/enhancers/middleware/lib/middleware.js +0 -179
  51. package/dist/enhancers/middleware/test-setup.d.ts +0 -1
  52. package/dist/enhancers/middleware/test-setup.js +0 -5
  53. package/dist/enhancers/presets/index.d.ts +0 -1
  54. package/dist/enhancers/presets/index.js +0 -1
  55. package/dist/enhancers/presets/jest.config.d.ts +0 -15
  56. package/dist/enhancers/presets/jest.config.js +0 -21
  57. package/dist/enhancers/presets/lib/presets.d.ts +0 -11
  58. package/dist/enhancers/presets/lib/presets.js +0 -77
  59. package/dist/enhancers/presets/test-setup.d.ts +0 -1
  60. package/dist/enhancers/presets/test-setup.js +0 -5
  61. package/dist/enhancers/serialization/constants.d.ts +0 -14
  62. package/dist/enhancers/serialization/constants.js +0 -14
  63. package/dist/enhancers/serialization/index.d.ts +0 -2
  64. package/dist/enhancers/serialization/index.js +0 -2
  65. package/dist/enhancers/serialization/jest.config.d.ts +0 -15
  66. package/dist/enhancers/serialization/jest.config.js +0 -21
  67. package/dist/enhancers/serialization/lib/serialization.d.ts +0 -59
  68. package/dist/enhancers/serialization/lib/serialization.js +0 -668
  69. package/dist/enhancers/serialization/test-setup.d.ts +0 -1
  70. package/dist/enhancers/serialization/test-setup.js +0 -5
  71. package/dist/enhancers/time-travel/index.d.ts +0 -1
  72. package/dist/enhancers/time-travel/index.js +0 -1
  73. package/dist/enhancers/time-travel/jest.config.d.ts +0 -15
  74. package/dist/enhancers/time-travel/jest.config.js +0 -21
  75. package/dist/enhancers/time-travel/lib/time-travel.d.ts +0 -36
  76. package/dist/enhancers/time-travel/lib/time-travel.js +0 -192
  77. package/dist/enhancers/time-travel/lib/utils.d.ts +0 -1
  78. package/dist/enhancers/time-travel/lib/utils.js +0 -1
  79. package/dist/enhancers/time-travel/test-setup.d.ts +0 -1
  80. package/dist/enhancers/time-travel/test-setup.js +0 -5
  81. package/dist/enhancers/types.d.ts +0 -105
  82. package/dist/enhancers/types.js +0 -0
  83. package/dist/index.d.ts +0 -17
  84. package/dist/index.js +0 -16
  85. package/dist/lib/constants.d.ts +0 -42
  86. package/dist/lib/constants.js +0 -61
  87. package/dist/lib/memory/memory-manager.d.ts +0 -30
  88. package/dist/lib/memory/memory-manager.js +0 -166
  89. package/dist/lib/performance/diff-engine.d.ts +0 -33
  90. package/dist/lib/performance/diff-engine.js +0 -156
  91. package/dist/lib/performance/path-index.d.ts +0 -25
  92. package/dist/lib/performance/path-index.js +0 -154
  93. package/dist/lib/performance/update-engine.d.ts +0 -32
  94. package/dist/lib/performance/update-engine.js +0 -193
  95. package/dist/lib/security/security-validator.d.ts +0 -33
  96. package/dist/lib/security/security-validator.js +0 -139
  97. package/dist/lib/signal-tree.d.ts +0 -8
  98. package/dist/lib/signal-tree.js +0 -665
  99. package/dist/lib/types.d.ts +0 -164
  100. package/dist/lib/types.js +0 -9
  101. package/dist/lib/utils.d.ts +0 -27
  102. package/dist/lib/utils.js +0 -286
package/README.md CHANGED
@@ -1457,20 +1457,44 @@ While `@signaltree/core` includes comprehensive built-in enhancers for most use
1457
1457
 
1458
1458
  ### 📝 @signaltree/ng-forms
1459
1459
 
1460
- **Angular Reactive Forms integration for SignalTree**
1460
+ **Angular Forms integration for SignalTree (Angular 17+)**
1461
1461
 
1462
- Seamlessly connect Angular Reactive Forms with your SignalTree state for two-way data binding, validation, and form control.
1462
+ Seamlessly connect Angular Forms with your SignalTree state for two-way data binding, validation, and form control.
1463
1463
 
1464
1464
  ```bash
1465
1465
  npm install @signaltree/ng-forms
1466
1466
  ```
1467
1467
 
1468
1468
  **Features:**
1469
+
1469
1470
  - 🔗 Two-way binding between forms and SignalTree state
1470
1471
  - ✅ Built-in validation integration
1471
1472
  - 🎯 Type-safe form controls
1472
1473
  - 🔄 Automatic sync between form state and tree state
1473
1474
  - 📊 Form status tracking (valid, pristine, touched, etc.)
1475
+ - ⚡ Native Signal Forms support (Angular 20.3+)
1476
+ - 🔧 Legacy bridge for Angular 17-19 (deprecated, will be removed with Angular 21)
1477
+
1478
+ **Signal Forms (Angular 20.3+ recommended)**
1479
+
1480
+ Use Angular's Signal Forms `connect()` API directly with SignalTree:
1481
+
1482
+ ```ts
1483
+ import { toWritableSignal } from '@signaltree/core';
1484
+
1485
+ const tree = signalTree({
1486
+ user: { name: '', email: '' },
1487
+ });
1488
+
1489
+ // Leaves are WritableSignal<T>
1490
+ nameControl.connect(tree.$.user.name);
1491
+
1492
+ // Convert a slice to a WritableSignal<T>
1493
+ const userSignal = toWritableSignal(tree.$.user);
1494
+ userGroupControl.connect(userSignal);
1495
+ ```
1496
+
1497
+ The `@signaltree/ng-forms` package supports Angular 17+ and will prefer `connect()` when available (Angular 20.3+). Angular 17-19 uses a legacy bridge that will be deprecated when Angular 21 is released.
1474
1498
 
1475
1499
  **Quick Example:**
1476
1500
 
@@ -1479,7 +1503,7 @@ import { signalTree } from '@signaltree/core';
1479
1503
  import { bindFormToTree } from '@signaltree/ng-forms';
1480
1504
 
1481
1505
  const tree = signalTree({
1482
- user: { name: '', email: '', age: 0 }
1506
+ user: { name: '', email: '', age: 0 },
1483
1507
  });
1484
1508
 
1485
1509
  @Component({
@@ -1489,13 +1513,13 @@ const tree = signalTree({
1489
1513
  <input formControlName="email" type="email" />
1490
1514
  <input formControlName="age" type="number" />
1491
1515
  </form>
1492
- `
1516
+ `,
1493
1517
  })
1494
1518
  class UserFormComponent {
1495
1519
  form = new FormGroup({
1496
1520
  name: new FormControl(''),
1497
1521
  email: new FormControl(''),
1498
- age: new FormControl(0)
1522
+ age: new FormControl(0),
1499
1523
  });
1500
1524
 
1501
1525
  constructor() {
@@ -1506,6 +1530,7 @@ class UserFormComponent {
1506
1530
  ```
1507
1531
 
1508
1532
  **When to use:**
1533
+
1509
1534
  - Building forms with Angular Reactive Forms
1510
1535
  - Need validation integration
1511
1536
  - Two-way data binding between forms and state
@@ -1526,6 +1551,7 @@ npm install @signaltree/enterprise
1526
1551
  ```
1527
1552
 
1528
1553
  **Features:**
1554
+
1529
1555
  - ⚡ PathIndex for O(k) lookup time regardless of tree size
1530
1556
  - 🗜️ Advanced memory optimization algorithms
1531
1557
  - 📊 Performance profiling and monitoring
@@ -1541,24 +1567,34 @@ import { withEnterpriseOptimizations } from '@signaltree/enterprise';
1541
1567
  const tree = signalTree({
1542
1568
  // Large application state with hundreds of signals
1543
1569
  modules: {
1544
- auth: { /* ... */ },
1545
- data: { /* ... */ },
1546
- ui: { /* ... */ },
1570
+ auth: {
1571
+ /* ... */
1572
+ },
1573
+ data: {
1574
+ /* ... */
1575
+ },
1576
+ ui: {
1577
+ /* ... */
1578
+ },
1547
1579
  // ... many more modules
1548
- }
1549
- }).with(withEnterpriseOptimizations({
1550
- enablePathIndex: true,
1551
- enableMemoryOptimizations: true,
1552
- enablePerformanceMonitoring: true
1553
- }));
1580
+ },
1581
+ }).with(
1582
+ withEnterpriseOptimizations({
1583
+ enablePathIndex: true,
1584
+ enableMemoryOptimizations: true,
1585
+ enablePerformanceMonitoring: true,
1586
+ })
1587
+ );
1554
1588
  ```
1555
1589
 
1556
1590
  **Performance Benefits:**
1591
+
1557
1592
  - **Constant-time lookups:** O(k) lookup where k is path depth, not total signal count
1558
1593
  - **Memory efficiency:** Up to 40% reduction in memory usage for large trees
1559
1594
  - **Faster updates:** Optimized update batching for high-frequency scenarios
1560
1595
 
1561
1596
  **When to use:**
1597
+
1562
1598
  - Applications with 500+ signals
1563
1599
  - Complex nested state structures (10+ levels deep)
1564
1600
  - High-frequency state updates
@@ -1580,6 +1616,7 @@ npm install --save-dev @signaltree/guardrails
1580
1616
  ```
1581
1617
 
1582
1618
  **Features:**
1619
+
1583
1620
  - 🔥 Hot-path detection - identifies frequently accessed signals
1584
1621
  - 💾 Memory leak detection - tracks signal cleanup issues
1585
1622
  - 📊 Performance budgets - enforces performance thresholds
@@ -1595,15 +1632,17 @@ import { withGuardrails } from '@signaltree/guardrails';
1595
1632
 
1596
1633
  const tree = signalTree({
1597
1634
  users: [] as User[],
1598
- posts: [] as Post[]
1599
- }).with(withGuardrails({
1600
- hotPathThreshold: 100, // Warn if signal accessed >100 times/sec
1601
- memoryLeakThreshold: 50, // Warn if >50 uncleaned signals
1602
- budgets: {
1603
- updateTime: 16, // Warn if updates take >16ms
1604
- signalCount: 1000 // Warn if >1000 signals created
1605
- }
1606
- }));
1635
+ posts: [] as Post[],
1636
+ }).with(
1637
+ withGuardrails({
1638
+ hotPathThreshold: 100, // Warn if signal accessed >100 times/sec
1639
+ memoryLeakThreshold: 50, // Warn if >50 uncleaned signals
1640
+ budgets: {
1641
+ updateTime: 16, // Warn if updates take >16ms
1642
+ signalCount: 1000, // Warn if >1000 signals created
1643
+ },
1644
+ })
1645
+ );
1607
1646
 
1608
1647
  // Development warnings will appear in console
1609
1648
  // Production builds get no-op functions (0 overhead)
@@ -1646,6 +1685,7 @@ if (leaks.length > 0) {
1646
1685
  In production builds, all guardrails functions become no-ops with zero runtime cost.
1647
1686
 
1648
1687
  **When to use:**
1688
+
1649
1689
  - During active development
1650
1690
  - Performance optimization phase
1651
1691
  - Debugging state management issues
@@ -1667,6 +1707,7 @@ npm install --save-dev @signaltree/callable-syntax
1667
1707
  ```
1668
1708
 
1669
1709
  **Features:**
1710
+
1670
1711
  - 🍬 Syntactic sugar for signal updates
1671
1712
  - ⚡ Zero runtime overhead (build-time transform)
1672
1713
  - ✅ Full TypeScript type safety
@@ -1677,11 +1718,11 @@ npm install --save-dev @signaltree/callable-syntax
1677
1718
 
1678
1719
  ```typescript
1679
1720
  // With callable-syntax transform
1680
- tree.$.name('Jane'); // Transformed to: tree.$.name.set('Jane')
1681
- tree.$.count((n) => n + 1); // Transformed to: tree.$.count.update((n) => n + 1)
1721
+ tree.$.name('Jane'); // Transformed to: tree.$.name.set('Jane')
1722
+ tree.$.count((n) => n + 1); // Transformed to: tree.$.count.update((n) => n + 1)
1682
1723
 
1683
1724
  // Reading always works directly (no transform needed)
1684
- const name = tree.$.name(); // Direct Angular signal API
1725
+ const name = tree.$.name(); // Direct Angular signal API
1685
1726
  ```
1686
1727
 
1687
1728
  **Setup (tsconfig.json):**
@@ -1689,9 +1730,7 @@ const name = tree.$.name(); // Direct Angular signal API
1689
1730
  ```json
1690
1731
  {
1691
1732
  "compilerOptions": {
1692
- "plugins": [
1693
- { "transform": "@signaltree/callable-syntax" }
1694
- ]
1733
+ "plugins": [{ "transform": "@signaltree/callable-syntax" }]
1695
1734
  }
1696
1735
  }
1697
1736
  ```
@@ -1702,25 +1741,26 @@ const name = tree.$.name(); // Direct Angular signal API
1702
1741
  import { callableSyntaxTransform } from '@signaltree/callable-syntax/rollup';
1703
1742
 
1704
1743
  export default {
1705
- plugins: [
1706
- callableSyntaxTransform()
1707
- ]
1744
+ plugins: [callableSyntaxTransform()],
1708
1745
  };
1709
1746
  ```
1710
1747
 
1711
1748
  **Important Notes:**
1749
+
1712
1750
  - **Optional:** You can always use direct `.set(value)` or `.update(fn)` syntax
1713
1751
  - **Build-time only:** No runtime code is added to your bundle
1714
1752
  - **Function-valued leaves:** When storing functions, use `.set(fn)` directly
1715
1753
  - **Type-safe:** Full TypeScript support via module augmentation
1716
1754
 
1717
1755
  **When to use:**
1756
+
1718
1757
  - Prefer shorter, more concise syntax
1719
1758
  - Team convention favors callable style
1720
1759
  - Migrating from other signal libraries with similar syntax
1721
1760
  - Want familiar DX without runtime overhead
1722
1761
 
1723
1762
  **When to skip:**
1763
+
1724
1764
  - Team prefers explicit `.set/.update` syntax
1725
1765
  - Build pipeline doesn't support transformers
1726
1766
  - Storing functions as signal values (use direct `.set`)
@@ -1732,6 +1772,7 @@ export default {
1732
1772
  ## Package Selection Guide
1733
1773
 
1734
1774
  **Start with just `@signaltree/core`** - it includes comprehensive enhancers for most applications:
1775
+
1735
1776
  - Performance optimization (batching, memoization)
1736
1777
  - Data management (entities, async operations)
1737
1778
  - Development tools (devtools, time-travel)
@@ -1739,12 +1780,12 @@ export default {
1739
1780
 
1740
1781
  **Add companion packages when you need:**
1741
1782
 
1742
- | Package | When to Add | Bundle Impact |
1743
- |---------|------------|---------------|
1744
- | `@signaltree/ng-forms` | Angular Reactive Forms integration | ~10KB gzipped |
1745
- | `@signaltree/enterprise` | 500+ signals, large-scale apps | ~8KB gzipped |
1746
- | `@signaltree/guardrails` | Development performance monitoring | 0KB (dev-only) |
1747
- | `@signaltree/callable-syntax` | Prefer callable syntax sugar | 0KB (build-time) |
1783
+ | Package | When to Add | Bundle Impact |
1784
+ | ----------------------------- | ---------------------------------- | ---------------- |
1785
+ | `@signaltree/ng-forms` | Angular Reactive Forms integration | ~10KB gzipped |
1786
+ | `@signaltree/enterprise` | 500+ signals, large-scale apps | ~8KB gzipped |
1787
+ | `@signaltree/guardrails` | Development performance monitoring | 0KB (dev-only) |
1788
+ | `@signaltree/callable-syntax` | Prefer callable syntax sugar | 0KB (build-time) |
1748
1789
 
1749
1790
  **Typical Installation Patterns:**
1750
1791
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signaltree/core",
3
- "version": "4.0.15",
3
+ "version": "4.0.16",
4
4
  "description": "Lightweight, type-safe signal-based state management for Angular. Core package providing hierarchical signal trees, basic entity management, and async actions.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -1 +0,0 @@
1
- export * from './lib/batching';
@@ -1 +0,0 @@
1
- export * from './lib/batching';
@@ -1,15 +0,0 @@
1
- declare const _default: {
2
- displayName: string;
3
- preset: string;
4
- setupFilesAfterEnv: string[];
5
- coverageDirectory: string;
6
- transform: {
7
- '^.+\\.(ts|mjs|js|html)$': (string | {
8
- tsconfig: string;
9
- stringifyContentPathRegex: string;
10
- })[];
11
- };
12
- transformIgnorePatterns: string[];
13
- snapshotSerializers: string[];
14
- };
15
- export default _default;
@@ -1,21 +0,0 @@
1
- export default {
2
- displayName: 'batching',
3
- preset: '../../../../../jest.preset.js',
4
- setupFilesAfterEnv: ['<rootDir>/test-setup.ts'],
5
- coverageDirectory: '../../../../../coverage/packages/core/enhancers/batching',
6
- transform: {
7
- '^.+\\.(ts|mjs|js|html)$': [
8
- 'jest-preset-angular',
9
- {
10
- tsconfig: '<rootDir>/tsconfig.spec.json',
11
- stringifyContentPathRegex: '\\.(html|svg)$',
12
- },
13
- ],
14
- },
15
- transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
16
- snapshotSerializers: [
17
- 'jest-preset-angular/build/serializers/no-ng-attributes',
18
- 'jest-preset-angular/build/serializers/ng-snapshot',
19
- 'jest-preset-angular/build/serializers/html-comment',
20
- ],
21
- };
@@ -1,16 +0,0 @@
1
- import type { SignalTree } from '../../../lib/types';
2
- interface BatchingConfig {
3
- enabled?: boolean;
4
- maxBatchSize?: number;
5
- autoFlushDelay?: number;
6
- batchTimeoutMs?: number;
7
- }
8
- interface BatchingSignalTree<T> extends SignalTree<T> {
9
- batchUpdate(updater: (current: T) => Partial<T>): void;
10
- }
11
- export declare function withBatching<T>(config?: BatchingConfig): (tree: SignalTree<T>) => BatchingSignalTree<T>;
12
- export declare function withHighPerformanceBatching<T>(): (tree: SignalTree<T>) => BatchingSignalTree<T>;
13
- export declare function flushBatchedUpdates(): void;
14
- export declare function hasPendingUpdates(): boolean;
15
- export declare function getBatchQueueSize(): number;
16
- export {};
@@ -1,155 +0,0 @@
1
- import { parsePath } from '@signaltree/shared';
2
- import { isNodeAccessor } from '../../../lib/utils';
3
- let updateQueue = [];
4
- let isUpdating = false;
5
- let flushTimeoutId;
6
- let currentBatchingConfig = {};
7
- function addToQueue(update, config = currentBatchingConfig) {
8
- const maxSize = config.maxBatchSize ?? 100;
9
- if (update.path) {
10
- updateQueue = updateQueue.filter((existing) => existing.path !== update.path);
11
- }
12
- updateQueue.push(update);
13
- if (updateQueue.length > maxSize) {
14
- flushUpdates();
15
- return true;
16
- }
17
- scheduleFlush(config);
18
- return false;
19
- }
20
- function scheduleFlush(config) {
21
- if (flushTimeoutId !== undefined) {
22
- clearTimeout(flushTimeoutId);
23
- }
24
- const delay = config.autoFlushDelay ?? 16;
25
- flushTimeoutId = setTimeout(() => {
26
- flushUpdates();
27
- }, delay);
28
- }
29
- function flushUpdates() {
30
- if (isUpdating)
31
- return;
32
- let queue;
33
- do {
34
- if (updateQueue.length === 0)
35
- return;
36
- isUpdating = true;
37
- queue = updateQueue;
38
- updateQueue = [];
39
- if (flushTimeoutId !== undefined) {
40
- clearTimeout(flushTimeoutId);
41
- flushTimeoutId = undefined;
42
- }
43
- queue.sort((a, b) => (b.depth ?? 0) - (a.depth ?? 0));
44
- try {
45
- queue.forEach(({ fn }) => fn());
46
- }
47
- finally {
48
- isUpdating = false;
49
- }
50
- } while (updateQueue.length > 0);
51
- }
52
- function batchUpdates(fn, path) {
53
- const startTime = performance.now();
54
- const depth = path ? parsePath(path).length : 0;
55
- const update = { fn, startTime, depth, path };
56
- const wasFlushed = addToQueue(update, currentBatchingConfig);
57
- if (!wasFlushed) {
58
- const isTimedOut = currentBatchingConfig.batchTimeoutMs &&
59
- updateQueue.length > 0 &&
60
- startTime - updateQueue[0].startTime >=
61
- currentBatchingConfig.batchTimeoutMs;
62
- if (isTimedOut) {
63
- flushUpdates();
64
- }
65
- else if (!isUpdating && updateQueue.length > 0) {
66
- queueMicrotask(() => {
67
- flushUpdates();
68
- });
69
- }
70
- }
71
- }
72
- export function withBatching(config = {}) {
73
- const { enabled = true } = config;
74
- currentBatchingConfig = { ...currentBatchingConfig, ...config };
75
- return (tree) => {
76
- if (!enabled) {
77
- return tree;
78
- }
79
- const originalTreeCall = tree.bind(tree);
80
- const enhancedTree = function (...args) {
81
- if (args.length === 0) {
82
- return originalTreeCall();
83
- }
84
- else {
85
- batchUpdates(() => {
86
- if (args.length === 1) {
87
- const arg = args[0];
88
- if (typeof arg === 'function') {
89
- originalTreeCall(arg);
90
- }
91
- else {
92
- originalTreeCall(arg);
93
- }
94
- }
95
- });
96
- }
97
- };
98
- Object.setPrototypeOf(enhancedTree, Object.getPrototypeOf(tree));
99
- Object.assign(enhancedTree, tree);
100
- if ('state' in tree) {
101
- Object.defineProperty(enhancedTree, 'state', {
102
- value: tree.state,
103
- enumerable: false,
104
- configurable: true,
105
- });
106
- }
107
- if ('$' in tree) {
108
- Object.defineProperty(enhancedTree, '$', {
109
- value: tree['$'],
110
- enumerable: false,
111
- configurable: true,
112
- });
113
- }
114
- enhancedTree.batchUpdate = (updater) => {
115
- batchUpdates(() => {
116
- const current = originalTreeCall();
117
- const updates = updater(current);
118
- Object.entries(updates).forEach(([key, value]) => {
119
- const property = enhancedTree.state[key];
120
- if (property && 'set' in property) {
121
- property.set(value);
122
- }
123
- else if (isNodeAccessor(property)) {
124
- property(value);
125
- }
126
- });
127
- });
128
- };
129
- return enhancedTree;
130
- };
131
- }
132
- export function withHighPerformanceBatching() {
133
- return withBatching({
134
- enabled: true,
135
- maxBatchSize: 200,
136
- batchTimeoutMs: 0,
137
- });
138
- }
139
- export function flushBatchedUpdates() {
140
- if (updateQueue.length > 0) {
141
- const queue = updateQueue.slice();
142
- updateQueue = [];
143
- isUpdating = false;
144
- queue.sort((a, b) => (b.depth ?? 0) - (a.depth ?? 0));
145
- queue.forEach(({ fn }) => {
146
- fn();
147
- });
148
- }
149
- }
150
- export function hasPendingUpdates() {
151
- return updateQueue.length > 0;
152
- }
153
- export function getBatchQueueSize() {
154
- return updateQueue.length;
155
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,5 +0,0 @@
1
- import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone';
2
- setupZoneTestEnv({
3
- errorOnUnknownElements: true,
4
- errorOnUnknownProperties: true,
5
- });
@@ -1 +0,0 @@
1
- export * from './lib/computed';
@@ -1 +0,0 @@
1
- export * from './lib/computed';
@@ -1,15 +0,0 @@
1
- declare const _default: {
2
- displayName: string;
3
- preset: string;
4
- setupFilesAfterEnv: string[];
5
- coverageDirectory: string;
6
- transform: {
7
- '^.+\\.(ts|mjs|js|html)$': (string | {
8
- tsconfig: string;
9
- stringifyContentPathRegex: string;
10
- })[];
11
- };
12
- transformIgnorePatterns: string[];
13
- snapshotSerializers: string[];
14
- };
15
- export default _default;
@@ -1,21 +0,0 @@
1
- export default {
2
- displayName: 'computed',
3
- preset: '../../../jest.preset.js',
4
- setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
5
- coverageDirectory: '../../../coverage/packages/core/enhancers/computed',
6
- transform: {
7
- '^.+\\.(ts|mjs|js|html)$': [
8
- 'jest-preset-angular',
9
- {
10
- tsconfig: '<rootDir>/tsconfig.spec.json',
11
- stringifyContentPathRegex: '\\.(html|svg)$',
12
- },
13
- ],
14
- },
15
- transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
16
- snapshotSerializers: [
17
- 'jest-preset-angular/build/serializers/no-ng-attributes',
18
- 'jest-preset-angular/build/serializers/ng-snapshot',
19
- 'jest-preset-angular/build/serializers/html-comment',
20
- ],
21
- };
@@ -1,12 +0,0 @@
1
- import { Signal } from '@angular/core';
2
- import type { TreeNode, SignalTree } from '../../../lib/types';
3
- export interface ComputedConfig {
4
- lazy?: boolean;
5
- memoize?: boolean;
6
- }
7
- export type ComputedSignal<T> = Signal<T>;
8
- export interface ComputedSignalTree<T extends Record<string, unknown>> extends SignalTree<T> {
9
- computed<U>(computeFn: (tree: TreeNode<T>) => U): ComputedSignal<U>;
10
- }
11
- export declare function computedEnhancer(_config?: ComputedConfig): import("../../../lib/types").EnhancerWithMeta<SignalTree<Record<string, unknown>>, ComputedSignalTree<Record<string, unknown>>>;
12
- export declare function createComputed<T>(dependencies: readonly Signal<unknown>[], computeFn: () => T): ComputedSignal<T>;
@@ -1,19 +0,0 @@
1
- import { computed } from '@angular/core';
2
- import { createEnhancer } from '../..';
3
- export function computedEnhancer(_config = {}) {
4
- void _config;
5
- return createEnhancer({
6
- name: 'computed',
7
- provides: ['computed'],
8
- requires: [],
9
- }, (tree) => {
10
- const computedTree = tree;
11
- computedTree.computed = function (computeFn) {
12
- return computed(() => computeFn(tree.state));
13
- };
14
- return computedTree;
15
- });
16
- }
17
- export function createComputed(dependencies, computeFn) {
18
- return computed(computeFn);
19
- }
@@ -1 +0,0 @@
1
- export * from './lib/devtools';
@@ -1 +0,0 @@
1
- export * from './lib/devtools';
@@ -1,15 +0,0 @@
1
- declare const _default: {
2
- displayName: string;
3
- preset: string;
4
- setupFilesAfterEnv: string[];
5
- coverageDirectory: string;
6
- transform: {
7
- '^.+\\.(ts|mjs|js|html)$': (string | {
8
- tsconfig: string;
9
- stringifyContentPathRegex: string;
10
- })[];
11
- };
12
- transformIgnorePatterns: string[];
13
- snapshotSerializers: string[];
14
- };
15
- export default _default;
@@ -1,21 +0,0 @@
1
- export default {
2
- displayName: 'devtools',
3
- preset: '../../../jest.preset.js',
4
- setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
5
- coverageDirectory: '../../../coverage/packages/core/enhancers/devtools',
6
- transform: {
7
- '^.+\\.(ts|mjs|js|html)$': [
8
- 'jest-preset-angular',
9
- {
10
- tsconfig: '<rootDir>/tsconfig.spec.json',
11
- stringifyContentPathRegex: '\\.(html|svg)$',
12
- },
13
- ],
14
- },
15
- transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
16
- snapshotSerializers: [
17
- 'jest-preset-angular/build/serializers/no-ng-attributes',
18
- 'jest-preset-angular/build/serializers/ng-snapshot',
19
- 'jest-preset-angular/build/serializers/html-comment',
20
- ],
21
- };