@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.
- package/README.md +106 -38
- package/dist/constants.js +6 -0
- package/dist/deep-clone.js +80 -0
- package/dist/deep-equal.js +41 -0
- package/dist/enhancers/batching/lib/batching.js +141 -135
- package/dist/enhancers/computed/lib/computed.js +18 -16
- package/dist/enhancers/devtools/lib/devtools.js +303 -260
- package/dist/enhancers/entities/lib/entities.js +109 -104
- package/dist/enhancers/index.js +65 -77
- package/dist/enhancers/memoization/lib/memoization.js +339 -351
- package/dist/enhancers/middleware/lib/async-helpers.js +71 -79
- package/dist/enhancers/middleware/lib/middleware.js +126 -169
- package/dist/enhancers/presets/lib/presets.js +82 -71
- package/dist/enhancers/serialization/constants.js +14 -13
- package/dist/enhancers/serialization/lib/serialization.js +615 -623
- package/dist/enhancers/time-travel/lib/time-travel.js +178 -177
- package/dist/index.d.ts +1 -17
- package/dist/index.js +19 -16
- package/dist/is-built-in-object.js +23 -0
- package/dist/lib/constants.js +51 -55
- package/dist/lib/memory/memory-manager.js +152 -154
- package/dist/lib/performance/diff-engine.js +141 -141
- package/dist/lib/performance/path-index.js +139 -137
- package/dist/lib/performance/update-engine.js +171 -176
- package/dist/lib/security/security-validator.js +110 -128
- package/dist/lib/signal-tree.js +577 -611
- package/dist/lib/types.js +3 -9
- package/dist/lib/utils.js +236 -268
- package/dist/lru-cache.js +64 -0
- package/dist/parse-path.js +13 -0
- package/package.json +30 -16
- package/src/index.d.ts +17 -0
- package/{dist → src}/lib/utils.d.ts +1 -0
- package/dist/enhancers/batching/index.js +0 -1
- package/dist/enhancers/batching/jest.config.js +0 -21
- package/dist/enhancers/batching/test-setup.js +0 -5
- package/dist/enhancers/computed/index.js +0 -1
- package/dist/enhancers/computed/jest.config.js +0 -21
- package/dist/enhancers/devtools/index.js +0 -1
- package/dist/enhancers/devtools/jest.config.js +0 -21
- package/dist/enhancers/devtools/test-setup.js +0 -5
- package/dist/enhancers/entities/index.js +0 -1
- package/dist/enhancers/entities/jest.config.js +0 -21
- package/dist/enhancers/entities/test-setup.js +0 -5
- package/dist/enhancers/memoization/index.js +0 -1
- package/dist/enhancers/memoization/jest.config.js +0 -21
- package/dist/enhancers/memoization/test-setup.js +0 -5
- package/dist/enhancers/middleware/index.js +0 -2
- package/dist/enhancers/middleware/jest.config.js +0 -21
- package/dist/enhancers/middleware/test-setup.js +0 -5
- package/dist/enhancers/presets/index.js +0 -1
- package/dist/enhancers/presets/jest.config.js +0 -21
- package/dist/enhancers/presets/test-setup.js +0 -5
- package/dist/enhancers/serialization/index.js +0 -2
- package/dist/enhancers/serialization/jest.config.js +0 -21
- package/dist/enhancers/serialization/test-setup.js +0 -5
- package/dist/enhancers/time-travel/index.js +0 -1
- package/dist/enhancers/time-travel/jest.config.js +0 -21
- package/dist/enhancers/time-travel/lib/utils.js +0 -1
- package/dist/enhancers/time-travel/test-setup.js +0 -5
- package/dist/enhancers/types.js +0 -0
- /package/{dist → src}/enhancers/batching/index.d.ts +0 -0
- /package/{dist → src}/enhancers/batching/jest.config.d.ts +0 -0
- /package/{dist → src}/enhancers/batching/lib/batching.d.ts +0 -0
- /package/{dist → src}/enhancers/batching/test-setup.d.ts +0 -0
- /package/{dist → src}/enhancers/computed/index.d.ts +0 -0
- /package/{dist → src}/enhancers/computed/jest.config.d.ts +0 -0
- /package/{dist → src}/enhancers/computed/lib/computed.d.ts +0 -0
- /package/{dist → src}/enhancers/devtools/index.d.ts +0 -0
- /package/{dist → src}/enhancers/devtools/jest.config.d.ts +0 -0
- /package/{dist → src}/enhancers/devtools/lib/devtools.d.ts +0 -0
- /package/{dist → src}/enhancers/devtools/test-setup.d.ts +0 -0
- /package/{dist → src}/enhancers/entities/index.d.ts +0 -0
- /package/{dist → src}/enhancers/entities/jest.config.d.ts +0 -0
- /package/{dist → src}/enhancers/entities/lib/entities.d.ts +0 -0
- /package/{dist → src}/enhancers/entities/test-setup.d.ts +0 -0
- /package/{dist → src}/enhancers/index.d.ts +0 -0
- /package/{dist → src}/enhancers/memoization/index.d.ts +0 -0
- /package/{dist → src}/enhancers/memoization/jest.config.d.ts +0 -0
- /package/{dist → src}/enhancers/memoization/lib/memoization.d.ts +0 -0
- /package/{dist → src}/enhancers/memoization/test-setup.d.ts +0 -0
- /package/{dist → src}/enhancers/middleware/index.d.ts +0 -0
- /package/{dist → src}/enhancers/middleware/jest.config.d.ts +0 -0
- /package/{dist → src}/enhancers/middleware/lib/async-helpers.d.ts +0 -0
- /package/{dist → src}/enhancers/middleware/lib/middleware.d.ts +0 -0
- /package/{dist → src}/enhancers/middleware/test-setup.d.ts +0 -0
- /package/{dist → src}/enhancers/presets/index.d.ts +0 -0
- /package/{dist → src}/enhancers/presets/jest.config.d.ts +0 -0
- /package/{dist → src}/enhancers/presets/lib/presets.d.ts +0 -0
- /package/{dist → src}/enhancers/presets/test-setup.d.ts +0 -0
- /package/{dist → src}/enhancers/serialization/constants.d.ts +0 -0
- /package/{dist → src}/enhancers/serialization/index.d.ts +0 -0
- /package/{dist → src}/enhancers/serialization/jest.config.d.ts +0 -0
- /package/{dist → src}/enhancers/serialization/lib/serialization.d.ts +0 -0
- /package/{dist → src}/enhancers/serialization/test-setup.d.ts +0 -0
- /package/{dist → src}/enhancers/time-travel/index.d.ts +0 -0
- /package/{dist → src}/enhancers/time-travel/jest.config.d.ts +0 -0
- /package/{dist → src}/enhancers/time-travel/lib/time-travel.d.ts +0 -0
- /package/{dist → src}/enhancers/time-travel/lib/utils.d.ts +0 -0
- /package/{dist → src}/enhancers/time-travel/test-setup.d.ts +0 -0
- /package/{dist → src}/enhancers/types.d.ts +0 -0
- /package/{dist → src}/lib/constants.d.ts +0 -0
- /package/{dist → src}/lib/memory/memory-manager.d.ts +0 -0
- /package/{dist → src}/lib/performance/diff-engine.d.ts +0 -0
- /package/{dist → src}/lib/performance/path-index.d.ts +0 -0
- /package/{dist → src}/lib/performance/update-engine.d.ts +0 -0
- /package/{dist → src}/lib/security/security-validator.d.ts +0 -0
- /package/{dist → src}/lib/signal-tree.d.ts +0 -0
- /package/{dist → src}/lib/types.d.ts +0 -0
|
@@ -1,85 +1,77 @@
|
|
|
1
1
|
import { signal } from '@angular/core';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
2
|
+
|
|
3
|
+
function createAsyncOperation(name, operation) {
|
|
4
|
+
return async tree => {
|
|
5
|
+
if (typeof tree.batchUpdate === 'function') {
|
|
6
|
+
const pendingPatch = {
|
|
7
|
+
[`${name}_PENDING`]: true
|
|
8
|
+
};
|
|
9
|
+
tree.batchUpdate(() => pendingPatch);
|
|
10
|
+
} else if ('$' in tree) {
|
|
11
|
+
try {
|
|
12
|
+
tree['$'][`${name}_PENDING`]?.set?.(true);
|
|
13
|
+
} catch (e) {
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const result = await operation();
|
|
18
|
+
if (typeof tree.batchUpdate === 'function') {
|
|
19
|
+
const resultPatch = {
|
|
20
|
+
[`${name}_RESULT`]: result,
|
|
21
|
+
[`${name}_PENDING`]: false
|
|
22
|
+
};
|
|
23
|
+
tree.batchUpdate(() => resultPatch);
|
|
24
|
+
} else if ('$' in tree) {
|
|
18
25
|
try {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
[`${name}_PENDING`]: false,
|
|
24
|
-
};
|
|
25
|
-
tree.batchUpdate(() => resultPatch);
|
|
26
|
-
}
|
|
27
|
-
else if ('$' in tree) {
|
|
28
|
-
try {
|
|
29
|
-
tree['$'][`${name}_RESULT`]?.set?.(result);
|
|
30
|
-
tree['$'][`${name}_PENDING`]?.set?.(false);
|
|
31
|
-
}
|
|
32
|
-
catch (e) {
|
|
33
|
-
void e;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return result;
|
|
26
|
+
tree['$'][`${name}_RESULT`]?.set?.(result);
|
|
27
|
+
tree['$'][`${name}_PENDING`]?.set?.(false);
|
|
28
|
+
} catch (e) {
|
|
29
|
+
void e;
|
|
37
30
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
void e;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
throw error;
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
} catch (error) {
|
|
34
|
+
if (typeof tree.batchUpdate === 'function') {
|
|
35
|
+
const errorPatch = {
|
|
36
|
+
[`${name}_ERROR`]: error,
|
|
37
|
+
[`${name}_PENDING`]: false
|
|
38
|
+
};
|
|
39
|
+
tree.batchUpdate(() => errorPatch);
|
|
40
|
+
} else if ('$' in tree) {
|
|
41
|
+
try {
|
|
42
|
+
tree['$'][`${name}_ERROR`]?.set?.(error);
|
|
43
|
+
tree['$'][`${name}_PENDING`]?.set?.(false);
|
|
44
|
+
} catch (e) {
|
|
56
45
|
}
|
|
57
|
-
|
|
46
|
+
}
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
58
50
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
},
|
|
84
|
-
};
|
|
51
|
+
function trackAsync(operation) {
|
|
52
|
+
const pending = signal(false);
|
|
53
|
+
const error = signal(null);
|
|
54
|
+
const result = signal(null);
|
|
55
|
+
return {
|
|
56
|
+
pending: pending.asReadonly(),
|
|
57
|
+
error: error.asReadonly(),
|
|
58
|
+
result: result.asReadonly(),
|
|
59
|
+
execute: async () => {
|
|
60
|
+
pending.set(true);
|
|
61
|
+
error.set(null);
|
|
62
|
+
try {
|
|
63
|
+
const res = await operation();
|
|
64
|
+
result.set(res);
|
|
65
|
+
return res;
|
|
66
|
+
} catch (e) {
|
|
67
|
+
const err = e instanceof Error ? e : new Error(String(e));
|
|
68
|
+
error.set(err);
|
|
69
|
+
throw err;
|
|
70
|
+
} finally {
|
|
71
|
+
pending.set(false);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
85
75
|
}
|
|
76
|
+
|
|
77
|
+
export { createAsyncOperation, trackAsync };
|
|
@@ -1,179 +1,136 @@
|
|
|
1
1
|
const middlewareMap = new WeakMap();
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
for (const middleware of treeMiddlewares) {
|
|
28
|
-
if (middleware.before &&
|
|
29
|
-
!middleware.before(action, updateResult, currentState)) {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
const previousState = currentState;
|
|
34
|
-
if (args.length === 1) {
|
|
35
|
-
const arg = args[0];
|
|
36
|
-
if (typeof arg === 'function') {
|
|
37
|
-
originalTreeCall(arg);
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
originalTreeCall(arg);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
const newState = originalTreeCall();
|
|
44
|
-
for (const middleware of treeMiddlewares) {
|
|
45
|
-
if (middleware.after) {
|
|
46
|
-
middleware.after(action, updateResult, previousState, newState);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
Object.setPrototypeOf(enhancedTree, Object.getPrototypeOf(tree));
|
|
52
|
-
Object.assign(enhancedTree, tree);
|
|
53
|
-
if ('state' in tree) {
|
|
54
|
-
Object.defineProperty(enhancedTree, 'state', {
|
|
55
|
-
value: tree.state,
|
|
56
|
-
enumerable: false,
|
|
57
|
-
configurable: true,
|
|
58
|
-
});
|
|
2
|
+
function withMiddleware(middlewares = []) {
|
|
3
|
+
return tree => {
|
|
4
|
+
middlewareMap.set(tree, [...middlewares]);
|
|
5
|
+
const originalTreeCall = tree.bind(tree);
|
|
6
|
+
const enhancedTree = function (...args) {
|
|
7
|
+
if (args.length === 0) {
|
|
8
|
+
return originalTreeCall();
|
|
9
|
+
} else {
|
|
10
|
+
const action = 'UPDATE';
|
|
11
|
+
const currentState = originalTreeCall();
|
|
12
|
+
const treeMiddlewares = middlewareMap.get(tree) || [];
|
|
13
|
+
let updateResult;
|
|
14
|
+
if (args.length === 1) {
|
|
15
|
+
const arg = args[0];
|
|
16
|
+
if (typeof arg === 'function') {
|
|
17
|
+
updateResult = arg(currentState);
|
|
18
|
+
} else {
|
|
19
|
+
updateResult = arg;
|
|
20
|
+
}
|
|
21
|
+
} else {
|
|
22
|
+
return;
|
|
59
23
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
configurable: true,
|
|
65
|
-
});
|
|
24
|
+
for (const middleware of treeMiddlewares) {
|
|
25
|
+
if (middleware.before && !middleware.before(action, updateResult, currentState)) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
66
28
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
middlewareMap.set(tree, treeMiddlewares);
|
|
77
|
-
};
|
|
78
|
-
enhancedTree.removeTap = (id) => {
|
|
79
|
-
const treeMiddlewares = middlewareMap.get(tree) || [];
|
|
80
|
-
const filtered = treeMiddlewares.filter((m) => m.id !== id);
|
|
81
|
-
middlewareMap.set(tree, filtered);
|
|
82
|
-
};
|
|
83
|
-
const originalBatchUpdate = tree.batchUpdate;
|
|
84
|
-
if (originalBatchUpdate) {
|
|
85
|
-
enhancedTree.batchUpdate = (updater) => {
|
|
86
|
-
const action = 'BATCH_UPDATE';
|
|
87
|
-
const currentState = originalTreeCall();
|
|
88
|
-
const updateResult = updater(currentState);
|
|
89
|
-
const treeMiddlewares = middlewareMap.get(tree) || [];
|
|
90
|
-
for (const middleware of treeMiddlewares) {
|
|
91
|
-
if (middleware.before &&
|
|
92
|
-
!middleware.before(action, updateResult, currentState)) {
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
const previousState = currentState;
|
|
97
|
-
originalBatchUpdate.call(tree, updater);
|
|
98
|
-
const newState = originalTreeCall();
|
|
99
|
-
for (const middleware of treeMiddlewares) {
|
|
100
|
-
if (middleware.after) {
|
|
101
|
-
middleware.after(action, updateResult, previousState, newState);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
};
|
|
29
|
+
const previousState = currentState;
|
|
30
|
+
if (args.length === 1) {
|
|
31
|
+
const arg = args[0];
|
|
32
|
+
if (typeof arg === 'function') {
|
|
33
|
+
originalTreeCall(arg);
|
|
34
|
+
} else {
|
|
35
|
+
originalTreeCall(arg);
|
|
36
|
+
}
|
|
105
37
|
}
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return enhancedTree;
|
|
38
|
+
const newState = originalTreeCall();
|
|
39
|
+
for (const middleware of treeMiddlewares) {
|
|
40
|
+
if (middleware.after) {
|
|
41
|
+
middleware.after(action, updateResult, previousState, newState);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
114
45
|
};
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
46
|
+
Object.setPrototypeOf(enhancedTree, Object.getPrototypeOf(tree));
|
|
47
|
+
Object.assign(enhancedTree, tree);
|
|
48
|
+
if ('state' in tree) {
|
|
49
|
+
Object.defineProperty(enhancedTree, 'state', {
|
|
50
|
+
value: tree.state,
|
|
51
|
+
enumerable: false,
|
|
52
|
+
configurable: true
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if ('$' in tree) {
|
|
56
|
+
Object.defineProperty(enhancedTree, '$', {
|
|
57
|
+
value: tree['$'],
|
|
58
|
+
enumerable: false,
|
|
59
|
+
configurable: true
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
enhancedTree.addTap = middleware => {
|
|
63
|
+
const treeMiddlewares = middlewareMap.get(tree) || [];
|
|
64
|
+
const existingIndex = treeMiddlewares.findIndex(m => m.id === middleware.id);
|
|
65
|
+
if (existingIndex >= 0) {
|
|
66
|
+
treeMiddlewares[existingIndex] = middleware;
|
|
67
|
+
} else {
|
|
68
|
+
treeMiddlewares.push(middleware);
|
|
69
|
+
}
|
|
70
|
+
middlewareMap.set(tree, treeMiddlewares);
|
|
129
71
|
};
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
before: (action) => {
|
|
135
|
-
console.time(`Tree update: ${action}`);
|
|
136
|
-
return true;
|
|
137
|
-
},
|
|
138
|
-
after: (action) => {
|
|
139
|
-
console.timeEnd(`Tree update: ${action}`);
|
|
140
|
-
},
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
export function createValidationMiddleware(validator) {
|
|
144
|
-
return {
|
|
145
|
-
id: 'validation',
|
|
146
|
-
after: (action, payload, state, newState) => {
|
|
147
|
-
const error = validator(newState);
|
|
148
|
-
if (error) {
|
|
149
|
-
console.error(`Validation failed after ${action}:`, error);
|
|
150
|
-
}
|
|
151
|
-
},
|
|
72
|
+
enhancedTree.removeTap = id => {
|
|
73
|
+
const treeMiddlewares = middlewareMap.get(tree) || [];
|
|
74
|
+
const filtered = treeMiddlewares.filter(m => m.id !== id);
|
|
75
|
+
middlewareMap.set(tree, filtered);
|
|
152
76
|
};
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
77
|
+
const originalBatchUpdate = tree.batchUpdate;
|
|
78
|
+
if (originalBatchUpdate) {
|
|
79
|
+
enhancedTree.batchUpdate = updater => {
|
|
80
|
+
const action = 'BATCH_UPDATE';
|
|
81
|
+
const currentState = originalTreeCall();
|
|
82
|
+
const updateResult = updater(currentState);
|
|
83
|
+
const treeMiddlewares = middlewareMap.get(tree) || [];
|
|
84
|
+
for (const middleware of treeMiddlewares) {
|
|
85
|
+
if (middleware.before && !middleware.before(action, updateResult, currentState)) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
160
88
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
},
|
|
89
|
+
const previousState = currentState;
|
|
90
|
+
originalBatchUpdate.call(tree, updater);
|
|
91
|
+
const newState = originalTreeCall();
|
|
92
|
+
for (const middleware of treeMiddlewares) {
|
|
93
|
+
if (middleware.after) {
|
|
94
|
+
middleware.after(action, updateResult, previousState, newState);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
const originalDestroy = tree.destroy;
|
|
100
|
+
enhancedTree.destroy = () => {
|
|
101
|
+
middlewareMap.delete(tree);
|
|
102
|
+
if (originalDestroy) {
|
|
103
|
+
originalDestroy.call(tree);
|
|
104
|
+
}
|
|
178
105
|
};
|
|
106
|
+
return enhancedTree;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function createLoggingMiddleware(treeName) {
|
|
110
|
+
return {
|
|
111
|
+
id: 'logging',
|
|
112
|
+
before: (action, payload, state) => {
|
|
113
|
+
console.group(`🏪 ${treeName}: ${action}`);
|
|
114
|
+
console.log('Previous state:', state);
|
|
115
|
+
console.log('Payload:', typeof payload === 'function' ? 'Function' : payload);
|
|
116
|
+
return true;
|
|
117
|
+
},
|
|
118
|
+
after: (action, payload, state, newState) => {
|
|
119
|
+
console.log('New state:', newState);
|
|
120
|
+
console.groupEnd();
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function createValidationMiddleware(validator) {
|
|
125
|
+
return {
|
|
126
|
+
id: 'validation',
|
|
127
|
+
after: (action, payload, state, newState) => {
|
|
128
|
+
const error = validator(newState);
|
|
129
|
+
if (error) {
|
|
130
|
+
console.error(`Validation failed after ${action}:`, error);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
};
|
|
179
134
|
}
|
|
135
|
+
|
|
136
|
+
export { createLoggingMiddleware, createValidationMiddleware, withMiddleware };
|
|
@@ -1,77 +1,88 @@
|
|
|
1
|
-
import { composeEnhancers } from '../../../lib/utils';
|
|
2
|
-
import {
|
|
3
|
-
import { withDevTools } from '../../devtools/lib/devtools';
|
|
4
|
-
import { withHighPerformanceMemoization, withMemoization } from '../../memoization/lib/memoization';
|
|
5
|
-
import { withMiddleware } from '../../middleware/lib/middleware';
|
|
6
|
-
import { withTimeTravel } from '../../time-travel/lib/time-travel';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
1
|
+
import { composeEnhancers } from '../../../lib/utils.js';
|
|
2
|
+
import { withHighPerformanceBatching, withBatching } from '../../batching/lib/batching.js';
|
|
3
|
+
import { withDevTools } from '../../devtools/lib/devtools.js';
|
|
4
|
+
import { withHighPerformanceMemoization, withMemoization } from '../../memoization/lib/memoization.js';
|
|
5
|
+
import { withMiddleware } from '../../middleware/lib/middleware.js';
|
|
6
|
+
import { withTimeTravel } from '../../time-travel/lib/time-travel.js';
|
|
7
|
+
|
|
8
|
+
const TREE_PRESETS = {
|
|
9
|
+
basic: {
|
|
10
|
+
batchUpdates: false,
|
|
11
|
+
useMemoization: false,
|
|
12
|
+
trackPerformance: false,
|
|
13
|
+
enableTimeTravel: false,
|
|
14
|
+
enableDevTools: false,
|
|
15
|
+
debugMode: false
|
|
16
|
+
},
|
|
17
|
+
performance: {
|
|
18
|
+
batchUpdates: true,
|
|
19
|
+
useMemoization: true,
|
|
20
|
+
trackPerformance: false,
|
|
21
|
+
enableTimeTravel: false,
|
|
22
|
+
enableDevTools: false,
|
|
23
|
+
debugMode: false,
|
|
24
|
+
useShallowComparison: true,
|
|
25
|
+
maxCacheSize: 200
|
|
26
|
+
},
|
|
27
|
+
development: {
|
|
28
|
+
batchUpdates: true,
|
|
29
|
+
useMemoization: true,
|
|
30
|
+
trackPerformance: true,
|
|
31
|
+
enableTimeTravel: true,
|
|
32
|
+
enableDevTools: true,
|
|
33
|
+
debugMode: true,
|
|
34
|
+
maxCacheSize: 100
|
|
35
|
+
},
|
|
36
|
+
production: {
|
|
37
|
+
batchUpdates: true,
|
|
38
|
+
useMemoization: true,
|
|
39
|
+
trackPerformance: false,
|
|
40
|
+
enableTimeTravel: false,
|
|
41
|
+
enableDevTools: false,
|
|
42
|
+
debugMode: false,
|
|
43
|
+
useShallowComparison: true,
|
|
44
|
+
maxCacheSize: 200
|
|
45
|
+
}
|
|
45
46
|
};
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
export function validatePreset(preset) {
|
|
54
|
-
if (!TREE_PRESETS[preset]) {
|
|
55
|
-
throw new Error(`Invalid preset: ${preset}. Valid presets are: ${Object.keys(TREE_PRESETS).join(', ')}`);
|
|
56
|
-
}
|
|
57
|
-
return true;
|
|
47
|
+
function createPresetConfig(preset, overrides = {}) {
|
|
48
|
+
const baseConfig = TREE_PRESETS[preset];
|
|
49
|
+
return {
|
|
50
|
+
...baseConfig,
|
|
51
|
+
...overrides
|
|
52
|
+
};
|
|
58
53
|
}
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
function validatePreset(preset) {
|
|
55
|
+
if (!TREE_PRESETS[preset]) {
|
|
56
|
+
throw new Error(`Invalid preset: ${preset}. Valid presets are: ${Object.keys(TREE_PRESETS).join(', ')}`);
|
|
57
|
+
}
|
|
58
|
+
return true;
|
|
61
59
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
for (const preset of presets) {
|
|
65
|
-
validatePreset(preset);
|
|
66
|
-
combined = { ...combined, ...TREE_PRESETS[preset] };
|
|
67
|
-
}
|
|
68
|
-
return { ...combined, ...overrides };
|
|
60
|
+
function getAvailablePresets() {
|
|
61
|
+
return Object.keys(TREE_PRESETS);
|
|
69
62
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
63
|
+
function combinePresets(presets, overrides = {}) {
|
|
64
|
+
let combined = {};
|
|
65
|
+
for (const preset of presets) {
|
|
66
|
+
validatePreset(preset);
|
|
67
|
+
combined = {
|
|
68
|
+
...combined,
|
|
69
|
+
...TREE_PRESETS[preset]
|
|
76
70
|
};
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
...combined,
|
|
74
|
+
...overrides
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function createDevTree(overrides = {}) {
|
|
78
|
+
const config = createPresetConfig('development', overrides);
|
|
79
|
+
const composed = composeEnhancers(withBatching(), withHighPerformanceBatching(), withMemoization(), withHighPerformanceMemoization(), withMiddleware(), withTimeTravel(), withDevTools({
|
|
80
|
+
treeName: config.treeName ?? 'SignalTree Dev'
|
|
81
|
+
}));
|
|
82
|
+
return {
|
|
83
|
+
config,
|
|
84
|
+
enhancer: composed
|
|
85
|
+
};
|
|
77
86
|
}
|
|
87
|
+
|
|
88
|
+
export { TREE_PRESETS, combinePresets, createDevTree, createPresetConfig, getAvailablePresets, validatePreset };
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
CIRCULAR: '§c',
|
|
1
|
+
const TYPE_MARKERS = {
|
|
2
|
+
DATE: '§d',
|
|
3
|
+
REGEXP: '§r',
|
|
4
|
+
MAP: '§m',
|
|
5
|
+
SET: '§s',
|
|
6
|
+
UNDEFINED: '§u',
|
|
7
|
+
NAN: '§n',
|
|
8
|
+
INFINITY: '§i',
|
|
9
|
+
NEG_INFINITY: '§-i',
|
|
10
|
+
BIGINT: '§b',
|
|
11
|
+
SYMBOL: '§y',
|
|
12
|
+
CIRCULAR: '§c'
|
|
14
13
|
};
|
|
14
|
+
|
|
15
|
+
export { TYPE_MARKERS };
|