@signaltree/enterprise 13.4.0 → 13.5.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 CHANGED
@@ -1,272 +1,115 @@
1
1
  # @signaltree/enterprise
2
2
 
3
- Enterprise-grade optimizations for SignalTree. Designed for large-scale applications with 500+ signals and high-frequency bulk updates.
3
+ > # ⚠️ Deprecated as of 13.5.0
4
+ >
5
+ > **Use `tree.updateAndReport()` from `@signaltree/core`.** They are built in, need no enhancer, add no bundle, and are faster than this package.
6
+ >
7
+ > This package remains published so existing installs keep resolving, and will receive security fixes only. No new features, and the array defect below is not being fixed.
4
8
 
5
- ## Features
9
+ ## Why it was retired
6
10
 
7
- - **Diff-based updates** - Only update signals that actually changed
8
- - **Bulk operation optimization** - 2-5x faster for large state updates
9
- - **Advanced change tracking** - Detailed statistics and monitoring
10
- - **Path-change subscriptions** - React to specific dot-paths changing (9.1+)
11
- - **Snapshot / restore** - Cheap structured-clone snapshots with diff-engine restore (9.1+)
12
- - **Auto-optimize threshold** - Route large updates through the diff engine automatically (9.1+)
13
- - **Lazy initialization** - Zero overhead until first use
11
+ **The headline performance claim was inverted.** Measured against `tree.updateAndReport()` — which returns the same changed paths — `updateOptimized()` is:
14
12
 
15
- ## Installation
13
+ | Workload (2,000 leaves) | `updateOptimized()` | `updateAndReport()` | Result |
14
+ | ----------------------------- | ------------------- | ------------------- | ------------------ |
15
+ | 10% of leaves changed | ~0.53 ms | ~0.08 ms | **~7x slower** |
16
+ | identical re-fetch (all no-op)| ~0.14 ms | ~0.07 ms | **~2x slower** |
17
+ | every leaf changed | ~24-27 ms | ~0.12-0.17 ms | **~160-190x slower** |
16
18
 
17
- ```bash
18
- npm install @signaltree/core @signaltree/enterprise
19
- ```
20
-
21
- ## Type Definitions
22
-
23
- Type declarations are shipped as `src/**/*.d.ts` and referenced by the package exports.
24
- No extra build step is needed to consume types.
25
-
26
- ## Quick Start
27
-
28
- ```typescript
29
- import { signalTree } from '@signaltree/core';
30
- import { enterprise } from '@signaltree/enterprise';
31
-
32
- const tree = signalTree(largeState).with(enterprise());
19
+ At 500 leaves the same workloads measure ~4-4.5x, ~1.2-1.6x and ~43x. The ratio
20
+ grows with tree size in every workload, which is the opposite of the scaling
21
+ story the package was sold on ("use it at 500+ signals").
33
22
 
34
- // Use optimized bulk updates
35
- const result = tree.updateOptimized(newData, {
36
- ignoreArrayOrder: true,
37
- maxDepth: 10,
38
- });
23
+ The long-standing "2-5x faster" claim was never measured against core. Numbers
24
+ are means over 50 timed iterations after warm-up, payloads generated outside the
25
+ timed loop; they will differ on your hardware, so treat the RATIOS as the
26
+ finding, not the absolute times.
39
27
 
40
- console.log(result.stats);
41
- // { totalChanges: 45, adds: 10, updates: 30, deletes: 5 }
42
- ```
43
-
44
- ## When to Use
45
-
46
- ### ✅ Use @signaltree/enterprise when:
47
-
48
- - You have 500+ signals in your state tree
49
- - Bulk updates happen at high frequency (60Hz+)
50
- - You need real-time dashboards or data feeds
51
- - You're building enterprise-scale applications
52
- - You need detailed update monitoring and statistics
53
-
54
- ### ❌ Skip @signaltree/enterprise when:
28
+ This is structural, not a tuning problem. Core leaves are `signal(value, { equal })` — deep equality plus a reference-equality short-circuit — so **"only write what actually changed" is already core behaviour, for free**. The diff engine walks the whole state to decide which writes to skip, and the writes it skips were already no-ops. No amount of optimization changes that shape; the work it does is work core does not need to do.
55
29
 
56
- - Small to medium apps (<100 signals)
57
- - Infrequent state updates
58
- - Startup/prototype projects
59
- - Bundle size is critical (adds +2.4KB gzipped)
30
+ Two further reasons:
60
31
 
