@signaltree/core 5.1.6 → 6.0.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.
Files changed (91) hide show
  1. package/package.json +1 -6
  2. package/dist/constants.js +0 -6
  3. package/dist/deep-clone.js +0 -80
  4. package/dist/deep-equal.js +0 -41
  5. package/dist/enhancers/batching/lib/batching.js +0 -161
  6. package/dist/enhancers/computed/lib/computed.js +0 -21
  7. package/dist/enhancers/devtools/lib/devtools.js +0 -321
  8. package/dist/enhancers/entities/lib/entities.js +0 -66
  9. package/dist/enhancers/index.js +0 -72
  10. package/dist/enhancers/memoization/lib/memoization.js +0 -410
  11. package/dist/enhancers/presets/lib/presets.js +0 -87
  12. package/dist/enhancers/serialization/constants.js +0 -15
  13. package/dist/enhancers/serialization/lib/serialization.js +0 -662
  14. package/dist/enhancers/time-travel/lib/time-travel.js +0 -193
  15. package/dist/index.js +0 -19
  16. package/dist/is-built-in-object.js +0 -23
  17. package/dist/lib/async-helpers.js +0 -77
  18. package/dist/lib/constants.js +0 -56
  19. package/dist/lib/entity-signal.js +0 -283
  20. package/dist/lib/memory/memory-manager.js +0 -164
  21. package/dist/lib/path-notifier.js +0 -106
  22. package/dist/lib/performance/diff-engine.js +0 -156
  23. package/dist/lib/performance/path-index.js +0 -156
  24. package/dist/lib/performance/update-engine.js +0 -188
  25. package/dist/lib/security/security-validator.js +0 -121
  26. package/dist/lib/signal-tree.js +0 -617
  27. package/dist/lib/types.js +0 -9
  28. package/dist/lib/utils.js +0 -261
  29. package/dist/lru-cache.js +0 -64
  30. package/dist/parse-path.js +0 -13
  31. package/src/async-helpers.d.ts +0 -8
  32. package/src/batching.d.ts +0 -16
  33. package/src/computed.d.ts +0 -12
  34. package/src/constants.d.ts +0 -14
  35. package/src/devtools.d.ts +0 -77
  36. package/src/diff-engine.d.ts +0 -33
  37. package/src/enhancers/batching/index.d.ts +0 -1
  38. package/src/enhancers/batching/lib/batching.d.ts +0 -16
  39. package/src/enhancers/batching/test-setup.d.ts +0 -3
  40. package/src/enhancers/computed/index.d.ts +0 -1
  41. package/src/enhancers/computed/lib/computed.d.ts +0 -12
  42. package/src/enhancers/devtools/index.d.ts +0 -1
  43. package/src/enhancers/devtools/lib/devtools.d.ts +0 -77
  44. package/src/enhancers/devtools/test-setup.d.ts +0 -3
  45. package/src/enhancers/entities/index.d.ts +0 -1
  46. package/src/enhancers/entities/lib/entities.d.ts +0 -17
  47. package/src/enhancers/entities/test-setup.d.ts +0 -3
  48. package/src/enhancers/index.d.ts +0 -3
  49. package/src/enhancers/memoization/index.d.ts +0 -1
  50. package/src/enhancers/memoization/lib/memoization.d.ts +0 -65
  51. package/src/enhancers/memoization/test-setup.d.ts +0 -3
  52. package/src/enhancers/presets/index.d.ts +0 -1
  53. package/src/enhancers/presets/lib/presets.d.ts +0 -11
  54. package/src/enhancers/presets/test-setup.d.ts +0 -3
  55. package/src/enhancers/serialization/constants.d.ts +0 -14
  56. package/src/enhancers/serialization/index.d.ts +0 -2
  57. package/src/enhancers/serialization/lib/serialization.d.ts +0 -59
  58. package/src/enhancers/serialization/test-setup.d.ts +0 -3
  59. package/src/enhancers/time-travel/index.d.ts +0 -1
  60. package/src/enhancers/time-travel/lib/time-travel.d.ts +0 -36
  61. package/src/enhancers/time-travel/lib/utils.d.ts +0 -1
  62. package/src/enhancers/time-travel/test-setup.d.ts +0 -3
  63. package/src/enhancers/types.d.ts +0 -74
  64. package/src/entities.d.ts +0 -28
  65. package/src/entity-signal.d.ts +0 -1
  66. package/src/index.d.ts +0 -18
  67. package/src/lib/async-helpers.d.ts +0 -8
  68. package/src/lib/constants.d.ts +0 -41
  69. package/src/lib/entity-signal.d.ts +0 -1
  70. package/src/lib/memory/memory-manager.d.ts +0 -30
  71. package/src/lib/path-notifier.d.ts +0 -4
  72. package/src/lib/performance/diff-engine.d.ts +0 -33
  73. package/src/lib/performance/path-index.d.ts +0 -25
  74. package/src/lib/performance/update-engine.d.ts +0 -32
  75. package/src/lib/security/security-validator.d.ts +0 -33
  76. package/src/lib/signal-tree.d.ts +0 -8
  77. package/src/lib/types.d.ts +0 -270
  78. package/src/lib/utils.d.ts +0 -28
  79. package/src/memoization.d.ts +0 -65
  80. package/src/memory-manager.d.ts +0 -30
  81. package/src/path-index.d.ts +0 -25
  82. package/src/path-notifier.d.ts +0 -12
  83. package/src/presets.d.ts +0 -11
  84. package/src/security-validator.d.ts +0 -33
  85. package/src/serialization.d.ts +0 -59
  86. package/src/signal-tree.d.ts +0 -8
  87. package/src/test-setup.d.ts +0 -3
  88. package/src/time-travel.d.ts +0 -36
  89. package/src/types.d.ts +0 -436
  90. package/src/update-engine.d.ts +0 -32
  91. package/src/utils.d.ts +0 -1
