@signaltree/core 4.0.15 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/README.md +106 -38
  2. package/dist/constants.js +6 -0
  3. package/dist/deep-clone.js +80 -0
  4. package/dist/deep-equal.js +41 -0
  5. package/dist/enhancers/batching/lib/batching.js +141 -135
  6. package/dist/enhancers/computed/lib/computed.js +18 -16
  7. package/dist/enhancers/devtools/lib/devtools.js +303 -260
  8. package/dist/enhancers/entities/lib/entities.js +109 -104
  9. package/dist/enhancers/index.js +65 -77
  10. package/dist/enhancers/memoization/lib/memoization.js +339 -351
  11. package/dist/enhancers/middleware/lib/async-helpers.js +71 -79
  12. package/dist/enhancers/middleware/lib/middleware.js +126 -169
  13. package/dist/enhancers/presets/lib/presets.js +82 -71
  14. package/dist/enhancers/serialization/constants.js +14 -13
  15. package/dist/enhancers/serialization/lib/serialization.js +615 -623
  16. package/dist/enhancers/time-travel/lib/time-travel.js +178 -177
  17. package/dist/index.d.ts +1 -17
  18. package/dist/index.js +19 -16
  19. package/dist/is-built-in-object.js +23 -0
  20. package/dist/lib/constants.js +51 -55
  21. package/dist/lib/memory/memory-manager.js +152 -154
  22. package/dist/lib/performance/diff-engine.js +141 -141
  23. package/dist/lib/performance/path-index.js +139 -137
  24. package/dist/lib/performance/update-engine.js +171 -176
  25. package/dist/lib/security/security-validator.js +110 -128
  26. package/dist/lib/signal-tree.js +577 -611
  27. package/dist/lib/types.js +3 -9
  28. package/dist/lib/utils.js +236 -268
  29. package/dist/lru-cache.js +64 -0
  30. package/dist/parse-path.js +13 -0
  31. package/package.json +30 -16
  32. package/src/index.d.ts +17 -0
  33. package/{dist → src}/lib/utils.d.ts +1 -0
  34. package/dist/enhancers/batching/index.js +0 -1
  35. package/dist/enhancers/batching/jest.config.js +0 -21
  36. package/dist/enhancers/batching/test-setup.js +0 -5
  37. package/dist/enhancers/computed/index.js +0 -1
  38. package/dist/enhancers/computed/jest.config.js +0 -21
  39. package/dist/enhancers/devtools/index.js +0 -1
  40. package/dist/enhancers/devtools/jest.config.js +0 -21
  41. package/dist/enhancers/devtools/test-setup.js +0 -5
  42. package/dist/enhancers/entities/index.js +0 -1
  43. package/dist/enhancers/entities/jest.config.js +0 -21
  44. package/dist/enhancers/entities/test-setup.js +0 -5
  45. package/dist/enhancers/memoization/index.js +0 -1
  46. package/dist/enhancers/memoization/jest.config.js +0 -21
  47. package/dist/enhancers/memoization/test-setup.js +0 -5
  48. package/dist/enhancers/middleware/index.js +0 -2
  49. package/dist/enhancers/middleware/jest.config.js +0 -21
  50. package/dist/enhancers/middleware/test-setup.js +0 -5
  51. package/dist/enhancers/presets/index.js +0 -1
  52. package/dist/enhancers/presets/jest.config.js +0 -21
  53. package/dist/enhancers/presets/test-setup.js +0 -5
  54. package/dist/enhancers/serialization/index.js +0 -2
  55. package/dist/enhancers/serialization/jest.config.js +0 -21
  56. package/dist/enhancers/serialization/test-setup.js +0 -5
  57. package/dist/enhancers/time-travel/index.js +0 -1
  58. package/dist/enhancers/time-travel/jest.config.js +0 -21
  59. package/dist/enhancers/time-travel/lib/utils.js +0 -1
  60. package/dist/enhancers/time-travel/test-setup.js +0 -5
  61. package/dist/enhancers/types.js +0 -0
  62. /package/{dist → src}/enhancers/batching/index.d.ts +0 -0
  63. /package/{dist → src}/enhancers/batching/jest.config.d.ts +0 -0
  64. /package/{dist → src}/enhancers/batching/lib/batching.d.ts +0 -0
  65. /package/{dist → src}/enhancers/batching/test-setup.d.ts +0 -0
  66. /package/{dist → src}/enhancers/computed/index.d.ts +0 -0
  67. /package/{dist → src}/enhancers/computed/jest.config.d.ts +0 -0
  68. /package/{dist → src}/enhancers/computed/lib/computed.d.ts +0 -0
  69. /package/{dist → src}/enhancers/devtools/index.d.ts +0 -0
  70. /package/{dist → src}/enhancers/devtools/jest.config.d.ts +0 -0
  71. /package/{dist → src}/enhancers/devtools/lib/devtools.d.ts +0 -0
  72. /package/{dist → src}/enhancers/devtools/test-setup.d.ts +0 -0
  73. /package/{dist → src}/enhancers/entities/index.d.ts +0 -0
  74. /package/{dist → src}/enhancers/entities/jest.config.d.ts +0 -0
  75. /package/{dist → src}/enhancers/entities/lib/entities.d.ts +0 -0
  76. /package/{dist → src}/enhancers/entities/test-setup.d.ts +0 -0
  77. /package/{dist → src}/enhancers/index.d.ts +0 -0
  78. /package/{dist → src}/enhancers/memoization/index.d.ts +0 -0
  79. /package/{dist → src}/enhancers/memoization/jest.config.d.ts +0 -0
  80. /package/{dist → src}/enhancers/memoization/lib/memoization.d.ts +0 -0
  81. /package/{dist → src}/enhancers/memoization/test-setup.d.ts +0 -0
  82. /package/{dist → src}/enhancers/middleware/index.d.ts +0 -0
  83. /package/{dist → src}/enhancers/middleware/jest.config.d.ts +0 -0
  84. /package/{dist → src}/enhancers/middleware/lib/async-helpers.d.ts +0 -0
  85. /package/{dist → src}/enhancers/middleware/lib/middleware.d.ts +0 -0
  86. /package/{dist → src}/enhancers/middleware/test-setup.d.ts +0 -0
  87. /package/{dist → src}/enhancers/presets/index.d.ts +0 -0
  88. /package/{dist → src}/enhancers/presets/jest.config.d.ts +0 -0
  89. /package/{dist → src}/enhancers/presets/lib/presets.d.ts +0 -0
  90. /package/{dist → src}/enhancers/presets/test-setup.d.ts +0 -0
  91. /package/{dist → src}/enhancers/serialization/constants.d.ts +0 -0
  92. /package/{dist → src}/enhancers/serialization/index.d.ts +0 -0
  93. /package/{dist → src}/enhancers/serialization/jest.config.d.ts +0 -0
  94. /package/{dist → src}/enhancers/serialization/lib/serialization.d.ts +0 -0
  95. /package/{dist → src}/enhancers/serialization/test-setup.d.ts +0 -0
  96. /package/{dist → src}/enhancers/time-travel/index.d.ts +0 -0
  97. /package/{dist → src}/enhancers/time-travel/jest.config.d.ts +0 -0
  98. /package/{dist → src}/enhancers/time-travel/lib/time-travel.d.ts +0 -0
  99. /package/{dist → src}/enhancers/time-travel/lib/utils.d.ts +0 -0
  100. /package/{dist → src}/enhancers/time-travel/test-setup.d.ts +0 -0
  101. /package/{dist → src}/enhancers/types.d.ts +0 -0
  102. /package/{dist → src}/lib/constants.d.ts +0 -0
  103. /package/{dist → src}/lib/memory/memory-manager.d.ts +0 -0
  104. /package/{dist → src}/lib/performance/diff-engine.d.ts +0 -0
  105. /package/{dist → src}/lib/performance/path-index.d.ts +0 -0
  106. /package/{dist → src}/lib/performance/update-engine.d.ts +0 -0
  107. /package/{dist → src}/lib/security/security-validator.d.ts +0 -0
  108. /package/{dist → src}/lib/signal-tree.d.ts +0 -0
  109. /package/{dist → src}/lib/types.d.ts +0 -0
