@signaltree/guardrails 8.0.2 → 9.0.1

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.
@@ -12,8 +12,7 @@ function resolveGuardrailsConfig(guardrails) {
12
12
  }
13
13
  return {
14
14
  budgets: {
15
- maxUpdateTime: 16,
16
- maxRecomputations: 100
15
+ maxUpdateTime: 16
17
16
  },
18
17
  hotPaths: {
19
18
  enabled: true,
@@ -70,8 +69,7 @@ function createPerformanceTree(signalTree, initial, name) {
70
69
  return createFeatureTree(signalTree, initial, {
71
70
  guardrails: {
72
71
  budgets: {
73
- maxUpdateTime: 8,
74
- maxRecomputations: 200
72
+ maxUpdateTime: 8
75
73
  },
76
74
  hotPaths: {
77
75
  threshold: 50
@@ -107,8 +105,7 @@ function createTestTree(signalTree, initial, overrides) {
107
105
  guardrails: {
108
106
  mode: 'throw',
109
107
  budgets: {
110
- maxUpdateTime: 5,
111
- maxRecomputations: 50
108
+ maxUpdateTime: 5
112
109
  },
113
110
  customRules: [rules.noFunctionsInState(), rules.noDeepNesting(4)],
114
111
  ...overrides
@@ -34,13 +34,12 @@ function tryStructuredClone(value) {
34
34
  }
35
35
  }
36
36
  function isDevEnvironment() {
37
- if (__DEV__ !== undefined) return __DEV__;
37
+ if (typeof __DEV__ !== 'undefined') return __DEV__;
38
38
  if (process?.env?.['NODE_ENV'] === 'production') return false;
39
39
  if (ngDevMode != null) return Boolean(ngDevMode);
40
40
  return true;
41
41
  }
42
42
  const MAX_TIMING_SAMPLES = 1000;
43
- const RECOMPUTATION_WINDOW_MS = 1000;
44
43
  const POLLING_INTERVAL_MS = 50;
45
44
  function guardrails(config = {}) {
46
45
  return function (tree) {
@@ -61,29 +60,10 @@ function guardrails(config = {}) {
61
60
  hotPathData: new Map(),
62
61
  issueMap: new Map(),
63
62
  signalUsage: new Map(),
64
- pathRecomputations: new Map(),
65
63
  memoryHistory: [],
66
- recomputationLog: [],
67
64
  previousState: tryStructuredClone(tree()),
68
65
  disposed: false
69
66
  };
70
- tree['__devHooks'] = {
71
- onRecompute: (path, count) => {
72
- if (!context.disposed && !context.suppressed) {
73
- recordRecomputations(path, context, count, Date.now());
74
- const maxRecomputations = config.budgets?.maxRecomputations;
75
- if (maxRecomputations && context.stats.recomputationCount > maxRecomputations) {
76
- addIssue(context, {
77
- type: 'budget',
78
- severity: 'error',
79
- message: `Recomputation budget exceeded: ${context.stats.recomputationCount} > ${maxRecomputations}`,
80
- path,
81
- count: 1
82
- });
83
- }
84
- }
85
- }
86
- };
87
67
  const stopChangeDetection = startChangeDetection(context);
88
68
  const stopMonitoring = startMonitoring(context);
89
69
  const teardown = () => {
@@ -349,20 +329,6 @@ function updateSignalStats(context, timestamp) {
349
329
  const growth = baseline === 0 ? 0 : (signalCount - baseline) / Math.max(1, baseline);
350
330
  context.stats.memoryGrowthRate = growth;
351
331
  }
352
- function recordRecomputations(path, context, count, timestamp) {
353
- const currentPathCount = context.pathRecomputations.get(path) ?? 0;
354
- context.pathRecomputations.set(path, currentPathCount + count);
355
- if (count > 0) {
356
- context.stats.recomputationCount += count;
357
- for (let i = 0; i < count; i++) {
358
- context.recomputationLog.push(timestamp);
359
- }
360
- }
361
- if (context.recomputationLog.length) {
362
- context.recomputationLog = context.recomputationLog.filter(value => timestamp - value <= RECOMPUTATION_WINDOW_MS);
363
- }
364
- context.stats.recomputationsPerSecond = context.recomputationLog.length;
365
- }
366
332
  function updateHotPath(context, hotPath) {
367
333
  const existing = context.hotPaths.find(h => h.path === hotPath.path);
368
334
  if (existing) {
@@ -514,12 +480,9 @@ function getSeverityPrefix(severity) {
514
480
  function generateReport(context) {
515
481
  const memoryCurrent = context.stats.signalCount;
516
482
  const memoryLimit = context.config.budgets?.maxMemory ?? 50;
517
- const recomputationCurrent = context.stats.recomputationsPerSecond;
518
- const recomputationLimit = context.config.budgets?.maxRecomputations ?? 100;
519
483
  const budgets = {
520
484
  updateTime: createBudgetItem(context.stats.avgUpdateTime, context.config.budgets?.maxUpdateTime || 16),
521
- memory: createBudgetItem(memoryCurrent, memoryLimit),
522
- recomputations: createBudgetItem(recomputationCurrent, recomputationLimit)
485
+ memory: createBudgetItem(memoryCurrent, memoryLimit)
523
486
  };
524
487
  return {
525
488
  timestamp: Date.now(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signaltree/guardrails",
3
- "version": "8.0.2",
3
+ "version": "9.0.1",
4
4
  "description": "Development guardrails for SignalTree reactive JSON. Performance monitoring and anti-pattern detection.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -57,8 +57,8 @@
57
57
  "type-check": "tsc --project tsconfig.lib.json --noEmit"
58
58
  },
59
59
  "peerDependencies": {
60
- "@signaltree/core": "^8.0.0",
61
- "@signaltree/shared": "^7.1.0",
60
+ "@signaltree/core": "^9.0.1",
61
+ "@signaltree/shared": "^9.0.1",
62
62
  "tslib": "^2.0.0"
63
63
  },
64
64
  "peerDependenciesMeta": {},
@@ -8,7 +8,6 @@ export interface GuardrailsConfig<T = Record<string, unknown>> {
8
8
  budgets?: {
9
9
  maxUpdateTime?: number;
10
10
  maxMemory?: number;
11
- maxRecomputations?: number;
12
11
  maxTreeDepth?: number;
13
12
  alertThreshold?: number;
14
13
  };
@@ -116,7 +115,6 @@ export interface HotPath {
116
115
  export interface BudgetStatus {
117
116
  updateTime: BudgetItem;
118
117
  memory: BudgetItem;
119
- recomputations: BudgetItem;
120
118
  }
121
119
  export interface BudgetItem {
122
120
  current: number;