@@ -1,164 +0,0 @@
1
- class SignalMemoryManager {
2
- cache = new Map();
3
- registry = null;
4
- config;
5
- stats = {
6
- cleanedUpSignals: 0,
7
- peakCachedSignals: 0,
8
- manualDisposes: 0
9
- };
10
- constructor(config = {}) {
11
- this.config = {
12
- enableAutoCleanup: config.enableAutoCleanup ?? true,
13
- debugMode: config.debugMode ?? false,
14
- onCleanup: config.onCleanup ?? (() => {})
15
- };
16
- if (this.config.enableAutoCleanup && typeof FinalizationRegistry !== 'undefined') {
17
- this.registry = new FinalizationRegistry(path => {
18
- this.handleCleanup(path);
19
- });
20
- }
21
- if (this.config.debugMode) {
22
- console.log('[SignalMemoryManager] Initialized', {
23
- autoCleanup: this.config.enableAutoCleanup,
24
- hasRegistry: !!this.registry
25
- });
26
- }
27
- }
28
- cacheSignal(path, signal) {
29
- const ref = new WeakRef(signal);
30
- const entry = {
31
- ref,
32
- path,
33
- cachedAt: Date.now()
34
- };
35
- this.cache.set(path, entry);
36
- if (this.registry) {
37
- this.registry.register(signal, path, signal);
38
- }
39
- const currentSize = this.cache.size;
40
- if (currentSize > this.stats.peakCachedSignals) {
41
- this.stats.peakCachedSignals = currentSize;
42
- }
43
- if (this.config.debugMode) {
44
- console.log(`[SignalMemoryManager] Cached signal: ${path}`, {
45
- cacheSize: currentSize,
46
- peak: this.stats.peakCachedSignals
47
- });
48
- }
49
- }
50
- getSignal(path) {
51
- const entry = this.cache.get(path);
52
- if (!entry) {
53
- return undefined;
54
- }
55
- const signal = entry.ref.deref();
56
- if (!signal) {
57
- this.cache.delete(path);
58
- if (this.config.debugMode) {
59
- console.log(`[SignalMemoryManager] Signal GC'd: ${path}`);
60
- }
61
- return undefined;
62
- }
63
- return signal;
64
- }
65
- hasSignal(path) {
66
- return this.cache.has(path);
67
- }
68
- removeSignal(path) {
69
- const entry = this.cache.get(path);
70
- if (!entry) {
71
- return false;
72
- }
73
- const signal = entry.ref.deref();
74
- if (signal && this.registry) {
75
- this.registry.unregister(signal);
76
- }
77
- this.cache.delete(path);
78
- if (this.config.debugMode) {
79
- console.log(`[SignalMemoryManager] Removed signal: ${path}`);
80
- }
81
- return true;
82
- }
83
- handleCleanup(path) {
84
- this.cache.delete(path);
85
- this.stats.cleanedUpSignals++;
86
- const currentStats = this.getStats();
87
- if (this.config.debugMode) {
88
- console.log(`[SignalMemoryManager] Auto cleanup: ${path}`, currentStats);
89
- }
90
- this.config.onCleanup(path, currentStats);
91
- }
92
- getStats() {
93
- let validSignals = 0;
94
- for (const [path, entry] of this.cache.entries()) {
95
- if (entry.ref.deref()) {
96
- validSignals++;
97
- } else {
98
- this.cache.delete(path);
99
- }
100
- }
101
- const estimatedMemoryBytes = validSignals * 100;
102
- return {
103
- cachedSignals: validSignals,
104
- cleanedUpSignals: this.stats.cleanedUpSignals,
105
- peakCachedSignals: this.stats.peakCachedSignals,
106
- manualDisposes: this.stats.manualDisposes,
107
- estimatedMemoryBytes
108
- };
109
- }
110
- dispose() {
111
- if (this.config.debugMode) {
112
- console.log('[SignalMemoryManager] Disposing', {
113
- cachedSignals: this.cache.size
114
- });
115
- }
116
- if (this.registry) {
117
- for (const entry of this.cache.values()) {
118
- const signal = entry.ref.deref();
119
- if (signal) {
120
- this.registry.unregister(signal);
121
- }
122
- }
123
- }
124
- this.cache.clear();
125
- this.stats.manualDisposes++;
126
- if (this.config.debugMode) {
127
- console.log('[SignalMemoryManager] Disposed', this.getStats());
128
- }
129
- }
130
- getCachedPaths() {
131
- const paths = [];
132
- for (const [path, entry] of this.cache.entries()) {
133
- if (entry.ref.deref()) {
134
- paths.push(path);
135
- }
136
- }
137
- return paths;
138
- }
139
- clearStale() {
140
- let removed = 0;
141
- for (const [path, entry] of this.cache.entries()) {
142
- if (!entry.ref.deref()) {
143
- this.cache.delete(path);
144
- removed++;
145
- }
146
- }
147
- if (this.config.debugMode && removed > 0) {
148
- console.log(`[SignalMemoryManager] Cleared ${removed} stale entries`);
149
- }
150
- return removed;
151
- }
152
- resetStats() {
153
- this.stats = {
154
- cleanedUpSignals: 0,
155
- peakCachedSignals: 0,
156
- manualDisposes: 0
157
- };
158
- if (this.config.debugMode) {
159
- console.log('[SignalMemoryManager] Stats reset');
160
- }
161
- }
162
- }
163
-
164
- export { SignalMemoryManager };
@@ -1,106 +0,0 @@
1
- class PathNotifier {
2
- subscribers = new Map();
3
- interceptors = new Map();
4
- subscribe(pattern, handler) {
5
- if (!this.subscribers.has(pattern)) {
6
- this.subscribers.set(pattern, new Set());
7
- }
8
- const handlers = this.subscribers.get(pattern);
9
- if (!handlers) {
10
- return () => {};
11
- }
12
- handlers.add(handler);
13
- return () => {
14
- handlers.delete(handler);
15
- if (handlers.size === 0) {
16
- this.subscribers.delete(pattern);
17
- }
18
- };
19
- }
20
- intercept(pattern, interceptor) {
21
- if (!this.interceptors.has(pattern)) {
22
- this.interceptors.set(pattern, new Set());
23
- }
24
- const interceptors = this.interceptors.get(pattern);
25
- if (!interceptors) {
26
- return () => {};
27
- }
28
- interceptors.add(interceptor);
29
- return () => {
30
- interceptors.delete(interceptor);
31
- if (interceptors.size === 0) {
32
- this.interceptors.delete(pattern);
33
- }
34
- };
35
- }
36
- notify(path, value, prev) {
37
- let blocked = false;
38
- let transformed = value;
39
- for (const [pattern, interceptorSet] of this.interceptors) {
40
- if (this.matches(pattern, path)) {
41
- for (const interceptor of interceptorSet) {
42
- const result = interceptor(transformed, prev, path);
43
- if (result.block) {
44
- blocked = true;
45
- }
46
- if (result.transform !== undefined) {
47
- transformed = result.transform;
48
- }
49
- }
50
- }
51
- }
52
- if (blocked) {
53
- return {
54
- blocked: true,
55
- value: prev
56
- };
57
- }
58
- for (const [pattern, handlers] of this.subscribers) {
59
- if (this.matches(pattern, path)) {
60
- for (const handler of handlers) {
61
- handler(transformed, prev, path);
62
- }
63
- }
64
- }
65
- return {
66
- blocked: false,
67
- value: transformed
68
- };
69
- }
70
- matches(pattern, path) {
71
- if (pattern === '**') return true;
72
- if (pattern === path) return true;
73
- if (pattern.endsWith('.*')) {
74
- const prefix = pattern.slice(0, -2);
75
- return path.startsWith(prefix + '.');
76
- }
77
- return false;
78
- }
79
- clear() {
80
- this.subscribers.clear();
81
- this.interceptors.clear();
82
- }
83
- getSubscriberCount() {
84
- let count = 0;
85
- for (const handlers of this.subscribers.values()) {
86
- count += handlers.size;
87
- }
88
- return count;
89
- }
90
- getInterceptorCount() {
91
- let count = 0;
92
- for (const interceptors of this.interceptors.values()) {
93
- count += interceptors.size;
94
- }
95
- return count;
96
- }
97
- }
98
- let globalPathNotifier = null;
99
- function getPathNotifier() {
100
- if (!globalPathNotifier) {
101
- globalPathNotifier = new PathNotifier();
102
- }
103
- return globalPathNotifier;
104
- }
105
-
106
- export { PathNotifier, getPathNotifier };
@@ -1,156 +0,0 @@
1
- var ChangeType;
2
- (function (ChangeType) {
3
- ChangeType["ADD"] = "add";
4
- ChangeType["UPDATE"] = "update";
5
- ChangeType["DELETE"] = "delete";
6
- ChangeType["REPLACE"] = "replace";
7
- })(ChangeType || (ChangeType = {}));
8
- class DiffEngine {
9
- defaultOptions = {
10
- maxDepth: 100,
11
- detectDeletions: false,
12
- ignoreArrayOrder: false,
13
- equalityFn: (a, b) => a === b,
14
- keyValidator: undefined
15
- };
16
- diff(current, updates, options = {}) {
17
- const opts = {
18
- ...this.defaultOptions,
19
- ...options
20
- };
21
- const changes = [];
22
- const visited = new WeakSet();
23
- this.traverse(current, updates, [], changes, visited, opts, 0);
24
- return {
25
- changes,
26
- hasChanges: changes.length > 0
27
- };
28
- }
29
- traverse(curr, upd, path, changes, visited, opts, depth) {
30
- if (depth > opts.maxDepth) {
31
- return;
32
- }
33
- if (typeof upd !== 'object' || upd === null) {
34
- if (!opts.equalityFn(curr, upd)) {
35
- changes.push({
36
- type: curr === undefined ? ChangeType.ADD : ChangeType.UPDATE,
37
- path: [...path],
38
- value: upd,
39
- oldValue: curr
40
- });
41
- }
42
- return;
43
- }
44
- if (visited.has(upd)) {
45
- return;
46
- }
47
- visited.add(upd);
48
- if (Array.isArray(upd)) {
49
- this.diffArrays(curr, upd, path, changes, visited, opts, depth);
50
- return;
51
- }
52
- if (!curr || typeof curr !== 'object' || Array.isArray(curr)) {
53
- changes.push({
54
- type: ChangeType.REPLACE,
55
- path: [...path],
56
- value: upd,
57
- oldValue: curr
58
- });
59
- return;
60
- }
61
- const currObj = curr;
62
- const updObj = upd;
63
- for (const key in updObj) {
64
- if (Object.prototype.hasOwnProperty.call(updObj, key)) {
65
- if (opts.keyValidator && !opts.keyValidator(key)) {
66
- continue;
67
- }
68
- this.traverse(currObj[key], updObj[key], [...path, key], changes, visited, opts, depth + 1);
69
- }
70
- }
71
- if (opts.detectDeletions) {
72
- for (const key in currObj) {
73
- if (Object.prototype.hasOwnProperty.call(currObj, key) && !(key in updObj)) {
74
- changes.push({
75
- type: ChangeType.DELETE,
76
- path: [...path, key],
77
- oldValue: currObj[key]
78
- });
79
- }
80
- }
81
- }
82
- }
83
- diffArrays(curr, upd, path, changes, visited, opts, depth) {
84
- if (!Array.isArray(curr)) {
85
- changes.push({
86
- type: ChangeType.REPLACE,
87
- path: [...path],
88
- value: upd,
89
- oldValue: curr
90
- });
91
- return;
92
- }
93
- if (opts.ignoreArrayOrder) {
94
- this.diffArraysUnordered(curr, upd, path, changes, opts);
95
- } else {
96
- this.diffArraysOrdered(curr, upd, path, changes, visited, opts, depth);
97
- }
98
- }
99
- diffArraysOrdered(curr, upd, path, changes, visited, opts, depth) {
100
- const maxLength = Math.max(curr.length, upd.length);
101
- for (let i = 0; i < maxLength; i++) {
102
- if (i >= upd.length) {
103
- if (opts.detectDeletions) {
104
- changes.push({
105
- type: ChangeType.DELETE,
106
- path: [...path, i],
107
- oldValue: curr[i]
108
- });
109
- }
110
- } else if (i >= curr.length) {
111
- changes.push({
112
- type: ChangeType.ADD,
113
- path: [...path, i],
114
- value: upd[i]
115
- });
116
- } else {
117
- this.traverse(curr[i], upd[i], [...path, i], changes, visited, opts, depth + 1);
118
- }
119
- }
120
- }
121
- diffArraysUnordered(curr, upd, path, changes, opts) {
122
- const currSet = new Set(curr.map(v => this.stringify(v)));
123
- const updSet = new Set(upd.map(v => this.stringify(v)));
124
- upd.forEach((value, index) => {
125
- const str = this.stringify(value);
126
- if (!currSet.has(str)) {
127
- changes.push({
128
- type: ChangeType.ADD,
129
- path: [...path, index],
130
- value
131
- });
132
- }
133
- });
134
- if (opts.detectDeletions) {
135
- curr.forEach((value, index) => {
136
- const str = this.stringify(value);
137
- if (!updSet.has(str)) {
138
- changes.push({
139
- type: ChangeType.DELETE,
140
- path: [...path, index],
141
- oldValue: value
142
- });
143
- }
144
- });
145
- }
146
- }
147
- stringify(value) {
148
- try {
149
- return JSON.stringify(value);
150
- } catch {
151
- return String(value);
152
- }
153
- }
154
- }
155
-
156
- export { ChangeType, DiffEngine };
@@ -1,156 +0,0 @@
1
- import { isSignal } from '@angular/core';
2
-
3
- class TrieNode {
4
- value = null;
5
- children = new Map();
6
- }
7
- class PathIndex {
8
- root = new TrieNode();
9
- pathCache = new Map();
10
- stats = {
11
- hits: 0,
12
- misses: 0,
13
- sets: 0,
14
- cleanups: 0
15
- };
16
- set(path, signal) {
17
- const pathStr = this.pathToString(path);
18
- const ref = new WeakRef(signal);
19
- let node = this.root;
20
- for (const segment of path) {
21
- const key = String(segment);
22
- if (!node.children.has(key)) {
23
- node.children.set(key, new TrieNode());
24
- }
25
- const nextNode = node.children.get(key);
26
- if (!nextNode) {
27
- throw new Error(`Failed to get node for key: ${key}`);
28
- }
29
- node = nextNode;
30
- }
31
- node.value = ref;
32
- this.pathCache.set(pathStr, ref);
33
- this.stats.sets++;
34
- }
35
- get(path) {
36
- const pathStr = this.pathToString(path);
37
- const cached = this.pathCache.get(pathStr);
38
- if (cached) {
39
- const value = cached.deref();
40
- if (value) {
41
- this.stats.hits++;
42
- return value;
43
- }
44
- this.pathCache.delete(pathStr);
45
- this.stats.cleanups++;
46
- }
47
- let node = this.root;
48
- for (const segment of path) {
49
- const key = String(segment);
50
- node = node.children.get(key);
51
- if (!node) {
52
- this.stats.misses++;
53
- return null;
54
- }
55
- }
56
- if (node.value) {
57
- const value = node.value.deref();
58
- if (value) {
59
- this.pathCache.set(pathStr, node.value);
60
- this.stats.hits++;
61
- return value;
62
- }
63
- node.value = null;
64
- this.stats.cleanups++;
65
- }
66
- this.stats.misses++;
67
- return null;
68
- }
69
- has(path) {
70
- return this.get(path) !== null;
71
- }
72
- getByPrefix(prefix) {
73
- const results = new Map();
74
- let node = this.root;
75
- for (const segment of prefix) {
76
- const key = String(segment);
77
- node = node.children.get(key);
78
- if (!node) {
79
- return results;
80
- }
81
- }
82
- this.collectDescendants(node, [], results);
83
- return results;
84
- }
85
- delete(path) {
86
- const pathStr = this.pathToString(path);
87
- this.pathCache.delete(pathStr);
88
- let node = this.root;
89
- const nodes = [node];
90
- for (const segment of path) {
91
- const key = String(segment);
92
- node = node.children.get(key);
93
- if (!node) {
94
- return false;
95
- }
96
- nodes.push(node);
97
- }
98
- const hadValue = node.value !== null;
99
- node.value = null;
100
- for (let i = nodes.length - 1; i > 0; i--) {
101
- const current = nodes[i];
102
- if (current.value === null && current.children.size === 0) {
103
- const parent = nodes[i - 1];
104
- const segment = path[i - 1];
105
- parent.children.delete(String(segment));
106
- } else {
107
- break;
108
- }
109
- }
110
- return hadValue;
111
- }
112
- clear() {
113
- this.root = new TrieNode();
114
- this.pathCache.clear();
115
- }
116
- getStats() {
117
- const total = this.stats.hits + this.stats.misses;
118
- const hitRate = total > 0 ? this.stats.hits / total : 0;
119
- return {
120
- ...this.stats,
121
- hitRate,
122
- cacheSize: this.pathCache.size
123
- };
124
- }
125
- buildFromTree(tree, path = []) {
126
- if (!tree) {
127
- return;
128
- }
129
- if (isSignal(tree)) {
130
- this.set(path, tree);
131
- return;
132
- }
133
- if (typeof tree !== 'object') {
134
- return;
135
- }
136
- for (const [key, value] of Object.entries(tree)) {
137
- this.buildFromTree(value, [...path, key]);
138
- }
139
- }
140
- pathToString(path) {
141
- return path.join('.');
142
- }
143
- collectDescendants(node, currentPath, results) {
144
- if (node.value) {
145
- const value = node.value.deref();
146
- if (value) {
147
- results.set(this.pathToString(currentPath), value);
148
- }
149
- }
150
- for (const [key, child] of node.children) {
151
- this.collectDescendants(child, [...currentPath, key], results);
152
- }
153
- }
154
- }
155
-
156
- export { PathIndex };