zulip/web/src/server_message.ts
Varun Singh 884317e407 server_message: Create zod schema to parse message recieved from server.
The commit creates a `server_message.ts` module which
will home our `zod` schema for the messages received
from server. We can then import the schema to parse
the data in needed modules at the API boundaries.
This will also help us write better tests.
2024-07-15 13:55:13 -07:00

89 lines
2.6 KiB
TypeScript

import {z} from "zod";
const display_recipient_users_schema = z.object({
id: z.number(),
email: z.string(),
full_name: z.string(),
is_mirror_dummy: z.boolean(),
});
export const message_edit_history_schema = z.array(
z.object({
prev_content: z.optional(z.string()),
prev_rendered_content: z.optional(z.string()),
prev_rendered_content_version: z.optional(z.number()),
prev_stream: z.optional(z.number()),
prev_topic: z.optional(z.string()),
stream: z.optional(z.number()),
timestamp: z.number(),
topic: z.optional(z.string()),
user_id: z.number().nullable(),
}),
);
const message_reaction_schema = z.array(
z.object({
emoji_name: z.string(),
emoji_code: z.string(),
reaction_type: z.enum(["unicode_emoji", "realm_emoji", "zulip_extra_emoji"]),
user_id: z.number(),
user: z.object({
id: z.number(),
email: z.string(),
full_name: z.string(),
is_mirror_dummy: z.boolean().nullish(),
}),
}),
);
const submessage_schema = z.array(
z.object({
msg_type: z.string(),
content: z.string(),
message_id: z.number(),
sender_id: z.number(),
id: z.number(),
}),
);
export const server_message_schema = z
.object({
avatar_url: z.string().nullish(),
client: z.string(),
content: z.string(),
content_type: z.enum(["text/html", "text/x-markdown"]),
display_recipient: z.union([z.string(), z.array(display_recipient_users_schema)]),
edit_history: z.optional(message_edit_history_schema),
id: z.number(),
is_me_message: z.boolean(),
last_edit_timestamp: z.number().optional(),
reactions: message_reaction_schema,
recipient_id: z.number(),
sender_email: z.string(),
sender_full_name: z.string(),
sender_id: z.number(),
sender_realm_str: z.string(),
submessages: submessage_schema,
timestamp: z.number(),
})
.and(
z.discriminatedUnion("type", [
z.object({
type: z.literal("stream"),
subject: z.string(),
stream_id: z.number(),
topic_links: z.array(
z.object({
text: z.string(),
url: z.string(),
}),
),
}),
z.object({
type: z.literal("private"),
subject: z.literal(""),
topic_links: z.array(z.never()),
}),
]),
);