47 lines
1.7 KiB
TypeScript
47 lines
1.7 KiB
TypeScript
import { z } from 'zod';
|
|
|
|
const CapturePayload = z.object({
|
|
noteId: z.string().min(1),
|
|
rawTextLength: z.number().int().nonnegative(),
|
|
hasMedia: z.boolean()
|
|
}).strict();
|
|
|
|
const AiSucceededPayload = z.object({
|
|
noteId: z.string().min(1),
|
|
durationMs: z.number().nonnegative(),
|
|
attempts: z.number().int().nonnegative()
|
|
}).strict();
|
|
|
|
const AiFailedReason = z.enum(['unreachable', 'schema', 'timeout', 'other']);
|
|
|
|
const AiFailedPayload = z.object({
|
|
noteId: z.string().min(1),
|
|
reason: AiFailedReason,
|
|
attempts: z.number().int().nonnegative()
|
|
}).strict();
|
|
|
|
const NoteIdPayload = z.object({
|
|
noteId: z.string().min(1)
|
|
}).strict();
|
|
|
|
const EmptyTrashPayload = z.object({
|
|
count: z.number().int().nonnegative()
|
|
}).strict();
|
|
|
|
export const TelemetryEventSchema = z.discriminatedUnion('kind', [
|
|
z.object({ ts: z.string(), kind: z.literal('capture'), payload: CapturePayload }).strict(),
|
|
z.object({ ts: z.string(), kind: z.literal('ai_succeeded'), payload: AiSucceededPayload }).strict(),
|
|
z.object({ ts: z.string(), kind: z.literal('ai_failed'), payload: AiFailedPayload }).strict(),
|
|
z.object({ ts: z.string(), kind: z.literal('trash'), payload: NoteIdPayload }).strict(),
|
|
z.object({ ts: z.string(), kind: z.literal('restore'), payload: NoteIdPayload }).strict(),
|
|
z.object({ ts: z.string(), kind: z.literal('permanent_delete'), payload: NoteIdPayload }).strict(),
|
|
z.object({ ts: z.string(), kind: z.literal('empty_trash'), payload: EmptyTrashPayload }).strict()
|
|
]);
|
|
|
|
export type TelemetryEvent = z.infer<typeof TelemetryEventSchema>;
|
|
export type TelemetryKind = TelemetryEvent['kind'];
|
|
|
|
export function validateEvent(raw: unknown): TelemetryEvent {
|
|
return TelemetryEventSchema.parse(raw);
|
|
}
|