@@ -1,155 +1,161 @@
1
- import { parsePath } from '@signaltree/shared';
2
- import { isNodeAccessor } from '../../../lib/utils';
1
+ import { isNodeAccessor } from '../../../lib/utils.js';
2
+
3
3
  let updateQueue = [];
4
4
  let isUpdating = false;
5
5
  let flushTimeoutId;
6
6
  let currentBatchingConfig = {};
7
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;
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
19
  }
20
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);
21
+ if (flushTimeoutId !== undefined) {
22
+ clearTimeout(flushTimeoutId);
23
+ }
24
+ const delay = config.autoFlushDelay ?? 16;
25
+ flushTimeoutId = setTimeout(() => {
26
+ flushUpdates();
27
+ }, delay);
28
28
  }
29
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);
30
+ if (isUpdating) return;
31
+ let queue;
32
+ do {
33
+ if (updateQueue.length === 0) return;
34
+ isUpdating = true;
35
+ queue = updateQueue;
36
+ updateQueue = [];
37
+ if (flushTimeoutId !== undefined) {
38
+ clearTimeout(flushTimeoutId);
39
+ flushTimeoutId = undefined;
40
+ }
41
+ queue.sort((a, b) => (b.depth ?? 0) - (a.depth ?? 0));
42
+ try {
43
+ queue.forEach(({
44
+ fn
45
+ }) => fn());
46
+ } finally {
47
+ isUpdating = false;
48
+ }
49
+ } while (updateQueue.length > 0);
51
50
  }
