Skip to content

Commit 42e5f04

Browse files
authored
Merge 1e385c8 into 91f50cf
2 parents 91f50cf + 1e385c8 commit 42e5f04

3 files changed

Lines changed: 288 additions & 0 deletions

File tree

packages/utils/src/lib/user-timing-extensibility-api.type.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,12 @@ export type WithDevToolsPayload<T extends TrackEntryPayload | MarkerPayload> = {
135135
devtools?: T;
136136
};
137137

138+
/**
139+
* Combined detail payload type for performance entries with DevTools support.
140+
*/
141+
export type DetailPayloadWithDevtools = WithDevToolsPayload<
142+
TrackEntryPayload | MarkerPayload
143+
>;
138144
/**
139145
* Extended MarkOptions that supports DevTools payload in detail.
140146
* @example

packages/utils/src/perf-hooks.d.ts

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
import type { DetailPayloadWithDevtools } from './lib/user-timing-extensibility-api.type';
2+
3+
export {};
4+
5+
/**
6+
* Type definitions extending Node.js perf_hooks module to enable Chrome DevTools UserTiming Extensibility API.
7+
*
8+
* The `detail` property allows custom payloads to be attached to performance marks and measures,
9+
* which are then accessible in Chrome DevTools and visualized in as custom tracks right under UserTiming.
10+
* This enables richer performance instrumentation with structured data that DevTools can display.
11+
*/
12+
declare module 'node:perf_hooks' {
13+
/**
14+
* Extends the base PerformanceEntry interface with optional custom detail payload.
15+
*
16+
* The detail property enables Chrome DevTools UserTiming Extensibility API by allowing
17+
* structured data to be attached to performance entries for enhanced debugging visualization.
18+
* This augmentation only ensures the payload is preserved and visible to DevTools.
19+
*
20+
* @example
21+
* ```typescript
22+
* // Preserved entries with entry.detail
23+
* const entry = performance.getEntriesByType('mark').at(0);
24+
* ```
25+
*/
26+
interface PerformanceEntry {
27+
/** Custom payload accessible in Chrome DevTools for enhanced performance analysis. */
28+
readonly detail?: DetailPayloadWithDevtools;
29+
}
30+
31+
/**
32+
* Represents a performance mark entry with custom detail support for DevTools extensibility.
33+
*
34+
* Mark entries with detail payloads enable Chrome DevTools to display additional context
35+
* and structured data alongside the mark in the Performance tab. Markers create vertical
36+
* lines that span all tracks and appear at the top of the timeline.
37+
*
38+
* @example
39+
* ```typescript
40+
* // Preserved mark entries with entry.detail
41+
* const entry = performance.getEntriesByType('mark').at(0);
42+
* ```
43+
*/
44+
interface MarkEntry extends PerformanceMark {
45+
readonly entryType: 'mark';
46+
/** Custom payload displayed in Chrome DevTools for enhanced mark visualization. */
47+
readonly detail?: DetailPayloadWithDevtools;
48+
}
49+
50+
/**
51+
* Represents a performance measure entry with custom detail support for DevTools extensibility.
52+
*
53+
* Measure entries with detail payloads allow Chrome DevTools to show additional metadata
54+
* and context information alongside the measured performance duration. Track entries appear
55+
* in custom tracks below the main UserTiming track.
56+
*
57+
* @example
58+
* ```typescript
59+
* // Preserved measure entries with entry.detail
60+
* const entry = performance.getEntriesByType('measure').at(0);
61+
* ```
62+
*/
63+
interface MeasureEntry extends PerformanceMeasure {
64+
readonly entryType: 'measure';
65+
/** Custom payload displayed in Chrome DevTools for enhanced measure visualization. */
66+
readonly detail?: DetailPayloadWithDevtools;
67+
}
68+
69+
/**
70+
* Extends Node.js PerformanceMark to include the custom detail payload support.
71+
*
72+
* This interface ensures that performance marks created through the extended API
73+
* have access to the `detail` property for Chrome DevTools UserTiming Extensibility.
74+
*/
75+
interface PerformanceMark extends PerformanceEntry {}
76+
77+
/**
78+
* Extends Node.js PerformanceMeasure to include the custom detail payload support.
79+
*
80+
* This interface ensures that performance measures created through the extended API
81+
* have access to the `detail` property for Chrome DevTools UserTiming Extensibility.
82+
*/
83+
interface PerformanceMeasure extends PerformanceEntry {}
84+
85+
/**
86+
* Options for creating performance marks with custom detail payload for DevTools integration.
87+
*
88+
* The detail property enables attaching structured data that Chrome DevTools can display
89+
* alongside the mark, providing richer debugging context.
90+
*
91+
* @example
92+
* ```typescript
93+
* // Options include detail property
94+
* const options: PerformanceMarkOptions = { detail: { devtools: {} } };
95+
* ```
96+
*/
97+
export interface PerformanceMarkOptions {
98+
/** Custom payload that will be accessible in Chrome DevTools UserTiming visualization. */
99+
detail?: DetailPayloadWithDevtools;
100+
startTime?: DOMHighResTimeStamp;
101+
}
102+
103+
/**
104+
* Options for creating performance measures with custom detail payload for DevTools integration.
105+
*
106+
* The detail property allows attaching metadata that Chrome DevTools will display
107+
* with the measure, enabling better performance analysis and debugging.
108+
*
109+
* @example
110+
* ```typescript
111+
* // Options include detail property
112+
* const options: PerformanceMeasureOptions = { detail: { devtools: {} } };
113+
* ```
114+
*/
115+
export interface PerformanceMeasureOptions {
116+
/** Custom payload that will be accessible in Chrome DevTools UserTiming visualization. */
117+
detail?: DetailPayloadWithDevtools;
118+
start?: string | number;
119+
end?: string | number;
120+
duration?: number;
121+
}
122+
123+
/**
124+
* Extended performance observer entry list with typed entry retrieval.
125+
*/
126+
export interface PerformanceObserverEntryList {
127+
getEntriesByType: (type: EntryType) => PerformanceEntry[];
128+
}
129+
130+
/**
131+
* Extended performance object with Chrome DevTools UserTiming Extensibility API support.
132+
*
133+
* Enables creating performance marks and measures with custom detail payloads that are
134+
* displayed in Chrome DevTools, providing enhanced debugging and performance analysis capabilities.
135+
*/
136+
const performance: {
137+
/**
138+
* Creates a performance mark with optional custom detail payload for DevTools visualization.
139+
*
140+
* The detail payload will be accessible in Chrome DevTools Performance tab,
141+
* enabling richer debugging context for the mark.
142+
*
143+
* @example
144+
* ```typescript
145+
* // Accepts detail options
146+
* performance.mark('checkpoint', { detail: { devtools: {} } });
147+
* ```
148+
*
149+
* @param name - The name of the mark displayed in DevTools
150+
* @param options - Optional configuration including detail payload for DevTools
151+
* @returns The created performance mark with DevTools-compatible detail
152+
*/
153+
mark: (name: string, options?: PerformanceMarkOptions) => PerformanceMark;
154+
155+
/**
156+
* Creates a performance measure with optional custom detail payload for DevTools visualization.
157+
*
158+
* The detail payload enables Chrome DevTools to display additional metadata
159+
* alongside the measured performance duration for enhanced analysis.
160+
*
161+
* @example
162+
* ```typescript
163+
* // Accepts detail options
164+
* performance.measure('task', { detail: { devtools: {} } });
165+
* ```
166+
*
167+
* @param name - The name of the measure displayed in DevTools
168+
* @param startOrOptions - Start mark name/number or full options object with DevTools detail
169+
* @param end - End mark name/number (when startOrOptions is not options object)
170+
* @returns The created performance measure with DevTools-compatible detail
171+
*/
172+
measure: (
173+
name: string,
174+
startOrOptions?: string | number | PerformanceMeasureOptions,
175+
end?: string | number,
176+
) => PerformanceMeasure;
177+
178+
/**
179+
* Retrieves performance entries of the specified type, including DevTools detail payloads.
180+
*
181+
* @example
182+
* ```typescript
183+
* // Returns entries with preserved entry.detail
184+
* const entry = performance.getEntriesByType('mark').at(0);
185+
* ```
186+
*
187+
* @param type - The entry type to filter by ('mark' or 'measure')
188+
* @returns Array of performance entries with DevTools detail payloads
189+
*/
190+
getEntriesByType: (type: EntryType) => PerformanceEntry[];
191+
};
192+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { type PerformanceMarkOptions, performance } from 'node:perf_hooks';
2+
import { describe, expect, expectTypeOf, it } from 'vitest';
3+
4+
describe('perf-hooks definitions', () => {
5+
it('PerformanceMarkOptions should be type safe', () => {
6+
expect(() =>
7+
expectTypeOf<{
8+
startTime: number;
9+
detail: {
10+
devtools: {
11+
dataType: 'marker';
12+
color: 'error';
13+
};
14+
};
15+
}>().toMatchTypeOf<PerformanceMarkOptions>(),
16+
).not.toThrow();
17+
18+
expect(() =>
19+
expectTypeOf<{
20+
startTime: number;
21+
detail: {
22+
devtools: {
23+
dataType: 'markerr';
24+
};
25+
};
26+
}>().not.toMatchTypeOf<PerformanceMarkOptions>(),
27+
).not.toThrow();
28+
});
29+
30+
it('perf_hooks.mark should be type safe', () => {
31+
expect(() =>
32+
performance.mark('name', {
33+
detail: {
34+
devtools: {
35+
dataType: 'marker',
36+
color: 'error',
37+
},
38+
},
39+
}),
40+
).not.toThrow();
41+
42+
expect(() =>
43+
performance.mark('name', {
44+
detail: {
45+
devtools: {
46+
// @ts-expect-error - dataType should be marker | track
47+
dataType: 'markerrr',
48+
color: 'error',
49+
},
50+
},
51+
}),
52+
).not.toThrow();
53+
});
54+
55+
it('PerformanceMeasureOptions should be type safe', () => {
56+
expect(() =>
57+
expectTypeOf<{
58+
start: string;
59+
end: string;
60+
detail: {
61+
devtools: {
62+
dataType: 'track-entry';
63+
track: 'test-track';
64+
color: 'primary';
65+
};
66+
};
67+
}>().toMatchTypeOf<PerformanceMeasureOptions>(),
68+
).not.toThrow();
69+
});
70+
71+
it('perf_hooks.measure should be type safe', () => {
72+
expect(() =>
73+
performance.measure('measure-name', 'start-mark', 'end-mark'),
74+
).not.toThrow();
75+
76+
expect(() =>
77+
performance.measure('measure-name', {
78+
start: 'start-mark',
79+
end: 'end-mark',
80+
detail: {
81+
// @ts-expect-error - track is required
82+
devtools: {
83+
dataType: 'track-entry',
84+
color: 'primary',
85+
},
86+
},
87+
}),
88+
).not.toThrow();
89+
});
90+
});

0 commit comments

Comments
 (0)