61
- ## API
32
+ - **It no longer offers anything core lacks.** `changedPaths` and `updateAndReport()` return the same information, and `onPathChange` now ships in core.
33
+ - **It has no independent runtime dependency**, which puts it on the wrong side of the packaging rule in [RFC 0007](../../docs/rfcs/0007-packaging-principle-and-ng-forms-reslice.md) — a package should exist because it pulls in a dependency core should not.
62
34
 
63
- ### `enterprise(options?)`
64
-
65
- Enhancer that adds enterprise optimizations to a SignalTree.
35
+ ## Migration
66
36
 
67
37
  ```typescript
38
+ // Before
68
39
  import { signalTree } from '@signaltree/core';
69
40
  import { enterprise } from '@signaltree/enterprise';
70
41
 
71
- const tree = signalTree(initialState).with(enterprise());
72
-
73
- // Or with auto-optimize threshold (9.1+):
74
- const tree2 = signalTree(initialState).with(enterprise({ autoOptimizeThreshold: 100 }));
75
- ```
76
-
77
- **Options (9.1+):**
78
-
79
- ```typescript
80
- {
81
- autoOptimizeThreshold?: number; // If set, tree.updateAuto(...) routes through
82
- // updateOptimized when the payload has at
83
- // least this many top-level keys.
84
- }
85
- ```
86
-
87
- ### `tree.updateOptimized(updates, options?)`
88
-
89
- Performs optimized bulk updates using diff-based change detection.
90
-
91
- **Parameters:**
92
-
93
- - `updates: Partial<T>` - The new state values
94
- - `options?: UpdateOptions` - Configuration options
95
-
96
- **Options:**
97
-
98
- ```typescript
99
- {
100
- maxDepth?: number; // Maximum depth to traverse (default: 100)
101
- ignoreArrayOrder?: boolean; // Ignore array element order (default: false)
102
- equalityFn?: (a, b) => boolean; // Custom equality function
103
- autoBatch?: boolean; // Automatically batch updates (default: true)
104
- batchSize?: number; // Patches per batch (default: 10)
105
- }
106
- ```
107
-
108
- **Returns:**
109
-
110
- ```typescript
111
- {
112
- changed: boolean; // Whether any changes were made
113
- stats: {
114
- totalChanges: number; // Total number of changes
115
- adds: number; // New properties added
116
- updates: number; // Properties updated
117
- deletes: number; // Properties deleted
118
- }
119
- }
120
- ```
121
-
122
- ### `tree.getPathIndex()`
123
-
124
- > **Deprecated (9.1+):** Path-index access is an internal detail and will be
125
- > removed in a future major. Use `onPathChange` for change observation.
42
+ const tree = signalTree(state).with(enterprise());
43
+ const result = tree.updateOptimized(payload);
44
+ if (result.changed) sync(result.changedPaths);
126
45
 
127
- Get the PathIndex for debugging/monitoring. Returns `null` if `updateOptimized` hasn't been called yet (lazy initialization).
128
-
129
- ```typescript
130
- const index = tree.getPathIndex();
131
- if (index) {
132
- console.log('Path index active');
133
- }
134
- ```
135
-
136
- ### `tree.onPathChange(listener)` (9.1+)
137
-
138
- Subscribe to dot-paths that change on each `updateOptimized` (or
139
- `updateAuto` when it routes through the diff engine). Returns an
140
- unsubscribe function.
141
-
142
- ```typescript
143
- const off = tree.onPathChange((paths) => {
144
- console.log('changed:', paths); // e.g. ['user.name', 'cart.items.0.qty']
145
- });
146
-
147
- tree.updateOptimized({ user: { name: 'Ada' } });
148
- // → listener fires with ['user.name']
149
-
150
- off(); // stop listening
151
- ```
152
-
153
- ### `tree.snapshot()` / `tree.restore(snap)` (9.1+)
154
-
155
- Capture and restore the entire state via a `structuredClone`. `restore`
156
- routes through the diff engine, so listeners and stats fire as if the
157
- restored values were a normal optimized update.
158
-
159
- ```typescript
160
- const snap = tree.snapshot();
161
-
162
- tree.updateOptimized({ user: { name: 'Grace' } });
163
-
164
- // later... roll back
165
- tree.restore(snap);
166
- ```
167
-
168
- ### `tree.updateAuto(updates)` (9.1+)
169
-
170
- When `enterprise({ autoOptimizeThreshold: N })` is configured, payloads
171
- with `≥ N` top-level keys are routed through `updateOptimized`; smaller
172
- payloads use the regular fast path. Without a threshold this is a plain
173
- `update`.
174
-
175
- ```typescript
176
- const tree = signalTree(initialState).with(enterprise({ autoOptimizeThreshold: 50 }));
46
+ // After no enhancer, no extra bundle
47
+ import { signalTree } from '@signaltree/core';
177
48
 
178
- tree.updateAuto({ a: 1, b: 2 }); // fast path
179
- tree.updateAuto(largeServerPayload); // diff engine
49
+ const tree = signalTree(state);
50
+ const changed = tree.updateAndReport(payload);
51
+ if (changed.length) sync(changed);
180
52
  ```