52
51
  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
- }
52
+ const startTime = performance.now();
53
+ const depth = 0;
54
+ const update = {
55
+ fn,
56
+ startTime,
57
+ depth,
58
+ path
59
+ };
60
+ const wasFlushed = addToQueue(update, currentBatchingConfig);
61
+ if (!wasFlushed) {
62
+ const isTimedOut = currentBatchingConfig.batchTimeoutMs && updateQueue.length > 0 && startTime - updateQueue[0].startTime >= currentBatchingConfig.batchTimeoutMs;
63
+ if (isTimedOut) {
64
+ flushUpdates();
65
+ } else if (!isUpdating && updateQueue.length > 0) {
66
+ queueMicrotask(() => {
67
+ flushUpdates();
68
+ });
70
69
  }
70
+ }
71
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
- });
72
+ function withBatching(config = {}) {
73
+ const {
74
+ enabled = true
75
+ } = config;
76
+ currentBatchingConfig = {
77
+ ...currentBatchingConfig,
78
+ ...config
79
+ };
80
+ return tree => {
81
+ if (!enabled) {
82
+ return tree;
83
+ }
84
+ const originalTreeCall = tree.bind(tree);
85
+ const enhancedTree = function (...args) {
86
+ if (args.length === 0) {
87
+ return originalTreeCall();
88
+ } else {
89
+ batchUpdates(() => {
90
+ if (args.length === 1) {
91
+ const arg = args[0];
92
+ if (typeof arg === 'function') {
93
+ originalTreeCall(arg);
94
+ } else {
95
+ originalTreeCall(arg);
96
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;
97
+ }
98
+ });
99
+ }
100
+ };
101
+ Object.setPrototypeOf(enhancedTree, Object.getPrototypeOf(tree));
102
+ Object.assign(enhancedTree, tree);
103
+ if ('state' in tree) {
104
+ Object.defineProperty(enhancedTree, 'state', {
105
+ value: tree.state,
106
+ enumerable: false,
107
+ configurable: true
108
+ });
109
+ }
110
+ if ('$' in tree) {
111
+ Object.defineProperty(enhancedTree, '$', {
112
+ value: tree['$'],
113
+ enumerable: false,
114
+ configurable: true
115
+ });
116
+ }
117
+ enhancedTree.batchUpdate = updater => {
118
+ batchUpdates(() => {
119
+ const current = originalTreeCall();
120
+ const updates = updater(current);
121
+ Object.entries(updates).forEach(([key, value]) => {
122
+ const property = enhancedTree.state[key];
123
+ if (property && 'set' in property) {
124
+ property.set(value);
125
+ } else if (isNodeAccessor(property)) {
126
+ property(value);
127
+ }
128
+ });
129
+ });
130
130
  };
131
+ return enhancedTree;
132
+ };
131
133
  }
132
- export function withHighPerformanceBatching() {
133
- return withBatching({
134
- enabled: true,
135
- maxBatchSize: 200,
136
- batchTimeoutMs: 0,
137
- });
134
+ function withHighPerformanceBatching() {
135
+ return withBatching({
136
+ enabled: true,
137
+ maxBatchSize: 200,
138
+ batchTimeoutMs: 0
139
+ });
138
140
  }
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
- }
141
+ function flushBatchedUpdates() {
142
+ if (updateQueue.length > 0) {
143
+ const queue = updateQueue.slice();
144
+ updateQueue = [];
145
+ isUpdating = false;
146
+ queue.sort((a, b) => (b.depth ?? 0) - (a.depth ?? 0));
147
+ queue.forEach(({
148
+ fn
149
+ }) => {
150
+ fn();
151
+ });
152
+ }
149
153
  }
150
- export function hasPendingUpdates() {
151
- return updateQueue.length > 0;
154
+ function hasPendingUpdates() {
155
+ return updateQueue.length > 0;
152
156
  }
153
- export function getBatchQueueSize() {
154
- return updateQueue.length;
157
+ function getBatchQueueSize() {
158
+ return updateQueue.length;
155
159
  }
160
+
161
+ export { flushBatchedUpdates, getBatchQueueSize, hasPendingUpdates, withBatching, withHighPerformanceBatching };
@@ -1,19 +1,21 @@
1
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
- });
2
+ import { createEnhancer } from '../../index.js';
3
+
4
+ function computedEnhancer(_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
16
  }
17
- export function createComputed(dependencies, computeFn) {
18
- return computed(computeFn);
17
+ function createComputed(dependencies, computeFn) {
18
+ return computed(computeFn);
19
19
  }
20
+
21
+ export { computedEnhancer, createComputed };