Skip to content
Closed
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 20 additions & 10 deletions packages/utils/src/lib/profiler/trace-file-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@
...opt,
name: opt?.name ?? entry.name,
ts: defaultClock.fromEntry(entry),
args: entry.detail ? { detail: entry.detail } : undefined,

Check failure on line 241 in packages/utils/src/lib/profiler/trace-file-utils.ts

View workflow job for this annotation

GitHub Actions / Standalone mode

<✓> TypeScript | Semantic errors

TS2322: Type '{ detail: {}; } | undefined' is not assignable to type 'InstantEventArgs | undefined'. Type '{ detail: {}; }' is not assignable to type 'InstantEventArgs'. Type '{ detail: {}; }' is not assignable to type '{ detail?: UserTimingDetail | undefined; }'. Types of property 'detail' are incompatible. Property 'devtools' is missing in type '{}' but required in type 'UserTimingDetail'.

Check failure on line 241 in packages/utils/src/lib/profiler/trace-file-utils.ts

View workflow job for this annotation

GitHub Actions / Standalone mode

<✓> TypeScript | Semantic errors

TS2322: Type '{ detail: {}; } | undefined' is not assignable to type 'InstantEventArgs | undefined'. Type '{ detail: {}; }' is not assignable to type 'InstantEventArgs'. Type '{ detail: {}; }' is not assignable to type '{ detail?: UserTimingDetail | undefined; }'. Types of property 'detail' are incompatible. Property 'devtools' is missing in type '{}' but required in type 'UserTimingDetail'.
});

/**
Expand All @@ -256,7 +256,7 @@
name: opt?.name ?? entry.name,
tsB: defaultClock.fromEntry(entry),
tsE: defaultClock.fromEntry(entry, true),
args: entry.detail ? { data: { detail: entry.detail } } : undefined,

Check failure on line 259 in packages/utils/src/lib/profiler/trace-file-utils.ts

View workflow job for this annotation

GitHub Actions / Standalone mode

<✓> TypeScript | Semantic errors

TS2322: Type '{ data: { detail: {}; }; } | undefined' is not assignable to type 'SpanEventArgs | undefined'. Type '{ data: { detail: {}; }; }' is not assignable to type 'SpanEventArgs'. Type '{ data: { detail: {}; }; }' is not assignable to type '{ data?: { detail?: UserTimingDetail | undefined; } | undefined; }'. The types of 'data.detail' are incompatible between these types. Property 'devtools' is missing in type '{}' but required in type 'UserTimingDetail'.

Check failure on line 259 in packages/utils/src/lib/profiler/trace-file-utils.ts

View workflow job for this annotation

GitHub Actions / Standalone mode

<✓> TypeScript | Semantic errors

TS2322: Type '{ data: { detail: {}; }; } | undefined' is not assignable to type 'SpanEventArgs | undefined'. Type '{ data: { detail: {}; }; }' is not assignable to type 'SpanEventArgs'. Type '{ data: { detail: {}; }; }' is not assignable to type '{ data?: { detail?: UserTimingDetail | undefined; } | undefined; }'. The types of 'data.detail' are incompatible between these types. Property 'devtools' is missing in type '{}' but required in type 'UserTimingDetail'.
});

/**
Expand Down Expand Up @@ -335,32 +335,42 @@
return target;
}

function encodeDetailToString<T extends { detail?: unknown }>(
target: T,
): T & { detail?: string } {
return processDetail(target, (detail: string | object) =>
typeof detail === 'object' ? JSON.stringify(detail) : detail,
) as T & { detail?: string };
}

/**
* Decodes a JSON string detail property back to its original object form.
* @param target - Object containing a detail property as a JSON string
* @returns UserTimingDetail with the detail property parsed from JSON
*/
export function decodeDetail(target: { detail: string }): UserTimingDetail {
export function decodeDetail<T extends { detail?: string | object }>(
target: T,
): T {
return processDetail(target, detail =>
typeof detail === 'string'
? (JSON.parse(detail) as string | object)
: detail,
) as UserTimingDetail;
);
}

