diff --git a/tools/linter_lib/custom_check.py b/tools/linter_lib/custom_check.py index 4d6b051d83..a183d8d9ed 100644 --- a/tools/linter_lib/custom_check.py +++ b/tools/linter_lib/custom_check.py @@ -120,6 +120,7 @@ js_rules = RuleList( "web/src/types.ts", "web/src/util.ts", "web/src/message_helper.ts", + "web/src/server_message.ts", "web/tests/", }, "exclude_pattern": "emails", diff --git a/tools/test-js-with-node b/tools/test-js-with-node index f0cd746b2a..c3a24bc56c 100755 --- a/tools/test-js-with-node +++ b/tools/test-js-with-node @@ -204,6 +204,7 @@ EXEMPT_FILES = make_set( "web/src/sent_messages.ts", "web/src/sentry.ts", "web/src/server_events.js", + "web/src/server_message.ts", "web/src/settings.js", "web/src/settings_account.js", "web/src/settings_bots.js", diff --git a/web/src/server_message.ts b/web/src/server_message.ts new file mode 100644 index 0000000000..f1aa40fbae --- /dev/null +++ b/web/src/server_message.ts @@ -0,0 +1,88 @@ +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()), + }), + ]), + );