This repository has been archived by the owner on Jul 10, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
schemas.ts
87 lines (76 loc) · 2.26 KB
/
schemas.ts
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import { z } from "zod";
import { rooms } from "./rooms.ts";
type ProfilesList = z.infer<typeof profilesListSchema>;
type Room = z.infer<typeof roomStrictSchema>;
/**
* Normalizes a room string by removing special characters.
*
* @param room - The room string to be normalized.
* @returns The normalized room string.
*/
function normalizeRoomString(room: string): string {
return room
.normalize()
.replaceAll("-", "")
.replaceAll("_", "")
.replaceAll("#", "")
.replaceAll("/", "");
}
function isKey<T extends object>(obj: T, val: PropertyKey): val is keyof T {
return Object.hasOwn(obj, val);
}
/**
* Represents the custom schema for a room.
*
* This schema is used to validate if a value is a valid room.
* A valid room, well, exists in the list of rooms.
*/
const roomStrictSchema = z.custom<keyof typeof rooms>(
(val) =>
z
.string()
.toUpperCase()
.trim()
.transform(normalizeRoomString)
.refine((val2: string): val2 is keyof typeof rooms => isKey(rooms, val2))
.safeParse(val).success,
(val) => ({ message: `${val} is not a room` }),
);
/**
* Represents the custom schema for a room.
*
* This schema is used to validate if a value is a valid room.
* A valid room, well, exists in the list of rooms.
* In addition, this allows an empty string to pass, so that that validation can be caught better.
*/
const roomSchema = z.union([roomStrictSchema, z.literal("")]).readonly();
/**
* Coerces a null value to undefined.
*
* @param val - Something possibly nullable.
* @returns Something, but the null value is coerced to undefined.
*/
function coerceNullToUndefined(val: unknown): unknown {
return val ?? undefined;
}
/**
* Represents the schema for profiles data.
*/
const profilesSchema = z.union([
z
.tuple([z.preprocess(coerceNullToUndefined, z.undefined())])
.rest(z.union([z.string(), z.string().array()])),
z.tuple([]),
]);
/**
* Represents the schema for an individual profile.
*/
const profileSchema = z.tuple([z.string(), z.string()]);
/**
* Represents the schema for a list of profiles.
*/
const profilesListSchema = z.union([
z.tuple([profilesSchema]).rest(profileSchema.array()),
z.tuple([]),
]);
export { isKey, profilesListSchema, roomSchema, type ProfilesList, type Room };