181
53
 
182
- ## Examples
54
+ | Enterprise | Core replacement |
55
+ | ----------------------------------------- | --------------------------------------------------- |
56
+ | `tree.updateOptimized(p)` | `tree.updateAndReport(p)` — returns changed paths |
57
+ | `tree.onPathChange(fn)` | **no direct replacement yet** — use `tree.updateAndReport(p)` at the call site; a subscription API is being designed |
58
+ | `tree.snapshot()` | `const snap = tree()` |
59
+ | `tree.restore(snap)` | `tree(snap)` |
60
+ | `tree.updateAuto(p)` | `tree(p)` |
61
+ | `tree.getPathIndex()` | no replacement — was debug-only, already deprecated |
62
+ | `enterprise({ autoOptimizeThreshold: n })` | drop it — core has one write path |
183
63
 
184
- ### Real-time Dashboard
64
+ ### Two rows above are an IMPROVEMENT, not an equivalence
185
65
 
186
- ```typescript
187
- import { signalTree } from '@signaltree/core';
188
- import { enterprise } from '@signaltree/enterprise';
66
+ `restore()` and `updateAuto()` do not merely have a core equal — the core form
67
+ is **more correct**, because both inherit the array defect:
189
68
 
190
- interface DashboardState {
191
- metrics: Record<string, number>;
192
- alerts: Alert[];
193
- users: User[];
194
- // ... hundreds more properties
195
- }
69
+ - `tree.restore(snap)` → `tree(snap)`. Restoring `{a, b:{c,d}, arr:[1,2,3]}`
70
+ after mutating it leaves `arr` at its mutated value while reporting
71
+ `arr.0`, `arr.1`, `arr.2` as changed — three paths it never wrote. `tree(snap)`
72
+ restores the array. Neither deletes keys absent from the snapshot; both merge.
73
+ - `tree.updateAuto(p)` `tree(p)`, but only exactly equivalent when NO
74
+ `autoOptimizeThreshold` is set (then `updateAuto` is a plain passthrough). With
75
+ a threshold, a payload over it routes through the diff engine and drops array
76
+ writes; `tree(p)` applies them.
196
77
 
197
- const dashboard = signalTree<DashboardState>(initialState).with(enterprise());
78
+ ### Three behaviour differences worth knowing
198
79
 
199
- // High-frequency updates from WebSocket
200
- socket.on('metrics', (newMetrics) => {
201
- const result = dashboard.updateOptimized({ metrics: newMetrics }, { ignoreArrayOrder: true });
80
+ **1. `updateAndReport()` is stricter about what counts as a change.** It reports only paths whose leaf signal actually accepted the write. A re-fetched payload identical to what you already hold reports `[]`; the diff engine reported every key in it. If you were counting on the old numbers, they were counting no-ops.
202
81
 
203
- console.log(`Updated ${result.stats.updates} metrics`);
204
- });
205
- ```
82
+ **2. `onPathChange` in core fires for every root write** — the call form `tree({...})`, `batchUpdate()` and `updateAndReport()` — not just `updateOptimized()`. It does **not** fire for direct leaf writes (`tree.$.a.b.set(x)`), which bypass the root.
206
83
 
207
- ### Data Grid with Bulk Operations
84
+ **3. `snapshot()` here used `structuredClone`,** so it threw `DataCloneError` on any tree holding a function. `tree()` has no such limit.
208
85
 
