@signaltree/core 4.0.13 → 4.0.15
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 +312 -0
- package/dist/enhancers/batching/index.d.ts +1 -0
- package/dist/enhancers/batching/index.js +1 -0
- package/dist/enhancers/batching/jest.config.d.ts +15 -0
- package/dist/enhancers/batching/jest.config.js +21 -0
- package/dist/enhancers/batching/lib/batching.d.ts +16 -0
- package/dist/enhancers/batching/lib/batching.js +155 -0
- package/dist/enhancers/batching/test-setup.d.ts +1 -0
- package/dist/enhancers/batching/test-setup.js +5 -0
- package/dist/enhancers/computed/index.d.ts +1 -0
- package/dist/enhancers/computed/index.js +1 -0
- package/dist/enhancers/computed/jest.config.d.ts +15 -0
- package/dist/enhancers/computed/jest.config.js +21 -0
- package/dist/enhancers/computed/lib/computed.d.ts +12 -0
- package/dist/enhancers/computed/lib/computed.js +19 -0
- package/dist/enhancers/devtools/index.d.ts +1 -0
- package/dist/enhancers/devtools/index.js +1 -0
- package/dist/enhancers/devtools/jest.config.d.ts +15 -0
- package/dist/enhancers/devtools/jest.config.js +21 -0
- package/dist/enhancers/devtools/lib/devtools.d.ts +77 -0
- package/dist/enhancers/devtools/lib/devtools.js +278 -0
- package/dist/enhancers/devtools/test-setup.d.ts +1 -0
- package/dist/enhancers/devtools/test-setup.js +5 -0
- package/dist/enhancers/entities/index.d.ts +1 -0
- package/dist/enhancers/entities/index.js +1 -0
- package/dist/enhancers/entities/jest.config.d.ts +15 -0
- package/dist/enhancers/entities/jest.config.js +21 -0
- package/dist/enhancers/entities/lib/entities.d.ts +22 -0
- package/dist/enhancers/entities/lib/entities.js +110 -0
- package/dist/enhancers/entities/test-setup.d.ts +1 -0
- package/dist/enhancers/entities/test-setup.js +5 -0
- package/dist/enhancers/index.d.ts +3 -0
- package/dist/enhancers/index.js +84 -0
- package/dist/enhancers/memoization/index.d.ts +1 -0
- package/dist/enhancers/memoization/index.js +1 -0
- package/dist/enhancers/memoization/jest.config.d.ts +15 -0
- package/dist/enhancers/memoization/jest.config.js +21 -0
- package/dist/enhancers/memoization/lib/memoization.d.ts +65 -0
- package/dist/enhancers/memoization/lib/memoization.js +391 -0
- package/dist/enhancers/memoization/test-setup.d.ts +1 -0
- package/dist/enhancers/memoization/test-setup.js +5 -0
- package/dist/enhancers/middleware/index.d.ts +2 -0
- package/dist/enhancers/middleware/index.js +2 -0
- package/dist/enhancers/middleware/jest.config.d.ts +15 -0
- package/dist/enhancers/middleware/jest.config.js +21 -0
- package/dist/enhancers/middleware/lib/async-helpers.d.ts +8 -0
- package/dist/enhancers/middleware/lib/async-helpers.js +85 -0
- package/dist/enhancers/middleware/lib/middleware.d.ts +11 -0
- package/dist/enhancers/middleware/lib/middleware.js +179 -0
- package/dist/enhancers/middleware/test-setup.d.ts +1 -0
- package/dist/enhancers/middleware/test-setup.js +5 -0
- package/dist/enhancers/presets/index.d.ts +1 -0
- package/dist/enhancers/presets/index.js +1 -0
- package/dist/enhancers/presets/jest.config.d.ts +15 -0
- package/dist/enhancers/presets/jest.config.js +21 -0
- package/dist/enhancers/presets/lib/presets.d.ts +11 -0
- package/dist/enhancers/presets/lib/presets.js +77 -0
- package/dist/enhancers/presets/test-setup.d.ts +1 -0
- package/dist/enhancers/presets/test-setup.js +5 -0
- package/dist/enhancers/serialization/constants.d.ts +14 -0
- package/dist/enhancers/serialization/constants.js +14 -0
- package/dist/enhancers/serialization/index.d.ts +2 -0
- package/dist/enhancers/serialization/index.js +2 -0
- package/dist/enhancers/serialization/jest.config.d.ts +15 -0
- package/dist/enhancers/serialization/jest.config.js +21 -0
- package/dist/enhancers/serialization/lib/serialization.d.ts +59 -0
- package/dist/enhancers/serialization/lib/serialization.js +668 -0
- package/dist/enhancers/serialization/test-setup.d.ts +1 -0
- package/dist/enhancers/serialization/test-setup.js +5 -0
- package/dist/enhancers/time-travel/index.d.ts +1 -0
- package/dist/enhancers/time-travel/index.js +1 -0
- package/dist/enhancers/time-travel/jest.config.d.ts +15 -0
- package/dist/enhancers/time-travel/jest.config.js +21 -0
- package/dist/enhancers/time-travel/lib/time-travel.d.ts +36 -0
- package/dist/enhancers/time-travel/lib/time-travel.js +192 -0
- package/dist/enhancers/time-travel/lib/utils.d.ts +1 -0
- package/dist/enhancers/time-travel/lib/utils.js +1 -0
- package/dist/enhancers/time-travel/test-setup.d.ts +1 -0
- package/dist/enhancers/time-travel/test-setup.js +5 -0
- package/dist/enhancers/types.d.ts +105 -0
- package/dist/enhancers/types.js +0 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +16 -0
- package/dist/lib/constants.d.ts +42 -0
- package/dist/lib/constants.js +61 -0
- package/dist/lib/memory/memory-manager.d.ts +30 -0
- package/dist/lib/memory/memory-manager.js +166 -0
- package/dist/lib/performance/diff-engine.d.ts +33 -0
- package/dist/lib/performance/diff-engine.js +156 -0
- package/dist/lib/performance/path-index.d.ts +25 -0
- package/dist/lib/performance/path-index.js +154 -0
- package/dist/lib/performance/update-engine.d.ts +32 -0
- package/dist/lib/performance/update-engine.js +193 -0
- package/dist/lib/security/security-validator.d.ts +33 -0
- package/dist/lib/security/security-validator.js +139 -0
- package/dist/lib/signal-tree.d.ts +8 -0
- package/dist/lib/signal-tree.js +665 -0
- package/dist/lib/types.d.ts +164 -0
- package/dist/lib/types.js +9 -0
- package/dist/lib/utils.d.ts +27 -0
- package/dist/lib/utils.js +286 -0
- package/package.json +2 -8
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
displayName: 'time-travel',
|
|
3
|
+
preset: '../../../jest.preset.js',
|
|
4
|
+
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
|
|
5
|
+
coverageDirectory: '../../../coverage/packages/core/enhancers/time-travel',
|
|
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
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { SignalTree } from '../../../lib/types';
|
|
2
|
+
export interface TimeTravelEntry<T> {
|
|
3
|
+
state: T;
|
|
4
|
+
timestamp: number;
|
|
5
|
+
action: string;
|
|
6
|
+
payload?: unknown;
|
|
7
|
+
}
|
|
8
|
+
export interface TimeTravelInterface<T> {
|
|
9
|
+
undo(): boolean;
|
|
10
|
+
redo(): boolean;
|
|
11
|
+
getHistory(): TimeTravelEntry<T>[];
|
|
12
|
+
resetHistory(): void;
|
|
13
|
+
jumpTo(index: number): boolean;
|
|
14
|
+
getCurrentIndex(): number;
|
|
15
|
+
canUndo(): boolean;
|
|
16
|
+
canRedo(): boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface TimeTravelConfig {
|
|
19
|
+
maxHistorySize?: number;
|
|
20
|
+
includePayload?: boolean;
|
|
21
|
+
actionNames?: {
|
|
22
|
+
update?: string;
|
|
23
|
+
set?: string;
|
|
24
|
+
batch?: string;
|
|
25
|
+
[key: string]: string | undefined;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export declare function withTimeTravel<T>(config?: TimeTravelConfig): (tree: SignalTree<T>) => SignalTree<T> & {
|
|
29
|
+
__timeTravel: TimeTravelInterface<T>;
|
|
30
|
+
};
|
|
31
|
+
export declare function enableTimeTravel<T>(maxHistorySize?: number): (tree: SignalTree<T>) => SignalTree<T> & {
|
|
32
|
+
__timeTravel: TimeTravelInterface<T>;
|
|
33
|
+
};
|
|
34
|
+
export declare function getTimeTravel<T>(tree: SignalTree<T> & {
|
|
35
|
+
__timeTravel?: TimeTravelInterface<T>;
|
|
36
|
+
}): TimeTravelInterface<T> | undefined;
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { deepClone, deepEqual } from './utils';
|
|
2
|
+
class TimeTravelManager {
|
|
3
|
+
tree;
|
|
4
|
+
config;
|
|
5
|
+
restoreStateFn;
|
|
6
|
+
history = [];
|
|
7
|
+
currentIndex = -1;
|
|
8
|
+
maxHistorySize;
|
|
9
|
+
includePayload;
|
|
10
|
+
actionNames;
|
|
11
|
+
constructor(tree, config = {}, restoreStateFn) {
|
|
12
|
+
this.tree = tree;
|
|
13
|
+
this.config = config;
|
|
14
|
+
this.restoreStateFn = restoreStateFn;
|
|
15
|
+
this.maxHistorySize = config.maxHistorySize ?? 50;
|
|
16
|
+
this.includePayload = config.includePayload ?? true;
|
|
17
|
+
this.actionNames = {
|
|
18
|
+
update: 'UPDATE',
|
|
19
|
+
set: 'SET',
|
|
20
|
+
batch: 'BATCH',
|
|
21
|
+
...config.actionNames,
|
|
22
|
+
};
|
|
23
|
+
this.addEntry('INIT', this.tree());
|
|
24
|
+
}
|
|
25
|
+
addEntry(action, state, payload) {
|
|
26
|
+
if (this.currentIndex < this.history.length - 1) {
|
|
27
|
+
this.history = this.history.slice(0, this.currentIndex + 1);
|
|
28
|
+
}
|
|
29
|
+
const entry = {
|
|
30
|
+
state: deepClone(state),
|
|
31
|
+
timestamp: Date.now(),
|
|
32
|
+
action: this.actionNames[action] || action,
|
|
33
|
+
...(this.includePayload && payload !== undefined && { payload }),
|
|
34
|
+
};
|
|
35
|
+
this.history.push(entry);
|
|
36
|
+
this.currentIndex = this.history.length - 1;
|
|
37
|
+
if (this.history.length > this.maxHistorySize) {
|
|
38
|
+
this.history.shift();
|
|
39
|
+
this.currentIndex--;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
undo() {
|
|
43
|
+
if (!this.canUndo()) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
this.currentIndex--;
|
|
47
|
+
const entry = this.history[this.currentIndex];
|
|
48
|
+
this.restoreState(entry.state);
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
redo() {
|
|
52
|
+
if (!this.canRedo()) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
this.currentIndex++;
|
|
56
|
+
const entry = this.history[this.currentIndex];
|
|
57
|
+
this.restoreState(entry.state);
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
getHistory() {
|
|
61
|
+
return this.history.map((entry) => ({
|
|
62
|
+
...entry,
|
|
63
|
+
state: deepClone(entry.state),
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
resetHistory() {
|
|
67
|
+
const currentState = this.tree();
|
|
68
|
+
this.history = [];
|
|
69
|
+
this.currentIndex = -1;
|
|
70
|
+
this.addEntry('RESET', currentState);
|
|
71
|
+
}
|
|
72
|
+
jumpTo(index) {
|
|
73
|
+
if (index < 0 || index >= this.history.length) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
this.currentIndex = index;
|
|
77
|
+
const entry = this.history[index];
|
|
78
|
+
this.restoreState(entry.state);
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
getCurrentIndex() {
|
|
82
|
+
return this.currentIndex;
|
|
83
|
+
}
|
|
84
|
+
canUndo() {
|
|
85
|
+
return this.currentIndex > 0;
|
|
86
|
+
}
|
|
87
|
+
canRedo() {
|
|
88
|
+
return this.currentIndex < this.history.length - 1;
|
|
89
|
+
}
|
|
90
|
+
restoreState(state) {
|
|
91
|
+
if (this.restoreStateFn) {
|
|
92
|
+
this.restoreStateFn(state);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
this.tree(state);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
export function withTimeTravel(config = {}) {
|
|
100
|
+
return (tree) => {
|
|
101
|
+
const originalTreeCall = tree.bind(tree);
|
|
102
|
+
let isRestoring = false;
|
|
103
|
+
const timeTravelManager = new TimeTravelManager(tree, config, (state) => {
|
|
104
|
+
isRestoring = true;
|
|
105
|
+
try {
|
|
106
|
+
originalTreeCall(state);
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
isRestoring = false;
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
const enhancedTree = function (...args) {
|
|
113
|
+
if (args.length === 0) {
|
|
114
|
+
return originalTreeCall();
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
if (isRestoring) {
|
|
118
|
+
if (args.length === 1) {
|
|
119
|
+
const arg = args[0];
|
|
120
|
+
if (typeof arg === 'function') {
|
|
121
|
+
return originalTreeCall(arg);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
return originalTreeCall(arg);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const beforeState = originalTreeCall();
|
|
130
|
+
let result;
|
|
131
|
+
if (args.length === 1) {
|
|
132
|
+
const arg = args[0];
|
|
133
|
+
if (typeof arg === 'function') {
|
|
134
|
+
result = originalTreeCall(arg);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
result = originalTreeCall(arg);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const afterState = originalTreeCall();
|
|
141
|
+
const statesEqual = deepEqual(beforeState, afterState);
|
|
142
|
+
if (!statesEqual) {
|
|
143
|
+
timeTravelManager.addEntry('update', afterState);
|
|
144
|
+
}
|
|
145
|
+
return result;
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
Object.setPrototypeOf(enhancedTree, Object.getPrototypeOf(tree));
|
|
149
|
+
Object.assign(enhancedTree, tree);
|
|
150
|
+
if ('state' in tree) {
|
|
151
|
+
Object.defineProperty(enhancedTree, 'state', {
|
|
152
|
+
value: tree.state,
|
|
153
|
+
enumerable: false,
|
|
154
|
+
configurable: true,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
if ('$' in tree) {
|
|
158
|
+
Object.defineProperty(enhancedTree, '$', {
|
|
159
|
+
value: tree['$'],
|
|
160
|
+
enumerable: false,
|
|
161
|
+
configurable: true,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
enhancedTree.undo = () => {
|
|
165
|
+
timeTravelManager.undo();
|
|
166
|
+
};
|
|
167
|
+
enhancedTree.redo = () => {
|
|
168
|
+
timeTravelManager.redo();
|
|
169
|
+
};
|
|
170
|
+
enhancedTree.getHistory = () => timeTravelManager.getHistory();
|
|
171
|
+
enhancedTree.resetHistory =
|
|
172
|
+
() => {
|
|
173
|
+
timeTravelManager.resetHistory();
|
|
174
|
+
};
|
|
175
|
+
enhancedTree.jumpTo = (index) => {
|
|
176
|
+
timeTravelManager.jumpTo(index);
|
|
177
|
+
};
|
|
178
|
+
enhancedTree.canUndo = () => timeTravelManager.canUndo();
|
|
179
|
+
enhancedTree.canRedo = () => timeTravelManager.canRedo();
|
|
180
|
+
enhancedTree.getCurrentIndex =
|
|
181
|
+
() => timeTravelManager.getCurrentIndex();
|
|
182
|
+
return Object.assign(enhancedTree, {
|
|
183
|
+
__timeTravel: timeTravelManager,
|
|
184
|
+
});
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
export function enableTimeTravel(maxHistorySize) {
|
|
188
|
+
return withTimeTravel({ maxHistorySize });
|
|
189
|
+
}
|
|
190
|
+
export function getTimeTravel(tree) {
|
|
191
|
+
return tree.__timeTravel;
|
|
192
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { deepClone, deepEqual } from '@signaltree/shared';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { deepClone, deepEqual } from '@signaltree/shared';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
export interface BatchingConfig {
|
|
2
|
+
maxBatchSize?: number;
|
|
3
|
+
debounceMs?: number;
|
|
4
|
+
flushOnMicrotask?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface BatchUpdate<T = unknown> {
|
|
7
|
+
path: string[];
|
|
8
|
+
value: T;
|
|
9
|
+
timestamp: number;
|
|
10
|
+
}
|
|
11
|
+
export interface ComputedSignal<T> {
|
|
12
|
+
(): T;
|
|
13
|
+
readonly value: T;
|
|
14
|
+
}
|
|
15
|
+
export interface ComputedConfig {
|
|
16
|
+
lazy?: boolean;
|
|
17
|
+
memoize?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface MiddlewareConfig {
|
|
20
|
+
beforeUpdate?: (path: string[], value: unknown) => void | boolean;
|
|
21
|
+
afterUpdate?: (path: string[], value: unknown, previousValue: unknown) => void;
|
|
22
|
+
beforeRead?: (path: string[]) => void;
|
|
23
|
+
afterRead?: (path: string[], value: unknown) => void;
|
|
24
|
+
}
|
|
25
|
+
export interface MiddlewareContext {
|
|
26
|
+
path: string[];
|
|
27
|
+
value: unknown;
|
|
28
|
+
previousValue?: unknown;
|
|
29
|
+
operation: 'read' | 'write';
|
|
30
|
+
}
|
|
31
|
+
export interface MemoizationConfig {
|
|
32
|
+
maxSize?: number;
|
|
33
|
+
ttl?: number;
|
|
34
|
+
strategy?: 'lru' | 'fifo' | 'lfu';
|
|
35
|
+
}
|
|
36
|
+
export interface MemoizedFunction<T extends (...args: never[]) => unknown> {
|
|
37
|
+
(...args: Parameters<T>): ReturnType<T>;
|
|
38
|
+
clear(): void;
|
|
39
|
+
stats(): {
|
|
40
|
+
hits: number;
|
|
41
|
+
misses: number;
|
|
42
|
+
size: number;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export interface TimeTravelConfig {
|
|
46
|
+
maxHistorySize?: number;
|
|
47
|
+
enableCompression?: boolean;
|
|
48
|
+
}
|
|
49
|
+
export interface TimeTravelState {
|
|
50
|
+
canUndo: boolean;
|
|
51
|
+
canRedo: boolean;
|
|
52
|
+
historySize: number;
|
|
53
|
+
currentIndex: number;
|
|
54
|
+
}
|
|
55
|
+
export interface DevToolsConfig {
|
|
56
|
+
name?: string;
|
|
57
|
+
enabled?: boolean;
|
|
58
|
+
logLevel?: 'debug' | 'info' | 'warn' | 'error';
|
|
59
|
+
}
|
|
60
|
+
export interface DevToolsAction {
|
|
61
|
+
type: string;
|
|
62
|
+
payload?: unknown;
|
|
63
|
+
timestamp: number;
|
|
64
|
+
source: string;
|
|
65
|
+
}
|
|
66
|
+
export interface PresetConfig {
|
|
67
|
+
name: string;
|
|
68
|
+
enhancers: unknown[];
|
|
69
|
+
config?: Record<string, unknown>;
|
|
70
|
+
}
|
|
71
|
+
export interface EntityConfig {
|
|
72
|
+
idField?: string;
|
|
73
|
+
indexes?: string[];
|
|
74
|
+
relations?: Record<string, string>;
|
|
75
|
+
}
|
|
76
|
+
export interface EntityCollection<T = unknown> {
|
|
77
|
+
add(entity: T): void;
|
|
78
|
+
remove(id: string | number): boolean;
|
|
79
|
+
update(id: string | number, updates: Partial<T>): boolean;
|
|
80
|
+
get(id: string | number): T | undefined;
|
|
81
|
+
find(predicate: (entity: T) => boolean): T | undefined;
|
|
82
|
+
filter(predicate: (entity: T) => boolean): T[];
|
|
83
|
+
count(): number;
|
|
84
|
+
}
|
|
85
|
+
export interface AsyncConfig {
|
|
86
|
+
timeout?: number;
|
|
87
|
+
retryAttempts?: number;
|
|
88
|
+
retryDelay?: number;
|
|
89
|
+
}
|
|
90
|
+
export interface AsyncAction<T = unknown> {
|
|
91
|
+
execute(): Promise<T>;
|
|
92
|
+
cancel(): void;
|
|
93
|
+
status: 'pending' | 'fulfilled' | 'rejected' | 'cancelled';
|
|
94
|
+
}
|
|
95
|
+
export interface SerializationConfig {
|
|
96
|
+
includeComputed?: boolean;
|
|
97
|
+
includeMeta?: boolean;
|
|
98
|
+
customSerializers?: Record<string, (value: unknown) => unknown>;
|
|
99
|
+
}
|
|
100
|
+
export interface SerializedState {
|
|
101
|
+
version: string;
|
|
102
|
+
timestamp: number;
|
|
103
|
+
data: unknown;
|
|
104
|
+
meta?: Record<string, unknown>;
|
|
105
|
+
}
|
|
File without changes
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export { signalTree } from './lib/signal-tree';
|
|
2
|
+
export type { SignalTree, TreeNode, RemoveSignalMethods, Primitive, BuiltInObject, NotFn, TreeConfig, TreePreset, Enhancer, EnhancerMeta, EnhancerWithMeta, ChainResult, WithMethod, Middleware, PerformanceMetrics, EntityHelpers, AsyncActionConfig, AsyncAction, TimeTravelEntry, } from './lib/types';
|
|
3
|
+
export { equal, deepEqual, isNodeAccessor, isAnySignal, parsePath, composeEnhancers, isBuiltInObject, createLazySignalTree, } from './lib/utils';
|
|
4
|
+
export { SecurityValidator, SecurityPresets, type SecurityEvent, type SecurityEventType, type SecurityValidatorConfig, } from './lib/security/security-validator';
|
|
5
|
+
export { createEnhancer, resolveEnhancerOrder } from './enhancers/index';
|
|
6
|
+
export { ENHANCER_META } from './lib/types';
|
|
7
|
+
export { withBatching, withHighPerformanceBatching, flushBatchedUpdates, hasPendingUpdates, getBatchQueueSize, } from './enhancers/batching/lib/batching';
|
|
8
|
+
export { withMemoization, withSelectorMemoization, withComputedMemoization, withDeepStateMemoization, withHighFrequencyMemoization, withHighPerformanceMemoization, withLightweightMemoization, withShallowMemoization, memoize, memoizeShallow, memoizeReference, cleanupMemoizationCache, clearAllCaches, getGlobalCacheStats, } from './enhancers/memoization/lib/memoization';
|
|
9
|
+
export { withTimeTravel, enableTimeTravel, getTimeTravel, type TimeTravelInterface, } from './enhancers/time-travel/lib/time-travel';
|
|
10
|
+
export { withEntities, enableEntities, withHighPerformanceEntities, } from './enhancers/entities/lib/entities';
|
|
11
|
+
export { withSerialization, enableSerialization, withPersistence, createStorageAdapter, createIndexedDBAdapter, applySerialization, applyPersistence, } from './enhancers/serialization/lib/serialization';
|
|
12
|
+
export { withDevTools, enableDevTools, withFullDevTools, withProductionDevTools, } from './enhancers/devtools/lib/devtools';
|
|
13
|
+
export { withMiddleware, createLoggingMiddleware, createValidationMiddleware, } from './enhancers/middleware/lib/middleware';
|
|
14
|
+
export { createAsyncOperation, trackAsync, } from './enhancers/middleware/lib/async-helpers';
|
|
15
|
+
export { TREE_PRESETS, createPresetConfig, validatePreset, getAvailablePresets, combinePresets, createDevTree, } from './enhancers/presets/lib/presets';
|
|
16
|
+
export { computedEnhancer, createComputed, type ComputedConfig, type ComputedSignal, type ComputedSignalTree, } from './enhancers/computed/lib/computed';
|
|
17
|
+
export { SIGNAL_TREE_CONSTANTS, SIGNAL_TREE_MESSAGES } from './lib/constants';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { signalTree } from './lib/signal-tree';
|
|
2
|
+
export { equal, deepEqual, isNodeAccessor, isAnySignal, parsePath, composeEnhancers, isBuiltInObject, createLazySignalTree, } from './lib/utils';
|
|
3
|
+
export { SecurityValidator, SecurityPresets, } from './lib/security/security-validator';
|
|
4
|
+
export { createEnhancer, resolveEnhancerOrder } from './enhancers/index';
|
|
5
|
+
export { ENHANCER_META } from './lib/types';
|
|
6
|
+
export { withBatching, withHighPerformanceBatching, flushBatchedUpdates, hasPendingUpdates, getBatchQueueSize, } from './enhancers/batching/lib/batching';
|
|
7
|
+
export { withMemoization, withSelectorMemoization, withComputedMemoization, withDeepStateMemoization, withHighFrequencyMemoization, withHighPerformanceMemoization, withLightweightMemoization, withShallowMemoization, memoize, memoizeShallow, memoizeReference, cleanupMemoizationCache, clearAllCaches, getGlobalCacheStats, } from './enhancers/memoization/lib/memoization';
|
|
8
|
+
export { withTimeTravel, enableTimeTravel, getTimeTravel, } from './enhancers/time-travel/lib/time-travel';
|
|
9
|
+
export { withEntities, enableEntities, withHighPerformanceEntities, } from './enhancers/entities/lib/entities';
|
|
10
|
+
export { withSerialization, enableSerialization, withPersistence, createStorageAdapter, createIndexedDBAdapter, applySerialization, applyPersistence, } from './enhancers/serialization/lib/serialization';
|
|
11
|
+
export { withDevTools, enableDevTools, withFullDevTools, withProductionDevTools, } from './enhancers/devtools/lib/devtools';
|
|
12
|
+
export { withMiddleware, createLoggingMiddleware, createValidationMiddleware, } from './enhancers/middleware/lib/middleware';
|
|
13
|
+
export { createAsyncOperation, trackAsync, } from './enhancers/middleware/lib/async-helpers';
|
|
14
|
+
export { TREE_PRESETS, createPresetConfig, validatePreset, getAvailablePresets, combinePresets, createDevTree, } from './enhancers/presets/lib/presets';
|
|
15
|
+
export { computedEnhancer, createComputed, } from './enhancers/computed/lib/computed';
|
|
16
|
+
export { SIGNAL_TREE_CONSTANTS, SIGNAL_TREE_MESSAGES } from './lib/constants';
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export declare const SIGNAL_TREE_CONSTANTS: {
|
|
2
|
+
readonly MAX_PATH_CACHE_SIZE: 1000;
|
|
3
|
+
readonly LAZY_THRESHOLD: 50;
|
|
4
|
+
readonly ESTIMATE_MAX_DEPTH: 3;
|
|
5
|
+
readonly ESTIMATE_SAMPLE_SIZE_ARRAY: 3;
|
|
6
|
+
readonly ESTIMATE_SAMPLE_SIZE_OBJECT: 5;
|
|
7
|
+
readonly DEFAULT_CACHE_SIZE: 100;
|
|
8
|
+
readonly DEFAULT_BATCH_SIZE: 10;
|
|
9
|
+
};
|
|
10
|
+
export declare const SIGNAL_TREE_MESSAGES: Readonly<{
|
|
11
|
+
readonly NULL_OR_UNDEFINED: "null/undefined";
|
|
12
|
+
readonly CIRCULAR_REF: "circular ref";
|
|
13
|
+
readonly UPDATER_INVALID: "updater invalid";
|
|
14
|
+
readonly LAZY_FALLBACK: "lazy fallback";
|
|
15
|
+
readonly SIGNAL_CREATION_FAILED: "signal creation failed";
|
|
16
|
+
readonly UPDATE_PATH_NOT_FOUND: "update path not found";
|
|
17
|
+
readonly UPDATE_FAILED: "update failed";
|
|
18
|
+
readonly ROLLBACK_FAILED: "rollback failed";
|
|
19
|
+
readonly CLEANUP_ERROR: "cleanup error";
|
|
20
|
+
readonly PRESET_UNKNOWN: "unknown preset";
|
|
21
|
+
readonly STRATEGY_SELECTION: "strategy select";
|
|
22
|
+
readonly TREE_DESTROYED: "destroyed";
|
|
23
|
+
readonly UPDATE_TRANSACTION: "update tx";
|
|
24
|
+
readonly BATCH_NOT_ENABLED: "batching disabled";
|
|
25
|
+
readonly MEMOIZE_NOT_ENABLED: "memoize disabled";
|
|
26
|
+
readonly MIDDLEWARE_NOT_AVAILABLE: "middleware missing";
|
|
27
|
+
readonly ENTITY_HELPERS_NOT_AVAILABLE: "entity helpers missing";
|
|
28
|
+
readonly ASYNC_ACTIONS_NOT_AVAILABLE: "async actions missing";
|
|
29
|
+
readonly TIME_TRAVEL_NOT_AVAILABLE: "time travel missing";
|
|
30
|
+
readonly OPTIMIZE_NOT_AVAILABLE: "optimize missing";
|
|
31
|
+
readonly UPDATE_OPTIMIZED_NOT_AVAILABLE: "update optimized missing";
|
|
32
|
+
readonly CACHE_NOT_AVAILABLE: "cache missing";
|
|
33
|
+
readonly PERFORMANCE_NOT_ENABLED: "performance disabled";
|
|
34
|
+
readonly ENHANCER_ORDER_FAILED: "enhancer order failed";
|
|
35
|
+
readonly ENHANCER_CYCLE_DETECTED: "enhancer cycle";
|
|
36
|
+
readonly ENHANCER_REQUIREMENT_MISSING: "enhancer req missing";
|
|
37
|
+
readonly ENHANCER_PROVIDES_MISSING: "enhancer provides missing";
|
|
38
|
+
readonly ENHANCER_FAILED: "enhancer failed";
|
|
39
|
+
readonly ENHANCER_NOT_FUNCTION: "enhancer not function";
|
|
40
|
+
readonly EFFECT_NO_CONTEXT: "no angular context";
|
|
41
|
+
readonly SUBSCRIBE_NO_CONTEXT: "no angular context";
|
|
42
|
+
}>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { DEFAULT_PATH_CACHE_SIZE } from '@signaltree/shared';
|
|
2
|
+
export const SIGNAL_TREE_CONSTANTS = {
|
|
3
|
+
MAX_PATH_CACHE_SIZE: DEFAULT_PATH_CACHE_SIZE,
|
|
4
|
+
LAZY_THRESHOLD: 50,
|
|
5
|
+
ESTIMATE_MAX_DEPTH: 3,
|
|
6
|
+
ESTIMATE_SAMPLE_SIZE_ARRAY: 3,
|
|
7
|
+
ESTIMATE_SAMPLE_SIZE_OBJECT: 5,
|
|
8
|
+
DEFAULT_CACHE_SIZE: 100,
|
|
9
|
+
DEFAULT_BATCH_SIZE: 10,
|
|
10
|
+
};
|
|
11
|
+
const DEV_MESSAGES = {
|
|
12
|
+
NULL_OR_UNDEFINED: 'null/undefined',
|
|
13
|
+
CIRCULAR_REF: 'circular ref',
|
|
14
|
+
UPDATER_INVALID: 'updater invalid',
|
|
15
|
+
LAZY_FALLBACK: 'lazy fallback',
|
|
16
|
+
SIGNAL_CREATION_FAILED: 'signal creation failed',
|
|
17
|
+
UPDATE_PATH_NOT_FOUND: 'update path not found',
|
|
18
|
+
UPDATE_FAILED: 'update failed',
|
|
19
|
+
ROLLBACK_FAILED: 'rollback failed',
|
|
20
|
+
CLEANUP_ERROR: 'cleanup error',
|
|
21
|
+
PRESET_UNKNOWN: 'unknown preset',
|
|
22
|
+
STRATEGY_SELECTION: 'strategy select',
|
|
23
|
+
TREE_DESTROYED: 'destroyed',
|
|
24
|
+
UPDATE_TRANSACTION: 'update tx',
|
|
25
|
+
BATCH_NOT_ENABLED: 'batching disabled',
|
|
26
|
+
MEMOIZE_NOT_ENABLED: 'memoize disabled',
|
|
27
|
+
MIDDLEWARE_NOT_AVAILABLE: 'middleware missing',
|
|
28
|
+
ENTITY_HELPERS_NOT_AVAILABLE: 'entity helpers missing',
|
|
29
|
+
ASYNC_ACTIONS_NOT_AVAILABLE: 'async actions missing',
|
|
30
|
+
TIME_TRAVEL_NOT_AVAILABLE: 'time travel missing',
|
|
31
|
+
OPTIMIZE_NOT_AVAILABLE: 'optimize missing',
|
|
32
|
+
UPDATE_OPTIMIZED_NOT_AVAILABLE: 'update optimized missing',
|
|
33
|
+
CACHE_NOT_AVAILABLE: 'cache missing',
|
|
34
|
+
PERFORMANCE_NOT_ENABLED: 'performance disabled',
|
|
35
|
+
ENHANCER_ORDER_FAILED: 'enhancer order failed',
|
|
36
|
+
ENHANCER_CYCLE_DETECTED: 'enhancer cycle',
|
|
37
|
+
ENHANCER_REQUIREMENT_MISSING: 'enhancer req missing',
|
|
38
|
+
ENHANCER_PROVIDES_MISSING: 'enhancer provides missing',
|
|
39
|
+
ENHANCER_FAILED: 'enhancer failed',
|
|
40
|
+
ENHANCER_NOT_FUNCTION: 'enhancer not function',
|
|
41
|
+
EFFECT_NO_CONTEXT: 'no angular context',
|
|
42
|
+
SUBSCRIBE_NO_CONTEXT: 'no angular context',
|
|
43
|
+
};
|
|
44
|
+
const PROD_MESSAGES = (() => {
|
|
45
|
+
const out = {};
|
|
46
|
+
let i = 0;
|
|
47
|
+
for (const k of Object.keys(DEV_MESSAGES)) {
|
|
48
|
+
out[k] = String(i++);
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
})();
|
|
52
|
+
const _isProdByEnv = Boolean(typeof globalThis === 'object' &&
|
|
53
|
+
globalThis !== null &&
|
|
54
|
+
'process' in globalThis &&
|
|
55
|
+
typeof globalThis.process === 'object' &&
|
|
56
|
+
'env' in globalThis.process &&
|
|
57
|
+
globalThis.process.env.NODE_ENV === 'production');
|
|
58
|
+
const _isDev = typeof ngDevMode !== 'undefined' ? Boolean(ngDevMode) : !_isProdByEnv;
|
|
59
|
+
export const SIGNAL_TREE_MESSAGES = Object.freeze(_isDev
|
|
60
|
+
? DEV_MESSAGES
|
|
61
|
+
: PROD_MESSAGES);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { WritableSignal } from '@angular/core';
|
|
2
|
+
export interface MemoryStats {
|
|
3
|
+
cachedSignals: number;
|
|
4
|
+
cleanedUpSignals: number;
|
|
5
|
+
peakCachedSignals: number;
|
|
6
|
+
manualDisposes: number;
|
|
7
|
+
estimatedMemoryBytes: number;
|
|
8
|
+
}
|
|
9
|
+
export interface MemoryManagerConfig {
|
|
10
|
+
enableAutoCleanup?: boolean;
|
|
11
|
+
debugMode?: boolean;
|
|
12
|
+
onCleanup?: (path: string, stats: MemoryStats) => void;
|
|
13
|
+
}
|
|
14
|
+
export declare class SignalMemoryManager {
|
|
15
|
+
private cache;
|
|
16
|
+
private registry;
|
|
17
|
+
private config;
|
|
18
|
+
private stats;
|
|
19
|
+
constructor(config?: MemoryManagerConfig);
|
|
20
|
+
cacheSignal<T>(path: string, signal: WritableSignal<T>): void;
|
|
21
|
+
getSignal(path: string): WritableSignal<unknown> | undefined;
|
|
22
|
+
hasSignal(path: string): boolean;
|
|
23
|
+
removeSignal(path: string): boolean;
|
|
24
|
+
private handleCleanup;
|
|
25
|
+
getStats(): MemoryStats;
|
|
26
|
+
dispose(): void;
|
|
27
|
+
getCachedPaths(): string[];
|
|
28
|
+
clearStale(): number;
|
|
29
|
+
resetStats(): void;
|
|
30
|
+
}
|