81 lines
2.0 KiB
TypeScript
81 lines
2.0 KiB
TypeScript
import { z } from "zod";
|
|
|
|
export const HOUSEKEEPING_PREFERENCE_MAX_IDENTIFIER_LENGTH = 128;
|
|
export const HOUSEKEEPING_PREFERENCE_MAX_ITEMS_PER_ARRAY = 64;
|
|
export const HOUSEKEEPING_PREFERENCE_MAX_SERIALIZED_BYTES = 4096;
|
|
|
|
export interface HousekeepingPreferences {
|
|
schemaVersion: 1;
|
|
pinnedRouteIds: string[];
|
|
pinnedCommandIds: string[];
|
|
shortcutOrder: string[];
|
|
widgetOrder: string[];
|
|
enabledOptionalWidgetIds: string[];
|
|
}
|
|
|
|
const uniqueIdentifiers = z
|
|
.array(
|
|
z.string().trim().min(1).max(HOUSEKEEPING_PREFERENCE_MAX_IDENTIFIER_LENGTH),
|
|
)
|
|
.max(HOUSEKEEPING_PREFERENCE_MAX_ITEMS_PER_ARRAY)
|
|
.superRefine((values, context) => {
|
|
const seen = new Set<string>();
|
|
for (const [index, value] of values.entries()) {
|
|
if (seen.has(value)) {
|
|
context.addIssue({
|
|
code: "custom",
|
|
message: "duplicate preference identifier",
|
|
path: [index],
|
|
});
|
|
}
|
|
seen.add(value);
|
|
}
|
|
});
|
|
|
|
export const housekeepingPreferencesSchema: z.ZodType<HousekeepingPreferences> =
|
|
z
|
|
.object({
|
|
schemaVersion: z.literal(1),
|
|
pinnedRouteIds: uniqueIdentifiers,
|
|
pinnedCommandIds: uniqueIdentifiers,
|
|
shortcutOrder: uniqueIdentifiers,
|
|
widgetOrder: uniqueIdentifiers,
|
|
enabledOptionalWidgetIds: uniqueIdentifiers,
|
|
})
|
|
.strict()
|
|
.superRefine((preferences, context) => {
|
|
if (
|
|
new TextEncoder().encode(JSON.stringify(preferences)).byteLength >
|
|
HOUSEKEEPING_PREFERENCE_MAX_SERIALIZED_BYTES
|
|
) {
|
|
context.addIssue({
|
|
code: "custom",
|
|
message: "housekeeping preferences payload is too large",
|
|
});
|
|
}
|
|
});
|
|
|
|
export function defaultHousekeepingPreferences(): HousekeepingPreferences {
|
|
return {
|
|
schemaVersion: 1,
|
|
pinnedRouteIds: [],
|
|
pinnedCommandIds: [],
|
|
shortcutOrder: [],
|
|
widgetOrder: [],
|
|
enabledOptionalWidgetIds: [],
|
|
};
|
|
}
|
|
|
|
export function parseHousekeepingPreferences(
|
|
serialized: string,
|
|
): HousekeepingPreferences {
|
|
let value: unknown;
|
|
try {
|
|
value = JSON.parse(serialized);
|
|
} catch {
|
|
throw new Error("invalid housekeeping preferences JSON");
|
|
}
|
|
|
|
return housekeepingPreferencesSchema.parse(value);
|
|
}
|