209
- ```typescript
210
- import { signalTree } from '@signaltree/core';
211
- import { enterprise } from '@signaltree/enterprise';
212
-
213
- const grid = signalTree({
214
- rows: [] as GridRow[],
215
- columns: [] as GridColumn[],
216
- filters: {} as FilterState,
217
- selection: new Set<string>(),
218
- }).with(enterprise());
86
+ ## Known defect (not being fixed)
219
87
 
220
- // Bulk update from API
221
- async function loadData() {
222
- const data = await fetchGridData();
88
+ `updateOptimized()` **silently drops writes that target an array.** It reports `changed: true`, lists the paths, and writes nothing.
223
89
 
224
- const result = grid.updateOptimized(data, {
225
- maxDepth: 5,
226
- autoBatch: true,
227
- });
90
+ An array in a SignalTree is a single leaf — one `WritableSignal<T[]>` — while the diff engine is a general-purpose differ emitting element-level paths (`users.1`). The apply step cannot consume those against a leaf, so it bails and reports success anyway.
228
91
 
229
- console.log(`Loaded ${result.stats.adds} rows in bulk`);
230
- }
231
- ```
92
+ Two fixes were attempted and both withdrawn, each having introduced defects worse than the one it closed (silent truncation and prototype injection in the first; dotted-key data loss and spurious writes in the second). Given the package is superseded, it stays documented rather than fixed.
232
93
 
233
- ### Custom Equality for Complex Objects
94
+ **Workaround** write the array through its leaf:
234
95
 
235
96
  ```typescript
236
- const tree = signalTree(complexState).with(enterprise());
237
-
238
- tree.updateOptimized(newState, {
239
- equalityFn: (a, b) => {
240
- // Custom deep equality for specific object types
241
- if (a instanceof Date && b instanceof Date) {
242
- return a.getTime() === b.getTime();
243
- }
244
- return a === b;
245
- },
246
- });
97
+ tree.$.users.set(nextUsers); // works
98
+ tree.updateOptimized({ users: nextUsers }); // silently does nothing
247
99
  ```
248
100
 
249
- ## Performance
250
-
251
- **Bundle Size:**
101
+ Or migrate to `updateAndReport()`, which handles arrays correctly.
252
102
 
253
- - Adds +2.4KB gzipped to your bundle
254
- - Zero overhead until first `updateOptimized()` call (lazy initialization)
103
+ ## Removed in 13.5.0
255
104
 
256
- **Performance Gains:**
257
-
258
- - 2-5x faster for bulk updates on large state trees
259
- - Scales efficiently with tree depth and complexity
260
- - Minimal memory overhead with path indexing
105
+ `./scheduler` and `./thread-pools` subpath exports are gone. Both were dead — no caller anywhere in the repo and no tests. (They were *mentioned* in the v9 plan and on a demo page, but never documented as an API.) And `thread-pools` only ever exported `createMockPool()`, a test double that should never have shipped to production consumers. `scheduler`'s advertised "yield to the event loop" was `await Promise.resolve()`, a microtask, which does not yield.
261
106
 
262
107
  ## License
263
108
 
264
- Business Source License 1.1 (BSL-1.1) - See [LICENSE](../../LICENSE) for details.
265
-
266
- Converts to MIT license on the Change Date specified in the license.
109
+ Business Source License 1.1 (BSL-1.1) see [LICENSE](../../LICENSE). Converts to MIT on the Change Date specified in the license.
267
110
 
268
- ## Related Packages
111
+ ## Related packages
269
112
 
270
- - [@signaltree/core](../core) - Core SignalTree functionality
271
- - [@signaltree/ng-forms](../ng-forms) - Angular forms integration
272
- - [@signaltree/callable-syntax](../callable-syntax) - Callable syntax transform
113
+ - [@signaltree/core](../core) where `updateAndReport()` and `onPathChange()` now live
114
+ - [@signaltree/ng-forms](../ng-forms) Angular forms integration
115
+ - [@signaltree/callable-syntax](../callable-syntax) callable syntax transform
package/dist/index.js CHANGED
@@ -2,5 +2,3 @@ export { ChangeType, DiffEngine } from './lib/diff-engine.js';
2
2
  export { PathIndex } from './lib/path-index.js';
3
3
  export { OptimizedUpdateEngine } from './lib/update-engine.js';
4
4
  export { enterprise } from './lib/enterprise-enhancer.js';
5
- export { configureScheduler, getSchedulerMetrics, postTask } from './lib/scheduler.js';
6
- export { createMockPool } from './lib/thread-pools.js';
@@ -3,6 +3,10 @@ import { isTraversableNode, isBuiltInObject } from '@signaltree/core';
3
3
  import { DiffEngine, ChangeType } from './diff-engine.js';
