@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.
- package/README.md +79 -38
- package/package.json +1 -1
- package/dist/enhancers/batching/index.d.ts +0 -1
- package/dist/enhancers/batching/index.js +0 -1
- package/dist/enhancers/batching/jest.config.d.ts +0 -15
- package/dist/enhancers/batching/jest.config.js +0 -21
- package/dist/enhancers/batching/lib/batching.d.ts +0 -16
- package/dist/enhancers/batching/lib/batching.js +0 -155
- package/dist/enhancers/batching/test-setup.d.ts +0 -1
- package/dist/enhancers/batching/test-setup.js +0 -5
- package/dist/enhancers/computed/index.d.ts +0 -1
- package/dist/enhancers/computed/index.js +0 -1
- package/dist/enhancers/computed/jest.config.d.ts +0 -15
- package/dist/enhancers/computed/jest.config.js +0 -21
- package/dist/enhancers/computed/lib/computed.d.ts +0 -12
- package/dist/enhancers/computed/lib/computed.js +0 -19
- package/dist/enhancers/devtools/index.d.ts +0 -1
- package/dist/enhancers/devtools/index.js +0 -1
- package/dist/enhancers/devtools/jest.config.d.ts +0 -15
- package/dist/enhancers/devtools/jest.config.js +0 -21
- package/dist/enhancers/devtools/lib/devtools.d.ts +0 -77
- package/dist/enhancers/devtools/lib/devtools.js +0 -278
- package/dist/enhancers/devtools/test-setup.d.ts +0 -1
- package/dist/enhancers/devtools/test-setup.js +0 -5
- package/dist/enhancers/entities/index.d.ts +0 -1
- package/dist/enhancers/entities/index.js +0 -1
- package/dist/enhancers/entities/jest.config.d.ts +0 -15
- package/dist/enhancers/entities/jest.config.js +0 -21
- package/dist/enhancers/entities/lib/entities.d.ts +0 -22
- package/dist/enhancers/entities/lib/entities.js +0 -110
- package/dist/enhancers/entities/test-setup.d.ts +0 -1
- package/dist/enhancers/entities/test-setup.js +0 -5
- package/dist/enhancers/index.d.ts +0 -3
- package/dist/enhancers/index.js +0 -84
- package/dist/enhancers/memoization/index.d.ts +0 -1
- package/dist/enhancers/memoization/index.js +0 -1
- package/dist/enhancers/memoization/jest.config.d.ts +0 -15
- package/dist/enhancers/memoization/jest.config.js +0 -21
- package/dist/enhancers/memoization/lib/memoization.d.ts +0 -65
- package/dist/enhancers/memoization/lib/memoization.js +0 -391
- package/dist/enhancers/memoization/test-setup.d.ts +0 -1
- package/dist/enhancers/memoization/test-setup.js +0 -5
- package/dist/enhancers/middleware/index.d.ts +0 -2
- package/dist/enhancers/middleware/index.js +0 -2
- package/dist/enhancers/middleware/jest.config.d.ts +0 -15
- package/dist/enhancers/middleware/jest.config.js +0 -21
- package/dist/enhancers/middleware/lib/async-helpers.d.ts +0 -8
- package/dist/enhancers/middleware/lib/async-helpers.js +0 -85
- package/dist/enhancers/middleware/lib/middleware.d.ts +0 -11
- package/dist/enhancers/middleware/lib/middleware.js +0 -179
- package/dist/enhancers/middleware/test-setup.d.ts +0 -1
- package/dist/enhancers/middleware/test-setup.js +0 -5
- package/dist/enhancers/presets/index.d.ts +0 -1
- package/dist/enhancers/presets/index.js +0 -1
- package/dist/enhancers/presets/jest.config.d.ts +0 -15
- package/dist/enhancers/presets/jest.config.js +0 -21
- package/dist/enhancers/presets/lib/presets.d.ts +0 -11
- package/dist/enhancers/presets/lib/presets.js +0 -77
- package/dist/enhancers/presets/test-setup.d.ts +0 -1
- package/dist/enhancers/presets/test-setup.js +0 -5
- package/dist/enhancers/serialization/constants.d.ts +0 -14
- package/dist/enhancers/serialization/constants.js +0 -14
- package/dist/enhancers/serialization/index.d.ts +0 -2
- package/dist/enhancers/serialization/index.js +0 -2
- package/dist/enhancers/serialization/jest.config.d.ts +0 -15
- package/dist/enhancers/serialization/jest.config.js +0 -21
- package/dist/enhancers/serialization/lib/serialization.d.ts +0 -59
- package/dist/enhancers/serialization/lib/serialization.js +0 -668
- package/dist/enhancers/serialization/test-setup.d.ts +0 -1
- package/dist/enhancers/serialization/test-setup.js +0 -5
- package/dist/enhancers/time-travel/index.d.ts +0 -1
- package/dist/enhancers/time-travel/index.js +0 -1
- package/dist/enhancers/time-travel/jest.config.d.ts +0 -15
- package/dist/enhancers/time-travel/jest.config.js +0 -21
- package/dist/enhancers/time-travel/lib/time-travel.d.ts +0 -36
- package/dist/enhancers/time-travel/lib/time-travel.js +0 -192
- package/dist/enhancers/time-travel/lib/utils.d.ts +0 -1
- package/dist/enhancers/time-travel/lib/utils.js +0 -1
- package/dist/enhancers/time-travel/test-setup.d.ts +0 -1
- package/dist/enhancers/time-travel/test-setup.js +0 -5
- package/dist/enhancers/types.d.ts +0 -105
- package/dist/enhancers/types.js +0 -0
- package/dist/index.d.ts +0 -17
- package/dist/index.js +0 -16
- package/dist/lib/constants.d.ts +0 -42
- package/dist/lib/constants.js +0 -61
- package/dist/lib/memory/memory-manager.d.ts +0 -30
- package/dist/lib/memory/memory-manager.js +0 -166
- package/dist/lib/performance/diff-engine.d.ts +0 -33
- package/dist/lib/performance/diff-engine.js +0 -156
- package/dist/lib/performance/path-index.d.ts +0 -25
- package/dist/lib/performance/path-index.js +0 -154
- package/dist/lib/performance/update-engine.d.ts +0 -32
- package/dist/lib/performance/update-engine.js +0 -193
- package/dist/lib/security/security-validator.d.ts +0 -33
- package/dist/lib/security/security-validator.js +0 -139
- package/dist/lib/signal-tree.d.ts +0 -8
- package/dist/lib/signal-tree.js +0 -665
- package/dist/lib/types.d.ts +0 -164
- package/dist/lib/types.js +0 -9
- package/dist/lib/utils.d.ts +0 -27
- 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
|
|
1460
|
+
**Angular Forms integration for SignalTree (Angular 17+)**
|
|
1461
1461
|
|
|
1462
|
-
Seamlessly connect Angular
|
|
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
|
-
|
|
1546
|
-
|
|
1570
|
+
auth: {
|
|
1571
|
+
/* ... */
|
|
1572
|
+
},
|
|
1573
|
+
data: {
|
|
1574
|
+
/* ... */
|
|
1575
|
+
},
|
|
1576
|
+
ui: {
|
|
1577
|
+
/* ... */
|
|
1578
|
+
},
|
|
1547
1579
|
// ... many more modules
|
|
1548
|
-
}
|
|
1549
|
-
}).with(
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
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(
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
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');
|
|
1681
|
-
tree.$.count((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();
|
|
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
|
|
1743
|
-
|
|
1744
|
-
| `@signaltree/ng-forms`
|
|
1745
|
-
| `@signaltree/enterprise`
|
|
1746
|
-
| `@signaltree/guardrails`
|
|
1747
|
-
| `@signaltree/callable-syntax` | Prefer callable syntax sugar
|
|
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.
|
|
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 +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
|
-
};
|