summaryrefslogtreecommitdiff
path: root/packages/integrations/web-vitals/src/schemas.ts
blob: 7a2050bd53ae76b423855d1fa29da4240df846a3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import { z } from 'astro/zod';

export const RatingSchema = z.enum(['good', 'needs-improvement', 'poor']);
const MetricTypeSchema = z.enum(['CLS', 'INP', 'LCP', 'FCP', 'FID', 'TTFB']);

/** `web-vitals` generated ID, transformed to reduce data resolution. */
const MetricIdSchema = z
	.string()
	// Match https://github.com/GoogleChrome/web-vitals/blob/main/src/lib/generateUniqueID.ts
	.regex(/^v3-\d{13}-\d{13}$/)
	// Avoid collecting higher resolution timestamp in ID.
	// Transforms `'v3-1711484350895-3748043125387'` to `'v3-17114843-3748043125387'`
	.transform((id) => id.replace(/^(v3-\d{8})\d{5}(-\d{13})$/, '$1$2'));

/** Shape of the data submitted from clients to the collection API. */
const ClientMetricSchema = z.object({
	pathname: z.string(),
	route: z.string(),
	name: MetricTypeSchema,
	id: MetricIdSchema,
	value: z.number().gte(0),
	rating: RatingSchema,
});

/** Transformed client data with added timestamp. */
export const ServerMetricSchema = ClientMetricSchema.transform((metric) => {
	const timestamp = new Date();
	timestamp.setMinutes(0, 0, 0);
	return { ...metric, timestamp };
});

export type ClientMetric = z.input<typeof ClientMetricSchema>;