4
4
  import { PathIndex } from './path-index.js';
5
5
 
6
+ const UNSAFE_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
7
+ function isUnsafeKey(key) {
8
+ return typeof key === 'string' && UNSAFE_KEYS.has(key);
9
+ }
6
10
  class OptimizedUpdateEngine {
7
11
  constructor(tree) {
8
12
  this.pathIndex = new PathIndex();
@@ -150,13 +154,18 @@ class OptimizedUpdateEngine {
150
154
  let current = tree;
151
155
  for (let i = 0; i < patch.path.length - 1; i++) {
152
156
  const key = patch.path[i];
157
+ if (isUnsafeKey(key)) return false;
158
+ if (!Object.prototype.hasOwnProperty.call(current, key)) {
159
+ return false;
160
+ }
153
161
  current = current[key];
154
162
  if (!isTraversableNode(current)) {
155
163
  return false;
156
164
  }
157
165
  }
158
166
  const lastKey = patch.path[patch.path.length - 1];
159
- const target = current[lastKey];
167
+ if (isUnsafeKey(lastKey)) return false;
168
+ const target = Object.prototype.hasOwnProperty.call(current, lastKey) ? current[lastKey] : undefined;
160
169
  if (isTraversableNode(target)) {
161
170
  if (isSignal(target)) {
162
171
  const leaf = target;
@@ -171,10 +180,19 @@ class OptimizedUpdateEngine {
171
180
  }
172
181
  return false;
173
182
  }
174
- if (this.isEqual(current[lastKey], patch.value)) {
183
+ if (this.isEqual(target, patch.value)) {
184
+ return false;
185
+ }
186
+ const existing = Object.getOwnPropertyDescriptor(current, lastKey);
187
+ if (!existing || !existing.enumerable) {
175
188
  return false;
176
189
  }
177
- current[lastKey] = patch.value;
190
+ Object.defineProperty(current, lastKey, {
191
+ value: patch.value,
192
+ enumerable: true,
193
+ writable: true,
194
+ configurable: true
195
+ });
178
196
  return true;
179
197
  } catch (error) {
180
198
  console.error(`Failed to apply patch at ${patch.path.join('.')}:`, error);
@@ -192,6 +210,8 @@ class OptimizedUpdateEngine {
192
210
  if (isTraversableNode(node) && value && typeof value === 'object') {
193
211
  let changed = false;
194
212
  for (const [key, child] of Object.entries(value)) {
213
+ if (isUnsafeKey(key)) continue;
214
+ if (!Object.prototype.hasOwnProperty.call(node, key)) continue;
195
215
  changed = this.applyDeepToNode(node[key], child) || changed;
196
216
  }
197
217
  return changed;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@signaltree/enterprise",
3
- "version": "13.4.0",
4
- "description": "Enterprise optimizations for SignalTree reactive JSON. Diff-based updates, bulk operations, and advanced change tracking for large-scale applications.",
3
+ "version": "13.5.0",
4
+ "description": "DEPRECATED use tree.updateAndReport() in @signaltree/core instead. The diff engine is measurably slower than the core API that replaced it.",
5
5
  "license": "BUSL-1.1",
6
6
  "type": "module",
7
7
  "sideEffects": false,
@@ -33,16 +33,6 @@
33
33
  "types": "./src/lib/enterprise-enhancer.d.ts",
34
34
  "import": "./dist/lib/enterprise-enhancer.js",
35
35
  "default": "./dist/lib/enterprise-enhancer.js"
36
- },
37
- "./scheduler": {
38
- "types": "./src/lib/scheduler.d.ts",
39
- "import": "./dist/lib/scheduler.js",
40
- "default": "./dist/lib/scheduler.js"
41
- },
42
- "./thread-pools": {
43
- "types": "./src/lib/thread-pools.d.ts",
44
- "import": "./dist/lib/thread-pools.js",
45
- "default": "./dist/lib/thread-pools.js"
46
36
  }
47
37
  },
48
38
  "keywords": [
@@ -68,7 +58,7 @@
68
58
  },
69
59
  "peerDependencies": {
70
60
  "@angular/core": "^20.0.0 || ^21.0.0 || ^22.0.0",
71
- "@signaltree/core": "^13.4.0",
61
+ "@signaltree/core": "^13.5.0",
72
62
  "tslib": "^2.0.0"
73
63
  },
74
64
  "peerDependenciesMeta": {},
package/src/index.d.ts CHANGED
@@ -2,5 +2,3 @@ export * from './lib/diff-engine';
2
2
  export * from './lib/path-index';
3
3
  export * from './lib/update-engine';
4
4
  export * from './lib/enterprise-enhancer';
5
- export * from './lib/scheduler';
6
- export * from './lib/thread-pools';
@@ -1,76 +0,0 @@
1
- import { __awaiter } from 'tslib';
2
-
3
- const defaultConfig = {
4
- yieldEveryTasks: 500,
5
- yieldEveryMs: 8,
6
- instrumentation: false
7
- };
8
- let config = Object.assign({}, defaultConfig);
9
- let metrics = {
10
- drainCycles: 0,
11
- tasksExecuted: 0,
12
- maxQueueLength: 0,
13
- yields: 0,
14
- lastDrainDurationMs: 0,
15
- totalDrainDurationMs: 0
16
- };
17
- const q = [];
18
- let draining = false;
19
- function configureScheduler(newConfig) {
20
- config = Object.assign(Object.assign({}, config), newConfig);
21
- }
22
- function getSchedulerMetrics(reset = false) {
23
- const snapshot = Object.assign({}, metrics);
24
- if (reset) {
25
- metrics = {
26
- drainCycles: 0,
27
- tasksExecuted: 0,
28
- maxQueueLength: 0,
29
- yields: 0,
30
- lastDrainDurationMs: 0,
31
- totalDrainDurationMs: 0
32
- };
33
- }
34
- return snapshot;
35
- }
36
- function postTask(t) {
37
- q.push(t);
38
- if (config.instrumentation && q.length > metrics.maxQueueLength) {
39
- metrics.maxQueueLength = q.length;
40
- }
41
- if (!draining) {
42
- draining = true;
43
- Promise.resolve().then(drain);
44
- }
45
- }
46
- function drain() {
47
- return __awaiter(this, void 0, void 0, function* () {
48
- const start = config.instrumentation ? performance.now() : 0;
49
- if (config.instrumentation) metrics.drainCycles++;
50
- let tasksSinceYield = 0;
51
- while (q.length) {
52
- const t = q.shift();
53
- if (!t) break;
54
- try {
55
- t();
56
- } catch (e) {
57
- console.error('[EnterpriseScheduler]', e);
58
- }
59
- tasksSinceYield++;
60
- if (config.instrumentation) metrics.tasksExecuted++;
61
- if (tasksSinceYield >= config.yieldEveryTasks || config.instrumentation && performance.now() - start >= config.yieldEveryMs) {
62
- if (config.instrumentation) metrics.yields++;
63
- tasksSinceYield = 0;
64
- yield Promise.resolve();
65
- }
66
- }
67
- if (config.instrumentation) {
68
- const duration = performance.now() - start;
69
- metrics.lastDrainDurationMs = duration;
70
- metrics.totalDrainDurationMs += duration;
71
- }
72
- draining = false;
73
- });
74
- }
75
-
76
- export { configureScheduler, getSchedulerMetrics, postTask };
@@ -1,13 +0,0 @@
1
- import { __awaiter } from 'tslib';
2
-
3
- function createMockPool() {
4
- return {
5
- run(fn, ...args) {
6
- return __awaiter(this, void 0, void 0, function* () {
7
- return fn(...args);
8
- });
9
- }
10
- };
11
- }
12
-
13
- export { createMockPool };
@@ -1,18 +0,0 @@
1
- export type Task = () => void;
2
- interface SchedulerConfig {
3
- yieldEveryTasks?: number;
4
- yieldEveryMs?: number;
5
- instrumentation?: boolean;
6
- }
7
- interface SchedulerMetrics {
8
- drainCycles: number;
9
- tasksExecuted: number;
10
- maxQueueLength: number;
11
- yields: number;
12
- lastDrainDurationMs: number;
13
- totalDrainDurationMs: number;
14
- }
15
- export declare function configureScheduler(newConfig: SchedulerConfig): void;
16
- export declare function getSchedulerMetrics(reset?: boolean): SchedulerMetrics;
17
- export declare function postTask(t: Task): void;
18
- export {};
@@ -1,4 +0,0 @@
1
- export interface WorkerPool {
2
- run<T, A extends unknown[]>(fn: (...args: A) => T, ...args: A): Promise<T>;
3
- }
4
- export declare function createMockPool(): WorkerPool;