/**
* Encodes object detail properties to JSON strings for storage/transmission.
* @param target - UserTimingDetail object with detail property to encode
* @returns UserTimingDetail with object details converted to JSON strings
*/
export function encodeDetail(target: UserTimingDetail): UserTimingDetail {
export function encodeDetail<T extends { detail?: string | object }>(
target: T,
): T {
return processDetail(
target as UserTimingDetail & { detail?: unknown },
target as T & { detail?: unknown },
(detail: string | object) =>
typeof detail === 'object'
? JSON.stringify(detail as UserTimingDetail)
: detail,
) as UserTimingDetail;
typeof detail === 'object' ? JSON.stringify(detail) : detail,
);
}

/**
Expand All @@ -380,7 +390,7 @@
const processedArgs = decodeDetail(args as { detail: string });
if ('data' in args && args.data && typeof args.data === 'object') {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
return {

Check failure on line 393 in packages/utils/src/lib/profiler/trace-file-utils.ts

View workflow job for this annotation

GitHub Actions / Standalone mode

<✓> TypeScript | Semantic errors

TS2352: Conversion of type '{ args: { data: { detail: string; }; detail: string; }; name: string; ts: number; pid: number; tid: number; cat: string; ph: "b" | "i" | "e" | "X"; }' to type 'UserTimingTraceEvent' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. Type '{ args: { data: { detail: string; }; detail: string; }; name: string; ts: number; pid: number; tid: number; cat: string; ph: "b" | "i" | "e" | "X"; }' is not comparable to type 'EndEvent'. Property 'id2' is missing in type '{ args: { data: { detail: string; }; detail: string; }; name: string; ts: number; pid: number; tid: number; cat: string; ph: "b" | "i" | "e" | "X"; }' but required in type '{ id2: { local: string; }; args: SpanEventArgs; }'.

Check failure on line 393 in packages/utils/src/lib/profiler/trace-file-utils.ts

View workflow job for this annotation

GitHub Actions / Standalone mode

<✓> TypeScript | Semantic errors

TS2352: Conversion of type '{ args: { data: { detail: string; }; detail: string; }; name: string; ts: number; cat: string; pid: number; tid: number; ph: "b" | "i" | "X" | "e"; }' to type 'UserTimingTraceEvent' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. Type '{ args: { data: { detail: string; }; detail: string; }; name: string; ts: number; cat: string; pid: number; tid: number; ph: "b" | "i" | "X" | "e"; }' is not comparable to type 'EndEvent'. Property 'id2' is missing in type '{ args: { data: { detail: string; }; detail: string; }; name: string; ts: number; cat: string; pid: number; tid: number; ph: "b" | "i" | "X" | "e"; }' but required in type '{ id2: { local: string; }; args: SpanEventArgs; }'.
...rest,
args: {
...processedArgs,
Expand All @@ -389,7 +399,7 @@
} as UserTimingTraceEvent;
}
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
return { ...rest, args: processedArgs } as UserTimingTraceEvent;

Check failure on line 402 in packages/utils/src/lib/profiler/trace-file-utils.ts

View workflow job for this annotation

GitHub Actions / Standalone mode

<✓> TypeScript | Semantic errors

TS2352: Conversion of type '{ args: { detail: string; }; name: string; ts: number; pid: number; tid: number; cat: string; ph: "b" | "i" | "e" | "X"; }' to type 'UserTimingTraceEvent' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. Type '{ args: { detail: string; }; name: string; ts: number; pid: number; tid: number; cat: string; ph: "b" | "i" | "e" | "X"; }' is not comparable to type 'EndEvent'. Property 'id2' is missing in type '{ args: { detail: string; }; name: string; ts: number; pid: number; tid: number; cat: string; ph: "b" | "i" | "e" | "X"; }' but required in type '{ id2: { local: string; }; args: SpanEventArgs; }'.

Check failure on line 402 in packages/utils/src/lib/profiler/trace-file-utils.ts

View workflow job for this annotation

GitHub Actions / Standalone mode

<✓> TypeScript | Semantic errors

TS2352: Conversion of type '{ args: { detail: string; }; name: string; ts: number; cat: string; pid: number; tid: number; ph: "b" | "i" | "X" | "e"; }' to type 'UserTimingTraceEvent' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. Type '{ args: { detail: string; }; name: string; ts: number; cat: string; pid: number; tid: number; ph: "b" | "i" | "X" | "e"; }' is not comparable to type 'EndEvent'. Property 'id2' is missing in type '{ args: { detail: string; }; name: string; ts: number; cat: string; pid: number; tid: number; ph: "b" | "i" | "X" | "e"; }' but required in type '{ id2: { local: string; }; args: SpanEventArgs; }'.
}

/**
Expand All @@ -406,13 +416,13 @@
return rest as TraceEventRaw;
}

const processedArgs = encodeDetail(args as UserTimingDetail);
const processedArgs = encodeDetailToString(args as { detail?: unknown });
if ('data' in args && args.data && typeof args.data === 'object') {
const result: TraceEventRaw = {
...rest,
args: {
...processedArgs,
data: encodeDetail(args.data as UserTimingDetail),
data: encodeDetailToString(args.data as { detail?: unknown }),
},
};
return result;
Expand Down
62 changes: 45 additions & 17 deletions packages/utils/src/lib/profiler/trace-file-utils.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -623,16 +623,18 @@ describe('getTraceMetadata', () => {

describe('decodeDetail', () => {
it('should decode string detail back to object', () => {
const input = { detail: '{"key": "value"}' };
const input = {
detail: '{"devtools":{"dataType":"marker","color":"primary"}}',
};
const result = decodeDetail(input);

expect(result).toStrictEqual({
detail: { key: 'value' },
detail: { devtools: { dataType: 'marker', color: 'primary' } },
});
});

it('should return object detail unchanged', () => {
const input = { detail: { key: 'value' } };
const input = { detail: { devtools: { dataType: 'marker' as const } } };
const result = decodeDetail(input);

expect(result).toStrictEqual(input);
Expand All @@ -655,11 +657,11 @@ describe('decodeDetail', () => {

describe('encodeDetail', () => {
it('should encode object detail to JSON string', () => {
const input = { detail: { key: 'value' } };
const input = { detail: { devtools: { dataType: 'marker' as const } } };
const result = encodeDetail(input);

expect(result).toStrictEqual({
detail: '{"key":"value"}',
detail: '{"devtools":{"dataType":"marker"}}',
});
});

Expand Down Expand Up @@ -695,8 +697,11 @@ describe('decodeTraceEvent', () => {
tid: 456,
ts: 1000,
args: {
detail: '{"custom": "data"}',
data: { detail: '{"nested": "value"}' },
detail: '{"devtools":{"dataType":"marker","color":"primary"}}',
data: {
detail:
'{"devtools":{"dataType":"track-entry","track":"test-track"}}',
},
},
};

Expand All @@ -710,8 +715,14 @@ describe('decodeTraceEvent', () => {
tid: 456,
ts: 1000,
args: {
detail: { custom: 'data' },
data: { detail: { nested: 'value' } },
detail: {
devtools: { dataType: 'marker' as const, color: 'primary' as const },
},
data: {
detail: {
devtools: { dataType: 'track-entry' as const, track: 'test-track' },
},
},
},
});
});
Expand All @@ -724,6 +735,7 @@ describe('decodeTraceEvent', () => {
pid: 123,
tid: 456,
ts: 1000,
args: {},
};

const result = decodeTraceEvent(rawEvent);
Expand All @@ -735,6 +747,7 @@ describe('decodeTraceEvent', () => {
pid: 123,
tid: 456,
ts: 1000,
args: {},
});
});

Expand All @@ -747,7 +760,7 @@ describe('decodeTraceEvent', () => {
tid: 456,
ts: 1000,
args: {
detail: '{"custom": "data"}',
detail: '{"devtools":{"dataType":"marker","color":"primary"}}',
},
};

Expand All @@ -761,7 +774,9 @@ describe('decodeTraceEvent', () => {
tid: 456,
ts: 1000,
args: {
detail: { custom: 'data' },
detail: {
devtools: { dataType: 'marker' as const, color: 'primary' as const },
},
},
});
});
Expand All @@ -777,8 +792,14 @@ describe('encodeTraceEvent', () => {
tid: 456,
ts: 1000,
args: {
detail: { custom: 'data' },
data: { detail: { nested: 'value' } },
detail: {
devtools: { dataType: 'marker' as const, color: 'primary' as const },
},
data: {
detail: {
devtools: { dataType: 'track-entry' as const, track: 'test-track' },
},
},
},
};

Expand All @@ -792,8 +813,11 @@ describe('encodeTraceEvent', () => {
tid: 456,
ts: 1000,
args: {
detail: '{"custom":"data"}',
data: { detail: '{"nested":"value"}' },
detail: '{"devtools":{"dataType":"marker","color":"primary"}}',
data: {
detail:
'{"devtools":{"dataType":"track-entry","track":"test-track"}}',
},
},
});
});
Expand All @@ -806,6 +830,7 @@ describe('encodeTraceEvent', () => {
pid: 123,
tid: 456,
ts: 1000,
args: {},
};

const result = encodeTraceEvent(event);
Expand All @@ -817,6 +842,7 @@ describe('encodeTraceEvent', () => {
pid: 123,
tid: 456,
ts: 1000,
args: {},
});
});

Expand All @@ -829,7 +855,9 @@ describe('encodeTraceEvent', () => {
tid: 456,
ts: 1000,
args: {
detail: { custom: 'data' },
detail: {
devtools: { dataType: 'marker' as const, color: 'primary' as const },
},
},
};

Expand All @@ -843,7 +871,7 @@ describe('encodeTraceEvent', () => {
tid: 456,
ts: 1000,
args: {
detail: '{"custom":"data"}',
detail: '{"devtools":{"dataType":"marker","color":"primary"}}',
},
});
});
Expand Down
3 changes: 3 additions & 0 deletions packages/utils/src/lib/reports/load-report.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ describe('loadReport', () => {
outputDir: MEMFS_VOLUME,
filename: 'report',
format: 'json',
skipReports: false,
}),
).resolves.toEqual(reportMock());
});
Expand All @@ -38,6 +39,7 @@ describe('loadReport', () => {
outputDir: MEMFS_VOLUME,
format: 'md',
filename: 'report',
skipReports: false,
}),
).resolves.toBe('test-42');
});
Expand All @@ -58,6 +60,7 @@ describe('loadReport', () => {
outputDir: MEMFS_VOLUME,
filename: 'report',
format: 'json',
skipReports: false,
}),
).rejects.toThrow('slug has to follow the pattern');
});
Expand Down
8 changes: 7 additions & 1 deletion packages/utils/src/lib/user-timing-extensibility-api.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,15 @@ export type ActionTrackEntryPayload = TrackEntryPayload & ActionColorPayload;
* Utility type that adds an optional devtools payload property.
*/
export type WithDevToolsPayload<T extends TrackEntryPayload | MarkerPayload> = {
devtools?: T;
devtools: T;
Comment thread
BioPhoton marked this conversation as resolved.
Outdated
};

/**
* Combined detail payload type for performance entries with DevTools support.
*/
export type DetailPayloadWithDevtools = WithDevToolsPayload<
TrackEntryPayload | MarkerPayload
>;
/**
* Extended MarkOptions that supports DevTools payload in detail.
* @example
Expand Down
Loading
Loading