Skip to content

Commit a301f1e

Browse files
authored
refactor: add extensibility API helper (#1207)
1 parent 4d69dc3 commit a301f1e

File tree

3 files changed

+638
-0
lines changed

3 files changed

+638
-0
lines changed
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import type {
2+
DevToolsColor,
3+
DevToolsProperties,
4+
EntryMeta,
5+
MarkOptionsWithDevtools,
6+
MarkerPayload,
7+
MeasureOptionsWithDevtools,
8+
TrackEntryPayload,
9+
WithDevToolsPayload,
10+
} from './user-timing-extensibility-api.type.js';
11+
12+
const dataTypeTrackEntry = 'track-entry';
13+
const dataTypeMarker = 'marker';
14+
15+
export function mergePropertiesWithOverwrite(
16+
baseProperties: DevToolsProperties | undefined,
17+
overrideProperties?: DevToolsProperties | undefined,
18+
) {
19+
return [
20+
...new Map([...(baseProperties ?? []), ...(overrideProperties ?? [])]),
21+
] satisfies DevToolsProperties;
22+
}
23+
24+
export function markerPayload(options?: Omit<MarkerPayload, 'dataType'>) {
25+
return {
26+
dataType: dataTypeMarker,
27+
...options,
28+
} satisfies MarkerPayload;
29+
}
30+
31+
export function trackEntryPayload(
32+
options: Omit<TrackEntryPayload, 'dataType'>,
33+
) {
34+
const { track, ...rest } = options;
35+
return {
36+
dataType: dataTypeTrackEntry,
37+
track,
38+
...rest,
39+
} satisfies TrackEntryPayload;
40+
}
41+
42+
export function markerErrorPayload<T extends DevToolsColor>(
43+
options?: Omit<MarkerPayload, 'dataType' | 'color'>,
44+
) {
45+
return {
46+
dataType: dataTypeMarker,
47+
color: 'error' as T,
48+
...options,
49+
} satisfies MarkerPayload;
50+
}
51+
52+
export function trackEntryErrorPayload<
53+
T extends string,
54+
C extends DevToolsColor,
55+
>(
56+
options: Omit<TrackEntryPayload, 'color' | 'dataType'> & {
57+
track: T;
58+
color?: C;
59+
},
60+
) {
61+
const { track, color = 'error' as const, ...restOptions } = options;
62+
return {
63+
dataType: dataTypeTrackEntry,
64+
color,
65+
track,
66+
...restOptions,
67+
} satisfies TrackEntryPayload;
68+
}
69+
70+
export function errorToDevToolsProperties(e: unknown) {
71+
const name = e instanceof Error ? e.name : 'UnknownError';
72+
const message = e instanceof Error ? e.message : String(e);
73+
return [
74+
['Error Type' as const, name],
75+
['Error Message' as const, message],
76+
] satisfies DevToolsProperties;
77+
}
78+
79+
export function errorToEntryMeta(
80+
e: unknown,
81+
options?: {
82+
tooltipText?: string;
83+
properties?: DevToolsProperties;
84+
},
85+
) {
86+
const { properties, tooltipText } = options ?? {};
87+
const props = mergePropertiesWithOverwrite(
88+
errorToDevToolsProperties(e),
89+
properties,
90+
);
91+
return {
92+
properties: props,
93+
...(tooltipText ? { tooltipText } : {}),
94+
} satisfies EntryMeta;
95+
}
96+
97+
export function errorToTrackEntryPayload<T extends string>(
98+
error: unknown,
99+
detail: Omit<TrackEntryPayload, 'color' | 'dataType'> & {
100+
track: T;
101+
},
102+
) {
103+
const { properties, tooltipText, ...trackPayload } = detail;
104+
return {
105+
dataType: dataTypeTrackEntry,
106+
color: 'error' as const,
107+
...trackPayload,
108+
...errorToEntryMeta(error, {
109+
properties,
110+
tooltipText,
111+
}),
112+
} satisfies TrackEntryPayload;
113+
}
114+
115+
export function errorToMarkerPayload(
116+
error: unknown,
117+
detail?: Omit<MarkerPayload, 'color' | 'dataType'>,
118+
) {
119+
const { properties, tooltipText } = detail ?? {};
120+
return {
121+
dataType: dataTypeMarker,
122+
color: 'error' as const,
123+
...errorToEntryMeta(error, {
124+
properties,
125+
tooltipText,
126+
}),
127+
} satisfies MarkerPayload;
128+
}
129+
130+
/**
131+
* asOptions wraps a DevTools payload into the `detail` property of User Timing entry options.
132+
*
133+
* @example
134+
* profiler.mark('mark', asOptions({
135+
* dataType: 'marker',
136+
* color: 'error',
137+
* tooltipText: 'This is a marker',
138+
* properties: [
139+
* ['str', 'This is a detail property']
140+
* ],
141+
* }));
142+
*/
143+
export function asOptions<T extends MarkerPayload>(
144+
devtools?: T | null,
145+
): MarkOptionsWithDevtools<T>;
146+
export function asOptions<T extends TrackEntryPayload>(
147+
devtools?: T | null,
148+
): MeasureOptionsWithDevtools<T>;
149+
export function asOptions<T extends MarkerPayload | TrackEntryPayload>(
150+
devtools?: T | null,
151+
): {
152+
detail?: WithDevToolsPayload<T>;
153+
} {
154+
return devtools == null ? { detail: {} } : { detail: { devtools } };
155+
}

0 commit comments

Comments
 (0)