ui: switch pinned tracks save/restore feature to use Zod
Change-Id: I126a9ef58a32e65b0759cadc61620906500a8d5d
diff --git a/ui/src/plugins/dev.perfetto.RestorePinnedTracks/index.ts b/ui/src/plugins/dev.perfetto.RestorePinnedTracks/index.ts
index b20ecef..fadb4ed 100644
--- a/ui/src/plugins/dev.perfetto.RestorePinnedTracks/index.ts
+++ b/ui/src/plugins/dev.perfetto.RestorePinnedTracks/index.ts
@@ -16,10 +16,13 @@
import {Trace} from '../../public/trace';
import {PerfettoPlugin} from '../../public/plugin';
import {TrackDescriptor} from '../../public/track';
+import {z} from 'zod';
const PLUGIN_ID = 'dev.perfetto.RestorePinnedTrack';
const SAVED_TRACKS_KEY = `${PLUGIN_ID}#savedPerfettoTracks`;
+const RESTORE_COMMAND_ID = `${PLUGIN_ID}#restore`;
+
/**
* Fuzzy save and restore of pinned tracks.
*
@@ -33,6 +36,7 @@
async onTraceLoad(ctx: Trace): Promise<void> {
this.ctx = ctx;
+
ctx.commands.registerCommand({
id: `${PLUGIN_ID}#save`,
name: 'Save: Pinned tracks',
@@ -41,7 +45,7 @@
},
});
ctx.commands.registerCommand({
- id: `${PLUGIN_ID}#restore`,
+ id: RESTORE_COMMAND_ID,
name: 'Restore: Pinned tracks',
callback: () => {
this.restoreTracks();
@@ -50,14 +54,10 @@
}
private saveTracks() {
- const workspace = this.ctx.workspace;
- const pinnedTracks = workspace.pinnedTracks;
- const tracksToSave: SavedPinnedTrack[] = pinnedTracks.map((track) =>
- this.toSavedTrack(track),
- );
-
this.savedState = {
- tracks: tracksToSave,
+ tracks: this.ctx.workspace.pinnedTracks.map((track) =>
+ this.toSavedTrack(track),
+ ),
};
}
@@ -67,7 +67,6 @@
alert('No saved tracks. Use the Save command first');
return;
}
- const tracksToRestore: SavedPinnedTrack[] = savedState.tracks;
const localTracks: Array<LocalTrack> = this.ctx.workspace.flatTracks.map(
(track) => ({
@@ -75,8 +74,7 @@
track: track,
}),
);
-
- tracksToRestore.forEach((trackToRestore) => {
+ savedState.tracks.forEach((trackToRestore) => {
const foundTrack = this.findMatchingTrack(localTracks, trackToRestore);
if (foundTrack) {
foundTrack.pin();
@@ -92,8 +90,8 @@
private findMatchingTrack(
localTracks: Array<LocalTrack>,
savedTrack: SavedPinnedTrack,
- ): TrackNode | null {
- let mostSimilarTrack: LocalTrack | null = null;
+ ): TrackNode | undefined {
+ let mostSimilarTrack: LocalTrack | undefined = undefined;
let mostSimilarTrackDifferenceScore: number = 0;
for (let i = 0; i < localTracks.length; i++) {
@@ -119,7 +117,7 @@
}
}
- return mostSimilarTrack?.track || null;
+ return mostSimilarTrack?.track || undefined;
}
/**
@@ -198,7 +196,7 @@
private toSavedTrack(track: TrackNode): SavedPinnedTrack {
let trackDescriptor: TrackDescriptor | undefined = undefined;
- if (track.uri != null) {
+ if (track.uri != undefined) {
trackDescriptor = this.ctx.tracks.getTrack(track.uri);
}
@@ -211,18 +209,18 @@
};
}
- private get savedState(): SavedState | null {
+ private get savedState(): SavedState | undefined {
const savedStateString = window.localStorage.getItem(SAVED_TRACKS_KEY);
if (!savedStateString) {
- return null;
+ return undefined;
}
-
- const savedState: SavedState = JSON.parse(savedStateString);
- if (!(savedState.tracks instanceof Array)) {
- return null;
+ const savedState = SAVED_STATE_SCHEMA.safeParse(
+ JSON.parse(savedStateString),
+ );
+ if (!savedState.success) {
+ return undefined;
}
-
- return savedState;
+ return savedState.data;
}
private set savedState(state: SavedState) {
@@ -240,28 +238,30 @@
return undefined;
}
-interface SavedState {
- tracks: Array<SavedPinnedTrack>;
-}
+const SAVED_PINNED_TRACK_SCHEMA = z
+ .object({
+ // Optional: group name for the track. Usually matches with process name.
+ groupName: z.string().optional(),
+ // Track name to restore.
+ trackName: z.string(),
+ // Plugin used to create this track
+ pluginId: z.string().optional(),
+ // Kind of the track
+ kind: z.string().optional(),
+ // If it's a thread track, it should be true in case it's a main thread track
+ isMainThread: z.boolean(),
+ })
+ .readonly();
-interface SavedPinnedTrack {
- // Optional: group name for the track. Usually matches with process name.
- groupName?: string;
+type SavedPinnedTrack = z.infer<typeof SAVED_PINNED_TRACK_SCHEMA>;
- // Track name to restore.
- trackName: string;
+const SAVED_STATE_SCHEMA = z
+ .object({tracks: z.array(SAVED_PINNED_TRACK_SCHEMA).readonly()})
+ .readonly();
- // Plugin used to create this track
- pluginId?: string;
-
- // Kind of the track
- kind?: string;
-
- // If it's a thread track, it should be true in case it's a main thread track
- isMainThread: boolean;
-}
+type SavedState = z.infer<typeof SAVED_STATE_SCHEMA>;
interface LocalTrack {
- savedTrack: SavedPinnedTrack;
- track: TrackNode;
+ readonly savedTrack: SavedPinnedTrack;
+ readonly track: TrackNode;
}