@mrclrchtr/supi-insights 4.9.0 → 4.10.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrclrchtr/supi-core",
3
- "version": "4.9.0",
3
+ "version": "4.10.0",
4
4
  "description": "Shared settings, configuration, reporting, and session infrastructure",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -46,13 +46,21 @@ export interface DebugTimer {
46
46
  * names are accumulated. Event data reserves the `timing` field. When Debug is
47
47
  * disabled at start, this returns a no-op timer and does not read the clock.
48
48
  * Pass a factory to `finish()` to avoid event-data construction when disabled.
49
+ * Clock, event-construction, and registry failures are isolated from the
50
+ * measured operation and make the timer a no-op.
49
51
  */
50
52
  export function startDebugTimer(options: DebugTimerOptions = {}): DebugTimer {
51
53
  if (!isDebugRegistryEnabled()) return DISABLED_DEBUG_TIMER;
52
54
  const now = options.now ?? performance.now.bind(performance);
53
- const startedAt = now();
55
+ let startedAt: number;
56
+ try {
57
+ startedAt = now();
58
+ } catch {
59
+ return DISABLED_DEBUG_TIMER;
60
+ }
54
61
  let previousAt = startedAt;
55
62
  let finished = false;
63
+ let failed = false;
56
64
  const phases = new Map<string, number>();
57
65
 
58
66
  const markAt = (phase: string, current: number): void => {
@@ -65,30 +73,35 @@ export function startDebugTimer(options: DebugTimerOptions = {}): DebugTimer {
65
73
  return {
66
74
  enabled: true,
67
75
  mark(phase) {
68
- if (finished) return;
69
- markAt(phase, now());
76
+ if (finished || failed) return;
77
+ try {
78
+ markAt(phase, now());
79
+ } catch {
80
+ failed = true;
81
+ }
70
82
  },
71
83
  finish(input, finalPhase) {
72
- if (finished) return null;
73
- if (!isDebugRegistryEnabled()) {
74
- finished = true;
84
+ if (finished || failed) return null;
85
+ finished = true;
86
+ try {
87
+ if (!isDebugRegistryEnabled()) return null;
88
+ const completedAt = now();
89
+ if (finalPhase) markAt(finalPhase, completedAt);
90
+ const phasesMs = Object.fromEntries(
91
+ [...phases.entries()].map(([name, value]) => [name, duration(value)]),
92
+ );
93
+ const timing: DebugTiming = {
94
+ durationMs: duration(completedAt - startedAt),
95
+ phasesMs,
96
+ };
97
+ const eventInput = typeof input === "function" ? input() : input;
98
+ return recordDebugEvent({
99
+ ...eventInput,
100
+ data: { ...eventInput.data, timing },
101
+ });
102
+ } catch {
75
103
  return null;
76
104
  }
77
- const completedAt = now();
78
- if (finalPhase) markAt(finalPhase, completedAt);
79
- finished = true;
80
- const phasesMs = Object.fromEntries(
81
- [...phases.entries()].map(([name, value]) => [name, duration(value)]),
82
- );
83
- const timing: DebugTiming = {
84
- durationMs: duration(completedAt - startedAt),
85
- phasesMs,
86
- };
87
- const eventInput = typeof input === "function" ? input() : input;
88
- return recordDebugEvent({
89
- ...eventInput,
90
- data: { ...eventInput.data, timing },
91
- });
92
105
  },
93
106
  };
94
107
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrclrchtr/supi-insights",
3
- "version": "4.9.0",
3
+ "version": "4.10.0",
4
4
  "description": "Historical Pi-session reports and shareable HTML",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -34,7 +34,7 @@
34
34
  "README.md"
35
35
  ],
36
36
  "dependencies": {
37
- "@mrclrchtr/supi-core": "4.9.0"
37
+ "@mrclrchtr/supi-core": "4.10.0"
38
38
  },
39
39
  "bundledDependencies": [
40
40
  "@mrclrchtr/supi-core"