mirror of https://github.com/zulip/zulip.git
message_store: Rewrite RawMessage type using Zod.
This commit rework RawMessage and it's related type to use Zod for parsing the data received from the server.
This commit is contained in:
parent
f148a7a3ed
commit
17e2d46760
|
@ -259,7 +259,6 @@ EXEMPT_FILES = make_set(
|
||||||
"web/src/topic_list.ts",
|
"web/src/topic_list.ts",
|
||||||
"web/src/topic_popover.js",
|
"web/src/topic_popover.js",
|
||||||
"web/src/tutorial.js",
|
"web/src/tutorial.js",
|
||||||
"web/src/types.ts",
|
|
||||||
"web/src/typing.ts",
|
"web/src/typing.ts",
|
||||||
"web/src/typing_events.ts",
|
"web/src/typing_events.ts",
|
||||||
"web/src/ui_init.js",
|
"web/src/ui_init.js",
|
||||||
|
|
|
@ -1,82 +1,109 @@
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
|
import {z} from "zod";
|
||||||
|
|
||||||
import * as blueslip from "./blueslip";
|
import * as blueslip from "./blueslip";
|
||||||
import * as people from "./people";
|
import * as people from "./people";
|
||||||
import type {Submessage} from "./submessage";
|
import {topic_link_schema} from "./types";
|
||||||
import type {TopicLink} from "./types";
|
|
||||||
import type {UserStatusEmojiInfo} from "./user_status";
|
import type {UserStatusEmojiInfo} from "./user_status";
|
||||||
|
|
||||||
const stored_messages = new Map<number, Message>();
|
const stored_messages = new Map<number, Message>();
|
||||||
|
|
||||||
export type MatchedMessage = {
|
const matched_message_schema = z.object({
|
||||||
match_content?: string | undefined;
|
match_content: z.optional(z.string()),
|
||||||
match_subject?: string | undefined;
|
match_subject: z.optional(z.string()),
|
||||||
};
|
});
|
||||||
|
|
||||||
export type MessageReactionType = "unicode_emoji" | "realm_emoji" | "zulip_extra_emoji";
|
export type MatchedMessage = z.infer<typeof matched_message_schema>;
|
||||||
|
|
||||||
export type DisplayRecipientUser = {
|
const message_reaction_type_schema = z.enum(["unicode_emoji", "realm_emoji", "zulip_extra_emoji"]);
|
||||||
email: string;
|
|
||||||
full_name: string;
|
|
||||||
id: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type DisplayRecipient = string | DisplayRecipientUser[];
|
export type MessageReactionType = z.infer<typeof message_reaction_type_schema>;
|
||||||
|
|
||||||
export type MessageEditHistoryEntry = {
|
const display_recipient_user_schema = z.object({
|
||||||
user_id: number | null;
|
email: z.string(),
|
||||||
timestamp: number;
|
full_name: z.string(),
|
||||||
prev_content?: string;
|
id: z.number(),
|
||||||
prev_rendered_content?: string;
|
});
|
||||||
prev_rendered_content_version?: number;
|
|
||||||
prev_stream?: number;
|
|
||||||
prev_topic?: string;
|
|
||||||
stream?: number;
|
|
||||||
topic?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type MessageReaction = {
|
export type DisplayRecipientUser = z.infer<typeof display_recipient_user_schema>;
|
||||||
emoji_name: string;
|
|
||||||
emoji_code: string;
|
|
||||||
reaction_type: MessageReactionType;
|
|
||||||
user_id: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type RawMessage = {
|
const display_recipient_schema = z.union([z.string(), z.array(display_recipient_user_schema)]);
|
||||||
avatar_url: string | null;
|
|
||||||
client: string;
|
export type DisplayRecipient = z.infer<typeof display_recipient_schema>;
|
||||||
content: string;
|
|
||||||
content_type: "text/html";
|
const message_edit_history_entry_schema = z.object({
|
||||||
display_recipient: DisplayRecipient;
|
user_id: z.nullable(z.number()),
|
||||||
edit_history?: MessageEditHistoryEntry[];
|
timestamp: z.number(),
|
||||||
id: number;
|
prev_content: z.optional(z.string()),
|
||||||
is_me_message: boolean;
|
prev_rendered_content: z.optional(z.string()),
|
||||||
last_edit_timestamp?: number;
|
prev_rendered_content_version: z.optional(z.number()),
|
||||||
reactions: MessageReaction[];
|
prev_stream: z.optional(z.number()),
|
||||||
recipient_id: number;
|
prev_topic: z.optional(z.string()),
|
||||||
sender_email: string;
|
stream: z.optional(z.number()),
|
||||||
sender_full_name: string;
|
topic: z.optional(z.string()),
|
||||||
sender_id: number;
|
});
|
||||||
sender_realm_str: string;
|
|
||||||
submessages: Submessage[];
|
export type MessageEditHistoryEntry = z.infer<typeof message_edit_history_entry_schema>;
|
||||||
timestamp: number;
|
|
||||||
flags: string[];
|
const message_reaction_schema = z.object({
|
||||||
} & (
|
emoji_name: z.string(),
|
||||||
| {
|
emoji_code: z.string(),
|
||||||
type: "private";
|
reaction_type: message_reaction_type_schema,
|
||||||
topic_links?: undefined;
|
user_id: z.number(),
|
||||||
}
|
});
|
||||||
| {
|
|
||||||
type: "stream";
|
export type MessageReaction = z.infer<typeof message_reaction_schema>;
|
||||||
stream_id: number;
|
|
||||||
// Messages that come from the server use `subject`.
|
export const submessage_schema = z.object({
|
||||||
// Messages that come from `send_message` use `topic`.
|
id: z.number(),
|
||||||
subject?: string;
|
sender_id: z.number(),
|
||||||
topic?: string;
|
message_id: z.number(),
|
||||||
topic_links: TopicLink[];
|
content: z.string(),
|
||||||
}
|
msg_type: z.string(),
|
||||||
) &
|
});
|
||||||
MatchedMessage;
|
|
||||||
|
export const raw_message_schema = z.intersection(
|
||||||
|
z.intersection(
|
||||||
|
z.object({
|
||||||
|
avatar_url: z.nullable(z.string()),
|
||||||
|
client: z.string(),
|
||||||
|
content: z.string(),
|
||||||
|
content_type: z.literal("text/html"),
|
||||||
|
display_recipient: display_recipient_schema,
|
||||||
|
edit_history: z.optional(z.array(message_edit_history_entry_schema)),
|
||||||
|
id: z.number(),
|
||||||
|
is_me_message: z.boolean(),
|
||||||
|
last_edit_timestamp: z.optional(z.number()),
|
||||||
|
reactions: z.array(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: z.array(submessage_schema),
|
||||||
|
timestamp: z.number(),
|
||||||
|
flags: z.array(z.string()),
|
||||||
|
}),
|
||||||
|
z.discriminatedUnion("type", [
|
||||||
|
z.object({
|
||||||
|
type: z.literal("private"),
|
||||||
|
topic_links: z.optional(z.array(z.undefined())),
|
||||||
|
}),
|
||||||
|
z.object({
|
||||||
|
type: z.literal("stream"),
|
||||||
|
stream_id: z.number(),
|
||||||
|
// Messages that come from the server use `subject`.
|
||||||
|
// Messages that come from `send_message` use `topic`.
|
||||||
|
subject: z.optional(z.string()),
|
||||||
|
topic: z.optional(z.string()),
|
||||||
|
topic_links: z.array(topic_link_schema),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
matched_message_schema,
|
||||||
|
);
|
||||||
|
|
||||||
|
export type RawMessage = z.infer<typeof raw_message_schema>;
|
||||||
|
|
||||||
// We add these boolean properties to Raw message in
|
// We add these boolean properties to Raw message in
|
||||||
// `message_store.convert_raw_message_to_message_with_booleans` method.
|
// `message_store.convert_raw_message_to_message_with_booleans` method.
|
||||||
|
|
|
@ -10,13 +10,7 @@ import {todo_widget_extra_data_schema} from "./todo_widget";
|
||||||
import type {TodoWidgetOutboundData} from "./todo_widget";
|
import type {TodoWidgetOutboundData} from "./todo_widget";
|
||||||
import * as widgetize from "./widgetize";
|
import * as widgetize from "./widgetize";
|
||||||
|
|
||||||
export type Submessage = {
|
export type Submessage = z.infer<typeof message_store.submessage_schema>;
|
||||||
id: number;
|
|
||||||
sender_id: number;
|
|
||||||
message_id: number;
|
|
||||||
content: string;
|
|
||||||
msg_type: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const zform_widget_extra_data_schema = z
|
export const zform_widget_extra_data_schema = z
|
||||||
.object({
|
.object({
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
|
import {z} from "zod";
|
||||||
|
|
||||||
// TODO/typescript: Move this to server_events
|
// TODO/typescript: Move this to server_events
|
||||||
export type TopicLink = {
|
export const topic_link_schema = z.object({
|
||||||
text: string;
|
text: z.string(),
|
||||||
url: string;
|
url: z.string(),
|
||||||
};
|
});
|
||||||
|
|
||||||
|
export type TopicLink = z.infer<typeof topic_link_schema>;
|
||||||
|
|
||||||
// TODO/typescript: Move this to server_events_dispatch
|
// TODO/typescript: Move this to server_events_dispatch
|
||||||
export type UserGroupUpdateEvent = {
|
export type UserGroupUpdateEvent = {
|
||||||
|
|
Loading…
Reference in New Issue